If userspace using nfqueue or nflog requests conntrack info, make sure that we register the conntrack netfilter hooks in the affected netns. This is a one-shot scheme: There is no unregister equivalent (except when backend conntrack l3proto module is unloaded or the network namespace is removed). Once nflog/nfqueue wants conntrack, the hooks are activated without being able to unregister the hooks again. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- not part of v2 series. This is a seperate patch to ease review. include/linux/netfilter.h | 1 + net/netfilter/nf_conntrack_netlink.c | 1 + net/netfilter/nfnetlink_log.c | 28 ++++++++++++++++++---------- net/netfilter/nfnetlink_queue.c | 8 ++++++++ 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 9230f9a..c3cf796 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -396,6 +396,7 @@ struct nfnl_ct_hook { u32 portid, u32 report); void (*seq_adjust)(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, s32 off); + int (*register_hooks)(struct net *); }; extern struct nfnl_ct_hook __rcu *nfnl_ct_hook; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b8a4067..0a9b1e9 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -2451,6 +2451,7 @@ static struct nfnl_ct_hook ctnetlink_glue_hook = { .parse = ctnetlink_glue_parse, .attach_expect = ctnetlink_glue_attach_expect, .seq_adjust = ctnetlink_glue_seqadj, + .register_hooks = ctnl_bind, }; #endif /* CONFIG_NETFILTER_NETLINK_GLUE_CT */ diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index dea4676..229685d 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -853,19 +853,27 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, if (nfula[NFULA_CFG_FLAGS]) { flags = ntohs(nla_get_be16(nfula[NFULA_CFG_FLAGS])); - if ((flags & NFULNL_CFG_F_CONNTRACK) && - !rcu_access_pointer(nfnl_ct_hook)) { + if (flags & NFULNL_CFG_F_CONNTRACK) { + struct nfnl_ct_hook *nfnl_ct; + + nfnl_ct = rcu_dereference(nfnl_ct_hook); + if (!nfnl_ct) { #ifdef CONFIG_MODULES - nfnl_unlock(NFNL_SUBSYS_ULOG); - request_module("ip_conntrack_netlink"); - nfnl_lock(NFNL_SUBSYS_ULOG); - if (rcu_access_pointer(nfnl_ct_hook)) { - ret = -EAGAIN; + nfnl_unlock(NFNL_SUBSYS_ULOG); + request_module("ip_conntrack_netlink"); + nfnl_lock(NFNL_SUBSYS_ULOG); + + if (rcu_access_pointer(nfnl_ct_hook)) { + ret = -EAGAIN; + goto out_put; + } +#endif + ret = -EOPNOTSUPP; goto out_put; + } -#endif - ret = -EOPNOTSUPP; - goto out_put; + + nfnl_ct->register_hooks(net); } } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 7d81d28..235f4c1 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -1222,6 +1222,14 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, goto err_out_unlock; } #endif + if (flags & mask & NFQA_CFG_F_CONNTRACK) { + struct nfnl_ct_hook *nfnl_ct; + + nfnl_ct = rcu_dereference(nfnl_ct_hook); + if (nfnl_ct) + nfnl_ct->register_hooks(net); + } + spin_lock_bh(&queue->lock); queue->flags &= ~mask; queue->flags |= flags & mask; -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html