-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve zero checksum handling #46
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1007,6 +1007,7 @@ int xlate_payload6_to4(nat46_instance_t *nat46, void *pv6, void *ptrans_hdr, int | |
/* zero checksum and the config to pass it is set - do nothing with it */ | ||
break; | ||
} | ||
/* pretend checksum is correct not null */ | ||
sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, infrag_payload_len, NEXTHDR_UDP, udp->check); | ||
sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, infrag_payload_len, NEXTHDR_UDP, sum1); /* add pseudoheader */ | ||
if(ul_sum) { | ||
|
@@ -1671,9 +1672,12 @@ int nat46_ipv6_input(struct sk_buff *old_skb) { | |
case NEXTHDR_UDP: { | ||
struct udphdr *udp = add_offset(ip6h, v6packet_l3size); | ||
u16 sum1, sum2; | ||
if ((udp->check == 0) && zero_csum_pass) { | ||
/* zero checksum and the config to pass it is set - do nothing with it */ | ||
break; | ||
if (udp->check == 0) { | ||
if (zero_csum_pass) { | ||
/* zero checksum and the config to pass it is set - do nothing with it */ | ||
break; | ||
} | ||
ip6_update_csum(old_skb, ip6h, ip6h->nexthdr == NEXTHDR_FRAGMENT); /* recalculate checksum before adjusting */ | ||
} | ||
sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, l3_infrag_payload_len, NEXTHDR_UDP, udp->check); | ||
sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, l3_infrag_payload_len, NEXTHDR_UDP, sum1); | ||
|
@@ -1767,8 +1771,17 @@ void ip6_update_csum(struct sk_buff * skb, struct ipv6hdr * ip6hdr, int do_atomi | |
unsigned udplen = ntohs(ip6hdr->payload_len) - (do_atomic_frag?8:0); /* UDP hdr + payload */ | ||
|
||
if ((udp->check == 0) && zero_csum_pass) { | ||
/* zero checksum and the config to pass it is set - do nothing with it */ | ||
break; | ||
/* zero checksum and the config to pass it is set - do nothing with it */ | ||
break; | ||
} | ||
|
||
if (do_atomic_frag) { | ||
if ((udp->check == 0) && !zero_csum_pass) { | ||
/* | ||
* Checksum will still be broken if we don't have full payload | ||
* since we can't do the full calculation in this case. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This new conditional seems to be a no-op ? Why adding it ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put UDP reassembly aside. So UDP fragments associated with zero checksum, the corner case, will not be well handled even if we do recalculate checksum before adjusting via the ip6_update_csum method. I therefore drop a comment in the ip6_update_csum to mark such condition. Both csum_partial and csum_ipv6_magic methods are still serviced for an UDP fragment with zero checksum. But the result is incorrect. |
||
*/ | ||
} | ||
} | ||
|
||
oldsum = udp->check; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to add a logic to recalculate the checksum here if it is zero ? (Reviewing on the phone, so might be wrong).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think recalculation over here is required. In the xlate_payload6_to4 method, we care about translation of a payload inside an ICMPv6. Although this payload is structured by an inner packet which has its own IPv6 header + L4 header + payload. But it is usually truncated. So checksum recalculation happens to the inner L4 header is also usually not possible.