summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/Makefile.am2
-rw-r--r--include/channel.h95
-rw-r--r--include/conntrackd.h10
-rw-r--r--include/mcast.h26
-rw-r--r--include/network.h5
-rw-r--r--src/Makefile.am1
-rw-r--r--src/channel.c180
-rw-r--r--src/channel_mcast.c123
-rw-r--r--src/mcast.c169
-rw-r--r--src/multichannel.c110
-rw-r--r--src/network.c61
-rw-r--r--src/read_config_yy.y69
-rw-r--r--src/sync-alarm.c4
-rw-r--r--src/sync-ftfw.c4
-rw-r--r--src/sync-mode.c82
-rw-r--r--src/sync-notrack.c4
16 files changed, 596 insertions, 349 deletions
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@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@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@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;