繁体   English   中英

如何计算TCP校验和

[英]How to calculate TCP checksum

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

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

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM