[PATCH 3/8] Netfilter: Use ct_extend for conntrack protocol helpers

Rusty Russell rusty at rustcorp.com.au
Wed Jan 12 21:58:31 CET 2005


Name: Use ct_extend for conntrack protocol helpers
Status: Tested under nfsim
Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>

Instead of a "union ip_conntrack_help" inside the conntrack structure,
we can use the ext field for the helpers.  In fact, only
ip_conntrack_ftp.c uses it inside the current tree.

Index: linux-2.6.10-bk14-Netfilter/net/ipv4/netfilter/ip_conntrack_ftp.c
===================================================================
--- linux-2.6.10-bk14-Netfilter.orig/net/ipv4/netfilter/ip_conntrack_ftp.c	2005-01-12 23:35:56.113259320 +1100
+++ linux-2.6.10-bk14-Netfilter/net/ipv4/netfilter/ip_conntrack_ftp.c	2005-01-12 23:40:34.633917744 +1100
@@ -19,6 +19,7 @@
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+#include <linux/netfilter_ipv4/ct_extend.h>
 #include <linux/moduleparam.h>
 
 MODULE_LICENSE("GPL");
@@ -28,8 +29,6 @@
 /* This is slow, but it's simple. --RR */
 static char ftp_buffer[65536];
 
-static DECLARE_LOCK(ip_ftp_lock);
-
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_c;
@@ -294,7 +293,7 @@
 	u32 seq, array[6] = { 0 };
 	int dir = CTINFO2DIR(ctinfo);
 	unsigned int matchlen, matchoff;
-	struct ip_ct_ftp_master *ct_ftp_info = &ct->help.ct_ftp_info;
+	struct ip_ct_ftp_master *ct_ftp_info;
 	struct ip_conntrack_expect *exp;
 	unsigned int i;
 	int found = 0, ends_in_nl;
@@ -319,7 +318,17 @@
 	}
 	datalen = (*pskb)->len - dataoff;
 
-	LOCK_BH(&ip_ftp_lock);
+	WRITE_LOCK(&ip_conntrack_lock);
+	ct_ftp_info = ct_extend_find(ct->ext, CTE_FTP_CONN);
+	if (!ct_ftp_info) {
+		ct_ftp_info = ct_extend_add(&ct->ext, CTE_FTP_CONN,GFP_ATOMIC);
+		if (!ct_ftp_info) {
+			ret = NF_DROP;
+			goto out;
+		}
+		memset(ct_ftp_info, 0, sizeof(*ct_ftp_info));
+	}
+
 	fb_ptr = skb_header_pointer(*pskb, dataoff,
 				    (*pskb)->len - dataoff, ftp_buffer);
 	BUG_ON(fb_ptr == NULL);
@@ -423,6 +432,9 @@
 	exp->expectfn = NULL;
 	exp->master = ct;
 
+	/* Drop lock around ip_conntrack_expect_related. */
+	WRITE_UNLOCK(&ip_conntrack_lock);
+
 	/* Now, NAT might want to mangle the packet, and register the
 	 * (possibly changed) expectation itself. */
 	if (ip_nat_ftp_hook)
@@ -437,19 +449,37 @@
 			ret = NF_ACCEPT;
 	}
 
+	WRITE_LOCK(&ip_conntrack_lock);
+	ct_ftp_info = ct_extend_find(ct->ext, CTE_FTP_CONN);
+
 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);
+		update_nl_seq(seq, ct_ftp_info, dir);
  out:
-	UNLOCK_BH(&ip_ftp_lock);
+	WRITE_UNLOCK(&ip_conntrack_lock);
 	return ret;
 }
 
 static struct ip_conntrack_helper ftp[MAX_PORTS];
 static char ftp_names[MAX_PORTS][10];
 
+static struct ct_extend_type ftp_extend =
+{
+	.len = sizeof(struct ip_ct_ftp_master),
+	.align = __alignof__(struct ip_ct_ftp_master),
+	.type = CTE_FTP_CONN,
+};
+
+/* Don't leave these lying around. */
+static int remove_ftp_ext(struct ip_conntrack *i, void *unused)
+{
+	if (i->ext)
+		i->ext = ct_extend_del(i->ext, CTE_FTP_CONN);
+	return 0;
+}
+
 /* Not __exit: called from init() */
 static void fini(void)
 {
@@ -459,6 +489,8 @@
 				ports[i]);
 		ip_conntrack_helper_unregister(&ftp[i]);
 	}
+	ip_ct_iterate_cleanup(remove_ftp_ext, NULL);
+	unregister_ct_extend_type(&ftp_extend);
 }
 
 static int __init init(void)
@@ -469,6 +501,8 @@
 	if (ports_c == 0)
 		ports[ports_c++] = FTP_PORT;
 
+	register_ct_extend_type(&ftp_extend);
+
 	for (i = 0; i < ports_c; i++) {
 		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
 		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
Index: linux-2.6.10-bk14-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h
===================================================================
--- linux-2.6.10-bk14-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack.h	2005-01-12 23:39:20.525183984 +1100
+++ linux-2.6.10-bk14-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h	2005-01-12 23:40:34.631918048 +1100
@@ -95,13 +95,6 @@
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
 
-/* per conntrack: application helper private data */
-union ip_conntrack_help {
-	/* insert conntrack helper private data (master) here */
-	struct ip_ct_ftp_master ct_ftp_info;
-	struct ip_ct_irc_master ct_irc_info;
-};
-
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 #include <linux/netfilter_ipv4/ip_nat.h>
 #endif
@@ -185,9 +178,7 @@
 	/* Storage reserved for other modules: */
 	union ip_conntrack_proto proto;
 
-	union ip_conntrack_help help;
-
-	/* Use for masqueraded connections: protected by ip_conntrack_lock */
+	/* Use for extra things: protected by ip_conntrack_lock */
 	struct ct_extend *ext;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
Index: linux-2.6.10-bk14-Netfilter/include/linux/netfilter_ipv4/ct_extend.h
===================================================================
--- linux-2.6.10-bk14-Netfilter.orig/include/linux/netfilter_ipv4/ct_extend.h	2005-01-12 23:39:20.529183376 +1100
+++ linux-2.6.10-bk14-Netfilter/include/linux/netfilter_ipv4/ct_extend.h	2005-01-12 23:41:03.500529352 +1100
@@ -5,10 +5,12 @@
 enum ct_ext_type
 {
 	CTE_MASQ,
+	CTE_FTP_CONN,
 	CTE_MAX,
 } __attribute__((packed));
 
 #define CTE_MASQ_TYPE char 	/* Actually char[IFNAMSIZ] */
+#define CTE_FTP_CONN_TYPE struct ip_ct_ftp_master
 
 /* Extensions: optional stuff which isn't permanently in struct. */
 struct ct_extend {




More information about the netfilter-devel mailing list