如何计算TCP校验和

时间:2012-07-10 05:23:26

标签: c linux networking network-programming linux-kernel

我正在编写一个内核模块,它使用Netfilter挂钩修改一些TCP头信息,显然,在发送之前,我想重新计算校验和。
我也在接收端编辑标题,所以我也需要在那里重新计算它。

在线搜索,我发现有些人说我可以简单地将其设置为0并且它将为我计算,显然这不起作用。
我也找到了这个功能

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

虽然没有人解释如何使用它,以及我是否可以在接收/发送时以相同的方式使用它 我自己的尝试是将校验和设置为0然后调用此函数传递我拥有的skb和skb-> sk我有,仍然没有。

那么请问,计算TCP数据报校验和的简单方法是什么?

3 个答案:

答案 0 :(得分:3)

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

当您知道旧值和存储的新值时,必须在更改数据包时执行此操作。

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

答案 1 :(得分:1)

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

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模块(有很多!!!)它们将在不同的层工作,例如iptable在IP层工作如下所示(图片):

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

答案 2 :(得分:1)

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

计算校验和的正确方法应该是: 'D:\juliet.txt'