summaryrefslogtreecommitdiff
path: root/src/tipc.c
diff options
context:
space:
mode:
authorQuentin Aebischer <quentin.aebischer@usherbrooke.ca>2012-02-13 15:47:10 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2012-02-14 00:08:15 +0100
commit5f75e067a0883a7e4128fefb46b74b71b0928d27 (patch)
treef00b2d321347a8d2c4d9c653757191e97a796baf /src/tipc.c
parent167eb3e2028561ab2cc0f2b7b6ff9d24c56514f6 (diff)
downloadconntrack-tools-tipc.tar.gz
conntrackd: basic TIPC supporttipc
Basic implementation of a TIPC channel for the conntrackd daemon (successfully tested in NOTRACK and FTFW modes). TIPC is a protocol that allows applications in a cluster-based environment to communicate quickly and reliably with other applications in the cluster. It allows both unicast and multicast, reliable/unreliable and datagram/stream oriented communications. One of its main feature's of interest here is to provide sockets that communicates in a connectionless, yet reliable manner that guarantees delivery of every message sent over the network. This can be useful in the context of high-available, cluster-based firewalls where states propagation has to be both fast and reliable. So far, the results are encouraging, though more tests have to performed on different setups to enhance the implementation and track any bugs. An example config file can be found in the doc/sync/ directory of the conntrack-tools, along with a README file providing basic installation instructions. Signed-off-by: Quentin Aebischer <quentin.aebischer@usherbrooke.ca>
Diffstat (limited to 'src/tipc.c')
-rw-r--r--src/tipc.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/tipc.c b/src/tipc.c
new file mode 100644
index 0000000..37f6128
--- /dev/null
+++ b/src/tipc.c
@@ -0,0 +1,252 @@
+/*
+ *
+ * (C) 2012 by Quentin Aebischer <quentin.aebicher@usherbrooke.ca>
+ *
+ * Derived work based on mcast.c from:
+ *
+ * (C) 2006-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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Description: tipc socket library
+ */
+
+
+#include "tipc.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+#include <limits.h>
+#include <libnfnetlink/libnfnetlink.h>
+
+#ifdef CTD_TIPC_DEBUG
+#include <fcntl.h> /* used for debug purposes */
+#endif
+
+struct tipc_sock *tipc_server_create(struct tipc_conf *conf)
+{
+ struct tipc_sock *m;
+
+#ifdef CTD_TIPC_DEBUG
+ int val = 0;
+#endif
+
+ m = (struct tipc_sock *) malloc(sizeof(struct tipc_sock));
+ if (!m)
+ return NULL;
+ memset(m, 0, sizeof(struct tipc_sock));
+ m->sockaddr_len = sizeof(struct sockaddr_tipc);
+
+ m->addr.family = AF_TIPC;
+ m->addr.addrtype = TIPC_ADDR_NAME;
+ m->addr.scope = TIPC_CLUSTER_SCOPE;
+ m->addr.addr.name.name.type = conf->server.type;
+ m->addr.addr.name.name.instance = conf->server.instance;
+
+ if ((m->fd = socket(AF_TIPC, SOCK_RDM, 0)) == -1) {
+ free(m);
+ return NULL;
+ }
+
+#ifdef CTD_TIPC_DEBUG
+ setsockopt(m->fd, SOL_TIPC, TIPC_DEST_DROPPABLE, &val, sizeof(val)); /*used for debug purposes */
+#endif
+ if (bind(m->fd, (struct sockaddr *) &m->addr, m->sockaddr_len) == -1) {
+ close(m->fd);
+ free(m);
+ return NULL;
+ }
+
+ return m;
+}
+
+void tipc_server_destroy(struct tipc_sock *m)
+{
+ close(m->fd);
+ free(m);
+}
+
+struct tipc_sock *tipc_client_create(struct tipc_conf *conf)
+{
+ struct tipc_sock *m;
+
+ m = (struct tipc_sock *) malloc(sizeof(struct tipc_sock));
+ if (!m)
+ return NULL;
+ memset(m, 0, sizeof(struct tipc_sock));
+
+ m->addr.family = AF_TIPC;
+ m->addr.addrtype = TIPC_ADDR_NAME;
+ m->addr.addr.name.name.type = conf->client.type;
+ m->addr.addr.name.name.instance = conf->client.instance;
+ m->addr.addr.name.domain = 0;
+ m->sockaddr_len = sizeof(struct sockaddr_tipc);
+
+ if ((m->fd = socket(AF_TIPC, SOCK_RDM, 0)) == -1) {
+ free(m);
+ return NULL;
+ }
+
+#ifdef CTD_TIPC_DEBUG
+ setsockopt(m->fd, SOL_TIPC, TIPC_DEST_DROPPABLE, &val, sizeof(val));
+ fcntl(m->fd, F_SETFL, O_NONBLOCK);
+#endif
+ setsockopt(m->fd, SOL_TIPC, TIPC_IMPORTANCE, &conf->msgImportance, sizeof(conf->msgImportance));
+
+ return m;
+}
+
+void tipc_client_destroy(struct tipc_sock *m)
+{
+ close(m->fd);
+ free(m);
+}
+
+ssize_t tipc_send(struct tipc_sock *m, const void *data, int size)
+{
+ ssize_t ret;
+#ifdef CTD_TIPC_DEBUG
+ char buf[50];
+#endif
+
+ ret = sendto(m->fd,
+ data,
+ size,
+ 0,
+ (struct sockaddr *) &m->addr,
+ m->sockaddr_len);
+ if (ret == -1) {
+ m->stats.error++;
+ return ret;
+ }
+
+#ifdef CTD_TIPC_DEBUG
+ if(!recv(m->fd,buf,sizeof(buf),0))
+ m->stats.returned_messages++;
+#endif
+
+ m->stats.bytes += ret;
+ m->stats.messages++;
+
+ return ret;
+}
+
+ssize_t tipc_recv(struct tipc_sock *m, void *data, int size)
+{
+ ssize_t ret;
+ socklen_t sin_size = sizeof(struct sockaddr_in);
+
+ ret = recvfrom(m->fd,
+ data,
+ size,
+ 0,
+ (struct sockaddr *)&m->addr,
+ &sin_size);
+ if (ret == -1) {
+ if (errno != EAGAIN)
+ m->stats.error++;
+ return ret;
+ }
+
+#ifdef CTD_TIPC_DEBUG
+ if (!ret)
+ m->stats.returned_messages++;
+#endif
+
+ m->stats.bytes += ret;
+ m->stats.messages++;
+
+ return ret;
+}
+
+int tipc_get_fd(struct tipc_sock *m)
+{
+ return m->fd;
+}
+
+int tipc_isset(struct tipc_sock *m, fd_set *readfds)
+{
+ return FD_ISSET(m->fd, readfds);
+}
+
+int
+tipc_snprintf_stats(char *buf, size_t buflen, char *ifname,
+ struct tipc_stats *s, struct tipc_stats *r)
+{
+ size_t size;
+
+ size = snprintf(buf, buflen, "tipc traffic (active device=%s):\n"
+ "%20llu Bytes sent "
+ "%20llu Bytes recv\n"
+ "%20llu Pckts sent "
+ "%20llu Pckts recv\n"
+ "%20llu Error send "
+ "%20llu Error recv\n",
+#ifdef CTD_TIPC_DEBUG
+ "%20llu Returned messages\n\n",
+#endif
+ ifname,
+ (unsigned long long)s->bytes,
+ (unsigned long long)r->bytes,
+ (unsigned long long)s->messages,
+ (unsigned long long)r->messages,
+ (unsigned long long)s->error,
+ (unsigned long long)r->error)
+#ifdef CTD_TIPC_DEBUG
+ (unsigned long long)s->returned_messages);
+#else
+ ;
+#endif
+ return size;
+}
+
+int
+tipc_snprintf_stats2(char *buf, size_t buflen, const char *ifname,
+ const char *status, int active,
+ struct tipc_stats *s, struct tipc_stats *r)
+{
+ size_t size;
+
+ size = snprintf(buf, buflen,
+ "tipc traffic device=%s status=%s role=%s:\n"
+ "%20llu Bytes sent "
+ "%20llu Bytes recv\n"
+ "%20llu Pckts sent "
+ "%20llu Pckts recv\n"
+ "%20llu Error send "
+ "%20llu Error recv\n",
+#ifdef CTD_TIPC_DEBUG
+ "%20llu Returned messages\n\n",
+#endif
+ ifname, status, active ? "ACTIVE" : "BACKUP",
+ (unsigned long long)s->bytes,
+ (unsigned long long)r->bytes,
+ (unsigned long long)s->messages,
+ (unsigned long long)r->messages,
+ (unsigned long long)s->error,
+ (unsigned long long)r->error);
+#ifdef CTD_TIPC_DEBUG
+ (unsigned long long)s->returned_messages);
+#else
+ ;
+#endif
+ return size;
+}