linux - 更新 header 中的 TCP/IP 校验和

标签 linux tcp linux-kernel ip

我试图在发送数据包时在内核中手动修改 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/

相关文章:

sockets - 通过闭合连接确定主体长度如何可靠(RFC 2616 4.4.5)

c - 是否可以通过用户编程来控制页出和页入?如果是的话怎么办?

c - 确保系统调用中的 UID/GID 检查在 RCU 临界区中执行

linux - 为什么我的 bashrc 脚本不起作用?

linux - xargs 执行 nc 检查端口

c# - 游戏如何处理 NAT 路由器问题?

linux - vmsplice(2) 的语义是什么,有和没有 gifting?

java - 如何使用 Eclipse 在 .JAR 文件中包含特定于平台的 native 库?

android - Android 和 Linux 中的桌面环境/架构

c - Linux TCP/IP 诊断 C 程序中 TCP/IP read() 返回 0 的原因