[netfilter-cvslog] r3707 - in trunk/patch-o-matic-ng/nf_conntrack/linux-2.6: include/linux/netfilter net/ipv4/netfilter net/ipv6/netfilter net/netfilter

laforge at netfilter.org laforge at netfilter.org
Tue Feb 15 03:38:49 CET 2005


Author: laforge at netfilter.org
Date: 2005-02-15 03:38:48 +0100 (Tue, 15 Feb 2005)
New Revision: 3707

Modified:
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack.h
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_core.h
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_ftp.h
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_helper.h
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_protocol.h
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_core.c
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_ftp.c
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_sctp.c
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_tcp.c
   trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_standalone.c
Log:
[NETFILTER]: Call NAT helper modules directly from conntrack modules, fixup FTP

Currently connection tracking and NAT helper modules for a protocol
interact only indirectly (the conntrack module places information in
the conntrack structure, which the NAT module pulls out).

This leads to several issues:
1) Both modules must know what port to watch, and must match.
2) Identifying the particular packet which created the connection
   is cumbersome (TCP) or impossible (UDP).
3) The connection tracking code sets up an expectation which the
   NAT code then has to change.
4) The lack of direct symbol dependencies means we have to contrive
   one, since they are functionally dependent.

Here is the current code flow:
FTP CONTROL PACKET:
NF_IP_PRE_ROUTING:
   ip_conntrack_in
      resolve_normal_ct
         init_conntrack: sets ct->helper to ip_conntrack_ftp.c:help()
   ct->help(): if PORT/PASV command:
      Sets exp->help.exp_ftp_info to tcp seq number of data.
      ip_conntrack_expect(): expects the connection

   ip_nat_setup_info: sets ct->nat.info->helper to ip_nat_ftp.c:help()
   ip_nat_fn:
      proto->exp_matches_pkt: if packet matches expectation
      ct->nat.info->helper(): If packet going client->server,
            and packet data is one in ct_ftp_info:
         ftp_data_fixup():
            ip_conntrack_change_expect(): change the expectation
            Modify packet contents with new address.

NF_IP_POST_ROUTING:
   ip_nat_fn
      ct->nat.info->helper(): If packet going server->client,
            and packet data is one in ct_ftp_info:
         ftp_data_fixup():
            ip_conntrack_change_expect(): change the expectation
            Modify packet contents with new address.

FTP DATA (EXPECTED) CONNECTION FIRST PACKET:
NF_IP_PRE_ROUTING:
   ip_conntrack_in
      resolve_normal_ct
         init_conntrack: set ct->master.
   ip_nat_fn:
      master->nat.info.helper->expect()
         Set up source NAT mapping to match FTP control connection.

NF_IP_PRE_ROUTING:
   ip_nat_fn:
      master->nat.info.helper->expect()
         Set up dest NAT mapping to match FTP control connection.


The new flow looks like this:
FTP CONTROL PACKET:
NF_IP_PRE_ROUTING:
   ip_conntrack_in
      resolve_normal_ct
         init_conntrack: sets ct->helper to ip_conntrack_ftp.c:help()

NF_IP_POST_ROUTING:
   ip_confirm:
      ct->helper->help:
         If !ip_nat_ftp_hook: ip_conntrack_expect().
         ip_nat_ftp: 
            set exp->oldproto to old port.
            ip_conntrack_change_expect(): change the expectation
            set exp->expectfn to ftp_nat_expected.
            Modify packet contents with new address.

FTP DATA (EXPECTED) CONNECTION FIRST PACKET:
NF_IP_PRE_ROUTING:
   ip_conntrack_in
      resolve_normal_ct
         init_conntrack: set ct->master.
         call exp->expectfn (ftp_nat_expected):
             call ip_nat_follow_master().

The big changes are that the ip_nat_ftp module sets ip_conntrack_ftp's
ip_nat_ftp_hook when it initializes, so it calls the NAT code directly
when a packet containing the expect information is found by the
conntrack helper: and this interface can carry all the information
these two want to share.  Also, that conntrack helper is called as the
packet leaves the box, so there are no issues with expectations being
set up before the packet has been filtered.  The NAT helper doesn't
need to register and duplicate the conntrack ports.

The other trick is ip_nat_follow_master(), which does the NAT setup
all at once (source and destination NAT as required) such that the
expected connection is NATed the same way the master connection
was.

We also call ip_conntrack_tcp_update() (which I incidentally neatened)
after mangling a TCP packet; ip_nat_seq_adjust() does this, but now
mangling is done at the last possible moment, after
ip_nat_seq_adjust() was already called.

Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
Signed-off-by: David S. Miller <davem at davemloft.net>


Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack.h
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack.h	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack.h	2005-02-15 02:38:48 UTC (rev 3707)
@@ -11,11 +11,6 @@
 
 #ifndef _NF_CONNTRACK_H
 #define _NF_CONNTRACK_H
-#include <linux/config.h>
-#include <linux/netfilter/nf_conntrack_tuple.h>
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <asm/atomic.h>
 
 enum nf_conntrack_info
 {
@@ -56,6 +51,13 @@
 	NF_S_CONFIRMED = (1 << NF_S_CONFIRMED_BIT),
 };
 
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/netfilter/nf_conntrack_tuple.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <asm/atomic.h>
+
 #include <linux/netfilter/nf_conntrack_tcp.h>
 #include <linux/netfilter/ipv4/nf_conntrack_icmp.h>
 #include <linux/netfilter/ipv6/nf_conntrack_icmpv6.h>
@@ -77,26 +79,12 @@
 /* Add protocol helper include file here */
 #include <linux/netfilter/nf_conntrack_ftp.h>
 
-/* per expectation: application helper private data */
-union nf_conntrack_expect_help {
-	/* insert conntrack helper private data (expect) here */
-	struct nf_ct_ftp_expect exp_ftp_info;
-
-#ifdef CONFIG_IP_NF_NAT_NEEDED
-	union {
-		/* insert nat helper private data (expect) here */
-	} nat;
-#endif
-};
-
 /* per conntrack: application helper private data */
 union nf_conntrack_help {
 	/* insert conntrack helper private data (master) here */
 	struct nf_ct_ftp_master ct_ftp_info;
 };
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <linux/skbuff.h>
 
@@ -143,14 +131,17 @@
 	struct nf_conntrack_tuple tuple, mask;
 
 	/* Function to call after setup and insertion */
-	int (*expectfn)(struct nf_conn *new);
+	void (*expectfn)(struct nf_conn *new);
 
-	/* At which sequence number did this expectation occur */
-	u_int32_t seq;
+#ifdef CONFIG_NF_NAT_NEEDED
+	/* This is the original per-proto part, used to map the
+	 * expected connection the way the recipient expects. */
+	union nf_conntrack_manip_proto saved_proto;
+	/* Direction relative to the master connection. */
+	enum nf_conntrack_dir dir;
+#endif
   
 	union nf_conntrack_expect_proto proto;
-
-	union nf_conntrack_expect_help help;
 };
 
 struct nf_conntrack_counter

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_core.h
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_core.h	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_core.h	2005-02-15 02:38:48 UTC (rev 3707)
@@ -50,14 +50,14 @@
 nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
 		      const struct nf_conn *ignored_conntrack);
 
-extern int __nf_conntrack_confirm(struct sk_buff *skb);
+extern int __nf_conntrack_confirm(struct sk_buff **pskb);
 
 /* Confirm a connection: returns NF_DROP if packet must be dropped. */
-static inline int nf_conntrack_confirm(struct sk_buff *skb)
+static inline int nf_conntrack_confirm(struct sk_buff **pskb)
 {
-	if (skb->nfct
-	    && !is_confirmed((struct nf_conn *)skb->nfct))
-		return __nf_conntrack_confirm(skb);
+	if ((*pskb)->nfct
+	    && !is_confirmed((struct nf_conn *)(*pskb)->nfct))
+		return __nf_conntrack_confirm(pskb);
 
 	return NF_ACCEPT;
 }

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_ftp.h
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_ftp.h	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_ftp.h	2005-02-15 02:38:48 UTC (rev 3707)
@@ -36,24 +36,25 @@
 	NF_CT_FTP_EPSV,
 };
 
-/* This structure is per expected connection */
-struct nf_ct_ftp_expect
-{
-	/* We record seq number and length of ftp ip/port text here: all in
-	 * host order. */
-
- 	/* sequence number of IP address in packet is in ip_conntrack_expect */
-	u_int32_t len;			/* length of IP address */
-	enum nf_ct_ftp_type ftptype;	/* PORT or PASV ? */
-	u_int16_t port; 		/* TCP port that was to be used */
-};
-
+#define NUM_SEQ_TO_REMEMBER	2
 /* This structure exists only once per master */
 struct nf_ct_ftp_master {
-	/* Next valid seq position for cmd matching after newline */
-	u_int32_t seq_aft_nl[NF_CT_DIR_MAX];
+	/* Valid seq positions for cmd matching after newline */
+	u_int32_t seq_aft_nl[NF_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
 	/* 0 means seq_match_aft_nl not set */
-	int seq_aft_nl_set[NF_CT_DIR_MAX];
+	int seq_aft_nl_num[NF_CT_DIR_MAX];
 };
 
+struct ip_conntrack_expect;
+
+/* For NAT to hook in when we find a packet which describes what other
+ * connection we should expect. */
+extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
+				       struct ip_conntrack *ct,
+				       enum ip_conntrack_info ctinfo,
+				       enum ip_ct_ftp_type type,
+				       unsigned int matchoff,
+				       unsigned int matchlen,
+				       struct ip_conntrack_expect *exp,
+				       u32 *seq);
 #endif /* _NF_CONNTRACK_FTP_H */

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_helper.h
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_helper.h	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_helper.h	2005-02-15 02:38:48 UTC (rev 3707)
@@ -33,7 +33,7 @@
 	
 	/* Function to call when data passes; return verdict, or -1 to
            invalidate. */
-	int (*help)(const struct sk_buff *skb,
+	int (*help)(struct sk_buff **pskb,
 		    unsigned int dataoff,
 		    struct nf_conn *ct,
 		    enum nf_conntrack_info conntrackinfo);
@@ -50,8 +50,6 @@
 /* Add an expected connection: can have more than one per connection */
 extern int nf_conntrack_expect_related(struct nf_conntrack_expect *exp,
 				       struct nf_conn *related_to);
-extern int nf_conntrack_change_expect(struct nf_conntrack_expect *expect,
-				      struct nf_conntrack_tuple *newtuple);
 extern void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
 
 #endif /*_NF_CONNTRACK_HELPER_H*/

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_protocol.h
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_protocol.h	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/include/linux/netfilter/nf_conntrack_protocol.h	2005-02-15 02:38:48 UTC (rev 3707)
@@ -62,11 +62,6 @@
 	/* Called when a conntrack entry is destroyed */
 	void (*destroy)(struct nf_conn *conntrack);
 
-	/* Has to decide if a expectation matches one packet or not */
-	int (*exp_matches_pkt)(struct nf_conntrack_expect *exp,
-			       const struct sk_buff *skb,
-			       unsigned int dataoff);
-
 	int (*error)(struct sk_buff *skb, unsigned int dataoff,
 		     enum nf_conntrack_info *ctinfo,
 		     int pf, unsigned int hooknum);

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c	2005-02-15 02:38:48 UTC (rev 3707)
@@ -160,9 +160,23 @@
 				 const struct net_device *out,
 				 int (*okfn)(struct sk_buff *))
 {
+	struct nf_conn *ct;
+	enum nf_conntrack_info ctinfo;
+
+	DEBUGP("ipv4_confirm\n");
+
+	/* This is where we call the helper: as the packet goes out. */
+	ct = nf_conntrack_get(*pskb, &ctinfo);
+	if (ct && ct->helper) {
+		unsigned int ret;
+		ret = ct->helper->help(pskb, ct, ctinfo);
+		if (ret != NF_ACCEPT)
+			return ret;
+	}
+
 	/* We've seen it coming out the other side: confirm it */
-	DEBUGP("ipv4_confirm\n");
-	return nf_conntrack_confirm(*pskb);
+
+	return nf_conntrack_confirm(pskb);
 }
 
 static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c	2005-02-15 02:38:48 UTC (rev 3707)
@@ -181,7 +181,20 @@
 				 const struct net_device *out,
 				 int (*okfn)(struct sk_buff *))
 {
+	struct nf_conn *ct;
+	enum nf_conntrack_info ctinfo;
+
+	/* This is where we call the helper: as the packet goes out. */
+	ct = nf_conntrack_get(*pskb, &ctinfo);
+	if (ct && ct->helper) {
+		unsigned int ret;
+		ret = ct->helper->help(pskb, ct, ctinfo);
+		if (ret != NF_ACCEPT)
+			return ret;
+	}
+
 	/* We've seen it coming out the other side: confirm it */
+
 	return nf_conntrack_confirm(*pskb);
 }
 

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_core.c
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_core.c	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_core.c	2005-02-15 02:38:48 UTC (rev 3707)
@@ -621,13 +621,13 @@
 
 /* Confirm a connection given skb; places it in hash table */
 int
-__nf_conntrack_confirm(struct sk_buff *skb)
+__nf_conntrack_confirm(struct sk_buff **pskb)
 {
 	unsigned int hash, repl_hash;
 	struct nf_conn *ct;
 	enum nf_conntrack_info ctinfo;
 
-	ct = nf_ct_get(skb, &ctinfo);
+	ct = nf_ct_get(*pskb, &ctinfo);
 
 	/* ipt_REJECT uses nf_conntrack_attach to attach related
 	   ICMP/TCP RST packets in other direction.  Actual packet
@@ -1026,16 +1026,6 @@
 		return -ret;
 	}
 
-	if (ret != NF_DROP && ct->helper) {
-		ret = ct->helper->help(*pskb, dataoff, ct, ctinfo);
-		if (ret == -1) {
-			/* Invalid */
-			NF_CT_STAT_INC(invalid);
-			nf_conntrack_put((*pskb)->nfct);
-			(*pskb)->nfct = NULL;
-			return NF_ACCEPT;
-		}
-	}
 	if (set_reply)
 		set_bit(NF_S_SEEN_REPLY_BIT, &ct->status);
 
@@ -1254,47 +1244,6 @@
 	return ret;
 }
 
-/* Change tuple in an existing expectation */
-int nf_conntrack_change_expect(struct nf_conntrack_expect *expect,
-			       struct nf_conntrack_tuple *newtuple)
-{
-	int ret;
-
-	MUST_BE_READ_LOCKED(&nf_conntrack_lock);
-	WRITE_LOCK(&nf_conntrack_expect_tuple_lock);
-
-	DEBUGP("change_expect:\n");
-	DEBUGP("exp tuple: "); NF_CT_DUMP_TUPLE(&expect->tuple);
-	DEBUGP("exp mask:  "); NF_CT_DUMP_TUPLE(&expect->mask);
-	DEBUGP("newtuple:  "); NF_CT_DUMP_TUPLE(newtuple);
-	if (expect->ct_tuple.dst.protonum == 0) {
-		/* Never seen before */
-		DEBUGP("change expect: never seen before\n");
-		if (!nf_ct_tuple_equal(&expect->tuple, newtuple) 
-		    && LIST_FIND(&nf_conntrack_expect_list, expect_clash,
-				 struct nf_conntrack_expect *, newtuple, &expect->mask)) {
-			/* Force NAT to find an unused tuple */
-			ret = -1;
-		} else {
-			memcpy(&expect->ct_tuple, &expect->tuple, sizeof(expect->tuple));
-			memcpy(&expect->tuple, newtuple, sizeof(expect->tuple));
-			ret = 0;
-		}
-	} else {
-		/* Resent packet */
-		DEBUGP("change expect: resent packet\n");
-		if (nf_ct_tuple_equal(&expect->tuple, newtuple)) {
-			ret = 0;
-		} else {
-			/* Force NAT to choose again the same port */
-			ret = -1;
-		}
-	}
-	WRITE_UNLOCK(&nf_conntrack_expect_tuple_lock);
-	
-	return ret;
-}
-
 /* Alter reply tuple (maybe alter helper).  This is for NAT, and is
    implicitly racy: see __nf_conntrack_confirm */
 void nf_conntrack_alter_reply(struct nf_conn *conntrack,

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_ftp.c
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_ftp.c	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_ftp.c	2005-02-15 02:38:48 UTC (rev 3707)
@@ -48,6 +48,16 @@
 static int loose;
 module_param(loose, int, 0600);
 
+unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
+				struct ip_conntrack *ct,
+				enum ip_conntrack_info ctinfo,
+				enum ip_ct_ftp_type type,
+				unsigned int matchoff,
+				unsigned int matchlen,
+				struct ip_conntrack_expect *exp,
+				u32 *seq);
+EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
+
 #if 0
 #define DEBUGP printk
 #else
@@ -385,7 +395,39 @@
 	return 1;
 }
 
-static int help(const struct sk_buff *skb,
+/* Look up to see if we're just after a \n. */
+static int find_nl_seq(u16 seq, const struct ip_ct_ftp_master *info, int dir)
+{
+	unsigned int i;
+
+	for (i = 0; i < info->seq_aft_nl_num[dir]; i++)
+		if (info->seq_aft_nl[dir][i] == seq)
+			return 1;
+	return 0;
+}
+
+/* We don't update if it's older than what we have. */
+static void update_nl_seq(u16 nl_seq, struct ip_ct_ftp_master *info, int dir)
+{
+	unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
+
+	/* Look for oldest: if we find exact match, we're done. */
+	for (i = 0; i < info->seq_aft_nl_num[dir]; i++) {
+		if (info->seq_aft_nl[dir][i] == nl_seq)
+			return;
+
+		if (oldest == info->seq_aft_nl_num[dir]
+		    || before(info->seq_aft_nl[dir][i], oldest))
+			oldest = i;
+	}
+
+	if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER)
+		info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
+	else if (oldest != NUM_SEQ_TO_REMEMBER)
+		info->seq_aft_nl[dir][oldest] = nl_seq;
+}
+
+static int help(struct sk_buff **pskb,
 		unsigned int protoff,
 		struct nf_conn *ct,
 		enum nf_conntrack_info ctinfo)
@@ -393,17 +435,16 @@
 	unsigned int dataoff, datalen;
 	struct tcphdr _tcph, *th;
 	char *fb_ptr;
-	u_int32_t old_seq_aft_nl;
-	int old_seq_aft_nl_set, ret;
+	int ret;
+	u32 seq, array[6] = { 0 };
 	int dir = NFCTINFO2DIR(ctinfo);
 	unsigned int matchlen, matchoff;
 	struct nf_ct_ftp_master *ct_ftp_info = &ct->help->ct_ftp_info;
 	struct nf_conntrack_expect *exp;
 	struct nf_conntrack_man cmd = {};
-	struct nf_ct_ftp_expect *exp_ftp_info;
 
 	unsigned int i;
-	int found = 0;
+	int found = 0, ends_in_nl;
 
 	/* Until there's been traffic both ways, don't look in packets. */
 	if (ctinfo != NF_CT_ESTABLISHED
@@ -412,44 +453,34 @@
 		return NF_ACCEPT;
 	}
 
-	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+	th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
 	if (th == NULL)
 		return NF_ACCEPT;
 
 	dataoff = protoff + th->doff * 4;
 	/* No data? */
-	if (dataoff >= skb->len) {
-		DEBUGP("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, skb->len);
+	if (dataoff >= (*pskb)->len) {
+		DEBUGP("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
+			(*pskb)->len);
 		return NF_ACCEPT;
 	}
-	datalen = skb->len - dataoff;
+	datalen = (*pskb)->len - dataoff;
 
 	LOCK_BH(&nf_ftp_lock);
-	fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer);
+	fb_ptr = skb_header_pointer(*pskb, dataoff, datalen, ftp_buffer);
 	BUG_ON(fb_ptr == NULL);
 
-	old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir];
-	old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir];
+	ends_in_nl = (fb_ptr[datalen - 1] == '\n');
+	seq = ntohl(th->seq) + datalen;
 
-	DEBUGP("conntrack_ftp: datalen %u\n", datalen);
-	if (fb_ptr[datalen - 1] == '\n') {
-		DEBUGP("conntrack_ftp: datalen %u ends in \\n\n", datalen);
-		if (!old_seq_aft_nl_set
-		    || after(ntohl(th->seq) + datalen, old_seq_aft_nl)) {
-			DEBUGP("conntrack_ftp: updating nl to %u\n",
-			       ntohl(th->seq) + datalen);
-			ct_ftp_info->seq_aft_nl[dir] = 
-						ntohl(th->seq) + datalen;
-			ct_ftp_info->seq_aft_nl_set[dir] = 1;
-		}
-	}
-
-	if(!old_seq_aft_nl_set ||
-			(ntohl(th->seq) != old_seq_aft_nl)) {
-		DEBUGP("nf_conntrack_ftp_help: wrong seq pos %s(%u)\n",
+	/* Look up to see if we're just after a \n. */
+	if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
+		/* Now if this ends in \n, update ftp info. */
+		DEBUGP("ip_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n",
+		       ct_ftp_info->seq_aft_nl[0][dir] 
 		       old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl);
 		ret = NF_ACCEPT;
-		goto out;
+		goto out_update_nl;
 	}
 
         /* Initialize IP/IPv6 addr to expected address (it's not mentioned
@@ -484,7 +515,7 @@
 		goto out;
 	} else if (found == 0) { /* No match */
 		ret = NF_ACCEPT;
-		goto out;
+		goto out_update_nl;
 	}
 
 	DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
@@ -493,21 +524,19 @@
 
 	exp = nf_conntrack_expect_alloc();
 	if (exp == NULL) {
-		ret = NF_ACCEPT;
+		ret = NF_DROP;
 		goto out;
 	}
 
-	exp_ftp_info = &exp->help.exp_ftp_info;
+	/* We refer to the reverse direction ("!dir") tuples here,
+	 * because we're expecting something in the other direction.
+	 * Doesn't matter unless NAT is happening.  */
+	exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
 
 	/* Update the ftp info */
 	if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) &&
-	    (!memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
-		     sizeof(cmd.u3.all)))) {
-		exp->seq = ntohl(th->seq) + matchoff;
-		exp_ftp_info->len = matchlen;
-		exp_ftp_info->ftptype = search[i].ftptype;
-		exp_ftp_info->port = ntohs(cmd.u.tcp.port);
-	} else {
+	    memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
+		     sizeof(cmd.u3.all))) {
 		/* Enrico Scholz's passive FTP to partially RNAT'd ftp
                    server: it really wants us to connect to a
                    different IP address.  Simply don't record it for
@@ -529,7 +558,8 @@
 		   networks, or the packet filter itself). */
 		if (!loose) {
 			ret = NF_ACCEPT;
-			goto out;
+			nf_conntrack_expect_put(exp);
+			goto out_update_nl;
 		}
 	}
 
@@ -561,9 +591,24 @@
 
 	exp->expectfn = NULL;
 
-	/* Ignore failure; should only happen with NAT */
-	nf_conntrack_expect_related(exp, ct);
-	ret = NF_ACCEPT;
+	/* Now, NAT might want to mangle the packet, and register the
+	 * (possibly changed) expectation itself. */
+	if (nf_nat_ftp_hook)
+		ret = nf_nat_ftp_hook(pskb, ct, ctinfo, search[i].ftptype,
+				      matchoff, matchlen, exp, &seq);
+	else {
+		/* Can't expect this?  Best to drop packet now. */
+		if (ip_conntrack_expect_related(exp, ct) != 0)
+			ret = NF_DROP;
+		else
+			ret = NF_ACCEPT;
+	}
+
+out_update_nl:
+	/* Now if this ends in \n, update ftp info.  Seq may have been
+	 * adjusted by NAT code. */
+	if (ends_in_nl)
+		update_nl_seq(seq, ct_ftp_info,dir);
  out:
 	UNLOCK_BH(&nf_ftp_lock);
 	return ret;
@@ -641,7 +686,5 @@
 	return ret;
 }
 
-PROVIDES_CONNTRACK(ftp);
-
 module_init(init);
 module_exit(fini);

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_sctp.c
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_sctp.c	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_sctp.c	2005-02-15 02:38:48 UTC (rev 3707)
@@ -501,14 +501,6 @@
 	return 1;
 }
 
-static int sctp_exp_matches_pkt(struct nf_conntrack_expect *exp,
-				const struct sk_buff *skb,
-				unsigned int dataoff)
-{
-	/* To be implemented */
-	return 0;
-}
-
 struct nf_conntrack_protocol nf_conntrack_protocol_sctp4 = { 
 	.l3proto	 = PF_INET,
 	.proto 		 = IPPROTO_SCTP, 
@@ -520,7 +512,6 @@
 	.packet 	 = sctp_packet, 
 	.new 		 = sctp_new, 
 	.destroy 	 = NULL, 
-	.exp_matches_pkt = sctp_exp_matches_pkt, 
 	.me 		 = THIS_MODULE 
 };
 
@@ -535,7 +526,6 @@
 	.packet 	 = sctp_packet, 
 	.new 		 = sctp_new, 
 	.destroy 	 = NULL, 
-	.exp_matches_pkt = sctp_exp_matches_pkt, 
 	.me 		 = THIS_MODULE 
 };
 

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_tcp.c
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_tcp.c	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_proto_tcp.c	2005-02-15 02:38:48 UTC (rev 3707)
@@ -720,10 +720,10 @@
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 /* Update sender->td_end after NAT successfully mangled the packet */
 /* Caller must linearize skb at tcp header. */
-int nf_conntrack_tcp_update(struct sk_buff *skb,
-			    unsigned int dataoff,
-			    struct nf_conn *conntrack, 
-			    int dir)
+void nf_conntrack_tcp_update(struct sk_buff *skb,
+			     unsigned int dataoff,
+			     struct nf_conn *conntrack, 
+			     int dir)
 {
 	struct tcphdr *tcph = (void *)skb->data + dataoff;
 	__u32 end;
@@ -748,8 +748,6 @@
 		sender->td_scale, 
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
-
-	return 1;
 }
  
 #endif
@@ -1106,21 +1104,6 @@
 	return 1;
 }
   
-static int tcp_exp_matches_pkt(struct nf_conntrack_expect *exp,
-			       const struct sk_buff *skb,
-			       unsigned dataoff)
-{
-	struct tcphdr *th, _tcph;
-	unsigned int datalen;
-
-	th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
-	if (th == NULL)
-		return 0;
-	datalen = skb->len - dataoff - th->doff*4;
-
-	return between(exp->seq, ntohl(th->seq), ntohl(th->seq) + datalen);
-}
-
 struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
 {
 	.l3proto		= PF_INET,
@@ -1132,7 +1115,6 @@
 	.print_conntrack 	= tcp_print_conntrack,
 	.packet 		= tcp_packet,
 	.new 			= tcp_new,
-	.exp_matches_pkt	= tcp_exp_matches_pkt,
 	.error			= tcp_error4,
 };
 
@@ -1147,7 +1129,6 @@
 	.print_conntrack 	= tcp_print_conntrack,
 	.packet 		= tcp_packet,
 	.new 			= tcp_new,
-	.exp_matches_pkt	= tcp_exp_matches_pkt,
 	.error			= tcp_error6,
 };
 

Modified: trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_standalone.c
===================================================================
--- trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_standalone.c	2005-02-15 02:06:33 UTC (rev 3706)
+++ trunk/patch-o-matic-ng/nf_conntrack/linux-2.6/net/netfilter/nf_conntrack_standalone.c	2005-02-15 02:38:48 UTC (rev 3707)
@@ -805,7 +805,6 @@
 EXPORT_SYMBOL(nf_ct_find_helper);
 EXPORT_SYMBOL(nf_conntrack_expect_alloc);
 EXPORT_SYMBOL(nf_conntrack_expect_related);
-EXPORT_SYMBOL(nf_conntrack_change_expect);
 EXPORT_SYMBOL(nf_conntrack_unexpect_related);
 EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);
 EXPORT_SYMBOL_GPL(nf_conntrack_expect_put);




More information about the netfilter-cvslog mailing list