7

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 also edit the header at the receiving side, so I need to re-calculate it there too.

Searching online, I found some people saying I can simply set it to 0 and it'll be calculated for me, apparently that didn't work.
I've also found this function

tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);

Though no one explained how this is used, and whether I can actually use it at the receiving/sending the same way.
My own attempt was to set checksum to 0 then call this function passing the skb I have and the skb->sk I have, still nothing.

So please, what is a straightforward way to calculate the checksum of TCP datagrams?

4

3 回答 3

3

要重新计算校验和,您最好计算增量校验和 - 只需根据您更改的字段修改现有校验和,而不是读取整个数据包。

这必须在您更改数据包时完成,当您知道旧值和存储的新值时。

基本思想是tcp->check += (new_val - old_val)
它比这更复杂一点,因为:
1.old_val并且new_val需要是 16 位值,它们在 2 个字节上对齐(例如更改端口号)。
2.校验和使用补码算法,所以需要做“进位反馈”。这基本上意味着,如果tcp->check + new_val - old_val是负数,则需要从结果中减去 1。

于 2012-07-10T10:42:59.167 回答
1

这是一个结合了 netfilter API + TCP(不是 IP)校验和的示例:

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

查看名为 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;

(注意它首先分配为零,计算校验和,然后 IP 校验和指示为不需要)。

取决于您加载的 netfilter 模块(有很多!!!)它们将在不同的层工作,例如,在 IP 层工作的 iptable 如下所示(图片):

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

于 2012-07-15T12:13:11.133 回答
1

@ugoren 的回答并不准确。根据 RFC1624 https://www.rfc-editor.org/rfc/rfc1624,这有时会产生 -0 (0xFFFF),这是不允许的。

计算校验和的正确方法应该是: new_tcp_check = ~(~old_tcp_check + ~old_val + new_val)

于 2017-06-30T00:54:05.067 回答