If I write a few kernel modules, and in all of them specify they should be the first (or last) netfilter hook called, in what order will they actually be called?
netfilter_ops_out.hook = hook_func_out;
netfilter_ops_out.pf = PF_INET;
netfilter_ops_out.hooknum = NF_IP_LOCAL_OUT;
netfilter_ops_out.priority = NF_IP_PRI_FIRST;
ret = nf_register_hook(&netfilter_ops_out);
if (0 > ret) {
printk("Error registering netfilter hook: %d\n", ret);
return ret;
}
netfilter_ops_in.hook = hook_func_in;
netfilter_ops_in.pf = PF_INET;
netfilter_ops_in.hooknum = NF_IP_LOCAL_IN;
netfilter_ops_in.priority = NF_IP_PRI_LAST;
ret = nf_register_hook(&netfilter_ops_in);
if (0 > ret) {
printk("Error registering netfilter hook: %d\n", ret);
return ret;
}
Experimentally, I made two modules, insmod
ed them in the two different orders - but they gave the same result, implying there's some suborder that's not just 'first come first serve'. (It's also not alphabetical...)
There are 5 hook types defined for the IPV4 protocol. It is common for a packet to be processed by multiple hooks.
What Are IPTables and Netfilter? The basic firewall software most commonly used in Linux is called iptables . The iptables firewall works by interacting with the packet filtering hooks in the Linux kernel's networking stack. These kernel hooks are known as the netfilter framework.
The Netfilter framework provides a series of “hooks” inside the Linux kernel network stack that are traversed by network packets (Figure 1). Other kernel components can register callback functions with those hooks, enabling them to inspect any packets coming in and decide whether to drop or accept them.
From the nf_register_hook() codes, we can know that if two hooks belong to the same nf_hooks[reg->pf][reg->hooknum], the hook execute sequence is decided by priority. If the priority is also the same, the sequence is 'first come first serve'. See following codes:
int nf_register_hook(struct nf_hook_ops *reg)
{
struct nf_hook_ops *elem;
int err;
err = mutex_lock_interruptible(&nf_hook_mutex);
if (err < 0)
return err;
list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
if (reg->priority < elem->priority)
break;
}
list_add_rcu(®->list, elem->list.prev);
mutex_unlock(&nf_hook_mutex);
#if defined(CONFIG_JUMP_LABEL)
static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
#endif
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With