我正在编写一个内核模块,它使用Netfilter挂钩修改一些TCP头信息,显然,在发送之前,我想重新计算校验和。
我也在接收端编辑标题,所以我也需要在那里重新计算它。
在线搜索,我发现有些人说我可以简单地将其设置为0并且它将为我计算,显然这不起作用。
我也找到了这个功能
tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
虽然没有人解释如何使用它,以及我是否可以在接收/发送时以相同的方式使用它
我自己的尝试是将校验和设置为0然后调用此函数传递我拥有的skb和skb-> sk我有,仍然没有。
那么请问,计算TCP数据报校验和的简单方法是什么?
答案 0 :(得分:3)
要重新计算校验和,最好计算增量校验和 - 只需根据您更改的字段修改现有校验和,而不是读取整个数据包。
当您知道旧值和存储的新值时,必须在更改数据包时执行此操作。
基本理念是tcp->check += (new_val - old_val)
这比这复杂一点,因为:
1. old_val
和new_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'