[PATCH 3/11] Netfilter: Fix Up IRC, AMANDA, TFTP and SNMP Helpers

Rusty Russell rusty at rustcorp.com.au
Mon Jan 17 06:45:16 CET 2005


Name: Fix Up IRC, AMANDA, TFTP and SNMP Helpers
Status: Compiled on 2.6.10-rc2-bk6
Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>

Fixes up the other helpers for direct conntrack->NAT helper calling.
SNMP doesn't really need a conntrack helper, but under this new model,
the NAT helper will register at that point anyway: NAT helpers
themselves are removed.

Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_core.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_nat_core.c	2005-01-17 14:59:08.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_core.c	2005-01-17 15:24:38.991188592 +1100
@@ -415,10 +415,6 @@
 		IP_NF_ASSERT(info->num_manips <= IP_NAT_MAX_MANIPS);
 	}
 
-	/* If there's a helper, assign it; based on new tuple. */
-	if (!conntrack->master)
-		info->helper = __ip_nat_find_helper(&reply);
-
 	/* It's done. */
 	info->initialized |= (1 << HOOK2MANIP(hooknum));
 
@@ -523,16 +519,6 @@
 			}
 		}
 	}
-
-	if (info->helper) {
-		DEBUGP("do_bindings: helper existing for (%p)\n", ct);
-
-		/* Always defragged for helpers */
-		IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
-			       & htons(IP_MF|IP_OFFSET)));
-
-		ret = info->helper->help(ct, NULL, info, ctinfo, hooknum,pskb);
-	}
 	READ_UNLOCK(&ip_nat_lock);
 
 	/* FIXME: NAT/conntrack helpers should set ctinfo &
Index: linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_nat_helper.h
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/include/linux/netfilter_ipv4/ip_nat_helper.h	2005-01-17 14:59:08.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_nat_helper.h	2005-01-17 15:24:42.044724384 +1100
@@ -7,40 +7,6 @@
 
 struct sk_buff;
 
-/* Flags */
-/* NAT helper must be called on every packet (for TCP) */
-#define IP_NAT_HELPER_F_ALWAYS		0x01
-
-struct ip_nat_helper
-{
-	struct list_head list;		/* Internal use */
-
-	const char *name;		/* name of the module */
-	unsigned char flags;		/* Flags (see above) */
-	struct module *me;		/* pointer to self */
-	
-	/* Mask of things we will help: vs. tuple from server */
-	struct ip_conntrack_tuple tuple;
-	struct ip_conntrack_tuple mask;
-	
-	/* Helper function: returns verdict */
-	unsigned int (*help)(struct ip_conntrack *ct,
-			     struct ip_conntrack_expect *exp,
-			     struct ip_nat_info *info,
-			     enum ip_conntrack_info ctinfo,
-			     unsigned int hooknum,
-			     struct sk_buff **pskb);
-};
-
-extern int ip_nat_helper_register(struct ip_nat_helper *me);
-extern void ip_nat_helper_unregister(struct ip_nat_helper *me);
-
-extern struct ip_nat_helper *
-ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
-
-extern struct ip_nat_helper *
-__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
-
 /* These return true or false. */
 extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
 				struct ip_conntrack *ct,
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_conntrack_amanda.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_conntrack_amanda.c	2005-01-06 12:02:22.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_conntrack_amanda.c	2005-01-17 15:24:41.988732896 +1100
@@ -44,14 +44,22 @@
 static char amanda_buffer[65536];
 static DECLARE_LOCK(amanda_buffer_lock);
 
-static int help(struct sk_buff *skb,
+unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
+				   struct ip_conntrack *ct,
+				   enum ip_conntrack_info ctinfo,
+				   unsigned int matchoff,
+				   unsigned int matchlen,
+				   struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_amanda_hook);
+
+static int help(struct sk_buff **pskb,
                 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
 	struct ip_conntrack_expect *exp;
-	struct ip_ct_amanda_expect *exp_amanda_info;
 	char *data, *data_limit, *tmp;
 	unsigned int dataoff, i;
 	u_int16_t port, len;
+	int ret = NF_ACCEPT;
 
 	/* Only look at packets from the Amanda server */
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
@@ -62,17 +70,17 @@
 	ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ);
 
 	/* No data? */
-	dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr);
-	if (dataoff >= skb->len) {
+	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+	if (dataoff >= (*pskb)->len) {
 		if (net_ratelimit())
-			printk("amanda_help: skblen = %u\n", skb->len);
+			printk("amanda_help: skblen = %u\n", (*pskb)->len);
 		return NF_ACCEPT;
 	}
 
 	LOCK_BH(&amanda_buffer_lock);
-	skb_copy_bits(skb, dataoff, amanda_buffer, skb->len - dataoff);
+	skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff);
 	data = amanda_buffer;
-	data_limit = amanda_buffer + skb->len - dataoff;
+	data_limit = amanda_buffer + (*pskb)->len - dataoff;
 	*data_limit = '\0';
 
 	/* Search for the CONNECT string */
@@ -96,36 +104,41 @@
 			break;
 
 		exp = ip_conntrack_expect_alloc();
-		if (exp == NULL)
+		if (exp == NULL) {
+			ret = NF_DROP;
 			goto out;
+		}
+
+		exp->expectfn = NULL;
 
 		exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+		exp->tuple.src.u.tcp.port = 0;
 		exp->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
 		exp->tuple.dst.protonum = IPPROTO_TCP;
+		exp->tuple.dst.u.tcp.port = htons(port);
+
 		exp->mask.src.ip = 0xFFFFFFFF;
+		exp->mask.src.u.tcp.port = 0;
 		exp->mask.dst.ip = 0xFFFFFFFF;
 		exp->mask.dst.protonum = 0xFFFF;
 		exp->mask.dst.u.tcp.port = 0xFFFF;
 
-		exp_amanda_info = &exp->help.exp_amanda_info;
-		exp_amanda_info->offset = tmp - amanda_buffer;
-		exp_amanda_info->port   = port;
-		exp_amanda_info->len    = len;
-
-		exp->tuple.dst.u.tcp.port = htons(port);
-
-		ip_conntrack_expect_related(exp, ct);
+		if (ip_nat_amanda_hook)
+			ret = ip_nat_amanda_hook(pskb, ct, ctinfo,
+						 tmp - amanda_buffer,
+						 len, exp);
+		else if (ip_conntrack_expect_related(exp, ct) != 0)
+			ret = NF_DROP;
 	}
 
 out:
 	UNLOCK_BH(&amanda_buffer_lock);
-	return NF_ACCEPT;
+	return ret;
 }
 
 static struct ip_conntrack_helper amanda_helper = {
 	.max_expected = ARRAY_SIZE(conns),
 	.timeout = 180,
-	.flags = IP_CT_HELPER_F_REUSE_EXPECT,
 	.me = THIS_MODULE,
 	.help = help,
 	.name = "amanda",
@@ -148,6 +161,5 @@
 	return ip_conntrack_helper_register(&amanda_helper);
 }
 
-PROVIDES_CONNTRACK(amanda);
 module_init(init);
 module_exit(fini);
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_helper.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_nat_helper.c	2005-01-17 14:59:08.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_helper.c	2005-01-17 15:24:41.988732896 +1100
@@ -47,7 +47,6 @@
 #define DUMP_OFFSET(x)
 #endif
 
-static LIST_HEAD(helpers);
 DECLARE_LOCK(ip_nat_seqofs_lock);
 
 /* Setup TCP sequence correction given this change at this sequence */
@@ -448,76 +447,3 @@
 
 	ip_nat_copy_manip(master, ct->master, ct);
 }
-
-static inline int
-helper_cmp(const struct ip_nat_helper *helper,
-	   const struct ip_conntrack_tuple *tuple)
-{
-	return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
-}
-
-int ip_nat_helper_register(struct ip_nat_helper *me)
-{
-	int ret = 0;
-
-	WRITE_LOCK(&ip_nat_lock);
-	if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple))
-		ret = -EBUSY;
-	else
-		list_prepend(&helpers, me);
-	WRITE_UNLOCK(&ip_nat_lock);
-
-	return ret;
-}
-
-struct ip_nat_helper *
-__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
-{
-	return LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple);
-}
-
-struct ip_nat_helper *
-ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
-{
-	struct ip_nat_helper *h;
-
-	READ_LOCK(&ip_nat_lock);
-	h = __ip_nat_find_helper(tuple);
-	READ_UNLOCK(&ip_nat_lock);
-
-	return h;
-}
-
-static int
-kill_helper(struct ip_conntrack *i, void *helper)
-{
-	int ret;
-
-	READ_LOCK(&ip_nat_lock);
-	ret = (i->nat.info.helper == helper);
-	READ_UNLOCK(&ip_nat_lock);
-
-	return ret;
-}
-
-void ip_nat_helper_unregister(struct ip_nat_helper *me)
-{
-	WRITE_LOCK(&ip_nat_lock);
-	/* Autoloading conntrack helper might have failed */
-	if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) {
-		LIST_DELETE(&helpers, me);
-	}
-	WRITE_UNLOCK(&ip_nat_lock);
-
-	/* Someone could be still looking at the helper in a bh. */
-	synchronize_net();
-
-	/* Find anything using it, and umm, kill them.  We can't turn
-	   them into normal connections: if we've adjusted SYNs, then
-	   they'll ackstorm.  So we just drop it.  We used to just
-	   bump module count when a connection existed, but that
-	   forces admins to gen fake RSTs or bounce box, either of
-	   which is just a long-winded way of making things
-	   worse. --RR */
-	ip_ct_iterate_cleanup(kill_helper, me);
-}
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_snmp_basic.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_nat_snmp_basic.c	2005-01-17 13:59:08.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_snmp_basic.c	2005-01-17 14:59:11.000000000 +1100
@@ -1234,15 +1234,15 @@
 	
 	if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
 	                       paylen, &map, &udph->check)) {
-		printk(KERN_WARNING "bsalg: parser failed\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "bsalg: parser failed\n");
 		return NF_DROP;
 	}
 	return NF_ACCEPT;
 }
 
-/* 
- * NAT helper function, packets arrive here from NAT code.
- */
+/* We don't actually set up expectations, just adjust internal IP
+ * addresses if this is being NATted */
 static unsigned int nat_help(struct ip_conntrack *ct,
 			     struct ip_conntrack_expect *exp,
                              struct ip_nat_info *info,
@@ -1251,25 +1251,23 @@
                              struct sk_buff **pskb)
 {
 	int dir = CTINFO2DIR(ctinfo);
+	unsigned int ret;
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
 	
-	if (!skb_ip_make_writable(pskb, (*pskb)->len))
-		return NF_DROP;
-
-	spin_lock_bh(&snmp_lock);
-	
 	/*
 	 * Translate snmp replies on pre-routing (DNAT) and snmp traps
 	 * on post routing (SNAT).
 	 */
 	if (!((dir == IP_CT_DIR_REPLY && hooknum == NF_IP_PRE_ROUTING &&
-			udph->source == ntohs(SNMP_PORT)) ||
+	       udph->source == ntohs(SNMP_PORT)) ||
 	      (dir == IP_CT_DIR_ORIGINAL && hooknum == NF_IP_POST_ROUTING &&
-	      		udph->dest == ntohs(SNMP_TRAP_PORT)))) {
-		spin_unlock_bh(&snmp_lock);
+	       udph->dest == ntohs(SNMP_TRAP_PORT))))
+		return NF_ACCEPT;
+
+	/* No NAT? */
+	if (ct->nat.num_manips == 0)
 		return NF_ACCEPT;
-	}
 
 	if (debug > 1) {
 		printk(KERN_DEBUG "bsalg: dir=%s hook=%d manip=%s len=%d "
@@ -1294,41 +1292,52 @@
 	 * enough room for a UDP header.  Just verify the UDP length field so we
 	 * can mess around with the payload.
 	 */
-	 if (ntohs(udph->len) == (*pskb)->len - (iph->ihl << 2)) {
-	 	int ret = snmp_translate(ct, info, ctinfo, hooknum, pskb);
-	 	spin_unlock_bh(&snmp_lock);
-	 	return ret;
+	if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {
+		 if (net_ratelimit())
+			 printk(KERN_WARNING "SNMP: dropping malformed packet "
+				"src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
+				NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+		 return NF_DROP;
 	}
-	
-	if (net_ratelimit())
-		printk(KERN_WARNING "bsalg: dropping malformed packet "
-		       "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
-		       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
+
+	if (!skb_ip_make_writable(pskb, (*pskb)->len))
+		return NF_DROP;
+
+	spin_lock_bh(&snmp_lock);
+	ret = snmp_translate(ct, info, ctinfo, hooknum, pskb);
 	spin_unlock_bh(&snmp_lock);
-	return NF_DROP;
+	return ret;
 }
 
-static struct ip_nat_helper snmp = { 
-	{ NULL, NULL },
-	"snmp",
-	0,
-	THIS_MODULE,
-	{ { 0, { .udp = { __constant_htons(SNMP_PORT) } } },
-	  { 0, { 0 }, IPPROTO_UDP } },
-	{ { 0, { .udp = { 0xFFFF } } },
-	  { 0, { 0 }, 0xFFFF } },
-	nat_help, NULL };
- 
-static struct ip_nat_helper snmp_trap = { 
-	{ NULL, NULL },
-	"snmp_trap",
-	0,
-	THIS_MODULE,
-	{ { 0, { .udp = { __constant_htons(SNMP_TRAP_PORT) } } },
-	  { 0, { 0 }, IPPROTO_UDP } },
-	{ { 0, { .udp = { 0xFFFF } } },
-	  { 0, { 0 }, 0xFFFF } },
-	nat_help, NULL };
+static struct ip_conntrack_helper snmp_helper = {
+	.max_expected = 0,
+	.timeout = 180,
+	.me = THIS_MODULE,
+	.help = help,
+	.name = "snmp",
+
+	.tuple = { .src = { .u = { __constant_htons(SNMP_PORT) } },
+		   .dst = { .protonum = IPPROTO_UDP },
+	},
+	.mask = { .src = { .u = { 0xFFFF } },
+		 .dst = { .protonum = 0xFFFF },
+	},
+};
+
+static struct ip_conntrack_helper snmp_trap_helper = {
+	.max_expected = 0,
+	.timeout = 180,
+	.me = THIS_MODULE,
+	.help = help,
+	.name = "snmp_trap",
+
+	.tuple = { .src = { .u = { __constant_htons(SNMP_TRAP_PORT) } },
+		   .dst = { .protonum = IPPROTO_UDP },
+	},
+	.mask = { .src = { .u = { 0xFFFF } },
+		 .dst = { .protonum = 0xFFFF },
+	},
+};
 
 /*****************************************************************************
  *
@@ -1340,12 +1349,12 @@
 {
 	int ret = 0;
 
-	ret = ip_nat_helper_register(&snmp);
+	ret = ip_conntrack_helper_register(&snmp);
 	if (ret < 0)
 		return ret;
-	ret = ip_nat_helper_register(&snmp_trap);
+	ret = ip_conntrack_helper_register(&snmp_trap);
 	if (ret < 0) {
-		ip_nat_helper_unregister(&snmp);
+		ip_conntrack_helper_unregister(&snmp);
 		return ret;
 	}
 	return ret;
@@ -1353,9 +1362,8 @@
 
 static void __exit fini(void)
 {
-	ip_nat_helper_unregister(&snmp);
-	ip_nat_helper_unregister(&snmp_trap);
-	synchronize_net();
+	ip_conntrack_helper_unregister(&snmp);
+	ip_conntrack_helper_unregister(&snmp_trap);
 }
 
 module_init(init);
Index: linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack.h	2005-01-17 14:59:08.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h	2005-01-17 15:24:42.044724384 +1100
@@ -79,11 +79,6 @@
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 #include <linux/netfilter_ipv4/ip_nat.h>
-
-/* per conntrack: nat application helper private data */
-union ip_conntrack_nat_help {
-	/* insert nat helper private data here */
-};
 #endif
 
 #include <linux/types.h>
@@ -191,7 +186,6 @@
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 	struct {
 		struct ip_nat_info info;
-		union ip_conntrack_nat_help help;
 #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
 	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
 		int masq_index;
@@ -303,15 +297,5 @@
 
 #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
 
-/* eg. PROVIDES_CONNTRACK(ftp); */
-#define PROVIDES_CONNTRACK(name)                        \
-        int needs_ip_conntrack_##name;                  \
-        EXPORT_SYMBOL(needs_ip_conntrack_##name)
-
-/*. eg. NEEDS_CONNTRACK(ftp); */
-#define NEEDS_CONNTRACK(name)                                           \
-        extern int needs_ip_conntrack_##name;                           \
-        static int *need_ip_conntrack_##name __attribute_used__ = &needs_ip_conntrack_##name
-
 #endif /* __KERNEL__ */
 #endif /* _IP_CONNTRACK_H */
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_conntrack_tftp.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_conntrack_tftp.c	2005-01-06 12:02:22.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_conntrack_tftp.c	2005-01-17 15:24:41.989732744 +1100
@@ -38,15 +38,22 @@
 #define DEBUGP(format, args...)
 #endif
 
-static int tftp_help(struct sk_buff *skb,
+unsigned int (*ip_nat_tftp_hook)(struct sk_buff **pskb,
+				 struct ip_conntrack *ct,
+				 enum ip_conntrack_info ctinfo,
+				 struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_tftp_hook);
+
+static int tftp_help(struct sk_buff **pskb,
 		     struct ip_conntrack *ct,
 		     enum ip_conntrack_info ctinfo)
 {
 	struct tftphdr _tftph, *tfh;
 	struct ip_conntrack_expect *exp;
+	unsigned int ret = NF_ACCEPT;
 
-	tfh = skb_header_pointer(skb,
-				 skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
+	tfh = skb_header_pointer(*pskb,
+				 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
 				 sizeof(_tftph), &_tftph);
 	if (tfh == NULL)
 		return NF_ACCEPT;
@@ -61,7 +68,7 @@
 
 		exp = ip_conntrack_expect_alloc();
 		if (exp == NULL)
-			return NF_ACCEPT;
+			return NF_DROP;
 
 		exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
 		exp->mask.src.ip = 0xffffffff;
@@ -73,7 +80,10 @@
 		DEBUGP("expect: ");
 		DUMP_TUPLE(&exp->tuple);
 		DUMP_TUPLE(&exp->mask);
-		ip_conntrack_expect_related(exp, ct);
+		if (ip_nat_tftp_hook)
+			ret = ip_nat_tftp_hook(pskb, ct, ctinfo, exp);
+		else if (ip_conntrack_expect_related(exp, ct) != 0)
+			ret = NF_DROP;
 		break;
 	case TFTP_OPCODE_DATA:
 	case TFTP_OPCODE_ACK:
@@ -120,7 +130,6 @@
 		tftp[i].mask.src.u.udp.port = 0xFFFF;
 		tftp[i].max_expected = 1;
 		tftp[i].timeout = 0;
-		tftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
 		tftp[i].me = THIS_MODULE;
 		tftp[i].help = tftp_help;
 
@@ -144,7 +153,5 @@
 	return(0);
 }
 
-PROVIDES_CONNTRACK(tftp);
-
 module_init(init);
 module_exit(fini);
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_amanda.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_nat_amanda.c	2005-01-13 12:11:13.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_amanda.c	2005-01-17 15:24:41.989732744 +1100
@@ -31,118 +31,63 @@
 MODULE_DESCRIPTION("Amanda NAT helper");
 MODULE_LICENSE("GPL");
 
-static unsigned int
-amanda_nat_expected(struct sk_buff **pskb,
-                    unsigned int hooknum,
-                    struct ip_conntrack *ct,
-                    struct ip_nat_info *info)
+static unsigned int help(struct sk_buff **pskb,
+			 struct ip_conntrack *ct,
+			 enum ip_conntrack_info ctinfo,
+			 unsigned int matchoff,
+			 unsigned int matchlen,
+			 struct ip_conntrack_expect *exp)
 {
-	struct ip_conntrack *master = master_ct(ct);
-	struct ip_ct_amanda_expect *exp_amanda_info;
-	struct ip_nat_range range;
-	u_int32_t newip;
-
-	IP_NF_ASSERT(info);
-	IP_NF_ASSERT(master);
-	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
-
-	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
-		newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
-	else
-		newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
-
-	/* We don't want to manip the per-protocol, just the IPs. */
-	range.flags = IP_NAT_RANGE_MAP_IPS;
-	range.min_ip = range.max_ip = newip;
-
-	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
-		exp_amanda_info = &ct->master->help.exp_amanda_info;
-		range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
-		range.min = range.max
-			= ((union ip_conntrack_manip_proto)
-				{ .udp = { htons(exp_amanda_info->port) } });
-	}
-
-	return ip_nat_setup_info(ct, &range, hooknum);
-}
-
-static int amanda_data_fixup(struct ip_conntrack *ct,
-                             struct sk_buff **pskb,
-                             enum ip_conntrack_info ctinfo,
-                             struct ip_conntrack_expect *exp)
-{
-	struct ip_ct_amanda_expect *exp_amanda_info;
-	struct ip_conntrack_tuple t = exp->tuple;
 	char buffer[sizeof("65535")];
 	u_int16_t port;
+	unsigned int ret;
 
-	/* Alter conntrack's expectations. */
-	exp_amanda_info = &exp->help.exp_amanda_info;
-	t.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
-	for (port = exp_amanda_info->port; port != 0; port++) {
-		t.dst.u.tcp.port = htons(port);
-		if (ip_conntrack_change_expect(exp, &t) == 0)
+	/* Connection comes from client. */
+	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+	exp->dir = IP_CT_DIR_ORIGINAL;
+
+	/* When you see the packet, we need to NAT it the same as the
+	 * this one (ie. same IP: it will be TCP and master is UDP). */
+	exp->expectfn = ip_nat_follow_master;
+
+	/* Try to get same port: if not, try to change it. */
+	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+		int err;
+		exp->tuple.dst.u.tcp.port = htons(port);
+		atomic_inc(&exp->use);
+		err = ip_conntrack_expect_related(exp, ct);
+		/* Success, or retransmit. */
+		if (!err || err == -EEXIST)
 			break;
 	}
-	if (port == 0)
-		return 0;
-
-	sprintf(buffer, "%u", port);
-	return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
-	                                exp_amanda_info->offset,
-	                                exp_amanda_info->len,
-	                                buffer, strlen(buffer));
-}
 
-static unsigned int help(struct ip_conntrack *ct,
-                         struct ip_conntrack_expect *exp,
-                         struct ip_nat_info *info,
-                         enum ip_conntrack_info ctinfo,
-                         unsigned int hooknum,
-                         struct sk_buff **pskb)
-{
-	int dir = CTINFO2DIR(ctinfo);
-	int ret = NF_ACCEPT;
-
-	/* Only mangle things once: original direction in POST_ROUTING
-	   and reply direction on PRE_ROUTING. */
-	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
-	      || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
-		return NF_ACCEPT;
-
-	/* if this exectation has a "offset" the packet needs to be mangled */
-	if (exp->help.exp_amanda_info.offset != 0)
-		if (!amanda_data_fixup(ct, pskb, ctinfo, exp))
-			ret = NF_DROP;
-	exp->help.exp_amanda_info.offset = 0;
+	if (port == 0) {
+		ip_conntrack_expect_put(exp);
+		return NF_DROP;
+	}
 
+	sprintf(buffer, "%u", port);
+	ret = ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+				       matchoff, matchlen,
+				       buffer, strlen(buffer));
+	if (ret != NF_ACCEPT)
+		ip_conntrack_unexpect_related(exp);
 	return ret;
 }
 
-static struct ip_nat_helper ip_nat_amanda_helper;
-
 static void __exit fini(void)
 {
-	ip_nat_helper_unregister(&ip_nat_amanda_helper);
+	ip_nat_amanda_hook = NULL;
+	/* Make sure noone calls it, meanwhile. */
+	synchronize_net();
 }
 
 static int __init init(void)
 {
-	struct ip_nat_helper *hlpr = &ip_nat_amanda_helper;
-
-	hlpr->tuple.dst.protonum = IPPROTO_UDP;
-	hlpr->tuple.src.u.udp.port = htons(10080);
-	hlpr->mask.src.u.udp.port = 0xFFFF;
-	hlpr->mask.dst.protonum = 0xFFFF;
-	hlpr->help = help;
-	hlpr->flags = 0;
-	hlpr->me = THIS_MODULE;
-	hlpr->expect = amanda_nat_expected;
-	hlpr->name = "amanda";
-
-	return ip_nat_helper_register(hlpr);
+	BUG_ON(ip_nat_amanda_hook);
+	ip_nat_amanda_hook = help;
+	return 0;
 }
 
-NEEDS_CONNTRACK(amanda);
 module_init(init);
 module_exit(fini);
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_tftp.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_nat_tftp.c	2005-01-13 12:11:13.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_tftp.c	2005-01-17 15:24:41.989732744 +1100
@@ -38,168 +38,33 @@
 MODULE_DESCRIPTION("tftp NAT helper");
 MODULE_LICENSE("GPL");
 
-#define MAX_PORTS 8
-
-static int ports[MAX_PORTS];
-static int ports_c = 0;
-module_param_array(ports, int, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "port numbers of tftp servers");
-
-#if 0
-#define DEBUGP(format, args...) printk("%s:%s:" format, \
-                                       __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-static unsigned int 
-tftp_nat_help(struct ip_conntrack *ct,
-	      struct ip_conntrack_expect *exp,
-	      struct ip_nat_info *info,
-	      enum ip_conntrack_info ctinfo,
-	      unsigned int hooknum,
-	      struct sk_buff **pskb)
+static unsigned int help(struct sk_buff **pskb,
+			 struct ip_conntrack *ct,
+			 enum ip_conntrack_info ctinfo,
+			 struct ip_conntrack_expect *exp)
 {
-	int dir = CTINFO2DIR(ctinfo);
-	struct tftphdr _tftph, *tfh;
-	struct ip_conntrack_tuple repl;
-
-	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
-	      || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) 
-		return NF_ACCEPT;
-
-	if (!exp) {
-		DEBUGP("no conntrack expectation to modify\n");
-		return NF_ACCEPT;
-	}
-
-	tfh = skb_header_pointer(*pskb,
-				 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
-				 sizeof(_tftph), &_tftph);
-	if (tfh == NULL)
+	exp->saved_proto.udp.port = exp->tuple.dst.u.tcp.port;
+	exp->dir = IP_CT_DIR_REPLY;
+	exp->expectfn = ip_nat_follow_master;
+	if (ip_conntrack_expect_related(exp, ct) != 0) {
+		ip_conntrack_expect_put(exp);
 		return NF_DROP;
-
-	switch (ntohs(tfh->opcode)) {
-	/* RRQ and WRQ works the same way */
-	case TFTP_OPCODE_READ:
-	case TFTP_OPCODE_WRITE:
-		repl = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-		DEBUGP("");
-		DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-		DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-		DEBUGP("expecting: ");
-		DUMP_TUPLE(&repl);
-		DUMP_TUPLE(&exp->mask);
-		ip_conntrack_change_expect(exp, &repl);
-		break;
-	default:
-		DEBUGP("Unknown opcode\n");
-	}               
-
-	return NF_ACCEPT;
-}
-
-static unsigned int 
-tftp_nat_expected(struct sk_buff **pskb,
-		  unsigned int hooknum,
-		  struct ip_conntrack *ct, 
-		  struct ip_nat_info *info) 
-{
-	const struct ip_conntrack *master = ct->master->expectant;
-	const struct ip_conntrack_tuple *orig = 
-			&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-	struct ip_nat_range range;
-#if 0
-	const struct ip_conntrack_tuple *repl =
-			&master->tuplehash[IP_CT_DIR_REPLY].tuple;
-	struct udphdr _udph, *uh;
-
-	uh = skb_header_pointer(*pskb,
-				(*pskb)->nh.iph->ihl*4,
-				sizeof(_udph), &_udph);
-	if (uh == NULL)
-		return NF_DROP;
-#endif
-
-	IP_NF_ASSERT(info);
-	IP_NF_ASSERT(master);
-	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
-
-	range.flags = IP_NAT_RANGE_MAP_IPS;
-
-	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
-		range.min_ip = range.max_ip = orig->dst.ip; 
-		DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
-			"newsrc: %u.%u.%u.%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
- 			NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
-			NIPQUAD(orig->dst.ip));
-	} else {
-		range.min_ip = range.max_ip = orig->src.ip;
-		range.min.udp.port = range.max.udp.port = orig->src.u.udp.port;
-		range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
-
-		DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
-			"newdst: %u.%u.%u.%u:%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
-                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
-                        NIPQUAD(orig->src.ip), ntohs(orig->src.u.udp.port));
 	}
-
-	return ip_nat_setup_info(ct, &range, hooknum);
+	return NF_ACCEPT;
 }
 
-static struct ip_nat_helper tftp[MAX_PORTS];
-static char tftp_names[MAX_PORTS][10];
-
-static void fini(void)
+static void __exit fini(void)
 {
-	int i;
-
-	for (i = 0 ; i < ports_c; i++) {
-		DEBUGP("unregistering helper for port %d\n", ports[i]);
-		ip_nat_helper_unregister(&tftp[i]);
-	}
+	ip_nat_tftp_hook = NULL;
+	/* Make sure noone calls it, meanwhile. */
+	synchronize_net();
 }
 
 static int __init init(void)
 {
-	int i, ret = 0;
-	char *tmpname;
-
-	if (ports_c == 0)
-		ports[ports_c++] = TFTP_PORT;
-
-	for (i = 0; i < ports_c; i++) {
-		memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
-
-		tftp[i].tuple.dst.protonum = IPPROTO_UDP;
-		tftp[i].tuple.src.u.udp.port = htons(ports[i]);
-		tftp[i].mask.dst.protonum = 0xFFFF;
-		tftp[i].mask.src.u.udp.port = 0xFFFF;
-		tftp[i].help = tftp_nat_help;
-		tftp[i].flags = 0;
-		tftp[i].me = THIS_MODULE;
-		tftp[i].expect = tftp_nat_expected;
-
-		tmpname = &tftp_names[i][0];
-		if (ports[i] == TFTP_PORT)
-			sprintf(tmpname, "tftp");
-		else
-			sprintf(tmpname, "tftp-%d", i);
-		tftp[i].name = tmpname;
-		
-		DEBUGP("ip_nat_tftp: registering for port %d: name %s\n",
-			ports[i], tftp[i].name);
-		ret = ip_nat_helper_register(&tftp[i]);
-
-		if (ret) {
-			printk("ip_nat_tftp: unable to register for port %d\n",
-				ports[i]);
-			fini();
-			return ret;
-		}
-	}
-	return ret;
+	BUG_ON(ip_nat_tftp_hook);
+	ip_nat_tftp_hook = help;
+	return 0;
 }
 
 module_init(init);
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_irc.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_nat_irc.c	2005-01-13 12:11:13.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_nat_irc.c	2005-01-17 15:24:41.989732744 +1100
@@ -1,5 +1,6 @@
 /* IRC extension for TCP NAT alteration.
  * (C) 2000-2001 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2004 Rusty Russell <rusty at rustcorp.com.au> IBM Corporation
  * based on a copy of RR's ip_nat_ftp.c
  *
  * ip_nat_irc.c,v 1.16 2001/12/06 07:42:10 laforge Exp
@@ -8,12 +9,6 @@
  *      modify it under the terms of the GNU General Public License
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
- *
- *	Module load syntax:
- * 	insmod ip_nat_irc.o ports=port1,port2,...port<MAX_PORTS>
- *	
- * 	please give the ports of all IRC servers You wish to connect to.
- *	If You don't specify ports, the default will be port 6667
  */
 
 #include <linux/module.h>
@@ -35,66 +30,21 @@
 #define DEBUGP(format, args...)
 #endif
 
-#define MAX_PORTS 8
-static int ports[MAX_PORTS];
-static int ports_c;
-
 MODULE_AUTHOR("Harald Welte <laforge at gnumonks.org>");
 MODULE_DESCRIPTION("IRC (DCC) NAT helper");
 MODULE_LICENSE("GPL");
-module_param_array(ports, int, &ports_c, 0400);
-MODULE_PARM_DESC(ports, "port numbers of IRC servers");
 
 /* FIXME: Time out? --RR */
 
-static unsigned int
-irc_nat_expected(struct sk_buff **pskb,
-		 unsigned int hooknum,
-		 struct ip_conntrack *ct,
-		 struct ip_nat_info *info)
-{
-	struct ip_nat_range range;
-	u_int32_t newdstip, newsrcip, newip;
-
-	struct ip_conntrack *master = master_ct(ct);
-
-	IP_NF_ASSERT(info);
-	IP_NF_ASSERT(master);
-
-	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
-
-	DEBUGP("nat_expected: We have a connection!\n");
-
-	newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-	newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-	DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
-	       NIPQUAD(newsrcip), NIPQUAD(newdstip));
-
-	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
-		newip = newsrcip;
-	else
-		newip = newdstip;
-
-	DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
-
-	/* We don't want to manip the per-protocol, just the IPs. */
-	range.flags = IP_NAT_RANGE_MAP_IPS;
-	range.min_ip = range.max_ip = newip;
-
-	return ip_nat_setup_info(ct, &range, hooknum);
-}
-
-static int irc_data_fixup(const struct ip_ct_irc_expect *exp_irc_info,
-			  struct ip_conntrack *ct,
-			  struct sk_buff **pskb,
-			  enum ip_conntrack_info ctinfo,
-			  struct ip_conntrack_expect *expect)
+static unsigned int help(struct sk_buff **pskb,
+			 struct ip_conntrack *ct,
+			 enum ip_conntrack_info ctinfo,
+			 unsigned int matchoff,
+			 unsigned int matchlen,
+			 struct ip_conntrack_expect *exp)
 {
-	u_int32_t newip;
-	struct ip_conntrack_tuple t;
-	struct iphdr *iph = (*pskb)->nh.iph;
-	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
 	u_int16_t port;
+	unsigned int ret;
 
 	/* "4294967296 65635 " */
 	char buffer[18];
@@ -103,21 +53,30 @@
 	       expect->seq, exp_irc_info->len,
 	       ntohl(tcph->seq));
 
-	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
-
-	/* Alter conntrack's expectations. */
-	t = expect->tuple;
-	t.dst.ip = newip;
-	for (port = exp_irc_info->port; port != 0; port++) {
-		t.dst.u.tcp.port = htons(port);
-		if (ip_conntrack_change_expect(expect, &t) == 0) {
-			DEBUGP("using port %d", port);
+	/* Reply comes from server. */
+	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+	exp->dir = IP_CT_DIR_REPLY;
+
+	/* When you see the packet, we need to NAT it the same as the
+	 * this one. */
+	exp->expectfn = ip_nat_follow_master;
+
+	/* Try to get same port: if not, try to change it. */
+	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
+		int err;
+
+		exp->tuple.dst.u.tcp.port = htons(port);
+		atomic_inc(&exp->use);
+		err = ip_conntrack_expect_related(exp, ct);
+		/* Success, or retransmit. */
+		if (!err || err == -EEXIST)
 			break;
-		}
+	}
 
+	if (port == 0) {
+		ip_conntrack_expect_put(exp);
+		return NF_DROP;
 	}
-	if (port == 0)
-		return 0;
 
 	/*      strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
 	 *      strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
@@ -132,131 +91,31 @@
 	 *              0x01, \n:  terminators
 	 */
 
-	sprintf(buffer, "%u %u", ntohl(newip), port);
+	sprintf(buffer, "%u %u", ntohl(exp->tuple.src.ip), port);
 	DEBUGP("ip_nat_irc: Inserting '%s' == %u.%u.%u.%u, port %u\n",
-	       buffer, NIPQUAD(newip), port);
-
-	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
-					expect->seq - ntohl(tcph->seq),
-					exp_irc_info->len, buffer, 
-					strlen(buffer));
-}
-
-static unsigned int help(struct ip_conntrack *ct,
-			 struct ip_conntrack_expect *exp,
-			 struct ip_nat_info *info,
-			 enum ip_conntrack_info ctinfo,
-			 unsigned int hooknum, 
-			 struct sk_buff **pskb)
-{
-	struct iphdr *iph = (*pskb)->nh.iph;
-	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
-	unsigned int datalen;
-	int dir;
-	struct ip_ct_irc_expect *exp_irc_info;
-
-	if (!exp)
-		DEBUGP("ip_nat_irc: no exp!!");
-		
-	exp_irc_info = &exp->help.exp_irc_info;
-
-	/* Only mangle things once: original direction in POST_ROUTING
-	   and reply direction on PRE_ROUTING. */
-	dir = CTINFO2DIR(ctinfo);
-	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
-	      || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
-		DEBUGP("nat_irc: Not touching dir %s at hook %s\n",
-		       dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-		       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-		       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-		       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
-		return NF_ACCEPT;
-	}
-	DEBUGP("got beyond not touching\n");
+	       buffer, NIPQUAD(exp->tuple.src.ip), port);
 
-	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	/* Check whether the whole IP/address pattern is carried in the payload */
-	if (between(exp->seq + exp_irc_info->len,
-		    ntohl(tcph->seq),
-		    ntohl(tcph->seq) + datalen)) {
-		if (!irc_data_fixup(exp_irc_info, ct, pskb, ctinfo, exp))
-			return NF_DROP;
-	} else { 
-		/* Half a match?  This means a partial retransmisison.
-		   It's a cracker being funky. */
-		if (net_ratelimit()) {
-			printk
-			    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
-			     exp->seq, exp_irc_info->len,
-			     ntohl(tcph->seq),
-			     ntohl(tcph->seq) + datalen);
-		}
-		return NF_DROP;
-	}
-	return NF_ACCEPT;
+	ret = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
+				       matchoff, matchlen, buffer, 
+				       strlen(buffer));
+	if (ret != NF_ACCEPT)
+		ip_conntrack_unexpect_related(exp);
+	return ret;
 }
 
-static struct ip_nat_helper ip_nat_irc_helpers[MAX_PORTS];
-static char irc_names[MAX_PORTS][10];
-
-/* This function is intentionally _NOT_ defined as  __exit, because
- * it is needed by init() */
-static void fini(void)
+static void __exit fini(void)
 {
-	int i;
-
-	for (i = 0; i < ports_c; i++) {
-		DEBUGP("ip_nat_irc: unregistering helper for port %d\n",
-		       ports[i]);
-		ip_nat_helper_unregister(&ip_nat_irc_helpers[i]);
-	} 
+	ip_nat_irc_hook = NULL;
+	/* Make sure noone calls it, meanwhile. */
+	synchronize_net();
 }
 
 static int __init init(void)
 {
-	int ret = 0;
-	int i;
-	struct ip_nat_helper *hlpr;
-	char *tmpname;
-
-	if (ports_c == 0)
-		ports[ports_c++] = IRC_PORT;
-
-	for (i = 0; i < ports_c; i++) {
-		hlpr = &ip_nat_irc_helpers[i];
-		hlpr->tuple.dst.protonum = IPPROTO_TCP;
-		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
-		hlpr->mask.src.u.tcp.port = 0xFFFF;
-		hlpr->mask.dst.protonum = 0xFFFF;
-		hlpr->help = help;
-		hlpr->flags = 0;
-		hlpr->me = THIS_MODULE;
-		hlpr->expect = irc_nat_expected;
-
-		tmpname = &irc_names[i][0];
-		if (ports[i] == IRC_PORT)
-			sprintf(tmpname, "irc");
-		else
-			sprintf(tmpname, "irc-%d", i);
-		hlpr->name = tmpname;
-
-		DEBUGP
-		    ("ip_nat_irc: Trying to register helper for port %d: name %s\n",
-		     ports[i], hlpr->name);
-		ret = ip_nat_helper_register(hlpr);
-
-		if (ret) {
-			printk
-			    ("ip_nat_irc: error registering helper for port %d\n",
-			     ports[i]);
-			fini();
-			return 1;
-		}
-	}
-	return ret;
+	BUG_ON(ip_nat_irc_hook);
+	ip_nat_irc_hook = help;
+	return 0;
 }
 
-NEEDS_CONNTRACK(irc);
-
 module_init(init);
 module_exit(fini);
Index: linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_tftp.h
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack_tftp.h	2005-01-06 12:02:22.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_tftp.h	2005-01-17 15:24:42.044724384 +1100
@@ -13,4 +13,9 @@
 #define TFTP_OPCODE_ACK		4
 #define TFTP_OPCODE_ERROR	5
 
+unsigned int (*ip_nat_tftp_hook)(struct sk_buff **pskb,
+				 struct ip_conntrack *ct,
+				 enum ip_conntrack_info ctinfo,
+				 struct ip_conntrack_expect *exp);
+
 #endif /* _IP_CT_TFTP */
Index: linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_conntrack_irc.c
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/net/ipv4/netfilter/ip_conntrack_irc.c	2005-01-06 12:02:22.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/net/ipv4/netfilter/ip_conntrack_irc.c	2005-01-17 15:24:41.989732744 +1100
@@ -43,6 +43,14 @@
 static char irc_buffer[65536];
 static DECLARE_LOCK(irc_buffer_lock);
 
+unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
+				struct ip_conntrack *ct,
+				enum ip_conntrack_info ctinfo,
+				unsigned int matchoff,
+				unsigned int matchlen,
+				struct ip_conntrack_expect *exp);
+EXPORT_SYMBOL_GPL(ip_nat_irc_hook);
+
 MODULE_AUTHOR("Harald Welte <davem at davemloft.net>");
 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
 MODULE_LICENSE("GPL");
@@ -98,7 +106,7 @@
 	return 0;
 }
 
-static int help(struct sk_buff *skb,
+static int help(struct sk_buff **pskb,
 		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
 	unsigned int dataoff;
@@ -106,11 +114,10 @@
 	char *data, *data_limit, *ib_ptr;
 	int dir = CTINFO2DIR(ctinfo);
 	struct ip_conntrack_expect *exp;
-	struct ip_ct_irc_expect *exp_irc_info = NULL;
-
+	u32 seq;
 	u_int32_t dcc_ip;
 	u_int16_t dcc_port;
-	int i;
+	int i, ret = NF_ACCEPT;
 	char *addr_beg_p, *addr_end_p;
 
 	DEBUGP("entered\n");
@@ -127,23 +134,23 @@
 	}
 
 	/* Not a full tcp header? */
-	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+	th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
 				sizeof(_tcph), &_tcph);
 	if (th == NULL)
 		return NF_ACCEPT;
 
 	/* No data? */
-	dataoff = skb->nh.iph->ihl*4 + th->doff*4;
-	if (dataoff >= skb->len)
+	dataoff = (*pskb)->nh.iph->ihl*4 + th->doff*4;
+	if (dataoff >= (*pskb)->len)
 		return NF_ACCEPT;
 
 	LOCK_BH(&irc_buffer_lock);
-	ib_ptr = skb_header_pointer(skb, dataoff,
-				    skb->len - dataoff, irc_buffer);
+	ib_ptr = skb_header_pointer(*pskb, dataoff,
+				    (*pskb)->len - dataoff, irc_buffer);
 	BUG_ON(ib_ptr == NULL);
 
 	data = ib_ptr;
-	data_limit = ib_ptr + skb->len - dataoff;
+	data_limit = ib_ptr + (*pskb)->len - dataoff;
 
 	/* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
 	 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
@@ -195,19 +202,15 @@
 			}
 
 			exp = ip_conntrack_expect_alloc();
-			if (exp == NULL)
+			if (exp == NULL) {
+				ret = NF_DROP;
 				goto out;
-
-			exp_irc_info = &exp->help.exp_irc_info;
+			}
 
 			/* save position of address in dcc string,
 			 * necessary for NAT */
 			DEBUGP("tcph->seq = %u\n", th->seq);
-			exp->seq = ntohl(th->seq) + (addr_beg_p - ib_ptr);
-			exp_irc_info->len = (addr_end_p - addr_beg_p);
-			exp_irc_info->port = dcc_port;
-			DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n",
-				exp->seq, (addr_end_p - _data), exp_irc_info->len);
+			seq = ntohl(th->seq) + (addr_beg_p - ib_ptr);
 
 			exp->tuple = ((struct ip_conntrack_tuple)
 				{ { 0, { 0 } },
@@ -216,24 +219,21 @@
 			exp->mask = ((struct ip_conntrack_tuple)
 				{ { 0, { 0 } },
 				  { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
-
 			exp->expectfn = NULL;
-
-			DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
-				NIPQUAD(exp->tuple.src.ip),
-				ntohs(exp->tuple.src.u.tcp.port),
-				NIPQUAD(exp->tuple.dst.ip),
-				ntohs(exp->tuple.dst.u.tcp.port));
-
-			ip_conntrack_expect_related(exp, ct);
-
+			if (ip_nat_irc_hook)
+				ret = ip_nat_irc_hook(pskb, ct, ctinfo, 
+						      addr_beg_p - ib_ptr,
+						      addr_end_p - addr_beg_p,
+						      exp);
+			else if (ip_conntrack_expect_related(exp, ct) != 0)
+				ret = NF_DROP;
 			goto out;
 		} /* for .. NUM_DCCPROTO */
 	} /* while data < ... */
 
  out:
 	UNLOCK_BH(&irc_buffer_lock);
-	return NF_ACCEPT;
+	return ret;
 }
 
 static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
@@ -268,7 +268,6 @@
 		hlpr->mask.dst.protonum = 0xFFFF;
 		hlpr->max_expected = max_dcc_channels;
 		hlpr->timeout = dcc_timeout;
-		hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
 		hlpr->me = ip_conntrack_irc;
 		hlpr->help = help;
 
@@ -305,7 +304,5 @@
 	}
 }
 
-PROVIDES_CONNTRACK(irc);
-
 module_init(init);
 module_exit(fini);
Index: linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_irc.h
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack_irc.h	2005-01-06 12:02:22.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_irc.h	2005-01-17 15:24:42.044724384 +1100
@@ -14,24 +14,17 @@
 #ifndef _IP_CONNTRACK_IRC_H
 #define _IP_CONNTRACK_IRC_H
 
-/* We record seq number and length of irc ip/port text here: all in
-   host order. */
-
-/* This structure is per expected connection */
-struct ip_ct_irc_expect
-{
-	/* length of IP address */
-	u_int32_t len;
-	/* Port that was to be used */
-	u_int16_t port;
-};
-
 /* This structure exists only once per master */
 struct ip_ct_irc_master {
 };
 
-
 #ifdef __KERNEL__
+extern unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
+				       struct ip_conntrack *ct,
+				       enum ip_conntrack_info ctinfo,
+				       unsigned int matchoff,
+				       unsigned int matchlen,
+				       struct ip_conntrack_expect *exp);
 
 #define IRC_PORT	6667
 
Index: linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_amanda.h
===================================================================
--- linux-2.6.11-rc1-bk4-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack_amanda.h	2005-01-06 12:02:22.000000000 +1100
+++ linux-2.6.11-rc1-bk4-Netfilter/include/linux/netfilter_ipv4/ip_conntrack_amanda.h	2005-01-17 15:24:42.044724384 +1100
@@ -2,11 +2,11 @@
 #define _IP_CONNTRACK_AMANDA_H
 /* AMANDA tracking. */
 
-struct ip_ct_amanda_expect
-{
-	u_int16_t port;		/* port number of this expectation */
-	u_int16_t offset;	/* offset of port in ctrl packet */
-	u_int16_t len;		/* length of the port number string */
-};
-
+struct ip_conntrack_expect;
+extern unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
+					  struct ip_conntrack *ct,
+					  enum ip_conntrack_info ctinfo,
+					  unsigned int matchoff,
+					  unsigned int matchlen,
+					  struct ip_conntrack_expect *exp);
 #endif /* _IP_CONNTRACK_AMANDA_H */




More information about the netfilter-devel mailing list