summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
6 files changed, 504 insertions, 10 deletions
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;
+}