Skip to content

Commit 9326343

Browse files
authored
Improve zero checksum handling
We put reassembly aside in this change. As per comment by @ayourtch: Let’s do step by step. Reassembly is a much larger thing and a much smaller hopefully corner case, i am not fully sure on the benefit vs complexity and fragility it brings.
1 parent 1c0066a commit 9326343

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

nat46/modules/nat46-core.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,8 @@ int xlate_payload6_to4(nat46_instance_t *nat46, void *pv6, void *ptrans_hdr, int
10061006
if ((udp->check == 0) && zero_csum_pass) {
10071007
/* zero checksum and the config to pass it is set - do nothing with it */
10081008
break;
1009-
}
1009+
}
1010+
/* pretend we have full payload */
10101011
sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, infrag_payload_len, NEXTHDR_UDP, udp->check);
10111012
sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, infrag_payload_len, NEXTHDR_UDP, sum1); /* add pseudoheader */
10121013
if(ul_sum) {
@@ -1671,9 +1672,15 @@ int nat46_ipv6_input(struct sk_buff *old_skb) {
16711672
case NEXTHDR_UDP: {
16721673
struct udphdr *udp = add_offset(ip6h, v6packet_l3size);
16731674
u16 sum1, sum2;
1674-
if ((udp->check == 0) && zero_csum_pass) {
1675-
/* zero checksum and the config to pass it is set - do nothing with it */
1676-
break;
1675+
if (udp->check == 0) {
1676+
if (zero_csum_pass) {
1677+
/* zero checksum and the config to pass it is set - do nothing with it */
1678+
break;
1679+
}
1680+
skb_set_transport_header(old_skb,v6packet_l3size); /* transport (TCP/UDP/ICMP/...) header starts after 40 bytes */
1681+
1682+
/* FIXME: what if we don't have full payload */
1683+
ip6_update_csum(old_skb, ip6h, 0);
16771684
}
16781685
sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, l3_infrag_payload_len, NEXTHDR_UDP, udp->check);
16791686
sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, l3_infrag_payload_len, NEXTHDR_UDP, sum1);
@@ -1767,13 +1774,23 @@ void ip6_update_csum(struct sk_buff * skb, struct ipv6hdr * ip6hdr, int do_atomi
17671774
unsigned udplen = ntohs(ip6hdr->payload_len) - (do_atomic_frag?8:0); /* UDP hdr + payload */
17681775

17691776
if ((udp->check == 0) && zero_csum_pass) {
1770-
/* zero checksum and the config to pass it is set - do nothing with it */
1771-
break;
1777+
/* zero checksum and the config to pass it is set - do nothing with it */
1778+
break;
17721779
}
17731780

17741781
oldsum = udp->check;
17751782
udp->check = 0;
17761783

1784+
if (do_atomic_frag) {
1785+
if ((udp->check == 0) && !zero_csum_pass) {
1786+
/*
1787+
* FIXME:
1788+
* checksum will still be broken if we don't have full payload
1789+
* since we can't do the full calculation first in this case
1790+
*/
1791+
}
1792+
}
1793+
17771794
sum1 = csum_partial((char*)udp, udplen, 0); /* calculate checksum for UDP hdr+payload */
17781795
sum2 = csum_ipv6_magic(&ip6hdr->saddr, &ip6hdr->daddr, udplen, ip6hdr->nexthdr, sum1); /* add pseudoheader */
17791796

0 commit comments

Comments
 (0)