如何追加从内核空间分组数据? [英] How to append data on a packet from kernel space?

查看:192
本文介绍了如何追加从内核空间分组数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想追加一些数据从内核空间的数据包。我有回声客户端和服务器。我在命令行中键入类似:./client信息,服务器只会回回来。服务器与./server运行。

I am trying to append some data on a packet from kernel space. I have an echo client and server. I type in the command line like: ./client "message" and the server just echoes it back. The server was run with ./server .

现在,在客户端和服务器是在两个不同的机器(可以是虚拟机)。我写它运行在客户机上的内核模块。其工作,而该包就从机器中追加12345,消息后。我是presenting低于code。

Now, the client and server are on two different machines (may be VMs). I am writing a kernel module which runs on the client machine. Its work is to append "12345" after "message" while the packet goes out of the machine. I am presenting the code below.

/*
 * This is ibss_obsf_cat.c
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/udp.h>
#include <linux/ip.h>

#undef __KERNEL__
#include <linux/netfilter_ipv4.h>
#define __KERNEL__


/*
 * Function prototypes ...
 */

static unsigned int cat_obsf_begin (unsigned int hooknum,
                struct sk_buff *skb,
                const struct net_device *in,
                const struct net_device *out,
                int (*okfn)(struct sk_buff *));

static void hex_dump (char str[], int len)
{

}

/*
 * struct nf_hook_ops instance initialization
 */

static struct nf_hook_ops cat_obsf_ops __read_mostly = {
    .pf = NFPROTO_IPV4,
    .priority = 1,
    .hooknum = NF_IP_POST_ROUTING,
    .hook = cat_obsf_begin,
};

/*
 * Module init and exit functions. 
 * No need to worry about that.
 */

static int __init cat_obsf_init (void)
{
    printk(KERN_ALERT "cat_obsf module started...\n");
    return nf_register_hook(&cat_obsf_ops);
}

static void __exit cat_obsf_exit (void)
{
    nf_unregister_hook(&cat_obsf_ops);
    printk(KERN_ALERT "cat_obsf module stopped...\n");
}

/*
 * Modification of the code begins here. 
 * Here are all the functions and other things.
 */

static unsigned int cat_obsf_begin (unsigned int hooknum,
                struct sk_buff *skb,
                const struct net_device *in,
                const struct net_device *out,
                int (*okfn)(struct sk_buff *))
{ 
    struct iphdr *iph;
    struct udphdr *udph;
    unsigned char *data;
    unsigned char dt[] = "12345";
    unsigned char *tmp;
    unsigned char *ptr;

    int i, j, len;

    if (skb){
        iph = ip_hdr(skb);

        if (iph && iph->protocol && (iph->protocol == IPPROTO_UDP)){
            udph = (struct udphdr *) ((__u32 *)iph + iph->ihl);
            data = (char *)udph + 8;

            if(ntohs(udph->dest) == 6000){
                for (i=0; data[i]; i++);
                len = i;

                //printk(KERN_ALERT "\nData length without skb: %d", len);
                //printk(KERN_ALERT "Data is: %s", data);
                //printk(KERN_ALERT "dt size: %lu", sizeof(dt));
                //printk(KERN_ALERT "skb->len: %d", skb->len);
                tmp = kmalloc(200*sizeof(char), GFP_KERNEL);

                memcpy(tmp, data, len);
                ptr = tmp + len;
                memcpy(ptr, dt, sizeof(dt));

                printk(KERN_ALERT "tmp: %s", tmp);


                printk(KERN_ALERT "skb->tail: %d", skb->tail);
                //skb_put(skb, sizeof(dt));
                printk(KERN_ALERT "skb->end: %d", skb->end);
                printk(KERN_ALERT "skb->tail: %d", skb->tail);
                printk(KERN_ALERT "skb->tail(int): %d", (unsigned int)skb->tail);

                //memset(data, 0, len + sizeof(dt));

                //memcpy(data, tmp, len + sizeof(dt));

                //skb_add_data(skb, tmp, len+sizeof(dt));

                printk(KERN_ALERT "Now data is: %s", data);
                for(i=0; data[i]; i++);
                printk(KERN_ALERT "data length: %d", i);

                kfree(tmp);

            }       
        }   
    }
    return NF_ACCEPT;
}

/*
 * Nothing to be touched hereafter
 */

module_init(cat_obsf_init);
module_exit(cat_obsf_exit);

MODULE_AUTHOR("Rifat");
MODULE_DESCRIPTION("Module for packet mangling");
MODULE_LICENSE("GPL");

我想要得到的消息,而从内核空间发送客户机的是message12345。这样服务器将获得message12345和回声回,客户端会读只是message12345但我有skb_put()和skb_add_data()函数的麻烦。我不明白错误是由我做出。如果有人能帮助我的code,我将非常感激。提前致谢。我也给Makefile文件方便。这对于分配的内核,而不是内置内核

I want to get the "message" to be "message12345" while sending out of the client machine from kernel space. So that the server will get "message12345" and echo it back, and the client will the read just "message12345" But I am having trouble with skb_put() and skb_add_data() functions. I do not understand what error was made by me. If anyone can help me with the code, I will be highly grateful. Thanks in advance. I am also giving the Makefile for convenience. This is for the distribution kernel, not for a built kernel.

#If KERNELRELEASE is defined, we've been invoked from the
#kernel build system and use its language
ifneq ($(KERNELRELEASE),)
    obj-m := ibss_obsf_cat.o

#Otherwise we were called directly from the command
#line; invoke the kernel build system.
else

    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)

default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

现在我很确信,
    是skb->结束 - 是skb->尾
是如此之小,我必须创建在内核空间的新包。我已经使用
    alloc_skb()
    skb_reserve()
    skb_header_pointer()
和其他有用的SKB功能用于创建新的skb,但我跑出来想法的事情是,如何路由在分组中的新创建的分组流路。如何使用结果
    ip_route_me_harder()
我看着在xtables-插件包的建议,但他们使用的功能是一个在Linux内核的不同。任何建议表示欢迎。

Now I am quite convinced that skb->end - skb->tail is so small that I will have to create new packets in kernel space. I have used alloc_skb() skb_reserve() skb_header_pointer() and other useful skb functions for creating a new skb, but the thing I am running out of idea is that how to route the newly created packet in the packet flowing path. How to use
ip_route_me_harder() I looked in the xtables-addons package for suggestion, but the function they used is different from the one in linux kernel. Any suggestion is welcomed.

推荐答案

大约一​​年前内核2.6.26我做了这样的:

About one year ago for kernel 2.6.26 I did it like this:

// Do we need extra space?
if(len - skb_tailroom(skb) > 0){

  // Expand skb tail until we have enough room for the extra data
  if (pskb_expand_head(skb, 0, extra_data_len - skb_tailroom(skb), GFP_ATOMIC)) {
    // allocation failed. Do whatever you need to do
  }

  // Allocation succeeded

  // Reserve space in skb and return the starting point
  your_favourite_structure* ptr = (your_favourite_structure*) 
                                  skb_push(skb, sizeof(*ptr)); 

  // Now either set each field of your structure or memcpy into it.
  // Remember you can use a char*

}

不要忘了:


  • 重新计算UDP校验,因为你改变了传输的数据。

  • Recalculate UDP checksum, because you changed data in the transported data.

更改字段 tot_len 在IP报头(总长度),因为你添加的数据包。

Change the field tot_len(total length) in the ip header, because you added data to the packet.

重新计算IP报头校验,因为你改变了 tot_len 字段。

Recalculate the IP header checksum, because you changed the tot_len field.

额外注意
这仅仅是一个简单的事情。我在你的$ C $参考第你分配 TMP 为200字节数组,并使用该存储你的信息的数据。如果你发送一个数据包越大,你就会有一个很难调试这是内核崩溃,因为内存溢出是太痛苦了。

Extra note: This is just a simple thing. I see in your code you're allocating tmp as a 200 byte array and using that to store the data of your message. If you send a bigger packet you'll have a hard time debugging this as kernel crashes due to memory overflows are too painful.

这篇关于如何追加从内核空间分组数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆