: ${USER:=$LOGNAME} : ${USER:=unknown} cat > /tmp/$USER.c < #include unsigned short in_cksum(addr, len) u_short *addr; int len; { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); } main () { char packet[] = "\377\377\377\377abcdefg"; printf("%d\n", in_cksum(packet, sizeof(packet))); /* simulate a fairly common form of xmit error */ * (int *)packet = 0x0000; printf("%d\n", in_cksum(packet, sizeof(packet))); } EOM gcc -g /tmp/$USER.c -o /tmp/$USER /tmp/$USER # # output: # 53870 # 53870 # # I believe the IP and TCP checksum are the same algorithm, so will likely # fail in the same way with this corruption. Ethernet checksums are # irrelevant if this corruption occurs within the router or host. # I should probably read RFC 1071, 1141 and 1624, but am too lazy.