All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2.6] Allow dynamic helper-port assignment
@ 2005-02-13 16:56 Harald Welte
  2005-02-13 17:34 ` Max Kellermann
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Harald Welte @ 2005-02-13 16:56 UTC (permalink / raw)
  To: Netfilter Development Mailinglist


[-- Attachment #1.1: Type: text/plain, Size: 1108 bytes --]

Hi!

The recent problem with h323 made me again consider the old idea of
having runtime-configurable port assignments for helpers. 

Ideally, we would actually have conntrack helpers be iptables targets,
this way allowing totally dynamic assignemnt.  Maybe yet another
pkttables todo.

Meanwhile, the following patch uses the same mechanism as CLUSTERIP:

Add port 2121 to ftp helper:
	echo "+2121" > /proc/net/ip_conntrack_helper/ftp

Remove port 6669 from irc helper:
	echo "-6669" > /proc/net/ip_conntrack_helper/irc

Show registered ports for amanda helper:
	cat /proc/net/ip_conntrack_helper/amanda

If nobody complains, we should push this for 2.6.12.

And yes, I'll do the nf_conntrack merge right now :)

-- 
- Harald Welte <laforge@netfilter.org>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #1.2: 2.6.11-rc4-ip_conntrack_helper_proc.patch --]
[-- Type: text/plain, Size: 21772 bytes --]

diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.6.11-rc4-helper_sysctl/include/linux/netfilter_ipv4/ip_conntrack_core.h
--- linux-2.6.11-rc4/include/linux/netfilter_ipv4/ip_conntrack_core.h	2005-02-13 13:52:05.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/include/linux/netfilter_ipv4/ip_conntrack_core.h	2005-02-13 16:15:56.000000000 +0100
@@ -48,5 +48,10 @@
 extern struct list_head *ip_conntrack_hash;
 extern struct list_head ip_conntrack_expect_list;
 DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
+extern struct list_head ip_conntrack_unconfirmed;
+
+extern void __ip_ct_destroy_expect(struct ip_conntrack_expect *exp);
+extern void __ip_ct_unlink_expect(struct ip_conntrack_expect *exp);
+
 #endif /* _IP_CONNTRACK_CORE_H */
 
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/include/linux/netfilter_ipv4/ip_conntrack_helper.h linux-2.6.11-rc4-helper_sysctl/include/linux/netfilter_ipv4/ip_conntrack_helper.h
--- linux-2.6.11-rc4/include/linux/netfilter_ipv4/ip_conntrack_helper.h	2005-02-13 13:52:05.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/include/linux/netfilter_ipv4/ip_conntrack_helper.h	2005-02-13 16:44:16.000000000 +0100
@@ -15,6 +15,10 @@
 					 * expected connections */
 	unsigned int timeout;		/* timeout for expecteds */
 
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry	*pde;	/* proc file for port changes */
+#endif
+
 	/* Mask of things we will help (compared against server response) */
 	struct ip_conntrack_tuple tuple;
 	struct ip_conntrack_tuple mask;
@@ -29,6 +33,11 @@
 extern int ip_conntrack_helper_register(struct ip_conntrack_helper *);
 extern void ip_conntrack_helper_unregister(struct ip_conntrack_helper *);
 
+extern int ip_conntrack_helper_add_port(struct ip_conntrack_helper *h,
+					u_int16_t port);
+extern int ip_conntrack_helper_del_port(struct ip_conntrack_helper *h,
+					u_int16_t port);
+
 /* Allocate space for an expectation: this is mandatory before calling 
    ip_conntrack_expect_related. */
 extern struct ip_conntrack_expect *ip_conntrack_expect_alloc(void);
@@ -38,4 +47,10 @@
 extern int ip_conntrack_expect_related(struct ip_conntrack_expect *exp);
 extern void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp);
 
+/* Find the helper for a for a particular tuple */
+extern struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple);
+
+extern int ip_conntrack_helper_init(void);
+extern void ip_conntrack_helper_fini(void);
+
 #endif /*_IP_CONNTRACK_HELPER_H*/
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/Makefile linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/Makefile
--- linux-2.6.11-rc4/net/ipv4/netfilter/Makefile	2005-02-13 13:52:06.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/Makefile	2005-02-13 13:59:13.000000000 +0100
@@ -3,7 +3,7 @@
 #
 
 # objects for the standalone - connection tracking / NAT
-ip_conntrack-objs	:= ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
+ip_conntrack-objs	:= ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_helper.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
 iptable_nat-objs	:= ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
 
 # connection tracking
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_amanda.c
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_amanda.c	2005-02-13 13:52:06.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_amanda.c	2005-02-13 17:41:38.000000000 +0100
@@ -160,7 +160,11 @@
 
 static int __init init(void)
 {
-	return ip_conntrack_helper_register(&amanda_helper);
+	int ret = ip_conntrack_helper_register(&amanda_helper);
+	if (ret)
+		return ret;
+	return ip_conntrack_helper_add_port(&amanda_helper,
+				ntohs(amanda_helper.tuple.src.u.tcp.port));
 }
 
 module_init(init);
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_core.c	2005-02-13 13:52:06.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_core.c	2005-02-13 17:01:40.000000000 +0100
@@ -49,7 +49,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
-#define IP_CONNTRACK_VERSION	"2.1"
+#define IP_CONNTRACK_VERSION	"2.2"
 
 #if 0
 #define DEBUGP printk
@@ -65,7 +65,6 @@
 void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
 LIST_HEAD(ip_conntrack_expect_list);
 struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
-static LIST_HEAD(helpers);
 unsigned int ip_conntrack_htable_size = 0;
 int ip_conntrack_max;
 struct list_head *ip_conntrack_hash;
@@ -73,7 +72,7 @@
 static kmem_cache_t *ip_conntrack_expect_cachep;
 struct ip_conntrack ip_conntrack_untracked;
 unsigned int ip_ct_log_invalid;
-static LIST_HEAD(unconfirmed);
+LIST_HEAD(ip_conntrack_unconfirmed);
 static int ip_conntrack_vmalloc;
 
 DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
@@ -137,7 +136,7 @@
 
 
 /* ip_conntrack_expect helper functions */
-static void destroy_expect(struct ip_conntrack_expect *exp)
+void __ip_ct_destroy_expect(struct ip_conntrack_expect *exp)
 {
 	ip_conntrack_put(exp->master);
 	IP_NF_ASSERT(!timer_pending(&exp->timeout));
@@ -145,7 +144,7 @@
 	CONNTRACK_STAT_INC(expect_delete);
 }
 
-static void unlink_expect(struct ip_conntrack_expect *exp)
+void __ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
 {
 	MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
 	list_del(&exp->list);
@@ -158,9 +157,9 @@
 	struct ip_conntrack_expect *exp = (void *)ul_expect;
 
 	WRITE_LOCK(&ip_conntrack_lock);
-	unlink_expect(exp);
+	__ip_ct_unlink_expect(exp);
 	WRITE_UNLOCK(&ip_conntrack_lock);
-	destroy_expect(exp);
+	__ip_ct_destroy_expect(exp);
 }
 
 /* If an expectation for this connection is found, it gets delete from
@@ -179,7 +178,7 @@
 		if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
 		    && is_confirmed(i->master)
 		    && del_timer(&i->timeout)) {
-			unlink_expect(i);
+			__ip_ct_unlink_expect(i);
 			return i;
 		}
 	}
@@ -197,8 +196,8 @@
 
 	list_for_each_entry_safe(i, tmp, &ip_conntrack_expect_list, list) {
 		if (i->master == ct && del_timer(&i->timeout)) {
-			unlink_expect(i);
-			destroy_expect(i);
+			__ip_ct_unlink_expect(i);
+			__ip_ct_destroy_expect(i);
 		}
 	}
 }
@@ -439,19 +438,6 @@
 	return dropped;
 }
 
-static inline int helper_cmp(const struct ip_conntrack_helper *i,
-			     const struct ip_conntrack_tuple *rtuple)
-{
-	return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
-}
-
-static struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
-{
-	return LIST_FIND(&helpers, helper_cmp,
-			 struct ip_conntrack_helper *,
-			 tuple);
-}
-
 /* Allocate a new conntrack: we return -ENOMEM if classification
    failed due to stress.  Otherwise it really is unclassifiable. */
 static struct ip_conntrack_tuple_hash *
@@ -529,7 +515,8 @@
 	}
 
 	/* Overload tuple linked list to put us in unconfirmed list. */
-	list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
+	list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list,
+		 &ip_conntrack_unconfirmed);
 
 	atomic_inc(&ip_conntrack_count);
 	WRITE_UNLOCK(&ip_conntrack_lock);
@@ -537,7 +524,7 @@
 	if (exp) {
 		if (exp->expectfn)
 			exp->expectfn(conntrack, exp);
-		destroy_expect(exp);
+		__ip_ct_destroy_expect(exp);
 	}
 
 	return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
@@ -727,9 +714,9 @@
 	/* choose the the oldest expectation to evict */
 	list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
 		if (expect_matches(i, exp) && del_timer(&i->timeout)) {
-			unlink_expect(i);
+			__ip_ct_unlink_expect(i);
 			WRITE_UNLOCK(&ip_conntrack_lock);
-			destroy_expect(i);
+			__ip_ct_destroy_expect(i);
 			return;
 		}
 	}
@@ -781,8 +768,8 @@
 	list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
 		if (i->master == master) {
 			if (del_timer(&i->timeout)) {
-				unlink_expect(i);
-				destroy_expect(i);
+				__ip_ct_unlink_expect(i);
+				__ip_ct_destroy_expect(i);
 			}
 			break;
 		}
@@ -854,50 +841,6 @@
 	WRITE_UNLOCK(&ip_conntrack_lock);
 }
 
-int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
-{
-	BUG_ON(me->timeout == 0);
-	WRITE_LOCK(&ip_conntrack_lock);
-	list_prepend(&helpers, me);
-	WRITE_UNLOCK(&ip_conntrack_lock);
-
-	return 0;
-}
-
-static inline int unhelp(struct ip_conntrack_tuple_hash *i,
-			 const struct ip_conntrack_helper *me)
-{
-	if (tuplehash_to_ctrack(i)->helper == me)
-		tuplehash_to_ctrack(i)->helper = NULL;
-	return 0;
-}
-
-void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
-{
-	unsigned int i;
-	struct ip_conntrack_expect *exp, *tmp;
-
-	/* Need write lock here, to delete helper. */
-	WRITE_LOCK(&ip_conntrack_lock);
-	LIST_DELETE(&helpers, me);
-
-	/* Get rid of expectations */
-	list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) {
-		if (exp->master->helper == me && del_timer(&exp->timeout)) {
-			unlink_expect(exp);
-			destroy_expect(exp);
-		}
-	}
-	/* Get rid of expecteds, set helpers to NULL. */
-	LIST_FIND_W(&unconfirmed, unhelp, struct ip_conntrack_tuple_hash*, me);
-	for (i = 0; i < ip_conntrack_htable_size; i++)
-		LIST_FIND_W(&ip_conntrack_hash[i], unhelp,
-			    struct ip_conntrack_tuple_hash *, me);
-	WRITE_UNLOCK(&ip_conntrack_lock);
-
-	/* Someone could be still looking at the helper in a bh. */
-	synchronize_net();
-}
 
 static inline void ct_add_counters(struct ip_conntrack *ct,
 				   enum ip_conntrack_info ctinfo,
@@ -1017,7 +960,7 @@
 			break;
 	}
 	if (!h)
-		h = LIST_FIND_W(&unconfirmed, do_iter,
+		h = LIST_FIND_W(&ip_conntrack_unconfirmed, do_iter,
 				struct ip_conntrack_tuple_hash *, iter, data);
 	if (h)
 		atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use);
@@ -1141,6 +1084,7 @@
 	kmem_cache_destroy(ip_conntrack_expect_cachep);
 	free_conntrack_hash();
 	nf_unregister_sockopt(&so_getorigdst);
+	ip_conntrack_helper_fini();
 }
 
 static int hashsize;
@@ -1234,8 +1178,14 @@
 	/*  - and look it like as a confirmed connection */
 	set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
 
+	ret = ip_conntrack_helper_init();
+	if (ret != 0)
+		goto err_free_exp_slab;
+
 	return ret;
 
+err_free_exp_slab:
+	kmem_cache_destroy(ip_conntrack_expect_cachep);
 err_free_conntrack_slab:
 	kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_helper.c linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_helper.c
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_helper.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_helper.c	2005-02-13 17:46:42.000000000 +0100
@@ -0,0 +1,338 @@
+/* Dynamic conntrack helper to port binding
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * Portions (C) 1999-2001 Paul `Rusty' Russell  
+ * 	    (C) 2002-2005 Netfilter Core Team <coreteam@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.
+ *
+ * 13 Feb 2005: Harald Welte <laforge@netfilter.org>
+ * 	- seperate out helper support from ip_conntrack_core
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
+ 
+#include <linux/netfilter_ipv4/listhelp.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+static LIST_HEAD(helpers);
+static LIST_HEAD(helper_ports);
+
+struct helper_port {
+	struct list_head		list;
+	struct ip_conntrack_helper	*helper;
+	struct ip_conntrack_tuple	tuple;
+};
+
+static struct helper_port *_hp_find_byport(struct ip_conntrack_helper *h, 
+					   u_int16_t port)
+{
+	struct helper_port *hp;
+	
+	/* Must be locked under ip_conntrack_lock */
+	list_for_each_entry(hp, &helper_ports, list) {
+		if (hp->helper == h && 
+		    hp->tuple.src.u.tcp.port == htons(port))
+			return hp;
+	}
+	return NULL;
+}
+
+int ip_conntrack_helper_add_port(struct ip_conntrack_helper *h, u_int16_t port)
+{
+	struct helper_port *hp;
+
+	hp = kmalloc(sizeof(*hp), GFP_KERNEL);
+	if (!hp)
+		return -ENOMEM;
+
+	/* Fill in the data */
+	hp->helper = h;
+	memcpy(&hp->tuple, &h->tuple, sizeof(struct ip_conntrack_tuple));
+	/* FIXME: this is a bit of a hack */
+	hp->tuple.src.u.tcp.port = htons(port);
+
+	WRITE_LOCK(&ip_conntrack_lock);
+
+	if (_hp_find_byport(h, port)) {
+		WRITE_UNLOCK(&ip_conntrack_lock);
+		kfree(hp);
+		return -EEXIST;
+	}
+
+	list_add(&hp->list, &helper_ports);
+
+	WRITE_UNLOCK(&ip_conntrack_lock);
+
+	return 0;
+}
+
+int ip_conntrack_helper_del_port(struct ip_conntrack_helper *h, u_int16_t port)
+{
+	struct helper_port *hp;
+
+	WRITE_LOCK(&ip_conntrack_lock);
+
+	hp = _hp_find_byport(h, port);
+
+	if (!hp) {
+		WRITE_UNLOCK(&ip_conntrack_lock);
+		return -ENODEV;
+	}
+
+	list_del(&hp->list);
+
+	WRITE_UNLOCK(&ip_conntrack_lock);
+
+	kfree(hp);
+
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *helper_procdir;
+
+static void *helper_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct proc_dir_entry *pde = s->private;
+	struct ip_conntrack_helper *h = pde->data;
+	struct helper_port *hp;
+	int i = 0;
+
+	/* strange seq_file aop calls stop even if start fails,
+	 * thus we need to unconditionally grab the lock */
+	READ_LOCK(&ip_conntrack_lock);
+
+	if (list_empty(&helper_ports))
+		return NULL;
+
+	list_for_each_entry(hp, &helper_ports, list) {
+		if (hp->helper == h) {
+			if (i == *pos) 
+				return hp;
+			i++;
+		}
+	}
+
+	return NULL;
+}
+
+static void *helper_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct proc_dir_entry *pde = s->private;
+	struct ip_conntrack_helper *h = pde->data;
+	struct helper_port *hp = v;
+
+	(*pos)++;
+	list_for_each_entry(hp, &hp->list, list) {
+		/* end traversal at list head */
+		if ((struct list_head *) hp == &helper_ports)
+			return NULL;
+		if (hp->helper == h) {
+			return hp;
+		}
+	}
+
+	return NULL;
+}
+
+static void helper_seq_stop(struct seq_file *s, void *v)
+{
+	READ_UNLOCK(&ip_conntrack_lock);
+}
+
+static int helper_seq_show(struct seq_file *s, void *v)
+{
+	struct helper_port *hp = v;
+
+	return seq_printf(s, "%u\n", ntohs(hp->tuple.src.u.tcp.port));
+}
+
+static struct seq_operations helper_seq_ops = {
+	.start	= helper_seq_start,
+	.next	= helper_seq_next,
+	.stop	= helper_seq_stop,
+	.show	= helper_seq_show,
+};
+
+static int helper_proc_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &helper_seq_ops);
+
+	if (!ret) {
+		struct seq_file *sf = file->private_data;
+		struct proc_dir_entry *pde = PDE(inode);
+
+		sf->private = pde;
+		/* FIXME: do we have to increase usage count ?*/
+	}
+
+	return ret;
+}
+
+static int helper_proc_release(struct inode *inode, struct file *file)
+{
+	int ret;
+
+	ret = seq_release(inode, file);
+
+	return ret;
+}
+
+static ssize_t helper_proc_write(struct file *file, const char __user *input,
+				 size_t size, loff_t *ofs)
+{
+#define PROC_WRITELEN	10
+	char buffer[PROC_WRITELEN+1];
+	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+	struct ip_conntrack_helper *h = pde->data;
+	unsigned long port;
+
+	if (copy_from_user(buffer, input, PROC_WRITELEN))
+		return -EFAULT;
+
+	if (*buffer == '+') {
+		port = simple_strtoul(buffer+1, NULL, 10);
+		if (ip_conntrack_helper_add_port(h, port))
+			return -EINVAL;
+	} else if (*buffer == '-') {
+		port = simple_strtoul(buffer+1, NULL, 10);
+		if (ip_conntrack_helper_del_port(h, port))
+			return -EINVAL;
+	} else
+		return -EIO;
+
+	return size;
+}
+
+static struct file_operations helper_proc_fops = {
+	.owner	= THIS_MODULE,
+	.open	= helper_proc_open,
+	.read	= seq_read,
+	.write	= helper_proc_write,
+	.llseek	= seq_lseek,
+	.release = helper_proc_release,
+};
+
+#endif
+
+static inline int helper_cmp(const struct ip_conntrack_helper *i,
+			     const struct ip_conntrack_tuple *rtuple)
+{
+	return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
+}
+
+struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+	return LIST_FIND(&helpers, helper_cmp,
+			 struct ip_conntrack_helper *,
+			 tuple);
+}
+
+
+int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
+{
+	BUG_ON(me->timeout == 0);
+
+
+	WRITE_LOCK(&ip_conntrack_lock);
+	list_prepend(&helpers, me);
+	WRITE_UNLOCK(&ip_conntrack_lock);
+
+#ifdef CONFIG_PROC_FS
+	me->pde = create_proc_entry(me->name, S_IWUSR|S_IRUSR, helper_procdir);
+	if (!me->pde)
+		return 1;
+	me->pde->proc_fops = &helper_proc_fops;
+	me->pde->data = me;
+#endif
+
+	return 0;
+}
+
+static inline int unhelp(struct ip_conntrack_tuple_hash *i,
+			 const struct ip_conntrack_helper *me)
+{
+	if (tuplehash_to_ctrack(i)->helper == me)
+		tuplehash_to_ctrack(i)->helper = NULL;
+	return 0;
+}
+
+void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
+{
+	unsigned int i;
+	struct ip_conntrack_expect *exp, *tmp;
+	struct helper_port *hp, *hp2;
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry(me->pde->name, me->pde->parent);
+#endif
+
+	/* Need write lock here, to delete helper. */
+	WRITE_LOCK(&ip_conntrack_lock);
+
+	/* First delete us from global list of helpers */
+	LIST_DELETE(&helpers, me);
+
+	/* Then delete us from helper_ports */
+	list_for_each_entry_safe(hp, hp2, &helper_ports, list) {
+		if (hp->helper == me) {
+			list_del(&hp->list);
+			kfree(hp);
+		}
+	}
+
+	/* Get rid of expectations */
+	list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) {
+		if (exp->master->helper == me && del_timer(&exp->timeout)) {
+			__ip_ct_unlink_expect(exp);
+			__ip_ct_destroy_expect(exp);
+		}
+	}
+	/* Get rid of expecteds, set helpers to NULL. */
+	LIST_FIND_W(&ip_conntrack_unconfirmed, 
+		    unhelp, struct ip_conntrack_tuple_hash*, me);
+	for (i = 0; i < ip_conntrack_htable_size; i++)
+		LIST_FIND_W(&ip_conntrack_hash[i], unhelp,
+			    struct ip_conntrack_tuple_hash *, me);
+	WRITE_UNLOCK(&ip_conntrack_lock);
+
+	/* Someone could be still looking at the helper in a bh. */
+	synchronize_net();
+}
+
+int ip_conntrack_helper_init(void)
+{
+#ifdef CONFIG_PROC_FS
+	helper_procdir = proc_mkdir("ip_conntrack_helper", proc_net);
+	if (!helper_procdir) {
+		printk(KERN_ERR "ip_conntrack_helper: unable to create proc\n");
+		return -ENOMEM;
+	}
+#endif
+
+	return 0;
+}
+
+void ip_conntrack_helper_fini(void)
+{
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry(helper_procdir->name, helper_procdir->parent);
+#endif
+}
+
+EXPORT_SYMBOL(ip_conntrack_helper_add_port);
+EXPORT_SYMBOL(ip_conntrack_helper_del_port);
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-02-13 13:52:06.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-02-13 16:14:26.000000000 +0100
@@ -918,3 +918,6 @@
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 EXPORT_SYMBOL(ip_conntrack_tcp_update);
 #endif
+EXPORT_SYMBOL(__ip_ct_unlink_expect);
+EXPORT_SYMBOL(__ip_ct_destroy_expect);
+EXPORT_SYMBOL(ip_conntrack_unconfirmed);


[-- Attachment #1.3: 2.6.11-rc4-ip_conntrack_helper_proc-helpers.patch --]
[-- Type: text/plain, Size: 8025 bytes --]

diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_ftp.c
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_ftp.c	2005-02-13 13:52:06.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_ftp.c	2005-02-13 17:39:03.000000000 +0100
@@ -1,7 +1,7 @@
 /* FTP extension for IP connection tracking. */
 
 /* (C) 1999-2001 Paul `Rusty' Russell  
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2002-2005 Netfilter Core Team <coreteam@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
@@ -446,48 +446,43 @@
 	return ret;
 }
 
-static struct ip_conntrack_helper ftp[MAX_PORTS];
-static char ftp_names[MAX_PORTS][10];
+static struct ip_conntrack_helper ftp = {
+	.name 		= "ftp",
+	.help 		= &help,
+	.me 		= THIS_MODULE,
+	.timeout	= 5 * 60,	/* 5 minutes */
+	.max_expected	= 1,
+	.mask		= { 
+			.dst.protonum 	= 0xff, 
+			.src.u.tcp.port	= 0xffff,
+		},
+	.tuple		= { 
+			.dst.protonum 	= IPPROTO_TCP,
+			.src.u.tcp.port	= __constant_htons(21),
+		},
+};
 
 /* Not __exit: called from init() */
 static void fini(void)
 {
-	int i;
-	for (i = 0; i < ports_c; i++) {
-		DEBUGP("ip_ct_ftp: unregistering helper for port %d\n",
-				ports[i]);
-		ip_conntrack_helper_unregister(&ftp[i]);
-	}
+	ip_conntrack_helper_unregister(&ftp);
 }
 
 static int __init init(void)
 {
 	int i, ret;
-	char *tmpname;
 
-	if (ports_c == 0)
-		ports[ports_c++] = FTP_PORT;
+	if (ports_c == 0) {
+		ports[0] = 21;
+		ports_c = 1;
+	}
+	
+	ret = ip_conntrack_helper_register(&ftp);
 
 	for (i = 0; i < ports_c; i++) {
-		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
-		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
-		ftp[i].mask.src.u.tcp.port = 0xFFFF;
-		ftp[i].mask.dst.protonum = 0xFF;
-		ftp[i].max_expected = 1;
-		ftp[i].timeout = 5 * 60; /* 5 minutes */
-		ftp[i].me = THIS_MODULE;
-		ftp[i].help = help;
-
-		tmpname = &ftp_names[i][0];
-		if (ports[i] == FTP_PORT)
-			sprintf(tmpname, "ftp");
-		else
-			sprintf(tmpname, "ftp-%d", ports[i]);
-		ftp[i].name = tmpname;
-
 		DEBUGP("ip_ct_ftp: registering helper for port %d\n", 
 				ports[i]);
-		ret = ip_conntrack_helper_register(&ftp[i]);
+		ret = ip_conntrack_helper_add_port(&ftp, ports[i]);
 
 		if (ret) {
 			fini();
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_irc.c	2005-02-13 13:52:06.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_irc.c	2005-02-13 17:39:29.000000000 +0100
@@ -1,5 +1,5 @@
 /* IRC extension for IP connection tracking, Version 1.21
- * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
  * based on RR's ip_conntrack_ftp.c	
  *
  * ip_conntrack_irc.c,v 1.21 2002/02/05 14:49:26 laforge Exp
@@ -241,16 +241,25 @@
 	return ret;
 }
 
-static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
-static char irc_names[MAX_PORTS][10];
+static struct ip_conntrack_helper irc_helper = {
+	.name		= "irc",
+	.help		= &help,
+	.me		= THIS_MODULE,
+	.mask		= {
+			.dst.protonum	= 0xff,
+			.src.u.tcp.port	= 0xffff,
+		},
+	.tuple		= {
+			.dst.protonum	= IPPROTO_TCP,
+			.src.u.tcp.port	= __constant_htons(6667),
+		},
+};
 
 static void fini(void);
 
 static int __init init(void)
 {
 	int i, ret;
-	struct ip_conntrack_helper *hlpr;
-	char *tmpname;
 
 	if (max_dcc_channels < 1) {
 		printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n");
@@ -260,32 +269,19 @@
 		printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n");
 		return -EBUSY;
 	}
-	
-	/* If no port given, default to standard irc port */
-	if (ports_c == 0)
-		ports[ports_c++] = IRC_PORT;
 
-	for (i = 0; i < ports_c; i++) {
-		hlpr = &irc_helpers[i];
-		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
-		hlpr->tuple.dst.protonum = IPPROTO_TCP;
-		hlpr->mask.src.u.tcp.port = 0xFFFF;
-		hlpr->mask.dst.protonum = 0xFF;
-		hlpr->max_expected = max_dcc_channels;
-		hlpr->timeout = dcc_timeout;
-		hlpr->me = THIS_MODULE;
-		hlpr->help = help;
-
-		tmpname = &irc_names[i][0];
-		if (ports[i] == IRC_PORT)
-			sprintf(tmpname, "irc");
-		else
-			sprintf(tmpname, "irc-%d", i);
-		hlpr->name = tmpname;
+	irc_helper.timeout = dcc_timeout;
+	irc_helper.max_expected = max_dcc_channels;
+	
+	if (ports_c == 0) {
+		ports[0] = 6667;
+		ports_c = 1;
+	}
 
-		DEBUGP("port #%d: %d\n", i, ports[i]);
+	ret = ip_conntrack_helper_register(&irc_helper);
 
-		ret = ip_conntrack_helper_register(hlpr);
+	for (i = 0; i < ports_c; i++) {
+		ret = ip_conntrack_helper_add_port(&irc_helper, ports[i]);
 
 		if (ret) {
 			printk("ip_conntrack_irc: ERROR registering port %d\n",
@@ -301,12 +297,7 @@
  * it is needed by the init function */
 static void fini(void)
 {
-	int i;
-	for (i = 0; i < ports_c; i++) {
-		DEBUGP("unregistering port %d\n",
-		       ports[i]);
-		ip_conntrack_helper_unregister(&irc_helpers[i]);
-	}
+	ip_conntrack_helper_unregister(&irc_helper);
 }
 
 module_init(init);
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_tftp.c
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_tftp.c	2005-02-13 13:52:06.000000000 +0100
+++ linux-2.6.11-rc4-helper_sysctl/net/ipv4/netfilter/ip_conntrack_tftp.c	2005-02-13 17:44:55.000000000 +0100
@@ -100,51 +100,38 @@
 	return NF_ACCEPT;
 }
 
-static struct ip_conntrack_helper tftp[MAX_PORTS];
-static char tftp_names[MAX_PORTS][10];
+static struct ip_conntrack_helper tftp_helper = {
+	.name 		= "tftp",
+	.help		= &tftp_help,
+	.me		= THIS_MODULE,
+	.timeout	= 5 * 60,	/* 5 minutes */
+	.max_expected	= 1,
+	.mask		= {
+			.src.u.udp.port = 0xffff,
+			.dst.protonum	= 0xff,
+		},
+	.tuple		= {
+			.src.u.udp.port = TFTP_PORT,
+			.dst.protonum	= IPPROTO_UDP,
+		},
+};
 
 static void fini(void)
 {
-	int i;
-
-	for (i = 0 ; i < ports_c; i++) {
-		DEBUGP("unregistering helper for port %d\n",
-			ports[i]);
-		ip_conntrack_helper_unregister(&tftp[i]);
-	} 
+	ip_conntrack_helper_unregister(&tftp_helper);
 }
 
 static int __init init(void)
 {
 	int i, ret;
-	char *tmpname;
 
 	if (ports_c == 0)
 		ports[ports_c++] = TFTP_PORT;
 
 	for (i = 0; i < ports_c; i++) {
-		/* Create helper structure */
-		memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
-
-		tftp[i].tuple.dst.protonum = IPPROTO_UDP;
-		tftp[i].tuple.src.u.udp.port = htons(ports[i]);
-		tftp[i].mask.dst.protonum = 0xFF;
-		tftp[i].mask.src.u.udp.port = 0xFFFF;
-		tftp[i].max_expected = 1;
-		tftp[i].timeout = 5 * 60; /* 5 minutes */
-		tftp[i].me = THIS_MODULE;
-		tftp[i].help = tftp_help;
-
-		tmpname = &tftp_names[i][0];
-		if (ports[i] == TFTP_PORT)
-			sprintf(tmpname, "tftp");
-		else
-			sprintf(tmpname, "tftp-%d", i);
-		tftp[i].name = tmpname;
-
 		DEBUGP("port #%d: %d\n", i, ports[i]);
 
-		ret=ip_conntrack_helper_register(&tftp[i]);
+		ret = ip_conntrack_helper_add_port(&tftp_helper, ports[i]);
 		if (ret) {
 			printk("ERROR registering helper for port %d\n",
 				ports[i]);

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-02-14 12:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-13 16:56 [PATCH 2.6] Allow dynamic helper-port assignment Harald Welte
2005-02-13 17:34 ` Max Kellermann
2005-02-13 22:38 ` Jozsef Kadlecsik
2005-02-14 11:21   ` Harald Welte
2005-02-14 11:59 ` Martijn Lievaart
2005-02-14 12:20   ` Martijn Lievaart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.