C TCP Checksum Programming

I am having trouble completing a checksum for TCP in a few days. I have looked at many sources on the Internet, but not one of the examples that I have seen shows how to perform the TCP checksum. I also looked through the RFC document and still am having problems:

Below is the code that I use to create the checksum:

unsigned short checksum(unsigned short * buffer, int bytes) { unsigned long sum = 0; unsigned short answer = 0; int i = bytes; while(i>0) { sum+=*buffer; buffer+=1; i-=2; } sum = (sum >> 16) + (sum & htonl(0x0000ffff)); sum += (sum >> 16); return ~sum; } 

This function works for IP checksum.

The following is the structure I created for my TCP header:

 struct tcp_header { unsigned short tcp_sprt; unsigned short tcp_dprt; unsigned int tcp_seq; unsigned int tcp_ack; unsigned char tcp_res:4; unsigned char tcp_off:4; unsigned char tcp_flags; unsigned short tcp_win; unsigned short tcp_csum; unsigned short tcp_urp; }; 

I use Wireshark to check for these packets, and the only error is the checksum.

Finally, this is the header pseudo-structure that I load with the TCP header and the information from the IP header:

 struct pseudoTcpHeader { unsigned int ip_src; unsigned int ip_dst; unsigned char zero;//always zero unsigned char protocol;// = 6;//for tcp unsigned short tcp_len; struct tcp_header tcph; }; 

Once I load this structure with the correct information, I then use the checksum function in the entire pseudo-header structure and assign the TCP checksum to this value. Do you see something wrong with what I have provided? If the problem is not here, it could be a careless mistake that I do not see.

+4
source share
3 answers

I found a pretty good example on the winpcap mailing list , which should address Greg's comment on 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); } 
+4
source

I see a couple of things:

  • You do not account for odd-length data by filling in zero.
  • When reading each word from the packet, you will need to indicate the byte order of the network.
  • Your use of htonl(0x0000ffff) seems suspicious. Why are you converting a constant to network byte order to combine it with data in host byte order?
+3
source

RFC 793 says: "If a segment contains an odd number of headers and text octets for a checksum, the last octet is padded with zeros to the right to form a 16-bit word for checksum purposes." Your code above does not handle this case. I think the loop condition should be i> 1, and then check i == 1 outside the loop and do special processing for the last octet.

+2
source

Source: https://habr.com/ru/post/1390761/


All Articles