diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 3b61a70a9..94c16f228 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -3957,11 +3958,6 @@ static int send_proxy_packet4(struct sk_buff *skb, struct re_address *src, struc .daddr = dst->u.ipv4, }; - skb->csum_start = skb_transport_header(skb) - skb->head; - skb->csum_offset = offsetof(struct udphdr, check); - uh->check = csum_tcpudp_magic(src->u.ipv4, dst->u.ipv4, datalen, IPPROTO_UDP, csum_partial(uh, datalen, 0)); - if (uh->check == 0) - uh->check = CSUM_MANGLED_0; skb->protocol = htons(ETH_P_IP); net = NULL; @@ -3982,7 +3978,22 @@ static int send_proxy_packet4(struct sk_buff *skb, struct re_address *src, struc goto drop; skb->dev = skb_dst(skb)->dev; - skb->ip_summed = CHECKSUM_NONE; + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct udphdr, check); + + if (skb->dev->features & (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM)) { + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = 0; + udp4_hwcsum(skb, ih->saddr, ih->daddr); + } + else { + __wsum csum = skb_checksum(skb, skb_transport_offset(skb), datalen, 0); + uh->check = csum_tcpudp_magic(src->u.ipv4, dst->u.ipv4, datalen, IPPROTO_UDP, + csum); + if (uh->check == 0) + uh->check = CSUM_MANGLED_0; + skb->ip_summed = CHECKSUM_COMPLETE; + } ip_select_ident(net, skb, NULL); ip_local_out(net, skb->sk, skb); @@ -4036,11 +4047,6 @@ static int send_proxy_packet6(struct sk_buff *skb, struct re_address *src, struc memcpy(&ih->saddr, src->u.ipv6, sizeof(ih->saddr)); memcpy(&ih->daddr, dst->u.ipv6, sizeof(ih->daddr)); - skb->csum_start = skb_transport_header(skb) - skb->head; - skb->csum_offset = offsetof(struct udphdr, check); - uh->check = csum_ipv6_magic(&ih->saddr, &ih->daddr, datalen, IPPROTO_UDP, csum_partial(uh, datalen, 0)); - if (uh->check == 0) - uh->check = CSUM_MANGLED_0; skb->protocol = htons(ETH_P_IPV6); net = NULL; @@ -4067,7 +4073,21 @@ static int send_proxy_packet6(struct sk_buff *skb, struct re_address *src, struc skb_dst_set(skb, dst_entry); skb->dev = skb_dst(skb)->dev; - skb->ip_summed = CHECKSUM_NONE; + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct udphdr, check); + + if (skb->dev->features & (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM)) { + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = 0; + uh->check = ~csum_ipv6_magic(&ih->saddr, &ih->daddr, datalen, IPPROTO_UDP, 0); + } + else { + __wsum csum = skb_checksum(skb, skb_transport_offset(skb), datalen, 0); + uh->check = csum_ipv6_magic(&ih->saddr, &ih->daddr, datalen, IPPROTO_UDP, csum); + if (uh->check == 0) + uh->check = CSUM_MANGLED_0; + skb->ip_summed = CHECKSUM_COMPLETE; + } ip6_local_out(net, skb->sk, skb);