[netfilter-cvslog] r4093 - in trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11: include/linux/netfilter_ipv4 net/ipv4/netfilter

laforge at netfilter.org laforge at netfilter.org
Mon Jul 4 20:44:45 CEST 2005


Author: laforge at netfilter.org
Date: 2005-07-04 20:44:44 +0200 (Mon, 04 Jul 2005)
New Revision: 4093

Modified:
   trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
   trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
   trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_pptp.c
   trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_proto_gre.c
   trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_pptp.c
Log:
major update.  fixed a couple of bugs in preliminary conntrack support, added port of NAT code. works fine now on 2.6.12.1


Modified: trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h	2005-07-04 15:35:34 UTC (rev 4092)
+++ trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h	2005-07-04 18:44:44 UTC (rev 4093)
@@ -33,6 +33,10 @@
 	enum pptp_ctrlcall_state cstate;	/* call state */
 	u_int16_t pac_call_id;			/* call id of PAC, host byte order */
 	u_int16_t pns_call_id;			/* call id of PNS, host byte order */
+
+	/* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
+	 * and therefore imposes a fixed limit on the number of maps */
+	struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
 };
 
 /* conntrack_expect private member */
@@ -45,6 +49,7 @@
 
 #ifdef __KERNEL__
 
+
 #include <linux/netfilter_ipv4/lockhelp.h>
 DECLARE_LOCK_EXTERN(ip_pptp_lock);
 
@@ -306,5 +311,26 @@
                 struct PptpSetLinkInfo          setlink;
 };
 
+extern int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig,
+			    struct ip_conntrack_expect *exp_reply);
+
+extern void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+			     struct ip_conntrack_expect *exp);
 #endif /* __KERNEL__ */
 #endif /* _CONNTRACK_PPTP_H */

Modified: trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h	2005-07-04 15:35:34 UTC (rev 4092)
+++ trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h	2005-07-04 18:44:44 UTC (rev 4093)
@@ -69,14 +69,11 @@
 struct ip_ct_gre {
 	unsigned int stream_timeout;
 	unsigned int timeout;
-
-	/* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
-	 * and therefore imposes a fixed limit on the number of maps */
-	struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
 };
 
 #ifdef __KERNEL__
 struct ip_conntrack_expect;
+struct ip_conntrack;
 
 /* structure for original <-> reply keymap */
 struct ip_ct_gre_keymap {
@@ -85,16 +82,11 @@
 	struct ip_conntrack_tuple tuple;
 };
 
-
 /* add new tuple->key_reply pair to keymap */
 int ip_ct_gre_keymap_add(struct ip_conntrack *ct,
 			 struct ip_conntrack_tuple *t,
 			 int reply);
 
-/* change an existing keymap entry */
-void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
-			     struct ip_conntrack_tuple *t);
-
 /* delete keymap entries */
 void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct);
 

Modified: trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_pptp.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_pptp.c	2005-07-04 15:35:34 UTC (rev 4092)
+++ trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_pptp.c	2005-07-04 18:44:44 UTC (rev 4093)
@@ -17,9 +17,9 @@
  * 	 - We blindly assume that control connections are always
  * 	   established in PNS->PAC direction.  This is a violation
  * 	   of RFFC2673
+ * 	 - We can only support one single call within each session
  *
- * TODO: - finish support for multiple calls within one session
- * 	   (needs expect reservations in newnat)
+ * TODO:
  *	 - testing of incoming PPTP calls 
  *
  * Changes: 
@@ -52,6 +52,8 @@
 #include <net/tcp.h>
 
 #include <linux/netfilter_ipv4/lockhelp.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
 #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
@@ -64,6 +66,28 @@
 
 DECLARE_LOCK(ip_pptp_lock);
 
+int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig,
+			    struct ip_conntrack_expect *expect_reply);
+
+void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+			     struct ip_conntrack_expect *exp);
+
 #if 0
 #include "ip_conntrack_pptp_priv.h"
 #define DEBUGP(format, args...)	printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
@@ -82,91 +106,95 @@
 static void pptp_expectfn(struct ip_conntrack *ct,
 			 struct ip_conntrack_expect *exp)
 {
-	struct ip_conntrack *master;
+	DEBUGP("increasing timeouts\n");
 
-	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;
 
-	master = master_ct(ct);
-	if (!master) {
-		DEBUGP(" no master!!!\n");
-		return 0;
-	}
+	/* 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 */
 
-	DEBUGP("completing tuples with ct info\n");
-	/* we can do this, since we're unconfirmed */
-	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == 
-		htons(master->help.ct_pptp_info.pac_call_id)) {	
-		/* assume PNS->PAC */
-		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = 
-			htons(master->help.ct_pptp_info.pns_call_id);
-		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
-			htons(master->help.ct_pptp_info.pns_call_id);
+	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 {
-		/* assume PAC->PNS */
-		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
-			htons(master->help.ct_pptp_info.pac_call_id);
-		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
-			htons(master->help.ct_pptp_info.pac_call_id);
+		/* we need more than simple inversion */
+		ip_nat_pptp_hook_expectfn(ct, exp);
 	}
-	
-#ifdef FIXME_LATER
-	/* delete other expectation */
-	if (exp->expected_list.next != &exp->expected_list) {
-		struct ip_conntrack_expect *other_exp;
-		struct list_head *cur_item, *next;
+}
 
-		for (cur_item = master->sibling_list.next;
-		     cur_item != &master->sibling_list; cur_item = next) {
-			next = cur_item->next;
-			other_exp = list_entry(cur_item,
-					       struct ip_conntrack_expect,
-					       expected_list);
-			/* remove only if occurred at same sequence number */
-			if (other_exp != exp && other_exp->seq == exp->seq) {
-				DEBUGP("unexpecting other direction\n");
-				ip_ct_gre_keymap_destroy(other_exp);
-				ip_conntrack_unexpect_related(other_exp);
-			}
+static int timeout_ct_or_exp(const struct ip_conntrack_tuple *t)
+{
+	struct ip_conntrack_tuple_hash *h;
+	struct ip_conntrack_expect *exp;
+
+	DEBUGP("trying to timeout ct or exp for tuple ");
+	DUMP_TUPLE(t);
+
+	h = __ip_conntrack_find(t, NULL);
+	if (h)  {
+		struct ip_conntrack *sibling = tuplehash_to_ctrack(h);
+		DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+		sibling->proto.gre.timeout = 0;
+		sibling->proto.gre.stream_timeout = 0;
+		/* refresh_acct will not modify counters if skb == NULL */
+		ip_ct_refresh_acct(sibling, 0, NULL, 0);
+		return 1;
+	} else {
+		exp = __ip_conntrack_exp_find(t);
+		if (exp) {
+			DEBUGP("unexpect_related of expect %p\n", exp);
+			ip_conntrack_unexpect_related(exp);
+			return 1;
 		}
 	}
-#endif
 
 	return 0;
 }
 
+
 /* timeout GRE data connections */
 static int pptp_timeout_related(struct ip_conntrack *ct)
 {
-	struct list_head *cur_item, *next;
-	struct ip_conntrack_expect *exp;
+	struct ip_conntrack_tuple t;
+	int ret;
 
-#ifdef FIXME_LATER
-	/* FIXME: do we have to lock something ? */
-	for (cur_item = ct->sibling_list.next;
-	    cur_item != &ct->sibling_list; cur_item = next) {
-		next = cur_item->next;
-		exp = list_entry(cur_item, struct ip_conntrack_expect,
-				 expected_list);
+	/* Since ct->sibling_list has literally rusted away in 2.6.11, 
+	 * we now need another way to find out about our sibling
+	 * contrack and expects... -HW */
 
-		ip_ct_gre_keymap_destroy(exp);
-		if (!exp->sibling) {
-			ip_conntrack_unexpect_related(exp);
-			continue;
-		}
+	/* try original (pns->pac) tuple */
+	memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
+	t.dst.protonum = IPPROTO_GRE;
+	t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+	t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
 
-		DEBUGP("setting timeout of conntrack %p to 0\n",
-			exp->sibling);
-		exp->sibling->proto.gre.timeout = 0;
-		exp->sibling->proto.gre.stream_timeout = 0;
-		/* refresh_acct will not modify counters if skb == NULL */
-		ip_ct_refresh_acct(exp->sibling, 0, NULL, 0);
-	}
-#endif
+	ret = timeout_ct_or_exp(&t);
 
-	return 0;
+	/* try reply (pac->pns) tuple */
+	memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
+	t.dst.protonum = IPPROTO_GRE;
+	t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
+	t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+
+	ret += timeout_ct_or_exp(&t);
+
+	return ret;
 }
 
 /* expect GRE connections (PNS->PAC and PAC->PNS direction) */
@@ -196,64 +224,93 @@
 			   .protonum = IPPROTO_GRE
 			 },
 		 }
-	}, *exp_tuple;
+	};
 
-	for (exp_tuple = exp_tuples; exp_tuple < &exp_tuples[2]; exp_tuple++) {
-		struct ip_conntrack_expect *exp;
-		struct ip_ct_pptp_expect exp_pptp_info;
+	struct ip_conntrack_expect *exp_orig, *exp_reply;
 
-		exp = ip_conntrack_expect_alloc();
-		if (exp == NULL)
+	exp_orig = ip_conntrack_expect_alloc();
+	if (exp_orig == NULL)
+		return 1;
+
+	exp_reply = ip_conntrack_expect_alloc();
+	if (exp_reply == NULL) {
+		ip_conntrack_expect_free(exp_orig);
+		return 1;
+	}
+
+	memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple));
+
+	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 = 0xffff;
+	exp_orig->mask.dst.ip = 0xffffffff;
+	exp_orig->mask.dst.protonum = 0xff;
+		
+	exp_orig->master = master;
+	exp_orig->expectfn = pptp_expectfn;
+
+	exp_orig->dir = IP_CT_DIR_ORIGINAL;
+
+	/* 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));
+
+	exp_reply->dir = !exp_orig->dir;
+
+	if (ip_nat_pptp_hook_exp_gre)
+		return ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
+	else {
+
+		DEBUGP("calling expect_related PNS->PAC");
+		DUMP_TUPLE(&exp_orig->tuple);
+
+		if (ip_conntrack_expect_related(exp_orig) != 0) {
+			ip_conntrack_expect_free(exp_orig);
+			ip_conntrack_expect_free(exp_reply);
+			DEBUGP("cannot expect_related()\n");
 			return 1;
+		}
 
-		memcpy(&exp->tuple, exp_tuple, sizeof(exp->tuple));
+		DEBUGP("calling expect_related PAC->PNS");
+		DUMP_TUPLE(&exp_reply->tuple);
 
-		exp->mask.src.ip = 0xffffffff;
-		exp->mask.src.u.all = 0;
-		exp->mask.dst.u.all = 0;
-		exp->mask.dst.u.gre.key = 0xffff;
-		exp->mask.dst.ip = 0xffffffff;
-		exp->mask.dst.protonum = 0xff;
-			
-		exp->master = master;
-		exp->expectfn = pptp_expectfn;
+		if (ip_conntrack_expect_related(exp_reply) != 0) {
+			ip_conntrack_unexpect_related(exp_orig);
+			ip_conntrack_expect_free(exp_reply);
+			DEBUGP("cannot expect_related()\n");
+			return 1;
+		}
 
-		exp_pptp_info.pac_call_id = ntohs(callid);
-		exp_pptp_info.pns_call_id = ntohs(peer_callid);
-
-		DEBUGP("calling expect_related ");
-		DUMP_TUPLE(&exp->tuple);
-	
 		/* Add GRE keymap entries */
-		if (ip_ct_gre_keymap_add(master, &exp->tuple, 0) != 0) {
-			ip_conntrack_expect_free(exp);
+		if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) {
+			ip_conntrack_unexpect_related(exp_orig);
+			ip_conntrack_unexpect_related(exp_reply);
+			DEBUGP("cannot keymap_add() exp\n");
 			return 1;
 		}
 
-		invert_tuplepr(&inv_tuple, &exp->tuple);
+		invert_tuplepr(&inv_tuple, &exp_reply->tuple);
 		if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) {
+			ip_conntrack_unexpect_related(exp_orig);
+			ip_conntrack_unexpect_related(exp_reply);
 			ip_ct_gre_keymap_destroy(master);
-			ip_conntrack_expect_free(exp);
+			DEBUGP("cannot keymap_add() exp_inv\n");
 			return 1;
 		}
 	
-		if (ip_conntrack_expect_related(exp) != 0) {
-			ip_ct_gre_keymap_destroy(master);
-			ip_conntrack_expect_free(exp);
-			DEBUGP("cannot expect_related()\n");
-			return 1;
-		}
 	}
 
 	return 0;
 }
 
 static inline int 
-pptp_inbound_pkt(struct sk_buff *skb,
+pptp_inbound_pkt(struct sk_buff **pskb,
 		 struct tcphdr *tcph,
 		 unsigned int ctlhoff,
 		 size_t datalen,
-		 struct ip_conntrack *ct)
+		 struct ip_conntrack *ct,
+		 enum ip_conntrack_info ctinfo)
 {
 	struct PptpControlHeader _ctlh, *ctlh;
 	unsigned int reqlen;
@@ -262,14 +319,14 @@
 	u_int16_t msg, *cid, *pcid;
 	u_int32_t seq;	
 
-	ctlh = skb_header_pointer(skb, ctlhoff, sizeof(_ctlh), &_ctlh);
+	ctlh = skb_header_pointer(*pskb, ctlhoff, sizeof(_ctlh), &_ctlh);
 	if (unlikely(!ctlh)) {
 		DEBUGP("error during skb_header_pointer\n");
 		return NF_ACCEPT;
 	}
 
 	reqlen = datalen - sizeof(struct pptp_pkt_hdr) - sizeof(_ctlh);
-	pptpReq = skb_header_pointer(skb, ctlhoff+sizeof(_ctlh),
+	pptpReq = skb_header_pointer(*pskb, ctlhoff+sizeof(_ctlh),
 				     reqlen, &_pptpReq);
 	if (unlikely(!pptpReq)) {
 		DEBUGP("error during skb_header_pointer\n");
@@ -446,16 +503,22 @@
 		break;
 	}
 
+
+	if (ip_nat_pptp_hook_inbound)
+		return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
+						pptpReq);
+
 	return NF_ACCEPT;
 
 }
 
 static inline int
-pptp_outbound_pkt(struct sk_buff *skb,
+pptp_outbound_pkt(struct sk_buff **pskb,
 		  struct tcphdr *tcph,
 		  unsigned int ctlhoff,
 		  size_t datalen,
-		  struct ip_conntrack *ct)
+		  struct ip_conntrack *ct,
+		  enum ip_conntrack_info ctinfo)
 {
 	struct PptpControlHeader _ctlh, *ctlh;
 	unsigned int reqlen;
@@ -463,12 +526,12 @@
 	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
 	u_int16_t msg, *cid, *pcid;
 
-	ctlh = skb_header_pointer(skb, ctlhoff, sizeof(_ctlh), &_ctlh);
+	ctlh = skb_header_pointer(*pskb, ctlhoff, sizeof(_ctlh), &_ctlh);
 	if (!ctlh)
 		return NF_ACCEPT;
 	
 	reqlen = datalen - sizeof(struct pptp_pkt_hdr) - sizeof(_ctlh);
-	pptpReq = skb_header_pointer(skb, ctlhoff+sizeof(_ctlh), reqlen, 
+	pptpReq = skb_header_pointer(*pskb, ctlhoff+sizeof(_ctlh), reqlen, 
 				     &_pptpReq);
 	if (!pptpReq)
 		return NF_ACCEPT;
@@ -560,6 +623,10 @@
 		/* unknown: no need to create GRE masq table entry */
 		break;
 	}
+	
+	if (ip_nat_pptp_hook_outbound)
+		return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
+						 pptpReq);
 
 	return NF_ACCEPT;
 }
@@ -610,7 +677,7 @@
 	if (tcp_v4_check(tcph, tcplen, (*pskb)->nh.iph->saddr,
 			 (*pskb)->nh.iph->daddr,
 			 csum_partial((char *) tcph, tcplen, 0))) {
-		printk(KERN_NOTICE __FILE__ ": bad csum\n");
+		DEBUGP(" bad csum\n");
 		/* W2K PPTP server sends TCP packets with wrong checksum :(( */
 		//return NF_ACCEPT;
 	}
@@ -651,10 +718,12 @@
 	 * established from PNS->PAC.  However, RFC makes no guarantee */
 	if (dir == IP_CT_DIR_ORIGINAL)
 		/* client -> server (PNS -> PAC) */
-		ret = pptp_outbound_pkt(*pskb, tcph, nexthdr_off, datalen, ct);
+		ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+					ctinfo);
 	else
 		/* server -> client (PAC -> PNS) */
-		ret = pptp_inbound_pkt(*pskb, tcph, nexthdr_off, datalen, ct);
+		ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+				       ctinfo);
 	DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
 		oldsstate, info->sstate, oldcstate, info->cstate);
 	UNLOCK_BH(&ip_pptp_lock);
@@ -694,7 +763,7 @@
 {
 	int retcode;
 
-	DEBUGP(__FILE__ ": registering helper\n");
+	DEBUGP(" registering helper\n");
 	if ((retcode = ip_conntrack_helper_register(&pptp))) {
 		printk(KERN_ERR "Unable to register conntrack application "
 				"helper for pptp: %d\n", retcode);
@@ -715,3 +784,7 @@
 module_exit(fini);
 
 EXPORT_SYMBOL(ip_pptp_lock);
+EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre);
+EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn);

Modified: trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_proto_gre.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_proto_gre.c	2005-07-04 15:35:34 UTC (rev 4092)
+++ trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_conntrack_proto_gre.c	2005-07-04 18:44:44 UTC (rev 4093)
@@ -80,18 +80,17 @@
 static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
 {
 	struct ip_ct_gre_keymap *km;
-	u_int32_t key;
+	u_int32_t key = 0;
 
 	READ_LOCK(&ip_ct_gre_lock);
 	km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
 			struct ip_ct_gre_keymap *, t);
-	if (!km) {
-		READ_UNLOCK(&ip_ct_gre_lock);
-		return 0;
-	}
-
-	key = km->tuple.src.u.gre.key;
+	if (km)
+		key = km->tuple.src.u.gre.key;
 	READ_UNLOCK(&ip_ct_gre_lock);
+	
+	DEBUGP("lookup src key 0x%x up key for ", key);
+	DUMP_TUPLE_GRE(t);
 
 	return key;
 }
@@ -101,8 +100,13 @@
 ip_ct_gre_keymap_add(struct ip_conntrack *ct,
 		     struct ip_conntrack_tuple *t, int reply)
 {
-	struct ip_ct_gre_keymap *km;
+	struct ip_ct_gre_keymap *km, *old;
 
+	if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
+		DEBUGP("refusing to add GRE keymap to non-pptp session\n");
+		return -1;
+	}
+
 	km = kmalloc(sizeof(*km), GFP_ATOMIC);
 	if (!km)
 		return -1;
@@ -112,11 +116,42 @@
 
 	memcpy(&km->tuple, t, sizeof(*t));
 
-	if (!reply)
-		ct->proto.gre.keymap_orig = km;
-	else
-		ct->proto.gre.keymap_reply = km;
+	if (!reply) {
+		if (ct->help.ct_pptp_info.keymap_orig) {
+			kfree(km);
 
+			/* check whether it's a retransmission */
+			old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
+					struct ip_ct_gre_keymap *, t);
+			if (old == ct->help.ct_pptp_info.keymap_orig) {
+				DEBUGP("retransmission\n");
+				return 0;
+			}
+
+			DEBUGP("trying to override keymap_orig for ct %p\n",
+				ct);
+			return -2;
+		}
+		ct->help.ct_pptp_info.keymap_orig = km;
+	} else {
+		if (ct->help.ct_pptp_info.keymap_reply) {
+			kfree(km);
+
+			/* check whether it's a retransmission */
+			old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
+					struct ip_ct_gre_keymap *, t);
+			if (old == ct->help.ct_pptp_info.keymap_reply) {
+				DEBUGP("retransmission\n");
+				return 0;
+			}
+
+			DEBUGP("trying to override keymap_reply for ct %p\n",
+				ct);
+			return -2;
+		}
+		ct->help.ct_pptp_info.keymap_reply = km;
+	}
+
 	DEBUGP("adding new entry %p: ", km);
 	DUMP_TUPLE_GRE(&km->tuple);
 
@@ -127,34 +162,30 @@
 	return 0;
 }
 
-/* change the tuple of a keymap entry (used by nat helper) */
-void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
-			     struct ip_conntrack_tuple *t)
-{
-	DEBUGP("changing entry %p to: ", km);
-	DUMP_TUPLE_GRE(t);
-
-	WRITE_LOCK(&ip_ct_gre_lock);
-	memcpy(&km->tuple, t, sizeof(km->tuple));
-	WRITE_UNLOCK(&ip_ct_gre_lock);
-}
-
 /* destroy the keymap entries associated with specified master ct */
 void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct)
 {
 	DEBUGP("entering for ct %p\n", ct);
+
+	if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
+		DEBUGP("refusing to destroy GRE keymap to non-pptp session\n");
+		return;
+	}
+
 	WRITE_LOCK(&ip_ct_gre_lock);
-	if (ct->proto.gre.keymap_orig) {
-		DEBUGP("removing %p from list\n", ct->proto.gre.keymap_orig);
-		list_del(&ct->proto.gre.keymap_orig->list);
-		kfree(ct->proto.gre.keymap_orig);
-		ct->proto.gre.keymap_orig = NULL;
+	if (ct->help.ct_pptp_info.keymap_orig) {
+		DEBUGP("removing %p from list\n", 
+			ct->help.ct_pptp_info.keymap_orig);
+		list_del(&ct->help.ct_pptp_info.keymap_orig->list);
+		kfree(ct->help.ct_pptp_info.keymap_orig);
+		ct->help.ct_pptp_info.keymap_orig = NULL;
 	}
-	if (ct->proto.gre.keymap_reply) {
-		DEBUGP("removing %p from list\n", ct->proto.gre.keymap_reply);
-		list_del(&ct->proto.gre.keymap_reply->list);
-		kfree(ct->proto.gre.keymap_reply);
-		ct->proto.gre.keymap_reply = NULL;
+	if (ct->help.ct_pptp_info.keymap_reply) {
+		DEBUGP("removing %p from list\n",
+			ct->help.ct_pptp_info.keymap_reply);
+		list_del(&ct->help.ct_pptp_info.keymap_reply->list);
+		kfree(ct->help.ct_pptp_info.keymap_reply);
+		ct->help.ct_pptp_info.keymap_reply = NULL;
 	}
 	WRITE_UNLOCK(&ip_ct_gre_lock);
 }
@@ -271,9 +302,6 @@
 	ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
 	ct->proto.gre.timeout = GRE_TIMEOUT;
 
-	ct->proto.gre.keymap_orig = NULL;
-	ct->proto.gre.keymap_reply = NULL;
-
 	return 1;
 }
 
@@ -281,9 +309,13 @@
  * and is about to be deleted from memory */
 static void gre_destroy(struct ip_conntrack *ct)
 {
+	struct ip_conntrack *master = ct->master;
 	DEBUGP(" entering\n");
 
-	ip_ct_gre_keymap_destroy(ct);
+	if (!master)
+		DEBUGP("no master !?!\n");
+	else
+		ip_ct_gre_keymap_destroy(master);
 }
 
 /* protocol helper struct */
@@ -331,7 +363,6 @@
 }
 
 EXPORT_SYMBOL(ip_ct_gre_keymap_add);
-EXPORT_SYMBOL(ip_ct_gre_keymap_change);
 EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
 
 module_init(init);

Modified: trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_pptp.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_pptp.c	2005-07-04 15:35:34 UTC (rev 4092)
+++ trunk/patch-o-matic-ng/patchlets/pptp-conntrack-nat/linux-2.6.11/net/ipv4/netfilter/ip_nat_pptp.c	2005-07-04 18:44:44 UTC (rev 4093)
@@ -45,6 +45,7 @@
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
 #include <linux/netfilter_ipv4/ip_nat_pptp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
 #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
@@ -56,7 +57,7 @@
 MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
 
 
-#if 0
+#if 1
 #include "ip_conntrack_pptp_priv.h"
 #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
 				       __FUNCTION__, ## args)
@@ -64,101 +65,67 @@
 #define DEBUGP(format, args...)
 #endif
 
-static void
-pptp_nat_expected(struct sk_buff **pskb,
-		  unsigned int hooknum,
-		  struct ip_conntrack *ct,
-		  struct ip_nat_info *info)
+static void pptp_nat_expected(struct ip_conntrack *ct,
+			      struct ip_conntrack_expect *exp)
 {
-	struct ip_conntrack *master = master_ct(ct);
-	struct ip_nat_range range;
+	struct ip_conntrack *master = ct->master;
+	struct ip_conntrack_expect *other_exp;
+	struct ip_conntrack_tuple t;
 	struct ip_ct_pptp_master *ct_pptp_info;
 	struct ip_nat_pptp *nat_pptp_info;
-	u_int32_t newip, newcid;
 
-	IP_NF_ASSERT(info);
-	IP_NF_ASSERT(master);
-	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
-
-	DEBUGP("we have a connection!\n");
-
-	LOCK_BH(&ip_pptp_lock);
 	ct_pptp_info = &master->help.ct_pptp_info;
 	nat_pptp_info = &master->nat.help.nat_pptp_info;
 
-	/* need to alter GRE tuple because conntrack expectfn() used 'wrong'
-	 * (unmanipulated) values */
-	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
-		DEBUGP("completing tuples with NAT info \n");
-		/* we can do this, since we're unconfirmed */
-		if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
-			htons(ct_pptp_info->pac_call_id)) {	
-			/* assume PNS->PAC */
-			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
-				htons(nat_pptp_info->pns_call_id);
-			ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
-				htons(nat_pptp_info->pns_call_id);
-			newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
-			newcid = htons(nat_pptp_info->pac_call_id);
-		} else {
-			/* assume PAC->PNS */
-			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
-				htons(nat_pptp_info->pac_call_id);
-			ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
-				htons(nat_pptp_info->pac_call_id);
-			newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-			newcid = htons(nat_pptp_info->pns_call_id);
-		}
+	/* And here goes the grand finale of corrosion... */
+
+	if (exp->dir == IP_CT_DIR_ORIGINAL) {
+		DEBUGP("we are PNS->PAC\n");
+		/* therefore, build tuple for PAC->PNS */
+		t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
+		t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id);
+		t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+		t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id);
+		t.dst.protonum = IPPROTO_GRE;
 	} else {
-		if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
-			htons(ct_pptp_info->pac_call_id)) {	
-			/* assume PNS->PAC */
-			newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
-			newcid = htons(ct_pptp_info->pns_call_id);
-		}
-		else {
-			/* assume PAC->PNS */
-			newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
-			newcid = htons(ct_pptp_info->pac_call_id);
-		}
+		DEBUGP("we are PAC->PNS\n");
+		/* build tuple for PNS->PAC */
+		t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+		t.src.u.gre.key = 
+			htons(master->nat.help.nat_pptp_info.pns_call_id);
+		t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+		t.dst.u.gre.key = 
+			htons(master->nat.help.nat_pptp_info.pac_call_id);
+		t.dst.protonum = IPPROTO_GRE;
 	}
 
-	range.flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
-	range.min_ip = range.max_ip = newip;
-	range.min = range.max = 
-		((union ip_conntrack_manip_proto ) { newcid }); 
-	DEBUGP("change ip to %u.%u.%u.%u\n", 
-		NIPQUAD(newip));
-	DEBUGP("change key to 0x%x\n", ntohs(newcid));
-	ip_nat_setup_info(ct, &range, hooknum);
+	DEBUGP("trying to unexpect other dir: ");
+	DUMP_TUPLE(&t);
+	other_exp = __ip_conntrack_exp_find(&t);
+	if (other_exp) {
+		ip_conntrack_unexpect_related(other_exp);
+		DEBUGP("success\n");
+	} else {
+		DEBUGP("not found!\n");
+	}
 
-	UNLOCK_BH(&ip_pptp_lock);
+	ip_nat_follow_master(ct, exp);
 }
 
 /* outbound packets == from PNS to PAC */
-static inline unsigned int
+static int
 pptp_outbound_pkt(struct sk_buff **pskb,
 		  struct ip_conntrack *ct,
 		  enum ip_conntrack_info ctinfo,
-		  struct ip_conntrack_expect *exp)
+		  struct PptpControlHeader *ctlh,
+		  union pptp_ctrl_union *pptpReq)
 
 {
-	struct iphdr *iph = (*pskb)->nh.iph;
-	struct tcphdr *tcph = (void *) iph + iph->ihl*4;
-	struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
-					((void *)tcph + tcph->doff*4);
-
-	struct PptpControlHeader *ctlh;
-	union pptp_ctrl_union *pptpReq;
 	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;
 
 	u_int16_t msg, *cid = NULL, new_callid;
 
-	/* FIXME: size checks !!! */
-	ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
-	pptpReq = (void *) ((void *) ctlh + sizeof(*ctlh));
-
 	new_callid = htons(ct_pptp_info->pns_call_id);
 	
 	switch (msg = ntohs(ctlh->messageType)) {
@@ -211,115 +178,114 @@
 		ntohs(*cid), ntohs(new_callid));
 
 	/* mangle packet */
-	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
-					(void *)cid - (void *)pptph,
+	if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+		(void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
 				 	sizeof(new_callid), 
 					(char *)&new_callid,
-				 	sizeof(new_callid));
+				 	sizeof(new_callid)) == 0)
+		return NF_DROP;
+
+	return NF_ACCEPT;
 }
 
+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(nat_pptp_info->pac_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;
+}
+
 /* inbound packets == from PAC to PNS */
-static inline unsigned int
+static int
 pptp_inbound_pkt(struct sk_buff **pskb,
 		 struct ip_conntrack *ct,
 		 enum ip_conntrack_info ctinfo,
-		 struct ip_conntrack_expect *oldexp)
+		 struct PptpControlHeader *ctlh,
+		 union pptp_ctrl_union *pptpReq)
 {
-	struct iphdr *iph = (*pskb)->nh.iph;
-	struct tcphdr *tcph = (void *) iph + iph->ihl*4;
-	struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
-					((void *)tcph + tcph->doff*4);
-
-	struct PptpControlHeader *ctlh;
-	union pptp_ctrl_union *pptpReq;
-	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;
-
 	u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
-	u_int32_t old_dst_ip;
 
-	struct ip_conntrack_tuple t, inv_t;
-	struct ip_conntrack_tuple *orig_t, *reply_t;
 	int ret = NF_ACCEPT, rv;
 
-	/* FIXME: size checks !!! */
-	ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
-	pptpReq = (void *) ((void *) ctlh + sizeof(*ctlh));
-
 	new_pcid = htons(nat_pptp_info->pns_call_id);
 
 	switch (msg = ntohs(ctlh->messageType)) {
 	case PPTP_OUT_CALL_REPLY:
 		pcid = &pptpReq->ocack.peersCallID;	
 		cid = &pptpReq->ocack.callID;
-		if (!oldexp) {
-			DEBUGP("outcall but no expectation\n");
-			break;
-		}
-		old_dst_ip = oldexp->tuple.dst.ip;
-		t = oldexp->tuple;
-		invert_tuplepr(&inv_t, &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;
-		if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
-			/* expectation for PNS->PAC direction */
-			t.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
-			t.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);
-		} else {
-			/* expectation for PAC->PNS direction */
-			t.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
-			t.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(oldexp)) {
-			DEBUGP("successfully changed expect\n");
-		} else {
-			DEBUGP("can't change expect\n");
-			ret = NF_DROP;
-			break;
-		}
-		if (ct->proto.gre.keymap_orig)
-			ip_ct_gre_keymap_change(ct->proto.gre.keymap_orig,
-						&t);
-		if (ct->proto.gre.keymap_reply)
-			ip_ct_gre_keymap_change(ct->proto.gre.keymap_reply, 
-						&inv_t);
 		break;
 	case PPTP_IN_CALL_CONNECT:
 		pcid = &pptpReq->iccon.peersCallID;
-		if (!oldexp)
-			break;
-		old_dst_ip = oldexp->tuple.dst.ip;
-		t = oldexp->tuple;
-
-		/* alter expectation, no need for callID */
-		if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
-			/* expectation for PNS->PAC direction */
-			t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
-		} else {
-			/* expectation for PAC->PNS direction */
-			t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
-		}
-
-		if (!ip_conntrack_expect_related(oldexp)) {
-			DEBUGP("successfully changed expect\n");
-		} else {
-			DEBUGP("can't change expect\n");
-			ret = NF_DROP;
-		}
 		break;
 	case PPTP_IN_CALL_REQUEST:
 		/* only need to nat in case PAC is behind NAT box */
@@ -355,7 +321,7 @@
 		ntohs(*pcid), ntohs(new_pcid));
 	
 	rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
-				      (void *)pcid - (void *)pptph,
+				      (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
 				      sizeof(new_pcid), (char *)&new_pcid, 
 				      sizeof(new_pcid));
 	if (rv != NF_ACCEPT) 
@@ -366,7 +332,7 @@
 		DEBUGP("altering call id from 0x%04x to 0x%04x\n",
 			ntohs(*cid), ntohs(new_cid));
 		rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
-					      (void *)cid - (void *)pptph, 
+					      (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), 
 					      sizeof(new_cid),
 					      (char *)&new_cid, 
 					      sizeof(new_cid));
@@ -383,75 +349,22 @@
 }
 
 
-static unsigned int ip_nat_pptp(struct sk_buff **pskb,
-				enum ip_conntrack_info ctinfo,
-				struct ip_conntrack_expect *exp,
-				)
-{
-	struct iphdr *iph = (*pskb)->nh.iph;
-	struct tcphdr *tcph = (void *) iph + iph->ihl*4;
-	unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
-	struct pptp_pkt_hdr *pptph;
-
-	int dir;
-#if 0
-	DEBUGP("entering\n");
-
-	/* Only mangle things once: DST for original direction
-	   and SRC for reply direction. */
-	dir = CTINFO2DIR(ctinfo);
-	if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
-	     && dir == IP_CT_DIR_ORIGINAL)
-	      || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
-		  && dir == IP_CT_DIR_REPLY))) {
-		DEBUGP("Not touching dir %s at hook %s\n",
-		       dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-		       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-		       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-		       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
-		       : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
-		return NF_ACCEPT;
-	}
-
-	/* if packet is too small, just skip it */
-	if (datalen < sizeof(struct pptp_pkt_hdr)+
-		      sizeof(struct PptpControlHeader)) {
-		DEBUGP("pptp packet too short\n");
-		return NF_ACCEPT;	
-	}
-
-	pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
-
-	/* if it's not a control message, we can't handle it */
-	if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
-	    ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
-		DEBUGP("not a pptp control packet\n");
-		return NF_ACCEPT;
-	}
-#endif
-	LOCK_BH(&ip_pptp_lock);
-
-	if (dir == IP_CT_DIR_ORIGINAL) {
-		/* reuqests sent by client to server (PNS->PAC) */
-		pptp_outbound_pkt(pskb, ct, ctinfo, exp);
-	} else {
-		/* response from the server to the client (PAC->PNS) */
-		pptp_inbound_pkt(pskb, ct, ctinfo, exp);
-	}
-
-	UNLOCK_BH(&ip_pptp_lock);
-
-	return NF_ACCEPT;
-}
-  
 static int __init init(void)
 {
 	DEBUGP("%s: registering NAT helper\n", __FILE__);
 
-	BUG_ON(ip_nat_pptp_hook);
+	BUG_ON(ip_nat_pptp_hook_outbound);
+	ip_nat_pptp_hook_outbound = &pptp_outbound_pkt;
 
-	ip_nat_pptp_hook = ip_nat_pptp;
+	BUG_ON(ip_nat_pptp_hook_inbound);
+	ip_nat_pptp_hook_inbound = &pptp_inbound_pkt;
 
+	BUG_ON(ip_nat_pptp_hook_exp_gre);
+	ip_nat_pptp_hook_exp_gre = &pptp_exp_gre;
+
+	BUG_ON(ip_nat_pptp_hook_expectfn);
+	ip_nat_pptp_hook_expectfn = &pptp_nat_expected;
+
 	printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
 	return 0;
 }
@@ -460,7 +373,11 @@
 {
 	DEBUGP("cleanup_module\n" );
 
-	ip_nat_pptp_hook = NULL;
+	ip_nat_pptp_hook_expectfn = NULL;
+	ip_nat_pptp_hook_exp_gre = NULL;
+	ip_nat_pptp_hook_inbound = NULL;
+	ip_nat_pptp_hook_outbound = NULL;
+
 	/* Make sure noone calls it, meanwhile */
 	synchronize_net();
 




More information about the netfilter-cvslog mailing list