How to calculate TCP checksum

后端 未结 3 1066
自闭症患者
自闭症患者 2021-02-06 08:46

I am writing a Kernel Module that uses Netfilter hooks to modify some of the TCP header information and obviously, before sending, I want to re-calculate the checksum.
I al

相关标签:
3条回答
  • 2021-02-06 09:18

    To re-calculate the checksum, you better calculate an incremental checksum - just modify the existing checksum based on the fields you've changed, rather than reading the entire packet.

    This must be done while you're changing the packet, when you know both the old values and the new values you store.

    The basic idea is tcp->check += (new_val - old_val).
    It's a bit more complicated than this, becuase:
    1. old_val and new_val need to be 16-bit values, which are aligned on 2 bytes (e.g. changing a port number).
    2. The checksum uses ones complement arithmetic, so you need to do "carry feedback". This basically means, that if tcp->check + new_val - old_val is negative, you need to subtract 1 from the result.

    0 讨论(0)
  • Here is an example which combine netfilter API + checksum for TCP (not IP):

    http://www.linuxvirtualserver.org/software/tcpsp/index.html

    Look into the file called tcpsp_core.c.

        th->check = 0;
        th->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
                                      datalen, iph->protocol,
                                      csum_partial((char *)th, datalen, 0));
        skb->ip_summed = CHECKSUM_UNNECESSARY;
    

    (notice it is assigned zero first, checksum calculated, then IP checksum indicated as not needed).

    Depends on which netfilter module u load (there are many!!!) they will work at different layer, eg, iptable working at IP layer is shown below (image):

    http://ars.sciencedirect.com/content/image/1-s2.0-S1389128608004040-gr3.jpg

    0 讨论(0)
  • 2021-02-06 09:23

    @ugoren's answer is not precise. According to RFC1624 https://tools.ietf.org/html/rfc1624, this will sometimes produce -0 (0xFFFF), which is not allowed.

    The correct way to compute checksum should be: new_tcp_check = ~(~old_tcp_check + ~old_val + new_val)

    0 讨论(0)
提交回复
热议问题