[NETFILTER]: nf_conntrack: Fix TCP/UDP HW checksum handling for IPv6 packet

If skb->ip_summed is CHECKSUM_HW here, skb->csum includes checksum
of actual IPv6 header and extension headers. Then such excess
checksum must be subtruct when nf_conntrack calculates TCP/UDP checksum
with pseudo IPv6 header. Spotted by Ben Skeggs.

Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Yasuyuki Kozakai and committed by David S. Miller 7c6de058 763ecff1

+6 -2
+3 -1
net/netfilter/nf_conntrack_proto_tcp.c
··· 864 { 865 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, 866 skb->len - dataoff, IPPROTO_TCP, 867 - skb->ip_summed == CHECKSUM_HW ? skb->csum 868 : skb_checksum(skb, dataoff, skb->len - dataoff, 869 0)); 870 }
··· 864 { 865 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, 866 skb->len - dataoff, IPPROTO_TCP, 867 + skb->ip_summed == CHECKSUM_HW 868 + ? csum_sub(skb->csum, 869 + skb_checksum(skb, 0, dataoff, 0)) 870 : skb_checksum(skb, dataoff, skb->len - dataoff, 871 0)); 872 }
+3 -1
net/netfilter/nf_conntrack_proto_udp.c
··· 161 { 162 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, 163 skb->len - dataoff, IPPROTO_UDP, 164 - skb->ip_summed == CHECKSUM_HW ? skb->csum 165 : skb_checksum(skb, dataoff, skb->len - dataoff, 166 0)); 167 }
··· 161 { 162 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, 163 skb->len - dataoff, IPPROTO_UDP, 164 + skb->ip_summed == CHECKSUM_HW 165 + ? csum_sub(skb->csum, 166 + skb_checksum(skb, 0, dataoff, 0)) 167 : skb_checksum(skb, dataoff, skb->len - dataoff, 168 0)); 169 }