服务器 频道

深入Linux网络核心堆栈之二

  【IT168 服务器学院】--[3 - 注册和注销Netfilter hook

  注册一个hook函数是围绕nf_hook_ops数据结构的一个非常简单的操作,nf_hook_ops数据结构在linux/netfilter.h中定义,该数据结构的定义如下:

        struct nf_hook_ops {
                struct list_head list;

                /* 此下的值由用户填充 */
                nf_hookfn *hook;
                int pf;
                int hooknum;
                /* Hook以升序的优先级排序 */
                int priority;
        };

  该数据结构中的list成员用于维护Netfilter hook的列表,并且不是用户在注册hook时需要关心的重点。hook成员是一个指向nf_hookfn类型的函数的指针,该函数是这个hook被调用时执行的函数。nf_hookfn同样在linux/netfilter.h中定义。pf这个成员用于指定协议族。有效的协议族在linux/socket.h中列出,但对于IPv4我们希望使用协议族PF_INET。hooknum这个成员用于指定安装的这个函数对应的具体的hook类型,其值为表1中列出的值之一。最后,priority这个成员用于指定在执行的顺序中,这个hook函数应当在被放在什么地方。对于IPv4,可用的值在linux/netfilter_ipv4.h的nf_ip_hook_priorities枚举中定义。出于示范的目的,在后面的模块中我们将使用NF_IP_PRI_FIRST。

  注册一个Netfilter hook需要调用nf_register_hook()函数,以及用到一个nf_hook_ops数据结构。nf_register_hook()函数以一个nf_hook_ops数据结构的地址作为参数并且返回一个整型的值。但是,如果你真正的看了在net/core/netfilter.c中的nf_register_hook()函数的实现代码,你会发现该函数总是返回0。以下提供的是一个示例代码,该示例代码简单的注册了一个丢弃所有到达的数据包的函数。该代码同时展示了Netfilter的返回值如何被解析。

  示例代码1 : Netfilter hook的注册
  /*
  * 安装一个丢弃所有到达的数据包的Netfilter hook函数的示例代码
  */

  #define __KERNEL__
  #define MODULE

  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/netfilter.h>
  #include <linux/netfilter_ipv4.h>

  /* 用于注册我们的函数的数据结构 */
  static struct nf_hook_ops nfho;

  /* 注册的hook函数的实现 */
  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 *))
  {
  return NF_DROP;           /* 丢弃所有的数据包 */
  }

  /* 初始化程序 */
  int init_module()
  {
  /* 填充我们的hook数据结构 */
  nfho.hook = hook_func;         /* 处理函数 */
  nfho.hooknum  = NF_IP_PRE_ROUTING; /* 使用IPv4的第一个hook */
  nfho.pf       = PF_INET;
  nfho.priority = NF_IP_PRI_FIRST;   /* 让我们的函数首先执行 */

  nf_register_hook(&nfho);

  return 0;
  }

  /* 清除程序 */
  void cleanup_module()
  {
  nf_unregister_hook(&nfho);
  }

  这就是全部内容,从示例代码1中,你可以看到,注销一个Netfilter hook是一件很简单事情,只需要调用nf_unregister_hook()函数,并且以你之前用于注册这个hook时用到的相同的数据结构的地址作为参数。

0
相关文章