[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 <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
bff9a89bca
commit
9457d851fc
5 changed files with 21 additions and 6 deletions
|
@ -22,6 +22,9 @@ struct nf_conntrack_expect
|
||||||
void (*expectfn)(struct nf_conn *new,
|
void (*expectfn)(struct nf_conn *new,
|
||||||
struct nf_conntrack_expect *this);
|
struct nf_conntrack_expect *this);
|
||||||
|
|
||||||
|
/* Helper to assign to new connection */
|
||||||
|
struct nf_conntrack_helper *helper;
|
||||||
|
|
||||||
/* The conntrack of the master connection */
|
/* The conntrack of the master connection */
|
||||||
struct nf_conn *master;
|
struct nf_conn *master;
|
||||||
|
|
||||||
|
|
|
@ -545,10 +545,10 @@ static int early_drop(struct list_head *chain)
|
||||||
static struct nf_conn *
|
static struct nf_conn *
|
||||||
__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
|
__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
|
||||||
const struct nf_conntrack_tuple *repl,
|
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;
|
struct nf_conn *conntrack = NULL;
|
||||||
u_int32_t features = 0;
|
|
||||||
struct nf_conntrack_helper *helper;
|
struct nf_conntrack_helper *helper;
|
||||||
|
|
||||||
if (unlikely(!nf_conntrack_hash_rnd_initted)) {
|
if (unlikely(!nf_conntrack_hash_rnd_initted)) {
|
||||||
|
@ -574,7 +574,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find features needed by this conntrack. */
|
/* find features needed by this conntrack. */
|
||||||
features = l3proto->get_features(orig);
|
features |= l3proto->get_features(orig);
|
||||||
|
|
||||||
/* FIXME: protect helper list per RCU */
|
/* FIXME: protect helper list per RCU */
|
||||||
read_lock_bh(&nf_conntrack_lock);
|
read_lock_bh(&nf_conntrack_lock);
|
||||||
|
@ -624,7 +624,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
|
||||||
struct nf_conntrack_l3proto *l3proto;
|
struct nf_conntrack_l3proto *l3proto;
|
||||||
|
|
||||||
l3proto = __nf_ct_l3proto_find(orig->src.l3num);
|
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)
|
void nf_conntrack_free(struct nf_conn *conntrack)
|
||||||
|
@ -649,13 +649,20 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
|
||||||
struct nf_conn *conntrack;
|
struct nf_conn *conntrack;
|
||||||
struct nf_conntrack_tuple repl_tuple;
|
struct nf_conntrack_tuple repl_tuple;
|
||||||
struct nf_conntrack_expect *exp;
|
struct nf_conntrack_expect *exp;
|
||||||
|
u_int32_t features = 0;
|
||||||
|
|
||||||
if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
|
if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
|
||||||
DEBUGP("Can't invert tuple.\n");
|
DEBUGP("Can't invert tuple.\n");
|
||||||
return NULL;
|
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)) {
|
if (conntrack == NULL || IS_ERR(conntrack)) {
|
||||||
DEBUGP("Can't allocate conntrack.\n");
|
DEBUGP("Can't allocate conntrack.\n");
|
||||||
return (struct nf_conntrack_tuple_hash *)conntrack;
|
return (struct nf_conntrack_tuple_hash *)conntrack;
|
||||||
|
@ -676,6 +683,8 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
|
||||||
/* Welcome, Mr. Bond. We've been expecting you... */
|
/* Welcome, Mr. Bond. We've been expecting you... */
|
||||||
__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
|
__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
|
||||||
conntrack->master = exp->master;
|
conntrack->master = exp->master;
|
||||||
|
if (exp->helper)
|
||||||
|
nfct_help(conntrack)->helper = exp->helper;
|
||||||
#ifdef CONFIG_NF_CONNTRACK_MARK
|
#ifdef CONFIG_NF_CONNTRACK_MARK
|
||||||
conntrack->mark = exp->master->mark;
|
conntrack->mark = exp->master->mark;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -516,6 +516,7 @@ static int help(struct sk_buff **pskb,
|
||||||
}
|
}
|
||||||
|
|
||||||
exp->expectfn = NULL;
|
exp->expectfn = NULL;
|
||||||
|
exp->helper = NULL;
|
||||||
exp->flags = 0;
|
exp->flags = 0;
|
||||||
|
|
||||||
/* Now, NAT might want to mangle the packet, and register the
|
/* Now, NAT might want to mangle the packet, and register the
|
||||||
|
|
|
@ -129,7 +129,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
|
||||||
/* Get rid of expectations */
|
/* Get rid of expectations */
|
||||||
list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
|
list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
|
||||||
struct nf_conn_help *help = nfct_help(exp->master);
|
struct nf_conn_help *help = nfct_help(exp->master);
|
||||||
if (help->helper == me && del_timer(&exp->timeout)) {
|
if ((help->helper == me || exp->helper == me) &&
|
||||||
|
del_timer(&exp->timeout)) {
|
||||||
nf_ct_unlink_expect(exp);
|
nf_ct_unlink_expect(exp);
|
||||||
nf_conntrack_expect_put(exp);
|
nf_conntrack_expect_put(exp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1447,6 +1447,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
|
||||||
exp->expectfn = NULL;
|
exp->expectfn = NULL;
|
||||||
exp->flags = 0;
|
exp->flags = 0;
|
||||||
exp->master = ct;
|
exp->master = ct;
|
||||||
|
exp->helper = NULL;
|
||||||
memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
|
memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
|
||||||
memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
|
memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue