В каком порядке идут крючки Netfilter, если все они указывают NF_IP_PRI_LAST или NF_IP_PRI_FIRST?
Если я напишу несколько модулей ядра, и во всех них укажите, что они должны быть первым (или последним) вызовом netfilter, в каком порядке они будут фактически вызваны?
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;
}
Экспериментально я сделал два модуля,
insmod
их в двух разных порядках, но они дали тот же результат, подразумевая там какой-то подотряд, который не просто "первым пришел первым". (Это также не в алфавитном порядке...)
Ответы
Ответ 1
Из кодов nf_register_hook() мы можем знать, что если два крючка принадлежат одному и тому же nf_hooks [reg- > pf] [reg- > hooknum], последовательность выполнения крюка определяется приоритетом. Если приоритет тоже одинаков, последовательность будет "first come first serve". См. Следующие коды:
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;
}