2012-07-10 188 views
7

我写一个使用Netfilter的钩子来修改某些TCP报头信息,并且显然是一个内核模块,发送前,我要重新计算校验和。
我也在接收端编辑标题,所以我需要在那里重新计算它。如何计算TCP校验

网上搜索,我发现有些人说我可以简单地将其设置为0,它会计算对我来说,显然没有奏效。
我还发现这个功能

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

虽然没有人解释这是怎么使用的,以及是否我可以在接收/实际使用它发送相同的方式。
我自己尝试是校验设置为0,则调用该函数传递SKB我已经和是skb-> SK我有,仍然一无所获。

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

+0

你究竟什么设置为0,你在哪里期望找到校验?查看代码,你应该设置tcp_hdr(skb) - > check为0,然后调用该函数,之后新的校验和应该在那里。 – BjoernD 2012-07-10 09:16:59

+0

,这正是我所做的,但是当我加载模块时,所有的TCP连接都不起作用。 – Fingolfin 2012-07-10 10:25:04

+0

您应该在问题中添加“C”标签。顺便说一句,看看http://www.winpcap.org/pipermail/winpcap-users/2007-July/001984.html – Jite 2012-07-10 10:27:47

回答

3

要重新计算校验和,你更好地计算增量校验 - 只需要修改根据你已经改变了各个领域,现有的校验和,而不是读取整个数据包。

这必须在你改变数据包来实现,当你知道这两个老的价值观和您存储的新值。

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

+1

这是做这件事的正确方法。它速度更快,数据损坏风险更小。从头开始重新计算校验和可能会掩盖已经发生的任何数据损坏。 – kasperd 2015-10-17 22:08:02

1

这里是一个结合网络过滤器API +校验的TCP(而不是IP)的例子:

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

查找到一个名为tcpsp_core.c文件。 (注意先分配零,计算校验和,然后IP校验和表示为不需要)。

取决于ü加载哪个网络过滤模块(有很多!!!),他们将在不同的层,例如,在iptable的IP层工作的工作如下所示(图像):

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

1

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

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