[conntrack-tools] sync-mode: add abstract layer to make daemon independent of multicast

Pablo Neira netfilter-cvslog-bounces at lists.netfilter.org
Thu Mar 12 21:11:56 CET 2009


Gitweb:		http://git.netfilter.org/cgi-bin/gitweb.cgi?p=conntrack-tools.git;a=commit;h=656d5ad7c69a5a7d356c6251743890f1eec0bb71
commit 656d5ad7c69a5a7d356c6251743890f1eec0bb71
Author:     Pablo Neira Ayuso <pablo at netfilter.org>
AuthorDate: Thu Mar 12 21:09:27 2009 +0100
Commit:     Pablo Neira Ayuso <pablo at netfilter.org>
CommitDate: Thu Mar 12 21:09:27 2009 +0100

    sync-mode: add abstract layer to make daemon independent of multicast
    
    This patch reworks conntrackd to make it independent of the protocol
    used to propagate state-changes. This patch adds the channel layer
    abstraction, this layer allows you to add support for different
    protocols like unicast UDP or TIPC.
    
    Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>
       via  656d5ad7c69a5a7d356c6251743890f1eec0bb71 (commit)
      from  56b484e3acc7205f0ebd71eec6905253eeace132 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 656d5ad7c69a5a7d356c6251743890f1eec0bb71
Author: Pablo Neira Ayuso <pablo at netfilter.org>
Date:   Thu Mar 12 21:09:27 2009 +0100

    sync-mode: add abstract layer to make daemon independent of multicast
    
    This patch reworks conntrackd to make it independent of the protocol
    used to propagate state-changes. This patch adds the channel layer
    abstraction, this layer allows you to add support for different
    protocols like unicast UDP or TIPC.
    
    Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>

-----------------------------------------------------------------------

 include/Makefile.am  |    2 +-
 include/channel.h    |   95 ++++++++++++++++++++++++++
 include/conntrackd.h |   10 ++--
 include/mcast.h      |   26 ++------
 include/network.h    |    5 --
 src/Makefile.am      |    1 +
 src/channel.c        |  180 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/channel_mcast.c  |  123 ++++++++++++++++++++++++++++++++++
 src/mcast.c          |  169 +----------------------------------------------
 src/multichannel.c   |  110 ++++++++++++++++++++++++++++++
 src/network.c        |   61 -----------------
 src/read_config_yy.y |   69 +++++++++++---------
 src/sync-alarm.c     |    4 +-
 src/sync-ftfw.c      |    4 +-
 src/sync-mode.c      |   82 ++++++++--------------
 src/sync-notrack.c   |    4 +-
 16 files changed, 596 insertions(+), 349 deletions(-)
 create mode 100644 include/channel.h
 create mode 100644 src/channel.c
 create mode 100644 src/channel_mcast.c
 create mode 100644 src/multichannel.c
This patch reworks conntrackd to make it independent of the protocol
used to propagate state-changes. This patch adds the channel layer
abstraction, this layer allows you to add support for different
protocols like unicast UDP or TIPC.

Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>

diff --git a/include/Makefile.am b/include/Makefile.am
index c3f8904..0265620 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -3,5 +3,5 @@ noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \
 		 sync.h conntrackd.h local.h \
 		 debug.h log.h hash.h mcast.h conntrack.h \
 		 network.h filter.h queue.h vector.h cidr.h \
-		 traffic_stats.h netlink.h fds.h event.h bitops.h
+		 traffic_stats.h netlink.h fds.h event.h bitops.h channel.h
 
diff --git a/include/channel.h b/include/channel.h
new file mode 100644
index 0000000..ac1a93c
--- /dev/null
+++ b/include/channel.h
@@ -0,0 +1,95 @@
+#ifndef _CHANNEL_H_
+#define _CHANNEL_H_
+
+#include "mcast.h"
+
+struct channel;
+struct nethdr;
+
+enum {
+	CHANNEL_MCAST,
+	CHANNEL_MAX,
+};
+
+struct mcast_channel {
+	struct mcast_sock *client;
+	struct mcast_sock *server;
+};
+
+#define CHANNEL_F_DEFAULT	(1 << 0)
+#define CHANNEL_F_BUFFERED	(1 << 1)
+#define CHANNEL_F_MAX		(1 << 2)
+
+union channel_type_conf {
+	struct mcast_conf mcast;
+};
+
+struct channel_conf {
+	int				channel_type;
+	char				channel_ifname[IFNAMSIZ];
+	unsigned int			channel_flags;
+	union channel_type_conf		u;
+};
+
+struct nlif_handle;
+
+struct channel_ops {
+	void *	(*open)(void *conf);
+	void	(*close)(void *channel);
+	int	(*send)(void *channel, const void *data, int len);
+	int	(*recv)(void *channel, char *buf, int len);
+	int	(*get_fd)(void *channel);
+	void	(*stats)(struct channel *c, int fd);
+	void	(*stats_extended)(struct channel *c, int active,
+				  struct nlif_handle *h, int fd);
+};
+
+struct channel_buffer;
+
+struct channel {
+	int			channel_type;
+	int			channel_ifindex;
+	int			channel_ifmtu;
+	unsigned int		channel_flags;
+	struct channel_buffer	*buffer;
+	struct channel_ops	*ops;
+	void			*data;
+};
+
+void channel_init(void);
+struct channel *channel_open(struct channel_conf *conf);
+void channel_close(struct channel *c);
+
+int channel_send(struct channel *c, const struct nethdr *net);
+int channel_send_flush(struct channel *c);
+int channel_recv(struct channel *c, char *buf, int size);
+
+int channel_get_fd(struct channel *c);
+void channel_stats(struct channel *c, int fd);
+void channel_stats_extended(struct channel *c, int active,
+			    struct nlif_handle *h, int fd);
+
+#define MULTICHANNEL_MAX	4
+
+struct multichannel {
+	int		channel_num;
+	struct channel *channel[MULTICHANNEL_MAX];
+	struct channel *current;
+};
+
+struct multichannel *multichannel_open(struct channel_conf *conf, int len);
+void multichannel_close(struct multichannel *m);
+
+int multichannel_send(struct multichannel *c, const struct nethdr *net);
+int multichannel_send_flush(struct multichannel *c);
+int multichannel_recv(struct multichannel *c, char *buf, int size);
+
+void multichannel_stats(struct multichannel *m, int fd);
+void multichannel_stats_extended(struct multichannel *m,
+				 struct nlif_handle *h, int fd);
+
+int multichannel_get_ifindex(struct multichannel *m, int i);
+int multichannel_get_current_ifindex(struct multichannel *m);
+void multichannel_set_current_channel(struct multichannel *m, int i);
+
+#endif /* _CHANNEL_H_ */
diff --git a/include/conntrackd.h b/include/conntrackd.h
index 536abc9..cfb1ac5 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -5,6 +5,7 @@
 #include "local.h"
 #include "alarm.h"
 #include "filter.h"
+#include "channel.h"
 
 #include <stdint.h>
 #include <stdio.h>
@@ -71,9 +72,9 @@ struct ct_conf {
 	int syslog_facility;
 	char lockfile[FILENAME_MAXLEN];
 	int hashsize;			/* hashtable size */
-	int mcast_links;
-	int mcast_default_link;
-	struct mcast_conf mcast[MCAST_LINKS_MAX];
+	int channel_num;
+	int channel_default;
+	struct channel_conf channel[MULTICHANNEL_MAX];
 	struct local_conf local;	/* unix socket facilities */
 	int nice;
 	int limit;
@@ -163,8 +164,7 @@ struct ct_sync_state {
 	struct cache *internal; 	/* internal events cache (netlink) */
 	struct cache *external; 	/* external events cache (mcast) */
 
-	struct mcast_sock_multi *mcast_server;  /* multicast incoming */
-	struct mcast_sock_multi *mcast_client;  /* multicast outgoing  */
+	struct multichannel	*channel;
 	struct nlif_handle	*interface;
 	struct queue *tx_queue;
 
diff --git a/include/mcast.h b/include/mcast.h
index 623f390..68d18e8 100644
--- a/include/mcast.h
+++ b/include/mcast.h
@@ -42,38 +42,22 @@ struct mcast_sock {
 	struct mcast_stats stats;
 };
 
-#define MCAST_LINKS_MAX	4
-
-struct mcast_sock_multi {
-	int num_links;
-	int max_mtu;
-	struct mcast_sock *current_link;
-	struct mcast_sock *multi[MCAST_LINKS_MAX];
-};
-
 struct mcast_sock *mcast_server_create(struct mcast_conf *conf);
 void mcast_server_destroy(struct mcast_sock *m);
-struct mcast_sock_multi *mcast_server_create_multi(struct mcast_conf *conf, int conf_len);
-void mcast_server_destroy_multi(struct mcast_sock_multi *m);
 
 struct mcast_sock *mcast_client_create(struct mcast_conf *conf);
 void mcast_client_destroy(struct mcast_sock *m);
-struct mcast_sock_multi *mcast_client_create_multi(struct mcast_conf *conf, int conf_len);
-void mcast_client_destroy_multi(struct mcast_sock_multi*m);
 
 ssize_t mcast_send(struct mcast_sock *m, void *data, int size);
 ssize_t mcast_recv(struct mcast_sock *m, void *data, int size);
 
 int mcast_get_fd(struct mcast_sock *m);
-int mcast_get_ifidx(struct mcast_sock_multi *m, int i);
-int mcast_get_current_ifidx(struct mcast_sock_multi *m);
-
-struct mcast_sock *mcast_get_current_link(struct mcast_sock_multi *m);
-void mcast_set_current_link(struct mcast_sock_multi *m, int i);
 
-void mcast_dump_stats(int fd, const struct mcast_sock_multi *s, const struct mcast_sock_multi *r);
+int mcast_snprintf_stats(char *buf, size_t buflen, char *ifname,
+			 struct mcast_stats *s, struct mcast_stats *r);
 
-struct nlif_handle;
+int mcast_snprintf_stats2(char *buf, size_t buflen, const char *ifname,
+			  const char *status, int active,
+			  struct mcast_stats *s, struct mcast_stats *r);
 
-void mcast_dump_stats_extended(int fd, const struct mcast_sock_multi *s, const struct mcast_sock_multi *r, const struct nlif_handle *h);
 #endif
diff --git a/include/network.h b/include/network.h
index 29a6113..7019d7d 100644
--- a/include/network.h
+++ b/include/network.h
@@ -106,11 +106,6 @@ int mcast_track_is_seq_set(void);
 
 struct mcast_conf;
 
-int mcast_buffered_init(int mtu);
-void mcast_buffered_destroy(void);
-int mcast_buffered_send_netmsg(struct mcast_sock_multi *m, const struct nethdr *net);
-ssize_t mcast_buffered_pending_netmsg(struct mcast_sock_multi *m);
-
 #define IS_DATA(x)	(x->type <= NET_T_STATE_MAX && \
 			(x->flags & ~(NET_F_HELLO | NET_F_HELLO_BACK)) == 0)
 #define IS_ACK(x)	(x->type == NET_T_CTL && x->flags & NET_F_ACK)
diff --git a/src/Makefile.am b/src/Makefile.am
index 8ba09e1..54cfda4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,7 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \
 		    traffic_stats.c stats-mode.c \
 		    network.c cidr.c \
 		    build.c parse.c \
+		    channel.c multichannel.c channel_mcast.c \
 		    read_config_yy.y read_config_lex.l
 
 # yacc and lex generate dirty code
diff --git a/src/channel.c b/src/channel.c
new file mode 100644
index 0000000..733fd03
--- /dev/null
+++ b/src/channel.c
@@ -0,0 +1,180 @@
+/*
+ * (C) 2009 by Pablo Neira Ayuso <pablo at netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or 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.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+
+#include "channel.h"
+#include "network.h"
+
+static struct channel_ops *ops[CHANNEL_MAX];
+extern struct channel_ops channel_mcast;
+
+void channel_init(void)
+{
+	ops[CHANNEL_MCAST] = &channel_mcast;
+}
+
+#define HEADERSIZ 28 /* IP header (20 bytes) + UDP header 8 (bytes) */
+
+struct channel_buffer {
+	char	*data;
+	int	size;
+	int	len;
+};
+
+static struct channel_buffer *
+channel_buffer_open(int mtu)
+{
+	struct channel_buffer *b;
+
+	b = calloc(sizeof(struct channel_buffer), 1);
+	if (b == NULL)
+		return NULL;
+
+	b->size = mtu - HEADERSIZ;
+
+	b->data = malloc(b->size);
+	if (b->data == NULL) {
+		free(b);
+		return NULL;
+	}
+	return b;
+}
+
+static void
+channel_buffer_close(struct channel_buffer *b)
+{
+	free(b->data);
+	free(b);
+}
+
+struct channel *
+channel_open(struct channel_conf *conf)
+{
+	struct channel *c;
+	struct ifreq ifr;
+	int fd;
+
+	if (conf->channel_type >= CHANNEL_MAX)
+		return NULL;
+	if (!conf->channel_ifname[0])
+		return NULL;
+	if (conf->channel_flags >= CHANNEL_F_MAX)
+		return NULL;
+
+	c = calloc(sizeof(struct channel), 1);
+	if (c == NULL)
+		return NULL;
+
+	c->channel_type = conf->channel_type;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1) {
+		free(c);
+		return NULL;
+	}
+	strncpy(ifr.ifr_name, conf->channel_ifname, sizeof(ifr.ifr_name));
+
+	if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
+		free(c);
+		return NULL;
+	}
+	close(fd);
+	c->channel_ifmtu = ifr.ifr_mtu;
+
+	c->channel_ifindex = if_nametoindex(conf->channel_ifname);
+	if (c->channel_ifindex == 0) {
+		free(c);
+		return NULL;
+	}
+	c->ops = ops[conf->channel_type];
+
+	if (conf->channel_flags & CHANNEL_F_BUFFERED) {
+		c->buffer = channel_buffer_open(c->channel_ifmtu);
+		if (c->buffer == NULL) {
+			free(c);
+			return NULL;
+		}
+	}
+	c->channel_flags = conf->channel_flags;
+
+	c->data = c->ops->open(&conf->u);
+	if (c->data == NULL) {
+		channel_buffer_close(c->buffer);
+		free(c);
+		return NULL;
+	}
+	return c;
+}
+
+void
+channel_close(struct channel *c)
+{
+	c->ops->close(c->data);
+	if (c->channel_flags & CHANNEL_F_BUFFERED)
+		channel_buffer_close(c->buffer);
+	free(c);
+}
+
+int channel_send(struct channel *c, const struct nethdr *net)
+{
+	int ret = 0, len = ntohs(net->len);
+
+	if (!(c->channel_flags & CHANNEL_F_BUFFERED)) {
+		c->ops->send(c->data, net, len);
+		return 1;
+	}
+retry:
+	if (c->buffer->len + len < c->buffer->size) {
+		memcpy(c->buffer->data + c->buffer->len, net, len);
+		c->buffer->len += len;
+	} else {
+		c->ops->send(c->data, c->buffer->data, c->buffer->len);
+		ret = 1;
+		c->buffer->len = 0;
+		goto retry;
+	}
+	return ret;
+}
+
+int channel_send_flush(struct channel *c)
+{
+	if (!(c->channel_flags & CHANNEL_F_BUFFERED) || c->buffer->len == 0)
+		return 0;
+
+	c->ops->send(c->data, c->buffer->data, c->buffer->len);
+	c->buffer->len = 0;
+	return 1;
+}
+
+int channel_recv(struct channel *c, char *buf, int size)
+{
+	return c->ops->recv(c->data, buf, size);
+}
+
+int channel_get_fd(struct channel *c)
+{
+	return c->ops->get_fd(c->data);
+}
+
+void channel_stats(struct channel *c, int fd)
+{
+	return c->ops->stats(c, fd);
+}
+
+void channel_stats_extended(struct channel *c, int active,
+			    struct nlif_handle *h, int fd)
+{
+	return c->ops->stats_extended(c, active, h, fd);
+}
diff --git a/src/channel_mcast.c b/src/channel_mcast.c
new file mode 100644
index 0000000..898b194
--- /dev/null
+++ b/src/channel_mcast.c
@@ -0,0 +1,123 @@
+/*
+ * (C) 2009 by Pablo Neira Ayuso <pablo at netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or 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.
+ */
+
+#include <stdlib.h>
+#include <libnfnetlink/libnfnetlink.h>
+
+#include "channel.h"
+#include "mcast.h"
+
+static void
+*channel_mcast_open(void *conf)
+{
+	struct mcast_channel *m;
+	struct mcast_conf *c = conf;
+
+	m = calloc(sizeof(struct mcast_channel), 1);
+	if (m == NULL)
+		return NULL;
+
+	m->client = mcast_client_create(c);
+	if (m->client == NULL) {
+		free(m);
+		return NULL;
+	}
+
+	m->server = mcast_server_create(c);
+	if (m->server == NULL) {
+		mcast_client_destroy(m->client);
+		free(m);
+		return NULL;
+	}
+	return m;
+}
+
+static int
+channel_mcast_send(void *channel, const void *data, int len)
+{
+	struct mcast_channel *m = channel;
+	return mcast_send(m->client, data, len);
+}
+
+static int
+channel_mcast_recv(void *channel, char *buf, int size)
+{
+	struct mcast_channel *m = channel;
+	return mcast_recv(m->server, buf, size);
+}
+
+static void
+channel_mcast_close(void *channel)
+{
+	struct mcast_channel *m = channel;
+	mcast_client_destroy(m->client);
+	mcast_server_destroy(m->server);
+	free(m);
+}
+
+static int
+channel_mcast_get_fd(void *channel)
+{
+	struct mcast_channel *m = channel;
+	return mcast_get_fd(m->server);
+}
+
+static void
+channel_mcast_stats(struct channel *c, int fd)
+{
+	struct mcast_channel *m = c->data;
+	char ifname[IFNAMSIZ], buf[512];
+	int size;
+
+	if_indextoname(c->channel_ifindex, ifname);
+	size = mcast_snprintf_stats(buf, sizeof(buf), ifname,
+				    &m->client->stats, &m->server->stats);
+	send(fd, buf, size, 0);
+}
+
+static void
+channel_mcast_stats_extended(struct channel *c, int active,
+			     struct nlif_handle *h, int fd)
+{
+	struct mcast_channel *m = c->data;
+	char ifname[IFNAMSIZ], buf[512];
+	const char *status;
+	unsigned int flags;
+	int size;
+
+	if_indextoname(c->channel_ifindex, ifname);
+	nlif_get_ifflags(h, c->channel_ifindex, &flags);
+	/* 
+	 * IFF_UP shows administrative status
+	 * IFF_RUNNING shows carrier status
+	 */
+	if (flags & IFF_UP) {
+		if (!(flags & IFF_RUNNING))
+			status = "NO-CARRIER";
+		else
+			status = "RUNNING";
+	} else {
+		status = "DOWN";
+	}
+	size = mcast_snprintf_stats2(buf, sizeof(buf),
+				     ifname, status, active,
+				     &m->client->stats,
+				     &m->server->stats);
+	send(fd, buf, size, 0);
+}
+
+struct channel_ops channel_mcast = {
+	.open		= channel_mcast_open,
+	.close		= channel_mcast_close,
+	.send		= channel_mcast_send,
+	.recv		= channel_mcast_recv,
+	.get_fd		= channel_mcast_get_fd,
+	.stats		= channel_mcast_stats,
+	.stats_extended = channel_mcast_stats_extended,
+};
diff --git a/src/mcast.c b/src/mcast.c
index 8f11762..8eedd07 100644
--- a/src/mcast.c
+++ b/src/mcast.c
@@ -143,52 +143,12 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf)
 	return m;
 }
 
-struct mcast_sock_multi *
-mcast_server_create_multi(struct mcast_conf *conf, int conf_len)
-{
-	struct mcast_sock_multi *m;
-	int i, j;
-
-	if (conf_len <= 0 || conf_len > MCAST_LINKS_MAX)
-		return NULL;
-
-	m = calloc(sizeof(struct mcast_sock_multi), 1);
-	if (m == NULL)
-		return NULL;
-
-	m->max_mtu = INT_MAX;
-	for (i=0; i<conf_len; i++) {
-		m->multi[i] = mcast_server_create(&conf[i]);
-		if (m->multi[i] == NULL) {
-			for (j=0; j<i; j++) {
-				mcast_server_destroy(m->multi[j]);
-			}
-			free(m);
-			return NULL;
-		}
-		if (m->max_mtu > conf[i].mtu)
-			m->max_mtu = conf[i].mtu;
-	}
-	m->num_links = conf_len;
-
-	return m;
-}
-
 void mcast_server_destroy(struct mcast_sock *m)
 {
 	close(m->fd);
 	free(m);
 }
 
-void mcast_server_destroy_multi(struct mcast_sock_multi *m)
-{
-	int i;
-
-	for (i=0; i<m->num_links; i++)
-		mcast_server_destroy(m->multi[i]);
-	free(m);
-}
-
 static int 
 __mcast_client_create_ipv4(struct mcast_sock *m, struct mcast_conf *conf)
 {
@@ -306,52 +266,12 @@ struct mcast_sock *mcast_client_create(struct mcast_conf *conf)
 	return m;
 }
 
-struct mcast_sock_multi *
-mcast_client_create_multi(struct mcast_conf *conf, int conf_len)
-{
-	struct mcast_sock_multi *m;
-	int i, j;
-
-	if (conf_len <= 0 || conf_len > MCAST_LINKS_MAX)
-		return NULL;
-
-	m = calloc(sizeof(struct mcast_sock_multi), 1);
-	if (m == NULL)
-		return NULL;
-
-	m->max_mtu = INT_MAX;
-	for (i=0; i<conf_len; i++) {
-		m->multi[i] = mcast_client_create(&conf[i]);
-		if (m->multi[i] == NULL) {
-			for (j=0; j<i; j++) {
-				mcast_client_destroy(m->multi[j]);
-			}
-			free(m);
-			return NULL;
-		}
-		if (m->max_mtu > conf[i].mtu)
-			m->max_mtu = conf[i].mtu;
-	}
-	m->num_links = conf_len;
-
-	return m;
-}
-
 void mcast_client_destroy(struct mcast_sock *m)
 {
 	close(m->fd);
 	free(m);
 }
 
-void mcast_client_destroy_multi(struct mcast_sock_multi *m)
-{
-	int i;
-
-	for (i=0; i<m->num_links; i++)
-		mcast_client_destroy(m->multi[i]);
-	free(m);
-}
-
 ssize_t mcast_send(struct mcast_sock *m, void *data, int size)
 {
 	ssize_t ret;
@@ -395,32 +315,12 @@ ssize_t mcast_recv(struct mcast_sock *m, void *data, int size)
 	return ret;
 }
 
-void mcast_set_current_link(struct mcast_sock_multi *m, int i)
-{
-	m->current_link = m->multi[i];
-}
-
-struct mcast_sock *mcast_get_current_link(struct mcast_sock_multi *m)
-{
-	return m->current_link;
-}
-
 int mcast_get_fd(struct mcast_sock *m)
 {
 	return m->fd;
 }
 
-int mcast_get_current_ifidx(struct mcast_sock_multi *m)
-{
-	return m->current_link->interface_idx;
-}
-
-int mcast_get_ifidx(struct mcast_sock_multi *m, int i)
-{
-	return m->multi[i]->interface_idx;
-}
-
-static int
+int
 mcast_snprintf_stats(char *buf, size_t buflen, char *ifname,
 		     struct mcast_stats *s, struct mcast_stats *r)
 {
@@ -443,7 +343,7 @@ mcast_snprintf_stats(char *buf, size_t buflen, char *ifname,
 	return size;
 }
 
-static int
+int
 mcast_snprintf_stats2(char *buf, size_t buflen, const char *ifname, 
 		      const char *status, int active,
 		      struct mcast_stats *s, struct mcast_stats *r)
@@ -467,68 +367,3 @@ mcast_snprintf_stats2(char *buf, size_t buflen, const char *ifname,
 			(unsigned long long)r->error);
 	return size;
 }
-
-void
-mcast_dump_stats(int fd,
-		 const struct mcast_sock_multi *s,
-		 const struct mcast_sock_multi *r)
-{
-	int i;
-	struct mcast_stats snd = { 0, 0, 0};
-	struct mcast_stats rcv = { 0, 0, 0};
-	char ifname[IFNAMSIZ], buf[512];
-	int size;
-
-	/* it is the same for the receiver, no need to do it twice */
-	if_indextoname(s->current_link->interface_idx, ifname);
-
-	for (i=0; i<s->num_links && i<r->num_links; i++) {
-		snd.bytes	+= s->multi[i]->stats.bytes;
-		snd.messages	+= s->multi[i]->stats.messages;
-		snd.error	+= s->multi[i]->stats.error;
-		rcv.bytes	+= r->multi[i]->stats.bytes;
-		rcv.messages	+= r->multi[i]->stats.messages;
-		rcv.error	+= r->multi[i]->stats.error;
-	}
-	size = mcast_snprintf_stats(buf, sizeof(buf), ifname, &snd, &rcv);
-	send(fd, buf, size, 0);
-}
-
-void
-mcast_dump_stats_extended(int fd,
-			  const struct mcast_sock_multi *s,
-			  const struct mcast_sock_multi *r,
-			  const struct nlif_handle *h)
-{
-	int i;
-	char buf[4096];
-	int size = 0;
-
-	for (i=0; i<s->num_links && i<r->num_links; i++) {
-		int idx = s->multi[i]->interface_idx, active;
-		unsigned int flags;
-		char ifname[IFNAMSIZ];
-		const char *status;
-
-		if_indextoname(idx, ifname);
-		nlif_get_ifflags(h, idx, &flags);
-		active = (s->multi[i] == s->current_link);
-		/* 
-		 * IFF_UP shows administrative status
-		 * IFF_RUNNING shows carrier status
-		 */
-		if (flags & IFF_UP) {
-			if (!(flags & IFF_RUNNING))
-				status = "NO-CARRIER";
-			else
-				status = "RUNNING";
-		} else {
-			status = "DOWN";
-		}
-		size += mcast_snprintf_stats2(buf+size, sizeof(buf),
-					      ifname, status, active,
-					      &s->multi[i]->stats,
-					      &r->multi[i]->stats);
-	}
-	send(fd, buf, size, 0);
-}
diff --git a/src/multichannel.c b/src/multichannel.c
new file mode 100644
index 0000000..ab0f04c
--- /dev/null
+++ b/src/multichannel.c
@@ -0,0 +1,110 @@
+/*
+ * (C) 2009 by Pablo Neira Ayuso <pablo at netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or 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.
+ */
+
+#include <stdlib.h>
+
+#include "channel.h"
+#include "network.h"
+
+struct multichannel *
+multichannel_open(struct channel_conf *conf, int len)
+{
+	struct multichannel *m;
+	int i, set_default_channel = 0;
+
+	if (len <= 0 || len > MULTICHANNEL_MAX)
+		return NULL;
+
+	m = calloc(sizeof(struct multichannel), 1);
+	if (m == NULL)
+		return NULL;
+
+	m->channel_num = len;
+	for (i = 0; i < len; i++) {
+		m->channel[i] = channel_open(&conf[i]);
+		if (m->channel[i] == NULL) {
+			int j;
+
+			for (j=0; j<i; j++) {
+				channel_close(m->channel[j]);
+			}
+			free(m);
+			return NULL;
+		}
+		if (conf[i].channel_flags & CHANNEL_F_DEFAULT) {
+			m->current = m->channel[i];
+			set_default_channel = 1;
+		}
+	}
+	if (!set_default_channel)
+		m->current = m->channel[0];
+
+	return m;
+}
+
+int multichannel_send(struct multichannel *c, const struct nethdr *net)
+{
+	return channel_send(c->current, net);
+}
+
+int multichannel_send_flush(struct multichannel *c)
+{
+	return channel_send_flush(c->current);
+}
+
+int multichannel_recv(struct multichannel *c, char *buf, int size)
+{
+	return channel_recv(c->current, buf, size);
+}
+
+void multichannel_close(struct multichannel *m)
+{
+	int i;
+
+	for (i = 0; i < m->channel_num; i++) {
+		channel_close(m->channel[i]);
+	}
+	free(m);
+}
+
+void multichannel_stats(struct multichannel *m, int fd)
+{
+	channel_stats(m->current, fd);
+}
+
+void
+multichannel_stats_extended(struct multichannel *m,
+			    struct nlif_handle *h, int fd)
+{
+	int i, active;
+
+	for (i = 0; i < m->channel_num; i++) {
+		if (m->current == m->channel[i]) {
+			active = 1;
+		} else {
+			active = 0;
+		}
+		channel_stats_extended(m->channel[i], active, h, fd);
+	}
+}
+
+int multichannel_get_ifindex(struct multichannel *m, int i)
+{
+	return m->channel[i]->channel_ifindex;
+}
+
+int multichannel_get_current_ifindex(struct multichannel *m)
+{
+	return m->current->channel_ifindex;
+}
+
+void multichannel_set_current_channel(struct multichannel *m, int i)
+{
+	m->current = m->channel[i];
+}
diff --git a/src/network.c b/src/network.c
index 690b28e..bdfa10c 100644
--- a/src/network.c
+++ b/src/network.c
@@ -65,67 +65,6 @@ void nethdr_set_ctl(struct nethdr *net)
 	__nethdr_set(net, NETHDR_SIZ);
 }
 
-static size_t tx_buflenmax;
-static size_t tx_buflen = 0;
-static char *tx_buf;
-
-#define HEADERSIZ 28 /* IP header (20 bytes) + UDP header 8 (bytes) */
-
-int mcast_buffered_init(int if_mtu)
-{
-	int mtu = if_mtu - HEADERSIZ;
-
-	/* default to Ethernet MTU 1500 bytes */
-	if (if_mtu == 0)
-		mtu = 1500 - HEADERSIZ;
-
-	tx_buf = malloc(mtu);
-	if (tx_buf == NULL)
-		return -1;
-
-	tx_buflenmax = mtu;
-
-	return 0;
-}
-
-void mcast_buffered_destroy(void)
-{
-	free(tx_buf);
-}
-
-/* return 0 if it is not sent, otherwise return 1 */
-int
-mcast_buffered_send_netmsg(struct mcast_sock_multi *m, const struct nethdr *net)
-{
-	int ret = 0, len = ntohs(net->len);
-
-retry:
-	if (tx_buflen + len < tx_buflenmax) {
-		memcpy(tx_buf + tx_buflen, net, len);
-		tx_buflen += len;
-	} else {
-		mcast_send(mcast_get_current_link(m), tx_buf, tx_buflen);
-		ret = 1;
-		tx_buflen = 0;
-		goto retry;
-	}
-
-	return ret;
-}
-
-ssize_t mcast_buffered_pending_netmsg(struct mcast_sock_multi *m)
-{
-	ssize_t ret;
-
-	if (tx_buflen == 0)
-		return 0;
-
-	ret = mcast_send(mcast_get_current_link(m), tx_buf, tx_buflen);
-	tx_buflen = 0;
-
-	return ret;
-}
-
 static int local_seq_set = 0;
 
 /* this function only tracks, it does not update the last sequence received */
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index b9a37f7..b3a2640 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -181,18 +181,18 @@ checksum: T_CHECKSUM T_ON
 	 * XXX: The use of Checksum outside of the Multicast clause is broken
 	 *	if we have more than one dedicated links.
 	 */
-	conf.mcast[0].checksum = 0;
+	conf.channel[0].u.mcast.checksum = 0;
 };
 
 checksum: T_CHECKSUM T_OFF
 {
 	fprintf(stderr, "WARNING: The use of `Checksum' outside the "
 			"`Multicast' clause is ambiguous.\n");
-	/* 
+	/*
 	 * XXX: The use of Checksum outside of the Multicast clause is broken
 	 *	if we have more than one dedicated links.
 	 */
-	conf.mcast[0].checksum = 1;
+	conf.channel[0].u.mcast.checksum = 1;
 };
 
 ignore_traffic : T_IGNORE_TRAFFIC '{' ignore_traffic_options '}'
@@ -256,13 +256,18 @@ ignore_traffic_option : T_IPV6_ADDR T_IP
 
 multicast_line : T_MULTICAST '{' multicast_options '}'
 {
-	conf.mcast_links++;
+	conf.channel[conf.channel_num].channel_type = CHANNEL_MCAST;
+	conf.channel[conf.channel_num].channel_flags = CHANNEL_F_BUFFERED;
+	conf.channel_num++;
 };
 
 multicast_line : T_MULTICAST T_DEFAULT '{' multicast_options '}'
 {
-	conf.mcast_default_link = conf.mcast_links;
-	conf.mcast_links++;
+	conf.channel[conf.channel_num].channel_type = CHANNEL_MCAST;
+	conf.channel[conf.channel_num].channel_flags = CHANNEL_F_DEFAULT |
+						       CHANNEL_F_BUFFERED;
+	conf.channel_default = conf.channel_num;
+	conf.channel_num++;
 };
 
 multicast_options :
@@ -272,19 +277,19 @@ multicast_option : T_IPV4_ADDR T_IP
 {
 	__max_mcast_dedicated_links_reached();
 
-	if (!inet_aton($2, &conf.mcast[conf.mcast_links].in)) {
+	if (!inet_aton($2, &conf.channel[conf.channel_num].u.mcast.in)) {
 		fprintf(stderr, "%s is not a valid IPv4 address\n", $2);
 		break;
 	}
 
-        if (conf.mcast[conf.mcast_links].ipproto == AF_INET6) {
+        if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) {
 		fprintf(stderr, "Your multicast address is IPv4 but "
 		                "is binded to an IPv6 interface? Surely "
 				"this is not what you want\n");
 		break;
 	}
 
-	conf.mcast[conf.mcast_links].ipproto = AF_INET;
+	conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET;
 };
 
 multicast_option : T_IPV6_ADDR T_IP
@@ -292,7 +297,8 @@ multicast_option : T_IPV6_ADDR T_IP
 	__max_mcast_dedicated_links_reached();
 
 #ifdef HAVE_INET_PTON_IPV6
-	if (inet_pton(AF_INET6, $2, &conf.mcast[conf.mcast_links].in) <= 0) {
+	if (inet_pton(AF_INET6, $2,
+		      &conf.channel[conf.channel_num].u.mcast.in) <= 0) {
 		fprintf(stderr, "%s is not a valid IPv6 address\n", $2);
 		break;
 	}
@@ -301,17 +307,17 @@ multicast_option : T_IPV6_ADDR T_IP
 	break;
 #endif
 
-	if (conf.mcast[conf.mcast_links].ipproto == AF_INET) {
+	if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET) {
 		fprintf(stderr, "Your multicast address is IPv6 but "
 				"is binded to an IPv4 interface? Surely "
 				"this is not what you want\n");
 		break;
 	}
 
-	conf.mcast[conf.mcast_links].ipproto = AF_INET6;
+	conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET6;
 
-	if (conf.mcast[conf.mcast_links].iface[0] &&
-	    !conf.mcast[conf.mcast_links].ifa.interface_index6) {
+	if (conf.channel[conf.channel_num].u.mcast.iface[0] &&
+	    !conf.channel[conf.channel_num].u.mcast.ifa.interface_index6) {
 		unsigned int idx;
 
 		idx = if_nametoindex($2);
@@ -320,8 +326,8 @@ multicast_option : T_IPV6_ADDR T_IP
 			break;
 		}
 
-		conf.mcast[conf.mcast_links].ifa.interface_index6 = idx;
-		conf.mcast[conf.mcast_links].ipproto = AF_INET6;
+		conf.channel[conf.channel_num].u.mcast.ifa.interface_index6 = idx;
+		conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET6;
 	}
 };
 
@@ -329,19 +335,19 @@ multicast_option : T_IPV4_IFACE T_IP
 {
 	__max_mcast_dedicated_links_reached();
 
-	if (!inet_aton($2, &conf.mcast[conf.mcast_links].ifa)) {
+	if (!inet_aton($2, &conf.channel[conf.channel_num].u.mcast.ifa)) {
 		fprintf(stderr, "%s is not a valid IPv4 address\n", $2);
 		break;
 	}
 
-        if (conf.mcast[conf.mcast_links].ipproto == AF_INET6) {
+        if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) {
 		fprintf(stderr, "Your multicast interface is IPv4 but "
 		                "is binded to an IPv6 interface? Surely "
 				"this is not what you want\n");
 		break;
 	}
 
-	conf.mcast[conf.mcast_links].ipproto = AF_INET;
+	conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET;
 };
 
 multicast_option : T_IPV6_IFACE T_IP
@@ -355,18 +361,19 @@ multicast_option : T_IFACE T_STRING
 
 	__max_mcast_dedicated_links_reached();
 
-	strncpy(conf.mcast[conf.mcast_links].iface, $2, IFNAMSIZ);
+	strncpy(conf.channel[conf.channel_num].channel_ifname, $2, IFNAMSIZ);
+	strncpy(conf.channel[conf.channel_num].u.mcast.iface, $2, IFNAMSIZ);
 
 	idx = if_nametoindex($2);
 	if (!idx) {
 		fprintf(stderr, "%s is an invalid interface.\n", $2);
 		break;
 	}
-	conf.mcast[conf.mcast_links].interface_idx = idx;
+	conf.channel[conf.channel_num].u.mcast.interface_idx = idx;
 
-	if (conf.mcast[conf.mcast_links].ipproto == AF_INET6) {
-		conf.mcast[conf.mcast_links].ifa.interface_index6 = idx;
-		conf.mcast[conf.mcast_links].ipproto = AF_INET6;
+	if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) {
+		conf.channel[conf.channel_num].u.mcast.ifa.interface_index6 = idx;
+		conf.channel[conf.channel_num].u.mcast.ipproto = AF_INET6;
 	}
 };
 
@@ -379,31 +386,31 @@ multicast_option : T_BACKLOG T_NUMBER
 multicast_option : T_GROUP T_NUMBER
 {
 	__max_mcast_dedicated_links_reached();
-	conf.mcast[conf.mcast_links].port = $2;
+	conf.channel[conf.channel_num].u.mcast.port = $2;
 };
 
 multicast_option: T_MCAST_SNDBUFF T_NUMBER
 {
 	__max_mcast_dedicated_links_reached();
-	conf.mcast[conf.mcast_links].sndbuf = $2;
+	conf.channel[conf.channel_num].u.mcast.sndbuf = $2;
 };
 
 multicast_option: T_MCAST_RCVBUFF T_NUMBER
 {
 	__max_mcast_dedicated_links_reached();
-	conf.mcast[conf.mcast_links].rcvbuf = $2;
+	conf.channel[conf.channel_num].u.mcast.rcvbuf = $2;
 };
 
 multicast_option: T_CHECKSUM T_ON 
 {
 	__max_mcast_dedicated_links_reached();
-	conf.mcast[conf.mcast_links].checksum = 0;
+	conf.channel[conf.channel_num].u.mcast.checksum = 0;
 };
 
 multicast_option: T_CHECKSUM T_OFF
 {
 	__max_mcast_dedicated_links_reached();
-	conf.mcast[conf.mcast_links].checksum = 1;
+	conf.channel[conf.channel_num].u.mcast.checksum = 1;
 };
 
 hashsize : T_HASHSIZE T_NUMBER
@@ -1128,10 +1135,10 @@ static void __kernel_filter_add_state(int value)
 
 static void __max_mcast_dedicated_links_reached(void)
 {
-	if (conf.mcast_links >= MCAST_LINKS_MAX) {
+	if (conf.channel_num >= MULTICHANNEL_MAX) {
 		fprintf(stderr, "ERROR: too many dedicated links in "
 				"the configuration file (Maximum: %d).\n",
-				MCAST_LINKS_MAX);
+				MULTICHANNEL_MAX);
 		exit(EXIT_FAILURE);
 	}
 }
diff --git a/src/sync-alarm.c b/src/sync-alarm.c
index a59ae11..caa6bb2 100644
--- a/src/sync-alarm.c
+++ b/src/sync-alarm.c
@@ -125,7 +125,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data)
 		net = queue_node_data(n);
 		nethdr_set_ctl(net);
 		HDR_HOST2NETWORK(net);
-		mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net);
+		multichannel_send(STATE_SYNC(channel), net);
 		queue_object_free((struct queue_object *)n);
 		break;
 	case Q_ELEM_OBJ: {
@@ -137,7 +137,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data)
 		obj = cache_data_get_object(STATE_SYNC(internal), ca);
 		type = object_status_to_network_type(obj->status);
 		net = BUILD_NETMSG(obj->ct, type);
-		mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net);
+		multichannel_send(STATE_SYNC(channel), net);
 		cache_object_put(obj);
 		break;
 	}
diff --git a/src/sync-ftfw.c b/src/sync-ftfw.c
index d608e5b..cacbb13 100644
--- a/src/sync-ftfw.c
+++ b/src/sync-ftfw.c
@@ -494,7 +494,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data)
 		dp("tx_queue sq: %u fl:%u len:%u\n",
 	               ntohl(net->seq), net->flags, ntohs(net->len));
 
-		mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net);
+		multichannel_send(STATE_SYNC(channel), net);
 		HDR_NETWORK2HOST(net);
 
 		if (IS_ACK(net) || IS_NACK(net) || IS_RESYNC(net)) {
@@ -523,7 +523,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data)
 		dp("tx_list sq: %u fl:%u len:%u\n",
 	                ntohl(net->seq), net->flags, ntohs(net->len));
 
-		mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net);
+		multichannel_send(STATE_SYNC(channel), net);
 		cn->seq = ntohl(net->seq);
 		if (queue_add(rs_queue, &cn->qnode) < 0) {
 			if (errno == ENOSPC) {
diff --git a/src/sync-mode.c b/src/sync-mode.c
index b452cba..22609df 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -38,12 +38,12 @@
 static void
 mcast_change_current_link(int if_idx)
 {
-	if (if_idx != mcast_get_current_ifidx(STATE_SYNC(mcast_client)))
-		mcast_set_current_link(STATE_SYNC(mcast_client), if_idx);
+	if (if_idx != multichannel_get_current_ifindex(STATE_SYNC(channel)))
+		multichannel_set_current_channel(STATE_SYNC(channel), if_idx);
 }
 
 static void
-do_mcast_handler_step(int if_idx, struct nethdr *net, size_t remain)
+do_channel_handler_step(int if_idx, struct nethdr *net, size_t remain)
 {
 	char __ct[nfct_maxsize()];
 	struct nf_conntrack *ct = (struct nf_conntrack *)(void*) __ct;
@@ -122,14 +122,14 @@ retry:
 	}
 }
 
-/* handler for multicast messages received */
-static void mcast_handler(struct mcast_sock *m, int if_idx)
+/* handler for messages received */
+static void channel_handler(struct channel *m, int if_idx)
 {
 	ssize_t numbytes;
 	ssize_t remain;
 	char __net[65536], *ptr = __net; /* XXX: maximum MTU for IPv4 */
 
-	numbytes = mcast_recv(m, __net, sizeof(__net));
+	numbytes = channel_recv(m, __net, sizeof(__net));
 	if (numbytes <= 0)
 		return;
 
@@ -168,7 +168,7 @@ static void mcast_handler(struct mcast_sock *m, int if_idx)
 
 		HDR_NETWORK2HOST(net);
 
-		do_mcast_handler_step(if_idx, net, remain);
+		do_channel_handler_step(if_idx, net, remain);
 		ptr += net->len;
 		remain -= net->len;
 	}
@@ -181,13 +181,13 @@ static void interface_candidate(void)
 	unsigned int flags;
 	char buf[IFNAMSIZ];
 
-	for (i=0; i<STATE_SYNC(mcast_client)->num_links; i++) {
-		idx = mcast_get_ifidx(STATE_SYNC(mcast_client), i);
-		if (idx == mcast_get_current_ifidx(STATE_SYNC(mcast_client)))
+	for (i=0; i<STATE_SYNC(channel)->channel_num; i++) {
+		idx = multichannel_get_ifindex(STATE_SYNC(channel), i);
+		if (idx == multichannel_get_current_ifindex(STATE_SYNC(channel)))
 			continue;
 		nlif_get_ifflags(STATE_SYNC(interface), idx, &flags);
 		if (flags & (IFF_RUNNING | IFF_UP)) {
-			mcast_set_current_link(STATE_SYNC(mcast_client), i);
+			multichannel_set_current_channel(STATE_SYNC(channel), i);
 			dlog(LOG_NOTICE, "device `%s' becomes multicast "
 					 "dedicated link", 
 					 if_indextoname(idx, buf));
@@ -199,7 +199,7 @@ static void interface_candidate(void)
 
 static void interface_handler(void)
 {
-	int idx = mcast_get_current_ifidx(STATE_SYNC(mcast_client));
+	int idx = multichannel_get_current_ifindex(STATE_SYNC(channel));
 	unsigned int flags;
 
 	nlif_catch(STATE_SYNC(interface));
@@ -267,38 +267,21 @@ static int init_sync(void)
 		return -1;
 	}
 
-	/* multicast server to receive events from the wire */
-	STATE_SYNC(mcast_server) =
-		mcast_server_create_multi(CONFIG(mcast), CONFIG(mcast_links));
-	if (STATE_SYNC(mcast_server) == NULL) {
-		dlog(LOG_ERR, "can't open multicast server!");
+	channel_init();
+
+	/* channel to send events on the wire */
+	STATE_SYNC(channel) =
+		multichannel_open(CONFIG(channel), CONFIG(channel_num));
+	if (STATE_SYNC(channel) == NULL) {
+		dlog(LOG_ERR, "can't open channel socket");
 		return -1;
 	}
-	for (i=0; i<STATE_SYNC(mcast_server)->num_links; i++) {
-		int fd = mcast_get_fd(STATE_SYNC(mcast_server)->multi[i]);
+	for (i=0; i<STATE_SYNC(channel)->channel_num; i++) {
+		int fd = channel_get_fd(STATE_SYNC(channel)->channel[i]);
 		if (register_fd(fd, STATE(fds)) == -1)
 			return -1;
 	}
 
-	/* multicast client to send events on the wire */
-	STATE_SYNC(mcast_client) =
-		mcast_client_create_multi(CONFIG(mcast), CONFIG(mcast_links));
-	if (STATE_SYNC(mcast_client) == NULL) {
-		dlog(LOG_ERR, "can't open client multicast socket");
-		mcast_server_destroy_multi(STATE_SYNC(mcast_server));
-		return -1;
-	}
-	/* we only use one link to send events, but all to receive them */
-	mcast_set_current_link(STATE_SYNC(mcast_client),
-			       CONFIG(mcast_default_link));
-
-	if (mcast_buffered_init(STATE_SYNC(mcast_client)->max_mtu) == -1) {
-		dlog(LOG_ERR, "can't init tx buffer!");
-		mcast_server_destroy_multi(STATE_SYNC(mcast_server));
-		mcast_client_destroy_multi(STATE_SYNC(mcast_client));
-		return -1;
-	}
-
 	STATE_SYNC(interface) = nl_init_interface_handler();
 	if (!STATE_SYNC(interface)) {
 		dlog(LOG_ERR, "can't open interface watcher");
@@ -328,10 +311,10 @@ static void run_sync(fd_set *readfds)
 {
 	int i;
 
-	for (i=0; i<STATE_SYNC(mcast_server)->num_links; i++) {
-		int fd = mcast_get_fd(STATE_SYNC(mcast_server)->multi[i]);
+	for (i=0; i<STATE_SYNC(channel)->channel_num; i++) {
+		int fd = channel_get_fd(STATE_SYNC(channel)->channel[i]);
 		if (FD_ISSET(fd, readfds))
-			mcast_handler(STATE_SYNC(mcast_server)->multi[i], i);
+			channel_handler(STATE_SYNC(channel)->channel[i], i);
 	}
 
 	if (FD_ISSET(queue_get_eventfd(STATE_SYNC(tx_queue)), readfds))
@@ -341,7 +324,7 @@ static void run_sync(fd_set *readfds)
 		interface_handler();
 
 	/* flush pending messages */
-	mcast_buffered_pending_netmsg(STATE_SYNC(mcast_client));
+	multichannel_send_flush(STATE_SYNC(channel));
 }
 
 static void kill_sync(void)
@@ -349,12 +332,10 @@ static void kill_sync(void)
 	cache_destroy(STATE_SYNC(internal));
 	cache_destroy(STATE_SYNC(external));
 
-	mcast_server_destroy_multi(STATE_SYNC(mcast_server));
-	mcast_client_destroy_multi(STATE_SYNC(mcast_client));
+	multichannel_close(STATE_SYNC(channel));
 
 	nlif_close(STATE_SYNC(interface));
 
-	mcast_buffered_destroy();
 	queue_destroy(STATE_SYNC(tx_queue));
 
 	if (STATE_SYNC(sync)->kill)
@@ -486,23 +467,20 @@ static int local_handler_sync(int fd, int type, void *data)
 		cache_stats(STATE_SYNC(internal), fd);
 		cache_stats(STATE_SYNC(external), fd);
 		dump_traffic_stats(fd);
-		mcast_dump_stats(fd, STATE_SYNC(mcast_client), 
-				     STATE_SYNC(mcast_server));
+		multichannel_stats(STATE_SYNC(channel), fd);
 		dump_stats_sync(fd);
 		break;
 	case STATS_NETWORK:
 		dump_stats_sync_extended(fd);
-		mcast_dump_stats(fd, STATE_SYNC(mcast_client), 
-				     STATE_SYNC(mcast_server));
+		multichannel_stats(STATE_SYNC(channel), fd);
 		break;
 	case STATS_CACHE:
 		cache_stats_extended(STATE_SYNC(internal), fd);
 		cache_stats_extended(STATE_SYNC(external), fd);
 		break;
 	case STATS_MULTICAST:
-		mcast_dump_stats_extended(fd, STATE_SYNC(mcast_client),
-					      STATE_SYNC(mcast_server),
-					      STATE_SYNC(interface));
+		multichannel_stats_extended(STATE_SYNC(channel),
+					    STATE_SYNC(interface), fd);
 		break;
 	default:
 		if (STATE_SYNC(sync)->local)
diff --git a/src/sync-notrack.c b/src/sync-notrack.c
index 57c3368..737ee52 100644
--- a/src/sync-notrack.c
+++ b/src/sync-notrack.c
@@ -134,7 +134,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data2)
 		else
 			nethdr_set_ctl(net);
 		HDR_HOST2NETWORK(net);
-		mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net);
+		multichannel_send(STATE_SYNC(channel), net);
 		queue_del(n);
 		queue_object_free((struct queue_object *)n);
 		break;
@@ -150,7 +150,7 @@ static int tx_queue_xmit(struct queue_node *n, const void *data2)
 		type = object_status_to_network_type(obj->status);;
 		net = BUILD_NETMSG(obj->ct, type);
 
-		mcast_buffered_send_netmsg(STATE_SYNC(mcast_client), net);
+		multichannel_send(STATE_SYNC(channel), net);
 		queue_del(n);
 		cache_object_put(obj);
 		break;



More information about the netfilter-cvslog mailing list