【问题标题】:How to recalculate IP checksum in netfilter?如何在 netfilter 中重新计算 IP 校验和?
【发布时间】:2012-11-02 21:08:03
【问题描述】:

我正在开发一个 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"?)]

【问题讨论】:

  • 你正在用 C++ 实现一个 Linux 内核模块?
  • 您在 Linux 内核模块中使用“您在互联网上找到的”代码?你明白版权是什么意思吗?您是否理解“签署人”意味着您发誓您编写了所有代码,或者拥有代码版权的人已根据 GPLv2 对其进行许可?
  • 定义“损坏的 IP 标头”。这是否意味着“不正确的校验和”或实际上是“损坏的 IP 标头”?如果是后者,那么您可能正在搞砸其他事情。
  • Header checksum: 0x0000 [不正确,应该是0x85de(可能是“IP checksum offload”引起的?)]

标签: c++ linux module kernel netfilter


【解决方案1】:

您在哪里捕获数据包?

IP 校验和(以及 TCP/UDP 校验和)可以由网卡本身计算。如果您的卡上是这种情况(这是一个非常常见的功能)并且您正在您的机器上捕获,我希望看到 0 个校验和。

【讨论】:

    【解决方案2】:

    如果您这样定义 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);
    

    你可以看看我的问题:How to append data on a packet from kernel space? 在那里,您可以在底部的给定答案中找到详细代码。我不得不在那里 重新计算 IP 和 UDP 标头校验和。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-21
      • 1970-01-01
      • 2018-10-23
      • 1970-01-01
      • 1970-01-01
      • 2012-09-03
      • 1970-01-01
      • 2015-01-02
      相关资源
      最近更新 更多