编写netfilter模块 第三部分 Netfilter核心

来源:互联网 发布:淘宝申请退款客服介入 编辑:程序博客网 时间:2024/06/06 04:30

第三部分

Netfilter核心

10 Netfilter钩子函数

网络代码中有若干调用是涉及到Netfilter的,并且所有的东西都和它绑定(也就是模块被加载)到netfilter框架中。最普遍的钩子组成部分是xtables(防火墙)、连接跟踪、IPv4的NAT引擎和IPVS的虚拟服务器。Ip6_input.c里面就调用了这个特定的钩子函数:

return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb,dev, NULL, ip6_rcv_finish);

这里调用了所有的prerouting的钩子。NF_HOOK是一个大的宏,最后它将进入实际的函数nf_hook_slow,我将这些留给特殊的开发者,让你们自己重新编写查看这部分。(不用紧张,这里只是训练你。)

10.1 框架结构体

在struct nf_hook_ops中为每个钩子包含有vtable(虚函数表?)和元数据,例如名字和关联的协议。这个结构体的定义可以通过包含<linux/netfilter.h>来获取。钩子是针对每个协议的;一个结构体只能注册一种协议,所以你需要注册多个钩子,那么就需要一个数组的nf_hook_ops实现。

struct nf_hook_ops {unsigned int pf;unsigned int priority;unsigned int hooknum;unsigned int (*hookfn)(unsigned int hooknum, struct sk_buff *skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *));struct module *owner;} 

10.2 初始化

结构体成员pf关系到这个钩子属于哪一个函数回调组。可能的值都列在netfilter.h中,最常见的值是NFPROTO_IPV6、NFPROTO_IPV4、NFPROTO_ARP和 NFPROTO_BRIDGE。在net/ipv4/目录中,你只能找到NFPROTO_IPV4,在net/ipv6/中,只能找到NFPROTO_IPV6。

成员priority则标示了这个钩子函数的调用顺序。一些标志性的静态变量定义在<linux/netfilter_ipv4.h>和<linux/netfilter_ipv6.h>可以当做是偏移的基址,例如,语句NF_IP6_PRI_FILTER+1让这个钩子函数在跑完filter表后进行处理。这个值更多的取决于模块的作者根据期望的效果。

       因为有Xtables模块,这个注册结构体一定不能使const的,因为对应的区域可能会随着实现被修改。

static struct nf_hook_ops myhook_ops __read_mostly = {.pf = PF_INET6,.priority = 1,.hooknum = NF_INET_LOCAL_OUT,.hookfn = myhook_fn,};static int __init myhook_init(void){return nf_register_hook(&myhook_ops);}static void __exit myhook_exit(void){nf_unregister_hook(&myhook_ops);}module_init(myhook_init);module_exit(myhook_exit);

这个钩子框架自己本身也不关注hooknum。一个钩子调用指定了一个特定的hooknum,hook模块可能会根据它来做一些事情。它通常是用于标示这个调用是从哪个位置来的:在前面(5.3节)提到Xtables、NAT和连接跟踪有五个静态变量,NF_INET_{PRE,POST}_ROUTING、NF_INET_LOCAL_{IN,OUT}和NF_INET_LOCAL_OUT。

 10.3 主要函数

static unsigned int myhook_fn(unsigned int hooknum, struct sk_buff *skb,const struct net_device *in, const struct net_device *out,int (*okfn)(struct sk_buff *)){pr_info("Arr matey! - Captain Hook approves your packet!\n");return NF_ACCEPT;}

一个钩子函数的可能的返回值和target的返回值非常相似。不过没有XT_RETURN,因为没有可以跳转的链我们可以返回,所以这个返回值在这里是没有意义的。同样也没有XT_CONTINUE,在最好的情况下等于NF_ACCEPT,意味着这个钩子函数允许这个包通过。

其他值都意味这个包被消化了,在头文件linux/netfilter.h中定义。(所以所有的NF_*静态变量都可以被使用,参考5.4节)

       有很多的返回值定义都不是普遍被使用,更多的是被netfilter内部使用,例如

NF_QUEUE,被xt_NFQUEUE使用,用于将包中继到用户空间处理。

NF_STOLEN,相对于NF_DROP将数据包丢弃并且释放掉skb,NF_STOLEN只是表示这个钩子函数接管了这个skb数据包,netfilter只需要丢弃。Netfilter忘记了这个数据包,并不意味这这个数据包丢失了—这个钩子函数可能将会重新发送或者延长发送。

NF_REPEAT,这个数据包将会重新执行这个钩子函数。连接跟踪使用这个返回值用于简化代码路径。

NF_STOP,在功能上和NF_ACCEPT相同。

原创粉丝点击