title: IP and TCP header checksum calculate in c
body: <p>I'm writing a simple program to send/receive TCP packets and incorporate it into a larger project. I got stuck at the checksum part where the number I calculated is not matched with the wireshark number.</p>
  
  <p>For checksum function, I re-use the code from Mike Muss as below:</p>
  
  <pre><code>static int
  in_cksum(u_short *addr, int len)
  {
      register int nleft = len;
      register u_short *w = addr;
      register int sum = 0;
      u_short answer = 0;
  
      /*
       * Our algorithm is simple, using a 32 bit accumulator (sum), we add
       * sequential 16 bit words to it, and at the end, fold back all the
       * carry bits from the top 16 bits into the lower 16 bits.
       */
      while (nleft &gt; 1)  {
          sum += *w++;
          nleft -= 2;
      }
  
      /* mop up an odd byte, if necessary */
      if (nleft == 1) {
          *(u_char *)(&amp;answer) = *(u_char *)w ;
          sum += answer;
      }
  
      /* add back carry outs from top 16 bits to low 16 bits */
      sum = (sum &gt;&gt; 16) + (sum &amp; 0xffff); /* add hi 16 to low 16 */
      sum += (sum &gt;&gt; 16);         /* add carry */
      answer = ~sum;              /* truncate to 16 bits */
      return(answer);
  }
  </code></pre>
  
  <p>I received a packet and store in char buffer[2048]. In order to get IP header, I do:</p>
  
  <pre><code>struct iphdr* ip;
  ip = (struct iphdr*) buffer;
  </code></pre>
  
  <p>From here, I can read information correctly as ip->protocol, ip->saddr, etc., and even print out the correct checksum as displayed in wireshark</p>
  
  <pre><code>printf("Print checksum = 0x%x\n",ntohs(ip-&gt;check));
  </code></pre>
  
  <p>Then I try to calculate the checksum using the function above and print it out</p>
  
  <pre><code>printf("My calculated checksum =0x%x\n",in_cksum ((unsigned short*) ip, sizeof(struct iphdr)));
  </code></pre>
  
  <p>What I got is "My calculated checksym = 0x0" and it seems that there is nothing in IP header. I guess that I might not pass in the in_cksum function parameter correctly, but I'm not sure how to fix or if there is another problem in the way that I'm doing.</p>
  
  <p>IP cksum problem is SOLVED below. However, I meet a similar problem when try to calculate TCP checksum. Below is how I get tcp header:</p>
  
  <pre><code>tcp=(struct tcphdr*) (buffer+sizeof(struct iphdr);
  </code></pre>
  
  <p>After this, again I can read correct information about tcp header such as tcp->source, tcp->dest, and even tcp->check</p>
  
  <p>Then I tried to re-compute the checksum as below:</p>
  
  <pre><code>tcp-&gt;check=0;
  tcp-&gt;check=in_cksum((unsigned short*)tcp, ntohs(ip-&gt;tot_length)-(4*ip-&gt;ihl));
  </code></pre>
  
  <p>The result I got here is different from what I printed out before. I think my problem could in the length that I pass in the cksum function, but am not quite sure how to fix it.</p>
  
  <p>Any help would be greatly appreciated. Thank you in advance!</p>