【问题标题】:Add data to packet of a specific protocol将数据添加到特定协议的数据包中
【发布时间】:2016-07-19 07:42:10
【问题描述】:

我正在实现一个名为 XOR 的新协议。首先,数据包在用户空间中创建并发送到网络。之后数据包正常到达网络中的其他节点。现在我需要创建一个模块来拦截发送的每个模块并添加标题或一些数据。我创建了一个将一些数据放入数据包的模块,但没有成功。

我尝试了一些东西,但是当激活我的模块时,数据包被丢弃了。这就是我的模块正在做的事情:

struct xorhdr {
    int in;
    int out;
};

static unsigned int asnfwd_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph;
    struct asnfwd_opt *opt;
    __be32 addr = 0;
    struct tcphdr *th;
    struct udphdr *uh;

    /* sanity check */
    if (!skb)
        goto accept;

    /* recover the IPv4 header */
    iph = ip_hdr(skb);
    if (!iph)
        goto accept;

    if (iph->protocol == 17) {
        uh = (struct udphdr *) skb_transport_header(skb);
        if ((unsigned int) ntohs(uh->source) == XOR_PORT && (unsigned int) ntohs(uh->dest) == XOR_PORT) {
            printk("\n****************************\n");
            printk("Hook is %s\n", (in ? "pre-routing" : "local-out"));
            printk("(Ogirinal) From %pI4 to %pI4.\n", &iph->saddr, &iph->daddr);
            printk(KERN_INFO "free:%d", skb_headroom(skb));

            if (in) {
                struct xorhdr *ptr;

                if (skb->tail + sizeof(struct xorhdr) < skb->end) {
                    unsigned char* tail_ptr = skb_tail_pointer(skb);
                    ptr = (struct xorhdr *)(tail_ptr);
                    printk(KERN_INFO "CBin:%d\n", ptr->in);
                    printk(KERN_INFO "CBout:%d\n", ptr->out);
                }

            } else {
                if (skb_headroom(skb) > sizeof(struct xorhdr)) {
                    struct xorhdr *xorh;
                    xorh = kmalloc(sizeof(struct xorhdr), GFP_ATOMIC);
                    unsigned char *new_data;

                    new_data = skb_tail_pointer(skb);
                    if (skb->tail + sizeof(struct xorhdr) < skb->end) {
                        xorh->in = 6;
                        xorh->out = 5;
                        printk(KERN_INFO "CBin:%d\n", xorh->in);
                        printk(KERN_INFO "CBout:%d\n", xorh->out);
                        skb->tail += sizeof(struct xorhdr);
                        skb->len += sizeof(struct xorhdr);
                        memcpy(new_data, xorh, sizeof(struct xorhdr));
                    }

                    kfree(xorh);

                    // update ip header pointer 
                    iph = ip_hdr(skb);

                    // calculate udp checksum
                    uh = udp_hdr(skb);
                    uh->check = 0;
                    uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, ip_payload_len(iph), IPPROTO_UDP, csum_partial(uh, ip_payload_len(iph), skb->csum));
                    skb->ip_summed = CHECKSUM_NONE;

                    // calculate ip checksum 
                    ip_send_check (iph);

                }
            }
            PRINTK("\n****************************\n\n");
        }


    }

    accept:
        return NF_ACCEPT;
}

我做错了什么?

【问题讨论】:

    标签: c networking kernel-module netfilter


    【解决方案1】:

    我解决了将 skb->tail 移回原始位置的问题:skb-&gt;tail -= sizeof(struct xorhdr);。所以当我在另一边收到包裹时,我使用我放置的数据,并将 skb->tail 恢复到原始位置。

    struct xorhdr {
        int in;
        int out;
    };
    
    static unsigned int asnfwd_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
    {
        struct iphdr *iph;
        struct asnfwd_opt *opt;
        __be32 addr = 0;
        struct tcphdr *th;
        struct udphdr *uh;
    
        /* sanity check */
        if (!skb)
            goto accept;
    
        /* recover the IPv4 header */
        iph = ip_hdr(skb);
        if (!iph)
            goto accept;
    
        if (iph->protocol == 17) {
            uh = (struct udphdr *) skb_transport_header(skb);
            if ((unsigned int) ntohs(uh->source) == XOR_PORT && (unsigned int) ntohs(uh->dest) == XOR_PORT) {
                printk("\n****************************\n");
                printk("Hook is %s\n", (in ? "pre-routing" : "local-out"));
                printk("(Ogirinal) From %pI4 to %pI4.\n", &iph->saddr, &iph->daddr);
                printk(KERN_INFO "free:%d", skb_headroom(skb));
    
                if (in) {
                    struct xorhdr *ptr;
    
                    if (skb->tail + sizeof(struct xorhdr) < skb->end) {
                        unsigned char* tail_ptr = skb_tail_pointer(skb);
                        ptr = (struct xorhdr *)(tail_ptr);
                        printk(KERN_INFO "CBin:%d\n", ptr->in);
                        printk(KERN_INFO "CBout:%d\n", ptr->out);
                        skb->tail -= sizeof(struct xorhdr);
    
                        // update ip header pointer 
                        iph = ip_hdr(skb);
    
                        // calculate udp checksum
                        uh = udp_hdr(skb);
                        uh->check = 0;
                        uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, ip_payload_len(iph), IPPROTO_UDP, csum_partial(uh, ip_payload_len(iph), skb->csum));
                        skb->ip_summed = CHECKSUM_NONE;
    
                        // calculate ip checksum 
                        ip_send_check (iph);
                    }
    
                } else {
                    if (skb_headroom(skb) > sizeof(struct xorhdr)) {
                        struct xorhdr *xorh;
                        xorh = kmalloc(sizeof(struct xorhdr), GFP_ATOMIC);
                        unsigned char *new_data;
    
                        new_data = skb_tail_pointer(skb);
                        if (skb->tail + sizeof(struct xorhdr) < skb->end) {
                            xorh->in = 6;
                            xorh->out = 5;
                            printk(KERN_INFO "CBin:%d\n", xorh->in);
                            printk(KERN_INFO "CBout:%d\n", xorh->out);
                            skb->tail += sizeof(struct xorhdr);
                            skb->len += sizeof(struct xorhdr);
                            memcpy(new_data, xorh, sizeof(struct xorhdr));
                        }
    
                        kfree(xorh);
    
                        // update ip header pointer 
                        iph = ip_hdr(skb);
    
                        // calculate udp checksum
                        uh = udp_hdr(skb);
                        uh->check = 0;
                        uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, ip_payload_len(iph), IPPROTO_UDP, csum_partial(uh, ip_payload_len(iph), skb->csum));
                        skb->ip_summed = CHECKSUM_NONE;
    
                        // calculate ip checksum 
                        ip_send_check (iph);
    
                    }
                }
                PRINTK("\n****************************\n\n");
            }
    
    
        }
    
        accept:
            return NF_ACCEPT;
    }
    

    【讨论】:

    • 您好!你的代码对我很有帮助。你能告诉我你把这个钩子放在内核代码的什么地方吗?是在 UDP 发送之前/之后吗?这会很有帮助。
    • 这是一个内核模块,所以为这个相同的功能添加了两个钩子。第一个挂钩是 NF_INET_PRE_ROUTING,第二个挂钩是 NF_INET_LOCAL_OUT。 NF_INET_PRE_ROUTING 什么时候执行 if (in) 里面的代码块,什么时候 NF_INET_LOCAL_OUT 执行 else 代码块。
    • 感谢您的快速回复。这回答了我的问题。
    • 还有一件事,当你只是在尾部追加数据时,为什么在 out 的情况下使用函数 skb_headroom()
    • 代码错误,正确的是检查tailroom是否有空间:)
    猜你喜欢
    • 2018-02-18
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多