Name: Use ct_extend for conntrack protocol helpers Status: Tested under nfsim Signed-off-by: Rusty Russell 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 #include #include +#include #include 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 #include -/* 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 #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 {