Chinaunix首页 | 论坛 | 博客
  • 博客访问: 967403
  • 博文数量: 442
  • 博客积分: 1146
  • 博客等级: 少尉
  • 技术积分: 1604
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-04 12:52
个人简介

123

文章分类

全部博文(442)

文章存档

2017年(3)

2016年(15)

2015年(132)

2014年(52)

2013年(101)

2012年(110)

2011年(29)

分类: LINUX

2014-05-28 13:46:01

作者:gfree.wind@gmail.com
博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net
 
 
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
======================================================================================================

向netfilter添加新的hook有两个函数,nf_register_hook和nf_register_hooks。其中后者是通过调用前者实现的。
下面看nf_register_hook
  1. int nf_register_hook(struct nf_hook_ops *reg)
  2. {
  3.     struct nf_hook_ops *elem;
  4.     int err;

  5.     err = mutex_lock_interruptible(&nf_hook_mutex);
  6.     if (err < 0)
  7.         return err;
  8.     list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
  9.         if (reg->priority < elem->priority)
  10.             break;
  11.     }
  12.     list_add_rcu(&reg->list, elem->list.prev);
  13.     mutex_unlock(&nf_hook_mutex);
  14.     return 0;
  15. }

  16. int nf_register_hook(struct nf_hook_ops *reg)
  17. {
  18.     struct nf_hook_ops *elem;
  19.     int err;

  20.     err = mutex_lock_interruptible(&nf_hook_mutex);
  21.     if (err < 0)
  22.         return err;
     
     /*
     通过reg->pf即协议,和reg->hooknum即挂载点,来确定二维数组nf_hooks的节点。 
     每个节点为某一协议的某一挂载点的netfiler匹配规则的链表。
     */
  1.     list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
  2.         /* 匹配规则按优先级排序,数值越小,优先级越高 */
  3.         if (reg->priority < elem->priority)
  4.             break;
  5.     }
  6.     /* 将新的规则hook加入到list中 */
  7.     list_add_rcu(&reg->list, elem->list.prev);
  8.     mutex_unlock(&nf_hook_mutex);
  9.     return 0;
  10. }
这个注册函数很简单,找个例子看看,文件net/ipv4/netfilter/nf_defrag_ipv4.c中:
  1. /* 定义两个hook结构实例 */
  2. static struct nf_hook_ops ipv4_defrag_ops[] = {
  3.     {
  4.         .hook        = ipv4_conntrack_defrag,
  5.         .owner        = THIS_MODULE,
  6.         .pf        = PF_INET,
  7.         .hooknum    = NF_INET_PRE_ROUTING,
  8.         .priority    = NF_IP_PRI_CONNTRACK_DEFRAG,
  9.     },
  10.     {
  11.         .hook = ipv4_conntrack_defrag,
  12.         .owner = THIS_MODULE,
  13.         .pf = PF_INET,
  14.         .hooknum = NF_INET_LOCAL_OUT,
  15.         .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
  16.     },
  17. };

  18. static int __init nf_defrag_init(void)
  19. {
  20.     /* 通过该函数,加入两个新的hook,在PF_INET下的pre_routing和local out两个挂载点 */
  21.     return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
  22. }
下面看一下ipv4_defrag_ops作为一个hook函数的例子。
  1. static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
  2.                      struct sk_buff *skb,
  3.                      const struct net_device *in,
  4.                      const struct net_device *out,
  5.                      int (*okfn)(struct sk_buff *))
  6. {
  7.     struct sock *sk = skb->sk;
  8.     struct inet_sock *inet = inet_sk(skb->sk);

  9.     /* 对应的socket为PF_INET,且指定该socket为nodefrag,则hook返回NF_ACCEPT */
  10.     if (sk && (sk->sk_family == PF_INET) &&
  11.      inet->nodefrag)
  12.         return NF_ACCEPT;

  13. #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  14. #if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
  15.     /* Previously seen (loopback)? Ignore. Do this before
  16.      fragment check. */
  17.     if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
  18.         return NF_ACCEPT;
  19. #endif
  20. #endif
  21.     /* Gather fragments. */
  22.     /* 
  23.     当IP报文中的标志中的IP_MF或者IP_OFFSET被置位,则表示该IP报文为分片。
  24.     第一个分片,IP_MF为1,IP_OFFSET为0;
  25.     中间的分片,IP_MF和IP_OFFSET均不为0;
  26.     最后一个分片,IP_MF为0,IP_OFFSET不为0;
  27.     */
  28.     if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
  29.         enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
  30.         if (nf_ct_ipv4_gather_frags(skb, user))
  31.             return NF_STOLEN; //哦~~,这里出现了NF_STOLEN,不过今天没时间了
  32.     }
  33.     return NF_ACCEPT;
  34. }
今天看到的netfilter的代码都比较简单——其实netfilter的代码都比较简单。争取再有一两篇博文,基本上netfilter就可以结束了。
阅读(913) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~