将数据添加到特定协议的数据包

时间:2016-03-31 03:13:47

标签: c networking kernel-module netfilter

我正在实施一项名为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;
}

我做错了什么?

1 个答案:

答案 0 :(得分:1)

我解决了将skb-&gt;尾部移回原始位置的问题:skb->tail -= sizeof(struct xorhdr);。因此,当我收到另一方的包时,我使用我放的数据,并将skb-&gt;尾返回到原始位置。

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;
}