我們正在編寫一個內核模塊來爲數據包添加一些額外的數據。我們在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的跟蹤,以下是我們的觀察。
如果同時incoming_hook_func和outgoing_hook_func註冊和源和目標機器上運行,Wireshark的顯示數據包外出源機器的「以太網幀校驗和序列不正確」的錯誤。在目標機器上沒有看到數據包。我不確定數據包是否不離開源機器,或者目標是否無法讀取數據包。 過了一段時間,源和目標都崩潰了。 (我們認爲這是由於incoming_hook_func()代碼的一些bug)
如果只outgoing_hook_func註冊的源機器並沒有什麼對目標的不同,同樣的「以太網幀校驗序列不正確」被認爲是來源跟蹤,此數據包被視爲在目標上收到,但目標不回覆該數據包。 在這種情況下沒有看到系統崩潰。
如果有人可以用給定的信息回答以下問題,我們將不勝感激。
以太網幀校驗序列究竟在哪裏計算?它在內核中完成還是由wireshark完成?我們應該如何解決wireshark中顯示的錯誤。我們是否應該在添加數據後重新計算任何校驗和?
我們的outgoing_hook_func不會使系統崩潰,所以我們假設我們在那個例程中的指針操作很好。但是incoming_hook_func導致系統崩潰。有人可以讓我們知道我們要去哪裏嗎?
在上面的情況2中,爲什麼目的地沒有響應?是否由於錯誤的幀檢查順序或者我們對事物的理解存在其他缺陷。
此外,在上述兩種情況下,ping測試似乎都工作得很好。我們無法理解爲什麼這樣做。
預先感謝