首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自定义ebtables模块&& skb操作&&内核死机

自定义ebtables模块&& skb操作&&内核死机
EN

Stack Overflow用户
提问于 2014-02-27 04:54:31
回答 1查看 607关注 0票数 0

不久前,我基于Ashwin Kashyap (http://www.research.rutgers.edu/~ashwink/misc_projs/ebt_vnat.html)的vnat模块实现了ebtables模块。模块可以在broute表中的BROUTING链中使用,用于剥离vlan标签,并将vlan id放入nf标记。模块还允许根据nat表的POSTROUTING链中的nf标记值添加vlan标签。模块在处理桥接流量时没有任何问题。系统非常稳定。当我将tproxy拦截添加到混合中时,问题就开始了。这会导致内核在运行一段时间后出现恐慌。我强调的事实是,我没有看到内核在tproxied流量流几分钟后的第一个数据包之后出现恐慌。我处理SKB的方式似乎不够干净,无法处理L3+。顺便说一句,我正在开发2.6.32内核。请使用下面的注释查找模块的关键部分:

代码语言:javascript
复制
// 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;

我将非常感谢任何指针(只要它们至少64位长)。谢谢!

EN

回答 1

Stack Overflow用户

发布于 2014-09-30 18:38:27

您的代码应更改MAC报头以添加或删除802.1q报头。现在我可能错了,但是为什么需要将指针转移到网络和传输层标头?

我预计MAC报头将扩展和收缩到skb净空中,而数据包的其余部分在这两种情况下都保持不变。移动网络和传输报头会导致上层(3+)读取错误的前4个字节。

(注:我会写这篇文章作为评论而不是答案,因为我不确定我是对的,但我最近一直在为ebtables开发一个VLAN标签转换模块,这是我第一次为此做出贡献,所以我的声誉显然还不够高)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22053028

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档