Linux 如果Netfilter挂钩都指定NF_IP_PRI_LAST或NF_IP_PRI_FIRST,那么它们的顺序是什么?

Linux 如果Netfilter挂钩都指定NF_IP_PRI_LAST或NF_IP_PRI_FIRST,那么它们的顺序是什么?,linux,linux-kernel,netfilter,Linux,Linux Kernel,Netfilter,如果我编写几个内核模块,并在所有模块中指定它们应该是第一个(或最后一个)被调用的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 = n

如果我编写几个内核模块,并在所有模块中指定它们应该是第一个(或最后一个)被调用的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
以两种不同的顺序对它们进行排序——但它们给出了相同的结果,这意味着存在一些不只是“先到先得”的子顺序。(也不是字母顺序…

从nf_register_hook()代码中,我们可以知道,如果两个钩子属于同一个nf_钩子[reg->pf][reg->hooknum],钩子执行顺序由优先级决定。如果优先级相同,则顺序为“先到先得”。参见以下代码:

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(&reg->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;
}
int-nf\u-register\u-hook(结构nf\u-hook\u-ops*reg)
{
结构nf_hook_ops*elem;
INTERR;
err=mutex\u lock\u interruptable(&nf\u hook\u mutex);
如果(误差<0)
返回错误;
为每个项目列出(元素和nf挂钩[reg->pf][reg->hooknum],列表){
如果(注册->优先级优先级)
打破
}
list\u add\u rcu(®->list,elem->list.prev);
互斥锁解锁(&nf\U挂钩\U互斥锁);
#如果已定义(配置跳转标签)
静态键慢键有限公司(&nf\u hooks\u需要[reg->pf][reg->hooknum]);
#恩迪夫
返回0;
}

nf\u register\u hook()
module\u init
函数中调用。较旧的内核:2.6.18。一个模块修改数据包,另一个模块记录数据包,两者使用相同的注册代码(如上所述)。但是,无论我以什么顺序加载模块,我总是在记录器中看到修改过的数据包。我想我应该能够让记录器在修改器之前运行。。。但是没有骰子。对不起,我的解释只是进一步混淆了这个问题。我有四个钩子,每个本地输入和本地输出各两个。这两个模块都与传入和传出挂钩,但我只关注传入。