2010-07-14 32 views
3

長話短說,我正在嘗試構建一個非常簡單的骨骼UDP SKB,以便將某些東西放到網絡上。該場景如下:構建出口設備的sk_buff linux內核

我有一個內核模塊加載(除其他外)覆蓋/net/ipv4/udp.c中的標準udp_sendmsg函數的內存位置。從這裏我想構建一個skb到我可以簡單地把它放到電線上的地方。通常情況下,udp_sendmsg只是簡單地做一些UDP簿記工作,綁定一個UDP頭並將其發送到IP層進行路由,L3/L2頭等。基本上,我將一些功能引入sendmsg函數。在這個時候,我只是分配一個SKB:

skb = alloc_skb(1500, GFP_KERNEL); 
    //skb has 1500 bytes of tail room only 
    skb_reserve(skb, 500); 
    //now has head and tail but no data space 
    data = skb_put(skb, 500); 
    //now we have an skb with 500 head, 500 data sec, 500 tail 

然後(某些路由表seteup後)我想添加一個udp_hdr:

struct udphdr *uh; 
    skb->transport_header = skb_push(skb, sizeof(struct udphdr)); 
    uh = udp_hdr(skb); 
    uh->source = 5555; 
    uh->dest = dport; 
    uh->len = 18; 
    uh->check = 0; 

和ip_hdr(僅基本填滿):

struct iphdr *iph; 
    skb->network_header = skb_push(skb, sizeof(struct iphdr)); 
    iph = ip_hdr(skb); 
    iph->version = 4; 
    iph->ihl = 5; 
    iph->tos = inet->tos; 
    iph->tot_len = htons(skb->len); 
    iph->protocol = IPPROTO_UDP; 
    iph->saddr = saddr; 
    iph->daddr = daddr; 
    skb->dst = dst_clone(&rt->u.dst); 

注:我得到了大部分的這些東西從this page但在網絡和傳輸頭是工會,他們使用的是老的內核(預2.6.24),並呼籲NH和H各自LY。新的方式涉及到使用skb-> transport_header/skb-> network_header並使用這些輔助函數,但顯然我做錯了什麼,因爲當我嘗試調用udp_sendmsg時,得到一個內核oops注意:這個運行沒有oops和傾倒垃圾到電線的代替時:

skb->transport_header = skb_push(skb, sizeof(struct udphdr)); 

我使用:

skb_reset_transport_header(skb); 

(和等效對於network_header但閱讀以上鍊接和查看源用於在linux復位功能之後/sk_buff.h,它沒有看到我喜歡它正在做我想做的事。

請注意,上面的(在此上下文中)未定義變量的任何賦值語句僅僅是因爲我沒有包含整個函數。

我意識到這個問題可能屬於一個非常具體的領域,但任何關於正確使用新的skb結構的指導將會非常有幫助。我的朋友谷歌會變得非常乾燥。

的哎呀呼叫追蹤:

[<ffffffff813dbf98>] oops_end+0xb9/0xc1 
[<ffffffff81030e21>] no_context+0x1f6/0x205 
[<ffffffff81030fd3>] __bad_area_nosemaphore+0x1a3/0x1c9 
[<ffffffff8101184e>] ? apic_timer_interrupt+0xe/0x20 
[<ffffffff8103100c>] bad_area_nosemaphore+0x13/0x15 
[<ffffffff813dd30a>] do_page_fault+0x125/0x222 
[<ffffffff813db485>] page_fault+0x25/0x30 
[<ffffffffa010924f>] ? udp_sendmsg_offload+0x1e3/0x250 [testmodule] 
[<ffffffffa010922e>] ? udp_sendmsg_offload+0x1c2/0x250 [testmodule] 
[<ffffffff81390a00>] inet_sendmsg+0x54/0x5d 
[<ffffffff8132f142>] __sock_sendmsg+0x61/0x6c 
[<ffffffff8132f8b9>] sock_sendmsg+0xcc/0xe5 
+0

請向我們展示哎呀。 – ninjalj 2010-07-14 18:34:48

+0

編輯後,以反映oops – 2010-07-14 21:08:31

回答

1

skb_push()返回指針來傳輸頭,但skb->transport_headersk_buff_data_t,這應該是一個偏移 - 怎麼看skb_transport_header()作品。您還需要將標題信息轉換爲網絡字節順序。

你設置UDP報頭應該是部分:

struct udphdr *uh; 
skb_push(skb, sizeof(struct udphdr)); 
skb_reset_transport_header(skb); 
uh = udp_hdr(skb); 
uh->source = __constant_htons(5555); 
/* ... */ 

同樣地,對於IP報頭:

struct iphdr *iph; 
skb_push(skb, sizeof(struct iphdr)); 
skb_reset_network_header(skb); 
iph = ip_hdr(skb); 
iph->version = 4; 
/* ... */ 
+0

是的,我同意。我昨天在看skbuff時發現,skb-> transport_header的使用取決於NET_SKBUFF_DATA_USES_OFFSET,而這依賴於__WORDSIZE。由於我在64位平臺上,似乎預處理器確實在使用這種方法。也感謝你指出字節順序,在黑客入侵後,我完全忘記了 – 2010-07-15 13:35:33

+0

PS這會繞過內核oops(至少在它發生之前),但我仍然沒有運氣與我的目標。我想這是爲了另一個帖子。 – 2010-07-15 13:36:45

相關問題