我试图在发送数据包时在内核中手动修改 IP header 中的源地址和目标地址。之后,我需要重新计算 IP 校验和和 TCP 校验和。
我是按照下面的方式来做的。
iph = ip_hdr(skb);
iph->saddr = mysaddr;
iph->daddr = mydaddr;
tcph= tcp_hdr(skb);
__tcp_v4_send_check(skb, iph->saddr, iph->daddr);
iph->tot_len = htons(skb->len);
ip_send_check(iph);
但是在接收端,校验和总是在TCP层失败,而它可以通过IP层。
我调试了很多,发现在正常过程中,当数据包到达时,skb->ip_summed一般是CHECKSUM_UNNECESSARY,但是如果我在发送方修改,那么这个值到达接收方时就是CHECKSUM_NONE .
有人可以给我一些建议吗?谢谢。
最佳答案
关于CHECKSUM_UNNECESSARY和CHECKSUM_NONE,细节太多,无法用简单的文字描述,最好阅读:
<<Understanding.Linux.Network.Internals >> / 19.1.1.2. sk_buff structure.
在这里发表我的猜测(希望对你有帮助):
Since at sender side, you see generally CHECKSUM_UNNECESSARY, this might means your network card is probably able to do checksum verification and computing checksum in hardware.
By default, if TCP stack seeing your network card has this hardware capability, it would not bother computing checksum itself in software. But set CHECKSUM_PARTIAL in egress packet, so that network interface driver would instruct its hardware to computing checksum.
In your case, you compute the checksum by yourself, and should set CHECKSUM_NONE, so network interface would not compute the checksum again for you ( if doing so, break your checksum of modified packet ).
您可以使用任何在发送方和接收方之间连接集线器的数据包捕获工具(如 wireshark),查看捕获数据包中的校验和是否损坏。
关于linux - 更新 header 中的 TCP/IP 校验和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21763071/