[NETFILTER]: nf_conntrack: automatic helper assignment for expectations Some helpers (namely H.323) manually assign further helpers to expected connections. This is not possible with nf_conntrack anymore since we need to know whether a helper is used at allocation time. Handle the helper assignment centrally, which allows to perform the correct allocation and as a nice side effect eliminates the need for the H.323 helper to fiddle with nf_conntrack_lock. Mid term the allocation scheme really needs to be redesigned since we do both the helper and expectation lookup _twice_ for every new connection. Signed-off-by: Patrick McHardy --- commit fa7ba8735f8bdcc47b2ca5d11c1b8ec6fb7ae241 tree ddcc58530cfeded09283ffd6659c6a44aaaeb294 parent 35d1fac7ef0f6a79e41f86af6d28036570dc21b9 author Patrick McHardy Thu, 30 Nov 2006 16:23:42 +0100 committer Patrick McHardy Thu, 30 Nov 2006 16:23:42 +0100 include/net/netfilter/nf_conntrack_expect.h | 3 +++ net/netfilter/nf_conntrack_core.c | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 2d335f0..5d853e8 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -22,6 +22,9 @@ struct nf_conntrack_expect void (*expectfn)(struct nf_conn *new, struct nf_conntrack_expect *this); + /* Helper to assign to new connection */ + struct nf_conntrack_helper *helper; + /* The conntrack of the master connection */ struct nf_conn *master; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index a672806..44b8744 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -545,10 +545,10 @@ static int early_drop(struct list_head * static struct nf_conn * __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, const struct nf_conntrack_tuple *repl, - const struct nf_conntrack_l3proto *l3proto) + const struct nf_conntrack_l3proto *l3proto, + u_int32_t features) { struct nf_conn *conntrack = NULL; - u_int32_t features = 0; struct nf_conntrack_helper *helper; if (unlikely(!nf_conntrack_hash_rnd_initted)) { @@ -574,7 +574,7 @@ __nf_conntrack_alloc(const struct nf_con } /* find features needed by this conntrack. */ - features = l3proto->get_features(orig); + features |= l3proto->get_features(orig); /* FIXME: protect helper list per RCU */ read_lock_bh(&nf_conntrack_lock); @@ -624,7 +624,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_l3proto *l3proto; l3proto = __nf_ct_l3proto_find(orig->src.l3num); - return __nf_conntrack_alloc(orig, repl, l3proto); + return __nf_conntrack_alloc(orig, repl, l3proto, 0); } void nf_conntrack_free(struct nf_conn *conntrack) @@ -649,13 +649,20 @@ init_conntrack(const struct nf_conntrack struct nf_conn *conntrack; struct nf_conntrack_tuple repl_tuple; struct nf_conntrack_expect *exp; + u_int32_t features = 0; if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { DEBUGP("Can't invert tuple.\n"); return NULL; } - conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto); + read_lock_bh(&nf_conntrack_lock); + exp = __nf_conntrack_expect_find(tuple); + if (exp && exp->helper) + features = NF_CT_F_HELP; + read_unlock_bh(&nf_conntrack_lock); + + conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features); if (conntrack == NULL || IS_ERR(conntrack)) { DEBUGP("Can't allocate conntrack.\n"); return (struct nf_conntrack_tuple_hash *)conntrack; @@ -676,6 +683,8 @@ init_conntrack(const struct nf_conntrack /* Welcome, Mr. Bond. We've been expecting you... */ __set_bit(IPS_EXPECTED_BIT, &conntrack->status); conntrack->master = exp->master; + if (exp->helper) + nfct_help(conntrack)->helper = exp->helper; #ifdef CONFIG_NF_CONNTRACK_MARK conntrack->mark = exp->master->mark; #endif