summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/manual/conntrack-tools.tmpl17
-rw-r--r--doc/sync/notrack/README16
-rw-r--r--doc/sync/notrack/conntrackd.conf120
-rw-r--r--include/Makefile.am2
-rw-r--r--include/channel.h10
-rw-r--r--include/tipc.h59
-rw-r--r--src/Makefile.am2
-rw-r--r--src/channel.c2
-rw-r--r--src/channel_tipc.c144
-rw-r--r--src/read_config_lex.l7
-rw-r--r--src/read_config_yy.y107
-rw-r--r--src/tipc.c252
12 files changed, 653 insertions, 85 deletions
diff --git a/doc/manual/conntrack-tools.tmpl b/doc/manual/conntrack-tools.tmpl
index 4936a76..40c331c 100644
--- a/doc/manual/conntrack-tools.tmpl
+++ b/doc/manual/conntrack-tools.tmpl
@@ -573,20 +573,27 @@ Sync {
</sect3>
<sect3 id="sync-transport-protocol">
-<title>Using UDP, TCP or multicast for flow-state synchronization</title>
+
+<title>Using UDP, multicast, TCP or TIPC for flow-state synchronization</title>
<para>You can use up to three different transport layer protocols to
- synchronize flow-state changes between the firewalls: UDP, TCP and
- Multicast. UDP and multicast are unreliable but together with the FT-FW
- mode provide partial reliable flow-state synchronization.
+ synchronize flow-state changes between the firewalls: UDP, TCP, Multicast and
+TIPC. UDP and multicast are unreliable but together with the FT-FW
+ mode provide partial reliable flow-state synchronization. TIPC provides a
+connectionless yet reliable message-based delivery system.
</para>
- <para>The preferred choice is FT-FW over UDP, or multicast alternatively.
+ <para>The preferred choice is FT-FW over UDP unicast/multicast, or TIPC alternatively.
TCP introduces latency in the flow-state synchronization due to the
congestion control. Under flow-state message are lost, the FIFO delivery
becomes also a problem since the backup firewall quickly gets out of
sync. For that reason, its use is discouraged. Note that using TCP only
makes sense with the NOTRACK mode.
+ TIPC provides some kind of link level sequencing in order to guarantee succesfull
+ delivery of messages between nodes in the cluster. Hence, it is recommended to use it
+ along with NOTRACK mode to minimise protocol overhead on the firewalls dedicated link.
+ Further informations on how to configure TIPC can be found in the README file under
+ the doc/notrack/ directory
</para>
</sect3>
diff --git a/doc/sync/notrack/README b/doc/sync/notrack/README
index b064e21..e7afcc7 100644
--- a/doc/sync/notrack/README
+++ b/doc/sync/notrack/README
@@ -1,3 +1,13 @@
-This directory contains the files for the NOTRACK replication protocol. This
-protocol provides best effort delivery. Therefore, it is unreliable unless
-that you select TCP-based state-synchronization.
+Installation instructions :
+
+TIPC is a built-in kernel module since kernel version 2.6.35 ; please make sure your using a => 2.6.35 kernel with TIPC 2.0, as this patch has not been tested with older versions of the protocol yet.
+
+For easy and fast configuration, you must install the TIPC utilies v2.0.0, available from sources here :
+
+ git://tipc.git.sourceforge.net/gitroot/tipc/tipcutils (branch tipcutils2.0)
+
+or by using aptitude on debian distributions :
+
+ sudo apt-get install tipcutils
+
+For further details on installation, node and network configuration, please refer to the online documentation : http://tipc.sourceforge.net/doc/tipc_2.0_users_guide.html#installation.
diff --git a/doc/sync/notrack/conntrackd.conf b/doc/sync/notrack/conntrackd.conf
index 34e7b32..71946ec 100644
--- a/doc/sync/notrack/conntrackd.conf
+++ b/doc/sync/notrack/conntrackd.conf
@@ -4,6 +4,17 @@
Sync {
Mode NOTRACK {
#
+ # Size of the resend queue (in objects). This is the maximum
+ # number of objects that can be stored waiting to be confirmed
+ # via acknoledgment. If you keep this value low, the daemon
+ # will have less chances to recover state-changes under message
+ # omission. On the other hand, if you keep this value high,
+ # the daemon will consume more memory to store dead objects.
+ # Default is 131072 objects.
+ #
+ # ResendQueueSize 131072
+
+ #
# This parameter allows you to set an initial fixed timeout
# for the committed entries when this node goes from backup
# to primary. This mechanism provides a way to purge entries
@@ -26,14 +37,19 @@ Sync {
#
# PurgeTimeout 60
+ # Set the acknowledgement window size. If you decrease this
+ # value, the number of acknowlegdments increases. More
+ # acknowledgments means more overhead as conntrackd has to
+ # handle more control messages. On the other hand, if you
+ # increase this value, the resend queue gets more populated.
+ # This results in more overhead in the queue releasing.
+ # The following value is based on some practical experiments
+ # measuring the cycles spent by the acknowledgment handling
+ # with oprofile. If not set, default window size is 300.
#
- # This clause allows you to disable the internal cache. Thus,
- # the synchronization messages are directly send through
- # the dedicated link. This option is set of off by default.
- #
- # DisableInternalCache Off
+ # ACKWindowSize 300
- #
+ #
# This clause allows you to disable the external cache. Thus,
# the state entries are directly injected into the kernel
# conntrack table. As a result, you save memory in user-space
@@ -57,33 +73,33 @@ Sync {
# iptables -I INPUT -d 225.0.0.50 -j ACCEPT
# iptables -I OUTPUT -d 225.0.0.50 -j ACCEPT
#
- Multicast {
+ # Multicast {
#
# Multicast address: The address that you use as destination
# in the synchronization messages. You do not have to add
# this IP to any of your existing interfaces. If any doubt,
# do not modify this value.
#
- IPv4_address 225.0.0.50
+ # IPv4_address 225.0.0.50
#
# The multicast group that identifies the cluster. If any
# doubt, do not modify this value.
#
- Group 3780
+ # Group 3780
#
# IP address of the interface that you are going to use to
# send the synchronization messages. Remember that you must
# use a dedicated link for the synchronization messages.
#
- IPv4_interface 192.168.100.100
+ # IPv4_interface 192.168.100.100
#
# The name of the interface that you are going to use to
# send the synchronization messages.
#
- Interface eth2
+ # Interface eth2
# The multicast sender uses a buffer to enqueue the packets
# that are going to be transmitted. The default size of this
@@ -94,10 +110,8 @@ Sync {
# notice some packet loss, you may want to increase the size
# of the sender buffer. The default size is usually around
# ~100 KBytes which is fairly small for busy firewalls.
- # Note: This protocol is best effort, it is really recommended
- # to increase the buffer size.
#
- SndSocketBuffer 1249280
+ # SndSocketBuffer 1249280
# The multicast receiver uses a buffer to enqueue the packets
# that the socket is pending to handle. The default size of this
@@ -106,20 +120,18 @@ Sync {
# receiver queue. The overrun results packet loss, thus, losing
# state information that would have to be retransmitted. If you
# notice some packet loss, you may want to increase the size of
- # of the sender buffer. The default size is usually around
+ # the receiver buffer. The default size is usually around
# ~100 KBytes which is fairly small for busy firewalls.
- # Note: This protocol is best effort, it is really recommended
- # to increase the buffer size.
#
- RcvSocketBuffer 1249280
+ # RcvSocketBuffer 1249280
- #
+ #
# Enable/Disable message checksumming. This is a good
# property to achieve fault-tolerance. In case of doubt, do
# not modify this value.
#
- Checksum on
- }
+ # Checksum on
+ # }
#
# You can specify more than one dedicated link. Thus, if one dedicated
# link fails, conntrackd can fail-over to another. Note that adding
@@ -192,60 +204,37 @@ Sync {
# Checksum on
# }
- #
- # You can also use Unicast TCP to propagate events. Thus, the NOTRACK
- # mode becomes reliable.
- #
- # TCP {
- #
- # TCP address that this firewall uses to listen to events.
- #
- # IPv4_address 192.168.2.100
- #
- # or you may want to use an IPv6 address:
- #
- # IPv6_address fe80::215:58ff:fe28:5a27
-
- #
- # Destination TCP address that receives events, ie. the other
- # firewall's dedicated link address.
+ TIPC {
#
- # IPv4_Destination_Address 192.168.2.101
+ # Name of the other TIPC port in the cluster (in the form type:instance)
#
- # or you may want to use an IPv6 address:
+ TIPC_Destination_Name 1000:51
+
#
- # IPv6_Destination_Address fe80::2d0:59ff:fe2a:775c
-
+ # Name of the local TIPC port (used to listen to events)
#
- # TCP port used
- #
- # Port 3780
+ TIPC_Name 1000:50
#
- # The name of the interface that you are going to use to
- # send the synchronization messages.
- #
- # Interface eth2
-
- #
- # The sender socket buffer size
+ # The name of the TIPC configured interface that you are going to use
+ # to send synchronization messages.
#
- # SndSocketBuffer 1249280
-
+ Interface eth0
+
#
- # The receiver socket buffer size
+ # The importance of the TIPC messages sent (the more important this is, the more packets will be enabled to queue up on the slave)
+ # This should be set to High or Critical to avoid congestion on the receiver side.
+ # (possible values : TIPC_LOW_IMPORTANCE, TIPC_MEDIUM_IMPORTANCE, TIPC_HIGH_IMPORTANCE, TIPC_CRITICAL_IMPROTANCE)
#
- # RcvSocketBuffer 1249280
+ TIPC_Message_Importance TIPC_CRITICAL_IMPORTANCE
- #
- # Enable/Disable message checksumming.
#
- # Checksum on
- # }
+ # Current TIPC implementation doesnt allow checksumming
+ }
- #
+ #
# Other unsorted options that are related to the synchronization.
- #
+ #
# Options {
#
# TCP state-entries have window tracking disabled by default,
@@ -259,9 +248,9 @@ Sync {
# you want to enable. Default is off.
#
# ExpectationSync {
- # ftp
- # h323
- # sip
+ # ftp
+ # h323
+ # sip
# }
#
# You can use this alternatively:
@@ -368,6 +357,7 @@ General {
#
# NetlinkOverrunResync On
+ #
# If you want reliable event reporting over Netlink, set on this
# option. If you set on this clause, it is a good idea to set off
# NetlinkOverrunResync. This option is off by default and you need
diff --git a/include/Makefile.am b/include/Makefile.am
index cbbca6b..6147d6b 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,6 +1,6 @@
noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \
- sync.h conntrackd.h local.h udp.h tcp.h \
+ sync.h conntrackd.h local.h udp.h tcp.h tipc.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 channel.h \
diff --git a/include/channel.h b/include/channel.h
index 9b5fad8..704d384 100644
--- a/include/channel.h
+++ b/include/channel.h
@@ -4,6 +4,7 @@
#include "mcast.h"
#include "udp.h"
#include "tcp.h"
+#include "tipc.h"
struct channel;
struct nethdr;
@@ -13,6 +14,7 @@ enum {
CHANNEL_MCAST,
CHANNEL_UDP,
CHANNEL_TCP,
+ CHANNEL_TIPC,
CHANNEL_MAX,
};
@@ -31,6 +33,11 @@ struct tcp_channel {
struct tcp_sock *server;
};
+struct tipc_channel {
+ struct tipc_sock *client;
+ struct tipc_sock *server;
+};
+
#define CHANNEL_F_DEFAULT (1 << 0)
#define CHANNEL_F_BUFFERED (1 << 1)
#define CHANNEL_F_STREAM (1 << 2)
@@ -41,6 +48,7 @@ union channel_type_conf {
struct mcast_conf mcast;
struct udp_conf udp;
struct tcp_conf tcp;
+ struct tipc_conf tipc;
};
struct channel_conf {
@@ -97,7 +105,7 @@ 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
+#define MULTICHANNEL_MAX 5
struct multichannel {
int channel_num;
diff --git a/include/tipc.h b/include/tipc.h
new file mode 100644
index 0000000..840eae0
--- /dev/null
+++ b/include/tipc.h
@@ -0,0 +1,59 @@
+#ifndef _TIPC_H_
+#define _TIPC_H_
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/tipc.h>
+
+/* TODO: no buffer tuning supported. */
+
+struct tipc_conf {
+ int ipproto;
+ int msgImportance;
+ struct {
+ uint32_t type;
+ uint32_t instance;
+ } client;
+ struct {
+ uint32_t type;
+ uint32_t instance;
+ } server;
+};
+
+struct tipc_stats {
+#ifdef CTD_TIPC_DEBUG
+ uint64_t returned_messages; /* used for debug purposes */
+#endif
+ uint64_t bytes;
+ uint64_t messages;
+ uint64_t error;
+};
+
+struct tipc_sock {
+ int fd;
+ struct sockaddr_tipc addr;
+ socklen_t sockaddr_len;
+ struct tipc_stats stats;
+};
+
+struct tipc_sock *tipc_server_create(struct tipc_conf *conf);
+void tipc_server_destroy(struct tipc_sock *m);
+
+struct tipc_sock *tipc_client_create(struct tipc_conf *conf);
+void tipc_client_destroy(struct tipc_sock *m);
+
+ssize_t tipc_send(struct tipc_sock *m, const void *data, int size);
+ssize_t tipc_recv(struct tipc_sock *m, void *data, int size);
+
+int tipc_get_fd(struct tipc_sock *m);
+int tipc_isset(struct tipc_sock *m, fd_set *readfds);
+
+int tipc_snprintf_stats(char *buf, size_t buflen, char *ifname,
+ struct tipc_stats *s, struct tipc_stats *r);
+
+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);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 7d7b2ac..995912f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,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 channel_udp.c \
+ channel.c multichannel.c channel_mcast.c channel_udp.c tipc.c channel_tipc.c \
tcp.c channel_tcp.c \
external_cache.c external_inject.c \
internal_cache.c internal_bypass.c \
diff --git a/src/channel.c b/src/channel.c
index 818bb01..f362af7 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -24,6 +24,7 @@ static struct channel_ops *ops[CHANNEL_MAX];
extern struct channel_ops channel_mcast;
extern struct channel_ops channel_udp;
extern struct channel_ops channel_tcp;
+extern struct channel_ops channel_tipc;
static struct queue *errorq;
@@ -32,6 +33,7 @@ int channel_init(void)
ops[CHANNEL_MCAST] = &channel_mcast;
ops[CHANNEL_UDP] = &channel_udp;
ops[CHANNEL_TCP] = &channel_tcp;
+ ops[CHANNEL_TIPC] = &channel_tipc;
errorq = queue_create("errorq", CONFIG(channelc).error_queue_length, 0);
if (errorq == NULL) {
diff --git a/src/channel_tipc.c b/src/channel_tipc.c
new file mode 100644
index 0000000..71e3607
--- /dev/null
+++ b/src/channel_tipc.c
@@ -0,0 +1,144 @@
+/*
+ * (C) 2012 by Quentin Aebischer <quentin.aebicher@usherbrooke.ca>
+ *
+ * Derived work based on channel_mcast.c from:
+ *
+ * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (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 "tipc.h"
+
+static void
+*channel_tipc_open(void *conf)
+{
+ struct tipc_channel *m;
+ struct tipc_conf *c = conf;
+
+ m = calloc(sizeof(struct tipc_channel), 1);
+ if (m == NULL)
+ return NULL;
+
+ m->client = tipc_client_create(c);
+ if (m->client == NULL) {
+ free(m);
+ return NULL;
+ }
+
+ m->server = tipc_server_create(c);
+ if (m->server == NULL) {
+ tipc_client_destroy(m->client);
+ free(m);
+ return NULL;
+ }
+ return m;
+}
+
+static int
+channel_tipc_send(void *channel, const void *data, int len)
+{
+ struct tipc_channel *m = channel;
+ return tipc_send(m->client, data, len);
+}
+
+static int
+channel_tipc_recv(void *channel, char *buf, int size)
+{
+ struct tipc_channel *m = channel;
+ return tipc_recv(m->server, buf, size);
+}
+
+static void
+channel_tipc_close(void *channel)
+{
+ struct tipc_channel *m = channel;
+ tipc_client_destroy(m->client);
+ tipc_server_destroy(m->server);
+ free(m);
+}
+
+static int
+channel_tipc_get_fd(void *channel)
+{
+ struct tipc_channel *m = channel;
+ return tipc_get_fd(m->server);
+}
+
+static void
+channel_tipc_stats(struct channel *c, int fd)
+{
+ struct tipc_channel *m = c->data;
+ char ifname[IFNAMSIZ], buf[512];
+ int size;
+
+ if_indextoname(c->channel_ifindex, ifname);
+ size = tipc_snprintf_stats(buf, sizeof(buf), ifname,
+ &m->client->stats, &m->server->stats);
+ send(fd, buf, size, 0);
+}
+
+static void
+channel_tipc_stats_extended(struct channel *c, int active,
+ struct nlif_handle *h, int fd)
+{
+ struct tipc_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 = tipc_snprintf_stats2(buf, sizeof(buf),
+ ifname, status, active,
+ &m->client->stats,
+ &m->server->stats);
+ send(fd, buf, size, 0);
+}
+
+static int
+channel_tipc_isset(struct channel *c, fd_set *readfds)
+{
+ struct tipc_channel *m = c->data;
+ return tipc_isset(m->server, readfds);
+}
+
+static int
+channel_tipc_accept_isset(struct channel *c, fd_set *readfds)
+{
+ return 0;
+}
+
+struct channel_ops channel_tipc = {
+ .headersiz = 60, /* IP header (20 bytes) + tipc unicast name message header 40 (bytes) (see http://tipc.sourceforge.net/doc/tipc_message_formats.html for details) */
+ .open = channel_tipc_open,
+ .close = channel_tipc_close,
+ .send = channel_tipc_send,
+ .recv = channel_tipc_recv,
+ .get_fd = channel_tipc_get_fd,
+ .isset = channel_tipc_isset,
+ .accept_isset = channel_tipc_accept_isset,
+ .stats = channel_tipc_stats,
+ .stats_extended = channel_tipc_stats_extended,
+};
diff --git a/src/read_config_lex.l b/src/read_config_lex.l
index 01fe4fc..ad37600 100644
--- a/src/read_config_lex.l
+++ b/src/read_config_lex.l
@@ -47,6 +47,7 @@ ip6_part {hex_255}":"?
ip6_form1 {ip6_part}{0,16}"::"{ip6_part}{0,16}
ip6_form2 ({hex_255}":"){16}{hex_255}
ip6 {ip6_form1}{ip6_cidr}?|{ip6_form2}{ip6_cidr}?
+tipc_name {integer}":"{integer}
string [a-zA-Z][a-zA-Z0-9\.\-]*
persistent [P|p][E|e][R|r][S|s][I|i][S|s][T|t][E|e][N|n][T|T]
nack [N|n][A|a][C|c][K|k]
@@ -63,9 +64,13 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k]
"IPv4_interface" { return T_IPV4_IFACE; }
"IPv6_interface" { return T_IPV6_IFACE; }
"Interface" { return T_IFACE; }
+"TIPC_Destination_Name" { return T_TIPC_DEST_NAME; }
+"TIPC_Name" { return T_TIPC_NAME; }
+"TIPC_Message_Importance" { return T_TIPC_MESSAGE_IMPORTANCE; }
"Multicast" { return T_MULTICAST; }
"UDP" { return T_UDP; }
"TCP" { return T_TCP; }
+"TIPC" { return T_TIPC; }
"HashSize" { return T_HASHSIZE; }
"RefreshTime" { return T_REFRESH; }
"CacheTimeout" { return T_EXPIRE; }
@@ -149,6 +154,8 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k]
{signed_integer} { yylval.val = atoi(yytext); return T_SIGNED_NUMBER; }
{ip4} { yylval.string = strdup(yytext); return T_IP; }
{ip6} { yylval.string = strdup(yytext); return T_IP; }
+{tipc_name} { yylval.string = strdup(yytext); return T_TIPC_NAME_VAL; }
+
{path} { yylval.string = strdup(yytext); return T_PATH_VAL; }
{alarm} { return T_ALARM; }
{persistent} { fprintf(stderr, "\nWARNING: Now `persistent' mode "
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index b22784c..21d1c20 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -30,6 +30,7 @@
#include "cidr.h"
#include <syslog.h>
#include <sched.h>
+#include <linux/tipc.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
@@ -74,8 +75,9 @@ static void __max_dedicated_links_reached(void);
%token T_SCHEDULER T_TYPE T_PRIO T_NETLINK_EVENTS_RELIABLE
%token T_DISABLE_INTERNAL_CACHE T_DISABLE_EXTERNAL_CACHE T_ERROR_QUEUE_LENGTH
%token T_OPTIONS T_TCP_WINDOW_TRACKING T_EXPECT_SYNC
+%token T_TIPC T_TIPC_DEST_NAME T_TIPC_NAME T_TIPC_MESSAGE_IMPORTANCE
-%token <string> T_IP T_PATH_VAL
+%token <string> T_IP T_PATH_VAL T_TIPC_NAME_VAL
%token <val> T_NUMBER
%token <val> T_SIGNED_NUMBER
%token <string> T_STRING
@@ -150,7 +152,7 @@ syslog_facility : T_SYSLOG T_STRING
if (conf.stats.syslog_facility != -1 &&
conf.syslog_facility != conf.stats.syslog_facility)
- print_err(CTD_CFG_WARN, "conflicting Syslog facility "
+ print_err(CTD_CFG_WARN, "conflicting Syslog facility "
"values, defaulting to General");
};
@@ -309,7 +311,7 @@ multicast_option : T_IPV4_ADDR T_IP
break;
}
- if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) {
+ if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) {
print_err(CTD_CFG_WARN, "your multicast address is IPv4 but "
"is binded to an IPv6 interface? "
"Surely, this is not what you want");
@@ -368,7 +370,7 @@ multicast_option : T_IPV4_IFACE T_IP
break;
}
- if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) {
+ if (conf.channel[conf.channel_num].u.mcast.ipproto == AF_INET6) {
print_err(CTD_CFG_WARN, "your multicast interface is IPv4 but "
"is binded to an IPv6 interface? "
"Surely, this is not what you want");
@@ -381,7 +383,7 @@ multicast_option : T_IPV4_IFACE T_IP
multicast_option : T_IPV6_IFACE T_IP
{
print_err(CTD_CFG_WARN, "`IPv6_interface' not required, ignoring");
-}
+};
multicast_option : T_IFACE T_STRING
{
@@ -440,6 +442,92 @@ multicast_option: T_CHECKSUM T_OFF
conf.channel[conf.channel_num].u.mcast.checksum = 1;
};
+tipc_line : T_TIPC '{' tipc_options '}'
+{
+ if (conf.channel_type_global != CHANNEL_NONE &&
+ conf.channel_type_global != CHANNEL_TIPC) {
+ print_err(CTD_CFG_ERROR, "cannot use `TIPC' with other "
+ "dedicated link protocols!");
+ exit(EXIT_FAILURE);
+ }
+ conf.channel_type_global = CHANNEL_TIPC;
+ conf.channel[conf.channel_num].channel_type = CHANNEL_TIPC;
+ conf.channel[conf.channel_num].channel_flags = CHANNEL_F_BUFFERED;
+ conf.channel_num++;
+};
+
+tipc_line : T_TIPC T_DEFAULT '{' tipc_options '}'
+{
+ if (conf.channel_type_global != CHANNEL_NONE &&
+ conf.channel_type_global != CHANNEL_TIPC) {
+ print_err(CTD_CFG_ERROR, "cannot use `TIPC' with other "
+ "dedicated link protocols!");
+ exit(EXIT_FAILURE);
+ }
+ conf.channel_type_global = CHANNEL_TIPC;
+ conf.channel[conf.channel_num].channel_type = CHANNEL_TIPC;
+ conf.channel[conf.channel_num].channel_flags = CHANNEL_F_DEFAULT |
+ CHANNEL_F_BUFFERED;
+ conf.channel_default = conf.channel_num;
+ conf.channel_num++;
+};
+
+tipc_options :
+ | tipc_options tipc_option;
+
+tipc_option : T_TIPC_DEST_NAME T_TIPC_NAME_VAL
+{
+ __max_dedicated_links_reached();
+
+ if(sscanf($2, "%d:%d", &conf.channel[conf.channel_num].u.tipc.client.type, &conf.channel[conf.channel_num].u.tipc.client.instance) != 2) {
+ print_err(CTD_CFG_WARN, "Please enter TIPC name in the form type:instance (ex: 1000:50)");
+ break;
+ }
+ conf.channel[conf.channel_num].u.tipc.ipproto = AF_TIPC;
+};
+
+tipc_option : T_TIPC_NAME T_TIPC_NAME_VAL
+{
+ __max_dedicated_links_reached();
+
+ if(sscanf($2, "%d:%d", &conf.channel[conf.channel_num].u.tipc.server.type, &conf.channel[conf.channel_num].u.tipc.server.instance) != 2) {
+ print_err(CTD_CFG_WARN, "Please enter TIPC name in the form type:instance (ex: 1000:50)");
+ break;
+ }
+ conf.channel[conf.channel_num].u.tipc.ipproto = AF_TIPC;
+};
+
+tipc_option : T_IFACE T_STRING
+{
+ unsigned int idx;
+
+ __max_dedicated_links_reached();
+
+ strncpy(conf.channel[conf.channel_num].channel_ifname, $2, IFNAMSIZ);
+
+ idx = if_nametoindex($2);
+ if (!idx) {
+ print_err(CTD_CFG_WARN, "%s is an invalid interface", $2);
+ break;
+ }
+};
+
+tipc_option : T_TIPC_MESSAGE_IMPORTANCE T_STRING
+{
+ if(!strcmp("LOW", $2))
+ conf.channel[conf.channel_num].u.tipc.msgImportance = TIPC_LOW_IMPORTANCE;
+ if(!strcmp("MEDIUM", $2))
+ conf.channel[conf.channel_num].u.tipc.msgImportance = TIPC_MEDIUM_IMPORTANCE;
+ if(!strcmp("HIGH", $2))
+ conf.channel[conf.channel_num].u.tipc.msgImportance = TIPC_HIGH_IMPORTANCE;
+ if(!strcmp("CRITICAL", $2))
+ conf.channel[conf.channel_num].u.tipc.msgImportance = TIPC_CRITICAL_IMPORTANCE;
+ if(conf.channel[conf.channel_num].u.tipc.msgImportance < TIPC_LOW_IMPORTANCE || conf.channel[conf.channel_num].u.tipc.msgImportance > TIPC_CRITICAL_IMPORTANCE) {
+ print_err(CTD_CFG_WARN, "%s is an invalid message importance level (defaulting to TIPC_HIGH_IMPORTANCE)", $2);
+ conf.channel[conf.channel_num].u.tipc.msgImportance = TIPC_HIGH_IMPORTANCE;
+ }
+};
+
udp_line : T_UDP '{' udp_options '}'
{
if (conf.channel_type_global != CHANNEL_NONE &&
@@ -800,6 +888,7 @@ sync_line: refreshtime
| multicast_line
| udp_line
| tcp_line
+ | tipc_line
| relax_transitions
| delay_destroy_msgs
| sync_mode_alarm
@@ -861,7 +950,7 @@ option: T_EXPECT_SYNC '{' expect_list '}'
};
expect_list:
- | expect_list expect_item ;
+ | expect_list expect_item ;
expect_item: T_STRING
{
@@ -887,8 +976,8 @@ sync_mode_alarm_list:
| sync_mode_alarm_list sync_mode_alarm_line;
sync_mode_alarm_line: refreshtime
- | expiretime
- | timeout
+ | expiretime
+ | timeout
| purge
| relax_transitions
| delay_destroy_msgs
@@ -1020,7 +1109,7 @@ tcp_state: T_ESTABLISHED
TCP_CONNTRACK_ESTABLISHED);
__kernel_filter_add_state(TCP_CONNTRACK_ESTABLISHED);
-};
+}
tcp_state: T_FIN_WAIT
{
ct_filter_add_state(STATE(us_filter),
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;
+}