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

[NETFILTER]: PPTP conntrack: simplify expectation handling



Remove duplicated expectation handling in the NAT helper and simplify
the remains in the conntrack helper.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 857c06da
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -315,7 +315,7 @@ extern int
			  struct PptpControlHeader *ctlh,
			  union pptp_ctrl_union *pptpReq);

extern int
extern void
(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig,
			    struct ip_conntrack_expect *exp_reply);

+31 −61
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ int
			  struct PptpControlHeader *ctlh,
			  union pptp_ctrl_union *pptpReq);

int
void
(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig,
			    struct ip_conntrack_expect *expect_reply);

@@ -219,93 +219,63 @@ static void pptp_destroy_siblings(struct ip_conntrack *ct)

/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
static inline int
exp_gre(struct ip_conntrack *master,
exp_gre(struct ip_conntrack *ct,
	__be16 callid,
	__be16 peer_callid)
{
	struct ip_conntrack_tuple inv_tuple;
	struct ip_conntrack_tuple exp_tuples[] = {
		/* tuple in original direction, PNS->PAC */
		{ .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
			   .u = { .gre = { .key = peer_callid } }
			 },
		  .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
			   .u = { .gre = { .key = callid } },
			   .protonum = IPPROTO_GRE
			 },
		 },
		/* tuple in reply direction, PAC->PNS */
		{ .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
			   .u = { .gre = { .key = callid } }
			 },
		  .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
			   .u = { .gre = { .key = peer_callid } },
			   .protonum = IPPROTO_GRE
			 },
		 }
	};
	struct ip_conntrack_expect *exp_orig, *exp_reply;
	int ret = 1;

	exp_orig = ip_conntrack_expect_alloc(master);
	exp_orig = ip_conntrack_expect_alloc(ct);
	if (exp_orig == NULL)
		goto out;

	exp_reply = ip_conntrack_expect_alloc(master);
	exp_reply = ip_conntrack_expect_alloc(ct);
	if (exp_reply == NULL)
		goto out_put_orig;

	memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple));
	/* original direction, PNS->PAC */
	exp_orig->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
	exp_orig->tuple.src.u.gre.key = peer_callid;
	exp_orig->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
	exp_orig->tuple.dst.u.gre.key = callid;
	exp_orig->tuple.dst.protonum = IPPROTO_GRE;

	exp_orig->mask.src.ip = 0xffffffff;
	exp_orig->mask.src.u.all = 0;
	exp_orig->mask.dst.u.all = 0;
	exp_orig->mask.dst.u.gre.key = htons(0xffff);
	exp_orig->mask.dst.ip = 0xffffffff;
	exp_orig->mask.dst.protonum = 0xff;

	exp_orig->master = master;
	exp_orig->master = ct;
	exp_orig->expectfn = pptp_expectfn;
	exp_orig->flags = 0;

	/* both expectations are identical apart from tuple */
	memcpy(exp_reply, exp_orig, sizeof(*exp_reply));
	memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple));

	if (ip_nat_pptp_hook_exp_gre)
		ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
	else {
	/* reply direction, PAC->PNS */
	exp_reply->tuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
	exp_reply->tuple.src.u.gre.key = callid;
	exp_reply->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
	exp_reply->tuple.dst.u.gre.key = peer_callid;
	exp_reply->tuple.dst.protonum = IPPROTO_GRE;

		DEBUGP("calling expect_related PNS->PAC");
		DUMP_TUPLE(&exp_orig->tuple);

		if (ip_conntrack_expect_related(exp_orig) != 0) {
			DEBUGP("cannot expect_related()\n");
	if (ip_nat_pptp_hook_exp_gre)
		ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
	if (ip_conntrack_expect_related(exp_orig) != 0)
		goto out_put_both;
		}

		DEBUGP("calling expect_related PAC->PNS");
		DUMP_TUPLE(&exp_reply->tuple);

		if (ip_conntrack_expect_related(exp_reply) != 0) {
			DEBUGP("cannot expect_related()\n");
	if (ip_conntrack_expect_related(exp_reply) != 0)
		goto out_unexpect_orig;
		}

	/* Add GRE keymap entries */
		if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) {
			DEBUGP("cannot keymap_add() exp\n");
	if (ip_ct_gre_keymap_add(ct, &exp_orig->tuple, 0) != 0)
		goto out_unexpect_both;
		}

		invert_tuplepr(&inv_tuple, &exp_reply->tuple);
		if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) {
			ip_ct_gre_keymap_destroy(master);
			DEBUGP("cannot keymap_add() exp_inv\n");
	if (ip_ct_gre_keymap_add(ct, &exp_reply->tuple, 1) != 0) {
		ip_ct_gre_keymap_destroy(ct);
		goto out_unexpect_both;
	}
	ret = 0;
	}

out_put_both:
	ip_conntrack_expect_put(exp_reply);
+3 −55
Original line number Diff line number Diff line
@@ -211,80 +211,28 @@ pptp_outbound_pkt(struct sk_buff **pskb,
	return NF_ACCEPT;
}

static int
static void
pptp_exp_gre(struct ip_conntrack_expect *expect_orig,
	     struct ip_conntrack_expect *expect_reply)
{
	struct ip_ct_pptp_master *ct_pptp_info =
				&expect_orig->master->help.ct_pptp_info;
	struct ip_nat_pptp *nat_pptp_info =
				&expect_orig->master->nat.help.nat_pptp_info;

	struct ip_conntrack *ct = expect_orig->master;

	struct ip_conntrack_tuple inv_t;
	struct ip_conntrack_tuple *orig_t, *reply_t;
	struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
	struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;

	/* save original PAC call ID in nat_info */
	nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;

	/* alter expectation */
	orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
	reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;

	/* alter expectation for PNS->PAC direction */
	invert_tuplepr(&inv_t, &expect_orig->tuple);
	expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id;
	expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id;
	expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id;
	expect_orig->dir = IP_CT_DIR_ORIGINAL;
	inv_t.src.ip = reply_t->src.ip;
	inv_t.dst.ip = reply_t->dst.ip;
	inv_t.src.u.gre.key = nat_pptp_info->pac_call_id;
	inv_t.dst.u.gre.key = ct_pptp_info->pns_call_id;

	if (!ip_conntrack_expect_related(expect_orig)) {
		DEBUGP("successfully registered expect\n");
	} else {
		DEBUGP("can't expect_related(expect_orig)\n");
		return 1;
	}

	/* alter expectation for PAC->PNS direction */
	invert_tuplepr(&inv_t, &expect_reply->tuple);
	expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id;
	expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id;
	expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id;
	expect_reply->dir = IP_CT_DIR_REPLY;
	inv_t.src.ip = orig_t->src.ip;
	inv_t.dst.ip = orig_t->dst.ip;
	inv_t.src.u.gre.key = nat_pptp_info->pns_call_id;
	inv_t.dst.u.gre.key = ct_pptp_info->pac_call_id;

	if (!ip_conntrack_expect_related(expect_reply)) {
		DEBUGP("successfully registered expect\n");
	} else {
		DEBUGP("can't expect_related(expect_reply)\n");
		ip_conntrack_unexpect_related(expect_orig);
		return 1;
	}

	if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) {
		DEBUGP("can't register original keymap\n");
		ip_conntrack_unexpect_related(expect_orig);
		ip_conntrack_unexpect_related(expect_reply);
		return 1;
	}

	if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) {
		DEBUGP("can't register reply keymap\n");
		ip_conntrack_unexpect_related(expect_orig);
		ip_conntrack_unexpect_related(expect_reply);
		ip_ct_gre_keymap_destroy(ct);
		return 1;
	}

	return 0;
}

/* inbound packets == from PAC to PNS */