LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-21-2010, 06:14 PM   #1
yaplej
Member
 
Registered: Apr 2009
Distribution: CentOS, Ubuntu, openSuSE
Posts: 165
Blog Entries: 1

Rep: Reputation: 22
TCP Checksum function


Hey all,

I have been trying to write my own TCP checksum function. Iv got a description of how the checksum is calculated from here.
http://en.wikipedia.org/wiki/Transmi...cksum_for_IPv4

In short the one complement of each 16-bit word are added up, and then the result of that is the bitwise complemented.

So to sum all the 16-bit words it would be something like this.
Code:
for each word{
      sum += ~word;
}
Then that sum is bitwise complemented.
Code:
sum = ~sum;
So here is my function so far. I have not been able to get a correct checksum out of though. Iv been tweaking things all day, and not figured out what I am doing wrong.

Code:
unsigned short tcp_sum_calc(unsigned short len_tcp, unsigned short *src_addr, unsigned short *dest_addr, unsigned short *buff)
{
      
	unsigned short prot_tcp = 6;
	unsigned short sum;
	int i;
	sum = 0;
	
	/* Check if the tcp length is even or odd.  Add padding if odd. */
	if((len_tcp % 2) == 1){
		buff[len_tcp] = 0;  // Empty space in the ip buffer should be 0 anyway.
      	len_tcp += 1; // incrase length to make even.
	}
	
	/* add the pseudo header */	
	sum += ~src_addr[0];
	sum += ~src_addr[1];
	sum += ~dest_addr[0];
	sum += ~dest_addr[1];
	sum += ~len_tcp;
	sum += ~prot_tcp;
      
	/* 
	 * calculate the checksum for the tcp header and payload
	 * len_tcp represents number of 8-bit bytes, 
	 * we are working with 16-bit words so divide len_tcp by 2. 
	 */
	for(i=0;i<(len_tcp/2);i++){
		sum += buff[i];
	}
    printf("%02x:", (unsigned short)sum);
    
	// keep only the last 16 bits of the 32 bit calculated sum and add the carries
	//sum = (sum >> 16) + (sum & 0xFFFF);
	//printf("%02x:", (unsigned short)sum);
	
	//sum += (sum >> 16);
	//printf("%02x:", (unsigned short)sum);
	
	// Take the bitwise complement of sum
	sum = ~sum;
	printf("%02x:\n", (unsigned short)sum);

	return ((unsigned short) sum);
}
Thank you.
 
Old 04-22-2010, 05:10 AM   #2
broken
Member
 
Registered: Apr 2010
Location: Your mom's trailer
Distribution: NetBSD
Posts: 31

Rep: Reputation: 15
Mind the endianness of the system.
 
Old 04-22-2010, 01:45 PM   #3
yaplej
Member
 
Registered: Apr 2009
Distribution: CentOS, Ubuntu, openSuSE
Posts: 165

Original Poster
Blog Entries: 1

Rep: Reputation: 22
So a TCP checksum is not the sum of one's complement of all the 16-bit words. Its the 32-bit sum of all the 16-bit words converted to 16-bit adding any carries, folded on itself, then taking the one's complement of that. Well something like that. Here is my working function.

Minding the endianness, and also how the 32-bit sum is converted to 16-bit. I noticed the order I was originally doing it was wrong based on the example given in the RFC.
http://www.faqs.org/rfcs/rfc1071.html

Code:
unsigned short tcp_sum_calc(unsigned short len_tcp, unsigned short *src_addr, unsigned short *dest_addr, unsigned short *buff)
{
      
	unsigned short prot_tcp = 6;
	long sum;
	int i;
	sum = 0;
	
	/* Check if the tcp length is even or odd.  Add padding if odd. */
	if((len_tcp % 2) == 1){
		buff[len_tcp] = 0;  // Empty space in the ip buffer should be 0 anyway.
      	len_tcp += 1; // incrase length to make even.
	}
	
	/* add the pseudo header */	
	sum += ntohs(src_addr[0]);
	sum += ntohs(src_addr[1]);
	sum += ntohs(dest_addr[0]);
	sum += ntohs(dest_addr[1]);
	sum += len_tcp; // already in host format.
	sum += prot_tcp; // already in host format.
      
	/* 
	 * calculate the checksum for the tcp header and payload
	 * len_tcp represents number of 8-bit bytes, 
	 * we are working with 16-bit words so divide len_tcp by 2. 
	 */
	for(i=0;i<(len_tcp/2);i++){
		sum += ntohs(buff[i]);
	}
    
	// keep only the last 16 bits of the 32 bit calculated sum and add the carries
	sum = (sum & 0xFFFF) + (sum >> 16);
	sum += (sum >> 16);
	
	// Take the bitwise complement of sum
	sum = ~sum;

	return htons(((unsigned short) sum));
}
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
TCP checksum doubt arun4will Programming 1 05-17-2007 08:53 AM
TCP checksum error mshenbagaraj Programming 3 05-16-2007 02:43 PM
tcp checksum incorrect x1228 Programming 1 09-11-2006 03:53 AM
TCP header checksum live_dont_exist Programming 16 04-13-2005 12:45 PM
anyone can help me with the TCP checksum? vaaub Programming 1 02-10-2004 01:32 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:28 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration