Estoy tratando de agregar algunos datos en un paquete desde el espacio del kernel. Tengo un cliente de eco y servidor. Escribo en la línea de comandos como: ./client "mensaje" y el servidor simplemente lo repite. El servidor se ejecutó con ./server.¿Cómo agregar datos en un paquete desde el espacio del kernel?
Ahora, el cliente y el servidor están en dos máquinas diferentes (pueden ser máquinas virtuales). Estoy escribiendo un módulo kernel que se ejecuta en la máquina cliente. Su trabajo es agregar "12345" después de "mensaje" mientras el paquete sale de la máquina. Estoy presentando el código a continuación.
/*
* 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");
quiero conseguir el "mensaje" a ser "message12345" al enviar fuera de la máquina cliente desde el espacio del núcleo. Para que el servidor reciba "message12345" y lo repita, y el cliente leerá simplemente "message12345". Pero estoy teniendo problemas con las funciones skb_put() y skb_add_data(). No entiendo qué error cometí yo. Si alguien puede ayudarme con el código, estaré muy agradecido. Gracias por adelantado. También estoy dando el Makefile por conveniencia. Esto es para el kernel de distribución, no para un kernel creado.
#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
Ahora estoy bastante convencido de que skb-> final - skb-> cola es tan pequeña que voy a tener que crear nuevos paquetes en el espacio del núcleo. He usado alloc_skb() skb_header_pointer() skb_header_pointer() y otras funciones skb útiles para crear una nueva skb, pero lo que me está quedando sin idea es cómo enrutar el paquete recién creado en la ruta de flujo de paquetes . Cómo usar
ip_route_me_harder() Busqué en el paquete xtables-addons la sugerencia, pero la función que utilizaron es diferente de la del kernel de linux. Cualquier sugerencia es bienvenida. Hace
Gracias por su ayuda. Sí, los campos de longitud me preocuparon mucho. –
Y también la suma de verificación en el espacio del kernel fue bastante vaga para mí al principio. –
@Fred, ¿puedes comentar esto también? Http://stackoverflow.com/questions/12529497/how-to-append-data-on-a-packet-from-kernel-space – user2087340