在探索netfilter功能时,我尝试编写一个简单的netfilter模块并注册了一个钩子,如下所示:
dhcp_nfho.owner = THIS_MODULE;
dhcp_nfho.hook = dhcp_hook_function;
dhcp_nfho.hooknum = NF_INET_POST_ROUTING;
dhcp_nfho.priority = NF_IP_PRI_FIRST;
dhcp_nfho.pf = PF_INET; // not on bridge interface
nf_register_hook(&dhcp_nfho);
我查看了LXR页面中nf_register_hook的代码:(3.13版本)
int nf_register_hook(struct nf_hook_ops *reg)
69 {
70 struct nf_hook_ops *elem;
71 int err;
72
73 err = mutex_lock_interruptible(&nf_hook_mutex);
74 if (err < 0)
75 return err;
76 list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
77 if (reg->priority < elem->priority)
78 break;
79 }
80 list_add_rcu(®->list, elem->list.prev);
81 mutex_unlock(&nf_hook_mutex);
82 #if defined(CONFIG_JUMP_LABEL)
83 static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
84 #endif
85 return 0;
86 }
这个2D链表是什么nf_hooks [PF] [hooknum]。看起来每个协议族都有一个PRE / INPUT / FORWARD / OUTPUT / POST挂钩列表?
netfilter子系统如何使用这个2D数组?
netfilter子系统代码是否与网络驱动程序代码交互? (因为挂钩是在Soft-irq中处理的,网络驱动程序也使用soft-irq来处理数据包)?
在驱动程序收回数据包后,我在哪里可以找到调用Netfilter Hook的代码?
答案 0 :(得分:3)
你是对的。对于每个协议族,确实有一个钩子列表,它们实际上是由PF本身设置的(例如,NFPROTO_BRIDGE有一个BROUTE钩子列表,但IPv4或IPv6都没有)。
当数据包进入逻辑网络接口(以太网桥,以太网接口等)时,它将在堆栈中传递。如果是IPv4数据包,最终会调用ip_rcv()。这将调用NF_INET_PRE_ROUTING挂钩,然后再继续正确的数据包路由。类似地,ip_output在实际发送数据包之前调用NF_INET_POST_ROUTING挂钩。
将Netfilter挂钩放入主网络代码允许网络接口驱动程序本身对整个过程一无所知。
要更好地了解这一切是如何流动的,请查看http://lxr.free-electrons.com/source/net/ipv4/ip_input.c和http://lxr.free-electrons.com/source/net/ipv4/ip_output.c。当数据包转换到不同的层等时,您会看到NF_HOOK和NF_HOOK_COND宏被调用。