[netfilter-cvslog] r3773 - branches/netfilter-ha/linux-2.6-actact/ct_sync

laforge at netfilter.org laforge at netfilter.org
Wed Mar 9 17:15:50 CET 2005


Author: laforge at netfilter.org
Date: 2005-03-09 17:15:49 +0100 (Wed, 09 Mar 2005)
New Revision: 3773

Modified:
   branches/netfilter-ha/linux-2.6-actact/ct_sync/ct_sync_main.c
Log:
- move remaining parameters to sysfs interface
- fix lots of cleanup/error handling code
- module can now be unloaded again


Modified: branches/netfilter-ha/linux-2.6-actact/ct_sync/ct_sync_main.c
===================================================================
--- branches/netfilter-ha/linux-2.6-actact/ct_sync/ct_sync_main.c	2005-03-09 12:19:57 UTC (rev 3772)
+++ branches/netfilter-ha/linux-2.6-actact/ct_sync/ct_sync_main.c	2005-03-09 16:15:49 UTC (rev 3773)
@@ -66,7 +66,7 @@
 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
 #include <linux/netfilter_ipv4/listhelp.h>
 
-#define CT_SYNC_VERSION	"0.19"
+#define CT_SYNC_VERSION	"0.6.51"
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("KOVACS Krisztian <hidden at sch.bme.hu>, Harald Welte <laforge at netfilter.org>");
@@ -96,17 +96,13 @@
 
 static int syncdev_ifindex;	/* ifindex of the network device */
 
-#ifdef CONFIG_PROG_FS
-static struct file_operations ctsync_proc_fops;
-static struct proc_dir_entry *ctsync_procdir;
-#endif
-
 struct ct_sync_instance;
 
 struct cts_inst_attribute {
 	struct attribute	attr;
 	ssize_t (*show)(struct ct_sync_instance *ctsi, char *buf);
-	ssize_t (*store)(struct ct_sync_instance *ctsi, const char *buf);
+	ssize_t (*store)(struct ct_sync_instance *ctsi, const char *buf,
+			 size_t len);
 };
 
 static struct cts_inst_attribute create_attr;
@@ -117,21 +113,31 @@
 	struct list_head list;
 	struct {
 		struct sockaddr_storage addr;	/* multicast address */
-		char name[32];			/* name */
+#define MAXNAMELEN	32
+		char name[MAXNAMELEN+1];	/* name */
+		char syncdev[IFNAMSIZ];		/* sync device */
+		unsigned long send_burst;
+		unsigned long recv_burst;
 	} config;
+	
+	unsigned int syncdev_ifindex;		/* ifindex for fast lookup */
 	unsigned int active;			/* already activated ? */
 	atomic_t initsync_active;
 
+	/* sysfs stuff */
 	struct kobject kobj;
 	struct cts_inst_attribute state_attr;
 	struct cts_inst_attribute addr_attr;
 	struct cts_inst_attribute active_attr;
+	struct cts_inst_attribute syncdev_attr;
+	struct cts_inst_attribute sendburst_attr;
+	struct cts_inst_attribute recvburst_attr;
 
 	struct proc_dir_entry *pdr_state;	/* state file */
 	struct cts_protoh *protoh;		/* protocol handle */
 };
 
-static struct list_head ct_sync_instances;
+static LIST_HEAD(ct_sync_instances);
 static spinlock_t ctsync_lock = SPIN_LOCK_UNLOCKED;
 
 /***********************************************************************
@@ -800,10 +806,7 @@
  ***********************************************************************/
 
 /* sysctl variables */
-static int cts_sysctl_state;
 static int cts_sysctl_maxage;
-static int cts_sysctl_send_burst = 100;
-static int cts_sysctl_recv_burst = 20;
 
 static int recovery_threshold_min = 1;
 static int recovery_threshold_max = 32000;
@@ -812,221 +815,6 @@
 #define CTS_SYSCTL_STATE_SLAVE	1
 #define CTS_SYSCTL_STATE_MASTER	2
 
-#if 0
-static int
-cts_sysctl_change_state(int state)
-{
-	CT_SYNC_ENTER();
-
-	switch (state) {
-	case CTS_SYSCTL_STATE_NONE:
-		/* cannot set state to NONE */
-		CT_SYNC_ERR("cannot switch to state none!\n");
-		CT_SYNC_LEAVE();
-		return -EINVAL;
-		break;
-
-	case CTS_SYSCTL_STATE_SLAVE:
-		if (cts_proto_is_master(cts_cfg.protoh)) {
-			CTS_STAT_INC(master2slave);
-			CT_SYNC_ERR("cannot switch active master to client!\n");
-			CT_SYNC_LEAVE();
-			return -EINVAL;
-		} else if (cts_proto_get_state(cts_cfg.protoh) == CT_SYNC_PSTATE_NONE) {
-			cts_proto_become_slave(cts_cfg.protoh);
-		}
-		break;
-
-	case CTS_SYSCTL_STATE_MASTER:
-		if (!cts_proto_is_master(cts_cfg.protoh)) {
-			if (cts_proto_become_master(cts_cfg.protoh) < 0) {
-				CT_SYNC_ERR("proto said we cannot become master\n");
-				CT_SYNC_LEAVE();
-				return -EINVAL;
-			}
-		} else {
-			CT_SYNC_INFO("we already are master; staying cool\n");
-		}
-		break;
-
-	default:
-		/* unknown state */
-		CT_SYNC_ERR("cannot switch to unknown state!\n");
-		CT_SYNC_LEAVE();
-		return -EINVAL;
-		break;
-		break;
-	}
-
-	CT_SYNC_LEAVE();
-
-	return 0;
-}
-
-static void
-cts_sysctl_update_state(void)
-{
-	CT_SYNC_ENTER();
-
-	switch (cts_proto_get_state(cts_cfg.protoh)) {
-	case CT_SYNC_PSTATE_NONE:
-		cts_sysctl_state = CTS_SYSCTL_STATE_NONE;
-		break;
-	case CT_SYNC_PSTATE_SLAVE_INIT:
-	case CT_SYNC_PSTATE_SLAVE_SYNSENT:
-	case CT_SYNC_PSTATE_SLAVE_SYNRECV:
-	case CT_SYNC_PSTATE_SLAVE_RUNNING:
-		cts_sysctl_state = CTS_SYSCTL_STATE_SLAVE;
-		break;
-	case CT_SYNC_PSTATE_MASTER_INIT:
-	case CT_SYNC_PSTATE_MASTER_ADVSENT:
-	case CT_SYNC_PSTATE_MASTER_RUNNING:
-		cts_sysctl_state = CTS_SYSCTL_STATE_MASTER;
-		break;
-	default:
-		CT_SYNC_ERR("invalid state\n");
-		break;
-	}
-
-	CT_SYNC_LEAVE();
-}
-
-static int
-cts_sysctl_state_handler(ctl_table *table, int write,
-			 struct file *filp, void *buffer,
-			 size_t *lenp, loff_t *ppos)
-{
-	int res;
-	
-	if (write) {
-		res = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-		if (res < 0)
-			return res;
-		return cts_sysctl_change_state(cts_sysctl_state);
-	} else {
-		cts_sysctl_update_state();
-		return proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	}
-}
-
-static int
-cts_sysctl_maxage_handler(ctl_table *table, int write,
-			  struct file *filp, void *buffer,
-			  size_t *lenp, loff_t *ppos)
-{
-	int res;
-
-	if (write) {
-		res = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-		if (res < 0)
-			return res;
-		return cts_proto_set_max_age(cts_sysctl_maxage);
-	} else {
-		cts_sysctl_maxage = cts_proto_get_max_age();
-		return proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	}
-}
-
-/* FIXME: define this in sysctl.h */
-#define NET_IPV4_NF_CONNTRACK_SYNC 20
-
-enum {
-	CTS_SYSCTL_STATE = 1,
-	CTS_SYSCTL_MAXAGE = 2,
-	CTS_SYSCTL_SEND_BURST = 3,
-	CTS_SYSCTL_RECV_BURST = 4,
-	CTS_SYSCTL_RECOVERY_THRESHOLD = 5,
-};
-
-static ctl_table ct_sync_sysctl_table[] = {
-	{
-		.ctl_name	= CTS_SYSCTL_STATE,
-		.procname	= "state",
-		.mode		= 0644,
-		.data		= &cts_sysctl_state,
-		.maxlen		= sizeof(int),
-		.proc_handler	= &cts_sysctl_state_handler,
-	},
-	{
-		.ctl_name	= CTS_SYSCTL_MAXAGE,
-		.procname	= "maxage",
-		.mode		= 0644,
-		.data		= &cts_sysctl_maxage,
-		.maxlen		= sizeof(int),
-		.proc_handler	= &cts_sysctl_maxage_handler,
-	},
-	{
-		.ctl_name	= CTS_SYSCTL_SEND_BURST,
-		.procname	= "send_burst",
-		.mode		= 0644,
-		.data		= &cts_sysctl_send_burst,
-		.maxlen		= sizeof(int),
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= CTS_SYSCTL_RECV_BURST,
-		.procname	= "recv_burst",
-		.mode		= 0644,
-		.data		= &cts_sysctl_recv_burst,
-		.maxlen		= sizeof(int),
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= CTS_SYSCTL_RECOVERY_THRESHOLD,
-		.procname	= "recovery_threshold",
-		.mode		= 0644,
-		.data		= &cts_proto_recovery_threshold,
-		.maxlen		= sizeof(int),
-		.proc_handler	= &proc_dointvec_minmax,
-		.extra1		= &recovery_threshold_min,
-		.extra2		= &recovery_threshold_max,
-	},
-	{ .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_cts_table[] = {
-	{
-		.ctl_name	= NET_IPV4_NF_CONNTRACK_SYNC,
-		.procname	= "ct_sync",
-		.mode		= 0555,
-		.child		= ct_sync_sysctl_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_netfilter_table[] = {
-	{
-		.ctl_name	= NET_IPV4_NETFILTER,
-		.procname	= "netfilter",
-		.mode		= 0555,
-		.child		= ct_sync_cts_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_net_table[] = {
-	{
-		.ctl_name	= NET_IPV4,
-		.procname	= "ipv4",
-		.mode		= 0555,
-		.child		= ct_sync_netfilter_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_root_table[] = {
-	{
-		.ctl_name	= CTL_NET,
-		.procname	= "net",
-		.mode		= 0555,
-		.child		= ct_sync_net_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static struct ctl_table_header *ct_sync_sysctl_header;
-#endif
-
 /***********************************************************************
  * KERNEL THREADS
  ***********************************************************************/
@@ -1056,7 +844,7 @@
 			while (cts_proto_send_pending(ctsi->protoh)) {
 				cts_proto_send_dequeue(ctsi->protoh);
 	
-				if (++i >= cts_sysctl_send_burst)
+				if (++i >= ctsi->config.send_burst)
 					break;
 			}
 
@@ -1087,6 +875,87 @@
 	return 0;
 }
 
+static inline int
+_cts_rcv_thread_perinstance(struct ct_sync_instance *ctsi, wait_queue_t *wait)
+{
+	int pkts_enqueued = 0;
+	int pkts_received = 0;
+	int msgs_received = 0;
+	struct ct_sync_msghdr *msghdr;
+	struct ct_sync_pkthdr *pkthdr;
+
+	/* wait for a new packet to arrive */
+	if (!cts_proto_recv_pending(ctsi->protoh)) {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		add_wait_queue(&ct_sync_rcv_wait, wait);
+
+		for (;;) {
+			__set_current_state(TASK_INTERRUPTIBLE);
+			if (cts_proto_recv_pending(ctsi->protoh) ||
+			    kthread_should_stop())
+				break;
+
+			CT_SYNC_DEBUG2("falling asleep\n");
+			schedule();
+		}
+
+		remove_wait_queue(&ct_sync_rcv_wait, wait);
+		__set_current_state(TASK_RUNNING);
+	}
+
+	/* first process packets from the socket buffer into
+	 * our protocol layer */
+	while (cts_proto_recv_pending(ctsi->protoh)) {
+		switch (cts_proto_recv_pkt(ctsi->protoh)) {
+		case CTS_PROTO_RCV_ERROR:
+			/* FIXME: unrecoverable error, should complain,
+ 			 * but should not exit! */
+			return -1;
+			break;
+		case CTS_PROTO_RCV_SYNC:
+			/* we'll handle this later when 
+			 * dequeuing messages */
+			pkts_enqueued++;
+			break;
+		case CTS_PROTO_RCV_INITSYNC:
+			/* initiate initial synchronization */
+			ct_sync_start_initsync(ctsi);
+			break;
+		default:
+			/* the protocol layer handled other cases,
+			   and dropped the packet */
+			break;
+		}
+
+		pkts_received++;
+		CTS_STAT_INC(rx.pkts_tot);
+		if (pkts_received >= ctsi->config.recv_burst)
+			break;
+	}
+
+	if (pkts_enqueued > 0) {
+		/* process messages */
+		while ((msghdr = cts_proto_recvmsg(ctsi->protoh, 
+							&pkthdr))) {
+			msgs_received++;
+			CTS_STAT_INC(rx.msgs);
+
+			if (cts_proto_is_master(ctsi->protoh))
+				ct_sync_msg_process_master(msghdr, 
+							pkthdr);
+			else
+				ct_sync_msg_process_slave(msghdr, 
+							pkthdr);
+		}
+	}
+
+	/* give chance for other processes to run */
+	if (pkts_received >= ctsi->config.recv_burst)
+		cond_resched();
+
+	return 0;
+}
+
 /* sync kernel thread: receiver */
 static int
 ct_sync_rcv_thread_main(void *data)
@@ -1097,85 +966,13 @@
 	
 	for (;;) {
 		struct ct_sync_instance *ctsi;
-		int pkts_enqueued = 0;
-		int pkts_received = 0;
-		int msgs_received = 0;
-		struct ct_sync_msghdr *msghdr;
-		struct ct_sync_pkthdr *pkthdr;
 
 	  	if (kthread_should_stop())
 			break;
 
 		list_for_each_entry(ctsi, &ct_sync_instances, list) {
-
-			/* wait for a new packet to arrive */
-			if (!cts_proto_recv_pending(ctsi->protoh)) {
-				__set_current_state(TASK_INTERRUPTIBLE);
-				add_wait_queue(&ct_sync_rcv_wait, &wait);
-
-				for (;;) {
-					__set_current_state(TASK_INTERRUPTIBLE);
-					if (cts_proto_recv_pending(ctsi->protoh) ||
-					    kthread_should_stop())
-						break;
-	
-					CT_SYNC_DEBUG2("falling asleep\n");
-					schedule();
-				}
-
-				remove_wait_queue(&ct_sync_rcv_wait, &wait);
-				__set_current_state(TASK_RUNNING);
-			}
-
-			/* first process packets from the socket buffer into
-			 * our protocol layer */
-			while (cts_proto_recv_pending(ctsi->protoh)) {
-				switch (cts_proto_recv_pkt(ctsi->protoh)) {
-				case CTS_PROTO_RCV_ERROR:
-					/* FIXME: unrecoverable error, should complain,
- 					 * but should not exit! */
-					goto error;
-					break;
-				case CTS_PROTO_RCV_SYNC:
-					/* we'll handle this later when 
-					 * dequeuing messages */
-					pkts_enqueued++;
-					break;
-				case CTS_PROTO_RCV_INITSYNC:
-					/* initiate initial synchronization */
-					ct_sync_start_initsync(ctsi);
-					break;
-				default:
-					/* the protocol layer handled other cases,
-					   and dropped the packet */
-					break;
-				}
-	
-				pkts_received++;
-				CTS_STAT_INC(rx.pkts_tot);
-				if (pkts_received >= cts_sysctl_recv_burst)
-					break;
-			}
-
-			if (pkts_enqueued > 0) {
-				/* process messages */
-				while ((msghdr = cts_proto_recvmsg(ctsi->protoh, 
-									&pkthdr))) {
-					msgs_received++;
-					CTS_STAT_INC(rx.msgs);
-	
-					if (cts_proto_is_master(ctsi->protoh))
-						ct_sync_msg_process_master(msghdr, 
-									pkthdr);
-					else
-						ct_sync_msg_process_slave(msghdr, 
-									pkthdr);
-				}
-			}
-
-			/* give chance for other processes to run */
-			if (pkts_received >= cts_sysctl_recv_burst)
-				cond_resched();
+			if (_cts_rcv_thread_perinstance(ctsi, &wait) < 0)
+				goto error;
 		}
 	}
 
@@ -1243,7 +1040,7 @@
 	return 0;
 }
 
-static int 
+static inline int 
 _cts_initsync_thread_perinstance(struct ct_sync_instance *ctsi)
 {
 	int i; 
@@ -1310,6 +1107,8 @@
 	atomic_set(&ctsi->initsync_active, 0);
 
 	CT_SYNC_INFO("finished initsync dump\n");
+
+	return 0;
 }
 
 /* sync kernel thread: recover */
@@ -1787,6 +1586,7 @@
 static int cts_instance_create(const char *name);
 static int cts_instance_activate(struct ct_sync_instance *ctsi);
 static void cts_instance_deactivate(struct ct_sync_instance *ctsi);
+static int cts_instance_destroy(const char *name);
 
 static ssize_t sysfs_state_show(struct ct_sync_instance *ctsi, char *buf)
 {
@@ -1794,7 +1594,7 @@
 }
 
 static ssize_t sysfs_state_store(struct ct_sync_instance *ctsi,
-				 const char *buf)
+				 const char *buf, size_t len)
 {
 	unsigned long state;
 
@@ -1844,7 +1644,7 @@
 
 	CT_SYNC_LEAVE();
 
-	return 0;
+	return len;
 }
 
 /* show whether this instance is active or not */
@@ -1854,7 +1654,7 @@
 }
 
 static ssize_t sysfs_active_store(struct ct_sync_instance *ctsi,
-				  const char *buf)
+				  const char *buf, size_t len)
 {
 	unsigned long state = simple_strtoul(buf, NULL, 10);
 
@@ -1867,7 +1667,7 @@
 			return 0;
 		cts_instance_deactivate(ctsi);
 	}
-	return 0;
+	return len;
 }
 
 static ssize_t sysfs_addr_show(struct ct_sync_instance *ctsi, char *buf)
@@ -1886,7 +1686,7 @@
 }
 
 static ssize_t sysfs_addr_store(struct ct_sync_instance *ctsi,
-				const char *buf)
+				const char *buf, size_t len)
 {
 	if (ctsi->active != 0)
 		return -EBUSY;
@@ -1903,16 +1703,84 @@
 		si->sin_addr.s_addr = in_aton(buf);
 		si->sin_port = __constant_htons(1999);
 	}
-	return 0;
+	return len;
 }
 
+static ssize_t sysfs_syncdev_show(struct ct_sync_instance *ctsi,
+				  char *buf)
+{
+	sprintf(buf, "%s\n", ctsi->config.syncdev);
+	return strlen(buf);
+}
+
+static ssize_t sysfs_syncdev_store(struct ct_sync_instance *ctsi,
+				   const char *buf, size_t len)
+{
+	if (len >= IFNAMSIZ)
+		return -E2BIG;
+
+	strlcpy((char *)&ctsi->config.syncdev, buf, IFNAMSIZ-1);
+
+	return strlen((char *)&ctsi->config.syncdev);
+}
+
+static ssize_t sysfs_sendburst_show(struct ct_sync_instance *ctsi,
+				    char *buf)
+{
+	sprintf(buf, "%u\n", ctsi->config.send_burst);
+	return strlen(buf);
+}
+
+static ssize_t sysfs_sendburst_store(struct ct_sync_instance *ctsi,
+				     const char *buf, size_t len)
+{
+	ctsi->config.send_burst = simple_strtoul(buf, NULL, 10);
+	return len;
+}
+
+static ssize_t sysfs_recvburst_show(struct ct_sync_instance *ctsi,
+				  char *buf)
+{
+	sprintf(buf, "%u\n", ctsi->config.recv_burst);
+	return strlen(buf);
+}
+
+static ssize_t sysfs_recvburst_store(struct ct_sync_instance *ctsi,
+				   const char *buf, size_t len)
+{
+	ctsi->config.recv_burst = simple_strtoul(buf, NULL, 10);
+	return len;
+}
+
 /* create a new instance by writing it's name to this file */
-static ssize_t sysfs_create_store(struct ct_sync_instance *ctsi,
-				  const char *buf)
+static ssize_t sysfs_control_store(struct ct_sync_instance *ctsi,
+				  const char *buf, size_t len)
 {
-	if (cts_instance_create(buf))
-		return -EINVAL;
-	return 0;
+	int ret;
+	char opcode;
+	char *tmpname;
+	
+	/* DON'T USE ctsi, IT IS NOT VALID HERE !!! */
+	
+	tmpname = kmalloc(len+1, GFP_KERNEL);
+	if (!tmpname)
+		return -ENOMEM;
+
+	sscanf(buf, "%c%s", &opcode, tmpname);
+
+	switch (opcode) {
+		case '+':
+			ret = cts_instance_create(tmpname);
+			break;
+		case '-':
+			ret = cts_instance_destroy(tmpname);
+			break;
+		default:
+			ret = -EINVAL;
+	}
+
+	kfree(tmpname);
+	return len;
 }
 
 #define to_ctsi(d) container_of(d, struct ct_sync_instance, kobj)
@@ -1940,7 +1808,7 @@
 	ssize_t ret = 0;
 
 	if (ctsi_attr->store)
-		ret = ctsi_attr->store(ctsi, buf);
+		ret = ctsi_attr->store(ctsi, buf, len);
 
 	return ret;
 }
@@ -1980,10 +1848,18 @@
 __cts_instance_find(const char *name)
 {
 	struct ct_sync_instance *ctsi;
+
+	CT_SYNC_ENTER();
 	list_for_each_entry(ctsi, &ct_sync_instances, list) {
-		if (!strcmp(ctsi->config.name, name))
+		if (!strcmp(&ctsi->config.name, name)) {
+			CT_SYNC_DEBUG("found instance %p for '%s'\n",
+					ctsi, name);
+			CT_SYNC_LEAVE();
 			return ctsi;
+		}
 	}
+	CT_SYNC_DEBUG("unable to find instance for '%s'\n", name);
+	CT_SYNC_LEAVE();
 	return NULL;
 }
 
@@ -1993,6 +1869,8 @@
 	int ret = 0;
 	struct ct_sync_instance *ctsi;
 
+	CT_SYNC_ENTER();
+
 	ctsi = kmalloc(sizeof(*ctsi), GFP_KERNEL);
 	if (!ctsi) {
 		CT_SYNC_ERR("ENOMEM while allocating new instance\n");
@@ -2001,7 +1879,18 @@
 	memset(ctsi, 0, sizeof(*ctsi));
 
 	atomic_set(&ctsi->initsync_active, 0);
+	ctsi->config.send_burst = 100;
+	ctsi->config.recv_burst = 20;
+	ctsi->config.addr.ss_family = AF_INET;
+	strlcpy(&ctsi->config.name, name, MAXNAMELEN);
 
+	spin_lock(&ctsync_lock);
+	if (__cts_instance_find(name)) {
+		ret = -EEXIST;
+		spin_unlock(&ctsync_lock);
+		goto out_unlock;
+	}
+
 	/* init protocol layer */
 	ctsi->protoh = cts_proto_init(&ct_sync_state_transition, NULL,
 					&ct_sync_send_wait, &ct_sync_rcv_wait);
@@ -2011,58 +1900,69 @@
 		goto out_free;
 	}
 
-#if 0
-	/* register sysctl entries */
-	ct_sync_sysctl_header = register_sysctl_table(ct_sync_root_table, 0);
-	if (ct_sync_sysctl_header == NULL)
-		goto error_proto;
-#endif
-
-	spin_lock(&ctsync_lock);
-	if (__cts_instance_find(name)) {
-		spin_unlock(&ctsync_lock);
-		goto out_unlock;
-	}
-#if 0
-#ifdef CONFIG_PROC_FS
-	/* create proc dir entry */
-	ctsi->pde = create_proc_entry(name, S_IWUSR|S_IRUSR, ctsync_procdir);
-	if (!ctsi->pde) {
-		/* FIXME */
-		return 1;
-	}
-	ctsi->pde->proc_fops = ctsync_proc_fops;
-	ctsi->pde->data = ctsi;
-#endif
-#endif
 	ret = kobject_set_name(&ctsi->kobj, "%s", name);
 	/* FIXME */
 	ctsi->kobj.parent = &cts_instance_kset.kobj;
 	ctsi->kobj.kset = &cts_instance_kset;
 	ctsi->kobj.ktype = &cts_instance_ktype;
 	ret = kobject_register(&ctsi->kobj);
-	/* FIXME */
+	if (ret < 0)
+		goto out_unlock;
 	CTSI_ATTR_INIT(ctsi->state_attr, "state", 0640, 
 			sysfs_state_show, sysfs_state_store);
 	ret = sysfs_create_file(&ctsi->kobj, &ctsi->state_attr.attr);
-	/* FIXME */
+	if (ret < 0)
+		goto out_kobj;
 
 	CTSI_ATTR_INIT(ctsi->addr_attr, "address", 0640, 
 			sysfs_addr_show, sysfs_addr_store);
 	ret = sysfs_create_file(&ctsi->kobj, &ctsi->addr_attr.attr);
-	/* FIXME */
+	if (ret < 0)
+		goto out_sysfs_state;
 
 	CTSI_ATTR_INIT(ctsi->active_attr, "active", 0640,
 			sysfs_active_show, sysfs_active_store);
 	ret = sysfs_create_file(&ctsi->kobj, &ctsi->active_attr.attr);
-	/* FIXME */
+	if (ret < 0)
+		goto out_sysfs_addr;
 
+	CTSI_ATTR_INIT(ctsi->syncdev_attr, "syncdev", 0640,
+			sysfs_syncdev_show, sysfs_syncdev_store);
+	ret = sysfs_create_file(&ctsi->kobj, &ctsi->syncdev_attr.attr);
+	if (ret < 0)
+		goto out_sysfs_active;
+
+	CTSI_ATTR_INIT(ctsi->sendburst_attr, "send_burst", 0640,
+			sysfs_sendburst_show, sysfs_sendburst_store);
+	ret = sysfs_create_file(&ctsi->kobj, &ctsi->sendburst_attr.attr);
+	if (ret < 0)
+		goto out_sysfs_syncdev;
+
+	CTSI_ATTR_INIT(ctsi->recvburst_attr, "recv_burst", 0640,
+			sysfs_recvburst_show, sysfs_recvburst_store);
+	ret = sysfs_create_file(&ctsi->kobj, &ctsi->recvburst_attr.attr);
+	if (ret < 0)
+		goto out_sysfs_sendburst;
+
 	list_add(&ctsi->list, &ct_sync_instances);
 	spin_unlock(&ctsync_lock);
 
 out:
+	CT_SYNC_LEAVE();
 	return ret;
 
+out_sysfs_sendburst:
+	sysfs_remove_file(&ctsi->kobj, &ctsi->sendburst_attr.attr);
+out_sysfs_syncdev:
+	sysfs_remove_file(&ctsi->kobj, &ctsi->syncdev_attr.attr);
+out_sysfs_active:
+	sysfs_remove_file(&ctsi->kobj, &ctsi->active_attr.attr);
+out_sysfs_addr:
+	sysfs_remove_file(&ctsi->kobj, &ctsi->addr_attr.attr);
+out_sysfs_state:
+	sysfs_remove_file(&ctsi->kobj, &ctsi->state_attr.attr);
+out_kobj:
+	kobject_unregister(&ctsi->kobj);
 out_unlock:
 	spin_unlock(&ctsync_lock);
 out_free:
@@ -2073,42 +1973,70 @@
 static int
 cts_instance_activate(struct ct_sync_instance *ctsi)
 {
-	if (cts_proto_start(ctsi->protoh, &ctsi->config.addr, syncdev))
-		return -1;
+	int ret = 0;
+	CT_SYNC_ENTER();
 
+	ret = cts_proto_start(ctsi->protoh, &ctsi->config.addr, 
+			    &ctsi->config.syncdev);
+	if (ret)
+		goto out;
+
 	ctsi->active = 1;
 
-	return 0;
+out:
+	CT_SYNC_LEAVE();
+	return ret;
 }
 
 static void
 cts_instance_deactivate(struct ct_sync_instance *ctsi)
 {
+	CT_SYNC_ENTER();
+
 	ctsi->active = 0;
 	cts_proto_stop(ctsi->protoh);
+
+	CT_SYNC_LEAVE();
 }
 
 static int
-cts_instance_destroy(char *name)
+cts_instance_destroy(const char *name)
 {
 	struct ct_sync_instance *ctsi;
+	int ret = 0;
 
+	CT_SYNC_ENTER();
+
 	spin_lock(&ctsync_lock);
 	ctsi = __cts_instance_find(name);
 	if (!ctsi) {
-		spin_unlock(&ctsync_lock);
-		return -1;
+		ret = -EINVAL;
+		goto out_unlock;
 	}
 
+	if (ctsi->active) {
+		ret = -EBUSY;
+		goto out_unlock;
+	}
+
 	list_del(&ctsi->list);
 
-	//remove_proc_entry(ctsi->pde->name, ctsi->pde->parent);
-
 	cts_proto_cleanup(ctsi->protoh);
+	sysfs_remove_file(&ctsi->kobj, &ctsi->recvburst_attr.attr);
+	sysfs_remove_file(&ctsi->kobj, &ctsi->sendburst_attr.attr);
+	sysfs_remove_file(&ctsi->kobj, &ctsi->syncdev_attr.attr);
+	sysfs_remove_file(&ctsi->kobj, &ctsi->active_attr.attr);
+	sysfs_remove_file(&ctsi->kobj, &ctsi->addr_attr.attr);
+	sysfs_remove_file(&ctsi->kobj, &ctsi->state_attr.attr);
+	kobject_unregister(&ctsi->kobj);
 
 	kfree(ctsi);
 
+out_unlock:
 	spin_unlock(&ctsync_lock);
+
+	CT_SYNC_LEAVE();
+	return ret;
 }
 
 
@@ -2183,20 +2111,12 @@
 		ip_ct_selective_cleanup(kill_all, NULL);
 	}
 
-#if 0
-	ctsync_procdir = proc_mkdir("ct_sync", proc_net);
-	if (!ctsync_procdir)
-		CT_SYNC_ERR("Can't create proc directory\n");
-		goto error_hook3;
-	}
-#endif
-
 	/* sysfs interface */
 	nf_subsys_register(&nfss_ctsync);
 	nf_kset_register(&nfss_ctsync, &cts_instance_kset);
 
-	CTSI_ATTR_INIT(create_attr, "create", 0640, 
-			NULL, sysfs_create_store);
+	CTSI_ATTR_INIT(create_attr, "control", 0640, 
+			NULL, sysfs_control_store);
 	ret = sysfs_create_file(&cts_instance_kset.kobj, &create_attr.attr);
 	/* FIXME */
 
@@ -2205,10 +2125,11 @@
 	CT_SYNC_DEBUG("proc_net_stat=%p, ct_sync_stat=%p\n", 
 		      proc_net_stat, ct_sync_stat);
 	if (!ct_sync_stat)
-		goto error_procdir;
+		goto error_hook3;
 	ct_sync_stat->proc_fops = &cts_stat_seq_fops;
 
 	/* start threads */
+#if 0
 	rcv_thread = kthread_run(ct_sync_rcv_thread_main, NULL,
 				 "ct_sync_rcv");
 	if (IS_ERR(rcv_thread)) {
@@ -2229,6 +2150,7 @@
 		ret = PTR_ERR(initsync_thread);
 		goto error_sthread;
 	}
+#endif
 
 	/* Now we have all of our infrastructure up and running */
 	printk(KERN_NOTICE "netfilter conntrack_sync version %s loaded\n",
@@ -2246,20 +2168,37 @@
         return 0;
 
 cleanup:
+	/* first remove control file to prevent further commands coming in */
+	sysfs_remove_file(&cts_instance_kset.kobj, &create_attr.attr);
+
+
+	{
+	struct ct_sync_instance *ctsi, *tmp;
+	CT_SYNC_DEBUG("deactivating/destroying all instances\n");
+	list_for_each_entry_safe(ctsi, tmp, &ct_sync_instances, list) {
+		cts_instance_deactivate(ctsi->config.name);
+		cts_instance_destroy(ctsi->config.name);
+	}
+	}
+
+	nf_kset_unregister(&cts_instance_kset);
+	nf_subsys_unregister(&nfss_ctsync);
+
+
 	CT_SYNC_DEBUG("stopping initsync thread\n");
-	err = kthread_stop(initsync_thread);
+	//err = kthread_stop(initsync_thread);
 	if (err < 0) {
 		CT_SYNC_INFO("unable to stop initsync thread\n");
 	}
 error_sthread:
 	CT_SYNC_DEBUG("stopping send thread\n");
-	err = kthread_stop(send_thread);
+	//err = kthread_stop(send_thread);
 	if (err < 0) {
 		CT_SYNC_INFO("unable to stop send thread\n");
 	}
 error_rthread:
 	CT_SYNC_DEBUG("stopping receive thread\n");
-	err = kthread_stop(rcv_thread);
+	//err = kthread_stop(rcv_thread);
 	if (err < 0) {
 		CT_SYNC_INFO("unable to stop receive thread\n");
 	}
@@ -2268,10 +2207,6 @@
 	ip_conntrack_unregister_notifier(&ct_sync_notifier);
 error_stat:
 	remove_proc_entry("ct_sync_stat", proc_net_stat);
-error_procdir:
-#ifdef PROC_FS
-	remove_proc_entry(ctsync_procdir->name, ctsync_procdir->parent);
-#endif
 error_hook3:
 	if (l2drop)
 		nf_unregister_hook(&cts_hook_ops[3]);




More information about the netfilter-cvslog mailing list