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>