static void pptp_expectfn(struct ip_conntrack *ct,
			 struct ip_conntrack_expect *exp)
{
	DEBUGP("increasing timeouts\n");

	/* increase timeout of GRE data channel conntrack entry */
	ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
	ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;

	/* Can you see how rusty this code is, compared with the pre-2.6.11
	 * one? That's what happened to my shiny newnat of 2002 ;( -HW */

	if (!ip_nat_pptp_hook_expectfn) {
		struct ip_conntrack_tuple inv_t;
		struct ip_conntrack_expect *exp_other;

		/* obviously this tuple inversion only works until you do NAT */
		invert_tuplepr(&inv_t, &exp->tuple);
		DEBUGP("trying to unexpect other dir: ");
		DUMP_TUPLE(&inv_t);
	
		exp_other = __ip_conntrack_exp_find(&inv_t);
		if (exp_other) {
			/* delete other expectation.  */
			DEBUGP("found\n");
			ip_conntrack_unexpect_related(exp_other);
		} else {
			DEBUGP("not found\n");
		}
	} else {
		/* we need more than simple inversion */
		ip_nat_pptp_hook_expectfn(ct, exp);
	}
}
Exemple #2
0
/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
static inline int
exp_gre(struct ip_conntrack *master,
	u_int32_t seq,
	u_int16_t callid,
	u_int16_t peer_callid)
{
	struct ip_conntrack_expect exp;
	struct ip_conntrack_tuple inv_tuple;

	memset(&exp, 0, sizeof(exp));
	/* tuple in original direction, PNS->PAC */
	exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
	exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
	exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
	exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
	exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
	exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
	exp.tuple.dst.protonum = IPPROTO_GRE;

	exp.mask.src.ip = 0xffffffff;
	exp.mask.src.u.all = 0;
	exp.mask.dst.u.all = 0;
	exp.mask.dst.u.gre.key = 0xffffffff;
	exp.mask.dst.u.gre.version = 0xff;
	exp.mask.dst.u.gre.protocol = 0xffff;
	exp.mask.dst.ip = 0xffffffff;
	exp.mask.dst.protonum = 0xffff;
			
	exp.seq = seq;
	exp.expectfn = pptp_expectfn;

	exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
	exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);

	DEBUGP("calling expect_related ");
	DUMP_TUPLE_RAW(&exp.tuple);
	
	/* Add GRE keymap entries */
	if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
		return 1;

	invert_tuplepr(&inv_tuple, &exp.tuple);
	if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
		ip_ct_gre_keymap_destroy(&exp);
		return 1;
	}
	
	if (ip_conntrack_expect_related(master, &exp) != 0) {
		ip_ct_gre_keymap_destroy(&exp);
		DEBUGP("cannot expect_related()\n");
		return 1;
	}

	/* tuple in reply direction, PAC->PNS */
	exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
	exp.tuple.src.u.gre.key = htonl(ntohs(callid));
	exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
	exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));

	DEBUGP("calling expect_related ");
	DUMP_TUPLE_RAW(&exp.tuple);
	
	/* Add GRE keymap entries */
	ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
	invert_tuplepr(&inv_tuple, &exp.tuple);
	ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
	/* FIXME: cannot handle error correctly, since we need to free
	 * the above keymap :( */
	
	if (ip_conntrack_expect_related(master, &exp) != 0) {
		/* free the second pair of keypmaps */
		ip_ct_gre_keymap_destroy(&exp);
		DEBUGP("cannot expect_related():\n");
		return 1;
	}

	return 0;
}
Exemple #3
0
/* expect GRE connection in PNS->PAC direction */
static inline int
exp_gre(struct ip_conntrack *master,
	u_int32_t seq,
	u_int16_t callid,
	u_int16_t peer_callid)
{
	struct ip_conntrack_expect exp;
	struct ip_conntrack_tuple inv_tuple;

	memset(&exp, 0, sizeof(exp));
	/* tuple in original direction, PNS->PAC */
	exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
	exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
	exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
	exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
	exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
	exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
	exp.tuple.dst.protonum = IPPROTO_GRE;

	exp.mask.src.ip = 0xffffffff;
	exp.mask.src.u.all = 0;
	exp.mask.dst.u.all = 0;
	exp.mask.dst.u.gre.key = 0xffffffff;
	exp.mask.dst.u.gre.version = 0xff;
	exp.mask.dst.u.gre.protocol = 0xffff;
	exp.mask.dst.ip = 0xffffffff;
	exp.mask.dst.protonum = 0xffff;
			
	exp.seq = seq;
	exp.expectfn = pptp_expectfn;

	exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
	exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);

	DEBUGP("calling expect_related ");
	DUMP_TUPLE_RAW(&exp.tuple);
	
	/* Add GRE keymap entries */
	ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
	invert_tuplepr(&inv_tuple, &exp.tuple);
	ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
	
	ip_conntrack_expect_related(master, &exp);

	/* tuple in reply direction, PAC->PNS */
	exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
	exp.tuple.src.u.gre.key = htonl(ntohs(callid));
	exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
	exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));

	DEBUGP("calling expect_related ");
	DUMP_TUPLE_RAW(&exp.tuple);
	
	/* Add GRE keymap entries */
	ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
	invert_tuplepr(&inv_tuple, &exp.tuple);
	ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
	
	ip_conntrack_expect_related(master, &exp);

	return 0;
}
static int
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;

	/* 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 = htons(ct_pptp_info->pns_call_id);
	expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
	expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
	inv_t.src.ip = reply_t->src.ip;
	inv_t.dst.ip = reply_t->dst.ip;
	inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
	inv_t.dst.u.gre.key = htons(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");
		ip_conntrack_expect_free(expect_orig);
		return 1;
	}

	/* alter expectation for PAC->PNS direction */
	invert_tuplepr(&inv_t, &expect_reply->tuple);
	expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id);
	expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
	expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id);
	inv_t.src.ip = orig_t->src.ip;
	inv_t.dst.ip = orig_t->dst.ip;
	inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
	inv_t.dst.u.gre.key = htons(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);
		ip_conntrack_expect_free(expect_reply);
		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;
}