Skip to content

Commit

Permalink
Improve zero checksum handling
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
angus19 authored Oct 28, 2024
1 parent 1c0066a commit 9326343
Showing 1 changed file with 23 additions and 6 deletions.
29 changes: 23 additions & 6 deletions nat46/modules/nat46-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,8 @@ int xlate_payload6_to4(nat46_instance_t *nat46, void *pv6, void *ptrans_hdr, int
if ((udp->check == 0) && zero_csum_pass) {
/* zero checksum and the config to pass it is set - do nothing with it */
break;
}
}
/* pretend we have full payload */
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) {
Expand Down Expand Up @@ -1671,9 +1672,15 @@ 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;
}
skb_set_transport_header(old_skb,v6packet_l3size); /* transport (TCP/UDP/ICMP/...) header starts after 40 bytes */

/* FIXME: what if we don't have full payload */
ip6_update_csum(old_skb, ip6h, 0);
}
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);
Expand Down Expand Up @@ -1767,13 +1774,23 @@ 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;
}

oldsum = udp->check;
udp->check = 0;

if (do_atomic_frag) {
if ((udp->check == 0) && !zero_csum_pass) {
/*
* FIXME:
* checksum will still be broken if we don't have full payload
* since we can't do the full calculation first in this case
*/
}
}

sum1 = csum_partial((char*)udp, udplen, 0); /* calculate checksum for UDP hdr+payload */
sum2 = csum_ipv6_magic(&ip6hdr->saddr, &ip6hdr->daddr, udplen, ip6hdr->nexthdr, sum1); /* add pseudoheader */

Expand Down

0 comments on commit 9326343

Please sign in to comment.