tcp checksum generation

I have been implementing various checksum functions, but none seem to
generate the correct checksum for a tcp packet with or with out
data.

I’ve tried using a checksum calculator on the tcp dump.
http://mna.nlanr.net/Software/HEC/hexhec.html Their calculation for
the following hex data was also incorrect.

C0 A8 02 01 sourceip
C0 A8 02 64 destip
00 06 protocol
00 20 length 32
C0 32 00 50 38 01 C6 98 00 00 00 00 80 02 20 00 0A 44 00 00 tcp
header
02 04 05 B4 01 03 03 02 01 01 04 02 tcp options

According to NetMon, the correct checksum for the syn packet above is
74b2.

Here is one checksum function I borrowed from http://www.netfor2.com/tcpsum.htm

typedef unsigned short u16;
typedef unsigned long u32;

u16 tcp_sum_calc(u16 len_tcp, u16 src_addr,u16 dest_addr, BOOL
padding, u16 buff)
{
u16 prot_tcp=6;
u16 padd=0;
u16 word16;
u32 sum;

// Find out if the length of data is even or odd number. If odd,
// add a padding byte = 0 at the end of packet
if (padding&1==1){
padd=1;
buff[len_tcp]=0;
}

//initialize sum to zero
sum=0;

// make 16 bit words out of every two adjacent 8 bit words and
// calculate the sum of all 16 vit words
for (i=0;i<len_tcp> word16 =((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
sum = sum + (unsigned long)word16;
}
// add the TCP pseudo header which contains:
// the IP source and destinationn addresses,
for (i=0;i<4;i=i+2){
word16 =((src_addr[i]<<8)&0xFF00)+(src_addr[i+1]&0xFF);
sum=sum+word16;
}
for (i=0;i<4;i=i+2){
word16 =((dest_addr[i]<<8)&0xFF00)+(dest_addr[i+1]&0xFF);
sum=sum+word16;
}
// the protocol number and the length of the TCP packet
sum = sum + prot_tcp + len_tcp;

// keep only the last 16 bits of the 32 bit calculated sum and add
the carries
while (sum>>16)
sum = (sum & 0xFFFF)+(sum >> 16);

// Take the one’s complement of sum
sum = ~sum;

return ((unsigned short) sum);

}

//check for tcp options in tcp header
//size = length of data
tcp_options_length = RtlUshortByteSwap/(iph->Length) - sizeof
(IP_HEADER) - sizeof(TCP_HEADER) - size;

tcp_header_length = sizeof(TCP_HEADER) + tcp_options_length;

return tcp_sum_calc((USHORT)(tcp_header_length+size), (u16 )&iph->Source,(u16)&iph->Destination, 1,(u16*)tcph);</len_tcp>

> I have been implementing various checksum functions, but none seem to

generate the correct checksum for a tcp packet with or with out
data.

I’ve tried using a checksum calculator on the tcp dump.
http://mna.nlanr.net/Software/HEC/hexhec.html Their calculation for
the following hex data was also incorrect.

I’m not sure exactly what your question is, but if you just want an
example of one that works, you can look at the code for my Xen PV
drivers. That code sums data across buffer boundaries but should be
pretty straightforward.

You can view the source online here:
http://xenbits.xensource.com/ext/win-pvdrivers.hg?file/2b7f8973a41b/xenn
et/xennet_rx.c

The function you want is XenNet_SumPacketData, around line 215.

James

I think explanation lies with the following statement

[begin quote]

Here is one checksum function I borrowed from http://www.netfor2.com/tcpsum.htm

[end quote]

This is what happens when people “borrow” someone else’s code, instead of using it simply as a reference when writing their own one. The algorithm of checksum calculation is very well defined and described in RFCs, as well as in quite a few books on TCPIP (Wright and Stevens classic is the very first example that comes to my mind). There are only two possibilities here - either you “borrowed” the buggy code, or, what is much more likely, just screwed up the perfectly workable code while adjusting it to your needs…

Anton Bassov

nevermind. I did not copy the source and destination ip address byte by byte correctly into the psuedoheader. I only noticed when I printed out the buffer that was being checksummed. It works now.