title: Calculating TCP Checksum in a netfilter module
body: <p>I am trying to change some fields in the IP and TCP header in a netfilter postrouting hook, however I can't seem to get the kernels TCP checksum function to work properly to amend it afterwards.</p>
  
  <p>The checksum is fine during the TCP handshake, but as soon as the packet has any payload the checksum is wrong.</p>
  
  <p>I have pulled this checksum code together from digging around the TCP source.  I am fairly sure tcplen is correct, matching the expected TCP header + payload size.</p>
  
  <pre><code>static unsigned int posthook_fn(
      unsigned int hooknum, 
      struct sk_buff *skb,
      const struct net_device *in, 
      const struct net_device *out,
      int (*okfn)(struct sk_buff *))
  {
    struct iphdr *iph;
    struct tcphdr *tcph;
    iph = ip_hdr(skb);
    tcph = (struct tcphdr *)(skb-&gt;data + iph-&gt;ihl * 4);
  
    tcph-&gt;source = port;
    iph-&gt;saddr = addr;
  
    tcplen = (skb-&gt;len - (ip_header-&gt;ihl &lt;&lt; 2));
    tcph-&gt;check = 0; 
    tcph-&gt;check = tcp_v4_check(tcph, tcplen, 
          iph-&gt;saddr, 
          iph-&gt;daddr, 
          csum_partial((char *)tcph, tcplen, 0)); 
    skb-&gt;ip_summed = CHECKSUM_NONE; //stop offloading
  
    ip_header-&gt;check = ip_fast_csum((u8 *)iph, iph-&gt;ihl);         
  
    return NF_ACCEPT;
  }
  </code></pre>
  
  <p>Am I correct in thinking that tcp_v4_check calculates the psuedo header and csum_partial calculates the unfolded checksum for the payload and tcp_header?</p>
  
  <p>I really want to avoid writing the function myself as the kernel will be much faster as the underlying functions use assembly for the calculation.  </p>
  
  <p>Is there an alternative method that might work? Or is there something I am missing out?</p>