I have been having trouble doing the checksum for TCP for several days now. I have looked at many sources on the Internet but none of the examples that I have seen show you
I see a couple of things:
htonl(0x0000ffff)
seems suspicious. Why are you converting a constant to network byte order to combine it with data in host byte order?RFC 793 says "If a segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a 16 bit word for checksum purposes." Your code above does not handle that case. I think the loop conditional should be i > 1 and then check for i == 1 outside the loop and do the special handling for the last octet.
I too struggled to find c++/c code that computes it, until I found How to Calculate IP/TCP/UDP Checksum–Part 2 Implementation – roman10, and it worked! Tested it with Wireshark's validation.
UPDATE
Link broke meanwhile, recovered it and put it as a gist in my account - How to Calculate IP/TCP/UDP Checksum
I found a fairly good example on the winpcap-users mailing list which should address Greg's comment about odd length data and give you something to compare your code against.
USHORT CheckSum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size)
cksum += *(UCHAR*)buffer;
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}