[netfilter-cvslog] r4073 - in trunk/patch-o-matic-ng/patchlets: nf-log tcp-window-tracking

kadlec at netfilter.org kadlec at netfilter.org
Tue Jun 28 12:12:55 CEST 2005


Author: kadlec at netfilter.org
Date: 2005-06-28 12:12:55 +0200 (Tue, 28 Jun 2005)
New Revision: 4073

Modified:
   trunk/patch-o-matic-ng/patchlets/nf-log/linux-2.4.patch
   trunk/patch-o-matic-ng/patchlets/tcp-window-tracking/linux-2.4.patch
Log:
nf-log patch updated to reflect changes in the 2.4 tree
TCP window tracking patch backported from the 2.6 tree


Modified: trunk/patch-o-matic-ng/patchlets/nf-log/linux-2.4.patch
===================================================================
--- trunk/patch-o-matic-ng/patchlets/nf-log/linux-2.4.patch	2005-06-28 09:37:27 UTC (rev 4072)
+++ trunk/patch-o-matic-ng/patchlets/nf-log/linux-2.4.patch	2005-06-28 10:12:55 UTC (rev 4073)
@@ -1,6 +1,6 @@
-diff -urN --exclude-from=diff.exclude linux-2.4.20-base/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.4.20-log/include/linux/netfilter_ipv4/ipt_ULOG.h
---- linux-2.4.20-base/include/linux/netfilter_ipv4/ipt_ULOG.h	2002-02-25 20:38:13.000000000 +0100
-+++ linux-2.4.20-log/include/linux/netfilter_ipv4/ipt_ULOG.h	2003-05-09 08:05:11.000000000 +0200
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-orig/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.4.31-nf-log/include/linux/netfilter_ipv4/ipt_ULOG.h
+--- linux-2.4.31-orig/include/linux/netfilter_ipv4/ipt_ULOG.h	2002-02-25 20:38:13.000000000 +0100
++++ linux-2.4.31-nf-log/include/linux/netfilter_ipv4/ipt_ULOG.h	2005-06-27 17:42:29.000000000 +0200
 @@ -11,6 +11,9 @@
  #define NETLINK_NFLOG 	5
  #endif
@@ -11,9 +11,9 @@
  #define ULOG_MAC_LEN	80
  #define ULOG_PREFIX_LEN	32
  
-diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/core/netfilter.c linux-2.4.20-log/net/core/netfilter.c
---- linux-2.4.20-base/net/core/netfilter.c	2002-08-03 02:39:46.000000000 +0200
-+++ linux-2.4.20-log/net/core/netfilter.c	2003-05-13 19:23:34.000000000 +0200
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-orig/net/core/netfilter.c linux-2.4.31-nf-log/net/core/netfilter.c
+--- linux-2.4.31-orig/net/core/netfilter.c	2005-01-19 15:10:13.000000000 +0100
++++ linux-2.4.31-nf-log/net/core/netfilter.c	2005-06-27 17:42:30.000000000 +0200
 @@ -8,9 +8,12 @@
   *
   * February 2000: Modified by James Morris to have 1 queue per protocol.
@@ -27,7 +27,7 @@
  #include <net/protocol.h>
  #include <linux/init.h>
  #include <linux/skbuff.h>
-@@ -624,6 +627,75 @@
+@@ -622,6 +625,75 @@
  }
  #endif /*CONFIG_INET*/
  
@@ -103,22 +103,25 @@
  /* This does not belong here, but locally generated errors need it if connection
     tracking in use: without this, connection may not be in hash table, and hence
     manufactured ICMP or RST packets will not be associated with it. */
-diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/ipv4/netfilter/ipt_LOG.c linux-2.4.20-log/net/ipv4/netfilter/ipt_LOG.c
---- linux-2.4.20-base/net/ipv4/netfilter/ipt_LOG.c	2002-02-25 20:38:14.000000000 +0100
-+++ linux-2.4.20-log/net/ipv4/netfilter/ipt_LOG.c	2003-05-13 19:30:26.000000000 +0200
-@@ -12,6 +12,11 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-orig/net/ipv4/netfilter/ipt_LOG.c linux-2.4.31-nf-log/net/ipv4/netfilter/ipt_LOG.c
+--- linux-2.4.31-orig/net/ipv4/netfilter/ipt_LOG.c	2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.31-nf-log/net/ipv4/netfilter/ipt_LOG.c	2005-06-28 11:43:48.000000000 +0200
+@@ -10,9 +10,14 @@
+ #include <net/tcp.h>
+ #include <net/route.h>
  
++#include <linux/netfilter_logging.h>
  #include <linux/netfilter_ipv4/ip_tables.h>
  #include <linux/netfilter_ipv4/ipt_LOG.h>
-+#include <linux/netfilter_ipv4/ip_logging.h>
-+
+ 
 +static unsigned int nflog = 1;
 +MODULE_PARM(nflog, "i");
 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
- 
++
  #if 0
  #define DEBUGP printk
-@@ -270,23 +275,21 @@
+ #else
+@@ -298,23 +303,21 @@
  	/* maxlen = 230+   91  + 230 + 252 = 803 */
  }
  
@@ -148,7 +151,7 @@
  	       in ? in->name : "",
  	       out ? out->name : "");
  	if (in && !out) {
-@@ -306,10 +309,59 @@
+@@ -334,10 +337,59 @@
  	dump_packet(loginfo, iph, (*pskb)->len, 1);
  	printk("\n");
  	spin_unlock_bh(&log_lock);
@@ -208,7 +211,7 @@
  static int ipt_log_checkentry(const char *tablename,
  			      const struct ipt_entry *e,
  			      void *targinfo,
-@@ -341,17 +393,23 @@
+@@ -369,17 +421,23 @@
  static struct ipt_target ipt_log_reg
  = { { NULL, NULL }, "LOG", ipt_log_target, ipt_log_checkentry, NULL, 
      THIS_MODULE };
@@ -221,7 +224,7 @@
  		return -EINVAL;
 -
 +	if (nflog)
-+		nf_ip_log_register(&ip_logging_fn);
++		nf_log_register(PF_INET, &ip_logging_fn);
 +	
  	return 0;
  }
@@ -229,22 +232,22 @@
  static void __exit fini(void)
  {
 +	if (nflog)
-+		nf_ip_log_unregister(&ip_logging_fn);
++		nf_log_unregister(PF_INET, &ip_logging_fn);
  	ipt_unregister_target(&ipt_log_reg);
  }
  
-diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/ipv4/netfilter/ipt_ULOG.c linux-2.4.20-log/net/ipv4/netfilter/ipt_ULOG.c
---- linux-2.4.20-base/net/ipv4/netfilter/ipt_ULOG.c	2003-03-24 17:22:51.000000000 +0100
-+++ linux-2.4.20-log/net/ipv4/netfilter/ipt_ULOG.c	2003-05-13 19:30:40.000000000 +0200
-@@ -48,6 +48,7 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-orig/net/ipv4/netfilter/ipt_ULOG.c linux-2.4.31-nf-log/net/ipv4/netfilter/ipt_ULOG.c
+--- linux-2.4.31-orig/net/ipv4/netfilter/ipt_ULOG.c	2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.31-nf-log/net/ipv4/netfilter/ipt_ULOG.c	2005-06-28 11:43:59.000000000 +0200
+@@ -49,6 +49,7 @@
+ #include <linux/netdevice.h>
  #include <linux/mm.h>
  #include <linux/socket.h>
++#include <linux/netfilter_logging.h>
  #include <linux/netfilter_ipv4/ip_tables.h>
-+#include <linux/netfilter_ipv4/ip_logging.h>
  #include <linux/netfilter_ipv4/ipt_ULOG.h>
  #include <linux/netfilter_ipv4/lockhelp.h>
- #include <net/sock.h>
-@@ -77,6 +78,10 @@
+@@ -79,6 +80,10 @@
  MODULE_PARM(flushtimeout, "i");
  MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
  
@@ -255,7 +258,7 @@
  /* global data structures */
  
  typedef struct {
-@@ -154,17 +159,17 @@
+@@ -155,17 +160,17 @@
  	return skb;
  }
  
@@ -279,7 +282,7 @@
  
  	/* ffs == find first bit set, necessary because userspace
  	 * is already shifting groupnumber, but we need unshifted.
-@@ -215,7 +220,9 @@
+@@ -216,7 +221,9 @@
  	pm->timestamp_usec = (*pskb)->stamp.tv_usec;
  	pm->mark = (*pskb)->nfmark;
  	pm->hook = hooknum;
@@ -290,7 +293,7 @@
  		strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
  	else
  		*(pm->prefix) = '\0';
-@@ -262,8 +269,7 @@
+@@ -264,8 +271,7 @@
  
  	UNLOCK_BH(&ulog_lock);
  
@@ -300,7 +303,7 @@
  
  nlmsg_failure:
  	PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
-@@ -272,8 +278,128 @@
+@@ -274,8 +280,128 @@
  	PRINTR("ipt_ULOG: Error building netlink message\n");
  
  	UNLOCK_BH(&ulog_lock);
@@ -313,7 +316,8 @@
 +				    const void *targinfo, void *userinfo)
 +{
 +	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
-+
+ 
+-	return IPT_CONTINUE;
 +	ipt_ulog_packet(pskb, hooknum, in, out, loginfo, NULL);
 + 
 + 	return IPT_CONTINUE;
@@ -421,8 +425,7 @@
 +
 +nlmsg_failure:
 +	PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
- 
--	return IPT_CONTINUE;
++
 +alloc_failure:
 +	PRINTR("ipt_ULOG: Error building netlink message\n");
 +
@@ -430,7 +433,7 @@
  }
  
  static int ipt_ulog_checkentry(const char *tablename,
-@@ -308,6 +434,8 @@
+@@ -310,6 +436,8 @@
      { {NULL, NULL}, "ULOG", ipt_ulog_target, ipt_ulog_checkentry, NULL,
  THIS_MODULE
  };
@@ -439,61 +442,38 @@
  
  static int __init init(void)
  {
-@@ -336,7 +464,9 @@
+@@ -337,7 +465,9 @@
  		sock_release(nflognl->socket);
  		return -EINVAL;
  	}
 -
 +	if (nflog)
-+		nf_ip_log_register(&ip_logging_fn);
++		nf_log_register(PF_INET, &ip_logging_fn);
 +	
  	return 0;
  }
  
-@@ -347,6 +477,8 @@
+@@ -348,6 +478,8 @@
  
  	DEBUGP("ipt_ULOG: cleanup_module\n");
  
 +	if (nflog)
-+		nf_ip_log_unregister(&ip_logging_fn);
++		nf_log_unregister(PF_INET, &ip_logging_fn);
  	ipt_unregister_target(&ipt_ulog_reg);
  	sock_release(nflognl->socket);
  
-diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/netsyms.c linux-2.4.20-log/net/netsyms.c
---- linux-2.4.20-base/net/netsyms.c	2003-05-09 17:34:23.000000000 +0200
-+++ linux-2.4.20-log/net/netsyms.c	2003-05-09 17:36:32.000000000 +0200
-@@ -572,6 +572,7 @@
- #endif
- #ifdef CONFIG_NETFILTER
- #include <linux/netfilter.h>
-+#include <linux/netfilter_logging.h>
- EXPORT_SYMBOL(nf_register_hook);
- EXPORT_SYMBOL(nf_unregister_hook);
- EXPORT_SYMBOL(nf_register_sockopt);
-@@ -584,6 +585,10 @@
- EXPORT_SYMBOL(nf_setsockopt);
- EXPORT_SYMBOL(nf_getsockopt);
- EXPORT_SYMBOL(ip_ct_attach);
- EXPORT_SYMBOL(nf_ct_attach);
-+EXPORT_SYMBOL(nf_log_register);
-+EXPORT_SYMBOL(nf_log_unregister);
-+EXPORT_SYMBOL(nf_log_packet);
-+EXPORT_SYMBOL(nf_log);
- #ifdef CONFIG_INET
- #include <linux/netfilter_ipv4.h>
- EXPORT_SYMBOL(ip_route_me_harder);
-diff -urN --exclude-from=diff.exclude linux-2.4.20-base/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.20-log/net/ipv6/netfilter/ip6t_LOG.c
---- linux-2.4.20-base/net/ipv6/netfilter/ip6t_LOG.c	2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.20-log/net/ipv6/netfilter/ip6t_LOG.c	2003-05-13 19:31:03.000000000 +0200
-@@ -10,6 +10,7 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-orig/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.31-nf-log/net/ipv6/netfilter/ip6t_LOG.c
+--- linux-2.4.31-orig/net/ipv6/netfilter/ip6t_LOG.c	2005-01-19 15:10:14.000000000 +0100
++++ linux-2.4.31-nf-log/net/ipv6/netfilter/ip6t_LOG.c	2005-06-28 11:51:21.000000000 +0200
+@@ -9,6 +9,7 @@
+ #include <net/udp.h>
  #include <net/tcp.h>
  #include <net/ipv6.h>
++#include <linux/netfilter_logging.h>
  #include <linux/netfilter_ipv6/ip6_tables.h>
-+#include <linux/netfilter_ipv6/ip6_logging.h>
  
  MODULE_AUTHOR("Jan Rekorajski <baggins at pld.org.pl>");
- MODULE_DESCRIPTION("IP6 tables LOG target module");
-@@ -266,23 +267,21 @@
+@@ -355,23 +356,21 @@
  	}
  }
  
@@ -523,8 +503,8 @@
  		in ? in->name : "",
  		out ? out->name : "");
  	if (in && !out) {
-@@ -329,10 +328,59 @@
- 	dump_packet(loginfo, ipv6h, 1);
+@@ -419,10 +418,41 @@
+ 		    1);
  	printk("\n");
  	spin_unlock_bh(&log_lock);
 +}
@@ -562,46 +542,28 @@
 +	ip6t_log_packet(pskb, hooknum, in, out, &loginfo, KERN_WARNING, prefix);
 +}
 +
-+static void
-+ip6_log_fn(char *pfh, size_t len,
-+	   const char *prefix)
-+{
-+	struct ipv6hdr *ipv6h = (struct ipv6hdr *)pfh;
-+	struct ip6t_log_info loginfo = { 
-+		.level = 0,
-+		.logflags = IP6T_LOG_MASK,
-+		.prefix = ""
-+	};
-+
-+	spin_lock_bh(&log_lock);
-+	printk(KERN_WARNING "%s", prefix);
-+	dump_packet(&loginfo, ipv6h, 1);
-+	printk("\n");
-+	spin_unlock_bh(&log_lock);
-+}
-+
  static int ip6t_log_checkentry(const char *tablename,
  			       const struct ip6t_entry *e,
  			       void *targinfo,
-@@ -364,17 +412,21 @@
+@@ -454,17 +484,21 @@
  static struct ip6t_target ip6t_log_reg
  = { { NULL, NULL }, "LOG", ip6t_log_target, ip6t_log_checkentry, NULL, 
      THIS_MODULE };
 +static struct nf_logging_t ip6_logging_fn
-+= { ip6_log_packet_fn, ip6_log_fn };
++= { ip6_log_packet_fn };
  
  static int __init init(void)
  {
  	if (ip6t_register_target(&ip6t_log_reg))
  		return -EINVAL;
-+	nf_ip6_log_register(&ip6_logging_fn);
++	nf_log_register(PF_INET6, &ip6_logging_fn);
  
  	return 0;
  }
  
  static void __exit fini(void)
  {
-+	nf_ip6_log_unregister(&ip6_logging_fn);
++	nf_log_unregister(PF_INET6, &ip6_logging_fn);
  	ip6t_unregister_target(&ip6t_log_reg);
  }
  

Modified: trunk/patch-o-matic-ng/patchlets/tcp-window-tracking/linux-2.4.patch
===================================================================
--- trunk/patch-o-matic-ng/patchlets/tcp-window-tracking/linux-2.4.patch	2005-06-28 09:37:27 UTC (rev 4072)
+++ trunk/patch-o-matic-ng/patchlets/tcp-window-tracking/linux-2.4.patch	2005-06-28 10:12:55 UTC (rev 4073)
@@ -1,22 +1,22 @@
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.23-tcp-win/include/linux/netfilter_ipv4/ip_conntrack.h
---- linux-2.4.23-pending/include/linux/netfilter_ipv4/ip_conntrack.h	2003-12-04 17:02:36.000000000 +0100
-+++ linux-2.4.23-tcp-win/include/linux/netfilter_ipv4/ip_conntrack.h	2004-05-19 15:49:51.000000000 +0200
-@@ -256,6 +256,11 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.31-tcp-win/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.4.31-nf-log/include/linux/netfilter_ipv4/ip_conntrack.h	2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.31-tcp-win/include/linux/netfilter_ipv4/ip_conntrack.h	2005-06-28 11:00:54.000000000 +0200
+@@ -246,6 +246,11 @@
  			  unsigned long extra_jiffies);
  
  /* These are for NAT.  Icky. */
-+/* Update TCP window tracking data when NAT mangles the packet */
-+extern void ip_conntrack_tcp_update(struct sk_buff *skb,
-+				    struct ip_conntrack *conntrack, 
-+				    int dir);
++/* Update TCP window tracking data after NAT successfully mangled the packet */
++extern int ip_conntrack_tcp_update(struct sk_buff *skb,
++				   struct ip_conntrack *conntrack, 
++				   int dir);
 +
  /* Call me when a conntrack is destroyed. */
  extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
  
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/include/linux/netfilter_ipv4/ip_conntrack_tcp.h linux-2.4.23-tcp-win/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
---- linux-2.4.23-pending/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.23-tcp-win/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2004-05-19 14:56:42.000000000 +0200
-@@ -4,25 +4,44 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/include/linux/netfilter_ipv4/ip_conntrack_tcp.h linux-2.4.31-tcp-win/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
+--- linux-2.4.31-nf-log/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2002-11-29 00:53:15.000000000 +0100
++++ linux-2.4.31-tcp-win/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2005-06-27 15:32:43.000000000 +0200
+@@ -4,25 +4,47 @@
  
  enum tcp_conntrack {
  	TCP_CONNTRACK_NONE,
@@ -38,18 +38,21 @@
 +};
 +
 +/* Window scaling is advertised by the sender */
-+#define IP_CT_TCP_STATE_FLAG_WINDOW_SCALE	0x01
++#define IP_CT_TCP_FLAG_WINDOW_SCALE		0x01
 +
 +/* SACK is permitted by the sender */
 +#define IP_CT_TCP_FLAG_SACK_PERM		0x02
 +
++/* This sender sent FIN first */
++#define IP_CT_TCP_FLAG_CLOSE_INIT		0x03
++
 +struct ip_ct_tcp_state {
 +	u_int32_t	td_end;		/* max of seq + len */
 +	u_int32_t	td_maxend;	/* max of ack + max(win, 1) */
 +	u_int32_t	td_maxwin;	/* max(win) */
 +	u_int8_t	td_scale;	/* window scale factor */
 +	u_int8_t	loose;		/* used when connection picked up from the middle */
-+	u_int8_t	flags;		/* per direction state flags */
++	u_int8_t	flags;		/* per direction options */
  };
  
  struct ip_ct_tcp
@@ -64,31 +67,31 @@
 +	/* For detecting stale connections */
 +	u_int8_t	last_dir;	/* Direction of the last packet (enum ip_conntrack_dir) */
 +	u_int8_t	retrans;	/* Number of retransmitted packets */
-+	u_int8_t	stored_seq;	/* What is stored in last_seq */
++	u_int8_t	last_index;	/* Index of the last packet */
 +	u_int32_t	last_seq;	/* Last sequence number seen in dir */
 +	u_int32_t	last_end;	/* Last seq + len */
  };
  
  #endif /* _IP_CONNTRACK_TCP_H */
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/include/linux/sysctl.h linux-2.4.23-tcp-win/include/linux/sysctl.h
---- linux-2.4.23-pending/include/linux/sysctl.h	2003-12-04 16:45:18.000000000 +0100
-+++ linux-2.4.23-tcp-win/include/linux/sysctl.h	2003-12-09 09:42:57.000000000 +0100
-@@ -377,6 +377,11 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/include/linux/sysctl.h linux-2.4.31-tcp-win/include/linux/sysctl.h
+--- linux-2.4.31-nf-log/include/linux/sysctl.h	2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.31-tcp-win/include/linux/sysctl.h	2005-06-28 10:56:32.000000000 +0200
+@@ -396,6 +396,11 @@
  	NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
  	NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
  	NET_IPV4_NF_CONNTRACK_BUCKETS=14,
-+ 	NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS=15,
-+ 	NET_IPV4_NF_CONNTRACK_TCP_LOG_INVALID=16,
-+ 	NET_IPV4_NF_CONNTRACK_TCP_LOOSE=17,
-+ 	NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL=18,
-+ 	NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS=19,
++	NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS=15,
++	NET_IPV4_NF_CONNTRACK_TCP_LOG_INVALID=16,
++	NET_IPV4_NF_CONNTRACK_TCP_LOOSE=17,
++	NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL=18,
++	NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS=19,
  };
   
  /* /proc/sys/net/ipv6 */
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_core.c
---- linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_core.c	2003-12-04 16:56:14.000000000 +0100
-+++ linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_core.c	2003-12-09 09:30:21.000000000 +0100
-@@ -864,11 +864,12 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_core.c
+--- linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_core.c	2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_core.c	2005-06-27 17:29:09.000000000 +0200
+@@ -874,11 +874,12 @@
  	IP_NF_ASSERT((*pskb)->nfct);
  
  	ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo);
@@ -104,9 +107,9 @@
  	}
  
  	if (ret != NF_DROP && ct->helper) {
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_ftp.c
---- linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-08-25 13:44:44.000000000 +0200
-+++ linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-12-09 09:30:21.000000000 +0100
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_ftp.c
+--- linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_ftp.c	2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_ftp.c	2005-06-27 17:31:07.000000000 +0200
 @@ -4,7 +4,6 @@
  #include <linux/netfilter.h>
  #include <linux/ip.h>
@@ -152,9 +155,9 @@
  	LOCK_BH(&ip_ftp_lock);
  	old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir];
  	old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir];
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_irc.c
---- linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_irc.c	2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_irc.c	2003-12-09 09:30:21.000000000 +0100
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_irc.c
+--- linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_irc.c	2004-11-17 12:54:22.000000000 +0100
++++ linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_irc.c	2005-06-27 17:32:26.000000000 +0200
 @@ -26,7 +26,6 @@
  #include <linux/module.h>
  #include <linux/netfilter.h>
@@ -162,8 +165,8 @@
 -#include <net/checksum.h>
  #include <net/tcp.h>
  
- #include <linux/netfilter_ipv4/lockhelp.h>
-@@ -109,13 +108,12 @@
+ #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+@@ -107,13 +106,12 @@
  static int help(const struct iphdr *iph, size_t len,
  		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
  {
@@ -179,7 +182,7 @@
  	int dir = CTINFO2DIR(ctinfo);
  	struct ip_conntrack_expect expect, *exp = &expect;
  	struct ip_ct_irc_expect *exp_irc_info = &exp->help.exp_irc_info;
-@@ -138,22 +136,6 @@
+@@ -136,22 +134,6 @@
  		return NF_ACCEPT;
  	}
  
@@ -202,17 +205,17 @@
  	data_limit = (char *) data + datalen;
  
  	/* strlen("\1DCC SEND t AAAAAAAA P\1\n")=24
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
---- linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2004-05-21 14:57:01.000000000 +0200
-@@ -1,3 +1,26 @@
-+/*
-+ * TCP connection tracking
-+ */
-+
-+/* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
-+ * Public Licence. 
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+--- linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2003-11-28 19:26:21.000000000 +0100
++++ linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2005-06-27 18:00:13.000000000 +0200
+@@ -1,3 +1,25 @@
++/* (C) 1999-2001 Paul `Rusty' Russell
++ * (C) 2002-2004 Netfilter Core Team <coreteam at netfilter.org>
 + *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
 + * Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>:
 + *	- Real stateful connection tracking
 + *	- Modified state transitions table
@@ -227,12 +230,11 @@
 + * version 2.2
 + */
 +
-+#define __NO_VERSION__
 +#include <linux/config.h>
  #include <linux/types.h>
  #include <linux/sched.h>
  #include <linux/timer.h>
-@@ -6,101 +29,268 @@
+@@ -6,45 +28,66 @@
  #include <linux/in.h>
  #include <linux/ip.h>
  #include <linux/tcp.h>
@@ -241,9 +243,11 @@
  
  #include <net/tcp.h>
  
++#include <linux/netfilter.h>
++#include <linux/netfilter_logging.h>
++#include <linux/netfilter_ipv4.h>
  #include <linux/netfilter_ipv4/ip_conntrack.h>
  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-+#include <linux/netfilter_ipv4/ip_logging.h>
  #include <linux/netfilter_ipv4/lockhelp.h>
  
  #if 0
@@ -258,8 +262,10 @@
  /* Protects conntrack->proto.tcp */
  static DECLARE_RWLOCK(tcp_lock);
  
+-/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
+-   closely.  They're more complex. --RR */
 +/* Log invalid/ignored packets */
-+int ip_ct_tcp_log_invalid = 1;
++int ip_ct_tcp_log_invalid = 0;
 +
 +/* "Be conservative in what you do, 
 +    be liberal in what you accept from others." 
@@ -269,22 +275,22 @@
 +/* When connection is picked up from the middle, how many packets are required
 +   to pass in each direction when we assume we are in sync - if any side uses
 +   window scaling, we lost the game. 
-+   If it is set to zero, we disable picking up already established connections. */
++   If it is set to zero, we disable picking up already established 
++   connections. */
 +int ip_ct_tcp_loose = 3;
 +
 +/* Max number of the retransmitted packets without receiving an (acceptable) 
 +   ACK from the destination. If this number is reached, a shorter timer 
 +   will be started. */
 +int ip_ct_tcp_max_retrans = 3;
-+
- /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
-    closely.  They're more complex. --RR */
  
 -/* Actually, I believe that neither ipmasq (where this code is stolen
 -   from) nor ipfilter do it exactly right.  A new conntrack machine taking
 -   into account packet loss (which creates uncertainty as to exactly
 -   the conntrack of the connection) is required.  RSN.  --RR */
--
++  /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
++     closely.  They're more complex. --RR */
+ 
  static const char *tcp_conntrack_names[] = {
  	"NONE",
 -	"ESTABLISHED",
@@ -300,60 +306,40 @@
 +	"CLOSE",
  	"LISTEN"
  };
- 
+-
 -#define SECS *HZ
++  
 +#define SECS * HZ
  #define MINS * 60 SECS
  #define HOURS * 60 MINS
  #define DAYS * 24 HOURS
+@@ -58,50 +101,199 @@
+ unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;
+ unsigned long ip_ct_tcp_timeout_close =        10 SECS;
  
--unsigned long ip_ct_tcp_timeout_syn_sent =      2 MINS;
--unsigned long ip_ct_tcp_timeout_syn_recv =     60 SECS;
--unsigned long ip_ct_tcp_timeout_established =   5 DAYS;
--unsigned long ip_ct_tcp_timeout_fin_wait =      2 MINS;
--unsigned long ip_ct_tcp_timeout_close_wait =   60 SECS;
--unsigned long ip_ct_tcp_timeout_last_ack =     30 SECS;
--unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;
--unsigned long ip_ct_tcp_timeout_close =        10 SECS;
-+unsigned long ip_ct_tcp_timeout_syn_sent =	 2 MINS;
-+unsigned long ip_ct_tcp_timeout_syn_recv =	60 SECS;
-+unsigned long ip_ct_tcp_timeout_established =	 5 DAYS;
-+unsigned long ip_ct_tcp_timeout_fin_wait =	 2 MINS;
-+unsigned long ip_ct_tcp_timeout_close_wait =	10 MINS;
-+unsigned long ip_ct_tcp_timeout_last_ack =	90 SECS;
-+unsigned long ip_ct_tcp_timeout_time_wait =	 2 MINS;
-+unsigned long ip_ct_tcp_timeout_close =		90 SECS;
-+
 +/* RFC1122 says the R2 limit should be at least 100 seconds.
 +   Linux uses 15 packets as limit, which corresponds 
 +   to ~13-30min depending on RTO. */
 +unsigned long ip_ct_tcp_timeout_max_retrans =     5 MINS;
- 
++ 
  static unsigned long * tcp_timeouts[]
 -= { 0,                                 /*      TCP_CONNTRACK_NONE */
 -    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
--    &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */
--    &ip_ct_tcp_timeout_syn_recv,       /*      TCP_CONNTRACK_SYN_RECV, */
--    &ip_ct_tcp_timeout_fin_wait,       /*      TCP_CONNTRACK_FIN_WAIT, */
++= { NULL,                              /*      TCP_CONNTRACK_NONE */
+     &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */
+     &ip_ct_tcp_timeout_syn_recv,       /*      TCP_CONNTRACK_SYN_RECV, */
++    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
+     &ip_ct_tcp_timeout_fin_wait,       /*      TCP_CONNTRACK_FIN_WAIT, */
 -    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
 -    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
--    &ip_ct_tcp_timeout_close_wait,     /*      TCP_CONNTRACK_CLOSE_WAIT,       */
--    &ip_ct_tcp_timeout_last_ack,       /*      TCP_CONNTRACK_LAST_ACK, */
+     &ip_ct_tcp_timeout_close_wait,     /*      TCP_CONNTRACK_CLOSE_WAIT,       */
+     &ip_ct_tcp_timeout_last_ack,       /*      TCP_CONNTRACK_LAST_ACK, */
 -    0,                                 /*      TCP_CONNTRACK_LISTEN */
-- };
-- 
-+= { 0,					/*	TCP_CONNTRACK_NONE */
-+    &ip_ct_tcp_timeout_syn_sent,	/*	TCP_CONNTRACK_SYN_SENT,	*/
-+    &ip_ct_tcp_timeout_syn_recv,	/*	TCP_CONNTRACK_SYN_RECV,	*/
-+    &ip_ct_tcp_timeout_established,	/*	TCP_CONNTRACK_ESTABLISHED,	*/
-+    &ip_ct_tcp_timeout_fin_wait,	/*	TCP_CONNTRACK_FIN_WAIT,	*/
-+    &ip_ct_tcp_timeout_close_wait,	/*	TCP_CONNTRACK_CLOSE_WAIT,	*/
-+    &ip_ct_tcp_timeout_last_ack,	/*	TCP_CONNTRACK_LAST_ACK,	*/
-+    &ip_ct_tcp_timeout_time_wait,	/*	TCP_CONNTRACK_TIME_WAIT,	*/
-+    &ip_ct_tcp_timeout_close,		/*	TCP_CONNTRACK_CLOSE,	*/
-+    0,					/*	TCP_CONNTRACK_LISTEN */
-+};
-+
++    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
++    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
++    NULL,                              /*      TCP_CONNTRACK_LISTEN */
+  };
+  
  #define sNO TCP_CONNTRACK_NONE
 -#define sES TCP_CONNTRACK_ESTABLISHED
  #define sSS TCP_CONNTRACK_SYN_SENT
@@ -380,7 +366,7 @@
 +	TCP_RST_SET,
 +	TCP_NONE_SET,
 +};
-+
++  
 +/*
 + * The TCP state transition table needs a few words...
 + *
@@ -493,6 +479,7 @@
 -/*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 }
+-	}
 +/* REPLY */
 +/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
 +/*syn*/	   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
@@ -513,7 +500,7 @@
 + *	sSS -> sSR	Standard open.
 + *	sSR -> sSR	Retransmitted SYN/ACK.
 + *	sES -> sIG	Late retransmitted SYN/ACK?
-+ *	sFW -> sIG
++ *	sFW -> sIG	Might be SYN/ACK answering ignored SYN
 + *	sCW -> sIG
 + *	sLA -> sIG
 + *	sTW -> sIG
@@ -532,10 +519,10 @@
 + *	sCL -> sCL
 + */
 +/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
-+/*ack*/	   { sIV, sIV, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV },
++/*ack*/	   { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
 +/*
-+ *	sSS -> sIV	ACK is invalid: we haven't seen a SYN/ACK yet.
-+ *	sSR -> sIV	Simultaneous open.
++ *	sSS -> sIV	Might be a half-open connection.
++ *	sSR -> sSR	Might answer late resent SYN.
 + *	sES -> sES	:-)
 + *	sFW -> sCW	Normal close request answered by ACK.
 + *	sCW -> sCW
@@ -546,16 +533,19 @@
 +/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
 +/*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
 +/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
- 	}
++  	}
  };
  
-@@ -145,13 +335,433 @@
- 	return sprintf(buffer, "%s ", tcp_conntrack_names[state]);
- }
+ static int tcp_pkt_to_tuple(const void *datah, size_t datalen,
+@@ -147,11 +339,484 @@
  
--static unsigned int get_conntrack_index(const struct tcphdr *tcph)
-+static inline unsigned int get_conntrack_index(const struct tcphdr *tcph)
-+{
+ static unsigned int get_conntrack_index(const struct tcphdr *tcph)
+ {
+-	if (tcph->rst) return 3;
+-	else if (tcph->syn) return 0;
+-	else if (tcph->fin) return 1;
+-	else if (tcph->ack) return 2;
+-	else return 4;
 +	if (tcph->rst) return TCP_RST_SET;
 +	else if (tcph->syn) return (tcph->ack ? TCP_SYNACK_SET : TCP_SYN_SET);
 +	else if (tcph->fin) return TCP_FIN_SET;
@@ -569,51 +559,57 @@
 +   http://www.nluug.nl/events/sane2000/papers.html
 +   http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
 +   
-+   The boundaries and the conditions are slightly changed:
-+   
++   The boundaries and the conditions are changed according to RFC793:
++   the packet must intersect the window (i.e. segments may be
++   after the right or before the left edge) and thus receivers may ACK
++   segments after the right edge of the window.
++
 +   	td_maxend = max(sack + max(win,1)) seen in reply packets
 +	td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
++	td_maxwin += seq + len - sender.td_maxend
++			if seq + len > sender.td_maxend
 +	td_end    = max(seq + len) seen in sent packets
 +   
-+   I. 	Upper bound for valid data:	seq + len <= sender.td_maxend
-+   II. 	Lower bound for valid data:	seq >= sender.td_end - receiver.td_maxwin
++   I.   Upper bound for valid data:	seq <= sender.td_maxend
++   II.  Lower bound for valid data:	seq + len >= sender.td_end - receiver.td_maxwin
 +   III.	Upper bound for valid ack:      sack <= receiver.td_end
 +   IV.	Lower bound for valid ack:	ack >= receiver.td_end - MAXACKWINDOW
-+
++   	
 +   where sack is the highest right edge of sack block found in the packet.
 +   	
 +   The upper bound limit for a valid ack is not ignored - 
 +   we doesn't have to deal with fragments. 
 +*/
 +
-+static inline __u32 segment_seq_plus_len(__u32 seq, size_t len, struct iphdr *iph,
++static inline __u32 segment_seq_plus_len(__u32 seq,
++					 size_t len,
++					 struct iphdr *iph,
 +					 struct tcphdr *tcph)
 +{
 +	return (seq + len - (iph->ihl + tcph->doff)*4
 +		+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
 +}
-+
++  
 +/* Fixme: what about big packets? */
 +#define MAXACKWINCONST			66000
-+#define MAXACKWINDOW(sender)		\
-+	((sender)->td_maxwin > MAXACKWINCONST ? (sender)->td_maxwin : MAXACKWINCONST)
-+
++#define MAXACKWINDOW(sender)						\
++	((sender)->td_maxwin > MAXACKWINCONST ? (sender)->td_maxwin	\
++					      : MAXACKWINCONST)
++  
 +/*
 + * Simplified tcp_parse_options routine from tcp_input.c
 + */
-+static void tcp_options(struct iphdr *iph, size_t len,
-+			struct tcphdr *tcph, 
++static void tcp_options(struct tcphdr *tcph, 
 +			struct ip_ct_tcp_state *state)
- {
--	if (tcph->rst) return 3;
--	else if (tcph->syn) return 0;
--	else if (tcph->fin) return 1;
--	else if (tcph->ack) return 2;
--	else return 4;
++{
 +	unsigned char *ptr;
 +	int length = (tcph->doff*4) - sizeof(struct tcphdr);
 +	
++	if (!length)
++		return;
++
 +	ptr = (unsigned char *)(tcph + 1);
++
 +	state->td_scale = 
 +	state->flags = 0;
 +	
@@ -638,14 +634,15 @@
 +			    && opsize == TCPOLEN_SACK_PERM)
 +				state->flags |= IP_CT_TCP_FLAG_SACK_PERM;
 +			else if (opcode == TCPOPT_WINDOW
-+			 	  && opsize == TCPOLEN_WINDOW) {
++				 && opsize == TCPOLEN_WINDOW) {
 +				state->td_scale = *(u_int8_t *)ptr;
 +				
 +				if (state->td_scale > 14) {
-+					/* See RFC1323 for an explanation of the limit to 14 */
++					/* See RFC1323 */
 +					state->td_scale = 14;
 +				}
-+				state->flags |= IP_CT_TCP_STATE_FLAG_WINDOW_SCALE;
++				state->flags |=
++					IP_CT_TCP_FLAG_WINDOW_SCALE;
 +			}
 +			ptr += opsize - 2;
 +			length -= opsize;
@@ -653,20 +650,26 @@
 +	}
 +}
 +
-+static void tcp_sack(struct tcphdr *tcph, __u32 *sack)
++static void tcp_sack(struct tcphdr *tcph,
++		     __u32 *sack)
 +{
-+	__u32 tmp;
 +	unsigned char *ptr;
 +	int length = (tcph->doff*4) - sizeof(struct tcphdr);
-+	
++	__u32 tmp;
++
++	if (!length)
++		return;
++
++	ptr = (unsigned char *)(tcph + 1);
 +	/* Fast path for timestamp-only option */
 +	if (length == TCPOLEN_TSTAMP_ALIGNED*4
-+	    && *(__u32 *)(tcph + 1) ==
-+	        __constant_ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
-+	        		 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
++	    && *(__u32 *)ptr ==
++	        __constant_ntohl((TCPOPT_NOP << 24) 
++	        		 | (TCPOPT_NOP << 16)
++	        		 | (TCPOPT_TIMESTAMP << 8)
++	        		 | TCPOLEN_TIMESTAMP))
 +		return;
 +		
-+	ptr = (unsigned char *)(tcph + 1);
 +	while (length > 0) {
 +		int opcode=*ptr++;
 +		int opsize, i;
@@ -685,12 +688,14 @@
 +				break;	/* don't parse partial options */
 +
 +			if (opcode == TCPOPT_SACK 
-+			    && opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)
-+			    && !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK)) {
++			    && opsize >= (TCPOLEN_SACK_BASE 
++			    		  + TCPOLEN_SACK_PERBLOCK)
++			    && !((opsize - TCPOLEN_SACK_BASE) 
++			    	 % TCPOLEN_SACK_PERBLOCK)) {
 +			    	for (i = 0;
 +			    	     i < (opsize - TCPOLEN_SACK_BASE);
 +			    	     i += TCPOLEN_SACK_PERBLOCK) {
-+					tmp = ntohl(*((u_int32_t *)(ptr+i) + 1));
++					tmp = ntohl(*((u_int32_t *)(ptr+i)+1));
 +					
 +					if (after(tmp, *sack))
 +						*sack = tmp;
@@ -705,6 +710,7 @@
 +
 +static int tcp_in_window(struct ip_ct_tcp *state, 
 +                         enum ip_conntrack_dir dir,
++                         unsigned int index,
 +                         struct iphdr *iph, size_t len,
 +                         struct tcphdr *tcph)
 +{
@@ -720,17 +726,22 @@
 +	ack = sack = ntohl(tcph->ack_seq);
 +	win = ntohs(tcph->window);
 +	end = segment_seq_plus_len(seq, len, iph, tcph);
-+
++	
 +	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
 +		tcp_sack(tcph, &sack);
 +		
 +	DEBUGP("tcp_in_window: START\n");
-+	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu seq=%u ack=%u sack=%u win=%u end=%u\n",
-+		NIPQUAD(iph->saddr), ntohs(tcph->source), NIPQUAD(iph->daddr), ntohs(tcph->dest),
++	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
++	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
++		NIPQUAD(iph->saddr), ntohs(tcph->source), 
++		NIPQUAD(iph->daddr), ntohs(tcph->dest),
 +		seq, ack, sack, win, end);
-+	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-+		sender->td_end, sender->td_maxend, sender->td_maxwin, sender->td_scale, 
-+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, receiver->td_scale);
++	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
++	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
++		sender->td_end, sender->td_maxend, sender->td_maxwin,
++		sender->td_scale, 
++		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, 
++		receiver->td_scale);
 +		
 +	if (sender->td_end == 0) {
 +		/*
@@ -744,14 +755,14 @@
 +			sender->td_maxend = end;
 +			sender->td_maxwin = (win == 0 ? 1 : win);
 +
-+			tcp_options(iph, len, tcph, sender);
++			tcp_options(tcph, sender);
 +			/* 
 +			 * RFC 1323:
 +			 * Both sides must send the Window Scale option
 +			 * to enable window scaling in either direction.
 +			 */
-+			if (!(sender->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE
-+			      && receiver->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE))
++			if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
++			      && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
 +				sender->td_scale = 
 +				receiver->td_scale = 0;
 +		} else {
@@ -764,9 +775,11 @@
 +			sender->td_maxwin = (win == 0 ? 1 : win);
 +			sender->td_maxend = end + sender->td_maxwin;
 +		}
-+	} else if (state->state == TCP_CONNTRACK_SYN_SENT
-+		   && dir == IP_CT_DIR_ORIGINAL
-+		   && after(end, sender->td_end)) {
++	} else if (((state->state == TCP_CONNTRACK_SYN_SENT
++		     && dir == IP_CT_DIR_ORIGINAL)
++		    || (state->state == TCP_CONNTRACK_SYN_RECV
++		        && dir == IP_CT_DIR_REPLY))
++		    && after(end, sender->td_end)) {
 +		/*
 +		 * RFC 793: "if a TCP is reinitialized ... then it need
 +		 * not wait at all; it must only be sure to use sequence 
@@ -776,7 +789,7 @@
 +		sender->td_maxend = end;
 +		sender->td_maxwin = (win == 0 ? 1 : win);
 +
-+		tcp_options(iph, len, tcph, sender);
++		tcp_options(tcph, sender);
 +	}
 +	
 +	if (!(tcph->ack)) {
@@ -784,7 +797,8 @@
 +		 * If there is no ACK, just pretend it was set and OK.
 +		 */
 +		ack = sack = receiver->td_end;
-+	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) == (TCP_FLAG_ACK|TCP_FLAG_RST)) 
++	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) == 
++		    (TCP_FLAG_ACK|TCP_FLAG_RST)) 
 +		   && (ack == 0)) {
 +		/*
 +		 * Broken TCP stacks, that set ACK in RST packets as well
@@ -793,39 +807,39 @@
 +		ack = sack = receiver->td_end;
 +	}
 +
-+	if (seq == end)
++	if (seq == end
++	    && (!tcph->rst 
++	        || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
 +		/*
 +		 * Packets contains no data: we assume it is valid
 +		 * and check the ack value only.
++		 * However RST segments are always validated by their
++		 * SEQ number, except when seq == 0 (reset sent answering
++		 * SYN.
 +		 */
 +		seq = end = sender->td_end;
 +		
-+	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu seq=%u ack=%u sack=%u win=%u end=%u trim=%u\n",
-+		NIPQUAD(iph->saddr), ntohs(tcph->source), NIPQUAD(iph->daddr), ntohs(tcph->dest),
-+		seq, ack, sack, win, end, 
-+		after(end, sender->td_maxend) && before(seq, sender->td_maxend) ? sender->td_maxend : end);
-+	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-+		sender->td_end, sender->td_maxend, sender->td_maxwin, sender->td_scale, 
-+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, receiver->td_scale);
++	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
++	       "seq=%u ack=%u sack =%u win=%u end=%u\n",
++		NIPQUAD(iph->saddr), ntohs(tcph->source),
++		NIPQUAD(iph->daddr), ntohs(tcph->dest),
++		seq, ack, sack, win, end);
++	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
++	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
++		sender->td_end, sender->td_maxend, sender->td_maxwin,
++		sender->td_scale, 
++		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
++		receiver->td_scale);
 +	
-+	/* Ignore data over the right edge of the receiver's window. */
-+	if (after(end, sender->td_maxend) &&
-+	    before(seq, sender->td_maxend)) {
-+		end = sender->td_maxend;
-+		if (state->stored_seq == TCP_FIN_SET)
-+			state->stored_seq = TCP_ACK_SET;
-+	}
 +	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
-+		before(end, sender->td_maxend + 1) 
-+			|| before(seq, sender->td_maxend + 1),
-+	    	after(seq, sender->td_end - receiver->td_maxwin - 1) 
-+	    		|| after(end, sender->td_end - receiver->td_maxwin - 1),
++		before(seq, sender->td_maxend + 1),
++	    	after(end, sender->td_end - receiver->td_maxwin - 1),
 +	    	before(sack, receiver->td_end + 1),
 +	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
 +	
 +	if (sender->loose || receiver->loose ||
-+	    (before(end, sender->td_maxend + 1) &&
-+	     after(seq, sender->td_end - receiver->td_maxwin - 1) &&
++	    (before(seq, sender->td_maxend + 1) &&
++	     after(end, sender->td_end - receiver->td_maxwin - 1) &&
 +	     before(sack, receiver->td_end + 1) &&
 +	     after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
 +	    	/*
@@ -842,6 +856,11 @@
 +			sender->td_maxwin = swin;
 +		if (after(end, sender->td_end))
 +			sender->td_end = end;
++		/*
++		 * Update receiver data.
++		 */
++		if (after(end, sender->td_maxend))
++			receiver->td_maxwin += end - sender->td_maxend;
 +		if (after(sack + win, receiver->td_maxend - 1)) {
 +			receiver->td_maxend = sack + win;
 +			if (win == 0)
@@ -851,7 +870,7 @@
 +		/* 
 +		 * Check retransmissions.
 +		 */
-+		if (state->stored_seq == TCP_ACK_SET) {
++		if (index == TCP_ACK_SET) {
 +			if (state->last_dir == dir
 +			    && state->last_seq == seq
 +			    && state->last_end == end)
@@ -872,21 +891,22 @@
 +		res = 1;
 +	} else {
 +		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+			nf_log_ip((char *)iph, len,
-+				"ip_conntrack_tcp: IGNORED: Out of window data; %s\n",
-+				before(end, sender->td_maxend + 1) ?
-+					after(seq, sender->td_end - receiver->td_maxwin - 1) ?
-+						before(ack, receiver->td_end + 1) ?
-+							after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
-+							: "ACK is under the lower bound (possibly overly delayed ACK)"
-+						: "ACK is over the upper bound (ACKed data has never seen yet)"
-+					: "SEQ is under the lower bound (retransmitted already ACKed data)"
-+				: "SEQ is over the upper bound (over the window of the receiver)");
++			nf_log(PF_INET, (char *)iph, len,
++			"ip_ct_tcp: %s ",
++			before(seq, sender->td_maxend + 1) ?
++			after(end, sender->td_end - receiver->td_maxwin - 1) ?
++			before(sack, receiver->td_end + 1) ?
++			after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
++			: "ACK is under the lower bound (possible overly delayed ACK)"
++			: "ACK is over the upper bound (ACKed data not seen yet)"
++			: "SEQ is under the lower bound (already ACKed data retransmitted)"
++			: "SEQ is over the upper bound (over the window of the receiver)");
 +
-+		res = ip_ct_tcp_be_liberal && !tcph->rst;
-+	}
-+
-+	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u receiver end=%u maxend=%u maxwin=%u\n",
++		res = ip_ct_tcp_be_liberal;
++  	}
++  
++	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
++	       "receiver end=%u maxend=%u maxwin=%u\n",
 +		res, sender->td_end, sender->td_maxend, sender->td_maxwin, 
 +		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
 +
@@ -895,9 +915,9 @@
 +
 +#ifdef CONFIG_IP_NF_NAT_NEEDED
 +/* Update sender->td_end after NAT successfully mangled the packet */
-+void ip_conntrack_tcp_update(struct sk_buff *skb,
-+			     struct ip_conntrack *conntrack, 
-+			     int dir)
++int ip_conntrack_tcp_update(struct sk_buff *skb,
++			    struct ip_conntrack *conntrack, 
++			    int dir)
 +{
 +	struct iphdr *iph = skb->nh.iph;
 +	struct tcphdr *tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
@@ -915,12 +935,18 @@
 +	 */
 +	if (after(end, conntrack->proto.tcp.seen[dir].td_end))
 +		conntrack->proto.tcp.seen[dir].td_end = end;
++	conntrack->proto.tcp.last_end = end;
 +	WRITE_UNLOCK(&tcp_lock);
-+	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-+		sender->td_end, sender->td_maxend, sender->td_maxwin, sender->td_scale, 
-+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, receiver->td_scale);
++	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
++	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
++		sender->td_end, sender->td_maxend, sender->td_maxwin,
++		sender->td_scale, 
++		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
++		receiver->td_scale);
++		
++	return 1;
 +}
-+ 
++
 +EXPORT_SYMBOL(ip_conntrack_tcp_update);
 +#endif
 +
@@ -952,44 +978,56 @@
 +};
 +
 +/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
-+static int unclean(struct iphdr *iph, size_t len)
++static int tcp_error(struct iphdr *iph, size_t len)
 +{
 +	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
 +	unsigned int tcplen = len - iph->ihl * 4;
 +	u_int8_t tcpflags;
 +
++	/* Smaller that minimal TCP header? Should be always false. */
++	if (len < iph->ihl * 4 + sizeof(struct tcphdr)) {
++		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
++			nf_log(PF_INET, (char *)iph, len, 
++				"ip_ct_tcp: short packet ");
++		return -NF_ACCEPT;
++  	}
++  
 +	/* Not whole TCP header or malformed packet */
 +	if (tcph->doff*4 < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
 +		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+			nf_log_ip((char *)iph, len, 
-+				  "ip_conntrack_tcp: INVALID: truncated/malformed packet ");
-+		return 1;
++			nf_log(PF_INET, (char *)iph, len, 
++				"ip_ct_tcp: truncated/malformed packet ");
++		return -NF_ACCEPT;
 +	}
++  
++	/* Checksum invalid? Ignore.
++	 * We skip checking packets on the outgoing path
++	 * because the semantic of CHECKSUM_HW is different there 
++	 * and moreover root might send raw packets.
++	 */
++	/* FIXME: Source route IP option packets --RR */
++	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
++			 csum_partial((char *)tcph, tcplen, 0))) {
++		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
++			nf_log(PF_INET, (char *)iph, len, 
++				"ip_ct_tcp: bad TCP checksum ");
++		return -NF_ACCEPT;
++	}
 +
 +	/* Check TCP flags. */
 +	tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
 +	if (!tcp_valid_flags[tcpflags]) {
 +		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+			nf_log_ip((char *)iph, len, 
-+				  "ip_conntrack_tcp: INVALID: invalid TCP flag combination ");
-+		return 1;
++			nf_log(PF_INET, (char *)iph, len, 
++				"ip_ct_tcp: invalid TCP flag combination ");
++		return -NF_ACCEPT;
 +	}
 +
-+	/* Checksum invalid?  Ignore. */
-+	/* FIXME: Source route IP option packets --RR */
-+	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
-+			 csum_partial((char *)tcph, tcplen, 0))) {
-+		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+			nf_log_ip((char *)iph, len, 
-+				  "ip_conntrack_tcp: INVALID: bad TCP checksum ");
-+		return 1;
-+	}
-+
-+	return 0;
++	return NF_ACCEPT;
  }
  
  /* Returns verdict for packet, or -1 for invalid. */
-@@ -159,60 +769,132 @@
+@@ -159,90 +824,248 @@
  		      struct iphdr *iph, size_t len,
  		      enum ip_conntrack_info ctinfo)
  {
@@ -1006,10 +1044,10 @@
 -	}
 -
 +	unsigned long timeout;
-+	unsigned int index, old_index;
++	unsigned int index;
 +	
-+	/* Do not handle unclean packets, which could cause false alarms */
-+	if (unclean(iph, len))
++	/* Do not handle unclean packets, which could cause false alarms. */
++	if (tcp_error(iph, len) != NF_ACCEPT)
 +		return -NF_ACCEPT;
 +	
  	WRITE_LOCK(&tcp_lock);
@@ -1021,6 +1059,9 @@
 -
 -	/* Invalid */
 -	if (newconntrack == TCP_CONNTRACK_MAX) {
+-		DEBUGP("ip_conntrack_tcp: Invalid dir=%i index=%u conntrack=%u\n",
+-		       CTINFO2DIR(ctinfo), get_conntrack_index(tcph),
+-		       conntrack->proto.tcp.state);
 +	old_state = conntrack->proto.tcp.state;
 +	dir = CTINFO2DIR(ctinfo);
 +	index = get_conntrack_index(tcph);
@@ -1028,73 +1069,86 @@
 +
 +	switch (new_state) {
 +	case TCP_CONNTRACK_IGNORE:
-+		/* Either SYN in ORIGINAL, or SYN/ACK in REPLY direction. */
++		/* Either SYN in ORIGINAL
++		 * or SYN/ACK in REPLY. */
 +		if (index == TCP_SYNACK_SET
-+		    && conntrack->proto.tcp.stored_seq == TCP_SYN_SET
++		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
 +		    && conntrack->proto.tcp.last_dir != dir
-+		    && after(ntohl(tcph->ack_seq), conntrack->proto.tcp.last_seq)) {
-+			/* This SYN/ACK acknowledges a SYN that we earlier ignored 
-+			 * as invalid. This means that the client and the server 
-+			 * are both in sync, while the firewall is not. We kill 
-+			 * this session and block the SYN/ACK so that the client 
-+			 * cannot but retransmit its SYN and thus initiate a 
-+			 * clean new session.
++		    && ntohl(tcph->ack_seq) ==
++		    	     conntrack->proto.tcp.last_end) {
++			/* This SYN/ACK acknowledges a SYN that we earlier 
++			 * ignored as invalid. This means that the client and
++			 * the server are both in sync, while the firewall is
++			 * not. We kill this session and block the SYN/ACK so
++			 * that the client cannot but retransmit its SYN and 
++			 * thus initiate a clean new session.
 +			 */
 +		    	WRITE_UNLOCK(&tcp_lock);
 +			if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+				nf_log_ip((char *)iph, len, 
-+					  "ip_conntrack_tcp: INVALID: killing out of sync session ");
++				nf_log(PF_INET, (char *)iph, len, 
++					"ip_ct_tcp: killing out of sync session ");
 +		    	if (del_timer(&conntrack->timeout))
-+		    		conntrack->timeout.function((unsigned long)conntrack);
++		    		conntrack->timeout.function((unsigned long)
++		    					    conntrack);
 +		    	return -NF_DROP;
 +		}
-+		conntrack->proto.tcp.stored_seq = index;
++		conntrack->proto.tcp.last_index = index;
 +		conntrack->proto.tcp.last_dir = dir;
 +		conntrack->proto.tcp.last_seq = ntohl(tcph->seq);
++		conntrack->proto.tcp.last_end = 
++		    segment_seq_plus_len(ntohl(tcph->seq), len, iph, tcph);
 +		
 +		WRITE_UNLOCK(&tcp_lock);
 +		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+			nf_log_ip((char *)iph, len, 
-+				  "ip_conntrack_tcp: INVALID: invalid SYN (ignored) ");
++			nf_log(PF_INET, (char *)iph, len, 
++				"ip_ct_tcp: invalid packet ignored ");
 +		return NF_ACCEPT;
 +	case TCP_CONNTRACK_MAX:
 +		/* Invalid packet */
- 		DEBUGP("ip_conntrack_tcp: Invalid dir=%i index=%u conntrack=%u\n",
--		       CTINFO2DIR(ctinfo), get_conntrack_index(tcph),
--		       conntrack->proto.tcp.state);
++		DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
 +		       dir, get_conntrack_index(tcph),
 +		       old_state);
  		WRITE_UNLOCK(&tcp_lock);
 -		return -1;
 +		if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+			nf_log_ip((char *)iph, len, 
-+				  "ip_conntrack_tcp: INVALID: invalid state ");
++			nf_log(PF_INET, (char *)iph, len, 
++				"ip_ct_tcp: invalid state ");
 +		return -NF_ACCEPT;
 +	case TCP_CONNTRACK_SYN_SENT:
-+		if (old_state >= TCP_CONNTRACK_TIME_WAIT) {	
++		if (old_state < TCP_CONNTRACK_TIME_WAIT)
++			break;
++		if ((conntrack->proto.tcp.seen[dir].flags &
++		         IP_CT_TCP_FLAG_CLOSE_INIT)
++		    || after(ntohl(tcph->seq),
++		    	     conntrack->proto.tcp.seen[dir].td_end)) {	
 +		    	/* Attempt to reopen a closed connection.
 +		    	* Delete this connection and look up again. */
 +		    	WRITE_UNLOCK(&tcp_lock);
 +		    	if (del_timer(&conntrack->timeout))
-+		    		conntrack->timeout.function((unsigned long)conntrack);
++		    		conntrack->timeout.function((unsigned long)
++		    					    conntrack);
 +		    	return -NF_REPEAT;
++		} else {
++			WRITE_UNLOCK(&tcp_lock);
++			if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
++				nf_log(PF_INET, (char *)iph, len, 
++					"ip_ct_tcp: invalid SYN ");
++			return -NF_ACCEPT;
 +		}
-+		break;
 +	case TCP_CONNTRACK_CLOSE:
 +		if (index == TCP_RST_SET
-+		    && conntrack->proto.tcp.stored_seq <= TCP_SYNACK_SET
-+		    && conntrack->proto.tcp.last_dir != dir
-+		    && after(ntohl(tcph->ack_seq), conntrack->proto.tcp.last_seq)) {
-+			/* Ignore RST closing down invalid SYN we had let trough. */ 
-+		    	WRITE_UNLOCK(&tcp_lock);
-+			if (NET_RATELIMIT(ip_ct_tcp_log_invalid))
-+				nf_log_ip((char *)iph, len, 
-+					  "ip_conntrack_tcp: INVALID: invalid RST (ignored) ");
-+			return NF_ACCEPT;
++		    && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
++		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
++		    && ntohl(tcph->ack_seq) == conntrack->proto.tcp.last_end) {
++			/* RST sent to invalid SYN we had let trough 
++			 * SYN was in window then, tear down connection.
++			 * We skip window checking, because packet might ACK
++			 * segments we ignored in the SYN. */
++			goto in_window;
 +		}
 +		/* Just fall trough */
 +	default:
-+		/* Keep compilers happy */
++		/* Keep compilers happy. */
 +		break;
  	}
  
@@ -1112,11 +1166,8 @@
 -	   problem case, so we can delete the conntrack
 -	   immediately.  --RR */
 -	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph->rst) {
-+	old_index =  conntrack->proto.tcp.stored_seq;
-+	conntrack->proto.tcp.stored_seq = index;
-+	if (!tcp_in_window(&conntrack->proto.tcp, dir, iph, len, tcph)) {
-+		/* Invalid packet, restore previous state */
-+		conntrack->proto.tcp.stored_seq = old_index;
++	if (!tcp_in_window(&conntrack->proto.tcp, dir, index, 
++			   iph, len, tcph)) {
  		WRITE_UNLOCK(&tcp_lock);
 -		if (del_timer(&conntrack->timeout))
 -			conntrack->timeout.function((unsigned long)conntrack);
@@ -1126,23 +1177,28 @@
 -		    && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL
 -		    && tcph->ack && !tcph->syn
 -		    && tcph->ack_seq == conntrack->proto.tcp.handshake_ack)
--			set_bit(IPS_ASSURED_BIT, &conntrack->status);
 +		return -NF_ACCEPT;
 +	}
-+	/* If FIN was trimmed off, don't change state. */
-+	new_state = tcp_conntracks[dir][conntrack->proto.tcp.stored_seq][old_state];
- 
--		WRITE_UNLOCK(&tcp_lock);
--		ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
-+	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
-+		NIPQUAD(iph->saddr), ntohs(tcph->source), NIPQUAD(iph->daddr), ntohs(tcph->dest),
-+		(tcph->syn ? 1 : 0), (tcph->ack ? 1 : 0), (tcph->fin ? 1 : 0), (tcph->rst ? 1 : 0),
++    in_window:
++	/* From now on we have got in-window packets */	
++	conntrack->proto.tcp.last_index = index;
++
++	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
++	       "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
++		NIPQUAD(iph->saddr), ntohs(tcph->source),
++		NIPQUAD(iph->daddr), ntohs(tcph->dest),
++		(tcph->syn ? 1 : 0), (tcph->ack ? 1 : 0),
++		(tcph->fin ? 1 : 0), (tcph->rst ? 1 : 0),
 +		old_state, new_state);
 +
 +	conntrack->proto.tcp.state = new_state;
++	if (old_state != new_state 
++	    && (new_state == TCP_CONNTRACK_FIN_WAIT
++	    	|| new_state == TCP_CONNTRACK_CLOSE))
++		conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
 +	timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
-+		  && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans ?
-+		  ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
++		  && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
++		  ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
 +	WRITE_UNLOCK(&tcp_lock);
 +
 +	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
@@ -1152,22 +1208,29 @@
 +		   immediately.  --RR */
 +		if (tcph->rst) {
 +			if (del_timer(&conntrack->timeout))
-+				conntrack->timeout.function((unsigned long)conntrack);
++				conntrack->timeout.function((unsigned long)
++							    conntrack);
 +			return NF_ACCEPT;
 +		}
 +	} else if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
 +		   && (old_state == TCP_CONNTRACK_SYN_RECV
 +		       || old_state == TCP_CONNTRACK_ESTABLISHED)
 +		   && new_state == TCP_CONNTRACK_ESTABLISHED) {
-+		/* Set ASSURED if we see see valid ack in ESTABLISHED after SYN_RECV 
-+		   or a valid answer for a picked up connection. */
-+			set_bit(IPS_ASSURED_BIT, &conntrack->status);
++		/* Set ASSURED if we see see valid ack in ESTABLISHED 
++		   after SYN_RECV or a valid answer for a picked up 
++		   connection. */
+ 			set_bit(IPS_ASSURED_BIT, &conntrack->status);
+-
+-		WRITE_UNLOCK(&tcp_lock);
+-		ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
  	}
 +	ip_ct_refresh(conntrack, timeout);
  
  	return NF_ACCEPT;
  }
-@@ -221,21 +903,80 @@
+-
++ 
+ /* Called when a new connection for this protocol found. */
  static int tcp_new(struct ip_conntrack *conntrack,
  		   struct iphdr *iph, size_t len)
  {
@@ -1178,11 +1241,11 @@
 +	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
 +	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
 +#endif
-+
+ 
 +	/* Skip unclean packets */
-+	if (unclean(iph, len))
++	if (tcp_error(iph, len) != NF_ACCEPT)
 +		return 0;
- 
++	
  	/* Don't need lock here: this conntrack not in circulation yet */
 -	newconntrack
 +	new_state
@@ -1191,8 +1254,9 @@
  
  	/* Invalid: delete conntrack */
 -	if (newconntrack == TCP_CONNTRACK_MAX) {
+-		DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
 +	if (new_state >= TCP_CONNTRACK_MAX) {
- 		DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
++		DEBUGP("ip_ct_tcp: invalid new deleting.\n");
  		return 0;
  	}
  
@@ -1200,14 +1264,15 @@
 +	if (new_state == TCP_CONNTRACK_SYN_SENT) {
 +		/* SYN packet */
 +		conntrack->proto.tcp.seen[0].td_end =
-+			segment_seq_plus_len(ntohl(tcph->seq), len, iph, tcph);
++			segment_seq_plus_len(ntohl(tcph->seq), len,
++					     iph, tcph);
 +		conntrack->proto.tcp.seen[0].td_maxwin = ntohs(tcph->window);
 +		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
 +			conntrack->proto.tcp.seen[0].td_maxwin = 1;
 +		conntrack->proto.tcp.seen[0].td_maxend =
 +			conntrack->proto.tcp.seen[0].td_end;
 +
-+		tcp_options(iph, len, tcph, &conntrack->proto.tcp.seen[0]);
++		tcp_options(tcph, &conntrack->proto.tcp.seen[0]);
 +		conntrack->proto.tcp.seen[1].flags = 0;
 +		conntrack->proto.tcp.seen[0].loose = 
 +		conntrack->proto.tcp.seen[1].loose = 0;
@@ -1221,7 +1286,8 @@
 +		 * Let's try to use the data from the packet.
 +		 */
 +		conntrack->proto.tcp.seen[0].td_end =
-+			segment_seq_plus_len(ntohl(tcph->seq), len, iph, tcph);
++			segment_seq_plus_len(ntohl(tcph->seq), len,
++					     iph, tcph);
 +		conntrack->proto.tcp.seen[0].td_maxwin = ntohs(tcph->window);
 +		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
 +			conntrack->proto.tcp.seen[0].td_maxwin = 1;
@@ -1230,7 +1296,7 @@
 +			conntrack->proto.tcp.seen[0].td_maxwin;
 +		conntrack->proto.tcp.seen[0].td_scale = 0;
 +
-+		/* We assume SACK. Should we assume window scaling? */
++		/* We assume SACK. Should we assume window scaling too? */
 +		conntrack->proto.tcp.seen[0].flags =
 +		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
 +		conntrack->proto.tcp.seen[0].loose = 
@@ -1244,18 +1310,50 @@
 +
 +	/* tcp_packet will set them */
 +	conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
-+	conntrack->proto.tcp.stored_seq = TCP_NONE_SET;
-+ 
-+	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-+		sender->td_end, sender->td_maxend, sender->td_maxwin, sender->td_scale, 
-+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, receiver->td_scale);
++	conntrack->proto.tcp.last_index = TCP_NONE_SET;
++	 
++	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
++	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
++		sender->td_end, sender->td_maxend, sender->td_maxwin,
++		sender->td_scale, 
++		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
++		receiver->td_scale);
  	return 1;
  }
+-
++  
+ static int tcp_exp_matches_pkt(struct ip_conntrack_expect *exp,
+ 			       struct sk_buff **pskb)
+ {
+-	struct iphdr *iph = (*pskb)->nh.iph;
++	const struct iphdr *iph = (*pskb)->nh.iph;
+ 	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
+ 	unsigned int datalen;
  
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_standalone.c
---- linux-2.4.23-pending/net/ipv4/netfilter/ip_conntrack_standalone.c	2003-12-04 16:56:14.000000000 +0100
-+++ linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_conntrack_standalone.c	2003-12-09 09:30:21.000000000 +0100
-@@ -289,6 +289,11 @@
+@@ -251,7 +1074,15 @@
+ 	return between(exp->seq, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
+ }
+ 
+-struct ip_conntrack_protocol ip_conntrack_protocol_tcp
+-= { { NULL, NULL }, IPPROTO_TCP, "tcp",
+-    tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
+-    tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
++struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
++{
++	.proto 			= IPPROTO_TCP,
++	.name 			= "tcp",
++	.pkt_to_tuple 		= tcp_pkt_to_tuple,
++	.invert_tuple 		= tcp_invert_tuple,
++	.print_tuple 		= tcp_print_tuple,
++	.print_conntrack 	= tcp_print_conntrack,
++	.packet 		= tcp_packet,
++	.new 			= tcp_new,
++	.exp_matches_pkt	= tcp_exp_matches_pkt,
++};
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- linux-2.4.31-nf-log/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-06-27 17:34:52.000000000 +0200
+@@ -259,6 +259,11 @@
  extern unsigned long ip_ct_tcp_timeout_last_ack;
  extern unsigned long ip_ct_tcp_timeout_time_wait;
  extern unsigned long ip_ct_tcp_timeout_close;
@@ -1267,7 +1365,7 @@
  
  /* From ip_conntrack_proto_udp.c */
  extern unsigned long ip_ct_udp_timeout;
-@@ -345,6 +350,21 @@
+@@ -315,6 +320,21 @@
  	{NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
  	 &ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
  	 &proc_dointvec_jiffies},
@@ -1289,15 +1387,15 @@
  	{0}
  };
  
-diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.23-pending/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_nat_helper.c
---- linux-2.4.23-pending/net/ipv4/netfilter/ip_nat_helper.c	2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.23-tcp-win/net/ipv4/netfilter/ip_nat_helper.c	2003-12-09 09:30:21.000000000 +0100
-@@ -452,6 +452,8 @@
+diff -urN --exclude-from=/usr/src/diff.exclude linux-2.4.31-nf-log/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_nat_helper.c
+--- linux-2.4.31-nf-log/net/ipv4/netfilter/ip_nat_helper.c	2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.31-tcp-win/net/ipv4/netfilter/ip_nat_helper.c	2005-06-27 17:35:40.000000000 +0200
+@@ -451,6 +451,8 @@
+ 	tcph->ack_seq = newack;
  
  	ip_nat_sack_adjust(skb, ct, ctinfo);
++	
++	ip_conntrack_tcp_update(skb, ct, dir);
  
-+	ip_conntrack_tcp_update(skb, ct, dir);
-+
  	return 0;
  }
- 




More information about the netfilter-cvslog mailing list