Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9457d851 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[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: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bff9a89b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;

+14 −5
Original line number Diff line number Diff line
@@ -545,10 +545,10 @@ static int early_drop(struct list_head *chain)
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_conntrack_tuple *orig,
	}

	/*  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_tuple *orig,
	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_tuple *tuple,
	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_tuple *tuple,
		/* 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
+1 −0
Original line number Diff line number Diff line
@@ -516,6 +516,7 @@ static int help(struct sk_buff **pskb,
	}

	exp->expectfn = NULL;
	exp->helper = NULL;
	exp->flags = 0;

	/* Now, NAT might want to mangle the packet, and register the
+2 −1
Original line number Diff line number Diff line
@@ -129,7 +129,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
	/* Get rid of expectations */
	list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
		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_conntrack_expect_put(exp);
		}
+1 −0
Original line number Diff line number Diff line
@@ -1447,6 +1447,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
	exp->expectfn = NULL;
	exp->flags = 0;
	exp->master = ct;
	exp->helper = NULL;
	memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
	memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));