【Linux 驅動】Netfilter/Iptables (七) 核心協議棧skb封裝分析(續六)

來源:互聯網
上載者:User

上文介紹了netfilter機制下,如何重造並發送一個skb,涉及到核心協議棧編程,而不是我們平時所說的使用者層socket網路編程。

我們先來介紹下上面skb重構程式涉及到的幾個函數:
首先,有必要說下,也是後面每段程式中都有說道的,就是開發源碼樹版本是3.13的,這個版本的skb_buff和我們常見的2.4、2.6有很大的不同。

一、主要看一下四個欄位:

//typedef unsigned int sk_buff_data_t;    sk_buff_data_t      tail;    sk_buff_data_t      end;    unsigned char       *head,                *data;

其表示含義如下圖所示《深入理解linux網路技術內幕》

head和end指向緩衝區的頭部和尾部,而data和tail指向實際資料的頭部和尾部,每一層會在head和data之間填充協議頭,或者在tail和end之間添加新的協議資料。

所以根據上面的分析,head和data之間是協議頭和承載,比如傳輸層、網路層、乙太網路幀頭。

重點:sk_buff 中的資料部分包含協議層頭部和承載。

下面就是sk_buff中各個頭部的長度欄位:

//局部    __u16           transport_header;    __u16           network_header;    __u16           mac_header;//sk_buff取消了在該資料結構內放置聯合體union欄位,//所以編程的時候不能直接調用sk_buff中的聯合體成員定位到對應的傳輸層頭部、網路層頭部等。//但是卻提供給我們更為便捷的方式://舉網路層為例static inline struct iphdr *ip_hdr(const struct sk_buff *skb){    return (struct iphdr *)skb_network_header(skb);}static inline unsigned char *skb_network_header(const struct sk_buff *skb){    return skb->head + skb->network_header;}//和我們在linux網路協議棧分析的如出一轍,就是通過先定位整個換緩衝區的頭端,//再根據協議層的位移量定位該協議層,至於協議頭的順序..都知道

二、alloc_skb 和 skb_reserve

還有,對於alloc_skb(),我們只需要指定其資料部分的大小即可(應用程式層資料+協議層頭部),該函數內部會額外把skb_buff所佔的那部分空間也給分配出來,這無需我們操心。

skb_reserve(),是一個定位函數,就是前面alloc一個skb之後,用這個函數調整下data和tail資料指標

static inline void skb_reserve(struct sk_buff *skb, int len){    skb->data += len;    skb->tail += len;}//len取多大,取決於你後面怎麼填充資料了

skb_reserve() 這個函數就是在緩衝區中預留skb協議頭部以及有效資料部分的空間,空間可大可小。

經過前面的alloc_skb和skb_reserve,現在那兩個指標(data和tail)發生了變化:
alloc_skb():

//tail以及tail之前的欄位初始化為0    memset(skb, 0, offsetof(struct sk_buff, tail));    /* Account for allocated memory : skb + skb->head */...    skb->head = data;    skb->data = data;...    skb->end = skb->tail + size;//head和data均指向分配的skb資料部分(協議頭+承載)的首地址位置,//end則指向尾端位置,tail值就是0

skb_reserve(skb, len)之後,data和tail的指標發生了變化,換句話說在head與data之間預留了len大小的空間用於填充協議頭和承載。

上面預留了整體空間,下面我們還要細分空間,上面的整體空間包括了各個協議層頭部和承載部分,我們還得按照各層協議頭部的防止順序合理劃分空間:

三、skb_push 和 skb_put

怎麼分,我們前面用的是 skb_push()

unsigned char *skb_push(struct sk_buff *skb, unsigned int len){    skb->data -= len;    skb->len  += len;    if (unlikely(skb->data<skb->head))        skb_under_panic(skb, len, __builtin_return_address(0));    return skb->data;}//看到起實現,我們就知道,調用這個函數來細分空間,必須嚴格按照資料幀的格式來劃分//乙太網路幀頭 | 網路層首部 | 傳輸層首部 | 應用程式層資料//所以先得細分應用程式層資料,最後是乙太網路幀頭//eg, pdata = skb_push(skb, pkt_len); udph = (struct udphdr*)skb_push(skb, sizeof(struct udphdr)); iph = (struct iphdr*)skb_push(skb, sizeof(struct iphdr)); ethdr = (struct ethhdr*)skb_push(skb, sizeof(struct ethhdr));

如果前面你看懂了,知道sk_buff 的資料空間布局的話,這個函數一看便知。額,sk_buff 中有好幾個len,分別表徵承載長度,各個協議頭部長度,以及整個長度。

再來看看 skb_put()

unsigned char *skb_put(struct sk_buff *skb, unsigned int len){    unsigned char *tmp = skb_tail_pointer(skb);    SKB_LINEAR_ASSERT(skb);    skb->tail += len;    skb->len  += len;    if (unlikely(skb->tail > skb->end))        skb_over_panic(skb, len, __builtin_return_address(0));    return tmp;}//看代碼,這裡改動的是tail(資料的尾部指標),所以這裡就是在資料區的尾部追加資料,//和skb_push()恰恰是反過來的

所以調用skb_put() 的話,前面的skb_reserve()就只需要預留乙太網路幀頭的空間,後面則調用skb_put(),依次往後追加細分網路層頭部、協議層頭部和承載部分了。

兩個函數都是用於細分空間,返回細分空間後的首部地址指標,便於後續的協議頭部以及承載資料填充。

空間細分之後就是單純的協議層欄位填充和承載填充了。

可以看出來建立skb幾個重要的函數介面就是:
alloc_skb、skb_reserver、skb_push、skb_put
後面三個函數其實都是簡單的修改指標操作。

上篇及本篇介紹的都是自己建立一個skb,實際上我們還可以拷貝(skb_copy())接收到的skb,然後針對性的修改發送出去。或者直接修改接收到的skb。由於接收到的skb,空間已經細分好,我們則不需要以上後面三個函數,直接調用以下幾個函數定位到各個協議層頭部:

static inline struct ethhdr *eth_hdr(const struct sk_buff *skb);static inline struct iphdr *ip_hdr(const struct sk_buff *skb);static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb);static inline struct udphdr *udp_hdr(const struct sk_buff *skb);...

然後針對性的修改即可,其餘原理是差不多的,這裡就不額外介紹了。

參考資料:
《深入理解Linux網路技術內幕》
http://www.2cto.com/os/201502/376226.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.