diff options
5 files changed, 125 insertions, 2563 deletions
diff --git a/target/linux/generic-2.4/patches/603-netfilter_nat_pptp.patch b/target/linux/generic-2.4/patches/603-netfilter_nat_pptp.patch deleted file mode 100644 index 7e54a7027..000000000 --- a/target/linux/generic-2.4/patches/603-netfilter_nat_pptp.patch +++ /dev/null @@ -1,2406 +0,0 @@ ---- a/include/linux/netfilter_ipv4/ip_conntrack.h -+++ b/include/linux/netfilter_ipv4/ip_conntrack.h -@@ -50,16 +50,19 @@ enum ip_conntrack_status { -  - #include <linux/netfilter_ipv4/ip_conntrack_tcp.h> - #include <linux/netfilter_ipv4/ip_conntrack_icmp.h> -+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> -  - /* per conntrack: protocol private data */ - union ip_conntrack_proto { - 	/* insert conntrack proto private data here */ - 	struct ip_ct_tcp tcp; - 	struct ip_ct_icmp icmp; -+	struct ip_ct_gre gre; - }; -  - union ip_conntrack_expect_proto { - 	/* insert expect proto private data here */ -+	struct ip_ct_gre_expect gre; - }; -  - /* Add protocol helper include file here */ -@@ -67,6 +70,7 @@ union ip_conntrack_expect_proto { -  - #include <linux/netfilter_ipv4/ip_conntrack_ftp.h> - #include <linux/netfilter_ipv4/ip_conntrack_irc.h> -+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h> -  - /* per expectation: application helper private data */ - union ip_conntrack_expect_help { -@@ -74,6 +78,7 @@ union ip_conntrack_expect_help { - 	struct ip_ct_amanda_expect exp_amanda_info; - 	struct ip_ct_ftp_expect exp_ftp_info; - 	struct ip_ct_irc_expect exp_irc_info; -+	struct ip_ct_pptp_expect exp_pptp_info; -  - #ifdef CONFIG_IP_NF_NAT_NEEDED - 	union { -@@ -87,14 +92,17 @@ union ip_conntrack_help { - 	/* insert conntrack helper private data (master) here */ - 	struct ip_ct_ftp_master ct_ftp_info; - 	struct ip_ct_irc_master ct_irc_info; -+	struct ip_ct_pptp_master ct_pptp_info; - }; -  - #ifdef CONFIG_IP_NF_NAT_NEEDED - #include <linux/netfilter_ipv4/ip_nat.h> -+#include <linux/netfilter_ipv4/ip_nat_pptp.h> -  - /* per conntrack: nat application helper private data */ - union ip_conntrack_nat_help { - 	/* insert nat helper private data here */ -+	struct ip_nat_pptp nat_pptp_info; - }; - #endif -  ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h -@@ -0,0 +1,313 @@ -+/* PPTP constants and structs */ -+#ifndef _CONNTRACK_PPTP_H -+#define _CONNTRACK_PPTP_H -+ -+/* state of the control session */ -+enum pptp_ctrlsess_state { -+	PPTP_SESSION_NONE,			/* no session present */ -+	PPTP_SESSION_ERROR,			/* some session error */ -+	PPTP_SESSION_STOPREQ,			/* stop_sess request seen */ -+	PPTP_SESSION_REQUESTED,			/* start_sess request seen */ -+	PPTP_SESSION_CONFIRMED,			/* session established */ -+}; -+ -+/* state of the call inside the control session */ -+enum pptp_ctrlcall_state { -+	PPTP_CALL_NONE, -+	PPTP_CALL_ERROR, -+	PPTP_CALL_OUT_REQ, -+	PPTP_CALL_OUT_CONF, -+	PPTP_CALL_IN_REQ, -+	PPTP_CALL_IN_REP, -+	PPTP_CALL_IN_CONF, -+	PPTP_CALL_CLEAR_REQ, -+}; -+ -+ -+/* conntrack private data */ -+struct ip_ct_pptp_master { -+	enum pptp_ctrlsess_state sstate;	/* session state */ -+ -+	/* everything below is going to be per-expectation in newnat, -+	 * since there could be more than one call within one session */ -+	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 */ -+}; -+ -+/* conntrack_expect private member */ -+struct ip_ct_pptp_expect { -+	enum pptp_ctrlcall_state cstate; 	/* call state */ -+	u_int16_t pac_call_id;			/* call id of PAC */ -+	u_int16_t pns_call_id;			/* call id of PNS */ -+}; -+ -+ -+#ifdef __KERNEL__ -+ -+#include <linux/netfilter_ipv4/lockhelp.h> -+DECLARE_LOCK_EXTERN(ip_pptp_lock); -+ -+#define IP_CONNTR_PPTP		PPTP_CONTROL_PORT -+ -+union pptp_ctrl_union { -+                void				*rawreq; -+		struct PptpStartSessionRequest	*sreq; -+		struct PptpStartSessionReply	*srep; -+		struct PptpStopSessionRequest	*streq; -+		struct PptpStopSessionReply	*strep; -+                struct PptpOutCallRequest       *ocreq; -+                struct PptpOutCallReply         *ocack; -+                struct PptpInCallRequest        *icreq; -+                struct PptpInCallReply          *icack; -+                struct PptpInCallConnected      *iccon; -+		struct PptpClearCallRequest	*clrreq; -+                struct PptpCallDisconnectNotify *disc; -+                struct PptpWanErrorNotify       *wanerr; -+                struct PptpSetLinkInfo          *setlink; -+}; -+ -+ -+ -+#define PPTP_CONTROL_PORT	1723 -+ -+#define PPTP_PACKET_CONTROL	1 -+#define PPTP_PACKET_MGMT	2 -+ -+#define PPTP_MAGIC_COOKIE	0x1a2b3c4d -+ -+struct pptp_pkt_hdr { -+	__u16	packetLength; -+	__u16	packetType; -+	__u32	magicCookie; -+}; -+ -+/* PptpControlMessageType values */ -+#define PPTP_START_SESSION_REQUEST	1 -+#define PPTP_START_SESSION_REPLY	2 -+#define PPTP_STOP_SESSION_REQUEST	3 -+#define PPTP_STOP_SESSION_REPLY		4 -+#define PPTP_ECHO_REQUEST		5 -+#define PPTP_ECHO_REPLY			6 -+#define PPTP_OUT_CALL_REQUEST		7 -+#define PPTP_OUT_CALL_REPLY		8 -+#define PPTP_IN_CALL_REQUEST		9 -+#define PPTP_IN_CALL_REPLY		10 -+#define PPTP_IN_CALL_CONNECT		11 -+#define PPTP_CALL_CLEAR_REQUEST		12 -+#define PPTP_CALL_DISCONNECT_NOTIFY	13 -+#define PPTP_WAN_ERROR_NOTIFY		14 -+#define PPTP_SET_LINK_INFO		15 -+ -+#define PPTP_MSG_MAX			15 -+ -+/* PptpGeneralError values */ -+#define PPTP_ERROR_CODE_NONE		0 -+#define PPTP_NOT_CONNECTED		1 -+#define PPTP_BAD_FORMAT			2 -+#define PPTP_BAD_VALUE			3 -+#define PPTP_NO_RESOURCE		4 -+#define PPTP_BAD_CALLID			5 -+#define PPTP_REMOVE_DEVICE_ERROR	6 -+ -+struct PptpControlHeader { -+	__u16	messageType; -+	__u16	reserved; -+}; -+ -+/* FramingCapability Bitmap Values */ -+#define PPTP_FRAME_CAP_ASYNC		0x1 -+#define PPTP_FRAME_CAP_SYNC		0x2 -+ -+/* BearerCapability Bitmap Values */ -+#define PPTP_BEARER_CAP_ANALOG		0x1 -+#define PPTP_BEARER_CAP_DIGITAL		0x2 -+ -+struct PptpStartSessionRequest { -+	__u16	protocolVersion; -+	__u8	reserved1; -+	__u8	reserved2; -+	__u32	framingCapability; -+	__u32	bearerCapability; -+	__u16	maxChannels; -+	__u16	firmwareRevision; -+	__u8	hostName[64]; -+	__u8	vendorString[64]; -+}; -+ -+/* PptpStartSessionResultCode Values */ -+#define PPTP_START_OK			1 -+#define PPTP_START_GENERAL_ERROR	2 -+#define PPTP_START_ALREADY_CONNECTED	3 -+#define PPTP_START_NOT_AUTHORIZED	4 -+#define PPTP_START_UNKNOWN_PROTOCOL	5 -+ -+struct PptpStartSessionReply { -+	__u16	protocolVersion; -+	__u8	resultCode; -+	__u8	generalErrorCode; -+	__u32	framingCapability; -+	__u32	bearerCapability; -+	__u16	maxChannels; -+	__u16	firmwareRevision; -+	__u8	hostName[64]; -+	__u8	vendorString[64]; -+}; -+ -+/* PptpStopReasons */ -+#define PPTP_STOP_NONE			1 -+#define PPTP_STOP_PROTOCOL		2 -+#define PPTP_STOP_LOCAL_SHUTDOWN	3 -+ -+struct PptpStopSessionRequest { -+	__u8	reason; -+}; -+ -+/* PptpStopSessionResultCode */ -+#define PPTP_STOP_OK			1 -+#define PPTP_STOP_GENERAL_ERROR		2 -+ -+struct PptpStopSessionReply { -+	__u8	resultCode; -+	__u8	generalErrorCode; -+}; -+ -+struct PptpEchoRequest { -+	__u32 identNumber; -+}; -+ -+/* PptpEchoReplyResultCode */ -+#define PPTP_ECHO_OK			1 -+#define PPTP_ECHO_GENERAL_ERROR		2 -+ -+struct PptpEchoReply { -+	__u32	identNumber; -+	__u8	resultCode; -+	__u8	generalErrorCode; -+	__u16	reserved; -+}; -+ -+/* PptpFramingType */ -+#define PPTP_ASYNC_FRAMING		1 -+#define PPTP_SYNC_FRAMING		2 -+#define PPTP_DONT_CARE_FRAMING		3 -+ -+/* PptpCallBearerType */ -+#define PPTP_ANALOG_TYPE		1 -+#define PPTP_DIGITAL_TYPE		2 -+#define PPTP_DONT_CARE_BEARER_TYPE	3 -+ -+struct PptpOutCallRequest { -+	__u16	callID; -+	__u16	callSerialNumber; -+	__u32	minBPS; -+	__u32	maxBPS; -+	__u32	bearerType; -+	__u32	framingType; -+	__u16	packetWindow; -+	__u16	packetProcDelay; -+	__u16	reserved1; -+	__u16	phoneNumberLength; -+	__u16	reserved2; -+	__u8	phoneNumber[64]; -+	__u8	subAddress[64]; -+}; -+ -+/* PptpCallResultCode */ -+#define PPTP_OUTCALL_CONNECT		1 -+#define PPTP_OUTCALL_GENERAL_ERROR	2 -+#define PPTP_OUTCALL_NO_CARRIER		3 -+#define PPTP_OUTCALL_BUSY		4 -+#define PPTP_OUTCALL_NO_DIAL_TONE	5 -+#define PPTP_OUTCALL_TIMEOUT		6 -+#define PPTP_OUTCALL_DONT_ACCEPT	7 -+ -+struct PptpOutCallReply { -+	__u16	callID; -+	__u16	peersCallID; -+	__u8	resultCode; -+	__u8	generalErrorCode; -+	__u16	causeCode; -+	__u32	connectSpeed; -+	__u16	packetWindow; -+	__u16	packetProcDelay; -+	__u32	physChannelID; -+}; -+ -+struct PptpInCallRequest { -+	__u16	callID; -+	__u16	callSerialNumber; -+	__u32	callBearerType; -+	__u32	physChannelID; -+	__u16	dialedNumberLength; -+	__u16	dialingNumberLength; -+	__u8	dialedNumber[64]; -+	__u8	dialingNumber[64]; -+	__u8	subAddress[64]; -+}; -+ -+/* PptpInCallResultCode */ -+#define PPTP_INCALL_ACCEPT		1 -+#define PPTP_INCALL_GENERAL_ERROR	2 -+#define PPTP_INCALL_DONT_ACCEPT		3 -+ -+struct PptpInCallReply { -+	__u16	callID; -+	__u16	peersCallID; -+	__u8	resultCode; -+	__u8	generalErrorCode; -+	__u16	packetWindow; -+	__u16	packetProcDelay; -+	__u16	reserved; -+}; -+ -+struct PptpInCallConnected { -+	__u16	peersCallID; -+	__u16	reserved; -+	__u32	connectSpeed; -+	__u16	packetWindow; -+	__u16	packetProcDelay; -+	__u32	callFramingType; -+}; -+ -+struct PptpClearCallRequest { -+	__u16	callID; -+	__u16	reserved; -+}; -+ -+struct PptpCallDisconnectNotify { -+	__u16	callID; -+	__u8	resultCode; -+	__u8	generalErrorCode; -+	__u16	causeCode; -+	__u16	reserved; -+	__u8	callStatistics[128]; -+}; -+ -+struct PptpWanErrorNotify { -+	__u16	peersCallID; -+	__u16	reserved; -+	__u32	crcErrors; -+	__u32	framingErrors; -+	__u32	hardwareOverRuns; -+	__u32	bufferOverRuns; -+	__u32	timeoutErrors; -+	__u32	alignmentErrors; -+}; -+ -+struct PptpSetLinkInfo { -+	__u16	peersCallID; -+	__u16	reserved; -+	__u32	sendAccm; -+	__u32	recvAccm; -+}; -+ -+ -+struct pptp_priv_data { -+	__u16	call_id; -+	__u16	mcall_id; -+	__u16	pcall_id; -+}; -+ -+#endif /* __KERNEL__ */ -+#endif /* _CONNTRACK_PPTP_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h -@@ -0,0 +1,123 @@ -+#ifndef _CONNTRACK_PROTO_GRE_H -+#define _CONNTRACK_PROTO_GRE_H -+#include <asm/byteorder.h> -+ -+/* GRE PROTOCOL HEADER */ -+ -+/* GRE Version field */ -+#define GRE_VERSION_1701	0x0 -+#define GRE_VERSION_PPTP	0x1 -+ -+/* GRE Protocol field */ -+#define GRE_PROTOCOL_PPTP	0x880B -+ -+/* GRE Flags */ -+#define GRE_FLAG_C		0x80 -+#define GRE_FLAG_R		0x40 -+#define GRE_FLAG_K		0x20 -+#define GRE_FLAG_S		0x10 -+#define GRE_FLAG_A		0x80 -+ -+#define GRE_IS_C(f)	((f)&GRE_FLAG_C) -+#define GRE_IS_R(f)	((f)&GRE_FLAG_R) -+#define GRE_IS_K(f)	((f)&GRE_FLAG_K) -+#define GRE_IS_S(f)	((f)&GRE_FLAG_S) -+#define GRE_IS_A(f)	((f)&GRE_FLAG_A) -+ -+/* GRE is a mess: Four different standards */ -+struct gre_hdr { -+#if defined(__LITTLE_ENDIAN_BITFIELD) -+	__u16	rec:3, -+		srr:1, -+		seq:1, -+		key:1, -+		routing:1, -+		csum:1, -+		version:3, -+		reserved:4, -+		ack:1; -+#elif defined(__BIG_ENDIAN_BITFIELD) -+	__u16	csum:1, -+		routing:1, -+		key:1, -+		seq:1, -+		srr:1, -+		rec:3, -+		ack:1, -+		reserved:4, -+		version:3; -+#else -+#error "Adjust your <asm/byteorder.h> defines" -+#endif -+	__u16	protocol; -+}; -+ -+/* modified GRE header for PPTP */ -+struct gre_hdr_pptp { -+	__u8  flags;		/* bitfield */ -+	__u8  version;		/* should be GRE_VERSION_PPTP */ -+	__u16 protocol;		/* should be GRE_PROTOCOL_PPTP */ -+	__u16 payload_len;	/* size of ppp payload, not inc. gre header */ -+	__u16 call_id;		/* peer's call_id for this session */ -+	__u32 seq;		/* sequence number.  Present if S==1 */ -+	__u32 ack;		/* seq number of highest packet recieved by */ -+				/*  sender in this session */ -+}; -+ -+ -+/* this is part of ip_conntrack */ -+struct ip_ct_gre { -+	unsigned int stream_timeout; -+	unsigned int timeout; -+}; -+ -+/* this is part of ip_conntrack_expect */ -+struct ip_ct_gre_expect { -+	struct ip_ct_gre_keymap *keymap_orig, *keymap_reply; -+}; -+ -+#ifdef __KERNEL__ -+struct ip_conntrack_expect; -+ -+/* structure for original <-> reply keymap */ -+struct ip_ct_gre_keymap { -+	struct list_head list; -+ -+	struct ip_conntrack_tuple tuple; -+}; -+ -+ -+/* add new tuple->key_reply pair to keymap */ -+int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp, -+			 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_expect *exp); -+ -+ -+/* get pointer to gre key, if present */ -+static inline u_int32_t *gre_key(struct gre_hdr *greh) -+{ -+	if (!greh->key) -+		return NULL; -+	if (greh->csum || greh->routing) -+		return (u_int32_t *) (greh+sizeof(*greh)+4); -+	return (u_int32_t *) (greh+sizeof(*greh)); -+} -+ -+/* get pointer ot gre csum, if present */ -+static inline u_int16_t *gre_csum(struct gre_hdr *greh) -+{ -+	if (!greh->csum) -+		return NULL; -+	return (u_int16_t *) (greh+sizeof(*greh)); -+} -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _CONNTRACK_PROTO_GRE_H */ ---- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h -+++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h -@@ -14,7 +14,7 @@ - union ip_conntrack_manip_proto - { - 	/* Add other protocols here. */ --	u_int16_t all; -+	u_int32_t all; -  - 	struct { - 		u_int16_t port; -@@ -25,6 +25,9 @@ union ip_conntrack_manip_proto - 	struct { - 		u_int16_t id; - 	} icmp; -+	struct { -+		u_int32_t key; -+	} gre; - }; -  - /* The manipulable part of the tuple. */ -@@ -44,7 +47,7 @@ struct ip_conntrack_tuple - 		u_int32_t ip; - 		union { - 			/* Add other protocols here. */ --			u_int16_t all; -+			u_int32_t all; -  - 			struct { - 				u_int16_t port; -@@ -55,6 +58,9 @@ struct ip_conntrack_tuple - 			struct { - 				u_int8_t type, code; - 			} icmp; -+			struct { -+				u_int32_t key; -+			} gre; - 		} u; -  - 		/* The protocol. */ -@@ -80,10 +86,16 @@ enum ip_conntrack_dir - #ifdef __KERNEL__ -  - #define DUMP_TUPLE(tp)						\ --DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n",	\ -+DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",	\ -        (tp), (tp)->dst.protonum,				\ --       NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all),		\ --       NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all)) -+       NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all),		\ -+       NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all)) -+ -+#define DUMP_TUPLE_RAW(x) 						\ -+	DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\ -+	(x), (x)->dst.protonum,						\ -+	NIPQUAD((x)->src.ip), ntohl((x)->src.u.all), 			\ -+	NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all)) -  - #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) -  ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_nat_pptp.h -@@ -0,0 +1,11 @@ -+/* PPTP constants and structs */ -+#ifndef _NAT_PPTP_H -+#define _NAT_PPTP_H -+ -+/* conntrack private data */ -+struct ip_nat_pptp { -+	u_int16_t pns_call_id;		/* NAT'ed PNS call id */ -+	u_int16_t pac_call_id;		/* NAT'ed PAC call id */ -+}; -+ -+#endif /* _NAT_PPTP_H */ ---- a/net/ipv4/netfilter/Config.in -+++ b/net/ipv4/netfilter/Config.in -@@ -10,6 +10,8 @@ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; -   dep_tristate '  Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK -   dep_tristate '  TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK -   dep_tristate '  IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK -+  dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK -+  dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE - fi -  - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -@@ -63,6 +65,20 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ];  -       define_bool CONFIG_IP_NF_NAT_NEEDED y -       dep_tristate '    MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT -       dep_tristate '    REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT -+      if [ "$CONFIG_IP_NF_PPTP" = "m" ]; then -+        define_tristate CONFIG_IP_NF_NAT_PPTP m -+      else -+        if [ "$CONFIG_IP_NF_PPTP" = "y" ]; then -+          define_tristate CONFIG_IP_NF_NAT_PPTP $CONFIG_IP_NF_NAT -+        fi -+      fi -+      if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "m" ]; then -+        define_tristate CONFIG_IP_NF_NAT_PROTO_GRE m -+      else -+        if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "y" ]; then -+          define_tristate CONFIG_IP_NF_NAT_PROTO_GRE $CONFIG_IP_NF_NAT -+        fi -+      fi -       if [ "$CONFIG_IP_NF_AMANDA" = "m" ]; then -         define_tristate CONFIG_IP_NF_NAT_AMANDA m -       else ---- a/net/ipv4/netfilter/ip_conntrack_core.c -+++ b/net/ipv4/netfilter/ip_conntrack_core.c -@@ -143,6 +143,8 @@ ip_ct_get_tuple(const struct iphdr *iph, - 	tuple->dst.ip = iph->daddr; - 	tuple->dst.protonum = iph->protocol; -  -+	tuple->src.u.all = tuple->dst.u.all = 0; -+ - 	ret = protocol->pkt_to_tuple((u_int32_t *)iph + iph->ihl, - 				     len - 4*iph->ihl, - 				     tuple); -@@ -158,6 +160,8 @@ invert_tuple(struct ip_conntrack_tuple * - 	inverse->dst.ip = orig->src.ip; - 	inverse->dst.protonum = orig->dst.protonum; -  -+	inverse->src.u.all = inverse->dst.u.all = 0; -+ - 	return protocol->invert_tuple(inverse, orig); - } -  -@@ -970,8 +974,8 @@ int ip_conntrack_expect_related(struct i - 	 * so there is no need to use the tuple lock too */ -  - 	DEBUGP("ip_conntrack_expect_related %p\n", related_to); --	DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple); --	DEBUGP("mask:  "); DUMP_TUPLE(&expect->mask); -+	DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple); -+	DEBUGP("mask:  "); DUMP_TUPLE_RAW(&expect->mask); -  - 	old = LIST_FIND(&ip_conntrack_expect_list, resent_expect, - 		        struct ip_conntrack_expect *, &expect->tuple,  -@@ -1089,15 +1093,14 @@ int ip_conntrack_change_expect(struct ip -  - 	MUST_BE_READ_LOCKED(&ip_conntrack_lock); - 	WRITE_LOCK(&ip_conntrack_expect_tuple_lock); -- - 	DEBUGP("change_expect:\n"); --	DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple); --	DEBUGP("exp mask:  "); DUMP_TUPLE(&expect->mask); --	DEBUGP("newtuple:  "); DUMP_TUPLE(newtuple); -+	DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple); -+	DEBUGP("exp mask:  "); DUMP_TUPLE_RAW(&expect->mask); -+	DEBUGP("newtuple:  "); DUMP_TUPLE_RAW(newtuple); - 	if (expect->ct_tuple.dst.protonum == 0) { - 		/* Never seen before */ - 		DEBUGP("change expect: never seen before\n"); --		if (!ip_ct_tuple_equal(&expect->tuple, newtuple)  -+		if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask) - 		    && LIST_FIND(&ip_conntrack_expect_list, expect_clash, - 			         struct ip_conntrack_expect *, newtuple, &expect->mask)) { - 			/* Force NAT to find an unused tuple */ ---- /dev/null -+++ b/net/ipv4/netfilter/ip_conntrack_pptp_priv.h -@@ -0,0 +1,24 @@ -+#ifndef _IP_CT_PPTP_PRIV_H -+#define _IP_CT_PPTP_PRIV_H -+ -+/* PptpControlMessageType names */ -+static const char *strMName[] = { -+	"UNKNOWN_MESSAGE", -+	"START_SESSION_REQUEST", -+	"START_SESSION_REPLY", -+	"STOP_SESSION_REQUEST", -+	"STOP_SESSION_REPLY", -+	"ECHO_REQUEST", -+	"ECHO_REPLY", -+	"OUT_CALL_REQUEST", -+	"OUT_CALL_REPLY", -+	"IN_CALL_REQUEST", -+	"IN_CALL_REPLY", -+	"IN_CALL_CONNECT", -+	"CALL_CLEAR_REQUEST", -+	"CALL_DISCONNECT_NOTIFY", -+	"WAN_ERROR_NOTIFY", -+	"SET_LINK_INFO" -+}; -+ -+#endif ---- /dev/null -+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c -@@ -0,0 +1,333 @@ -+/* -+ * ip_conntrack_proto_gre.c - Version 1.2  -+ * -+ * Connection tracking protocol helper module for GRE. -+ * -+ * GRE is a generic encapsulation protocol, which is generally not very -+ * suited for NAT, as it has no protocol-specific part as port numbers. -+ * -+ * It has an optional key field, which may help us distinguishing two  -+ * connections between the same two hosts. -+ * -+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784  -+ * -+ * PPTP is built on top of a modified version of GRE, and has a mandatory -+ * field called "CallID", which serves us for the same purpose as the key -+ * field in plain GRE. -+ * -+ * Documentation about PPTP can be found in RFC 2637 -+ * -+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org> -+ * -+ * Development of this code funded by Astaro AG (http://www.astaro.com/) -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/timer.h> -+#include <linux/netfilter.h> -+#include <linux/ip.h> -+#include <linux/in.h> -+#include <linux/list.h> -+ -+#include <linux/netfilter_ipv4/lockhelp.h> -+ -+DECLARE_RWLOCK(ip_ct_gre_lock); -+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock) -+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock) -+ -+#include <linux/netfilter_ipv4/listhelp.h> -+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> -+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> -+#include <linux/netfilter_ipv4/ip_conntrack_core.h> -+ -+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> -+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h> -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); -+MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE"); -+ -+/* shamelessly stolen from ip_conntrack_proto_udp.c */ -+#define GRE_TIMEOUT		(30*HZ) -+#define GRE_STREAM_TIMEOUT	(180*HZ) -+ -+#if 0 -+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \ -+		                       ": " format, ## args) -+#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \ -+			NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \ -+			NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key)) -+#else -+#define DEBUGP(x, args...) -+#define DUMP_TUPLE_GRE(x) -+#endif -+				 -+/* GRE KEYMAP HANDLING FUNCTIONS */ -+static LIST_HEAD(gre_keymap_list); -+ -+static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km, -+				const struct ip_conntrack_tuple *t) -+{ -+	return ((km->tuple.src.ip == t->src.ip) && -+		(km->tuple.dst.ip == t->dst.ip) && -+	        (km->tuple.dst.protonum == t->dst.protonum) && -+	        (km->tuple.dst.u.all == t->dst.u.all)); -+} -+ -+/* look up the source key for a given tuple */ -+static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t) -+{ -+	struct ip_ct_gre_keymap *km; -+	u_int32_t key; -+ -+	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; -+	READ_UNLOCK(&ip_ct_gre_lock); -+ -+	return key; -+} -+ -+/* add a single keymap entry, associate with specified expect */ -+int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp, -+			 struct ip_conntrack_tuple *t, int reply) -+{ -+	struct ip_ct_gre_keymap *km; -+ -+	km = kmalloc(sizeof(*km), GFP_ATOMIC); -+	if (!km) -+		return -1; -+ -+	/* initializing list head should be sufficient */ -+	memset(km, 0, sizeof(*km)); -+ -+	memcpy(&km->tuple, t, sizeof(*t)); -+ -+	if (!reply) -+		exp->proto.gre.keymap_orig = km; -+	else -+		exp->proto.gre.keymap_reply = km; -+ -+	DEBUGP("adding new entry %p: ", km); -+	DUMP_TUPLE_GRE(&km->tuple); -+ -+	WRITE_LOCK(&ip_ct_gre_lock); -+	list_append(&gre_keymap_list, km); -+	WRITE_UNLOCK(&ip_ct_gre_lock); -+ -+	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 expect */ -+void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp) -+{ -+	DEBUGP("entering for exp %p\n", exp); -+	WRITE_LOCK(&ip_ct_gre_lock); -+	if (exp->proto.gre.keymap_orig) { -+		DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig); -+		list_del(&exp->proto.gre.keymap_orig->list); -+		kfree(exp->proto.gre.keymap_orig); -+		exp->proto.gre.keymap_orig = NULL; -+	} -+	if (exp->proto.gre.keymap_reply) { -+		DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply); -+		list_del(&exp->proto.gre.keymap_reply->list); -+		kfree(exp->proto.gre.keymap_reply); -+		exp->proto.gre.keymap_reply = NULL; -+	} -+	WRITE_UNLOCK(&ip_ct_gre_lock); -+} -+ -+ -+/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ -+ -+/* invert gre part of tuple */ -+static int gre_invert_tuple(struct ip_conntrack_tuple *tuple, -+			    const struct ip_conntrack_tuple *orig) -+{ -+	tuple->dst.u.gre.key = orig->src.u.gre.key; -+	tuple->src.u.gre.key = orig->dst.u.gre.key; -+ -+	return 1; -+} -+ -+/* gre hdr info to tuple */ -+static int gre_pkt_to_tuple(const void *datah, size_t datalen, -+			    struct ip_conntrack_tuple *tuple) -+{ -+	struct gre_hdr *grehdr = (struct gre_hdr *) datah; -+	struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah; -+	u_int32_t srckey; -+ -+	/* core guarantees 8 protocol bytes, no need for size check */ -+ -+	switch (grehdr->version) { -+		case GRE_VERSION_1701: -+			if (!grehdr->key) { -+				DEBUGP("Can't track GRE without key\n"); -+				return 0; -+			} -+			tuple->dst.u.gre.key = *(gre_key(grehdr)); -+			break; -+ -+		case GRE_VERSION_PPTP: -+			if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { -+				DEBUGP("GRE_VERSION_PPTP but unknown proto\n"); -+				return 0; -+			} -+			tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id)); -+			break; -+ -+		default: -+			printk(KERN_WARNING "unknown GRE version %hu\n", -+				grehdr->version); -+			return 0; -+	} -+ -+	srckey = gre_keymap_lookup(tuple); -+ -+#if 0 -+	DEBUGP("found src key %x for tuple ", ntohl(srckey)); -+	DUMP_TUPLE_GRE(tuple); -+#endif -+	tuple->src.u.gre.key = srckey; -+ -+	return 1; -+} -+ -+/* print gre part of tuple */ -+static unsigned int gre_print_tuple(char *buffer, -+				    const struct ip_conntrack_tuple *tuple) -+{ -+	return sprintf(buffer, "srckey=0x%x dstkey=0x%x ",  -+			ntohl(tuple->src.u.gre.key), -+			ntohl(tuple->dst.u.gre.key)); -+} -+ -+/* print private data for conntrack */ -+static unsigned int gre_print_conntrack(char *buffer, -+					const struct ip_conntrack *ct) -+{ -+	return sprintf(buffer, "timeout=%u, stream_timeout=%u ", -+		       (ct->proto.gre.timeout / HZ), -+		       (ct->proto.gre.stream_timeout / HZ)); -+} -+ -+/* Returns verdict for packet, and may modify conntrack */ -+static int gre_packet(struct ip_conntrack *ct, -+		      struct iphdr *iph, size_t len, -+		      enum ip_conntrack_info conntrackinfo) -+{ -+	/* If we've seen traffic both ways, this is a GRE connection. -+	 * Extend timeout. */ -+	if (ct->status & IPS_SEEN_REPLY) { -+		ip_ct_refresh_acct(ct, ct->proto.gre.stream_timeout); -+		/* Also, more likely to be important, and not a probe. */ -+		set_bit(IPS_ASSURED_BIT, &ct->status); -+	} else -+		ip_ct_refresh_acct(ct, ct->proto.gre.timeout); -+	 -+	return NF_ACCEPT; -+} -+ -+/* Called when a new connection for this protocol found. */ -+static int gre_new(struct ip_conntrack *ct, -+		   struct iphdr *iph, size_t len) -+{  -+	DEBUGP(": "); -+	DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); -+ -+	/* initialize to sane value.  Ideally a conntrack helper -+	 * (e.g. in case of pptp) is increasing them */ -+	ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT; -+	ct->proto.gre.timeout = GRE_TIMEOUT; -+ -+	return 1; -+} -+ -+/* Called when a conntrack entry has already been removed from the hashes -+ * and is about to be deleted from memory */ -+static void gre_destroy(struct ip_conntrack *ct) -+{ -+	struct ip_conntrack_expect *master = ct->master; -+ -+	DEBUGP(" entering\n"); -+ -+	if (!master) { -+		DEBUGP("no master exp for ct %p\n", ct); -+		return; -+	} -+ -+	ip_ct_gre_keymap_destroy(master); -+} -+ -+/* protocol helper struct */ -+static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE, -+					    "gre",  -+					    gre_pkt_to_tuple, -+					    gre_invert_tuple, -+					    gre_print_tuple, -+					    gre_print_conntrack, -+					    gre_packet, -+					    gre_new, -+					    gre_destroy, -+					    NULL, -+					    THIS_MODULE }; -+ -+/* ip_conntrack_proto_gre initialization */ -+static int __init init(void) -+{ -+	int retcode; -+ -+	if ((retcode = ip_conntrack_protocol_register(&gre))) { -+                printk(KERN_ERR "Unable to register conntrack protocol " -+			        "helper for gre: %d\n",	retcode); -+		return -EIO; -+	} -+ -+	return 0; -+} -+ -+static void __exit fini(void) -+{ -+	struct list_head *pos, *n; -+ -+	/* delete all keymap entries */ -+	WRITE_LOCK(&ip_ct_gre_lock); -+	list_for_each_safe(pos, n, &gre_keymap_list) { -+		DEBUGP("deleting keymap %p at module unload time\n", pos); -+		list_del(pos); -+		kfree(pos); -+	} -+	WRITE_UNLOCK(&ip_ct_gre_lock); -+ -+	ip_conntrack_protocol_unregister(&gre);  -+} -+ -+EXPORT_SYMBOL(ip_ct_gre_keymap_add); -+EXPORT_SYMBOL(ip_ct_gre_keymap_change); -+EXPORT_SYMBOL(ip_ct_gre_keymap_destroy); -+ -+module_init(init); -+module_exit(fini); ---- a/net/ipv4/netfilter/ip_nat_core.c -+++ b/net/ipv4/netfilter/ip_nat_core.c -@@ -424,7 +424,7 @@ get_unique_tuple(struct ip_conntrack_tup - 	*tuple = *orig_tuple; - 	while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum)) - 	       != NULL) { --		DEBUGP("Found best for "); DUMP_TUPLE(tuple); -+		DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple); - 		/* 3) The per-protocol part of the manip is made to - 		   map into the range to make a unique tuple. */ -  -@@ -564,9 +564,9 @@ ip_nat_setup_info(struct ip_conntrack *c - 		       HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST", - 		       conntrack); - 		DEBUGP("Original: "); --		DUMP_TUPLE(&orig_tp); -+		DUMP_TUPLE_RAW(&orig_tp); - 		DEBUGP("New: "); --		DUMP_TUPLE(&new_tuple); -+		DUMP_TUPLE_RAW(&new_tuple); - #endif -  - 		/* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT): ---- /dev/null -+++ b/net/ipv4/netfilter/ip_nat_pptp.c -@@ -0,0 +1,482 @@ -+/* -+ * ip_nat_pptp.c	- Version 1.5 -+ * -+ * NAT support for PPTP (Point to Point Tunneling Protocol). -+ * PPTP is a a protocol for creating virtual private networks. -+ * It is a specification defined by Microsoft and some vendors -+ * working with Microsoft.  PPTP is built on top of a modified -+ * version of the Internet Generic Routing Encapsulation Protocol. -+ * GRE is defined in RFC 1701 and RFC 1702.  Documentation of -+ * PPTP can be found in RFC 2637 -+ * -+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org> -+ * -+ * Development of this code funded by Astaro AG (http://www.astaro.com/) -+ * -+ * TODO: - Support for multiple calls within one session -+ * 	   (needs netfilter newnat code) -+ * 	 - NAT to a unique tuple, not to TCP source port -+ * 	   (needs netfilter tuple reservation) -+ * -+ * Changes: -+ *     2002-02-10 - Version 1.3 -+ *       - Use ip_nat_mangle_tcp_packet() because of cloned skb's -+ *	   in local connections (Philip Craig <philipc@snapgear.com>) -+ *       - add checks for magicCookie and pptp version -+ *       - make argument list of pptp_{out,in}bound_packet() shorter -+ *       - move to C99 style initializers -+ *       - print version number at module loadtime -+ *     2003-09-22 - Version 1.5 -+ *       - use SNATed tcp sourceport as callid, since we get called before -+ *         TCP header is mangled (Philip Craig <philipc@snapgear.com>) -+ *  -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/ip.h> -+#include <linux/tcp.h> -+#include <net/tcp.h> -+#include <linux/netfilter_ipv4/ip_nat.h> -+#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_helper.h> -+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> -+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h> -+ -+#define IP_NAT_PPTP_VERSION "1.5" -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); -+MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); -+ -+ -+#if 0 -+#include "ip_conntrack_pptp_priv.h" -+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \ -+				       ": " format, ## args) -+#else -+#define DEBUGP(format, args...) -+#endif -+ -+static unsigned int -+pptp_nat_expected(struct sk_buff **pskb, -+		  unsigned int hooknum, -+		  struct ip_conntrack *ct, -+		  struct ip_nat_info *info) -+{ -+	struct ip_conntrack *master = master_ct(ct); -+	struct ip_nat_multi_range mr; -+	struct ip_ct_pptp_master *ct_pptp_info; -+	struct ip_nat_pptp *nat_pptp_info; -+	u_int32_t newip, newcid; -+	int ret; -+ -+	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 == -+			htonl(ct_pptp_info->pac_call_id)) {	 -+			/* assume PNS->PAC */ -+			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = -+				htonl(nat_pptp_info->pns_call_id); -+			ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = -+				htonl(nat_pptp_info->pns_call_id); -+			newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; -+			newcid = htonl(nat_pptp_info->pac_call_id); -+		} else { -+			/* assume PAC->PNS */ -+			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = -+				htonl(nat_pptp_info->pac_call_id); -+			ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = -+				htonl(nat_pptp_info->pac_call_id); -+			newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; -+			newcid = htonl(nat_pptp_info->pns_call_id); -+		} -+	} else { -+		if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == -+			htonl(ct_pptp_info->pac_call_id)) {	 -+			/* assume PNS->PAC */ -+			newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; -+			newcid = htonl(ct_pptp_info->pns_call_id); -+		} -+		else { -+			/* assume PAC->PNS */ -+			newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; -+			newcid = htonl(ct_pptp_info->pac_call_id); -+		} -+	} -+ -+	mr.rangesize = 1; -+	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED; -+	mr.range[0].min_ip = mr.range[0].max_ip = newip; -+	mr.range[0].min = mr.range[0].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", ntohl(newcid)); -+	ret = ip_nat_setup_info(ct, &mr, hooknum); -+ -+	UNLOCK_BH(&ip_pptp_lock); -+ -+	return ret; -+ -+} -+ -+/* outbound packets == from PNS to PAC */ -+static inline unsigned int -+pptp_outbound_pkt(struct sk_buff **pskb, -+		  struct ip_conntrack *ct, -+		  enum ip_conntrack_info ctinfo, -+		  struct ip_conntrack_expect *exp) -+ -+{ -+	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.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh)); -+ -+	new_callid = htons(ct_pptp_info->pns_call_id); -+	 -+	switch (msg = ntohs(ctlh->messageType)) { -+		case PPTP_OUT_CALL_REQUEST: -+			cid = &pptpReq.ocreq->callID; -+			/* FIXME: ideally we would want to reserve a call ID -+			 * here.  current netfilter NAT core is not able to do -+			 * this :( For now we use TCP source port. This breaks -+			 * multiple calls within one control session */ -+ -+			/* save original call ID in nat_info */ -+			nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id; -+ -+			/* don't use tcph->source since we are at a DSTmanip -+			 * hook (e.g. PREROUTING) and pkt is not mangled yet */ -+			new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; -+ -+			/* save new call ID in ct info */ -+			ct_pptp_info->pns_call_id = ntohs(new_callid); -+			break; -+		case PPTP_IN_CALL_REPLY: -+			cid = &pptpReq.icreq->callID; -+			break; -+		case PPTP_CALL_CLEAR_REQUEST: -+			cid = &pptpReq.clrreq->callID; -+			break; -+		default: -+			DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, -+			      (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]); -+			/* fall through */ -+ -+		case PPTP_SET_LINK_INFO: -+			/* only need to NAT in case PAC is behind NAT box */ -+		case PPTP_START_SESSION_REQUEST: -+		case PPTP_START_SESSION_REPLY: -+		case PPTP_STOP_SESSION_REQUEST: -+		case PPTP_STOP_SESSION_REPLY: -+		case PPTP_ECHO_REQUEST: -+		case PPTP_ECHO_REPLY: -+			/* no need to alter packet */ -+			return NF_ACCEPT; -+	} -+ -+	IP_NF_ASSERT(cid); -+ -+	DEBUGP("altering call id from 0x%04x to 0x%04x\n", -+		ntohs(*cid), ntohs(new_callid)); -+ -+	/* mangle packet */ -+	ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph, -+				 sizeof(new_callid), (char *)&new_callid, -+				 sizeof(new_callid)); -+ -+	return NF_ACCEPT; -+} -+ -+/* inbound packets == from PAC to PNS */ -+static inline unsigned int -+pptp_inbound_pkt(struct sk_buff **pskb, -+		 struct ip_conntrack *ct, -+		 enum ip_conntrack_info ctinfo, -+		 struct ip_conntrack_expect *oldexp) -+{ -+	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; -+ -+	/* FIXME: size checks !!! */ -+	ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph)); -+	pptpReq.rawreq = (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 = htonl(nat_pptp_info->pns_call_id); -+			t.dst.u.gre.key = htonl(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 = htonl(nat_pptp_info->pac_call_id); -+			inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id); -+		} else { -+			/* expectation for PAC->PNS direction */ -+			t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id); -+			t.dst.u.gre.key = htonl(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 = htonl(nat_pptp_info->pns_call_id); -+			inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id); -+		} -+ -+		if (!ip_conntrack_change_expect(oldexp, &t)) { -+			DEBUGP("successfully changed expect\n"); -+		} else { -+			DEBUGP("can't change expect\n"); -+		} -+		if (oldexp->proto.gre.keymap_orig) -+			ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig,  -+						&t); -+		if (oldexp->proto.gre.keymap_reply) -+			ip_ct_gre_keymap_change(oldexp->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_change_expect(oldexp, &t)) { -+			DEBUGP("successfully changed expect\n"); -+		} else { -+			DEBUGP("can't change expect\n"); -+		} -+		break; -+	case PPTP_IN_CALL_REQUEST: -+		/* only need to nat in case PAC is behind NAT box */ -+		break; -+	case PPTP_WAN_ERROR_NOTIFY: -+		pcid = &pptpReq.wanerr->peersCallID; -+		break; -+	case PPTP_CALL_DISCONNECT_NOTIFY: -+		pcid = &pptpReq.disc->callID; -+		break; -+	case PPTP_SET_LINK_INFO: -+		pcid = &pptpReq.setlink->peersCallID; -+		break; -+ -+	default: -+		DEBUGP("unknown inbound packet %s\n", -+			(msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]); -+		/* fall through */ -+ -+	case PPTP_START_SESSION_REQUEST: -+	case PPTP_START_SESSION_REPLY: -+	case PPTP_STOP_SESSION_REQUEST: -+	case PPTP_STOP_SESSION_REPLY: -+	case PPTP_ECHO_REQUEST: -+	case PPTP_ECHO_REPLY: -+		/* no need to alter packet */ -+		return NF_ACCEPT; -+	} -+ -+	/* mangle packet */ -+	IP_NF_ASSERT(pcid); -+	DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", -+		ntohs(*pcid), ntohs(new_pcid)); -+	ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph, -+				 sizeof(new_pcid), (char *)&new_pcid,  -+				 sizeof(new_pcid)); -+ -+	if (new_cid) { -+		IP_NF_ASSERT(cid); -+		DEBUGP("altering call id from 0x%04x to 0x%04x\n", -+			ntohs(*cid), ntohs(new_cid)); -+		ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,  -+					 (void *)cid - (void *)pptph,  -+					 sizeof(new_cid), (char *)&new_cid,  -+					 sizeof(new_cid)); -+	} -+ -+	/* great, at least we don't need to resize packets */ -+	return NF_ACCEPT; -+} -+ -+ -+static unsigned int tcp_help(struct ip_conntrack *ct, -+			     struct ip_conntrack_expect *exp, -+			     struct ip_nat_info *info, -+			     enum ip_conntrack_info ctinfo, -+			     unsigned int hooknum, struct sk_buff **pskb) -+{ -+	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; -+ -+	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; -+	} -+ -+	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; -+} -+ -+/* nat helper struct for control connection */ -+static struct ip_nat_helper pptp_tcp_helper = {  -+	.list = { NULL, NULL }, -+	.name = "pptp",  -+	.flags = IP_NAT_HELPER_F_ALWAYS,  -+	.me = THIS_MODULE, -+	.tuple = { .src = { .ip = 0,  -+			    .u = { .tcp = { .port =  -+				    	__constant_htons(PPTP_CONTROL_PORT) }  -+				 }  -+			  }, -+	  	   .dst = { .ip = 0,  -+			    .u = { .all = 0 },  -+			    .protonum = IPPROTO_TCP  -+		   	  }  -+		 }, -+ -+	.mask = { .src = { .ip = 0,  -+			   .u = { .tcp = { .port = 0xFFFF } }  -+			 }, -+		  .dst = { .ip = 0,  -+			   .u = { .all = 0 },  -+			   .protonum = 0xFFFF  -+		  	 }  -+		}, -+	.help = tcp_help,  -+	.expect = pptp_nat_expected  -+}; -+ -+			   -+static int __init init(void) -+{ -+	DEBUGP("%s: registering NAT helper\n", __FILE__); -+	if (ip_nat_helper_register(&pptp_tcp_helper)) { -+		printk(KERN_ERR "Unable to register NAT application helper " -+				"for pptp\n"); -+		return -EIO; -+	} -+ -+	printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); -+	return 0; -+} -+ -+static void __exit fini(void) -+{ -+	DEBUGP("cleanup_module\n" ); -+	ip_nat_helper_unregister(&pptp_tcp_helper); -+	printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); -+} -+ -+module_init(init); -+module_exit(fini); ---- /dev/null -+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c -@@ -0,0 +1,202 @@ -+/* -+ * ip_nat_proto_gre.c - Version 1.2 -+ * -+ * NAT protocol helper module for GRE. -+ * -+ * GRE is a generic encapsulation protocol, which is generally not very -+ * suited for NAT, as it has no protocol-specific part as port numbers. -+ * -+ * It has an optional key field, which may help us distinguishing two  -+ * connections between the same two hosts. -+ * -+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784  -+ * -+ * PPTP is built on top of a modified version of GRE, and has a mandatory -+ * field called "CallID", which serves us for the same purpose as the key -+ * field in plain GRE. -+ * -+ * Documentation about PPTP can be found in RFC 2637 -+ * -+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org> -+ * -+ * Development of this code funded by Astaro AG (http://www.astaro.com/) -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/ip.h> -+#include <linux/netfilter_ipv4/ip_nat.h> -+#include <linux/netfilter_ipv4/ip_nat_rule.h> -+#include <linux/netfilter_ipv4/ip_nat_protocol.h> -+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); -+MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); -+ -+#if 0 -+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \ -+				       ": " format, ## args) -+#else -+#define DEBUGP(x, args...) -+#endif -+ -+/* is key in given range between min and max */ -+static int -+gre_in_range(const struct ip_conntrack_tuple *tuple, -+	     enum ip_nat_manip_type maniptype, -+	     const union ip_conntrack_manip_proto *min, -+	     const union ip_conntrack_manip_proto *max) -+{ -+	u_int32_t key; -+ -+	if (maniptype == IP_NAT_MANIP_SRC) -+		key = tuple->src.u.gre.key; -+	else -+		key = tuple->dst.u.gre.key; -+ -+	return ntohl(key) >= ntohl(min->gre.key) -+		&& ntohl(key) <= ntohl(max->gre.key); -+} -+ -+/* generate unique tuple ... */ -+static int  -+gre_unique_tuple(struct ip_conntrack_tuple *tuple, -+		 const struct ip_nat_range *range, -+		 enum ip_nat_manip_type maniptype, -+		 const struct ip_conntrack *conntrack) -+{ -+	u_int32_t min, i, range_size; -+	u_int32_t key = 0, *keyptr; -+ -+	if (maniptype == IP_NAT_MANIP_SRC) -+		keyptr = &tuple->src.u.gre.key; -+	else -+		keyptr = &tuple->dst.u.gre.key; -+ -+	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { -+ -+		DEBUGP("%p: NATing GRE PPTP\n", conntrack); -+		min = 1; -+		range_size = 0xffff; -+ -+	} else { -+		min = ntohl(range->min.gre.key); -+		range_size = ntohl(range->max.gre.key) - min + 1; -+	} -+ -+	DEBUGP("min = %u, range_size = %u\n", min, range_size);  -+ -+	for (i = 0; i < range_size; i++, key++) { -+		*keyptr = htonl(min + key % range_size); -+		if (!ip_nat_used_tuple(tuple, conntrack)) -+			return 1; -+	} -+ -+	DEBUGP("%p: no NAT mapping\n", conntrack); -+ -+	return 0; -+} -+ -+/* manipulate a GRE packet according to maniptype */ -+static void  -+gre_manip_pkt(struct iphdr *iph, size_t len,  -+	      const struct ip_conntrack_manip *manip, -+	      enum ip_nat_manip_type maniptype) -+{ -+	struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl); -+	struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh; -+ -+	/* we only have destination manip of a packet, since 'source key'  -+	 * is not present in the packet itself */ -+	if (maniptype == IP_NAT_MANIP_DST) { -+		/* key manipulation is always dest */ -+		switch (greh->version) { -+		case 0: -+			if (!greh->key) { -+				DEBUGP("can't nat GRE w/o key\n"); -+				break; -+			} -+			if (greh->csum) { -+				/* FIXME: Never tested this code... */ -+				*(gre_csum(greh)) =  -+					ip_nat_cheat_check(~*(gre_key(greh)), -+							manip->u.gre.key, -+							*(gre_csum(greh))); -+			} -+			*(gre_key(greh)) = manip->u.gre.key; -+			break; -+		case GRE_VERSION_PPTP: -+			DEBUGP("call_id -> 0x%04x\n",  -+				ntohl(manip->u.gre.key)); -+			pgreh->call_id = htons(ntohl(manip->u.gre.key)); -+			break; -+		default: -+			DEBUGP("can't nat unknown GRE version\n"); -+			break; -+		} -+	} -+} -+ -+/* print out a nat tuple */ -+static unsigned int  -+gre_print(char *buffer,  -+	  const struct ip_conntrack_tuple *match, -+	  const struct ip_conntrack_tuple *mask) -+{ -+	unsigned int len = 0; -+ -+	if (mask->src.u.gre.key) -+		len += sprintf(buffer + len, "srckey=0x%x ",  -+				ntohl(match->src.u.gre.key)); -+ -+	if (mask->dst.u.gre.key) -+		len += sprintf(buffer + len, "dstkey=0x%x ", -+				ntohl(match->src.u.gre.key)); -+ -+	return len; -+} -+ -+/* print a range of keys */ -+static unsigned int  -+gre_print_range(char *buffer, const struct ip_nat_range *range) -+{ -+	if (range->min.gre.key != 0  -+	    || range->max.gre.key != 0xFFFF) { -+		if (range->min.gre.key == range->max.gre.key) -+			return sprintf(buffer, "key 0x%x ", -+					ntohl(range->min.gre.key)); -+		else -+			return sprintf(buffer, "keys 0x%u-0x%u ", -+					ntohl(range->min.gre.key), -+					ntohl(range->max.gre.key)); -+	} else -+		return 0; -+} -+ -+/* nat helper struct */ -+static struct ip_nat_protocol gre =  -+	{ { NULL, NULL }, "GRE", IPPROTO_GRE, -+	  gre_manip_pkt, -+	  gre_in_range, -+	  gre_unique_tuple, -+	  gre_print, -+	  gre_print_range  -+	}; -+				   -+static int __init init(void) -+{ -+        if (ip_nat_protocol_register(&gre)) -+                return -EIO; -+ -+        return 0; -+} -+ -+static void __exit fini(void) -+{ -+        ip_nat_protocol_unregister(&gre); -+} -+ -+module_init(init); -+module_exit(fini); ---- a/net/ipv4/netfilter/Makefile -+++ b/net/ipv4/netfilter/Makefile -@@ -36,23 +36,32 @@ obj-$(CONFIG_IP_NF_AMANDA) += ip_conntra - ifdef CONFIG_IP_NF_AMANDA - 	export-objs += ip_conntrack_amanda.o - endif -- - obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o - obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o - ifdef CONFIG_IP_NF_FTP - 	export-objs += ip_conntrack_ftp.o - endif -- - obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o - ifdef CONFIG_IP_NF_IRC - 	export-objs += ip_conntrack_irc.o - endif -+obj-$(CONFIG_IP_NF_CT_PROTO_GRE) += ip_conntrack_proto_gre.o -+ifdef CONFIG_IP_NF_CT_PROTO_GRE -+	export-objs += ip_conntrack_proto_gre.o -+endif -+obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o -+ifdef CONFIG_IP_NF_NAT_PPTP -+	export-objs += ip_conntrack_pptp.o -+endif -+ -  - # NAT helpers  - obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o - obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o - obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o - obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o -+obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o -+obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o -  - # generic IP tables  - obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o ---- /dev/null -+++ b/net/ipv4/netfilter/ip_conntrack_pptp.c -@@ -0,0 +1,635 @@ -+/* -+ * ip_conntrack_pptp.c	- Version 1.9 -+ * -+ * Connection tracking support for PPTP (Point to Point Tunneling Protocol). -+ * PPTP is a a protocol for creating virtual private networks. -+ * It is a specification defined by Microsoft and some vendors -+ * working with Microsoft.  PPTP is built on top of a modified -+ * version of the Internet Generic Routing Encapsulation Protocol. -+ * GRE is defined in RFC 1701 and RFC 1702.  Documentation of -+ * PPTP can be found in RFC 2637 -+ * -+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org> -+ * -+ * Development of this code funded by Astaro AG (http://www.astaro.com/) -+ * -+ * Limitations: -+ * 	 - We blindly assume that control connections are always -+ * 	   established in PNS->PAC direction.  This is a violation -+ * 	   of RFFC2673 -+ * -+ * TODO: - finish support for multiple calls within one session -+ * 	   (needs expect reservations in newnat) -+ *	 - testing of incoming PPTP calls  -+ * -+ * Changes:  -+ * 	2002-02-05 - Version 1.3 -+ * 	  - Call ip_conntrack_unexpect_related() from  -+ * 	    pptp_timeout_related() to destroy expectations in case -+ * 	    CALL_DISCONNECT_NOTIFY or tcp fin packet was seen -+ * 	    (Philip Craig <philipc@snapgear.com>) -+ * 	  - Add Version information at module loadtime -+ * 	2002-02-10 - Version 1.6 -+ * 	  - move to C99 style initializers -+ * 	  - remove second expectation if first arrives -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/netfilter.h> -+#include <linux/ip.h> -+#include <net/checksum.h> -+#include <net/tcp.h> -+ -+#include <linux/netfilter_ipv4/lockhelp.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> -+ -+#define IP_CT_PPTP_VERSION "1.9" -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); -+MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); -+ -+DECLARE_LOCK(ip_pptp_lock); -+ -+#if 0 -+#include "ip_conntrack_pptp_priv.h" -+#define DEBUGP(format, args...)	printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \ -+					": " format, ## args) -+#else -+#define DEBUGP(format, args...) -+#endif -+ -+#define SECS *HZ -+#define MINS * 60 SECS -+#define HOURS * 60 MINS -+#define DAYS * 24 HOURS -+ -+#define PPTP_GRE_TIMEOUT 		(10 MINS) -+#define PPTP_GRE_STREAM_TIMEOUT 	(5 DAYS) -+ -+static int pptp_expectfn(struct ip_conntrack *ct) -+{ -+	struct ip_conntrack *master; -+	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; -+ -+	master = master_ct(ct); -+	if (!master) { -+		DEBUGP(" no master!!!\n"); -+		return 0; -+	} -+ -+	exp = ct->master; -+	if (!exp) { -+		DEBUGP("no expectation!!\n"); -+		return 0; -+	} -+ -+	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 ==  -+		htonl(master->help.ct_pptp_info.pac_call_id)) {	 -+		/* assume PNS->PAC */ -+		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =  -+			htonl(master->help.ct_pptp_info.pns_call_id); -+		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = -+			htonl(master->help.ct_pptp_info.pns_call_id); -+	} else { -+		/* assume PAC->PNS */ -+		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = -+			htonl(master->help.ct_pptp_info.pac_call_id); -+		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = -+			htonl(master->help.ct_pptp_info.pac_call_id); -+	} -+	 -+	/* 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); -+			} -+		} -+	} -+ -+	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; -+	enum ip_conntrack_info ctinfo; -+	struct iphdr *iph; -+ -+	/* 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); -+ -+		ip_ct_gre_keymap_destroy(exp); -+		if (!exp->sibling) { -+			ip_conntrack_unexpect_related(exp); -+			continue; -+		} -+ -+		DEBUGP("setting timeout of conntrack %p to 0\n", -+			exp->sibling); -+		exp->sibling->proto.gre.timeout = 0; -+		exp->sibling->proto.gre.stream_timeout = 0; -+		ip_ct_refresh_acct(exp->sibling, ctinfo, iph, 0); -+	} -+ -+	return 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.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.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; -+} -+ -+static inline int  -+pptp_inbound_pkt(struct tcphdr *tcph, -+		 struct pptp_pkt_hdr *pptph,  -+		 size_t datalen, -+		 struct ip_conntrack *ct, -+		 enum ip_conntrack_info ctinfo) -+{ -+	struct PptpControlHeader *ctlh; -+        union pptp_ctrl_union pptpReq; -+	 -+	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; -+	u_int16_t msg, *cid, *pcid; -+	u_int32_t seq;	 -+ -+	ctlh = (struct PptpControlHeader *)  -+		((char *) pptph + sizeof(struct pptp_pkt_hdr)); -+	pptpReq.rawreq = (void *)  -+		((char *) ctlh + sizeof(struct PptpControlHeader)); -+ -+	msg = ntohs(ctlh->messageType); -+	DEBUGP("inbound control message %s\n", strMName[msg]); -+ -+	switch (msg) { -+	case PPTP_START_SESSION_REPLY: -+		/* server confirms new control session */ -+		if (info->sstate < PPTP_SESSION_REQUESTED) { -+			DEBUGP("%s without START_SESS_REQUEST\n", -+				strMName[msg]); -+			break; -+		} -+		if (pptpReq.srep->resultCode == PPTP_START_OK) -+			info->sstate = PPTP_SESSION_CONFIRMED; -+		else  -+			info->sstate = PPTP_SESSION_ERROR; -+		break; -+ -+	case PPTP_STOP_SESSION_REPLY: -+		/* server confirms end of control session */ -+		if (info->sstate > PPTP_SESSION_STOPREQ) { -+			DEBUGP("%s without STOP_SESS_REQUEST\n", -+				strMName[msg]); -+			break; -+		} -+		if (pptpReq.strep->resultCode == PPTP_STOP_OK) -+			info->sstate = PPTP_SESSION_NONE; -+		else -+			info->sstate = PPTP_SESSION_ERROR; -+		break; -+ -+	case PPTP_OUT_CALL_REPLY: -+		/* server accepted call, we now expect GRE frames */ -+		if (info->sstate != PPTP_SESSION_CONFIRMED) { -+			DEBUGP("%s but no session\n", strMName[msg]); -+			break; -+		} -+		if (info->cstate != PPTP_CALL_OUT_REQ && -+		    info->cstate != PPTP_CALL_OUT_CONF) { -+			DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]); -+			break; -+		} -+		if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) { -+			info->cstate = PPTP_CALL_NONE; -+			break; -+		} -+ -+		cid = &pptpReq.ocack->callID; -+		pcid = &pptpReq.ocack->peersCallID; -+ -+		info->pac_call_id = ntohs(*cid); -+		 -+		if (htons(info->pns_call_id) != *pcid) { -+			DEBUGP("%s for unknown callid %u\n", -+				strMName[msg], ntohs(*pcid)); -+			break; -+		} -+ -+		DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg],  -+			ntohs(*cid), ntohs(*pcid)); -+		 -+		info->cstate = PPTP_CALL_OUT_CONF; -+ -+		seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph); -+		if (exp_gre(ct, seq, *cid, *pcid) != 0) -+			printk("ip_conntrack_pptp: error during exp_gre\n"); -+		break; -+ -+	case PPTP_IN_CALL_REQUEST: -+		/* server tells us about incoming call request */ -+		if (info->sstate != PPTP_SESSION_CONFIRMED) { -+			DEBUGP("%s but no session\n", strMName[msg]); -+			break; -+		} -+		pcid = &pptpReq.icack->peersCallID; -+		DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid)); -+		info->cstate = PPTP_CALL_IN_REQ; -+		info->pac_call_id= ntohs(*pcid); -+		break; -+ -+	case PPTP_IN_CALL_CONNECT: -+		/* server tells us about incoming call established */ -+		if (info->sstate != PPTP_SESSION_CONFIRMED) { -+			DEBUGP("%s but no session\n", strMName[msg]); -+			break; -+		} -+		if (info->sstate != PPTP_CALL_IN_REP -+		    && info->sstate != PPTP_CALL_IN_CONF) { -+			DEBUGP("%s but never sent IN_CALL_REPLY\n", -+				strMName[msg]); -+			break; -+		} -+ -+		pcid = &pptpReq.iccon->peersCallID; -+		cid = &info->pac_call_id; -+ -+		if (info->pns_call_id != ntohs(*pcid)) { -+			DEBUGP("%s for unknown CallID %u\n",  -+				strMName[msg], ntohs(*cid)); -+			break; -+		} -+ -+		DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid)); -+		info->cstate = PPTP_CALL_IN_CONF; -+ -+		/* we expect a GRE connection from PAC to PNS */ -+		seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph); -+		if (exp_gre(ct, seq, *cid, *pcid) != 0) -+			printk("ip_conntrack_pptp: error during exp_gre\n"); -+ -+		break; -+ -+	case PPTP_CALL_DISCONNECT_NOTIFY: -+		/* server confirms disconnect */ -+		cid = &pptpReq.disc->callID; -+		DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid)); -+		info->cstate = PPTP_CALL_NONE; -+ -+		/* untrack this call id, unexpect GRE packets */ -+		pptp_timeout_related(ct); -+		break; -+ -+	case PPTP_WAN_ERROR_NOTIFY: -+		break; -+ -+	case PPTP_ECHO_REQUEST: -+	case PPTP_ECHO_REPLY: -+		/* I don't have to explain these ;) */ -+		break; -+	default: -+		DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX) -+			? strMName[msg]:strMName[0], msg); -+		break; -+	} -+ -+	return NF_ACCEPT; -+ -+} -+ -+static inline int -+pptp_outbound_pkt(struct tcphdr *tcph, -+		  struct pptp_pkt_hdr *pptph, -+		  size_t datalen, -+		  struct ip_conntrack *ct, -+		  enum ip_conntrack_info ctinfo) -+{ -+	struct PptpControlHeader *ctlh; -+        union pptp_ctrl_union pptpReq; -+	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; -+	u_int16_t msg, *cid, *pcid; -+ -+	ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph)); -+	pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh)); -+ -+	msg = ntohs(ctlh->messageType); -+	DEBUGP("outbound control message %s\n", strMName[msg]); -+ -+	switch (msg) { -+	case PPTP_START_SESSION_REQUEST: -+		/* client requests for new control session */ -+		if (info->sstate != PPTP_SESSION_NONE) { -+			DEBUGP("%s but we already have one", -+				strMName[msg]); -+		} -+		info->sstate = PPTP_SESSION_REQUESTED; -+		break; -+	case PPTP_STOP_SESSION_REQUEST: -+		/* client requests end of control session */ -+		info->sstate = PPTP_SESSION_STOPREQ; -+		break; -+ -+	case PPTP_OUT_CALL_REQUEST: -+		/* client initiating connection to server */ -+		if (info->sstate != PPTP_SESSION_CONFIRMED) { -+			DEBUGP("%s but no session\n", -+				strMName[msg]); -+			break; -+		} -+		info->cstate = PPTP_CALL_OUT_REQ; -+		/* track PNS call id */ -+		cid = &pptpReq.ocreq->callID; -+		DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid)); -+		info->pns_call_id = ntohs(*cid); -+		break; -+	case PPTP_IN_CALL_REPLY: -+		/* client answers incoming call */ -+		if (info->cstate != PPTP_CALL_IN_REQ -+		    && info->cstate != PPTP_CALL_IN_REP) { -+			DEBUGP("%s without incall_req\n",  -+				strMName[msg]); -+			break; -+		} -+		if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) { -+			info->cstate = PPTP_CALL_NONE; -+			break; -+		} -+		pcid = &pptpReq.icack->peersCallID; -+		if (info->pac_call_id != ntohs(*pcid)) { -+			DEBUGP("%s for unknown call %u\n",  -+				strMName[msg], ntohs(*pcid)); -+			break; -+		} -+		DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid)); -+		/* part two of the three-way handshake */ -+		info->cstate = PPTP_CALL_IN_REP; -+		info->pns_call_id = ntohs(pptpReq.icack->callID); -+		break; -+ -+	case PPTP_CALL_CLEAR_REQUEST: -+		/* client requests hangup of call */ -+		if (info->sstate != PPTP_SESSION_CONFIRMED) { -+			DEBUGP("CLEAR_CALL but no session\n"); -+			break; -+		} -+		/* FUTURE: iterate over all calls and check if -+		 * call ID is valid.  We don't do this without newnat, -+		 * because we only know about last call */ -+		info->cstate = PPTP_CALL_CLEAR_REQ; -+		break; -+	case PPTP_SET_LINK_INFO: -+		break; -+	case PPTP_ECHO_REQUEST: -+	case PPTP_ECHO_REPLY: -+		/* I don't have to explain these ;) */ -+		break; -+	default: -+		DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)?  -+			strMName[msg]:strMName[0], msg); -+		/* unknown: no need to create GRE masq table entry */ -+		break; -+	} -+ -+	return NF_ACCEPT; -+} -+ -+ -+/* track caller id inside control connection, call expect_related */ -+static int  -+conntrack_pptp_help(const struct iphdr *iph, size_t len, -+		    struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) -+ -+{ -+	struct pptp_pkt_hdr *pptph; -+	 -+	struct tcphdr *tcph = (void *) iph + iph->ihl * 4; -+	u_int32_t tcplen = len - iph->ihl * 4; -+	u_int32_t datalen = tcplen - tcph->doff * 4; -+	void *datalimit; -+	int dir = CTINFO2DIR(ctinfo); -+	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; -+ -+	int oldsstate, oldcstate; -+	int ret; -+ -+	/* don't do any tracking before tcp handshake complete */ -+	if (ctinfo != IP_CT_ESTABLISHED  -+	    && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { -+		DEBUGP("ctinfo = %u, skipping\n", ctinfo); -+		return NF_ACCEPT; -+	} -+	 -+	/* not a complete TCP header? */ -+	if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) { -+		DEBUGP("tcplen = %u\n", tcplen); -+		return NF_ACCEPT; -+	} -+ -+	/* checksum invalid? */ -+	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, -+			csum_partial((char *) tcph, tcplen, 0))) { -+		printk(KERN_NOTICE __FILE__ ": bad csum\n"); -+		/* W2K PPTP server sends TCP packets with wrong checksum :(( */ -+		//return NF_ACCEPT; -+	} -+ -+	if (tcph->fin || tcph->rst) { -+		DEBUGP("RST/FIN received, timeouting GRE\n"); -+		/* can't do this after real newnat */ -+		info->cstate = PPTP_CALL_NONE; -+ -+		/* untrack this call id, unexpect GRE packets */ -+		pptp_timeout_related(ct); -+	} -+ -+ -+	pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4); -+	datalimit = (void *) pptph + datalen; -+ -+	/* not a full pptp packet header? */ -+	if ((void *) pptph+sizeof(*pptph) >= datalimit) { -+		DEBUGP("no full PPTP header, can't track\n"); -+		return NF_ACCEPT; -+	} -+	 -+	/* if it's not a control message we can't do anything with it */ -+        if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || -+	    ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { -+		DEBUGP("not a control packet\n"); -+		return NF_ACCEPT; -+	} -+ -+	oldsstate = info->sstate; -+	oldcstate = info->cstate; -+ -+	LOCK_BH(&ip_pptp_lock); -+ -+	/* FIXME: We just blindly assume that the control connection is always -+	 * established from PNS->PAC.  However, RFC makes no guarantee */ -+	if (dir == IP_CT_DIR_ORIGINAL) -+		/* client -> server (PNS -> PAC) */ -+		ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo); -+	else -+		/* server -> client (PAC -> PNS) */ -+		ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo); -+	DEBUGP("sstate: %d->%d, cstate: %d->%d\n", -+		oldsstate, info->sstate, oldcstate, info->cstate); -+	UNLOCK_BH(&ip_pptp_lock); -+ -+	return ret; -+} -+ -+/* control protocol helper */ -+static struct ip_conntrack_helper pptp = {  -+	.list = { NULL, NULL }, -+	.name = "pptp",  -+	.flags = IP_CT_HELPER_F_REUSE_EXPECT, -+	.me = THIS_MODULE, -+	.max_expected = 2, -+	.timeout = 0, -+	.tuple = { .src = { .ip = 0,  -+		 	    .u = { .tcp = { .port =   -+				    __constant_htons(PPTP_CONTROL_PORT) } }  -+			  },  -+		   .dst = { .ip = 0,  -+			    .u = { .all = 0 }, -+			    .protonum = IPPROTO_TCP -+			  }  -+		 }, -+	.mask = { .src = { .ip = 0,  -+			   .u = { .tcp = { .port = 0xffff } }  -+			 },  -+		  .dst = { .ip = 0,  -+			   .u = { .all = 0 }, -+			   .protonum = 0xffff  -+		 	 }  -+		}, -+	.help = conntrack_pptp_help -+}; -+ -+/* ip_conntrack_pptp initialization */ -+static int __init init(void) -+{ -+	int retcode; -+ -+	DEBUGP(__FILE__ ": registering helper\n"); -+	if ((retcode = ip_conntrack_helper_register(&pptp))) { -+                printk(KERN_ERR "Unable to register conntrack application " -+				"helper for pptp: %d\n", retcode); -+		return -EIO; -+	} -+ -+	printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION); -+	return 0; -+} -+ -+static void __exit fini(void) -+{ -+	ip_conntrack_helper_unregister(&pptp); -+	printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION); -+} -+ -+module_init(init); -+module_exit(fini); -+ -+EXPORT_SYMBOL(ip_pptp_lock); diff --git a/target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch b/target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch index 0dc2fba39..064f74f92 100644 --- a/target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch +++ b/target/linux/generic-2.4/patches/606-netfilter_NETMAP.patch @@ -1,6 +1,8 @@ ---- a/Documentation/Configure.help -+++ b/Documentation/Configure.help -@@ -3086,6 +3086,17 @@ CONFIG_IP_NF_TARGET_REDIRECT +Index: linux-2.4.37.5/Documentation/Configure.help +=================================================================== +--- linux-2.4.37.5.orig/Documentation/Configure.help	2009-09-03 00:09:38.000000000 -0700 ++++ linux-2.4.37.5/Documentation/Configure.help	2009-09-03 00:12:30.000000000 -0700 +@@ -3086,6 +3086,17 @@     If you want to compile it as a module, say M here and read     <file:Documentation/modules.txt>.  If unsure, say `N'. @@ -18,18 +20,22 @@   Packet mangling   CONFIG_IP_NF_MANGLE     This option adds a `mangle' table to iptables: see the man page for ---- a/net/ipv4/netfilter/Config.in -+++ b/net/ipv4/netfilter/Config.in -@@ -65,6 +65,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ];  +Index: linux-2.4.37.5/net/ipv4/netfilter/Config.in +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/Config.in	2009-09-03 00:09:38.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/Config.in	2009-09-03 00:14:38.000000000 -0700 +@@ -63,6 +63,7 @@         define_bool CONFIG_IP_NF_NAT_NEEDED y         dep_tristate '    MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT         dep_tristate '    REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT  +      dep_tristate '    NETMAP target support' CONFIG_IP_NF_TARGET_NETMAP $CONFIG_IP_NF_NAT -       if [ "$CONFIG_IP_NF_PPTP" = "m" ]; then -         define_tristate CONFIG_IP_NF_NAT_PPTP m +       if [ "$CONFIG_IP_NF_AMANDA" = "m" ]; then +         define_tristate CONFIG_IP_NF_NAT_AMANDA m         else ---- /dev/null -+++ b/net/ipv4/netfilter/ipt_NETMAP.c +Index: linux-2.4.37.5/net/ipv4/netfilter/ipt_NETMAP.c +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.4.37.5/net/ipv4/netfilter/ipt_NETMAP.c	2009-09-03 00:12:30.000000000 -0700  @@ -0,0 +1,112 @@  +/* NETMAP - static NAT mapping of IP network addresses (1:1).  +   The mapping can be applied to source (POSTROUTING), @@ -143,9 +149,11 @@  +  +module_init(init);  +module_exit(fini); ---- a/net/ipv4/netfilter/Makefile -+++ b/net/ipv4/netfilter/Makefile -@@ -108,6 +108,7 @@ obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_D +Index: linux-2.4.37.5/net/ipv4/netfilter/Makefile +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/Makefile	2009-09-03 00:09:38.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/Makefile	2009-09-03 00:12:30.000000000 -0700 +@@ -99,6 +99,7 @@   obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o   obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o   obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o diff --git a/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch b/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch index b5ca3b6de..c6ddb51e2 100644 --- a/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch +++ b/target/linux/generic-2.4/patches/610-netfilter_connbytes.patch @@ -1,17 +1,21 @@ ---- a/net/ipv4/netfilter/Config.in -+++ b/net/ipv4/netfilter/Config.in -@@ -11,6 +11,8 @@ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; +Index: linux-2.4.37.5/net/ipv4/netfilter/Config.in +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/Config.in	2009-09-03 00:17:38.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/Config.in	2009-09-03 00:25:34.000000000 -0700 +@@ -11,6 +11,8 @@     dep_tristate '  Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK     dep_tristate '  TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK     dep_tristate '  IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK  +  dep_tristate '  Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK  +  dep_tristate '  Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES -   dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK -   dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE   fi ---- a/net/ipv4/netfilter/Makefile -+++ b/net/ipv4/netfilter/Makefile -@@ -106,6 +106,7 @@ obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_ +  + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then +Index: linux-2.4.37.5/net/ipv4/netfilter/Makefile +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/Makefile	2009-09-03 00:17:38.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/Makefile	2009-09-03 00:17:57.000000000 -0700 +@@ -97,6 +97,7 @@   obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o   obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o   obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o @@ -19,9 +23,11 @@   obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o   obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o   obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o ---- a/net/ipv4/netfilter/ip_conntrack_amanda.c -+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c -@@ -75,7 +75,7 @@ static int help(const struct iphdr *iph, +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_amanda.c +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/ip_conntrack_amanda.c	2009-08-13 15:04:00.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_amanda.c	2009-09-03 00:17:57.000000000 -0700 +@@ -75,7 +75,7 @@   	/* increase the UDP timeout of the master connection as replies from   	 * Amanda clients to the server can be quite delayed */ @@ -30,9 +36,11 @@   	/* Search for "CONNECT " string */   	do { ---- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c -+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c -@@ -211,7 +211,7 @@ static int tcp_packet(struct ip_conntrac +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2009-08-13 15:04:00.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2009-09-03 00:17:57.000000000 -0700 +@@ -211,7 +211,7 @@   			set_bit(IPS_ASSURED_BIT, &conntrack->status);   		WRITE_UNLOCK(&tcp_lock); @@ -41,9 +49,11 @@   	}   	return NF_ACCEPT; ---- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c -+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c -@@ -47,16 +47,16 @@ static unsigned int udp_print_conntrack( +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_udp.c +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/ip_conntrack_proto_udp.c	2009-08-13 15:04:00.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_udp.c	2009-09-03 00:17:57.000000000 -0700 +@@ -47,16 +47,16 @@   /* Returns verdict for packet, and may modify conntracktype */   static int udp_packet(struct ip_conntrack *conntrack,   		      struct iphdr *iph, size_t len, @@ -63,9 +73,11 @@   	return NF_ACCEPT;   } ---- a/net/ipv4/netfilter/ip_conntrack_standalone.c -+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c -@@ -79,6 +79,18 @@ print_expect(char *buffer, const struct  +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_standalone.c +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/ip_conntrack_standalone.c	2009-09-03 00:17:18.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_standalone.c	2009-09-03 00:17:57.000000000 -0700 +@@ -79,6 +79,18 @@   	return len;   } @@ -84,7 +96,7 @@   static unsigned int   print_conntrack(char *buffer, struct ip_conntrack *conntrack)   { -@@ -98,11 +110,15 @@ print_conntrack(char *buffer, struct ip_ +@@ -98,11 +110,15 @@   	len += print_tuple(buffer + len,   			   &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,   			   proto); @@ -100,7 +112,7 @@   	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))   		len += sprintf(buffer + len, "[ASSURED] ");   	len += sprintf(buffer + len, "use=%u ", -@@ -481,7 +497,7 @@ EXPORT_SYMBOL(ip_conntrack_get); +@@ -481,7 +497,7 @@   EXPORT_SYMBOL(ip_conntrack_helper_register);   EXPORT_SYMBOL(ip_conntrack_helper_unregister);   EXPORT_SYMBOL(ip_ct_iterate_cleanup); @@ -109,9 +121,11 @@   EXPORT_SYMBOL(ip_ct_find_proto);   EXPORT_SYMBOL(__ip_ct_find_proto);   EXPORT_SYMBOL(ip_ct_find_helper); ---- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c -+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c -@@ -41,9 +41,9 @@ static unsigned int generic_print_conntr +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_generic.c +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/ip_conntrack_proto_generic.c	2009-08-13 15:04:00.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_generic.c	2009-09-03 00:17:57.000000000 -0700 +@@ -41,9 +41,9 @@   /* Returns verdict for packet, or -1 for invalid. */   static int established(struct ip_conntrack *conntrack,   		       struct iphdr *iph, size_t len, @@ -123,9 +137,11 @@   	return NF_ACCEPT;   } ---- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c -+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c -@@ -82,7 +82,7 @@ static int icmp_packet(struct ip_conntra +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	2009-08-13 15:04:00.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	2009-09-03 00:17:57.000000000 -0700 +@@ -82,7 +82,7 @@   			ct->timeout.function((unsigned long)ct);   	} else {   		atomic_inc(&ct->proto.icmp.count); @@ -134,9 +150,11 @@   	}   	return NF_ACCEPT; ---- a/net/ipv4/netfilter/ip_conntrack_core.c -+++ b/net/ipv4/netfilter/ip_conntrack_core.c -@@ -1196,22 +1196,40 @@ void ip_conntrack_helper_unregister(stru +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_core.c +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/ip_conntrack_core.c	2009-09-03 00:17:18.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_core.c	2009-09-03 00:17:57.000000000 -0700 +@@ -1193,22 +1193,40 @@   	MOD_DEC_USE_COUNT;   } @@ -180,9 +198,11 @@   	}   	WRITE_UNLOCK(&ip_conntrack_lock);   } ---- a/include/linux/netfilter_ipv4/ip_conntrack.h -+++ b/include/linux/netfilter_ipv4/ip_conntrack.h -@@ -164,6 +164,12 @@ struct ip_conntrack_expect +Index: linux-2.4.37.5/include/linux/netfilter_ipv4/ip_conntrack.h +=================================================================== +--- linux-2.4.37.5.orig/include/linux/netfilter_ipv4/ip_conntrack.h	2009-09-03 00:17:18.000000000 -0700 ++++ linux-2.4.37.5/include/linux/netfilter_ipv4/ip_conntrack.h	2009-09-03 00:17:57.000000000 -0700 +@@ -156,6 +156,12 @@   	union ip_conntrack_expect_help help;   }; @@ -195,7 +215,7 @@   struct ip_conntrack_helper;   struct ip_conntrack -@@ -181,6 +187,12 @@ struct ip_conntrack +@@ -173,6 +179,12 @@   	/* Timer function; drops refcnt when it goes off. */   	struct timer_list timeout; @@ -208,7 +228,7 @@   	/* If we're expecting another related connection, this will be              in expected linked list */   	struct list_head sibling_list; -@@ -264,8 +276,10 @@ extern int invert_tuplepr(struct ip_conn +@@ -256,8 +268,10 @@   			  const struct ip_conntrack_tuple *orig);   /* Refresh conntrack for this many jiffies */ @@ -221,8 +241,10 @@   /* These are for NAT.  Icky. */   /* Call me when a conntrack is destroyed. */ ---- /dev/null -+++ b/net/ipv4/netfilter/ipt_connbytes.c +Index: linux-2.4.37.5/net/ipv4/netfilter/ipt_connbytes.c +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.4.37.5/net/ipv4/netfilter/ipt_connbytes.c	2009-09-03 00:17:57.000000000 -0700  @@ -0,0 +1,163 @@  +/* Kernel module to match connection tracking byte counter.  + * GPL (C) 2002 Martin Devera (devik@cdi.cz). @@ -387,8 +409,10 @@  +module_init(init);  +module_exit(fini);  +MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ipt_connbytes.h +Index: linux-2.4.37.5/include/linux/netfilter_ipv4/ipt_connbytes.h +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.4.37.5/include/linux/netfilter_ipv4/ipt_connbytes.h	2009-09-03 00:17:57.000000000 -0700  @@ -0,0 +1,25 @@  +#ifndef _IPT_CONNBYTES_H  +#define _IPT_CONNBYTES_H @@ -415,25 +439,3 @@  +};  +  +#endif ---- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c -+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c -@@ -237,16 +237,16 @@ static unsigned int gre_print_conntrack( - /* Returns verdict for packet, and may modify conntrack */ - static int gre_packet(struct ip_conntrack *ct, - 		      struct iphdr *iph, size_t len, --		      enum ip_conntrack_info conntrackinfo) -+		      enum ip_conntrack_info ctinfo) - { - 	/* If we've seen traffic both ways, this is a GRE connection. - 	 * Extend timeout. */ - 	if (ct->status & IPS_SEEN_REPLY) { --		ip_ct_refresh_acct(ct, ct->proto.gre.stream_timeout); -+		ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.stream_timeout); - 		/* Also, more likely to be important, and not a probe. */ - 		set_bit(IPS_ASSURED_BIT, &ct->status); - 	} else --		ip_ct_refresh_acct(ct, ct->proto.gre.timeout); -+		ip_ct_refresh_acct(ct, ctinfo, iph, ct->proto.gre.timeout); - 	 - 	return NF_ACCEPT; - } diff --git a/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch b/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch index cb23abde6..ee7a91abc 100644 --- a/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch +++ b/target/linux/generic-2.4/patches/613-netfilter_nat_h323.patch @@ -1,14 +1,16 @@ ---- a/net/ipv4/netfilter/Config.in -+++ b/net/ipv4/netfilter/Config.in -@@ -15,6 +15,7 @@ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; +Index: linux-2.4.37.5/net/ipv4/netfilter/Config.in +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/Config.in	2009-09-03 01:07:45.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/Config.in	2009-09-03 01:30:37.000000000 -0700 +@@ -13,6 +13,7 @@ +   dep_tristate '  IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK +   dep_tristate '  Connection tracking flow accounting' CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK     dep_tristate '  Connection byte counter support' CONFIG_IP_NF_MATCH_CONNBYTES $CONFIG_IP_NF_CT_ACCT $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES -   dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK -   dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE  +  dep_tristate '  H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK   fi   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -@@ -110,6 +111,13 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ];  +@@ -94,6 +95,13 @@             define_tristate CONFIG_IP_NF_NAT_AMANDA $CONFIG_IP_NF_NAT           fi         fi @@ -22,29 +24,32 @@         if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then           dep_tristate '    Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT         fi ---- a/net/ipv4/netfilter/Makefile -+++ b/net/ipv4/netfilter/Makefile -@@ -53,6 +53,10 @@ obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack - ifdef CONFIG_IP_NF_NAT_PPTP - 	export-objs += ip_conntrack_pptp.o +Index: linux-2.4.37.5/net/ipv4/netfilter/Makefile +=================================================================== +--- linux-2.4.37.5.orig/net/ipv4/netfilter/Makefile	2009-09-03 01:07:45.000000000 -0700 ++++ linux-2.4.37.5/net/ipv4/netfilter/Makefile	2009-09-03 01:31:13.000000000 -0700 +@@ -47,12 +47,17 @@ + ifdef CONFIG_IP_NF_IRC + 	export-objs += ip_conntrack_irc.o   endif  +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o  +ifdef CONFIG_IP_NF_NAT_H323  +       export-objs += ip_conntrack_h323.o  +endif -    # NAT helpers  -@@ -62,6 +66,7 @@ obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ft + obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o + obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o + obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o   obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o - obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o - obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o  +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o   # generic IP tables    obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o ---- /dev/null -+++ b/net/ipv4/netfilter/ip_conntrack_h323.c +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_h323.c +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_conntrack_h323.c	2009-09-03 01:16:29.000000000 -0700  @@ -0,0 +1,302 @@  +/*   + * H.323 'brute force' extension for H.323 connection tracking.  @@ -348,8 +353,10 @@  +  +module_init(init);  +module_exit(fini); ---- /dev/null -+++ b/net/ipv4/netfilter/ip_nat_h323.c +Index: linux-2.4.37.5/net/ipv4/netfilter/ip_nat_h323.c +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.4.37.5/net/ipv4/netfilter/ip_nat_h323.c	2009-09-03 01:16:29.000000000 -0700  @@ -0,0 +1,403 @@  +/*   + * H.323 'brute force' extension for NAT alteration.  @@ -754,34 +761,38 @@  +  +module_init(init);  +module_exit(fini); ---- a/include/linux/netfilter_ipv4/ip_conntrack.h -+++ b/include/linux/netfilter_ipv4/ip_conntrack.h -@@ -71,6 +71,7 @@ union ip_conntrack_expect_proto { +Index: linux-2.4.37.5/include/linux/netfilter_ipv4/ip_conntrack.h +=================================================================== +--- linux-2.4.37.5.orig/include/linux/netfilter_ipv4/ip_conntrack.h	2009-09-03 00:17:57.000000000 -0700 ++++ linux-2.4.37.5/include/linux/netfilter_ipv4/ip_conntrack.h	2009-09-03 01:28:53.000000000 -0700 +@@ -67,6 +67,7 @@ +    #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>   #include <linux/netfilter_ipv4/ip_conntrack_irc.h> - #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>  +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>   /* per expectation: application helper private data */   union ip_conntrack_expect_help { -@@ -79,6 +80,7 @@ union ip_conntrack_expect_help { +@@ -74,6 +75,7 @@ + 	struct ip_ct_amanda_expect exp_amanda_info;   	struct ip_ct_ftp_expect exp_ftp_info;   	struct ip_ct_irc_expect exp_irc_info; - 	struct ip_ct_pptp_expect exp_pptp_info;  +	struct ip_ct_h225_expect exp_h225_info;   #ifdef CONFIG_IP_NF_NAT_NEEDED   	union { -@@ -93,6 +95,7 @@ union ip_conntrack_help { +@@ -87,6 +89,7 @@ + 	/* insert conntrack helper private data (master) here */   	struct ip_ct_ftp_master ct_ftp_info;   	struct ip_ct_irc_master ct_irc_info; - 	struct ip_ct_pptp_master ct_pptp_info;  +	struct ip_ct_h225_master ct_h225_info;   };   #ifdef CONFIG_IP_NF_NAT_NEEDED ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h +Index: linux-2.4.37.5/include/linux/netfilter_ipv4/ip_conntrack_h323.h +=================================================================== +--- /dev/null	1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.4.37.5/include/linux/netfilter_ipv4/ip_conntrack_h323.h	2009-09-03 01:16:29.000000000 -0700  @@ -0,0 +1,30 @@  +#ifndef _IP_CONNTRACK_H323_H  +#define _IP_CONNTRACK_H323_H diff --git a/target/linux/generic-2.4/patches/625-netfilter_nat_pptp_fix.patch b/target/linux/generic-2.4/patches/625-netfilter_nat_pptp_fix.patch deleted file mode 100644 index c65c9614d..000000000 --- a/target/linux/generic-2.4/patches/625-netfilter_nat_pptp_fix.patch +++ /dev/null @@ -1,53 +0,0 @@ ---- a/net/ipv4/netfilter/ip_conntrack_pptp.c -+++ b/net/ipv4/netfilter/ip_conntrack_pptp.c -@@ -134,12 +134,11 @@ static int pptp_expectfn(struct ip_connt - } -  - /* timeout GRE data connections */ --static int pptp_timeout_related(struct ip_conntrack *ct) -+static int pptp_timeout_related(struct ip_conntrack *ct, const struct iphdr *iph) - { - 	struct list_head *cur_item, *next; - 	struct ip_conntrack_expect *exp; - 	enum ip_conntrack_info ctinfo; --	struct iphdr *iph; -  - 	/* FIXME: do we have to lock something ? */ - 	for (cur_item = ct->sibling_list.next; -@@ -245,7 +244,8 @@ pptp_inbound_pkt(struct tcphdr *tcph, - 		 struct pptp_pkt_hdr *pptph,  - 		 size_t datalen, - 		 struct ip_conntrack *ct, --		 enum ip_conntrack_info ctinfo) -+		 enum ip_conntrack_info ctinfo, -+		 const struct iphdr *iph) - { - 	struct PptpControlHeader *ctlh; -         union pptp_ctrl_union pptpReq; -@@ -377,7 +377,7 @@ pptp_inbound_pkt(struct tcphdr *tcph, - 		info->cstate = PPTP_CALL_NONE; -  - 		/* untrack this call id, unexpect GRE packets */ --		pptp_timeout_related(ct); -+		pptp_timeout_related(ct, iph); - 		break; -  - 	case PPTP_WAN_ERROR_NOTIFY: -@@ -539,7 +539,7 @@ conntrack_pptp_help(const struct iphdr * - 		info->cstate = PPTP_CALL_NONE; -  - 		/* untrack this call id, unexpect GRE packets */ --		pptp_timeout_related(ct); -+		pptp_timeout_related(ct, iph); - 	} -  -  -@@ -571,7 +571,7 @@ conntrack_pptp_help(const struct iphdr * - 		ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo); - 	else - 		/* server -> client (PAC -> PNS) */ --		ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo); -+		ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo, iph); - 	DEBUGP("sstate: %d->%d, cstate: %d->%d\n", - 		oldsstate, info->sstate, oldcstate, info->cstate); - 	UNLOCK_BH(&ip_pptp_lock);  | 
