Skip to content

Commit 9e6a8db

Browse files
committed
Improve zero checksum handling
As per the suggestion by @ayourtch: Well setting zero_csum_pass to 1 is not much of a fix, is it - it rather masks the problem in the code. Also it is a change of defaults, which i would be a bit hesitant to do… Here’s an idea, what if we rewrite that bit as follows: if (!udp->check) { if (zero_csum_pass) { // do nothing break; } // recalculate the IPv6 checksum before adjusting ip6_update_csum(…) } // here we will have nonzero checksum, unmagic + remagic so, if it’s UDP and the checksum is zero and we don’t pass the zero checksum, recalculate it ? It will still be broken if we don’t have full payload since we can’t do the full calculation in this case, but should take care of other cases ? what do you think ?
1 parent 1c0066a commit 9e6a8db

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

nat46/modules/nat46-core.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ int xlate_payload6_to4(nat46_instance_t *nat46, void *pv6, void *ptrans_hdr, int
10071007
/* zero checksum and the config to pass it is set - do nothing with it */
10081008
break;
10091009
}
1010+
/* pretend checksum is correct not null */
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,12 @@ 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+
ip6_update_csum(old_skb, ip6h, ip6h->nexthdr == NEXTHDR_FRAGMENT); /* recalculate checksum before adjusting */
16771681
}
16781682
sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, l3_infrag_payload_len, NEXTHDR_UDP, udp->check);
16791683
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
17671771
unsigned udplen = ntohs(ip6hdr->payload_len) - (do_atomic_frag?8:0); /* UDP hdr + payload */
17681772

17691773
if ((udp->check == 0) && zero_csum_pass) {
1770-
/* zero checksum and the config to pass it is set - do nothing with it */
1771-
break;
1774+
/* zero checksum and the config to pass it is set - do nothing with it */
1775+
break;
1776+
}
1777+
1778+
if (do_atomic_frag) {
1779+
if ((udp->check == 0) && !zero_csum_pass) {
1780+
/*
1781+
* Checksum will still be broken if we don't have full payload
1782+
* since we can't do the full calculation in this case.
1783+
*/
1784+
}
17721785
}
17731786

17741787
oldsum = udp->check;

nat46/modules/nat46-core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,6 @@ nat46_instance_t *get_nat46_instance(struct sk_buff *sk);
8282
nat46_instance_t *alloc_nat46_instance(int npairs, nat46_instance_t *old, int from_ipair, int to_ipair, int remove_ipair);
8383
void release_nat46_instance(nat46_instance_t *nat46);
8484

85+
void ip6_update_csum(struct sk_buff * skb, struct ipv6hdr * ip6hdr, int do_atomic_frag);
86+
8587
#endif

0 commit comments

Comments
 (0)