请教各位一个关于sk_buff成员变量问题

各位好,请教大家一个关于sk_buff的问题:

  编写一个简单的防火墙工具,内核版本是“2.6.18-92.el5”,内核源码中sk_buff的关于各个协议层的头结构体如下:
  struct sk_buff {
  。。。。。。
  。。。。。。
  union {
  struct tcphdr        *th;
  struct udphdr        *uh;
  struct icmphdr        *icmph;
  struct igmphdr        *igmph;
  struct iphdr        *ipiph;
  struct ipv6hdr        *ipv6h;
  unsigned char        *raw;
  } h;

  union {
  struct iphdr        *iph;
  struct ipv6hdr        *ipv6h;
  struct arphdr        *arph;
  unsigned char        *raw;
  } nh;

  union {
  unsigned char *raw;
  } mac;
  。。。。。。
  。。。。。。
  }
   
  然后我在防火墙的hook函数里面进行以下三种方法试图获取数据包的IP地址,

  方法一,直接用IP结构体头类型转换skb->data,执行结果是打印的地址值都是零。
  unsigned int hook_func(unsigned int hooknum,
  struct sk_buff *skb,
  const struct net_device *in,
  const struct net_device *out,
  int (*okfn)(struct sk_buff *))
  {
struct iphdr *network_header = (struct iphdr *)skb->data;
printk("<1>%x ==> %x\n", network_header->saddr, network_header->daddr);       

return NF_ACCEPT;
  }

  方法二,直接取得skb->nh.iph,执行结果是打印的地址值都是零。
  unsigned int hook_func(unsigned int hooknum,
  struct sk_buff *skb,
  const struct net_device *in,
  const struct net_device *out,
  int (*okfn)(struct sk_buff *))
  {
struct iphdr *network_header = (struct iphdr *)skb->nh.iph;
printk("<1>%x ==> %x\n", network_header->saddr, network_header->daddr);       

return NF_ACCEPT;
  }

  方法三,从skb->head开始偏移14个字节(Erthnet头长度),然后类型转换,执行结果是,系统崩溃。
  unsigned int hook_func(unsigned int hooknum,
  struct sk_buff *skb,
  const struct net_device *in,
  const struct net_device *out,
  int (*okfn)(struct sk_buff *))
  {
        struct iphdr *network_header = (struct iphdr *)(skb->head + 14);
printk("<1>%x ==> %x\n", network_header->saddr, network_header->daddr);       

return NF_ACCEPT;
  }

  我在网上google了一下,方法二比较常见,但是我取出来的值总是零,很奇怪。
  顺便说一下,在这个内核版本中没有skb_network_header()这样的函数,新的内核版本中的
  skb_network_header()是通过第三种方法实现的,但是sk_buff结构体变化很大,没有以上三个联合体。

请问,如何才能正确取得skb->nh.iph->saddr和skb->nh.iph->daddr的值?
  请各位达人不吝赐教,谢谢。

作者: nisiyun0127   发布时间: 2011-01-18

贴一下你的完整代码吧。通常情况下,NF 中用 skb->data 取出 iphdr 是没问题的,虽然内核中已经提供了 API 取出 iphdr。

作者: Godbach   发布时间: 2011-01-18