[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