2014-11-16 2 views
0

Мы пишем модуль ядра для добавления дополнительных данных в пакеты данных. Мы добавляем 120 байт данных в источнике в разделе данных skbuff, и мы пытаемся извлечь эти данные из skbuff в пункт назначения.Как читать данные из sk_buff с помощью модуля ядра netfilter?

Ниже приведен код ядра, который мы запускаем на обеих машинах.

#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/netfilter.h> 
#include <linux/netfilter_ipv4.h> 
#include <linux/slab.h> 
#include <linux/inet.h> 
#include <linux/time.h> 
#include <linux/ktime.h> 

static struct nf_hook_ops nf_out; 
static struct nf_hook_ops nf_in; 

struct my_struct { 
// 24 byte struct 
}; 

unsigned int outgoing_hook_func(unsigned int hooknum, struct sk_buff *skb, const struct    net_device *in, const struct net_device *out, int(*okfn)(struct sk_buff *)) 
{ 
int i = 0; 
struct my_struct *ptr; 
unsigned char *new_data; 
int size = 5 * sizeof(struct my_struct); 
ptr = kmalloc(size, GFP_ATOMIC); 
for(i = 0; i < 5; i++) { 
    //Assign some values to the array of mystruct 
    } 
}  
printk("output_Before: %d\n",skb->len); 

new_data = skb_tail_pointer(skb); 
SKB_LINEAR_ASSERT(skb); 
// Add this additional data only if there is enough room in the data section of the skbuff 
if (skb->tail + size < skb->end) { 
    skb->tail += size; 
     skb->len += size; 
     memcpy(new_data, ptr, size); 
} 

kfree(ptr); 
printk("output_After: %d\n",skb->len); 
return NF_ACCEPT; 
} 

unsigned int incoming_hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int(*okfn)(struct sk_buff *)) 
{ 
int i = 0; 
struct loc_time_tag *ptr; 
int size = 5 * sizeof(struct my_struct); 
printk("input_Before: %d\n",skb->len); 

// Collect data only from packets that have my_struct appended to them 

if (skb->tail + size < skb->end) { 
    unsigned int tail_ptr = skb_tail_pointer(skb); 
    ptr = (struct my_struct *)(tail_ptr - 5 * sizeof(struct my_struct)); 
    printk("tail = %d; end = %d; ptr = %d", skb->tail,skb->end, ptr); 

    for(i = 0; i < 5; i++) { 
    // Print out the values of ptr 
    } 

} 

printk("input_after: %d\n",skb->len); 
return NF_ACCEPT; 
} 

//Called when module loaded using 'insmod' 
int init_module() 
{ 
    nf_out.hook = outgoing_hook_func;    
    nf_out.hooknum = NF_INET_LOCAL_OUT;   
    nf_out.pf = PF_INET; 
    nf_out.priority = NF_IP_PRI_FIRST; 
    nf_register_hook(&nf_out); 

    nf_in.hook = incoming_hook_func; 
    nf_in.hooknum = NF_INET_LOCAL_IN; 
    nf_in.pf = PF_INET; 
    nf_in.priority = NF_IP_PRI_FIRST; 
    nf_register_hook(&nf_in); 
    return 0;    
} 

//Called when module unloaded using 'rmmod' 
void cleanup_module() 
{ 
    nf_unregister_hook(&nf_out);      //cleanup – unregister hook 
    nf_unregister_hook(&nf_in); 
} 

Но когда мы выполняем простую операцию, как SSH между источником и пунктом назначения и exmine в Wireshark след на обеих машинах, следующие наши наблюдения.

  1. Если оба incoming_hook_func и outgoing_hook_func зарегистрированы и работают на обоих источника и назначения машины, Wireshark показывает «ETHERNET КАДР CHECKSUM ПОСЛЕДОВАТЕЛЬНОСТИ НЕПРАВИЛЬНО» ошибка для пакетов, выходящих из исходной машины. На машине назначения не отображается пакет. Я не уверен, что пакет не покидал исходный компьютер или если адресату не удалось прочитать пакет. Через некоторое время как сбой источника, так и назначения. (Мы предполагаем, что это связано с какой-то ошибки в incoming_hook_func коде())

  2. Если только outgoing_hook_func зарегистрирован на исходной машине и ничего на место назначения, то же самое «ETHERNET КАДР CHECKSUM ПОСЛЕДОВАТЕЛЬНОСТЬ НЕПРАВИЛЬНО» виден на источнике трассировка, этот пакет рассматривается как полученный в пункте назначения, но получатель не отвечает на этот пакет. В этом случае сбоев системы не наблюдается.

Мы будем очень признательны, если кто-то может ответить на следующие вопросы с данной информацией.

  1. Где именно рассчитана последовательность проверок Ethernet Frame Check Sequence? Это делается в ядре или выполняется с помощью wirehark? Что мы должны сделать, чтобы преодолеть ошибку, показанную в wirehark. Должны ли мы пересчитать любую контрольную сумму после добавления наших данных?

  2. Наш outgoing_hook_func не разбивает систему, поэтому мы предполагаем, что наши манипуляции с указателями в этой программе прекрасны. Но входящий_hook_func приводит к сбоям системы. Может кто-нибудь, пожалуйста, сообщите нам, где мы ошибаемся?

  3. В случае 2 выше, почему пункт назначения не отвечает? Это из-за неудачной последовательности проверки кадров или есть какой-либо другой недостаток в нашем понимании вещей.

  4. Кроме того, тесты ping, как представляется, отлично работают в обоих случаях. Мы не можем понять, почему это так.

Заранее спасибо

ответ

2
unsigned int tail_ptr = skb_tail_pointer(skb); 
ptr = (struct my_struct *)(tail_ptr - 5 * sizeof(struct my_struct)); 

Заменить приведенный выше код с нижеследующим.

unsigned char* tail_ptr = skb_tail_pointer(skb); 
ptr = (struct my_struct *)(tail_ptr - 5 * sizeof(struct my_struct)); 

Это был бы правильный путь для возврата 5 * 24 байта от указателя хвоста. Это может объяснить причину ваших сбоев.

Смежные вопросы