如何在网络过滤器中重新计算 IP 校验和
How to recalculate IP checksum in netfilter?
我正在开发一个网络过滤器内核模块,我需要在其中重新计算IP校验和。我使用这个函数来计算IP校验和(在互联网上的某个地方找到它):
unsigned short ComputeIPChecksum(unsigned char *data, int len)
{
long sum = 0; /* assume 32 bit long, 16 bit short */
unsigned short *temp = (unsigned short *)data;
while(len > 1){
sum += *temp++;
if(sum & 0x80000000) /* if high order bit set, fold */
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}
if(len) /* take care of left over byte */
sum += (unsigned short) *((unsigned char *)temp);
while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);
return ~sum;
}
通过查看 wireshark,我可以看到传入数据包已成功接收,但对于传出数据包,wireshark 显示不正确的 ip 校验和。这是我的钩子函数:
static unsigned int hook_func(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
sock_buff = skb;
if (sock_buff)
{
ip_header = (struct iphdr *)skb_network_header(sock_buff);
if (ip_header && ip_header->protocol == TCP)
{
ip_header->check = ComputeIPChecksum((unsigned char *)ip_header, ip_header->ihl*4);
}
}
return NF_ACCEPT;
}
这是主要的,我已经将相同的钩子函数绑定到PRE_ROUTING和POST_ROUTING
static int __init init_main(void)
{
nfho.hook = hook_func;
nfho.hooknum = 0;
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST;
nfho1.hook = hook_func;
nfho1.hooknum = 4;
nfho1.pf = PF_INET;
nfho1.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho);
nf_register_hook(&nfho1);
return 0;
}
为什么传出数据包的 IP 校验和会损坏???
wireshark 中显示的错误:
Header checksum: 0x0000 [incorrect, should be 0x85de (maybe caused by "IP checksum offload"?)]
您在哪里捕获数据包?
IP 校验和(以及 TCP/UDP 校验和)可以由网卡本身计算。如果您的卡上是这种情况(这是一个非常常见的功能),并且您在计算机上捕获,我希望看到 0 个校验和。
如果像这样定义 IP 标头:
struct iphdr *iph;
然后
iph = (struct iphdr *) skb_header_pointer(skb, 0, 0, NULL);
然后,您可以重新计算校验和,如下所示。
/* Calculation of IP header checksum */
iph->check = 0;
ip_send_check (iph);
你可以看看我的问题:如何从内核空间在数据包上附加数据?在那里,您可以在底部的给定答案中找到详细代码。在那里我不得不重新计算 IP 和 UDP 标头校验和。
相关文章:
- 如何用尽可能少的数据将数据缓冲区计算为零校验和值
- 计算校验和的逐位运算符
- 如何从存储在 QByteArray 中的十六进制值计算校验和
- 如何在 c++ 中计算对象的哈希/校验和/指纹?
- C++文件传输的校验和算法
- 如何从 IP 校验和字段中计算十六进制值
- 计算句子的校验和(XOR)(由不同变量/类型的组合形成)
- 编译后如何计算某些二进制功能(或基本块)的校验和
- 确定是否使用boost.asio计算UDP校验和
- 正在计算ICMP数据包校验和
- 如何计算 dmg 文件上的主校验和和数据分叉校验和
- 在 C++ 中计算 8 位校验和
- 如何计算大文件的 MD5 和 SHA 校验和
- 如何在网络过滤器中重新计算 IP 校验和
- Sqlite 表中的校验和计算
- TCP校验和计算出错
- 计算 400mb >大文件的 sha-1 或 CRC32 校验和
- 计算一个点数的校验和
- 是否有SIMD指令来加速校验和计算
- 计算OSPF中LSA的校验和