免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2873 | 回复: 2
打印 上一主题 下一主题

请教各位一个关于sk_buff成员变量问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-18 15:33 |只看该作者 |倒序浏览
各位好,请教大家一个关于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的值?
  请各位达人不吝赐教,谢谢。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2011-01-18 19:50 |只看该作者
贴一下你的完整代码吧。通常情况下,NF 中用 skb->data 取出 iphdr 是没问题的,虽然内核中已经提供了 API 取出 iphdr。

论坛徽章:
0
3 [报告]
发表于 2011-01-19 14:00 |只看该作者
谢谢楼上的关注,这个问题我已经解决了,在2.6.22以前的内核版本中这样取得skb->nh.iph里面的值没有问题。
问题是2.6.18内核版本的netfilter的注册函数与新版本(比方说2.6.31)的不一样:

2.6.18的netfilter注册函数原型为:
unsigned int main_hook(unsigned int hooknum,
                  struct sk_buff **skb,
                  const struct net_device *in,
                  const struct net_device *out,
                  int (*okfn)(struct sk_buff*));

2.6.31的netfilter注册函数原型为:
unsigned int main_hook(unsigned int hooknum,
                  struct sk_buff  *skb,
                  const struct net_device *in,
                  const struct net_device *out,
                  int (*okfn)(struct sk_buff*));

区别在于第二个参数,一个是指针的指针,一个是指针。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP