2014-11-16 112 views
0

我們正在編寫一個內核模塊來爲數據包添加一些額外的數據。我們在skbuff的數據部分的源處添加120個字節的數據,我們試圖從目的地的skbuff中提取數據。如何使用netfilter內核模塊從sk_buff讀取數據?

以下是我們在兩臺機器上運行的內核模塊代碼。

#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的顯示數據包外出源機器的「以太網幀校驗和序列不正確」的錯誤。在目標機器上沒有看到數據包。我不確定數據包是否不離開源機器,或者目標是否無法讀取數據包。 過了一段時間,源和目標都崩潰了。 (我們認爲這是由於incoming_hook_func()代碼的一些bug)

  2. 如果只outgoing_hook_func註冊的源機器並沒有什麼對目標的不同,同樣的「以太網幀校驗序列不正確」被認爲是來源跟蹤,此數據包被視爲在目標上收到,但目標不回覆該數據包。 在這種情況下沒有看到系統崩潰。

如果有人可以用給定的信息回答以下問題,我們將不勝感激。

  1. 以太網幀校驗序列究竟在哪裏計算?它在內核中完成還是由wireshark完成?我們應該如何解決wireshark中顯示的錯誤。我們是否應該在添加數據後重新計算任何校驗和?

  2. 我們的outgoing_hook_func不會使系統崩潰,所以我們假設我們在那個例程中的指針操作很好。但是incoming_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字節正確方式。這可能會解釋你的崩潰原因。

相關問題