2014-02-26 124 views
0

前段時間我實現了基於vinat模塊的Ashbash Kashyap(http://www.research.rutgers.edu/~ashwink/misc_projs/ebt_vnat.html)的ebtables模塊。模塊可用於佈線表中的BROUTING鏈,用於剝離vlan標籤並將vlan id置於nf標記中。模塊還允許在nat表的POSTROUTING鏈中添加基於nf標記值的vlan標記。模塊在處理橋接通信時沒有任何問題。系統堅如磐石。一旦將tproxy截取添加到混音中,問題就會開始。這會在操作一段時間後導致內核恐慌。我強調這一事實,即在幾分鐘的流量流之後的第一個數據包之後,我看不到內核崩潰。看起來,我修理SKB的方式對L3 +處理來說不夠乾淨。順便說一句我正在研究2.6.32內核。 (只要他們有至少64位長)定製ebtables模塊&& skb操作&& kernel panic

// code for adding vlan tag based on skb->mark value 
if (!skb_make_writable(skb, 0)) 
    return EBT_DROP; 

if(skb->mark > 0){ 
    // maybe we should always seek VLAN_HLEN+ETH_HLEN instead of using condition? 
    if (skb_headroom(skb) < (skb->mac_len == 0 ? VLAN_HLEN + ETH_HLEN : VLAN_HLEN)) { 
    struct sk_buff *sk_tmp = skb; 
    skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); 
    kfree_skb(sk_tmp); 

    if (skb == NULL) { 
     return EBT_DROP; 
    } 
    } 

    // we need 4 more bytes for 802.1q header, so push!...I can almost see the head(er) 
    skb_push(skb, VLAN_HLEN); 

    skb->mac_header-=VLAN_HLEN; 
    skb->network_header-=VLAN_HLEN; 
    skb->transport_header-=VLAN_HLEN; 
    veth = (struct vlan_ethhdr *) eth_hdr(skb); 

    // move dst/src mac addresses (12b of header) 4 bytes back to make room for 
    // 802.1q header 
    memmove(skb->head + skb->mac_header, skb->head + skb->mac_header + VLAN_HLEN, 12); 

    // fill 802.1q header 
    veth->h_vlan_proto = __constant_htons(ETH_P_8021Q); 
    veth_TCI = skb->mark & 0xfff; 
    veth->h_vlan_TCI = htons(veth_TCI);  
} 

// code for stripping vlan tag and putting it into skb->mark value 
veth = (struct vlan_ethhdr *)eth_hdr(skb); 
if(veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)){ 

    if (!skb_make_writable(skb, 0)) 
    return EBT_DROP; 

    // determine vlan id 
    vid=(ntohs(veth->h_vlan_TCI) & 0xfff); 
    mark = vid; 

    // copy dst/src mac addresses (12b) 4 bytes fwd, so it covers 802.1q header 
    memmove(skb->head + skb->mac_header + VLAN_HLEN, skb->head + skb->mac_header, 12); 

    // adapt header pointers 
    skb->mac_header+=VLAN_HLEN; 
    skb->mac_len = ETH_HLEN; 
    skb->network_header+=VLAN_HLEN; 
    skb->transport_header+=VLAN_HLEN; 
    skb->data += VLAN_HLEN; 
    skb->len -= VLAN_HLEN; 

    eth = eth_hdr(skb); 
    skb->protocol=eth->h_proto; 
} 
skb->mark=mark; 

我會爲任何指針感激:請找到該模塊的關鍵部分與下面的評論。謝謝!

回答

0

你的代碼應該改變MAC頭來添加或刪除一個802.1q頭。現在我可能在這裏錯了,但爲什麼你需要將指針轉移到網絡和傳輸層頭?

我希望MAC頭擴展並收縮到skb餘量空間中,而其餘的數據包在任何情況下都保持不變。移動網絡和傳輸標題導致上層(3+)讀取錯誤的前4個字節。我注意到這是作爲評論而不是答案,因爲我不確定自己是對的,但是最近我一直在爲ebtables開發一個VLAN標記轉換模塊,這是我第一次將它作爲註釋而不是答案。對SO有所貢獻,所以我的聲譽顯然不夠高)。