--- linux-2.4.19-pre8/net/ipv4/netfilter/ip_conntrack_core.c.hej	Sun May 19 00:59:00 2002
+++ linux-2.4.19-pre8/net/ipv4/netfilter/ip_conntrack_core.c	Wed May 22 14:54:25 2002
@@ -1258,6 +1261,8 @@
 
 #define NET_IP_CONNTRACK_MAX 2089
 #define NET_IP_CONNTRACK_MAX_NAME "ip_conntrack_max"
+#define NET_IP_CONNTRACK_PICKUP 2090
+#define NET_IP_CONNTRACK_PICKUP_NAME "ip_conntrack_pickup"
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *ip_conntrack_sysctl_header;
@@ -1265,6 +1270,8 @@
 static ctl_table ip_conntrack_table[] = {
 	{ NET_IP_CONNTRACK_MAX, NET_IP_CONNTRACK_MAX_NAME, &ip_conntrack_max,
 	  sizeof(ip_conntrack_max), 0644,  NULL, proc_dointvec },
+	{ NET_IP_CONNTRACK_PICKUP, NET_IP_CONNTRACK_PICKUP_NAME, &ip_conntrack_pickup,
+	  sizeof(ip_conntrack_pickup), 0644,  NULL, proc_dointvec },
  	{ 0 }
 };
 
--- linux-2.4.19-pre8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c.hej	Sun May 19 01:07:40 2002
+++ linux-2.4.19-pre8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	Wed May 22 14:55:14 2002
@@ -23,6 +23,8 @@
 /* Protects conntrack->proto.tcp */
 static DECLARE_RWLOCK(tcp_lock);
 
+static int ip_conntrack_pickup = 1;
+
 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
    closely.  They're more complex. --RR */
 
@@ -75,24 +77,48 @@
 #define sLI TCP_CONNTRACK_LISTEN
 #define sIV TCP_CONNTRACK_MAX
 
-static enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = {
+static enum tcp_conntrack tcp_conntracks[2][2][5][TCP_CONNTRACK_MAX] = {
 	{
-/*	ORIGINAL */
-/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
-/*syn*/	{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI },
-/*fin*/	{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI },
-/*ack*/	{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES },
-/*rst*/ {sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL },
-/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+		/* No pickup */
+		{
+	/*     ORIGINAL */
+	/*       sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI      */
+	/*syn*/        {sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI },
+	/*fin*/        {sIV, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI },
+	/*ack*/        {sIV, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES },
+	/*rst*/ {sIV, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL },
+	/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+		},
+		{
+	/*     REPLY */
+	/*       sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI      */
+	/*syn*/        {sIV, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR },
+	/*fin*/        {sIV, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI },
+	/*ack*/        {sIV, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI },
+	/*rst*/ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI },
+	/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+		}
 	},
 	{
-/*	REPLY */
-/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
-/*syn*/	{sSR, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR },
-/*fin*/	{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI },
-/*ack*/	{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI },
-/*rst*/ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI },
-/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+		/* Normal mode with pickup */
+		{
+	/*	ORIGINAL */
+	/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
+	/*syn*/	{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI },
+	/*fin*/	{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI },
+	/*ack*/	{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES },
+	/*rst*/ {sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL },
+	/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+		},
+		{
+	/*	REPLY */
+	/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
+	/*syn*/	{sSR, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR },
+	/*fin*/	{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI },
+	/*ack*/	{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI },
+	/*rst*/ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI },
+	/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+		}
 	}
 };
 
@@ -165,6 +191,7 @@
 	oldtcpstate = conntrack->proto.tcp.state;
 	newconntrack
 		= tcp_conntracks
+		[!!ip_conntrack_pickup]
 		[CTINFO2DIR(ctinfo)]
 		[get_conntrack_index(tcph)][oldtcpstate];
 
@@ -217,7 +244,7 @@
 
 	/* Don't need lock here: this conntrack not in circulation yet */
 	newconntrack
-		= tcp_conntracks[0][get_conntrack_index(tcph)]
+		= tcp_conntracks[!!ip_conntrack_pickup][0][get_conntrack_index(tcph)]
 		[TCP_CONNTRACK_NONE];
 
 	/* Invalid: delete conntrack */
--- linux-2.4.19-pre8/include/linux/netfilter_ipv4/ip_conntrack_protocol.h.hej	Sun May 19 01:53:08 2002
+++ linux-2.4.19-pre8/include/linux/netfilter_ipv4/ip_conntrack_protocol.h	Wed May 22 14:55:37 2002
@@ -62,4 +62,7 @@
 extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
 extern int ip_conntrack_protocol_tcp_init(void);
+
+extern int ip_conntrack_pickup;
+
 #endif /*_IP_CONNTRACK_PROTOCOL_H*/
