: Fix invalid IP checksums on 64bit
PATCH 1/1 : Fix invalid IP checksums on 64bit
IP checksums are calculated wrong on 64 bit because too large types are used. This patch fixes them and a couple of unrelated snprintf-sizeof-warnings in the same file. I still get invalid TCP checksums, but couldn't locate the problem yet.
ipv4/ipv4.c +6 -6
@@ -565,7 +565,7 @@ iph->check =ip_fast_csum ((unsigned char *)iph, iph->ihl); } -static inline unsigned short from32to16 (unsigned long x) +static inline unsigned short from32to16 (unsigned int x) {/* add up 16-bit and 16-bit for 16+c bit */ x = (x &0xffff ) + (x >>16 );
@@ -574,10 +574,10 @@return x; } -static unsigned long do_csum (const unsigned char * buff,int len) +static unsigned int do_csum (const unsigned char * buff,int len) {int odd, count; -unsigned long result =0 ; +unsigned int result =0 ;if (len <=0 )return 0 ;
@@ -819,7 +819,7 @@switch (iph->protocol) {case IPPROTO_ICMP : icmph = (struct icmphdr *)(iph +1 ); - ptr +=sprintf (ptr,"%u %u " , + ptr +=sprintf (ptr,"%Zu %u " , iplen -sizeof (struct icmphdr ), iph->protocol);if (len <sizeof (struct icmphdr )) {
@@ -855,7 +855,7 @@case IPPROTO_UDP : udph = (struct udphdr *)(iph +1 ); - ptr +=sprintf (ptr,"%u %u " , + ptr +=sprintf (ptr,"%Zu %u " , iplen -sizeof (struct udphdr ), iph->protocol);if (len <sizeof (struct udphdr )) {
@@ -891,7 +891,7 @@ tcph = (struct tcphdr *)(iph +1 );if (len <sizeof (struct tcphdr )) {/* Assume no tcp options... */ - ptr +=sprintf (ptr,"%u %u " , + ptr +=sprintf (ptr,"%Zu %u " , iplen -sizeof (*tcph), iph->protocol); ptr +=sprintf (ptr,"-TRUNCATED-" );
Quoted 4 lines · Patrick McHardy
IP checksums are calculated wrong on 64 bit because too large types are used. This patch fixes them and a couple of unrelated snprintf-sizeof-warnings in the same file. I still get invalid TCP checksums, but couldn't locate the problem yet.
I found the real bug, my previous fix just hid it. This patch fixes all checksum problems, the calculated checksum are equal to the ones of a 32-bit binary.
ipv4/ipv4.c +4 -4
@@ -600,7 +600,7 @@if (count) {unsigned long carry =0 ; do { - unsigned long w = *(unsigned long *) buff; + unsigned int w = *(unsigned int *) buff; count--; buff += 4; result += carry;
@@ -819,7 +819,7 @@switch (iph->protocol) {case IPPROTO_ICMP : icmph = (struct icmphdr *)(iph +1 ); - ptr +=sprintf (ptr,"%u %u " , + ptr +=sprintf (ptr,"%Zu %u " , iplen -sizeof (struct icmphdr ), iph->protocol);if (len <sizeof (struct icmphdr )) {
@@ -855,7 +855,7 @@case IPPROTO_UDP : udph = (struct udphdr *)(iph +1 ); - ptr +=sprintf (ptr,"%u %u " , + ptr +=sprintf (ptr,"%Zu %u " , iplen -sizeof (struct udphdr ), iph->protocol);if (len <sizeof (struct udphdr )) {
@@ -891,7 +891,7 @@ tcph = (struct tcphdr *)(iph +1 );if (len <sizeof (struct tcphdr )) {/* Assume no tcp options... */ - ptr +=sprintf (ptr,"%u %u " , + ptr +=sprintf (ptr,"%Zu %u " , iplen -sizeof (*tcph), iph->protocol); ptr +=sprintf (ptr,"-TRUNCATED-" );