diff --git a/build-aux/update-copyright.sh b/build-aux/update-copyright.sh
index d5c256ae..82f9c4d4 100755
--- a/build-aux/update-copyright.sh
+++ b/build-aux/update-copyright.sh
@@ -1,28 +1,29 @@
 #!/bin/bash
 #
 # Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 # script to update copyright dates across the tree
 
-input=$(grep -ril -e "Copyright.*Red Hat" |grep -v .swp)
+enddate=$(date +%Y)
+
+input=$(grep -ril -e "Copyright.*Red Hat" |grep -v .swp |grep -v update-copyright)
 for i in $input; do
-	startdate=$(git log "$i" | grep ^Date: | tail -n 1 | awk '{print $6}')
-	enddate=$(git log "$i" | grep ^Date: | head -n 1 | awk '{print $6}')
+	startdate=$(git log --follow "$i" | grep ^Date: | tail -n 1 | awk '{print $6}')
 	if [ "$startdate" != "$enddate" ]; then
 		sed -i -e 's#Copyright (C).*Red Hat#Copyright (C) '$startdate'-'$enddate' Red Hat#g' $i
 	else
 		sed -i -e 's#Copyright (C).*Red Hat#Copyright (C) '$startdate' Red Hat#g' $i
 	fi
 done
 
 input=$(find . -type f |grep -v ".git")
 for i in $input; do
 	if [ -z "$(grep -i "Copyright" $i)" ]; then
 		echo "WARNING: $i appears to be missing Copyright information"
 	fi
 done
diff --git a/init/Makefile.am b/init/Makefile.am
index 23c71e04..ed74d2ea 100644
--- a/init/Makefile.am
+++ b/init/Makefile.am
@@ -1,47 +1,47 @@
 #
-# Copyright (C) 2012-2016 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 MAINTAINERCLEANFILES	= Makefile.in
 
 include $(top_srcdir)/build-aux/check.mk
 
 EXTRA_DIST		= kronosnetd.in kronosnetd.service.in \
 			  kronosnetd.default
 
 if BUILD_KRONOSNETD
 
 systemdconfdir		= $(SYSTEMDDIR)
 systemdconf_DATA	= kronosnetd.service
 
 initscriptdir		= $(INITDDIR)
 initscript_SCRIPTS	= kronosnetd
 
 %: %.in Makefile
 	rm -f $@-t $@
 	cat $< | sed \
 		-e 's#@''SBINDIR@#$(sbindir)#g' \
 		-e 's#@''SYSCONFDIR@#$(sysconfdir)#g' \
 		-e 's#@''INITDDIR@#$(INITDDIR)#g' \
 		-e 's#@''LOCALSTATEDIR@#$(localstatedir)#g' \
 	    > $@-t
 	mv $@-t $@
 
 install-exec-local:
 	$(INSTALL) -d $(DESTDIR)/$(INITDEFAULTDIR)
 	$(INSTALL) -m 644 $(srcdir)/kronosnetd.default $(DESTDIR)/$(INITDEFAULTDIR)/kronosnetd
 
 uninstall-local:
 	rm -f $(DESTDIR)/$(INITDEFAULTDIR)/kronosnetd
 	rmdir $(DESTDIR)/$(INITDEFAULTDIR) || :;
 
 all-local: $(initscript_SCRIPTS) $(systemdconf_DATA)
 
 clean-local:
 	rm -rf $(initscript_SCRIPTS) $(systemdconf_DATA)
 
 endif
diff --git a/init/kronosnetd.in b/init/kronosnetd.in
index d879d89e..0edeb987 100644
--- a/init/kronosnetd.in
+++ b/init/kronosnetd.in
@@ -1,152 +1,152 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2012-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 # chkconfig: - 20 80
 # description: kronosnetd vpn daemon
 # processname: kronosnetd
 #
 ### BEGIN INIT INFO
 # Provides:		kronosnetd
 # Required-Start:	$network $remote_fs $syslog
 # Required-Stop:	$network $remote_fs $syslog
 # Default-Start:	2 3 4 5
 # Default-Stop:
 # Short-Description:	Starts and stops kronosnetd vpn daemon.
 # Description:		Starts and stops kronosnetd vpn daemon.
 ### END INIT INFO
 
 desc="kronosnetd"
 prog="kronosnetd"
 
 # set secure PATH
 PATH="/sbin:/bin:/usr/sbin:/usr/bin:@SBINDIR@"
 
 success()
 {
 	echo -ne "[  OK  ]\r"
 }
 
 failure()
 {
 	echo -ne "[FAILED]\r"
 }
 
 status()
 {
 	pid=$(pidof $1 2>/dev/null)
 	rtrn=$?
 	if [ $rtrn -ne 0 ]; then
 		echo "$1 is stopped"
 	else
 		echo "$1 (pid $pid) is running..."
 	fi
 	return $rtrn
 }
 
 # rpm based distros
 if [ -d @SYSCONFDIR@/sysconfig ]; then
 	[ -f @INITDDIR@/functions ] && . @INITDDIR@/functions
 	[ -f @SYSCONFDIR@/sysconfig/$prog ] && . @SYSCONFDIR@/sysconfig/$prog
 	[ -z "$LOCK_FILE" ] && LOCK_FILE="@LOCALSTATEDIR@/lock/subsys/$prog"
 fi
 
 # deb based distros
 if [ -d @SYSCONFDIR@/default ]; then
 	[ -f @SYSCONFDIR@/default/$prog ] && . @SYSCONFDIR@/default/$prog
 	[ -z "$LOCK_FILE" ] && LOCK_FILE="@LOCALSTATEDIR@/lock/$prog"
 fi
 
 # The version of __pids_pidof in /etc/init.d/functions calls pidof with -x
 # This means it matches scripts, including this one.
 # Redefine it here so that status (from the same file) works.
 # Otherwise simultaneous calls to stop() will loop forever
 __pids_pidof() {
         pidof -c -o $$ -o $PPID -o %PPID "$1" || \
                 pidof -c -o $$ -o $PPID -o %PPID "${1##*/}"
 }
 
 start()
 {
 	echo -n "Starting $desc ($prog): "
 
 	# most recent distributions use tmpfs for @LOCALSTATEDIR@/run
 	# to avoid to clean it up on every boot.
 	# they also assume that init scripts will create
 	# required subdirectories for proper operations
 	mkdir -p @LOCALSTATEDIR@/run
 
 	if status $prog > /dev/null 2>&1; then
 		success
 	else
 		$prog $KNETD_OPTS > /dev/null 2>&1
 		touch $LOCK_FILE
 		success
 	fi
 	echo
 }
 
 stop()
 {
 	! status $prog > /dev/null 2>&1 && return
 
 	echo -n "Signaling $desc ($prog) to terminate: "
 	kill -TERM $(pidof $prog) > /dev/null 2>&1
 	success
 	echo
 
 	echo -n "Waiting for $prog to unload:"
 	while status $prog > /dev/null 2>&1; do
 		sleep 1
 		echo -n "."
 	done
 
 	rm -f $LOCK_FILE
 	success
 	echo
 }
 
 restart()
 {
 	stop
 	start
 }
 
 rtrn=0
 
 case "$1" in
 start)
 	start
 	rtrn=$?
 ;;
 restart|reload|force-reload)
 	restart
 	rtrn=$?
 ;;
 condrestart|try-restart)
 	if status $prog > /dev/null 2>&1; then
 		restart
 		rtrn=$?
 	fi
 ;;
 status)
 	status $prog
 	rtrn=$?
 ;;
 stop)
 	stop
 	rtrn=$?
 ;;
 *)
 	echo "usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}"
 	rtrn=2
 ;;
 esac
 
 exit $rtrn
diff --git a/kronosnetd/cfg.c b/kronosnetd/cfg.c
index 02d200ed..1d9074c1 100644
--- a/kronosnetd/cfg.c
+++ b/kronosnetd/cfg.c
@@ -1,88 +1,88 @@
 /*
- * Copyright (C) 2012-2015 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <pthread.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "cfg.h"
 #include "libtap.h"
 
 struct knet_cfg *knet_get_iface(const char *name, int create)
 {
 	struct knet_cfg *knet_iface = knet_cfg_head.knet_cfg;
 	int found = 0;
 
 	while (knet_iface != NULL) {
 		if (!strcmp(tap_get_name(knet_iface->cfg_eth.tap), name)) {
 			found = 1;
 			break;
 		}
 		knet_iface = knet_iface->next;
 	}
 
 	if ((!found) && (create)) {
 		knet_iface = malloc(sizeof(struct knet_cfg));
 		if (!knet_iface)
 			goto out_clean;
 
 		memset(knet_iface, 0, sizeof(struct knet_cfg));
 
 		knet_iface->cfg_ring.base_port = KNET_RING_DEFPORT;
 
 		strncpy(knet_iface->knet_handle_crypto_cfg.crypto_model,
 			"none",
 			sizeof(knet_iface->knet_handle_crypto_cfg.crypto_model) - 1);
 
 		strncpy(knet_iface->knet_handle_crypto_cfg.crypto_cipher_type,
 			"none",
 			sizeof(knet_iface->knet_handle_crypto_cfg.crypto_cipher_type) - 1);
 
 		strncpy(knet_iface->knet_handle_crypto_cfg.crypto_hash_type,
 			"none",
 			sizeof(knet_iface->knet_handle_crypto_cfg.crypto_hash_type) - 1);
 
 		if (knet_cfg_head.knet_cfg) {
 			struct knet_cfg *knet_iface_last = knet_cfg_head.knet_cfg;
 
 			while (knet_iface_last->next != NULL) {
 				knet_iface_last = knet_iface_last->next;
 			}
 			knet_iface_last->next = knet_iface;
 		} else {
 			knet_cfg_head.knet_cfg = knet_iface;
 		}
 	}
 
 out_clean:
 
 	return knet_iface;
 }
 
 void knet_destroy_iface(struct knet_cfg *knet_iface)
 {
 	struct knet_cfg *knet_iface_tmp = knet_cfg_head.knet_cfg;
 	struct knet_cfg *knet_iface_prev = knet_cfg_head.knet_cfg;
 
 	while (knet_iface_tmp != knet_iface) {
 		knet_iface_prev = knet_iface_tmp;
 		knet_iface_tmp = knet_iface_tmp->next;
 	}
 
 	if (knet_iface_tmp == knet_iface) {
 		if (knet_iface_tmp == knet_iface_prev) {
 			knet_cfg_head.knet_cfg = knet_iface_tmp->next;
 		} else {
 			knet_iface_prev->next = knet_iface_tmp->next;
 		}
 		free(knet_iface);
 	}
 }
diff --git a/kronosnetd/cfg.h b/kronosnetd/cfg.h
index 99a9d217..f046e96a 100644
--- a/kronosnetd/cfg.h
+++ b/kronosnetd/cfg.h
@@ -1,55 +1,55 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNETD_CFG_H__
 #define __KNETD_CFG_H__
 
 #include <stdint.h>
 #include <net/if.h>
 
 #include "libtap.h"
 #include "libknet.h"
 
 #define KNET_RING_DEFPORT 50000
 
 struct knet_cfg_eth {
 	tap_t tap;
 	int auto_mtu;
 	knet_node_id_t node_id;
 };
 
 struct knet_cfg_ring {
 	knet_handle_t knet_h;
 	int data_mtu;
 	int base_port;
 };
 
 struct knet_cfg {
 	struct knet_cfg_eth cfg_eth;
 	struct knet_cfg_ring cfg_ring;
 	int active;
 	struct knet_handle_crypto_cfg knet_handle_crypto_cfg;
 	struct knet_cfg *next;
 };
 
 struct knet_cfg_top {
 	char *conffile;
 	char *logfile;
 	char *vty_ipv4;
 	char *vty_ipv6;
 	char *vty_port;
 	struct knet_cfg *knet_cfg;
 };
 
 struct knet_cfg *knet_get_iface(const char *name, const int create);
 void knet_destroy_iface(struct knet_cfg *knet_iface);
 
 extern struct knet_cfg_top knet_cfg_head;
 
 #endif
diff --git a/kronosnetd/knet-keygen.8 b/kronosnetd/knet-keygen.8
index 4e30ba20..d272b0c7 100644
--- a/kronosnetd/knet-keygen.8
+++ b/kronosnetd/knet-keygen.8
@@ -1,28 +1,28 @@
 .\"/*
-.\" * Copyright (C) 2012-2015 Red Hat, Inc.
+.\" * Copyright (C) 2012-2017 Red Hat, Inc.
 .\" *
 .\" * All rights reserved.
 .\" *
 .\" * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 .\" *
 .\" * This software licensed under GPL-2.0+, LGPL-2.0+
 .\" */
 .TH "KRONOSNETD" "8" "November 2012" "kronosnetd key generator." "System Administration Utilities"
 
 .SH "NAME"
 knet\-keygen \- Tool to generate keys for kronosnetd.
 
 .SH "SYNOPSIS"
 .B knet\-keygen
 \fB\-o\fR <output_file> [\-s <size>]
 
 .SH "OPTIONS"
 .TP
 \fB\-o\fR
 Output file
 .TP
 \fB\-s\fR
 Key size (value between 1024 and 4096 included)
 
 .SH "SEE ALSO"
 kronosnetd(8)
diff --git a/kronosnetd/kronosnetd.8 b/kronosnetd/kronosnetd.8
index b34de276..110d8c37 100644
--- a/kronosnetd/kronosnetd.8
+++ b/kronosnetd/kronosnetd.8
@@ -1,51 +1,51 @@
 .\"/*
-.\" * Copyright (C) 2012-2015 Red Hat, Inc.
+.\" * Copyright (C) 2012-2017 Red Hat, Inc.
 .\" *
 .\" * All rights reserved.
 .\" *
 .\" * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 .\" *
 .\" * This software licensed under GPL-2.0+, LGPL-2.0+
 .\" */
 .TH "KRONOSNETD" "8" "November 2012" "kronosnetd Usage:" "System Administration Utilities"
 
 .SH "NAME"
 kronosnetd \- libknet management daemon
 
 .SH "DESCRIPTION"
 Usage:
 .PP
 kronosnetd [options]
 
 .SH "OPTIONS"
 
 .TP
 \fB\-a\fR <ipv6_addr>
 Bind management VTY to ipv6_addr (default: localhost)
 .TP
 \fB\-b\fR <ipv4_addr>
 Bind management VTY to ipv4_addr (default: localhost)
 .TP
 \fB\-p\fR <port>
 Bind management VTY to port (default 50000)
 .TP
 \fB\-c\fR <file>
 Use config file (default /etc/kronosnet/kronosnetd.conf)
 .TP
 \fB\-l\fR <file>
 Use log file (default /var/log//kronosnetd.log)
 .TP
 \fB\-f\fR
 Do not fork in background
 .TP
 \fB\-d\fR
 Enable debugging output
 .TP
 \fB\-h\fR
 This help
 .TP
 \fB\-V\fR
 Print program version information
 
 .SH "SEE ALSO"
 knet-keygen(8)
diff --git a/kronosnetd/kronosnetd.logrotate.in b/kronosnetd/kronosnetd.logrotate.in
index acfd331d..af4a113e 100644
--- a/kronosnetd/kronosnetd.logrotate.in
+++ b/kronosnetd/kronosnetd.logrotate.in
@@ -1,17 +1,17 @@
 #
-# Copyright (C) 2012-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 @LOGDIR@kronosnetd.log {
 	missingok
 	compress
 	copytruncate
 	daily
 	rotate 31
 	minsize 2048
 	notifempty
 }
diff --git a/kronosnetd/logging.c b/kronosnetd/logging.c
index d041a2ad..a1006a6a 100644
--- a/kronosnetd/logging.c
+++ b/kronosnetd/logging.c
@@ -1,55 +1,55 @@
 /*
- * Copyright (C) 2012-2015 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include "logging.h"
 
 void logging_init_defaults(int debug, int daemonize, const char *logfile)
 {
 	int level = SYSLOGLEVEL;
 	int32_t filetarget;
 
 	if (debug) {
 		level = LOG_DEBUG;
 	}
 
 	qb_log_init(PACKAGE "d", SYSLOGFACILITY, level);
 
 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
 	if (debug) {
 		qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP,
 			   LOG_INFO - LOG_DEBUG);
 	}
 
 	/*
 	 * initialize stderr output only if we are not forking in background
 	 */
 	if (!daemonize) {
 		qb_log_format_set(QB_LOG_STDERR, "%t %N [%p]: %b");
 		qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
 		qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
 				  QB_LOG_FILTER_FUNCTION, "*", level);
 	}
 
 	filetarget = qb_log_file_open(logfile);
 	qb_log_ctl(filetarget, QB_LOG_CONF_ENABLED, QB_TRUE);
 	qb_log_format_set(filetarget, "%t %N [%p]: %b");
 	qb_log_filter_ctl(filetarget, QB_LOG_FILTER_ADD,
 			  QB_LOG_FILTER_FUNCTION, "*", level);
 
 	qb_log_thread_start();
 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE);
 	qb_log_ctl(filetarget, QB_LOG_CONF_THREADED, QB_TRUE);
 }
 
 void logging_fini(void)
 {
 	qb_log_fini();
 }
diff --git a/kronosnetd/logging.h b/kronosnetd/logging.h
index 6ab6acbc..61cc96c0 100644
--- a/kronosnetd/logging.h
+++ b/kronosnetd/logging.h
@@ -1,29 +1,29 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNETD_LOGGING_H__
 #define __KNETD_LOGGING_H__
 
 #include <qb/qblog.h>
 
 #define log_debug(fmt, args...) qb_log(LOG_DEBUG, "(%s:%i|%s): " fmt, __FILE__, __LINE__, __FUNCTION__, ##args);
 
 #define log_kdebug(fmt, args...) qb_log(LOG_DEBUG, fmt, ##args);
 
 #define log_info(fmt, args...) qb_log(LOG_INFO, fmt, ##args);
 
 #define log_warn(fmt, args...) qb_log(LOG_WARNING, fmt, ##args);
 
 #define log_error(fmt, args...) qb_log(LOG_ERR, fmt, ##args);
 
 void logging_init_defaults(int debug, int daemonize, const char *logfile);
 
 void logging_fini(void);
 
 #endif
diff --git a/kronosnetd/main.c b/kronosnetd/main.c
index 39cc2d58..34403a2f 100644
--- a/kronosnetd/main.c
+++ b/kronosnetd/main.c
@@ -1,347 +1,347 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <sched.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 
 #include "cfg.h"
 #include "vty.h"
 #include "logging.h"
 
 #define LOCKFILE_NAME RUNDIR PACKAGE "d.pid"
 
 #define OPTION_STRING "hdfVc:l:a:b:p:"
 
 static int debug = 0;
 static int daemonize = 1;
 
 struct knet_cfg_top knet_cfg_head;
 
 static void print_usage(void)
 {
 	printf("Usage:\n\n");
 	printf(PACKAGE "d [options]\n\n");
 	printf("Options:\n\n");
 	printf("  -a <ipv6_addr> Bind management VTY to ipv6_addr (default: localhost)\n");
 	printf("  -b <ipv4_addr> Bind management VTY to ipv4_addr (default: localhost)\n");
 	printf("  -p <port>      Bind management VTY to port (default %d)\n",
 		KNET_VTY_DEFAULT_PORT);
 	printf("  -c <file>      Use config file (default "DEFAULT_CONFIG_FILE")\n");
 	printf("  -l <file>      Use log file (default "DEFAULT_LOG_FILE")\n");
 	printf("  -f             Do not fork in background\n");
 	printf("  -d             Enable debugging output\n");
 	printf("  -h             This help\n");
 	printf("  -V             Print program version information\n");
 	return;
 }
 
 static int read_arguments(int argc, char **argv)
 {
 	int cont = 1;
 	int optchar;
 	int int_port;
 
 	while (cont) {
 		optchar = getopt(argc, argv, OPTION_STRING);
 
 		switch (optchar) {
 
 		case 'a':
 			knet_cfg_head.vty_ipv6 = strdup(optarg);
 			if (!knet_cfg_head.vty_ipv6)
 				return -1;
 			break;
 
 		case 'b':
 			knet_cfg_head.vty_ipv4 = strdup(optarg);
 			if (!knet_cfg_head.vty_ipv4)
 				return -1;
 			break;
 
 		case 'p':
 			int_port = atoi(optarg);
 			if ((int_port < 0) || (int_port > 65535)) {
 				errno = EINVAL;
 				return -1;
 			}
 			knet_cfg_head.vty_port = strdup(optarg);
 			if (!knet_cfg_head.vty_port)
 				return -1;
 			break;
 
 		case 'c':
 			knet_cfg_head.conffile = strdup(optarg);
 			if (!knet_cfg_head.conffile)
 				return -1;
 			break;
 
 		case 'l':
 			knet_cfg_head.logfile = strdup(optarg);
 			if (!knet_cfg_head.logfile)
 				return -1;
 			break;
 
 		case 'd':
 			debug = 1;
 			break;
 
 		case 'f':
 			daemonize = 0;
 			break;
 
 		case 'h':
 			print_usage();
 			exit(EXIT_SUCCESS);
 			break;
 
 		case 'V':
 			printf(PACKAGE "d " PACKAGE_VERSION " (built " __DATE__
 			       " " __TIME__ ")\n");
 			exit(EXIT_SUCCESS);
 			break;
 
 		case EOF:
 			cont = 0;
 			break;
 
 		default:
 			fprintf(stderr, "unknown option: %c\n", optchar);
 			print_usage();
 			exit(EXIT_FAILURE);
 			break;
 
 		}
 	}
 	return 0;
 }
 
 static int set_scheduler(void)
 {
 	struct sched_param sched_param;
 	int err;
 
 	err = sched_get_priority_max(SCHED_RR);
 	if (err < 0) {
 		log_warn("Could not get maximum scheduler priority");
 		return err;
 	}
 
 	sched_param.sched_priority = err;
 	err = sched_setscheduler(0, SCHED_RR, &sched_param);
 	if (err < 0)
 		log_warn("could not set SCHED_RR priority %d",
 			   sched_param.sched_priority);
 
 	return err;
 }
 
 static void remove_lockfile(void)
 {
 	unlink(LOCKFILE_NAME);
 }
 
 static int create_lockfile(const char *lockfile)
 {
 	int fd, value;
 	size_t bufferlen;
 	ssize_t write_out;
 	struct flock lock;
 	char buffer[50];
 
 	if ((fd = open(lockfile, O_CREAT | O_WRONLY,
 		       (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
 		fprintf(stderr, "Cannot open lockfile [%s], error was [%s]\n",
 			lockfile, strerror(errno));
 		return -1;
 	}
 
 	lock.l_type = F_WRLCK;
 	lock.l_start = 0;
 	lock.l_whence = SEEK_SET;
 	lock.l_len = 0;
 
 retry_fcntl:
 
 	if (fcntl(fd, F_SETLK, &lock) < 0) {
 		switch (errno) {
 		case EINTR:
 			goto retry_fcntl;
 			break;
 		case EACCES:
 		case EAGAIN:
 			fprintf(stderr, "Cannot lock lockfile [%s], error was [%s]\n",
 				lockfile, strerror(errno));
 			break;
 		default:
 			fprintf(stderr, "process is already running\n");
 		}
 
 		goto fail_close;
 	}
 
 	if (ftruncate(fd, 0) < 0) {
 		fprintf(stderr, "Cannot truncate pidfile [%s], error was [%s]\n",
 			lockfile, strerror(errno));
 
 		goto fail_close_unlink;
 	}
 
 	memset(buffer, 0, sizeof(buffer));
 	snprintf(buffer, sizeof(buffer)-1, "%d\n", getpid());
 
 	bufferlen = strlen(buffer);
 	write_out = write(fd, buffer, bufferlen);
 
 	if ((write_out < 0) || (write_out == 0 && errno)) {
 		fprintf(stderr, "Cannot write pid to pidfile [%s], error was [%s]\n",
 			lockfile, strerror(errno));
 
 		goto fail_close_unlink;
 	}
 
 	if ((write_out == 0) || ((size_t)write_out < bufferlen)) {
 		fprintf(stderr, "Cannot write pid to pidfile [%s], shortwrite of"
 				"[%zd] bytes, expected [%zu]\n",
 				lockfile, write_out, bufferlen);
 
 		goto fail_close_unlink;
 	}
 
 	if ((value = fcntl(fd, F_GETFD, 0)) < 0) {
 		fprintf(stderr, "Cannot get close-on-exec flag from pidfile [%s], "
 				"error was [%s]\n", lockfile, strerror(errno));
 
 		goto fail_close_unlink;
 	}
 	value |= FD_CLOEXEC;
 	if (fcntl(fd, F_SETFD, value) < 0) {
 		fprintf(stderr, "Cannot set close-on-exec flag from pidfile [%s], "
 				"error was [%s]\n", lockfile, strerror(errno));
 
 		goto fail_close_unlink;
 	}
 
 	atexit(remove_lockfile);
 
 	return 0;
 
 fail_close_unlink:
 	if (unlink(lockfile))
 		fprintf(stderr, "Unable to unlink %s\n", lockfile);
 
 fail_close:
 	if (close(fd))
 		fprintf(stderr, "Unable to close %s file descriptor\n", lockfile);
 	return -1;
 }
 
 static void set_cfg_defaults(void)
 {
 	if (!knet_cfg_head.conffile)
 		knet_cfg_head.conffile = strdup(DEFAULT_CONFIG_FILE);
 	if (!knet_cfg_head.conffile) {
 		fprintf(stderr, "Unable to allocate memory for config file\n");
 		exit(EXIT_FAILURE);
 	}
 
 	if (!knet_cfg_head.logfile)
 		knet_cfg_head.logfile = strdup(DEFAULT_LOG_FILE);
 	if (!knet_cfg_head.conffile) {
 		fprintf(stderr, "Unable to allocate memory for log file\n");
 		exit(EXIT_FAILURE);
 	}
 
 	if (!knet_cfg_head.vty_ipv6)
 		knet_cfg_head.vty_ipv6 = strdup("::1");
 	if (!knet_cfg_head.vty_ipv6) {
 		fprintf(stderr, "Unable to allocate memory for default ip address\n");
 		exit(EXIT_FAILURE);
 	}
 
 	if (!knet_cfg_head.vty_ipv4)
 		knet_cfg_head.vty_ipv4 = strdup("127.0.0.1");
 	if (!knet_cfg_head.vty_ipv4) {
 		fprintf(stderr, "Unable to allocate memory for default ip address\n");
 		exit(EXIT_FAILURE);
 	}
 
 	if (!knet_cfg_head.vty_port) {
 		char portbuf[8];
 		memset(&portbuf, 0, sizeof(portbuf));
 		snprintf(portbuf, sizeof(portbuf), "%d", KNET_VTY_DEFAULT_PORT);
 		knet_cfg_head.vty_port = strdup(portbuf);
 	}
 	if (!knet_cfg_head.vty_port) {
 		fprintf(stderr, "Unable to allocate memory for default port address\n");
 		exit(EXIT_FAILURE);
 	}
 }
 
 int main(int argc, char **argv)
 {
 	int err;
 
 	memset(&knet_cfg_head, 0, sizeof(struct knet_cfg_top));
 
 	if (read_arguments(argc, argv) < 0) {
 		fprintf(stderr, "Unable to parse options\n");
 		exit(EXIT_FAILURE);
 	}
 
 	set_cfg_defaults();
 
 	if (create_lockfile(LOCKFILE_NAME) < 0) {
 		fprintf(stderr, "Unable to create lockfile\n");
 		exit(EXIT_FAILURE);
 	}
 
 	if (daemonize) {
 		if (daemon(0, 0) < 0) {
 			perror("Unable to daemonize");
 			exit(EXIT_FAILURE);
 		}
 	}
 
 	logging_init_defaults(debug, daemonize, knet_cfg_head.logfile);
 	log_info(PACKAGE "d version " VERSION);
 
 	/*
 	 * don't fail if scheduler is not RR because systemd is
 	 * an utter piece of shit that refuses us to set RR via init script
 	 */
 	set_scheduler();
 
 	err = knet_vty_main_loop(debug);
 	if (err < 0)
 		log_error("Detected fatal error in main loop");
 
 	if (knet_cfg_head.logfile)
 		free(knet_cfg_head.logfile);
 	if (knet_cfg_head.conffile)
 		free(knet_cfg_head.conffile);
 	if (knet_cfg_head.vty_ipv6)
 		free(knet_cfg_head.vty_ipv6);
 	if (knet_cfg_head.vty_ipv4)
 		free(knet_cfg_head.vty_ipv4);
 	if (knet_cfg_head.vty_port)
 		free(knet_cfg_head.vty_port);
 
 	logging_fini();
 
 	return err;
 }
diff --git a/kronosnetd/vty.c b/kronosnetd/vty.c
index c25993fe..067b93e8 100644
--- a/kronosnetd/vty.c
+++ b/kronosnetd/vty.c
@@ -1,504 +1,504 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <arpa/inet.h>
 #include <string.h>
 #include <errno.h>
 #include <pthread.h>
 #include <signal.h>
 #include <stdlib.h>
 
 #include "cfg.h"
 #include "logging.h"
 #include "netutils.h"
 #include "vty.h"
 #include "vty_auth.h"
 #include "vty_cli.h"
 #include "vty_cli_cmds.h"
 #include "vty_utils.h"
 
 static int vty_max_connections = KNET_VTY_DEFAULT_MAX_CONN;
 static int vty_current_connections = 0;
 static int daemon_quit = 0;
 
 pthread_mutex_t knet_vty_mutex = PTHREAD_MUTEX_INITIALIZER;
 int knet_vty_config = -1;
 struct knet_vty knet_vtys[KNET_VTY_TOTAL_MAX_CONN];
 struct knet_vty_global_conf vty_global_conf;
 pthread_t logging_thread;
 
 static int _fdset_cloexec(int fd)
 {
 	int fdflags;
 
 	fdflags = fcntl(fd, F_GETFD, 0);
 	if (fdflags < 0)
 		return -1;
 
 	fdflags |= FD_CLOEXEC;
 
 	if (fcntl(fd, F_SETFD, fdflags) < 0)
 		return -1;
 
 	return 0;
 }
 
 static int _fdset_nonblock(int fd)
 {
 	int fdflags;
 
 	fdflags = fcntl(fd, F_GETFL, 0);
 	if (fdflags < 0)
 		return -1;
 
 	fdflags |= O_NONBLOCK;
 
 	if (fcntl(fd, F_SETFL, fdflags) < 0)
 		return -1;
 
 	return 0;
 }
 
 static void *_handle_logging_thread(void *data)
 {
 	int logfd;
 	int se_result = 0;
 	fd_set rfds;
 	struct timeval tv;
 
 	memmove(&logfd, data, sizeof(int));
 
 	while (se_result >= 0 && !daemon_quit){
 		FD_ZERO (&rfds);
 		FD_SET (logfd, &rfds);
 
 		tv.tv_sec = 1;
 		tv.tv_usec = 0;
 
 		se_result = select(FD_SETSIZE, &rfds, 0, 0, &tv);
 
 		if (se_result == -1)
 			goto out;
 
 		if (se_result == 0)
 			continue;
 
 		if (FD_ISSET(logfd, &rfds))  {
 			struct knet_log_msg msg;
 			size_t bytes_read = 0;
 			size_t len;
 
 			while (bytes_read < sizeof(struct knet_log_msg)) {
 				len = read(logfd, &msg + bytes_read,
 					   sizeof(struct knet_log_msg) - bytes_read);
 				if (len <= 0) {
 					break;
 				}
 				bytes_read += len;
 			}
 
 			if (bytes_read != sizeof(struct knet_log_msg))
 				continue;
 
 			switch(msg.msglevel) {
 				case KNET_LOG_WARN:
 					log_warn("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg);
 					break;
 				case KNET_LOG_INFO:
 					log_info("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg);
 					break;
 				case KNET_LOG_DEBUG:
 					log_kdebug("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg);
 					break;
 				case KNET_LOG_ERR:
 				default:
 					log_error("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg);
 			}
 		}
 	}
 
 out:
 	return NULL;
 }
 
 static int knet_vty_init_listener(const char *ip_addr, const char *port)
 {
 	int sockfd = -1, sockopt = 1;
 	int socktype = SOCK_STREAM;
 	int err = 0;
 	struct sockaddr_storage ss;
 
 	memset(&ss, 0, sizeof(struct sockaddr_storage));
 
 	if (knet_strtoaddr(ip_addr, port, &ss, sizeof(struct sockaddr_storage)) != 0)
 		return -1;
 
 	pthread_mutex_lock(&knet_vty_mutex);
 
 	/* handle sigpipe if we decide to use KEEPALIVE */
 
 	sockfd = socket(ss.ss_family, socktype, 0);
 	if (sockfd < 0) {
 		err = sockfd;
 		goto out_clean;
 	}
 
 	if (ss.ss_family == AF_INET6) {
 		err = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
 				 (void *)&sockopt, sizeof(sockopt));
 		if (err)
 			goto out_clean;
 	}
 
 	err = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
 			 (void *)&sockopt, sizeof(sockopt));
 	if (err)
 		goto out_clean;
 
 	if (_fdset_cloexec(sockfd)) {
 		err = -1;
 		goto out_clean;
 	}
 
 	err = bind(sockfd, (struct sockaddr *)&ss, sizeof(struct sockaddr_storage));
 	if (err)
 		goto out_clean;
 
 	err = listen(sockfd, 0);
 	if (err)
 		goto out_clean;
 
 	pthread_mutex_unlock(&knet_vty_mutex);
 
 	return sockfd;
 
 out_clean:
 	if (sockfd >= 0)
 		close(sockfd);
 
 	pthread_mutex_unlock(&knet_vty_mutex);
 
 	return err;
 }
 
 static void knet_vty_close_listener(int listener_fd)
 {
 	pthread_mutex_lock(&knet_vty_mutex);
 
 	if (listener_fd <= 0)
 		goto out_clean;
 
 	close(listener_fd);
 	listener_fd = 0;
 
 out_clean:
 
 	pthread_mutex_unlock(&knet_vty_mutex);
 
 	return;
 }
 
 static void sigterm_handler(int sig)
 {
 	daemon_quit = 1;
 }
 
 static void sigpipe_handler(int sig)
 {
 	return;
 }
 
 static void knet_vty_close(struct knet_vty *vty)
 {
 	if (knet_vty_config == vty->conn_num)
 		knet_vty_config = -1;
 
 	knet_vty_free_history(vty);
 	vty->active = 0;
 	close(vty->vty_sock);
 	vty_current_connections--;
 }
 
 static void *vty_accept_thread(void *arg)
 {
 	struct knet_vty *vty = (struct knet_vty *)&knet_vtys[*(int *)arg];
 	char addr_str[KNET_MAX_HOST_LEN];
 	char port_str[KNET_MAX_PORT_LEN];
 	int err;
 
 	knet_vty_print_banner(vty);
 	if (vty->got_epipe)
 		goto out_clean;
 
 	err = knet_addrtostr(&vty->src_sa, vty->src_sa_len,
 			     addr_str, KNET_MAX_HOST_LEN,
 			     port_str, KNET_MAX_PORT_LEN);
 
 	if (!err) {
 		strncpy(vty->ip, addr_str, sizeof(vty->ip));
 	} else {
 		strcpy(vty->ip, "unknown");
 	}
 
 	if ((knet_vty_auth_user(vty, NULL) < 0) && (!vty->got_epipe)) {
 		log_info("User failed to authenticate (ip: %s)", vty->ip);
 		goto out_clean;
 	}
 	if (vty->got_epipe)
 		goto out_clean;
 
 	log_info("User %s connected from %s", vty->username, vty->ip);
 	knet_vty_write(vty, "Welcome %s (%s) on vty(%d)\n\n", vty->username, vty->ip, vty->conn_num);
 	if (vty->got_epipe)
 		goto out_clean;
 
 	if (knet_vty_set_iacs(vty) < 0) {
 		knet_vty_write(vty, "Unable to set telnet session preferences");
 		goto out_clean;
 	}
 	if (vty->got_epipe)
 		goto out_clean;
 
 	knet_vty_cli_bind(vty);
 
 out_clean:
 	pthread_mutex_lock(&knet_vty_mutex);
 	knet_vty_close(vty);
 	pthread_mutex_unlock(&knet_vty_mutex);
 
 	return NULL;
 }
 
 /*
  * mainloop is not thread safe as there should only be one
  */
 int knet_vty_main_loop(int debug)
 {
 	int logfd[2];
 	int vty_listener6_fd;
 	int vty_listener4_fd;
 	int vty_listener_fd;
 	int vty_accept_fd;
 	struct sockaddr_storage incoming_sa;
 	socklen_t salen;
 	fd_set rfds;
 	int se_result = 0;
 	struct timeval tv;
 	int err = 0;
 	int conn_index, found;
 
 	signal(SIGTERM, sigterm_handler);
 	signal(SIGINT, sigterm_handler);
 	signal(SIGPIPE, sigpipe_handler);
 
 	if (pipe(logfd)) {
 		log_error("Unable to create logging pipe");
 		return -1;
 	}
 
 	if ((_fdset_cloexec(logfd[0])) ||
 	    (_fdset_nonblock(logfd[0])) ||
 	    (_fdset_cloexec(logfd[1])) ||
 	    (_fdset_nonblock(logfd[1]))) {
 		log_error("Unable to set FD_CLOEXEX / O_NONBLOCK on logfd pipe");
 		return -1;
 	}
 
 	err = pthread_create(&logging_thread,
 			     NULL, _handle_logging_thread,
 			     (void *)&logfd[0]);
 	if (err) {
 		log_error("Unable to create logging thread");
 		return -1;
 	}
 
 	memset(&knet_vtys, 0, sizeof(knet_vtys));
 	memset(&vty_global_conf, 0, sizeof(struct knet_vty_global_conf));
 	vty_global_conf.idle_timeout = KNET_VTY_CLI_TIMEOUT;
 
 	for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) {
 		knet_vtys[conn_index].logfd = logfd[1];
 		knet_vtys[conn_index].vty_global_conf = &vty_global_conf;
 		if (debug) {
 			knet_vtys[conn_index].loglevel = KNET_LOG_DEBUG;
 		} else {
 			knet_vtys[conn_index].loglevel = KNET_LOG_INFO;
 		}
 	}
 
 	if (knet_read_conf() < 0) {
 		log_error("Unable to read config file %s", knet_cfg_head.conffile);
 		return -1;
 	}
 
 	vty_listener6_fd = knet_vty_init_listener(knet_cfg_head.vty_ipv6,
 						  knet_cfg_head.vty_port);
 	if (vty_listener6_fd < 0) {
 		log_error("Unable to setup vty listener for ipv6");
 		return -1;
 	}
 
 	vty_listener4_fd = knet_vty_init_listener(knet_cfg_head.vty_ipv4,
 						  knet_cfg_head.vty_port);
 
 	if (vty_listener4_fd < 0) {
 		log_error("Unable to setup vty listener for ipv4");
 		goto out;
 	}
 
 	while (se_result >= 0 && !daemon_quit) {
 		FD_ZERO (&rfds);
 		FD_SET (vty_listener6_fd, &rfds);
 		FD_SET (vty_listener4_fd, &rfds);
 
 		tv.tv_sec = 1;
 		tv.tv_usec = 0;
 
 		se_result = select(FD_SETSIZE, &rfds, 0, 0, &tv);
 
 		if ((se_result == -1) && (daemon_quit)) {
 			log_info("Got a SIGTERM, requesting CLI threads to exit");	
 			for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) {
 				if (knet_vtys[conn_index].active) {
 					knet_vty_write(&knet_vtys[conn_index], "%s%sServer is going down..%s%s",
 						telnet_newline, telnet_newline, telnet_newline, telnet_newline);
 					knet_vty_close(&knet_vtys[conn_index]);
 					knet_vtys[conn_index].got_epipe = 1;
 				}
 			}
 			sleep(2); /* give time to all vty to exit */
 			knet_close_down();
 			log_info("Have a nice day! Goodbye");
 			goto out;
 		}
 
 		if (se_result == -1) {
 			err = se_result;
 			log_error("Unable to select on vty listener socket!");
 			goto out;
 		}
 
 		if (se_result == 0) {
 			pthread_mutex_lock(&knet_vty_mutex);
 			for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) {
 				if ((knet_vtys[conn_index].active) &&
 				    (knet_vtys[conn_index].idle_timeout)) {
 					knet_vtys[conn_index].idle++;
 					if (knet_vtys[conn_index].idle > knet_vtys[conn_index].idle_timeout) {
 						knet_vty_close(&knet_vtys[conn_index]);
 						knet_vtys[conn_index].got_epipe = 1;
 					}
 				}
 			}
 			pthread_mutex_unlock(&knet_vty_mutex);
 			continue;
 		}
 
 		if (FD_ISSET(vty_listener6_fd, &rfds)) {
 			vty_listener_fd = vty_listener6_fd;
 		} else if (FD_ISSET(vty_listener4_fd, &rfds)) {
 			vty_listener_fd = vty_listener4_fd;
 		} else {
 			continue;
 		}
 
 		memset(&incoming_sa, 0, sizeof(struct sockaddr_storage));
 		salen = sizeof(struct sockaddr_storage);
 
 		vty_accept_fd = accept(vty_listener_fd, (struct sockaddr *)&incoming_sa, &salen);
 		if (vty_accept_fd < 0) {
 			log_error("Unable to accept connection to vty");
 			continue;
 		}
 
 		// check for ip address access list here against incoming_sa
 
 		pthread_mutex_lock(&knet_vty_mutex);
 
 		found = 0;
 		for(conn_index = 0; conn_index <= vty_max_connections; conn_index++) {
 			if (knet_vtys[conn_index].active == 0) {
 				found = 1;
 				break;
 			}
 		}
 
 		if ((vty_current_connections == vty_max_connections) || (!found)) {
 			errno = ECONNREFUSED;
 			log_error("Too many connections to VTY or no available slots");
 			close(vty_accept_fd);
 			pthread_mutex_unlock(&knet_vty_mutex);
 			continue;
 		}
 
 		vty_current_connections++;
 
 		memset(&knet_vtys[conn_index], 0,
 		       sizeof(struct knet_vty));
 
 		knet_vtys[conn_index].vty_sock = vty_accept_fd;
 		knet_vtys[conn_index].conn_num = conn_index;
 		memmove(&knet_vtys[conn_index].src_sa, &incoming_sa, salen);
 		knet_vtys[conn_index].src_sa_len = salen;
 		knet_vtys[conn_index].active = 1;
 		knet_vtys[conn_index].logfd = logfd[1];
 		knet_vtys[conn_index].vty_global_conf = &vty_global_conf;
 		knet_vtys[conn_index].idle_timeout = vty_global_conf.idle_timeout;
 		if (debug) {
 			knet_vtys[conn_index].loglevel = KNET_LOG_DEBUG;
 		} else {
 			knet_vtys[conn_index].loglevel = KNET_LOG_INFO;
 		}
 
 		err = pthread_create(&knet_vtys[conn_index].vty_thread,
 				     NULL, vty_accept_thread,
 				     (void *)&conn_index);
 		if (err < 0) {
 			log_error("Unable to spawn vty thread");
 			memset(&knet_vtys[conn_index], 0,
 			       sizeof(struct knet_vty));
 			vty_current_connections--;
 		}
 
 		pthread_mutex_unlock(&knet_vty_mutex);
 	}
 
 out:
 	pthread_cancel(logging_thread);
 	knet_vty_close_listener(vty_listener6_fd);
 	knet_vty_close_listener(vty_listener4_fd);
 	close(logfd[0]);
 	close(logfd[1]);
 
 	return err;
 }
 
 /*
 int knet_vty_set_max_connections(const int max_connections)
 {
 	int err = 0;
 
 	pthread_mutex_lock(&knet_vty_mutex);
 	if ((max_connections > KNET_VTY_TOTAL_MAX_CONN) ||
 	    (max_connections < 1)) {
 		errno = EINVAL;
 		err = -1;
 	} else {
 		vty_max_connections = max_connections;
 	}
 	pthread_mutex_unlock(&knet_vty_mutex);
 	return err;
 }
 */
diff --git a/kronosnetd/vty.h b/kronosnetd/vty.h
index 73608897..f91be4d0 100644
--- a/kronosnetd/vty.h
+++ b/kronosnetd/vty.h
@@ -1,74 +1,74 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNETD_VTY_H__
 #define __KNETD_VTY_H__
 
 #include <pthread.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include "libknet.h"
 
 #define KNET_VTY_DEFAULT_PORT		50000
 
 #define KNET_VTY_DEFAULT_MAX_CONN	4
 #define KNET_VTY_TOTAL_MAX_CONN		16
 #define KNET_VTY_CLI_TIMEOUT		300
 
 #define KNET_VTY_MAX_LINE		512
 
 #define KNET_VTY_MAX_HIST		50
 
 struct knet_vty_global_conf {
 	int	idle_timeout;
 };
 
 struct knet_vty {
 	pthread_t		vty_thread;	/* thread struct for this vty */
 	struct sockaddr_storage	src_sa;		/* source IP */
 	socklen_t		src_sa_len;	/* sa len */
 	char			ip[128];	/* ip addr of source */
 	char			username[64];	/* username */
 	char			line[KNET_VTY_MAX_LINE]; /* input line */
 	char			*history[KNET_VTY_MAX_HIST]; /* history */
 	int			history_idx;	/* index to history */
 	int			history_pos;	/* position in the history */
 	int			insert_mode;	/* add or insert */
 	int			line_idx;	/* index on the input line */
 	int			cursor_pos;	/* position of the cursor in the line */
 	int			escape;		/* escape status */
 	int			escape_code;	/* escape code buffer */
 	int			user_can_enable;/* user is in group kronosnetadm */
 	int			vty_sock;	/* tcp socket for this vty */
 	int			conn_num;	/* vty number */
 	int			active;		/* vty is active */
 	int			got_epipe;	/* vty_sock has been closed */
 	int			idle;		/* idle time */
 	int			idle_timeout;	/* in seconds or 0 to disable automatic logout */
 	int			node;		/* node number of the menus */
 	int			prevnode;	/* node number of the menus (used by VTY node) */
 	void			*param;		/* pointer to cmd param */
 	int			paramoffset;	/* required if param is set */
 	int			logfd;		/* fd to pass to iface create */
 	int			loglevel;	/* loglevel (debug, etc) */
 	void			*iface;		/* pointer to iface we are working on */
 	knet_node_id_t		host_id;	/* peer/host we are working on */
 	uint8_t			link_id;	/* link id we are working on */
 	int			filemode;	/* tell print_conf to add or not carriage return */
 	struct knet_vty_global_conf *vty_global_conf; /* pointer to vty global config */
 };
 
 extern pthread_mutex_t knet_vty_mutex;
 extern int knet_vty_config;
 
 extern struct knet_vty knet_vtys[KNET_VTY_TOTAL_MAX_CONN];
 
 int knet_vty_main_loop(int debug);
 
 #endif
diff --git a/kronosnetd/vty_auth.c b/kronosnetd/vty_auth.c
index 250ffb22..4ee793fb 100644
--- a/kronosnetd/vty_auth.c
+++ b/kronosnetd/vty_auth.c
@@ -1,305 +1,305 @@
 /*
- * Copyright (C) 2012-2015 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/types.h>
 #include <grp.h>
 
 #include <security/pam_appl.h>
 #include <security/pam_misc.h>
 
 #include "logging.h"
 #include "vty_auth.h"
 #include "vty_utils.h"
 
 static int knet_pam_misc_conv(int num_msg, const struct pam_message **msgm,
 			      struct pam_response **response, void *appdata_ptr)
 {
 	int count = 0;
 	struct pam_response *reply;
 	struct knet_vty *vty = (struct knet_vty *)appdata_ptr;
 
 	if (num_msg <= 0)
 		return PAM_CONV_ERR;
 
 	reply = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response));
 
 	if (reply == NULL)
 		return PAM_CONV_ERR;
 
 	for (count=0; count < num_msg; ++count) {
 		unsigned char readbuf[VTY_MAX_BUFFER_SIZE];
 		char *string=NULL;
 		int nc;
 
 		memset(readbuf, 0, sizeof(readbuf));
 
 		switch (msgm[count]->msg_style) {
 		case PAM_PROMPT_ECHO_OFF:
 			if (knet_vty_set_echo(vty, 0) < 0) {
 				knet_vty_write(vty, "Unable to turn off terminal/telnet echo");
 				goto failed_conversation;
 			}
 			knet_vty_write(vty, "%s", msgm[count]->msg);
 			nc = knet_vty_read(vty, readbuf, sizeof(readbuf));
 			if (nc < 0)
 				goto failed_conversation;
 			if (knet_vty_set_echo(vty, 1) < 0) {
 				/* doesn't really make a lot of sense tho.... */
 				knet_vty_write(vty, "Unable to turn on terminal/telnet echo");
 				goto failed_conversation;
 			}
 			knet_vty_write(vty, "\n");
 			readbuf[nc-2] = 0;
 			string = strdup((const char*)readbuf);
 			if (!string)
 				goto failed_conversation;
 			break;
 		case PAM_PROMPT_ECHO_ON:
 			knet_vty_write(vty, "\n%s", msgm[count]->msg);
 			nc = knet_vty_read(vty, readbuf, sizeof(readbuf));
 			if (nc < 0)
 				goto failed_conversation;
 			readbuf[nc-2] = 0;
 			string = strdup((const char*)readbuf);
 			if (!string)
 				goto failed_conversation;
 			break;
 		case PAM_ERROR_MSG:
 			log_error("Received PAM error message %s", msgm[count]->msg);
 			knet_vty_write(vty, "%s", msgm[count]->msg);
 			break;
 		case PAM_TEXT_INFO:
 			log_error("Received PAM text info: %s", msgm[count]->msg);
 			knet_vty_write(vty, "%s", msgm[count]->msg);
 			break;
 		default:
 			if (!vty->got_epipe) {
 				log_error("Unknown PAM conversation message");
 				knet_vty_write(vty, "Unknown PAM conversation message");
 			}
 			goto failed_conversation;
 		}
 
 		if (string) {
 			reply[count].resp_retcode = 0;
 			reply[count].resp = string;
 			string = NULL;
 		}
 	}
 
 	*response = reply;
 	reply = NULL;
 
 	return PAM_SUCCESS;
 
 failed_conversation:
 	if (!vty->got_epipe) {
 		log_error("PAM conversation error");
 		knet_vty_write(vty, "PAM conversation error");
 	}
 	if (reply) {
 		for (count=0; count < num_msg; ++count) {
 			if (reply[count].resp == NULL)
 				continue;
 			switch (msgm[count]->msg_style) {
 			case PAM_PROMPT_ECHO_ON:
 			case PAM_PROMPT_ECHO_OFF:
 				_pam_overwrite(reply[count].resp);
 				free(reply[count].resp);
 				break;
 			case PAM_BINARY_PROMPT:
 				{
 					void *bt_ptr = reply[count].resp;
 					pam_binary_handler_free(appdata_ptr, bt_ptr);
 					break;
 				}
 			case PAM_ERROR_MSG:
 			case PAM_TEXT_INFO:
 				free(reply[count].resp);
 			}
 		}
 		free(reply);
 		reply = NULL;
 	}
 
 	return PAM_CONV_ERR;
 }
 
 static int knet_vty_get_pam_user(struct knet_vty *vty, pam_handle_t *pamh)
 {
 	const void *value;
 	int err;
 
 	memset(vty->username, 0, sizeof(vty->username));
 
 	err = pam_get_item(pamh, PAM_USER, &value);
 
 	if (err != PAM_SUCCESS)
 		return err;
 
 	strncpy(vty->username, (const char*)value, 32);
 
 	return 0;
 }
 
 static int knet_vty_pam_auth_user(struct knet_vty *vty, const char *user)
 {
 	pam_handle_t *pamh=NULL;
 	struct pam_conv conv;
 	int err;
 	int retry = 1;
 
 	conv.conv = knet_pam_misc_conv;
 	conv.appdata_ptr = (void *)vty;
 
 retry_auth:
 	err = pam_start("kronosnetd", user, &conv, &pamh);
 	if (err != PAM_SUCCESS) {
 		errno = EINVAL;
 		log_error("PAM fatal error: %s", pam_strerror(pamh, err));
 		knet_vty_write(vty, "PAM fatal error: %s",
 				pam_strerror(pamh, err));
 		goto out_fatal;
 	}
 
 	if (pam_set_item(pamh, PAM_USER_PROMPT, (const void *)"login: ") != PAM_SUCCESS) {
 		log_error("PAM fatal error: %s", pam_strerror(pamh, err));
 		knet_vty_write(vty, "PAM fatal error: %s",
 				pam_strerror(pamh, err));
 		goto out_fatal;
 	}
 
 	err = pam_authenticate(pamh, 0);
 	if (err != PAM_SUCCESS) {
 		if (vty->got_epipe) {
 			errno = EPIPE;
 			goto out_fatal;
 		} else {
 			errno = EINVAL;
 			goto out_clean;
 		}
 	}
 
 	if (knet_vty_get_pam_user(vty, pamh) != PAM_SUCCESS) {
 		log_error("PAM: unable to get PAM_USER: %s",
 			  pam_strerror(pamh, err));
 		knet_vty_write(vty, "PAM: unable to get PAM_USER: %s",
 				pam_strerror(pamh, err));
 		goto out_clean;
 	}
 
 	err = pam_acct_mgmt(pamh, 0);
 	if (err != PAM_SUCCESS) {
 		log_info("User: %s failed to authenticate on vty(%d) attempt %d",
 			 vty->username, vty->conn_num, retry);
 		goto out_clean;
 	}
 
 out_clean:
 	if (pamh) {
 		pam_end(pamh, err);
 		pamh = NULL;
 	}
 
 	if ((err != PAM_SUCCESS) && (retry < AUTH_MAX_RETRY)) {
 		retry++;
 		goto retry_auth;
 	}
 
 out_fatal:
 	if (pamh) {
 		pam_end(pamh, err);
 		pamh = NULL;
 	}
 
 	knet_vty_write(vty, "\n");
 
 	return err;
 }
 
 static int knet_vty_group_check(struct knet_vty *vty)
 {
 	struct group grp;
 	char *buf;
 	size_t buflen;
 	long int initlen;
 	struct group *result;
 	char *gr_mem;
 	int err, i;
 
 	errno = 0;
 	initlen = sysconf(_SC_GETGR_R_SIZE_MAX);
 	if ((initlen < 0) && (errno == EINVAL))
 		return -1;
 
 	if (initlen < 0)
 		initlen = 1024;
 
 	buflen = (size_t) initlen;
 
 	buf = malloc(buflen);
 	if (!buf)
 		return -1;
 
 	while ((err = getgrnam_r(DEFAULTADMGROUP, &grp, buf, buflen, &result)) == ERANGE) {
 		size_t newlen = 2 * buflen;
 		char *newbuf;
 
 		newbuf = realloc(buf, newlen);
 		if (!newbuf) {
 			err = -1;
 			goto out_clean;
 		}
 		buf = newbuf;
 	}
 	if (err)
 		goto out_clean;
 
 	if (result == NULL) {
 		errno = EACCES;
 		log_error("No " DEFAULTADMGROUP " group found on the system");
 		knet_vty_write(vty, "No " DEFAULTADMGROUP " group found on the system\n");
 		err = -1;
 		goto out_clean;
 	}
 
 	gr_mem = *grp.gr_mem;
 
 	i = 0;
 	while(gr_mem != NULL) {
 		if (!strcmp(vty->username, gr_mem)) {
 			vty->user_can_enable = 1;
 			break;
 		}
 		gr_mem = *(grp.gr_mem + i);
 		i++;
 	}
 
 out_clean:
 	free(buf);
 
 	return err;
 }
 
 int knet_vty_auth_user(struct knet_vty *vty, const char *user)
 {
 	int err;
 
 	err = knet_vty_pam_auth_user(vty, user);
 	if (err != PAM_SUCCESS)
 		return -1;
 
 	return knet_vty_group_check(vty);
 }
diff --git a/kronosnetd/vty_auth.h b/kronosnetd/vty_auth.h
index ef787224..2274f76d 100644
--- a/kronosnetd/vty_auth.h
+++ b/kronosnetd/vty_auth.h
@@ -1,18 +1,18 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNETD_VTY_AUTH_H__
 #define __KNETD_VTY_AUTH_H__
 
 #include "vty.h"
 
 #define AUTH_MAX_RETRY 3
 
 int knet_vty_auth_user(struct knet_vty *vty, const char *user);
 
 #endif
diff --git a/kronosnetd/vty_cli.c b/kronosnetd/vty_cli.c
index 8bac0667..09e4a2d7 100644
--- a/kronosnetd/vty_cli.c
+++ b/kronosnetd/vty_cli.c
@@ -1,531 +1,531 @@
 /*
- * Copyright (C) 2012-2015 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <sys/select.h>
 #include <unistd.h>
 #include <stdlib.h>
 
 #include "logging.h"
 #include "vty.h"
 #include "vty_cli.h"
 #include "vty_cli_cmds.h"
 #include "vty_utils.h"
 
 /* if this code looks like quagga lib/vty.c it is because we stole it in good part */
 
 #define CONTROL(X)	((X) - '@')
 #define VTY_NORMAL	0
 #define VTY_PRE_ESCAPE	1
 #define VTY_ESCAPE	2
 #define VTY_EXT_ESCAPE	3
 
 static void knet_vty_reset_buf(struct knet_vty *vty)
 {
 	memset(vty->line, 0, sizeof(vty->line));
 	vty->line_idx = 0;
 	vty->cursor_pos = 0;
 	vty->history_pos = vty->history_idx;
 }
 
 static void knet_vty_add_to_buf(struct knet_vty *vty, unsigned char *buf, int pos)
 {
 	char outbuf[2];
 	int i;
 
 	if (vty->cursor_pos == vty->line_idx) {
 		vty->line[vty->line_idx] = buf[pos];
 		vty->line_idx++;
 		vty->cursor_pos++;
 	} else {
 		if (!vty->insert_mode) {
 			memmove(&vty->line[vty->cursor_pos+1], &vty->line[vty->cursor_pos],
 				vty->line_idx - vty->cursor_pos);
 			vty->line_idx++;
 		}
 		vty->line[vty->cursor_pos] = buf[pos];
 		vty->cursor_pos++;
 	}
 
 	outbuf[0] = buf[pos];
 	outbuf[1] = 0;
 	knet_vty_write(vty, "%s%s", outbuf, &vty->line[vty->cursor_pos]);
 	for (i = 0; i < (vty->line_idx - vty->cursor_pos); i++)
 		knet_vty_write(vty, "%s", telnet_backward_char);
 }
 
 static void knet_vty_forward_char(struct knet_vty *vty)
 {
 	char buf[2];
 
 	if (vty->cursor_pos < vty->line_idx) {
 		buf[0] = vty->line[vty->cursor_pos];
 		buf[1] = 0;
 		knet_vty_write(vty, "%s", buf);
 		vty->cursor_pos++;
 	}
 }
 
 static void knet_vty_backward_char(struct knet_vty *vty)
 {
 	if (vty->cursor_pos > 0) {
 		knet_vty_write(vty, "%s", telnet_backward_char);
 		vty->cursor_pos--;
 	}
 }
 
 static void knet_vty_kill_line(struct knet_vty *vty)
 {
 	int size, i;
 
 	size = vty->line_idx - vty->cursor_pos;
 
 	if (size == 0)
 		return;
 
 	for (i = 0; i < size; i++)
 		knet_vty_write(vty, " ");
 
 	for (i = 0; i < size; i++)
 		knet_vty_write(vty, "%s", telnet_backward_char);
 
 	memset(&vty->line[vty->cursor_pos], 0, size);
 	vty->line_idx = vty->cursor_pos;
 }
 
 static void knet_vty_newline(struct knet_vty *vty)
 {
 	knet_vty_write(vty, "%s", telnet_newline);
 	knet_vty_reset_buf(vty);
 	knet_vty_prompt(vty);
 }
 
 static void knet_vty_delete_char(struct knet_vty *vty)
 {
 	int size, i;
 
 	if (vty->line_idx == 0) {
 		knet_vty_exit_node(vty);
 		if (!vty->got_epipe) {
 			knet_vty_newline(vty);
 		}
 		return;
 	}
 
 	if (vty->line_idx == vty->cursor_pos)
 		return;
 
 	size = vty->line_idx - vty->cursor_pos;
 
 	vty->line_idx--;
 	memmove(&vty->line[vty->cursor_pos], &vty->line[vty->cursor_pos+1],
 		size - 1);
 	vty->line[vty->line_idx] = '\0';
 
 	knet_vty_write(vty, "%s ", &vty->line[vty->cursor_pos]);
 	for (i = 0; i < size; i++)
 		knet_vty_write(vty, "%s", telnet_backward_char);
 }
 
 static void knet_vty_delete_backward_char(struct knet_vty *vty)
 {
 	if (vty->cursor_pos == 0)
 		return;
 
 	knet_vty_backward_char(vty);
 	knet_vty_delete_char(vty);
 }
 
 static void knet_vty_beginning_of_line(struct knet_vty *vty)
 {
 	while (vty->cursor_pos != 0)
 		knet_vty_backward_char(vty);
 }
 
 static void knet_vty_end_of_line(struct knet_vty *vty)
 {
 	while (vty->cursor_pos != vty->line_idx)
 		knet_vty_forward_char(vty);
 }
 
 static void knet_vty_kill_line_from_beginning(struct knet_vty *vty)
 {
 	knet_vty_beginning_of_line(vty);
 	knet_vty_kill_line(vty);
 }
 
 static void knet_vty_backward_word(struct knet_vty *vty)
 {
 	while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] == ' ')
 		knet_vty_backward_char(vty);
 
 	while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] != ' ')
 		knet_vty_backward_char(vty);
 }
 
 static void knet_vty_forward_word(struct knet_vty *vty)
 {
 	while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] == ' ')
 		knet_vty_forward_char(vty);
 
 	while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] != ' ')
 		knet_vty_forward_char(vty);
 }
 
 static void knet_vty_backward_kill_word(struct knet_vty *vty)
 {
 	while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] == ' ')
 		knet_vty_delete_backward_char(vty);
 
 	while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] != ' ')
 		knet_vty_delete_backward_char(vty);
 }
 
 static void knet_vty_forward_kill_word(struct knet_vty *vty)
 {
 	while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] == ' ')
 		knet_vty_delete_char(vty);
 
 	while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] != ' ')
 		knet_vty_delete_backward_char(vty);
 }
 
 static void knet_vty_transpose_chars(struct knet_vty *vty)
 {
 	unsigned char swap[2];
 
 	if (vty->line_idx < 2 || vty->cursor_pos < 2)
 		return;
 
 	swap[0] = vty->line[vty->cursor_pos - 1];
 	swap[1] = vty->line[vty->cursor_pos - 2];
 	knet_vty_delete_backward_char(vty);
 	knet_vty_delete_backward_char(vty);
 	knet_vty_add_to_buf(vty, swap, 0);
 	knet_vty_add_to_buf(vty, swap, 1);
 }
 
 static void knet_vty_history_add(struct knet_vty *vty)
 {
 	int idx;
 
 	if (knet_vty_is_line_empty(vty))
 		return;
 
 	idx = vty->history_idx % KNET_VTY_MAX_HIST;
 
 	if (vty->history[idx]) {
 		free(vty->history[idx]);
 		vty->history[idx] = NULL;
 	}
 
 	vty->history[idx] = strdup(vty->line);
 	if (vty->history[idx] == NULL) {
 		log_error("Not enough memory to add history lines!");
 		knet_vty_write(vty, "Not enough memory to add history lines!");
 	}
 
 	vty->history_idx++;
 
 	if (vty->history_idx == KNET_VTY_MAX_HIST)
 		vty->history_idx = 0;
 
 	vty->history_pos = vty->history_idx;
 }
 
 static void knet_vty_history_print(struct knet_vty *vty)
 {
 	int len;
 
 	knet_vty_kill_line_from_beginning(vty);
 
 	len = strlen(vty->history[vty->history_pos]);
 	memmove(vty->line, vty->history[vty->history_pos], len);
 	vty->cursor_pos = vty->line_idx = len;
 
 	knet_vty_write(vty, "%s", vty->line);
 }
 
 static void knet_vty_history_prev(struct knet_vty *vty)
 {
 	int idx;
 
 	idx = vty->history_pos;
 
 	if (idx == 0) {
 		idx = KNET_VTY_MAX_HIST - 1;
 	} else {
 		idx--;
 	}
 
 	if (vty->history[idx] == NULL)
 		return;
 
 	vty->history_pos = idx;
 
 	knet_vty_history_print(vty);
 }
 
 static void knet_vty_history_next(struct knet_vty *vty)
 {
 	int idx;
 
 	if (vty->history_pos == vty->history_idx)
 		return;
 
 	idx = vty->history_pos;
 
 	if (idx == (KNET_VTY_MAX_HIST - 1)) {
 		idx = 0;
 	} else {
 		idx++;
 	}
 
 	if (vty->history[idx] == NULL) {
 		knet_vty_kill_line_from_beginning(vty);
 		vty->history_pos = vty->history_idx;
 		return;
 	}
 
 	vty->history_pos = idx;
 
 	knet_vty_history_print(vty);
 }
 
 static int knet_vty_process_buf(struct knet_vty *vty, unsigned char *buf, int buflen)
 {
 	int i;
 
 	if (vty->line_idx >= KNET_VTY_MAX_LINE)
 		return -1;
 
 	for (i = 0; i < buflen; i++) {
 		if (vty->escape == VTY_EXT_ESCAPE)  {
 			if (buf[i] != '~')
 				goto vty_ext_escape_out;
 
 			switch (vty->escape_code) {
 				case ('1'):
 					knet_vty_beginning_of_line(vty);
 					break;
 				case ('2'):
 					if (!vty->insert_mode) {
 						vty->insert_mode = 1;
 					} else {
 						vty->insert_mode = 0;
 					}
 					break;
 				case ('3'):
 					knet_vty_delete_char(vty);
 					break;
 				case ('4'):
 					knet_vty_end_of_line(vty);
 					break;
 				case ('5'):
 					knet_vty_history_prev(vty);
 					break;
 				case ('6'):
 					knet_vty_history_next(vty);
 					break;
 			}
 
 vty_ext_escape_out:
 			vty->escape = VTY_NORMAL;
 			continue;
 		}
 
 		if (vty->escape == VTY_ESCAPE) {
 			switch (buf[i]) {
 				case ('A'):
 					knet_vty_history_prev(vty);
 					break;
 				case ('B'):
 					knet_vty_history_next(vty);
 					break;
 				case ('C'):
 					knet_vty_forward_char(vty);
 					break;
 				case ('D'):
 					knet_vty_backward_char(vty);
 					break;
 				case ('H'):
 					knet_vty_beginning_of_line(vty);
 					break;
 				case ('F'):
 					knet_vty_end_of_line(vty);
 					break;
 				case ('1'):
 				case ('2'):
 				case ('3'):
 				case ('4'):
 				case ('5'):
 				case ('6'):
 					vty->escape = VTY_EXT_ESCAPE;
 					vty->escape_code = buf[i];
 					break;
 				default:
 					break;
 			}
 
 			if (vty->escape == VTY_ESCAPE)
 				vty->escape = VTY_NORMAL;
 
 			continue;
 		}
 
 		if (vty->escape == VTY_PRE_ESCAPE) {
 			switch (buf[i]) {
 				case 'O':
 				case '[':
 					vty->escape = VTY_ESCAPE;
 					break;
 				case 'b':
 					vty->escape = VTY_NORMAL;
 					knet_vty_backward_word(vty);
 					break;
 				case 'f':
 					vty->escape = VTY_NORMAL;
 					knet_vty_forward_word(vty);
 					break;
 				case 'd':
 					vty->escape = VTY_NORMAL;
 					knet_vty_forward_kill_word(vty);
 					break;
 				case CONTROL('H'):
 				case 0x7f:
 					vty->escape = VTY_NORMAL;
 					knet_vty_backward_kill_word(vty);
 					break;
 				default:
 					break;
 			}
 			continue;
 		}
 
 		switch (buf[i]) {
 			case CONTROL('A'):
 				knet_vty_beginning_of_line(vty);
 				break;
 			case CONTROL('B'):
 				knet_vty_backward_char(vty);
 				break;
 			case CONTROL('C'):
 				knet_vty_newline(vty);
 				break;
 			case CONTROL('D'):
 				knet_vty_delete_char(vty);
 				break;
 			case CONTROL('E'):
 				knet_vty_end_of_line(vty);
 				break;
 			case CONTROL('F'):
 				knet_vty_forward_char(vty);
 				break;
 			case CONTROL('H'):
 			case 0x7f:
 				knet_vty_delete_backward_char(vty);
 				break;
 			case CONTROL('K'):
 				knet_vty_kill_line(vty);
 				break;
 			case CONTROL('N'):
 				knet_vty_history_next(vty);
 				break;
 			case CONTROL('P'):
 				knet_vty_history_prev(vty);
 				break;
 			case CONTROL('T'):
 				knet_vty_transpose_chars(vty);
 				break;
 			case CONTROL('U'):
 				knet_vty_kill_line_from_beginning(vty);
 				break;
 			case CONTROL('W'):
 				knet_vty_backward_kill_word(vty);
 				break;
 			case CONTROL('Z'):
 				vty->node = NODE_CONFIG;
 				knet_vty_exit_node(vty);
 				knet_vty_newline(vty);
 				break;
 			case '\n':
 			case '\r':
 				knet_vty_end_of_line(vty);
 				knet_vty_write(vty, "%s", telnet_newline);
 				knet_vty_history_add(vty);
 				knet_vty_execute_cmd(vty);
 				knet_vty_reset_buf(vty);
 				knet_vty_prompt(vty);
 				break;
 			case '\t':
 				knet_vty_end_of_line(vty);
 				knet_vty_tab_completion(vty);
 				break;
 			case '?':
 				knet_vty_end_of_line(vty);
 				knet_vty_write(vty, "%s", telnet_newline);
 				knet_vty_help(vty);
 				knet_vty_prompt(vty);
 				knet_vty_write(vty, "%s", vty->line);
 				break;
 			case '\033':
 				vty->escape = VTY_PRE_ESCAPE;
 				break;
 			default:
 				if (buf[i] > 31 && buf[i] < 127)
 					knet_vty_add_to_buf(vty, buf, i);
 				break;
 		}
 	}
 
 	return 0;
 }
 
 void knet_vty_cli_bind(struct knet_vty *vty)
 {
 	int se_result = 0;
 	fd_set rfds;
 	struct timeval tv;
 	unsigned char buf[VTY_MAX_BUFFER_SIZE];
 	int readlen;
 
 	knet_vty_prompt(vty);
 
 	while (se_result >= 0 && !vty->got_epipe) {
 		FD_ZERO (&rfds);
 		FD_SET (vty->vty_sock, &rfds);
 
 		tv.tv_sec = 1;
 		tv.tv_usec = 0;
 
 		se_result = select((vty->vty_sock + 1), &rfds, 0, 0, &tv);
 
 		if ((se_result == -1) || (vty->got_epipe))
 			goto out_clean;
 
 		if ((se_result == 0) || (!FD_ISSET(vty->vty_sock, &rfds)))
 			continue;
 
 		memset(buf, 0 , sizeof(buf));
 		readlen = knet_vty_read(vty, buf, sizeof(buf));
 		if (readlen <= 0)
 			goto out_clean;
 
 		if (knet_vty_process_buf(vty, buf, readlen) < 0) {
 			knet_vty_write(vty, "\nError processing command: command too long\n");
 			knet_vty_reset_buf(vty);
 		}
 	}
 
 out_clean:
 
 	return;
 }
diff --git a/kronosnetd/vty_cli.h b/kronosnetd/vty_cli.h
index 0895b28d..73bcd50c 100644
--- a/kronosnetd/vty_cli.h
+++ b/kronosnetd/vty_cli.h
@@ -1,20 +1,20 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNETD_VTY_CLI_H__
 #define __KNETD_VTY_CLI_H__
 
 #include "vty.h"
 
 static const char telnet_backward_char[] = { 0x08, 0x0 };
 static const char telnet_newline[] = { '\n', '\r', 0x0 };
 static const char file_newline[] = { '\n', 0x0 };
 
 void knet_vty_cli_bind(struct knet_vty *vty);
 
 #endif
diff --git a/kronosnetd/vty_cli_cmds.c b/kronosnetd/vty_cli_cmds.c
index 7dcdc689..6f6a9279 100644
--- a/kronosnetd/vty_cli_cmds.c
+++ b/kronosnetd/vty_cli_cmds.c
@@ -1,2188 +1,2188 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "cfg.h"
 #include "etherfilter.h"
 #include "logging.h"
 #include "libtap.h"
 #include "netutils.h"
 #include "vty.h"
 #include "vty_cli.h"
 #include "vty_cli_cmds.h"
 #include "vty_utils.h"
 
 #define KNET_VTY_MAX_MATCHES    64
 #define KNET_VTY_MATCH_HELP      0
 #define KNET_VTY_MATCH_EXEC      1
 #define KNET_VTY_MATCH_EXPAND    2
 
 #define CMDS_PARAM_NOMORE        0
 #define CMDS_PARAM_KNET          1
 #define CMDS_PARAM_IP            2
 #define CMDS_PARAM_IP_PREFIX     3
 #define CMDS_PARAM_IP_PORT       4
 #define CMDS_PARAM_BOOL          5
 #define CMDS_PARAM_INT           6
 #define CMDS_PARAM_NODEID        7
 #define CMDS_PARAM_NAME          8
 #define CMDS_PARAM_MTU           9
 #define CMDS_PARAM_CRYPTO_MODEL 10
 #define CMDS_PARAM_CRYPTO_TYPE  11
 #define CMDS_PARAM_HASH_TYPE    12
 #define CMDS_PARAM_POLICY       13
 #define CMDS_PARAM_LINK_ID      14
 #define CMDS_PARAM_LINK_PRI     15
 #define CMDS_PARAM_LINK_KEEPAL  16
 #define CMDS_PARAM_LINK_HOLDTI  17
 #define CMDS_PARAM_LINK_PONG    18
 #define CMDS_PARAM_VTY_TIMEOUT  19
 #define CMDS_PARAM_PMTU_FREQ    20
 #define CMDS_PARAM_LINK_TRANSP  21
 
 /*
  * CLI helper functions - menu/node stuff starts below
  */
 
 
 /*
  * return 0 if we find a command in vty->line and cmd/len/no are set
  * return -1 if we cannot find a command. no can be trusted. cmd/len would be empty
  */
 
 static int get_command(struct knet_vty *vty, char **cmd, int *cmdlen, int *cmdoffset, int *no)
 {
 	int start = 0, idx;
 
 	for (idx = 0; idx < vty->line_idx; idx++) {
 		if (vty->line[idx] != ' ')
 			break;
 	}
 
 	if (!strncmp(&vty->line[idx], "no ", 3)) {
 		*no = 1;
 		idx = idx + 3;
 
 		for (; idx < vty->line_idx; idx++) {
 			if (vty->line[idx] != ' ')
 				break;
 		}
 	} else {
 		*no = 0;
 	}
 
 	start = idx;
 	if (start == vty->line_idx)
 		return -1;
 
 	*cmd = &vty->line[start];
 	*cmdoffset = start;
 
 	for (idx = start; idx < vty->line_idx; idx++) {
 		if (vty->line[idx] == ' ')
 			break;
 	}
 
 	*cmdlen = idx - start;
 
 	return 0;
 }
 
 /*
  * still not sure why I need to count backwards...
  */
 static void get_n_word_from_end(struct knet_vty *vty, int n,
 					char **word, int *wlen, int *woffset)
 {
 	int widx;
 	int idx, end, start;
 
 	start = end = vty->line_idx;
 
 	for (widx = 0; widx < n; widx++) {
 		for (idx = start - 1; idx > 0; idx--) {
 			if (vty->line[idx] != ' ')
 				break;
 		}
 		end = idx;
 		for (idx = end; idx > 0; idx--) {
 			if (vty->line[idx-1] == ' ')
 				break;
 		}
 		start = idx;
 	}
 
 	*wlen = (end - start) + 1;
 	*word = &vty->line[start];
 	*woffset = start;
 }
 
 static int expected_params(const vty_param_t *params)
 {
 	int idx = 0;
 
 	while(params[idx].param != CMDS_PARAM_NOMORE)
 		idx++;
 
 	return idx;
 }
 
 static int count_words(struct knet_vty *vty,
 			 int offset)
 {
 	int idx, widx = 0;
 	int status = 0;
 
 	for (idx = offset; idx < vty->line_idx; idx++) {
 		if (vty->line[idx] == ' ') {
 			status = 0;
 			continue;
 		}
 		if ((vty->line[idx] != ' ') && (!status)) {
 			widx++;
 			status = 1;
 			continue;
 		}
 	}
 	return widx;
 }
 
 static int param_to_int(const char *param, int paramlen)
 {
 	char buf[KNET_VTY_MAX_LINE];
 
 	memset(buf, 0, sizeof(buf));
 	memmove(buf, param, paramlen);
 	return atoi(buf);
 }
 
 static int param_to_str(char *buf, int bufsize, const char *param, int paramlen)
 {
 	if (bufsize < paramlen)
 		return -1;
 
 	memset(buf, 0, bufsize);
 	memmove(buf, param, paramlen);
 	return paramlen;
 }
 
 static const vty_node_cmds_t *get_cmds(struct knet_vty *vty, char **cmd, int *cmdlen, int *cmdoffset)
 {
 	int no;
 	const vty_node_cmds_t *cmds =  knet_vty_nodes[vty->node].cmds;
 
 	get_command(vty, cmd, cmdlen, cmdoffset, &no);
 
 	if (no)
 		cmds = knet_vty_nodes[vty->node].no_cmds;
 
 	return cmds;
 }
 
 static int check_param(struct knet_vty *vty, const int paramtype, char *param, int paramlen)
 {
 	int err = 0;
 	char buf[KNET_VTY_MAX_LINE];
 	int tmp;
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 
 	memset(buf, 0, sizeof(buf));
 
 	switch(paramtype) {
 		case CMDS_PARAM_NOMORE:
 			break;
 		case CMDS_PARAM_KNET:
 			if (paramlen >= IFNAMSIZ) {
 				knet_vty_write(vty, "interface name too long%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_IP:
 			break;
 		case CMDS_PARAM_IP_PREFIX:
 			break;
 		case CMDS_PARAM_IP_PORT:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp < 0) || (tmp > 65279)) {
 				knet_vty_write(vty, "port number must be a value between 0 and 65279%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_BOOL:
 			break;
 		case CMDS_PARAM_INT:
 			break;
 		case CMDS_PARAM_NODEID:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp < 0) || (tmp > 255)) {
 				knet_vty_write(vty, "node id must be a value between 0 and 255%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_NAME:
 			if (paramlen >= KNET_MAX_HOST_LEN) {
 				knet_vty_write(vty, "name cannot exceed %d char in len%s", KNET_MAX_HOST_LEN - 1, telnet_newline);
 			}
 			break;
 		case CMDS_PARAM_MTU:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp < 576) || (tmp > 65536)) {
 				knet_vty_write(vty, "mtu should be a value between 576 and 65536 (note: max value depends on the media)%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_PMTU_FREQ:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp < 5) || (tmp > 600)) {
 				knet_vty_write(vty, "PMTUd frequency should be a value between 5 and 600%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_CRYPTO_MODEL:
 			param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen);
 			if (!strncmp("none", buf, 4))
 				break;
 			if (!strncmp("nss", buf, 3))
 				break;
 			knet_vty_write(vty, "unknown encryption model: %s. Supported: none/nss%s", param, telnet_newline);
 			err = -1;
 			break;
 		case CMDS_PARAM_CRYPTO_TYPE:
 			param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen);
 			if (!strncmp("none", buf, 4))
 				break;
 			if (!strncmp("aes256", buf, 6))
 				break;
 			if (!strncmp("aes192", buf, 6))
 				break;
 			if (!strncmp("aes128", buf, 6))
 				break;
 			if (!strncmp("3des", buf, 4))
 				break;
 			knet_vty_write(vty, "unknown encryption method: %s. Supported: none/aes256/aes192/aes128/3des%s", param, telnet_newline);
 			err = -1;
 			break;
 		case CMDS_PARAM_HASH_TYPE:
 			param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen);
 			if (!strncmp("none", buf, 4))
 				break;
 			if (!strncmp("md5", buf, 3))
 				break;
 			if (!strncmp("sha1", buf, 4))
 				break;
 			if (!strncmp("sha256", buf, 6))
 				break;
 			if (!strncmp("sha384", buf, 6))
 				break;
 			if (!strncmp("sha512", buf, 6))
 				break;
 			knet_vty_write(vty, "unknown hash method: %s. Supported none/md5/sha1/sha256/sha384/sha512%s", param, telnet_newline);
 			err = -1;
 			break;
 		case CMDS_PARAM_POLICY:
 			param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen);
 			if (!strncmp("passive", buf, 7))
 				break;
 			if (!strncmp("active", buf, 6))
 				break;
 			if (!strncmp("round-robin", buf, 11))
 				break;
 			knet_vty_write(vty, "unknown switching policy: %s. Supported passive/active/round-robin%s", param, telnet_newline);
 			err = -1;
 			break;
 		case CMDS_PARAM_LINK_ID:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp < 0) || (tmp > 7)) {
 				knet_vty_write(vty, "link id should be a value between 0 and 7%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_LINK_TRANSP:
 			param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen);
 			if (knet_handle_get_transport_id_by_name(knet_iface->cfg_ring.knet_h, buf) == KNET_MAX_TRANSPORTS) {
 				knet_vty_write(vty, "link transport is invalid%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_LINK_PRI:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp < 0) || (tmp > 255)) {
 				knet_vty_write(vty, "link priority should be a value between 0 and 256%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_LINK_KEEPAL:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp <= 0) || (tmp > 60000)) {
 				knet_vty_write(vty, "link keepalive should be a value between 0 and 60000 (milliseconds). Default: 1000%s", telnet_newline);
 				err = -1;
 			}
 			break; 
 		case CMDS_PARAM_LINK_HOLDTI: 
 			tmp = param_to_int(param, paramlen);
 			if ((tmp <= 0) || (tmp > 60000)) {
 				knet_vty_write(vty, "link holdtimer should be a value between 0 and 60000 (milliseconds). Default: 5000%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_LINK_PONG:
 			tmp = param_to_int(param, paramlen);
 			if (tmp < 1) {
 				knet_vty_write(vty, "pong_count must be a value between 0 and 255%s", telnet_newline);
 				err = -1;
 			}
 			break;
 		case CMDS_PARAM_VTY_TIMEOUT:
 			tmp = param_to_int(param, paramlen);
 			if ((tmp < 0) || (tmp > 3600)) {
 				knet_vty_write(vty, "vty logout timeout should be a value between 0 (disabled) and 3600 seconds. Default: %d%s", KNET_VTY_CLI_TIMEOUT, telnet_newline);
 			}
 			break;
 		default:
 			knet_vty_write(vty, "CLI ERROR: unknown parameter type%s", telnet_newline);
 			err = -1;
 			break;
 	}
 	return err;
 }
 
 static void describe_param(struct knet_vty *vty, const int paramtype)
 {
 	switch(paramtype) {
 		case CMDS_PARAM_NOMORE:
 			knet_vty_write(vty, "no more parameters%s", telnet_newline);
 			break;
 		case CMDS_PARAM_KNET:
 			knet_vty_write(vty, "KNET_IFACE_NAME - interface name (max %d chars) eg: kronosnet0%s", IFNAMSIZ, telnet_newline);
 			break;
 		case CMDS_PARAM_IP:
 			knet_vty_write(vty, "IP address - ipv4 or ipv6 address to add/remove%s", telnet_newline);
 			break;
 		case CMDS_PARAM_IP_PREFIX:
 			knet_vty_write(vty, "IP prefix len (eg. 24, 64)%s", telnet_newline);
 			break;
 		case CMDS_PARAM_IP_PORT:
 			knet_vty_write(vty, "base port (eg: %d) %s", KNET_RING_DEFPORT, telnet_newline);
 		case CMDS_PARAM_BOOL:
 			break;
 		case CMDS_PARAM_INT:
 			break;
 		case CMDS_PARAM_NODEID:
 			knet_vty_write(vty, "NODEID - unique identifier for this interface in this kronos network (value between 0 and 255)%s", telnet_newline);
 			break;
 		case CMDS_PARAM_NAME:
 			knet_vty_write(vty, "NAME - unique name identifier for this entity (max %d chars)%s", KNET_MAX_HOST_LEN - 1, telnet_newline);
 			break;
 		case CMDS_PARAM_MTU:
 			knet_vty_write(vty, "MTU - a value between 576 and 65536 (note: max value depends on the media)%s", telnet_newline);
 			break;
 		case CMDS_PARAM_PMTU_FREQ:
 			knet_vty_write(vty, "PMTUd frequency - a value in seconds between 5 and 600 (default: 5)%s", telnet_newline);
 			break;
 		case CMDS_PARAM_CRYPTO_MODEL:
 			knet_vty_write(vty, "MODEL - define encryption backend: none or nss%s", telnet_newline);
 			break;
 		case CMDS_PARAM_CRYPTO_TYPE:
 			knet_vty_write(vty, "CRYPTO - define packets encryption method: none or aes256%s", telnet_newline);
 			break;
 		case CMDS_PARAM_HASH_TYPE:
 			knet_vty_write(vty, "HASH - define packets hashing method: none/md5/sha1/sha256/sha384/sha512%s", telnet_newline);
 			break;
 		case CMDS_PARAM_POLICY:
 			knet_vty_write(vty, "POLICY - define packets switching policy: passive/active/round-robin%s", telnet_newline);
 			break;
 		case CMDS_PARAM_LINK_ID:
 			knet_vty_write(vty, "LINKID - specify the link identification number (0-7)%s", telnet_newline);
 			break;
 		case CMDS_PARAM_LINK_TRANSP:
 			knet_vty_write(vty, "TRANSPORT - specify the link transport protocol (UDP/SCTP/..)%s", telnet_newline);
 			break;
 		case CMDS_PARAM_LINK_PRI:
 			knet_vty_write(vty, "PRIORITY - specify the link priority for passive switching (0 to 255, default is 0). The higher value is preferred over lower value%s", telnet_newline);
 			break;
 		case CMDS_PARAM_LINK_KEEPAL:
 			knet_vty_write(vty, "KEEPALIVE - specify the keepalive interval for this link (0 to 60000 milliseconds, default is 1000).%s", telnet_newline);
 			break;
 		case CMDS_PARAM_LINK_HOLDTI:
 			knet_vty_write(vty, "HOLDTIME - specify how much time has to pass without connection before a link is considered dead (0 to 60000 milliseconds, default is 5000).%s", telnet_newline);
 			break;
 		case CMDS_PARAM_VTY_TIMEOUT:
 			knet_vty_write(vty, "VTY_TIMEOUT - specify the number of seconds before a session is automatically closed.%s", telnet_newline);
 			break;
 		default: /* this should never happen */
 			knet_vty_write(vty, "CLI ERROR: unknown parameter type%s", telnet_newline);
 			break;
 	}
 }
 
 static void print_help(struct knet_vty *vty, const vty_node_cmds_t *cmds, int idx)
 {
 	if ((idx < 0) || (cmds == NULL) || (cmds[idx].cmd == NULL))
 		return;
 
 	if (cmds[idx].help != NULL) {
 		knet_vty_write(vty, "%s\t%s%s",
 			cmds[idx].cmd,
 			cmds[idx].help,
 			telnet_newline);
 	} else {
 		knet_vty_write(vty, "%s\tNo help available for this command%s",
 			cmds[idx].cmd,
 			telnet_newline);
 	}
 }
 
 static int get_param(struct knet_vty *vty, int wanted_paranum,
 			      char **param, int *paramlen, int *paramoffset)
 {
 	int eparams, tparams;
 	const vty_param_t *params = (const vty_param_t *)vty->param;
 	int paramstart = vty->paramoffset;
 
 	eparams = expected_params(params);
 	tparams = count_words(vty, paramstart);
 
 	if (tparams > eparams)
 		return -1;
 
 	if (wanted_paranum == -1) {
 		get_n_word_from_end(vty, 1, param, paramlen, paramoffset);
 		return tparams;
 	}
 
 	if (tparams < wanted_paranum)
 		return -1;
 
 	get_n_word_from_end(vty, (tparams - wanted_paranum) + 1, param, paramlen, paramoffset);
 	return tparams - wanted_paranum;
 }
 
 
 static int match_command(struct knet_vty *vty, const vty_node_cmds_t *cmds,
 			 char *cmd, int cmdlen, int cmdoffset, int mode)
 {
 	int idx = 0, found = -1, paramoffset = 0, paramlen = 0, last_param = 0;
 	char *param = NULL;
 	int paramstart = cmdlen + cmdoffset;
 	int matches[KNET_VTY_MAX_MATCHES];
 
 	memset(&matches, -1, sizeof(matches));
 
 	while ((cmds[idx].cmd != NULL) && (idx < KNET_VTY_MAX_MATCHES)) {
 		if (!strncmp(cmds[idx].cmd, cmd, cmdlen)) {
 			found++;
 			matches[found] = idx;
 		}
 		idx++;
 	}
 
 	if (idx >= KNET_VTY_MAX_MATCHES) {
 		knet_vty_write(vty, "Too many matches for this command%s", telnet_newline);
 		return -1;
 	}
 
 	if (found < 0) {
 		knet_vty_write(vty, "There is no such command%s", telnet_newline);
 		return -1;
 	}
 
 	switch(mode) {
 		case KNET_VTY_MATCH_HELP:
 			if (found == 0) {
 				if ((cmdoffset <= vty->cursor_pos) && (vty->cursor_pos <= paramstart)) {
 					print_help(vty, cmds, matches[0]);
 					break;
 				}
 				if (cmds[matches[0]].params != NULL) {
 					vty->param = (void *)cmds[matches[0]].params;
 					vty->paramoffset = paramstart;
 					last_param = get_param(vty, -1, &param, &paramlen, &paramoffset);
 
 					if ((paramoffset <= vty->cursor_pos) && (vty->cursor_pos <= (paramoffset + paramlen)))
 						last_param--;
 
 					if (last_param >= CMDS_PARAM_NOMORE) {
 						describe_param(vty, cmds[matches[0]].params[last_param].param);
 						if (paramoffset > 0)
 							check_param(vty, cmds[matches[0]].params[last_param].param, param, paramlen);
 					}
 					break;
 				}
 			}
 			if (found >= 0) {
 				idx = 0;
 				while (matches[idx] >= 0) {
 					print_help(vty, cmds, matches[idx]);
 					idx++;
 				}
 			}
 			break;
 		case KNET_VTY_MATCH_EXEC:
 			if (found == 0) {
 				int exec = 0;
 				if (cmds[matches[0]].params != NULL) {
 					int eparams, tparams;
 
 					eparams = expected_params(cmds[matches[0]].params);
 					tparams = count_words(vty, paramstart);
 
 					if (eparams != tparams) {
 						exec = -1;
 						idx = 0;
 
 						knet_vty_write(vty, "Parameter required for this command:%s", telnet_newline);
 
 						while(cmds[matches[0]].params[idx].param != CMDS_PARAM_NOMORE) {
 							describe_param(vty, cmds[matches[0]].params[idx].param);
 							idx++;
 						}
 						break;
 					}
 
 					idx = 0;
 					vty->param = (void *)cmds[matches[0]].params;
 					vty->paramoffset = paramstart;
 					while(cmds[matches[0]].params[idx].param != CMDS_PARAM_NOMORE) {
 						get_param(vty, idx + 1, &param, &paramlen, &paramoffset);
 						if (check_param(vty, cmds[matches[0]].params[idx].param,
 								param, paramlen) < 0) {
 							exec = -1;
 							if (vty->filemode)
 								return -1;
 						}
 
 						idx++;
 					}
 				}
 				if (!exec) {
 					if (cmds[matches[0]].params != NULL) {
 						vty->param = (void *)cmds[matches[0]].params;
 						vty->paramoffset = paramstart;
 					}
 					if (cmds[matches[0]].func != NULL) {
 						return cmds[matches[0]].func(vty);
 					} else { /* this will eventually disappear */
 						knet_vty_write(vty, "no fn associated to this command%s", telnet_newline);
 					}
 				}
 			}
 			if (found > 0) {
 				knet_vty_write(vty, "Ambiguous command.%s", telnet_newline);
 			}
 			break;
 		case KNET_VTY_MATCH_EXPAND:
 			if (found == 0) {
 				int cmdreallen;
 
 				if (vty->cursor_pos > cmdoffset+cmdlen) /* complete param? */
 					break;
 
 				cmdreallen = strlen(cmds[matches[0]].cmd);
 				memset(vty->line + cmdoffset, 0, cmdlen);
 				memmove(vty->line + cmdoffset, cmds[matches[0]].cmd, cmdreallen);
 				vty->line[cmdreallen + cmdoffset] = ' ';
 				vty->line_idx = cmdreallen + cmdoffset + 1;
 				vty->cursor_pos = cmdreallen + cmdoffset + 1;
 			}
 			if (found > 0) { /* add completion to string base root */
 				int count = 0;
 				idx = 0;
 				while (matches[idx] >= 0) {
 					knet_vty_write(vty, "%s\t\t", cmds[matches[idx]].cmd);
 					idx++;
 					count++;
 					if (count == 4) {
 						knet_vty_write(vty, "%s",telnet_newline);
 						count = 0;
 					}
 				}
 				knet_vty_write(vty, "%s",telnet_newline);
 			}
 			break;
 		default: /* this should never really happen */
 			log_info("Unknown match mode");
 			break;
 	}
 	return found;
 }
 
 /* forward declarations */
 
 /* common to almost all nodes */
 static int knet_cmd_logout(struct knet_vty *vty);
 static int knet_cmd_who(struct knet_vty *vty);
 static int knet_cmd_exit_node(struct knet_vty *vty);
 static int knet_cmd_help(struct knet_vty *vty);
 
 /* root node */
 static int knet_cmd_config(struct knet_vty *vty);
 
 /* config node */
 static int knet_cmd_interface(struct knet_vty *vty);
 static int knet_cmd_no_interface(struct knet_vty *vty);
 static int knet_cmd_status(struct knet_vty *vty);
 static int knet_cmd_show_conf(struct knet_vty *vty);
 static int knet_cmd_write_conf(struct knet_vty *vty);
 
 /* interface node */
 static int knet_cmd_mtu(struct knet_vty *vty);
 static int knet_cmd_no_mtu(struct knet_vty *vty);
 static int knet_cmd_ip(struct knet_vty *vty);
 static int knet_cmd_no_ip(struct knet_vty *vty);
 static int knet_cmd_peer(struct knet_vty *vty);
 static int knet_cmd_no_peer(struct knet_vty *vty);
 static int knet_cmd_start(struct knet_vty *vty);
 static int knet_cmd_stop(struct knet_vty *vty);
 static int knet_cmd_crypto(struct knet_vty *vty);
 static int knet_cmd_pmtufreq(struct knet_vty *vty);
 static int knet_cmd_no_pmtufreq(struct knet_vty *vty);
 
 
 /* peer node */
 static int knet_cmd_link(struct knet_vty *vty);
 static int knet_cmd_no_link(struct knet_vty *vty);
 static int knet_cmd_switch_policy(struct knet_vty *vty);
 
 /* link node */
 static int knet_cmd_link_pri(struct knet_vty *vty);
 static int knet_cmd_link_pong(struct knet_vty *vty);
 static int knet_cmd_link_timer(struct knet_vty *vty);
 
 /* vty node */
 static int knet_cmd_vty(struct knet_vty *vty);
 static int knet_cmd_vty_timeout(struct knet_vty *vty);
 
 /* root node description */
 vty_node_cmds_t root_cmds[] = {
 	{ "configure", "enter configuration mode", NULL, knet_cmd_config },
 	{ "exit", "exit from CLI", NULL, knet_cmd_logout },
 	{ "help", "display basic help", NULL, knet_cmd_help },
 	{ "logout", "exit from CLI", NULL, knet_cmd_logout },
 	{ "status", "display current network status", NULL, knet_cmd_status },
 	{ "vty", "enter vty configuration mode", NULL, knet_cmd_vty },
 	{ "who", "display users connected to CLI", NULL, knet_cmd_who },
 	{ NULL, NULL, NULL, NULL },
 };
 
 /* config node description */
 vty_param_t no_int_params[] = {
 	{ CMDS_PARAM_KNET },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_node_cmds_t no_config_cmds[] = {
 	{ "interface", "destroy kronosnet interface", no_int_params, knet_cmd_no_interface },
 	{ NULL, NULL, NULL, NULL },
 };
 
 vty_param_t int_params[] = {
 	{ CMDS_PARAM_KNET },
 	{ CMDS_PARAM_NODEID },
 	{ CMDS_PARAM_IP_PORT },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_node_cmds_t config_cmds[] = {
 	{ "exit", "exit configuration mode", NULL, knet_cmd_exit_node },
 	{ "interface", "configure kronosnet interface", int_params, knet_cmd_interface },
 	{ "show", "show running config", NULL, knet_cmd_show_conf },
 	{ "help", "display basic help", NULL, knet_cmd_help },
 	{ "logout", "exit from CLI", NULL, knet_cmd_logout },
 	{ "no", "revert command", NULL, NULL },
 	{ "status", "display current network status", NULL, knet_cmd_status },
 	{ "vty", "enter vty configuration mode", NULL, knet_cmd_vty },
 	{ "who", "display users connected to CLI", NULL, knet_cmd_who },
 	{ "write", "write current config to file", NULL, knet_cmd_write_conf },
 	{ NULL, NULL, NULL, NULL },
 };
 
 /* interface node description */
 
 vty_param_t ip_params[] = {
 	{ CMDS_PARAM_IP },
 	{ CMDS_PARAM_IP_PREFIX },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_param_t peer_params[] = {
 	{ CMDS_PARAM_NAME },
 	{ CMDS_PARAM_NODEID },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_node_cmds_t no_interface_cmds[] = {
 	{ "ip", "remove ip address", ip_params, knet_cmd_no_ip },
 	{ "mtu", "revert to default MTU", NULL, knet_cmd_no_mtu },
 	{ "pmtudfreq", "revert to default PMTUd frequency (default: 5)", NULL, knet_cmd_no_pmtufreq },
 	{ "peer", "remove peer from this interface", peer_params, knet_cmd_no_peer },
 	{ NULL, NULL, NULL, NULL },
 };
 
 vty_param_t mtu_params[] = {
 	{ CMDS_PARAM_MTU },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_param_t pmtu_params[] = {
 	{ CMDS_PARAM_PMTU_FREQ },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_param_t crypto_params[] = {
 	{ CMDS_PARAM_CRYPTO_MODEL },
 	{ CMDS_PARAM_CRYPTO_TYPE },
 	{ CMDS_PARAM_HASH_TYPE },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_node_cmds_t interface_cmds[] = {
 	{ "crypto", "enable crypto/hmac", crypto_params, knet_cmd_crypto },
 	{ "exit", "exit configuration mode", NULL, knet_cmd_exit_node },
 	{ "help", "display basic help", NULL, knet_cmd_help },
 	{ "ip", "add ip address", ip_params, knet_cmd_ip },
 	{ "logout", "exit from CLI", NULL, knet_cmd_logout },
 	{ "mtu", "set mtu (default: auto)", mtu_params, knet_cmd_mtu },
 	{ "pmtudfreq", "PMTUd frequency (default: 5)", pmtu_params, knet_cmd_pmtufreq },
 	{ "no", "revert command", NULL, NULL },
 	{ "peer", "add peer endpoint", peer_params, knet_cmd_peer },
 	{ "show", "show running config", NULL, knet_cmd_show_conf },
 	{ "start", "start forwarding engine", NULL, knet_cmd_start },
 	{ "status", "display current network status", NULL, knet_cmd_status },
 	{ "stop", "stop forwarding engine", NULL, knet_cmd_stop },
 	{ "who", "display users connected to CLI", NULL, knet_cmd_who },
 	{ "write", "write current config to file", NULL, knet_cmd_write_conf },
 	{ NULL, NULL, NULL, NULL },
 };
 
 /* peer node description */
 
 vty_param_t nolink_params[] = {
 	{ CMDS_PARAM_LINK_ID },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_param_t link_params[] = {
 	{ CMDS_PARAM_LINK_ID },
 	{ CMDS_PARAM_IP },
 	{ CMDS_PARAM_IP },
 	{ CMDS_PARAM_LINK_TRANSP },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_param_t switch_params[] = {
 	{ CMDS_PARAM_POLICY },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_node_cmds_t no_peer_cmds[] = {
 	{ "link", "remove peer endpoint", nolink_params, knet_cmd_no_link},
 	{ NULL, NULL, NULL, NULL },
 };
 
 vty_node_cmds_t peer_cmds[] = {
 	{ "exit", "exit configuration mode", NULL, knet_cmd_exit_node },
 	{ "help", "display basic help", NULL, knet_cmd_help },
 	{ "link", "add peer endpoint", link_params, knet_cmd_link },
 	{ "logout", "exit from CLI", NULL, knet_cmd_logout },
 	{ "no", "revert command", NULL, NULL },
 	{ "show", "show running config", NULL, knet_cmd_show_conf },
 	{ "status", "display current network status", NULL, knet_cmd_status },
 	{ "switch-policy", "configure switching policy engine", switch_params, knet_cmd_switch_policy },
 	{ "who", "display users connected to CLI", NULL, knet_cmd_who },
 	{ "write", "write current config to file", NULL, knet_cmd_write_conf },
 	{ NULL, NULL, NULL, NULL },
 };
 
 /* link node description */
 
 vty_param_t link_pri_params[] = {
 	{ CMDS_PARAM_LINK_PRI },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_param_t link_timer_params[] = {
 	{ CMDS_PARAM_LINK_KEEPAL },
 	{ CMDS_PARAM_LINK_HOLDTI },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_param_t pong_count_params[] = {
 	{ CMDS_PARAM_LINK_PONG },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_node_cmds_t link_cmds[] = {
 	{ "exit", "exit configuration mode", NULL, knet_cmd_exit_node },
 	{ "help", "display basic help", NULL, knet_cmd_help },
 	{ "logout", "exit from CLI", NULL, knet_cmd_logout },
 	{ "no", "revert command", NULL, NULL },
 	{ "pong_count", "set number of pongs to be received before a link is considered alive", pong_count_params, knet_cmd_link_pong },
 	{ "priority", "set priority of this link for passive switching", link_pri_params, knet_cmd_link_pri },
 	{ "show", "show running config", NULL, knet_cmd_show_conf },
 	{ "status", "display current network status", NULL, knet_cmd_status },
 	{ "timers", "set link keepalive and holdtime", link_timer_params, knet_cmd_link_timer },
 	{ "who", "display users connected to CLI", NULL, knet_cmd_who },
 	{ "write", "write current config to file", NULL, knet_cmd_write_conf },
 	{ NULL, NULL, NULL, NULL },
 };
 
 vty_param_t vty_timeout_params[] = {
 	{ CMDS_PARAM_VTY_TIMEOUT },
 	{ CMDS_PARAM_NOMORE },
 };
 
 vty_node_cmds_t vty_cmds[] = {
 	{ "exit", "exit configuration mode", NULL, knet_cmd_exit_node },
 	{ "help", "display basic help", NULL, knet_cmd_help },
 	{ "logout", "exit from CLI", NULL, knet_cmd_logout },
 	{ "show", "show running config", NULL, knet_cmd_show_conf },
 	{ "status", "display current network status", NULL, knet_cmd_status },
 	{ "timeout", "set number of seconds before session is automatically closed", vty_timeout_params, knet_cmd_vty_timeout },
 	{ "who", "display users connected to CLI", NULL, knet_cmd_who },
 	{ "write", "write current config to file", NULL, knet_cmd_write_conf },
 	{ NULL, NULL, NULL, NULL },
 };
 
 /* nodes */
 vty_nodes_t knet_vty_nodes[] = {
 	{ NODE_ROOT, "knet", root_cmds, NULL },
 	{ NODE_CONFIG, "config", config_cmds, no_config_cmds },
 	{ NODE_INTERFACE, "iface", interface_cmds, no_interface_cmds },
 	{ NODE_PEER, "peer", peer_cmds, no_peer_cmds },
 	{ NODE_LINK, "link", link_cmds, NULL },
 	{ NODE_VTY, "vty", vty_cmds, NULL },
 	{ -1, NULL, NULL, NULL },
 };
 
 /* command execution */
 
 /* vty */
 static int knet_cmd_vty_timeout(struct knet_vty *vty)
 {
 	int paramlen = 0, paramoffset = 0, timeout;
 	char *param = NULL;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	timeout = param_to_int(param, paramlen);
 
 	if ((vty->filemode) || (vty->prevnode == NODE_CONFIG)) {
 		vty->vty_global_conf->idle_timeout = timeout;
 	}
 	vty->idle_timeout = timeout;
 
 	return 0;
 }
 
 static int knet_cmd_vty(struct knet_vty *vty)
 {
 	vty->prevnode = vty->node;
 	vty->node = NODE_VTY;
 	return 0;
 }
 
 /* links */
 
 static int knet_cmd_link_pong(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 	uint8_t pong_count;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	pong_count = param_to_int(param, paramlen);
 
 	knet_link_set_pong_count(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, pong_count);
 
 	return 0;
 }
 
 static int knet_cmd_link_timer(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 	time_t keepalive, holdtime;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	keepalive = param_to_int(param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	holdtime = param_to_int(param, paramlen);
 
 	knet_link_set_ping_timers(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, keepalive, holdtime, 2048);
 
 	return 0;
 }
 
 static int knet_cmd_link_pri(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 	uint8_t priority;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	priority = param_to_int(param, paramlen);
 
 	if (knet_link_set_priority(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, priority)) {
 		knet_vty_write(vty, "Error: unable to update link priority%s", telnet_newline);
 		return -1;
 	}
 
 	return 0;
 }
 
 static int knet_cmd_no_link(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	struct knet_link_status status;
 	int paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	vty->link_id = param_to_int(param, paramlen);
 
 	knet_link_get_status(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, &status, sizeof(status));
 
 	if (status.enabled) {
 		if (knet_link_set_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 0)) {
 			knet_vty_write(vty, "Error: unable to update switching cache%s", telnet_newline);
 			return -1;
 		}
 		knet_link_clear_config(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id);
 	}
 
 	return 0;
 }
 
 static int knet_cmd_link(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	struct knet_link_status status;
 	int paramlen = 0, paramoffset = 0, err = 0;
 	char *param = NULL;
 	char src_ipaddr[KNET_MAX_HOST_LEN], src_port[KNET_MAX_PORT_LEN], dst_ipaddr[KNET_MAX_HOST_LEN], dst_port[KNET_MAX_PORT_LEN];
 	struct sockaddr_storage src_addr;
 	struct sockaddr_storage dst_addr;
 	struct sockaddr_storage *dst = NULL;
 	char transport[10];
 	uint8_t transport_id;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	vty->link_id = param_to_int(param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	param_to_str(src_ipaddr, KNET_MAX_HOST_LEN, param, paramlen);
 
 	memset(src_port, 0, sizeof(src_port));
 	snprintf(src_port, KNET_MAX_PORT_LEN, "%d", knet_iface->cfg_ring.base_port + vty->host_id);
 
 	get_param(vty, 3, &param, &paramlen, &paramoffset);
 	param_to_str(dst_ipaddr, KNET_MAX_HOST_LEN, param, paramlen);
 
 	memset(dst_port, 0, sizeof(dst_port));
 	snprintf(dst_port, KNET_MAX_PORT_LEN, "%d", knet_iface->cfg_ring.base_port + knet_iface->cfg_eth.node_id);
 
 	get_param(vty, 4, &param, &paramlen, &paramoffset);
 	param_to_str(transport, sizeof(transport), param, paramlen);
 
 	transport_id = knet_handle_get_transport_id_by_name(knet_iface->cfg_ring.knet_h, transport);
 
 	knet_link_get_status(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, &status, sizeof(status));
 	if (!status.enabled) {
 		if (knet_strtoaddr(src_ipaddr, src_port, &src_addr, sizeof(struct sockaddr_storage)) != 0) {
 			knet_vty_write(vty, "Error: unable to convert source ip addr to sockaddr!%s", telnet_newline);
 			err = -1;
 			goto out_clean;
 		}
 
 		if (!strncmp(dst_ipaddr, "dynamic", 7)) {
 			dst = NULL;
 		} else {
 			if (knet_strtoaddr(dst_ipaddr, dst_port, &dst_addr, sizeof(struct sockaddr_storage)) != 0) {
 				knet_vty_write(vty, "Error: unable to convert destination ip addr to sockaddr!%s", telnet_newline);
 				err = -1;
 				goto out_clean;
 			}
 			dst = &dst_addr;
 		}
 
 		knet_link_set_config(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, transport_id, &src_addr, dst, KNET_LINK_FLAG_TRAFFICHIPRIO);
 
 		knet_link_set_ping_timers(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 1000, 5000, 2048);
 
 		knet_link_set_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 1);
 	}
 
 	vty->node = NODE_LINK;
 
 out_clean:
 	return err;
 }
 
 static int knet_cmd_switch_policy(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0, err = 0;
 	char *param = NULL;
 	char policystr[16];
 	int policy = -1;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(policystr, sizeof(policystr), param, paramlen);
 
 	if (!strncmp("passive", policystr, 7))
 		policy = KNET_LINK_POLICY_PASSIVE;
 	if (!strncmp("active", policystr, 6))
 		policy = KNET_LINK_POLICY_ACTIVE;
 	if (!strncmp("round-robin", policystr, 11))
 		policy = KNET_LINK_POLICY_RR;
 
 	if (policy < 0) {
 		knet_vty_write(vty, "Error: unknown switching policy method%s", telnet_newline);
 		return -1;
 	}
 
 	err = knet_host_set_policy(knet_iface->cfg_ring.knet_h, vty->host_id, policy);
 	if (err)
 		knet_vty_write(vty, "Error: unable to set switching policy to %s%s", policystr, telnet_newline);
 
 	return err;
 }
 
 /*
  * -1 on internal error
  *  0 host does not exist
  *  1 host exists
  */
 static int knet_find_host(struct knet_vty *vty,	const char *nodename, const knet_node_id_t requested_node_id)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int have_nodeid, have_name;
 	knet_node_id_t node_id;
 	char name[KNET_MAX_HOST_LEN];
 
 	have_nodeid = knet_host_get_id_by_host_name(knet_iface->cfg_ring.knet_h, nodename, &node_id);
 	have_name = knet_host_get_name_by_host_id(knet_iface->cfg_ring.knet_h, requested_node_id, name);
 
 	/*
 	 * host does not exist without a name
 	 */
 	if (have_name < 0) {
 		return 0;
 	}
 
 	/*
 	 * internal error.. get out
 	 */
 	if (have_nodeid < 0) {
 		knet_vty_write(vty, "Error: unable to query libknet for nodeid info%s", telnet_newline);
 		return -1;
 	}
 
 	if ((!have_name) && (!have_nodeid)) {
 		if (!strcmp(name, nodename) && (node_id == requested_node_id))
 			return 1;
 	}
 
 	knet_vty_write(vty, "Error: requested nodename or id already exists in libknet%s", telnet_newline);
 
 	return -1;
 }
 
 static int knet_cmd_no_peer(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0, requested_node_id = 0, err = 0;
 	char *param = NULL;
 	char nodename[KNET_MAX_HOST_LEN];
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(nodename, sizeof(nodename), param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	requested_node_id = param_to_int(param, paramlen);
 
 	if (requested_node_id == knet_iface->cfg_eth.node_id) {
 		knet_vty_write(vty, "Error: remote peer id cannot be the same as local id%s", telnet_newline);
 		return -1;
 	}
 
 	err = knet_find_host(vty, nodename, requested_node_id);
 	if (err < 0)
 		goto out_clean;
 
 	if (err != 1) {
 		knet_vty_write(vty, "Error: peer not found in list%s", telnet_newline);
 		goto out_clean;
 	}
 
 	err = knet_host_remove(knet_iface->cfg_ring.knet_h, requested_node_id);
 	if (err < 0) {
 		knet_vty_write(vty, "Error: unable to remove peer from current config%s", telnet_newline);
 		goto out_clean;
 	}
 
 out_clean:
 	return err;
 }
 
 static int knet_cmd_peer(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0, requested_node_id = 0, err = 0, host = 0;
 	char *param = NULL;
 	char nodename[KNET_MAX_HOST_LEN];
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(nodename, sizeof(nodename), param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	requested_node_id = param_to_int(param, paramlen);
 
 	if (requested_node_id == knet_iface->cfg_eth.node_id) {
 		knet_vty_write(vty, "Error: remote peer id cannot be the same as local id%s", telnet_newline);
 		return -1;
 	}
 
 	err = knet_find_host(vty, nodename, requested_node_id);
 	if (err < 0)
 		goto out_clean;
 
 	if (err == 0) {
 		err = knet_host_add(knet_iface->cfg_ring.knet_h, requested_node_id);
 		if (err < 0) {
 			knet_vty_write(vty, "Error: unable to allocate memory for host struct!%s", telnet_newline);
 			goto out_clean;
 		}
 		host = 1;
 		knet_host_set_name(knet_iface->cfg_ring.knet_h, requested_node_id, nodename);
 		knet_host_set_policy(knet_iface->cfg_ring.knet_h, requested_node_id, KNET_LINK_POLICY_PASSIVE);
 	}
 
 	vty->host_id = requested_node_id;
 	vty->node = NODE_PEER;
 
 out_clean:
 	if (err < 0) {
 		if (host)
 			knet_host_remove(knet_iface->cfg_ring.knet_h, requested_node_id);
 	}
 
 	return err;
 }
 
 static int knet_cmd_no_ip(struct knet_vty *vty)
 {
 	int paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 	char ipaddr[KNET_MAX_HOST_LEN], prefix[4];
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	char *error_string = NULL;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(ipaddr, sizeof(ipaddr), param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	param_to_str(prefix, sizeof(prefix), param, paramlen);
 
 	if (tap_del_ip(knet_iface->cfg_eth.tap, ipaddr, prefix, &error_string) < 0) {
 		knet_vty_write(vty, "Error: Unable to del ip addr %s/%s on device %s%s",
 				ipaddr, prefix, tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 		if (error_string) {
 			knet_vty_write(vty, "(%s)%s", error_string, telnet_newline);
 			free(error_string);
 		}
 		return -1;
 	}
 
 	return 0;
 }
 
 static int knet_cmd_ip(struct knet_vty *vty)
 {
 	int paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 	char ipaddr[512], prefix[4];
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	char *error_string = NULL;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(ipaddr, sizeof(ipaddr), param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	param_to_str(prefix, sizeof(prefix), param, paramlen);
 
 	if (tap_add_ip(knet_iface->cfg_eth.tap, ipaddr, prefix, &error_string) < 0) {
 		knet_vty_write(vty, "Error: Unable to set ip addr %s/%s on device %s%s",
 				ipaddr, prefix, tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 		if (error_string) {
 			knet_vty_write(vty, "(%s)%s", error_string, telnet_newline);
 			free(error_string);
 		}
 		return -1;
 	}
 
 	return 0;
 }
 
 static void knet_cmd_auto_mtu_notify(void *private_data,
 				     unsigned int data_mtu)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)private_data;
 
 	/*
 	 * 48 is the magic number! yes it is.. it's the magic number...
 	 */
 	knet_iface->cfg_ring.data_mtu = data_mtu - 48;
 
 	if (!knet_iface->cfg_eth.auto_mtu) {
 		int mtu = 0;
 
 		mtu = tap_get_mtu(knet_iface->cfg_eth.tap);
 		if (mtu < 0) {
 			log_debug("Unable to get current MTU?");
 		} else {
 			if (data_mtu < (unsigned int)mtu) {
 				log_debug("Manually configured MTU (%d) is higher than automatically detected MTU (%d)",
 					  mtu, data_mtu);
 			}
 		}
 
 		return;
 	}
 
 	if (tap_set_mtu(knet_iface->cfg_eth.tap, knet_iface->cfg_ring.data_mtu) < 0) {
 		log_warn("Error: Unable to set requested mtu %d on device %s via mtu notify",
 			 knet_iface->cfg_ring.data_mtu, tap_get_name(knet_iface->cfg_eth.tap));
 	} else {
 		log_info("Device %s new mtu: %d (via mtu notify)",
 			 tap_get_name(knet_iface->cfg_eth.tap), knet_iface->cfg_ring.data_mtu);
 	}
 }
 
 static int knet_cmd_no_pmtufreq(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 
 	if (knet_handle_pmtud_setfreq(knet_iface->cfg_ring.knet_h, 5) < 0) {
 		knet_vty_write(vty, "Error: Unable to reset PMTUd frequency to 5 seconds on device %s%s",
 				tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 		return -1;
 	}
 
 	return 0;
 }
 
 static int knet_cmd_pmtufreq(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0, pmtufreq = 5;
 	char *param = NULL;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	pmtufreq = param_to_int(param, paramlen);
 
 	if (knet_handle_pmtud_setfreq(knet_iface->cfg_ring.knet_h, pmtufreq) < 0) {
 		knet_vty_write(vty, "Error: Unable to set PMTUd frequency to %d seconds on device %s%s",
 				pmtufreq, tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 		return -1;
 	}
 
 	return 0;
 }
 
 static int knet_cmd_no_mtu(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 
 	/* allow automatic updates of mtu */
 	knet_iface->cfg_eth.auto_mtu = 1;
 
 	if (knet_iface->cfg_ring.data_mtu > 0) {
 		if (tap_set_mtu(knet_iface->cfg_eth.tap, knet_iface->cfg_ring.data_mtu) < 0) {
 			knet_iface->cfg_eth.auto_mtu = 0;
 			knet_vty_write(vty, "Error: Unable to set auto detected mtu on device %s%s",
 					tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 			return -1;
 		}
 	} else {
 		if (tap_reset_mtu(knet_iface->cfg_eth.tap) < 0) {
 			knet_iface->cfg_eth.auto_mtu = 0;
 			knet_vty_write(vty, "Error: Unable to reset mtu on device %s%s",
 					tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 			return -1;
 		}
 	}
 
 	return 0;
 }
 
 static int knet_cmd_mtu(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0, expected_mtu = 0;
 	char *param = NULL;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	expected_mtu = param_to_int(param, paramlen);
 
 	/* disable mtu auto updates */
 	knet_iface->cfg_eth.auto_mtu = 0;
 
 	if ((knet_iface->cfg_ring.data_mtu) &&
 	    (expected_mtu > knet_iface->cfg_ring.data_mtu)) {
 		knet_vty_write(vty, "WARNING: Manually configured MTU (%d) is higher than automatically detected MTU (%d)%s",
 			       expected_mtu, knet_iface->cfg_ring.data_mtu, telnet_newline);
 	}
 
 	if (tap_set_mtu(knet_iface->cfg_eth.tap, expected_mtu) < 0) {
 		knet_iface->cfg_eth.auto_mtu = 1;
 		knet_vty_write(vty, "Error: Unable to set requested mtu %d on device %s%s",
 				expected_mtu, tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 		return -1;
 	}
 
 	return 0;
 }
 
 static int knet_cmd_stop(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	char *error_down = NULL, *error_postdown = NULL;
 	int err = 0;
 
 	err = tap_set_down(knet_iface->cfg_eth.tap, &error_down, &error_postdown);
 	if (err < 0) {
 		knet_vty_write(vty, "Error: Unable to set interface %s down!%s", tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 	} else {
 		if (knet_iface->cfg_ring.knet_h)
 			knet_handle_setfwd(knet_iface->cfg_ring.knet_h, 0);
 		knet_iface->active = 0;
 	}
 	if (error_down) {
 		knet_vty_write(vty, "down script output:%s(%s)%s", telnet_newline, error_down, telnet_newline);
 		free(error_down);
 	}
 	if (error_postdown) {
 		knet_vty_write(vty, "post-down script output:%s(%s)%s", telnet_newline, error_postdown, telnet_newline);
 		free(error_postdown);
 	}
 
 	return err;
 }
 
 static int knet_cmd_crypto(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	int paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 	int err = 0;
 	struct knet_handle_crypto_cfg knet_handle_crypto_cfg_new;
 	int fd = -1;
 	char keyfile[PATH_MAX];
 	struct stat sb;
 
 	if (knet_iface->active) {
 		knet_vty_write(vty, "Error: Unable to activate encryption while interface is active%s", telnet_newline);
 		return -1;
 	}
 
 	memset(&knet_handle_crypto_cfg_new, 0, sizeof(struct knet_handle_crypto_cfg));
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(knet_handle_crypto_cfg_new.crypto_model,
 		     sizeof(knet_handle_crypto_cfg_new.crypto_model), param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	param_to_str(knet_handle_crypto_cfg_new.crypto_cipher_type,
 		     sizeof(knet_handle_crypto_cfg_new.crypto_cipher_type), param, paramlen);
 
 	get_param(vty, 3, &param, &paramlen, &paramoffset);
 	param_to_str(knet_handle_crypto_cfg_new.crypto_hash_type,
 		     sizeof(knet_handle_crypto_cfg_new.crypto_hash_type), param, paramlen);
 
 	if ((!strncmp("none", knet_handle_crypto_cfg_new.crypto_model, 4)) ||
 	    ((!strncmp("none", knet_handle_crypto_cfg_new.crypto_cipher_type, 4)) &&
 	     ((!strncmp("none", knet_handle_crypto_cfg_new.crypto_hash_type, 4)))))
 		goto no_key;
 
 	memset(keyfile, 0, PATH_MAX);
 	snprintf(keyfile, PATH_MAX - 1, DEFAULT_CONFIG_DIR "/cryptokeys.d/%s", tap_get_name(knet_iface->cfg_eth.tap));
 
 	fd = open(keyfile, O_RDONLY);
 	if (fd < 0) {
 		knet_vty_write(vty, "Error: Unable to open security key: %s%s", keyfile, telnet_newline);
 		err = -1;
 		return -1;
 	}
 
 	if (fstat(fd, &sb)) {
 		knet_vty_write(vty, "Error: Unable to verify security key: %s%s", keyfile, telnet_newline);
 		goto key_error;
 	}
 
 	if (!S_ISREG(sb.st_mode)) {
 		knet_vty_write(vty, "Error: Key %s does not appear to be a regular file%s",
 			       keyfile, telnet_newline);
 		goto key_error;
 	}
 
 	knet_handle_crypto_cfg_new.private_key_len = (unsigned int)sb.st_size;
 	if ((knet_handle_crypto_cfg_new.private_key_len < KNET_MIN_KEY_LEN) ||
 	    (knet_handle_crypto_cfg_new.private_key_len > KNET_MAX_KEY_LEN)) {
 		knet_vty_write(vty, "Error: Key %s is %u long. Must be %d <= key_len <= %d%s",
 			       keyfile, knet_handle_crypto_cfg_new.private_key_len,
 			       KNET_MIN_KEY_LEN, KNET_MAX_KEY_LEN, telnet_newline);
 		goto key_error;
 	}
 
 	if (((sb.st_mode & S_IRWXU) != S_IRUSR) ||
 	    (sb.st_mode & S_IRWXG) ||
 	    (sb.st_mode & S_IRWXO)) {
 		knet_vty_write(vty, "Error: Key %s does not have the correct permission (must be user read-only)%s",
 			       keyfile, telnet_newline);
 		goto key_error;
 	}
 
 	if (read(fd,
 		 &knet_handle_crypto_cfg_new.private_key,
 		 knet_handle_crypto_cfg_new.private_key_len) != knet_handle_crypto_cfg_new.private_key_len) {
 		knet_vty_write(vty, "Error: Unable to read key %s%s", keyfile, telnet_newline);
 		goto key_error;
 	}
 
 	close(fd);
 
 no_key:
 	err = knet_handle_crypto(knet_iface->cfg_ring.knet_h,
 				 &knet_handle_crypto_cfg_new);
 
 	if (!err) {
 		memmove(&knet_iface->knet_handle_crypto_cfg, &knet_handle_crypto_cfg_new, sizeof(struct knet_handle_crypto_cfg));
 	} else {
 		knet_vty_write(vty, "Error: Unable to initialize crypto module%s", telnet_newline);
 	}
 
 	return err;
 
 key_error:
 	close(fd);
 	return -1;
 }
 
 static int knet_cmd_start(struct knet_vty *vty)
 {
 	struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface;
 	char *error_preup = NULL, *error_up = NULL;
 	int err = 0;
 
 	err = tap_set_up(knet_iface->cfg_eth.tap, &error_preup, &error_up);
 	if (err < 0) {
 		knet_vty_write(vty, "Error: Unable to set interface %s up!%s", tap_get_name(knet_iface->cfg_eth.tap), telnet_newline);
 		knet_handle_setfwd(knet_iface->cfg_ring.knet_h, 0);
 	} else {
 		knet_handle_setfwd(knet_iface->cfg_ring.knet_h, 1);
 		knet_iface->active = 1;
 	}
 	if (error_preup) {
 		knet_vty_write(vty, "pre-up script output:%s(%s)%s", telnet_newline, error_preup, telnet_newline);
 		free(error_preup);
 	}
 	if (error_up) {
 		knet_vty_write(vty, "up script output:%s(%s)%s", telnet_newline, error_up, telnet_newline);
 		free(error_up);
 	}
 
 	return err;
 }
 
 static int knet_cmd_no_interface(struct knet_vty *vty)
 {
 	int err = 0, paramlen = 0, paramoffset = 0;
 	char *param = NULL;
 	char device[IFNAMSIZ];
 	struct knet_cfg *knet_iface = NULL;
 	char *ip_list = NULL;
 	int ip_list_entries = 0, offset = 0;
 	size_t j, i;
 	char *error_string = NULL;
 	knet_node_id_t host_ids[KNET_MAX_HOST];
 	uint8_t link_ids[KNET_MAX_LINK];
 	size_t host_ids_entries = 0, link_ids_entries = 0;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(device, IFNAMSIZ, param, paramlen);
 
 	knet_iface = knet_get_iface(device, 0);
 	if (!knet_iface) {
 		knet_vty_write(vty, "Error: Unable to find requested interface%s", telnet_newline);
 		return -1;
 	}
 
 	vty->iface = (void *)knet_iface;
 
 	/*
 	 * disable PTMUd notification before shutting down the tap device
 	 */
 	knet_handle_enable_pmtud_notify(knet_iface->cfg_ring.knet_h, NULL, NULL);
 
 	tap_get_ips(knet_iface->cfg_eth.tap, &ip_list, &ip_list_entries);
 	if ((ip_list) && (ip_list_entries > 0)) {
 		for (i = 1; i <= (size_t)ip_list_entries; i++) {
 			tap_del_ip(knet_iface->cfg_eth.tap,
 					ip_list + offset,
 					ip_list + offset + strlen(ip_list + offset) + 1, &error_string);
 			if (error_string) {
 				free(error_string);
 				error_string = NULL;
 			}
 			offset = offset + strlen(ip_list) + 1;
 			offset = offset + strlen(ip_list + offset) + 1;
 		}
 		free(ip_list);
 		ip_list = NULL;
 		ip_list_entries = 0;
 	}
 
 	knet_host_get_host_list(knet_iface->cfg_ring.knet_h, host_ids, &host_ids_entries);
 	for (j = 0; j < host_ids_entries; j++) {
 		knet_link_get_link_list(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids, &link_ids_entries);
 		for (i = 0; i < link_ids_entries; i++) {
 			knet_link_set_enable(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], 0);
 			knet_link_clear_config(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i]);
 		}
 		knet_host_remove(knet_iface->cfg_ring.knet_h, host_ids[j]);
 	}
 
 	knet_cmd_stop(vty);
 
 	if (knet_iface->cfg_ring.knet_h) {
 		knet_handle_free(knet_iface->cfg_ring.knet_h);
 		knet_iface->cfg_ring.knet_h = NULL;
 	}
 
 	if (knet_iface->cfg_eth.tap)
 		tap_close(knet_iface->cfg_eth.tap);
 
 	if (knet_iface)
 		knet_destroy_iface(knet_iface);
 
 	return err;
 }
 
 static void sock_notify_fn(void *private_data, int datafd, int8_t chan, uint8_t tx_rx, int error, int errorno)
 {
 	struct knet_vty *vty = (struct knet_vty *)private_data;
 
 	knet_vty_write(vty, "Error: received sock notify, datafd: %d channel: %d direction: %u error: %d errno: %d (%s)%s",
 			datafd, chan, tx_rx, error, errorno, strerror(errorno), telnet_newline);
 }
 
 static int knet_cmd_interface(struct knet_vty *vty)
 {
 	int err = 0, paramlen = 0, paramoffset = 0, found = 0, requested_id, tapfd;
 	uint16_t baseport;
 	uint8_t *bport = (uint8_t *)&baseport;
 	char *param = NULL;
 	char device[IFNAMSIZ];
 	char mac[18];
 	struct knet_cfg *knet_iface = NULL;
 	int8_t channel = 0;
 
 	get_param(vty, 1, &param, &paramlen, &paramoffset);
 	param_to_str(device, IFNAMSIZ, param, paramlen);
 
 	get_param(vty, 2, &param, &paramlen, &paramoffset);
 	requested_id = param_to_int(param, paramlen);
 
 	get_param(vty, 3, &param, &paramlen, &paramoffset);
 	baseport = param_to_int(param, paramlen);
 
 	knet_iface = knet_get_iface(device, 1);
 	if (!knet_iface) {
 		knet_vty_write(vty, "Error: Unable to allocate memory for config structures%s",
 				telnet_newline);
 		return -1;
 	}
 
 	if (knet_iface->cfg_eth.tap) {
 		found = 1;
 		goto tap_found;
 	}
 
 	if (!knet_iface->cfg_eth.tap)
 		knet_iface->cfg_eth.tap = tap_open(device, IFNAMSIZ, DEFAULT_CONFIG_DIR);
 
 	if ((!knet_iface->cfg_eth.tap) && (errno == EBUSY)) {
 		knet_vty_write(vty, "Error: interface %s seems to exist in the system%s",
 				device, telnet_newline);
 		err = -1;
 		goto out_clean;
 	}
 
 	if (!knet_iface->cfg_eth.tap) {
 		knet_vty_write(vty, "Error: Unable to create %s system tap device%s",
 				device, telnet_newline);
 		err = -1;
 		goto out_clean;
 	}
 tap_found:
 
 	if (knet_iface->cfg_ring.knet_h)
 		goto knet_found;
 
 	knet_iface->cfg_ring.base_port = baseport;
 
 	tapfd = tap_get_fd(knet_iface->cfg_eth.tap);
 
 	knet_iface->cfg_ring.knet_h = knet_handle_new(requested_id, vty->logfd, vty->loglevel);
 	if (!knet_iface->cfg_ring.knet_h) {
 		knet_vty_write(vty, "Error: Unable to create ring handle for device %s%s",
 				device, telnet_newline);
 		err = -1;
 		goto out_clean;
 	}
 
 	if (knet_handle_enable_sock_notify(knet_iface->cfg_ring.knet_h, &vty, sock_notify_fn)) {
 		knet_vty_write(vty, "Error: Unable to add sock notify callback to to knet_handle %s%s",
 				strerror(errno), telnet_newline);
 		err = -1;
 		goto out_clean;
 	}
 
 	if (knet_handle_add_datafd(knet_iface->cfg_ring.knet_h, &tapfd, &channel) < 0) {
 		knet_vty_write(vty, "Error: Unable to add tapfd to knet_handle %s%s",
 				strerror(errno), telnet_newline);
 		err = -1;
 		goto out_clean;
 	}
 
 	knet_handle_enable_filter(knet_iface->cfg_ring.knet_h, NULL, ether_host_filter_fn);
 
 	if (knet_handle_enable_pmtud_notify(knet_iface->cfg_ring.knet_h,
 					    knet_iface,
 					    knet_cmd_auto_mtu_notify) < 0) {
 		knet_vty_write(vty, "Error: Unable to configure auto mtu notification for device %s%s",
 				device, telnet_newline);
 		err = -1;
 		goto out_clean;
 	}
 	knet_iface->cfg_eth.auto_mtu = 1;
 
 	/*
 	 * make this configurable
 	 */
 	knet_handle_pmtud_setfreq(knet_iface->cfg_ring.knet_h, 5);
 
 knet_found:
 	if (found) {
 		if (requested_id == knet_iface->cfg_eth.node_id)
 			goto out_found;
 
 		knet_vty_write(vty, "Error: no interface %s with nodeid %d found%s",
 				device, requested_id, telnet_newline);
 		goto out_clean;
 
 	} else {
 		knet_iface->cfg_eth.node_id = requested_id;
 	}
 
 	baseport = htons(baseport);
 	memset(&mac, 0, sizeof(mac));
 	snprintf(mac, sizeof(mac) - 1, "54:54:%x:%x:0:%x", bport[0], bport[1], knet_iface->cfg_eth.node_id);
 	if (tap_set_mac(knet_iface->cfg_eth.tap, mac) < 0) {
 		knet_vty_write(vty, "Error: Unable to set mac address %s on device %s%s",
 				mac, device, telnet_newline); 
 		err = -1;
 		goto out_clean;
 	}
 
 out_found:
 
 	vty->node = NODE_INTERFACE;
 	vty->iface = (void *)knet_iface;
 
 out_clean:
 	if (err) {
 		if (knet_iface->cfg_ring.knet_h)
 			knet_handle_free(knet_iface->cfg_ring.knet_h);
 
 		if (knet_iface->cfg_eth.tap)
 			tap_close(knet_iface->cfg_eth.tap);
  
 		knet_destroy_iface(knet_iface);
 	}
 	return err;
 }
 
 static int knet_cmd_exit_node(struct knet_vty *vty)
 {
 	knet_vty_exit_node(vty);
 	return 0;
 }
 
 static int knet_cmd_status(struct knet_vty *vty)
 {
 	size_t i, j;
 	struct knet_cfg *knet_iface = knet_cfg_head.knet_cfg;
 	struct knet_link_status status;
 	const char *nl = telnet_newline;
 	struct timespec now;
 	char nodename[KNET_MAX_HOST_LEN];
 	knet_node_id_t host_ids[KNET_MAX_HOST];
 	uint8_t link_ids[KNET_MAX_LINK];
 	size_t host_ids_entries = 0, link_ids_entries = 0;
 	uint8_t policy;
 
 	clock_gettime(CLOCK_MONOTONIC, &now);
 
 	knet_vty_write(vty, "Current knet status%s", nl);
 	knet_vty_write(vty, "-------------------%s", nl);
 
 	while (knet_iface != NULL) {
 		knet_vty_write(vty, "interface %s (active: %d)%s", tap_get_name(knet_iface->cfg_eth.tap), knet_iface->active, nl);
 
 		knet_host_get_host_list(knet_iface->cfg_ring.knet_h, host_ids, &host_ids_entries);
 
 		for (j = 0; j < host_ids_entries; j++) {
 			knet_host_get_name_by_host_id(knet_iface->cfg_ring.knet_h, host_ids[j], nodename);
 			knet_vty_write(vty, "  peer %s ", nodename);
 
 			knet_host_get_policy(knet_iface->cfg_ring.knet_h, host_ids[j], &policy);
 			switch (policy) {
 				case KNET_LINK_POLICY_PASSIVE:
 					knet_vty_write(vty, "(passive)%s", nl);
 					break;
 				case KNET_LINK_POLICY_ACTIVE:
 					knet_vty_write(vty, "(active)%s", nl);
 					break;
 				case KNET_LINK_POLICY_RR:
 					knet_vty_write(vty, "(round-robin)%s", nl);
 					break;
 			}
 
 			knet_link_get_link_list(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids, &link_ids_entries);
 			for (i = 0; i < link_ids_entries; i++) {
 				uint8_t dynamic, transport;
 				const char *transport_name;
 				struct sockaddr_storage src_addr;
 				struct sockaddr_storage dst_addr;
 				uint64_t flags;
 
 				if (!knet_link_get_config(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &transport, &src_addr, &dst_addr, &dynamic, &flags)) {
 					transport_name = knet_handle_get_transport_name_by_id(knet_iface->cfg_ring.knet_h, transport);
 					knet_link_get_status(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &status, sizeof(status));
 					if (status.enabled == 1) {
 						if (dynamic) {
 							knet_vty_write(vty, "    link %s dynamic (%s/connected: %d)%s", status.src_ipaddr, transport_name, status.connected, nl);
 						} else {
 							knet_vty_write(vty, "    link %s %s (%s/connected: %d)%s", status.src_ipaddr, status.dst_ipaddr, transport_name, status.connected, nl);
 						}
 						if (status.connected) {
 							knet_vty_write(vty, "      average latency: %llu us%s", status.latency, nl);
 							if ((dynamic) && (status.dynconnected)) {
 								knet_vty_write(vty, "      source ip: %s%s", status.dst_ipaddr, nl);
 							}
 						} else {
 							knet_vty_write(vty, "      last heard: ");
 							if (status.pong_last.tv_sec) {
 								knet_vty_write(vty, "%lu s ago%s",
 									(long unsigned int)now.tv_sec - status.pong_last.tv_sec, nl);
 							} else {
 								knet_vty_write(vty, "never%s", nl);
 							}
 						}
 					}
 				}
 			}
 		}
 
 		knet_iface = knet_iface->next;
 	}
 
 	return 0;
 }
 
 static int knet_cmd_print_conf(struct knet_vty *vty)
 {
 	size_t i, j;
 	struct knet_cfg *knet_iface = knet_cfg_head.knet_cfg;
 	struct knet_link_status status;
 	const char *nl = telnet_newline;
 	char *ip_list = NULL;
 	int ip_list_entries = 0;
 	knet_node_id_t host_ids[KNET_MAX_HOST];
 	uint8_t link_ids[KNET_MAX_LINK];
 	size_t host_ids_entries = 0, link_ids_entries = 0;
 	char nodename[KNET_MAX_HOST_LEN];
 	uint8_t policy;
 	unsigned int pmtudfreq = 0;
 
 	if (vty->filemode)
 		nl = file_newline;
 
 	knet_vty_write(vty, "configure%s", nl);
 
 	knet_vty_write(vty, " vty%s", nl);
 	knet_vty_write(vty, "  timeout %d%s", vty->idle_timeout, nl);
 	knet_vty_write(vty, "  exit%s", nl);
 
 	while (knet_iface != NULL) {
 		knet_vty_write(vty, " interface %s %d %d%s", tap_get_name(knet_iface->cfg_eth.tap),
 							     knet_iface->cfg_eth.node_id,
 							     knet_iface->cfg_ring.base_port, nl);
 
 		if (!knet_iface->cfg_eth.auto_mtu)
 			knet_vty_write(vty, "  mtu %d%s", tap_get_mtu(knet_iface->cfg_eth.tap), nl);
 
 		knet_handle_pmtud_getfreq(knet_iface->cfg_ring.knet_h, &pmtudfreq);
 		if ((pmtudfreq > 0) && (pmtudfreq != 5))
 			knet_vty_write(vty, "  pmtudfreq %u%s", pmtudfreq, nl);
 
 		tap_get_ips(knet_iface->cfg_eth.tap, &ip_list, &ip_list_entries);
 		if ((ip_list) && (ip_list_entries > 0)) {
 			char *ipaddr = NULL, *prefix = NULL, *next = ip_list;
 			for (i = 1; i <= (size_t)ip_list_entries; i++) {
 				ipaddr = next;
 				prefix = ipaddr + strlen(ipaddr) + 1;
 				next = prefix + strlen(prefix) + 1;
 				knet_vty_write(vty, "  ip %s %s%s", ipaddr, prefix, nl);
 			}
 			free(ip_list);
 			ip_list = NULL;
 			ip_list_entries = 0;
 		}
 
 		knet_vty_write(vty, "  crypto %s %s %s%s",
 			       knet_iface->knet_handle_crypto_cfg.crypto_model,
 			       knet_iface->knet_handle_crypto_cfg.crypto_cipher_type,
 			       knet_iface->knet_handle_crypto_cfg.crypto_hash_type, nl);
 
 		knet_host_get_host_list(knet_iface->cfg_ring.knet_h, host_ids, &host_ids_entries);
 		for (j = 0; j < host_ids_entries; j++) {
 			knet_host_get_name_by_host_id(knet_iface->cfg_ring.knet_h, host_ids[j], nodename);
 			knet_vty_write(vty, "  peer %s %u%s", nodename, host_ids[j], nl);
 
 			knet_host_get_policy(knet_iface->cfg_ring.knet_h, host_ids[j], &policy);
 			switch (policy) {
 				case KNET_LINK_POLICY_PASSIVE:
 					knet_vty_write(vty, "   switch-policy passive%s", nl);
 					break;
 				case KNET_LINK_POLICY_ACTIVE:
 					knet_vty_write(vty, "   switch-policy active%s", nl);
 					break;
 				case KNET_LINK_POLICY_RR:
 					knet_vty_write(vty, "   switch-policy round-robin%s", nl);
 					break;
 			}
 
 			knet_link_get_link_list(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids, &link_ids_entries);
 			for (i = 0; i < link_ids_entries; i++) {
 				uint8_t dynamic, transport;
 				const char *transport_name;
 				struct sockaddr_storage src_addr;
 				struct sockaddr_storage dst_addr;
 				uint64_t flags;
 
 				if (!knet_link_get_config(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &transport, &src_addr, &dst_addr, &dynamic, &flags)) {
 					transport_name = knet_handle_get_transport_name_by_id(knet_iface->cfg_ring.knet_h, transport);
 					knet_link_get_status(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &status, sizeof(status));
 					if (status.enabled == 1) {
 						uint8_t priority, pong_count;
 						unsigned int precision;
 						time_t interval, timeout;
 
 						if (dynamic) {
 							knet_vty_write(vty, "   link %d %s dynamic %s%s", link_ids[i], status.src_ipaddr, transport_name, nl);
 						} else {
 							knet_vty_write(vty, "   link %d %s %s %s%s", link_ids[i], status.src_ipaddr, status.dst_ipaddr, transport_name, nl);
 						}
 						knet_link_get_pong_count(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &pong_count);
 						knet_vty_write(vty, "    pong_count %u%s", pong_count, nl);
 						knet_link_get_ping_timers(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &interval, &timeout, &precision);
 						knet_vty_write(vty, "    timers %llu %llu%s", (unsigned long long)interval, (unsigned long long)timeout, nl);
 						knet_link_get_priority(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &priority);
 						knet_vty_write(vty, "    priority %u%s", priority, nl);
 						/* print link properties */
 						knet_vty_write(vty, "    exit%s", nl);
 					}
 				}
 			}
 			knet_vty_write(vty, "   exit%s", nl);
 		}
 
 		if (knet_iface->active)
 			knet_vty_write(vty, "  start%s", nl);
 
 		knet_vty_write(vty, "  exit%s", nl);
 		knet_iface = knet_iface->next;
 	}
 
 	knet_vty_write(vty, " exit%sexit%s", nl, nl);
 
 	return 0;
 }
 
 static int knet_cmd_show_conf(struct knet_vty *vty)
 {
 	return knet_cmd_print_conf(vty);
 }
 
 static int knet_cmd_write_conf(struct knet_vty *vty)
 {
 	int fd = 1, vty_sock, err = 0, backup = 1;
 	char tempfile[PATH_MAX];
 
 	memset(tempfile, 0, sizeof(tempfile));
 
 	snprintf(tempfile, sizeof(tempfile), "%s.sav", knet_cfg_head.conffile);
 	err = rename(knet_cfg_head.conffile, tempfile);
 	if ((err < 0) && (errno != ENOENT)) {
 		knet_vty_write(vty, "Unable to create backup config file %s %s", tempfile, telnet_newline);
 		return -1;
 	}
 	if ((err < 0) && (errno == ENOENT))
 		backup = 0;
 
 	fd = open(knet_cfg_head.conffile,
 		  O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
 		  S_IRUSR | S_IWUSR);
 	if (fd < 0) {
 		knet_vty_write(vty, "Error unable to open file%s", telnet_newline);
 		return -1;
 	}
 
 	vty_sock = vty->vty_sock;
 	vty->vty_sock = fd;
 	vty->filemode = 1;
 	knet_cmd_print_conf(vty);
 	vty->vty_sock = vty_sock;
 	vty->filemode = 0;
 
 	close(fd);
 
 	knet_vty_write(vty, "Configuration saved to %s%s", knet_cfg_head.conffile, telnet_newline);
 	if (backup)
 		knet_vty_write(vty, "Old configuration file has been stored in %s%s",
 				tempfile, telnet_newline);
 
 	return err;
 }
 
 static int knet_cmd_config(struct knet_vty *vty)
 {
 	int err = 0;
 
 	if (!vty->user_can_enable) {
 		knet_vty_write(vty, "Error: user %s does not have enough privileges to perform config operations%s", vty->username, telnet_newline);
 		return -1;
 	}
 
 	pthread_mutex_lock(&knet_vty_mutex);
 	if (knet_vty_config >= 0) {
 		knet_vty_write(vty, "Error: configuration is currently locked by user %s on vty(%d). Try again later%s", vty->username, knet_vty_config, telnet_newline);
 		err = -1;
 		goto out_clean;
 	}
 	vty->node = NODE_CONFIG;
 	knet_vty_config = vty->conn_num;
 out_clean:
 	pthread_mutex_unlock(&knet_vty_mutex);
 	return err;
 }
 
 static int knet_cmd_logout(struct knet_vty *vty)
 {
 	vty->got_epipe = 1;
 	return 0;
 }
 
 static int knet_cmd_who(struct knet_vty *vty)
 {
 	int conn_index;
 
 	pthread_mutex_lock(&knet_vty_mutex);
 
 	for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) {
 		if (knet_vtys[conn_index].active) {
 			knet_vty_write(vty, "User %s connected on vty(%d) from %s%s",
 				knet_vtys[conn_index].username,
 				knet_vtys[conn_index].conn_num,
 				knet_vtys[conn_index].ip,
 				telnet_newline);
 		}
 	}
 
 	pthread_mutex_unlock(&knet_vty_mutex);
 
 	return 0;
 }
 
 static int knet_cmd_help(struct knet_vty *vty)
 {
 	knet_vty_write(vty, PACKAGE "d VTY provides advanced help feature.%s%s"
 			    "When you need help, anytime at the command line please press '?'.%s%s"
 			    "If nothing matches, the help list will be empty and you must backup%s"
 			    " until entering a '?' shows the available options.%s",
 			    telnet_newline, telnet_newline, telnet_newline, telnet_newline, 
 			    telnet_newline, telnet_newline);
 	return 0;
 }
 
 /* exported API to vty_cli.c */
 
 int knet_vty_execute_cmd(struct knet_vty *vty)
 {
 	const vty_node_cmds_t *cmds = NULL;
 	char *cmd = NULL;
 	int cmdlen = 0;
 	int cmdoffset = 0;
 
 	if (knet_vty_is_line_empty(vty))
 		return 0;
 
 	cmds = get_cmds(vty, &cmd, &cmdlen, &cmdoffset);
 
 	/* this will eventually disappear. keep it as safeguard for now */
 	if (cmds == NULL) {
 		knet_vty_write(vty, "No commands associated to this node%s", telnet_newline);
 		return 0;
 	}
 
 	return match_command(vty, cmds, cmd, cmdlen, cmdoffset, KNET_VTY_MATCH_EXEC);
 }
 
 void knet_close_down(void)
 {
 	struct knet_vty *vty = &knet_vtys[0];
 	int err, loop = 0;
 
 	vty->node = NODE_CONFIG;
 	vty->vty_sock = 1;
 	vty->user_can_enable = 1;
 	vty->filemode = 1;
 	vty->got_epipe = 0;
 
 	while ((knet_cfg_head.knet_cfg) && (loop < 10)) {
 		memset(vty->line, 0, sizeof(vty->line));
 		snprintf(vty->line, sizeof(vty->line) - 1, "no interface %s", tap_get_name(knet_cfg_head.knet_cfg->cfg_eth.tap));
 		vty->line_idx = strlen(vty->line);
 		err = knet_vty_execute_cmd(vty);
 		if (err != 0)  {
 			log_error("error shutting down: %s", vty->line);
 			break;
 		}
 		loop++;
 	}
 }
 
 int knet_read_conf(void)
 {
 	int err = 0, len = 0, line = 0;
 	struct knet_vty *vty = &knet_vtys[0];
 	FILE *file = NULL;
 
 	file = fopen(knet_cfg_head.conffile, "r");
 
 	if ((file == NULL) && (errno != ENOENT)) {
 		log_error("Unable to open config file for reading %s", knet_cfg_head.conffile);
 		return -1;
 	}
 
 	if ((file == NULL) && (errno == ENOENT)) {
 		log_info("Configuration file %s not found, starting with default empty config", knet_cfg_head.conffile);
 		return 0;
 	}
 
 	vty->vty_sock = 1;
 	vty->user_can_enable = 1;
 	vty->filemode = 1;
 
 	while(fgets(vty->line, sizeof(vty->line), file) != NULL) {
 		line++;
 		len = strlen(vty->line) - 1;
 		memset(&vty->line[len], 0, 1);
 		vty->line_idx = len;
 		err = knet_vty_execute_cmd(vty);
 		if (err != 0)  {
 			log_error("line[%d]: %s", line, vty->line);
 			break;
 		}
 	}
 
 	fclose(file);
 
 	memset(vty, 0, sizeof(*vty));
 
 	return err;
 }
 
 void knet_vty_help(struct knet_vty *vty)
 {
 	int idx = 0;
 	const vty_node_cmds_t *cmds = NULL;
 	char *cmd = NULL;
 	int cmdlen = 0;
 	int cmdoffset = 0;
 
 	cmds = get_cmds(vty, &cmd, &cmdlen, &cmdoffset);
 
 	/* this will eventually disappear. keep it as safeguard for now */
 	if (cmds == NULL) {
 		knet_vty_write(vty, "No commands associated to this node%s", telnet_newline);
 		return;
 	}
 
 	if (knet_vty_is_line_empty(vty) || cmd == NULL) {
 		while (cmds[idx].cmd != NULL) {
 			print_help(vty, cmds, idx);
 			idx++;
 		}
 		return;
 	}
 
 	match_command(vty, cmds, cmd, cmdlen, cmdoffset, KNET_VTY_MATCH_HELP);
 }
 
 void knet_vty_tab_completion(struct knet_vty *vty)
 {
 	const vty_node_cmds_t *cmds = NULL;
 	char *cmd = NULL;
 	int cmdlen = 0;
 	int cmdoffset = 0;
 
 	if (knet_vty_is_line_empty(vty))
 		return;
 
 	knet_vty_write(vty, "%s", telnet_newline);
 
 	cmds = get_cmds(vty, &cmd, &cmdlen, &cmdoffset);
 
 	/* this will eventually disappear. keep it as safeguard for now */
 	if (cmds == NULL) {
 		knet_vty_write(vty, "No commands associated to this node%s", telnet_newline);
 		return;
 	}
 
 	match_command(vty, cmds, cmd, cmdlen, cmdoffset, KNET_VTY_MATCH_EXPAND);
 
 	knet_vty_prompt(vty);
 	knet_vty_write(vty, "%s", vty->line);
 }
diff --git a/kronosnetd/vty_cli_cmds.h b/kronosnetd/vty_cli_cmds.h
index 79615f5d..c03f7411 100644
--- a/kronosnetd/vty_cli_cmds.h
+++ b/kronosnetd/vty_cli_cmds.h
@@ -1,50 +1,50 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNETD_VTY_CLI_CMDS_H__
 #define __KNETD_VTY_CLI_CMDS_H__
 
 #include "vty.h"
 
 typedef struct {
 	const int		param;
 } vty_param_t;
 
 typedef struct {
 	const char		*cmd;
 	const char		*help;
 	const vty_param_t	*params;
 	int (*func) (struct knet_vty *vty);
 } vty_node_cmds_t;
 
 typedef struct {
 	const int		node_num;
 	const char		*prompt;
 	const vty_node_cmds_t	*cmds;
 	const vty_node_cmds_t	*no_cmds;
 } vty_nodes_t;
 
 enum vty_nodes {
 	NODE_ROOT = 0,
 	NODE_CONFIG,
 	NODE_INTERFACE,
 	NODE_PEER,
 	NODE_LINK,
 	NODE_VTY
 };
 
 int knet_vty_execute_cmd(struct knet_vty *vty);
 void knet_vty_help(struct knet_vty *vty);
 void knet_vty_tab_completion(struct knet_vty *vty);
 
 int knet_read_conf(void);
 void knet_close_down(void);
 
 extern vty_nodes_t knet_vty_nodes[];
 
 #endif
diff --git a/kronosnetd/vty_utils.c b/kronosnetd/vty_utils.c
index 77f3dc48..fb7d2454 100644
--- a/kronosnetd/vty_utils.c
+++ b/kronosnetd/vty_utils.c
@@ -1,269 +1,269 @@
 /*
- * Copyright (C) 2012-2015 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <stdarg.h>
 #include <arpa/telnet.h>
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 
 #include "logging.h"
 #include "vty_cli.h"
 #include "vty_cli_cmds.h"
 #include "vty_utils.h"
 
 static int check_vty(struct knet_vty *vty)
 {
 	if (!vty) {
 		errno = EINVAL;
 		return -1;
 	}
 	if (vty->got_epipe) {
 		errno = EPIPE;
 		return -1;
 	}
 	return 0;
 }
 
 /*
  * TODO: implement loopy_write here
  * should sock be non-blocking?
  */
 static int knet_vty_loopy_write(struct knet_vty *vty, const char *buf, size_t bufsize)
 {
 	ssize_t writelen;
 
 	writelen = write(vty->vty_sock, buf, bufsize);
 	if (writelen < 0)
 		vty->got_epipe = 1;
 
 	return writelen;
 }
 
 int knet_vty_write(struct knet_vty *vty, const char *format, ...)
 {
 	va_list args;
 	int len = 0;
 	char buf[VTY_MAX_BUFFER_SIZE];
 
 	if (check_vty(vty))
 		return -1;
 
 	va_start (args, format);
 	len = vsnprintf (buf, VTY_MAX_BUFFER_SIZE, format, args);
 	va_end (args);
 
 	if ((len < 0) || (len > VTY_MAX_BUFFER_SIZE))
 		return -1;
 
 	return knet_vty_loopy_write(vty, buf, len);
 }
 
 static int knet_vty_read_real(struct knet_vty *vty, unsigned char *buf, size_t bufsize,
 			      int ignore_iac)
 {
 	ssize_t readlen;
 
 iac_retry:
 	readlen = recv(vty->vty_sock, buf, bufsize, 0);
 	if (readlen == 0) {
 		vty->got_epipe = 1;
 		goto out_clean;
 	}
 	if (readlen < 0)
 		goto out_clean;
 
 	vty->idle = 0;
 
 	/* at somepoint we have to add IAC parsing */
 	if ((buf[0] == IAC) && (ignore_iac))
 		goto iac_retry;
 
 out_clean:
 	return readlen;
 }
 
 int knet_vty_read(struct knet_vty *vty, unsigned char *buf, size_t bufsize)
 {
 	if (check_vty(vty))
 		return -1;
 
 	if ((!buf) || (bufsize == 0)) {
 		errno = EINVAL;
 		return -1;
 	}
 	return knet_vty_read_real(vty, buf, bufsize, 1);
 }
 
 static int knet_vty_set_echooff(struct knet_vty *vty)
 {
 	unsigned char cmdreply[VTY_MAX_BUFFER_SIZE];
 	unsigned char cmdechooff[] = { IAC, WILL, TELOPT_ECHO, '\0' };
 	unsigned char cmdechooffreply[] = { IAC, DO, TELOPT_ECHO, '\0' };
 	ssize_t readlen;
 
 	if (knet_vty_write(vty, "%s", cmdechooff) < 0)
 		return -1;
 
 	readlen = knet_vty_read_real(vty, cmdreply, VTY_MAX_BUFFER_SIZE, 0);
 	if (readlen < 0)
 		return readlen;
 
 	if (memcmp(&cmdreply, &cmdechooffreply, readlen))
 		return -1;
 
 	return 0;
 }
 
 static int knet_vty_set_echoon(struct knet_vty *vty)
 {
 	unsigned char cmdreply[VTY_MAX_BUFFER_SIZE];
 	unsigned char cmdechoon[] = { IAC, WONT, TELOPT_ECHO, '\0' };
 	unsigned char cmdechoonreply[] = { IAC, DONT, TELOPT_ECHO, '\0' };
 	ssize_t readlen;
 
 	if (knet_vty_write(vty, "%s", cmdechoon) < 0)
 		return -1;
 
 	readlen = knet_vty_read_real(vty, cmdreply, VTY_MAX_BUFFER_SIZE, 0);
 	if (readlen < 0)
 		return readlen;
 
 	if (memcmp(&cmdreply, &cmdechoonreply, readlen))
 		return -1;
 
 	return 0;
 }
 
 int knet_vty_set_echo(struct knet_vty *vty, int on)
 {
 	if (check_vty(vty))
 		return -1;
 
 	if (on)
 		return knet_vty_set_echoon(vty);
 
 	return knet_vty_set_echooff(vty);
 }
 
 void knet_vty_print_banner(struct knet_vty *vty)
 {
 	if (check_vty(vty))
 		return;
 
 	knet_vty_write(vty,
 		"Welcome to " PACKAGE "d " PACKAGE_VERSION " (built " __DATE__
 		" " __TIME__ ")\n");
 }
 
 int knet_vty_set_iacs(struct knet_vty *vty)
 {
 	unsigned char cmdreply[VTY_MAX_BUFFER_SIZE];
 	unsigned char cmdsga[] = { IAC, WILL, TELOPT_SGA, '\0' };
 	unsigned char cmdsgareply[] = { IAC, DO, TELOPT_SGA, '\0' };
 	unsigned char cmdlm[] = { IAC, DONT, TELOPT_LINEMODE, '\0' };
 	ssize_t readlen;
 
 	if (check_vty(vty))
 		return -1;
 
 	if (knet_vty_set_echo(vty, 0) < 0)
 		return -1;
 
 	if (knet_vty_write(vty, "%s", cmdsga) < 0)
 		return -1;
 
 	readlen = knet_vty_read_real(vty, cmdreply, VTY_MAX_BUFFER_SIZE, 0);
 	if (readlen < 0)
 		return readlen;
 
 	if (memcmp(&cmdreply, &cmdsgareply, readlen))
 		return -1;
 
 	if (knet_vty_write(vty, "%s", cmdlm) < 0)
 		return -1;
 
 	return 0;
 }
 
 void knet_vty_free_history(struct knet_vty *vty)
 {
 	int i;
 
 	if (check_vty(vty))
 		return;
 
 	for (i = 0; i < KNET_VTY_MAX_HIST; i++) {
 		if (vty->history[i]) {
 			free(vty->history[i]);
 			vty->history[i] = NULL;
 		}
 	}
 }
 
 void knet_vty_exit_node(struct knet_vty *vty)
 {
 	switch(vty->node) {
 		case NODE_VTY:
 			vty->node = vty->prevnode;
 			break;
 		case NODE_LINK:
 			vty->node = NODE_PEER;
 			break;
 		case NODE_PEER:
 			vty->node = NODE_INTERFACE;
 			break;
 		case NODE_INTERFACE:
 			vty->node = NODE_CONFIG;
 			break;
 		case NODE_CONFIG:
 			pthread_mutex_lock(&knet_vty_mutex);
 			knet_vty_config = -1;
 			pthread_mutex_unlock(&knet_vty_mutex);
 			vty->node = NODE_ROOT;
 			break;
 		case NODE_ROOT:
 			vty->got_epipe = 1;
 			break;
 		default:
 			knet_vty_write(vty, "No idea where to go..%s", telnet_newline);
 			break;
 	}
 }
 
 int knet_vty_is_line_empty(struct knet_vty *vty)
 {
 	int idx;
 
 	for (idx = 0; idx < vty->line_idx; idx++) {
 		if (vty->line[idx] != ' ')
 			return 0;
 	}
 
 	return 1;
 }
 
 void knet_vty_prompt(struct knet_vty *vty)
 {
 	char buf[3];
 
 	if (vty->user_can_enable) {
 		buf[0] = '#';
 	} else {
 		buf[0] = '>';
 	}
 	buf[1] = ' ';
 	buf[2] = 0;
 	knet_vty_write(vty, "%s%s", knet_vty_nodes[vty->node].prompt, buf);
 }
diff --git a/kronosnetd/vty_utils.h b/kronosnetd/vty_utils.h
index c6ff101d..326bcbc0 100644
--- a/kronosnetd/vty_utils.h
+++ b/kronosnetd/vty_utils.h
@@ -1,35 +1,35 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNETD_VTY_UTILS_H__
 #define __KNETD_VTY_UTILS_H__
 
 #include "vty.h"
 
 #define VTY_MAX_BUFFER_SIZE	4096
 
 int knet_vty_write(struct knet_vty *vty, const char *format, ...)
 		   __attribute__ ((__format__ (__printf__, 2, 3)));
 
 int knet_vty_read(struct knet_vty *vty, unsigned char *buf, size_t bufsize);
 
 int knet_vty_set_echo(struct knet_vty *vty, int on);
 
 void knet_vty_print_banner(struct knet_vty *vty);
 
 int knet_vty_set_iacs(struct knet_vty *vty);
 
 void knet_vty_free_history(struct knet_vty *vty);
 
 void knet_vty_exit_node(struct knet_vty *vty);
 
 int knet_vty_is_line_empty(struct knet_vty *vty);
 
 void knet_vty_prompt(struct knet_vty *vty);
 
 #endif
diff --git a/libknet/common.c b/libknet/common.c
index 69e3d3f0..eefa100c 100644
--- a/libknet/common.c
+++ b/libknet/common.c
@@ -1,120 +1,120 @@
 /*
- * Copyright (C) 2011-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <unistd.h>
 #include <fcntl.h>
 #include <dlfcn.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "logging.h"
 #include "common.h"
 
 int _fdset_cloexec(int fd)
 {
 	int fdflags;
 
 	fdflags = fcntl(fd, F_GETFD, 0);
 	if (fdflags < 0)
 		return -1;
 
 	fdflags |= FD_CLOEXEC;
 
 	if (fcntl(fd, F_SETFD, fdflags) < 0)
 		return -1;
 
 	return 0;
 }
 
 int _fdset_nonblock(int fd)
 {
 	int fdflags;
 
 	fdflags = fcntl(fd, F_GETFL, 0);
 	if (fdflags < 0)
 		return -1;
 
 	fdflags |= O_NONBLOCK;
 
 	if (fcntl(fd, F_SETFL, fdflags) < 0)
 		return -1;
 
 	return 0;
 }
 
 void *open_lib(knet_handle_t knet_h, const char *libname, int extra_flags)
 {
 	void *ret = NULL;
 	char *error = NULL;
 	char dir[MAXPATHLEN], path[MAXPATHLEN], link[MAXPATHLEN];
 	struct stat sb;
 
 	/*
 	 * clear any pending error
 	 */
 	dlerror();
 
 	ret = dlopen(libname, RTLD_NOW | RTLD_GLOBAL | extra_flags);
 	error = dlerror();
 	if (error != NULL) {
 		log_err(knet_h, KNET_SUB_COMMON, "unable to dlopen %s: %s",
 			libname, error);
 		errno = EAGAIN;
 		return NULL;
 	}
 
 	memset(dir, 0, sizeof(dir));
 	memset(link, 0, sizeof(link));
 	memset(path, 0, sizeof(path));
 	if (dlinfo(ret, RTLD_DI_ORIGIN, &dir) < 0) {
 		/*
 		 * should we dlclose and return error?
 		 */
 		log_warn(knet_h, KNET_SUB_COMMON, "unable to dlinfo %s: %s",
 			 libname, error);
 	} else {
 		snprintf(path, sizeof(path), "%s/%s", dir, libname);
 
 		log_info(knet_h, KNET_SUB_COMMON, "%s has been loaded from %s", libname, path);
 
 		/*
 		 * try to resolve the library and check if it is a symlink and to where.
 		 * we can't prevent symlink attacks but at least we can log where the library
 		 * has been loaded from
 		 */
 		if (lstat(path, &sb) < 0) {
 			log_debug(knet_h, KNET_SUB_COMMON, "Unable to stat %s: %s", path, strerror(errno));
 			goto out;
 		}
 
 		if (S_ISLNK(sb.st_mode)) {
 			if (readlink(path, link, sizeof(link)) < 0) {
 				log_debug(knet_h, KNET_SUB_COMMON, "Unable to readlink %s: %s", path, strerror(errno));
 				goto out;
 			}
 			/*
 			 * symlink is relative to the directory
 			 */
 			if (link[0] != '/') {
 				snprintf(path, sizeof(path), "%s/%s", dir, link);
 				log_info(knet_h, KNET_SUB_COMMON, "%s/%s is a symlink to %s", dir, libname, path);
 			} else {
 				log_info(knet_h, KNET_SUB_COMMON, "%s/%s is a symlink to %s", dir, libname, link);
 			}
 		}
 	}
 out:
 	return ret;
 }
diff --git a/libknet/crypto_nss.c b/libknet/crypto_nss.c
index 7169da01..c6a12e67 100644
--- a/libknet/crypto_nss.c
+++ b/libknet/crypto_nss.c
@@ -1,1147 +1,1147 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <dlfcn.h>
 #include <stdlib.h>
 #ifdef BUILDCRYPTONSS
 #include <nss.h>
 #include <nspr.h>
 #include <pk11pub.h>
 #include <pkcs11.h>
 #include <prerror.h>
 #include <blapit.h>
 #include <hasht.h>
 #include <pthread.h>
 #include <secerr.h>
 #include <prinit.h>
 
 #include "common.h"
 #include "crypto.h"
 #include "crypto_nss.h"
 #include "logging.h"
 
 #define LIBNSS3 "libnss3.so"
 
 /*
  * global vars for dlopen
  */
 static void *nss_lib;
 
 /*
  * symbols remapping
  */
 /*
  * nss3
  */
 CK_MECHANISM_TYPE (*_int_PK11_GetBestWrapMechanism)(PK11SlotInfo *slot);
 PK11SlotInfo *(*_int_PK11_GetBestSlot)(CK_MECHANISM_TYPE type, void *wincx);
 int (*_int_PK11_GetBestKeyLength)(PK11SlotInfo *slot, CK_MECHANISM_TYPE type);
 SECStatus (*_int_PK11_DigestFinal)(PK11Context *context, unsigned char *data,
 				   unsigned int *outLen, unsigned int length);
 void (*_int_SECITEM_FreeItem)(SECItem *zap, PRBool freeit);
 SECStatus (*_int_NSS_NoDB_Init)(const char *configdir);
 SECStatus (*_int_NSS_Shutdown)(void);
 SECStatus (*_int_PK11_DigestBegin)(PK11Context *cx);
 SECStatus (*_int_PK11_DigestOp)(PK11Context *context, const unsigned char *in, unsigned len);
 void (*_int_PK11_DestroyContext)(PK11Context *context, PRBool freeit);
 SECStatus (*_int_PK11_Finalize)(PK11Context *context);
 SECStatus (*_int_PK11_CipherOp)(PK11Context *context, unsigned char *out, int *outlen,
 				int maxout, const unsigned char *in, int inlen);
 PK11SymKey *(*_int_PK11_UnwrapSymKey)(PK11SymKey *key,
 				      CK_MECHANISM_TYPE wraptype, SECItem *param, SECItem *wrapppedKey,
 				      CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize);
 void (*_int_PK11_FreeSymKey)(PK11SymKey *key);
 PK11Context *(*_int_PK11_CreateContextBySymKey)(CK_MECHANISM_TYPE type,
 						CK_ATTRIBUTE_TYPE operation,
 						PK11SymKey *symKey, SECItem *param);
 SECStatus (*_int_PK11_GenerateRandom)(unsigned char *data, int len);
 SECItem *(*_int_PK11_ParamFromIV)(CK_MECHANISM_TYPE type, SECItem *iv);
 void (*_int_PK11_FreeSlot)(PK11SlotInfo *slot);
 int (*_int_PK11_GetBlockSize)(CK_MECHANISM_TYPE type, SECItem *params);
 PK11SymKey *(*_int_PK11_KeyGen)(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
 				SECItem *param, int keySize, void *wincx);
 
 /*
  * nspr4
  */
 PRStatus (*_int_PR_Cleanup)(void);
 const char * (*_int_PR_ErrorToString)(PRErrorCode code, PRLanguageCode language);
 PRErrorCode (*_int_PR_GetError)(void);
 PRBool (*_int_PR_Initialized)(void);
 
 /*
  * plds4
  */
 void (*_int_PL_ArenaFinish)(void);
 
 static void clean_nss_syms(void)
 {
 	_int_PK11_GetBestWrapMechanism = NULL;
 	_int_PK11_GetBestSlot = NULL;
 	_int_PK11_GetBestKeyLength = NULL;
 	_int_PK11_DigestFinal = NULL;
 	_int_SECITEM_FreeItem = NULL;
 	_int_NSS_NoDB_Init = NULL;
 	_int_NSS_Shutdown = NULL;
 	_int_PK11_DigestBegin = NULL;
 	_int_PK11_DigestOp = NULL;
 	_int_PK11_DestroyContext = NULL;
 	_int_PK11_Finalize = NULL;
 	_int_PK11_CipherOp = NULL;
 	_int_PK11_UnwrapSymKey = NULL;
 	_int_PK11_FreeSymKey = NULL;
 	_int_PK11_CreateContextBySymKey = NULL;
 	_int_PK11_GenerateRandom = NULL;
 	_int_PK11_ParamFromIV = NULL;
 	_int_PK11_FreeSlot = NULL;
 	_int_PK11_GetBlockSize = NULL;
 	_int_PK11_KeyGen = NULL;
 
 	_int_PR_Cleanup = NULL;
 	_int_PR_ErrorToString = NULL;
 	_int_PR_Initialized = NULL;
 	_int_PR_GetError = NULL;
 
 	_int_PL_ArenaFinish = NULL;
 	return;
 }
 
 static int nsscrypto_remap_symbols(knet_handle_t knet_h)
 {
 	int err = 0;
 	char *error = NULL;
 
 	/*
 	 * nss3
 	 */
 
 	_int_PK11_GetBestWrapMechanism = dlsym(nss_lib, "PK11_GetBestWrapMechanism");
 	if (!_int_PK11_GetBestWrapMechanism) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBestWrapMechanism: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_GetBestSlot = dlsym(nss_lib, "PK11_GetBestSlot");
 	if (!_int_PK11_GetBestSlot) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBestSlot: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_GetBestKeyLength = dlsym(nss_lib, "PK11_GetBestKeyLength");
 	if (!_int_PK11_GetBestKeyLength) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBestKeyLength: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_DigestFinal = dlsym(nss_lib, "PK11_DigestFinal");
 	if (!_int_PK11_DigestFinal) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DigestFinal: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_SECITEM_FreeItem = dlsym(nss_lib, "SECITEM_FreeItem");
 	if (!_int_SECITEM_FreeItem) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map SECITEM_FreeItem: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_NSS_NoDB_Init = dlsym(nss_lib, "NSS_NoDB_Init");
 	if (!_int_NSS_NoDB_Init) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map NSS_NoDB_Init: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_NSS_Shutdown = dlsym(nss_lib, "NSS_Shutdown");
 	if (!_int_NSS_Shutdown) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map NSS_Shutdown: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_DigestBegin = dlsym(nss_lib, "PK11_DigestBegin");
 	if (!_int_PK11_DigestBegin) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DigestBegin: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_DigestOp = dlsym(nss_lib, "PK11_DigestOp");
 	if (!_int_PK11_DigestOp) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DigestOp: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_DestroyContext = dlsym(nss_lib, "PK11_DestroyContext");
 	if (!_int_PK11_DestroyContext) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DestroyContext: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_Finalize = dlsym(nss_lib, "PK11_Finalize");
 	if (!_int_PK11_Finalize) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_Finalize: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_CipherOp = dlsym(nss_lib, "PK11_CipherOp");
 	if (!_int_PK11_CipherOp) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_CipherOp: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_UnwrapSymKey = dlsym(nss_lib, "PK11_UnwrapSymKey");
 	if (!_int_PK11_UnwrapSymKey) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_UnwrapSymKey: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_FreeSymKey = dlsym(nss_lib, "PK11_FreeSymKey");
 	if (!_int_PK11_FreeSymKey) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_FreeSymKey: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_CreateContextBySymKey = dlsym(nss_lib, "PK11_CreateContextBySymKey");
 	if (!_int_PK11_CreateContextBySymKey) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_CreateContextBySymKey: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_GenerateRandom = dlsym(nss_lib, "PK11_GenerateRandom");
 	if (!_int_PK11_GenerateRandom) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GenerateRandom: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_ParamFromIV = dlsym(nss_lib, "PK11_ParamFromIV");
 	if (!_int_PK11_ParamFromIV) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_ParamFromIV: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_FreeSlot = dlsym(nss_lib, "PK11_FreeSlot");
 	if (!_int_PK11_FreeSlot) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_FreeSlot: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_GetBlockSize = dlsym(nss_lib, "PK11_GetBlockSize");
 	if (!_int_PK11_GetBlockSize) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBlockSize: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PK11_KeyGen = dlsym(nss_lib, "PK11_KeyGen");
 	if (!_int_PK11_KeyGen) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_KeyGen: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	/*
 	 * nspr4
 	 */
 
 	_int_PR_Cleanup = dlsym(nss_lib, "PR_Cleanup");
 	if (!_int_PR_Cleanup) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PR_Cleanup: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PR_ErrorToString = dlsym(nss_lib, "PR_ErrorToString");
 	if (!_int_PR_ErrorToString) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PR_ErrorToString: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PR_Initialized = dlsym(nss_lib, "PR_Initialized");
 	if (!_int_PR_Initialized) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map Initialized: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	_int_PR_GetError = dlsym(nss_lib, "PR_GetError");
 	if (!_int_PR_GetError) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PR_GetError: %s", error);
 		err = -1;
 		goto out;
 	}
 
 	/*
 	 * plds4
 	 */
 
 	_int_PL_ArenaFinish = dlsym(nss_lib, "PL_ArenaFinish");
 	if (!_int_PL_ArenaFinish) {
 		error = dlerror();
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PL_ArenaFinish: %s", error);
 		err = -1;
 		goto out;
 	}
 
 
 out:
 	if (err) {
 		clean_nss_syms();
 	}
 	return err;
 }
 
 static int nss_db_is_init = 0;
 static int at_exit_registered = 0;
 
 static void nss_atexit_handler(void)
 {
 	if (nss_db_is_init) {
 		if (_int_NSS_Shutdown) {
 			(*_int_NSS_Shutdown)();
 		}
 		if ((_int_PR_Initialized) && ((*_int_PR_Initialized)())) {
 			if (_int_PL_ArenaFinish) {
 				(*_int_PL_ArenaFinish)();
 			}
 			if (_int_PR_Cleanup) {
 				(*_int_PR_Cleanup)();
 			}
 		}
 	}
 	return;
 }
 
 int nsscrypto_load_lib(
 	knet_handle_t knet_h)
 {
 	int err = 0, savederrno = 0;
 
 	if (!nss_lib) {
 		nss_lib = open_lib(knet_h, LIBNSS3, 0);
 		if (!nss_lib) {
 			savederrno = errno;
 			err = -1;
 			goto out;
 		}
 	}
 
 	if (nsscrypto_remap_symbols(knet_h) < 0) {
 		savederrno = errno;
 		err = -1;
 		goto out;
 	}
 
 	if (!at_exit_registered) {
 		if (atexit(nss_atexit_handler)) {
 			log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to register NSS atexit handler");
 			savederrno = EAGAIN;
 			err = -1;
 			goto out;
 		}
 		at_exit_registered = 1;
 	}
 
 	if ((nss_lib) && (_int_NSS_NoDB_Init) && (!nss_db_is_init)) {
 		if ((*_int_NSS_NoDB_Init)(".") != SECSuccess) {
 			log_err(knet_h, KNET_SUB_NSSCRYPTO, "NSS DB initialization failed (err %d): %s",
 				(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 			savederrno = EAGAIN;
 			err = -1;
 			goto out;
 		}
 		nss_db_is_init = 1;
 	}
 out:
 	errno = savederrno;
 	return err;
 }
 
 /*
  * crypto definitions and conversion tables
  */
 
 #define SALT_SIZE 16
 
 /*
  * This are defined in new NSS. For older one, we will define our own
  */
 #ifndef AES_256_KEY_LENGTH
 #define AES_256_KEY_LENGTH 32
 #endif
 
 #ifndef AES_192_KEY_LENGTH
 #define AES_192_KEY_LENGTH 24
 #endif
 
 #ifndef AES_128_KEY_LENGTH
 #define AES_128_KEY_LENGTH 16
 #endif
 
 enum nsscrypto_crypt_t {
 	CRYPTO_CIPHER_TYPE_NONE = 0,
 	CRYPTO_CIPHER_TYPE_AES256 = 1,
 	CRYPTO_CIPHER_TYPE_AES192 = 2,
 	CRYPTO_CIPHER_TYPE_AES128 = 3,
 	CRYPTO_CIPHER_TYPE_3DES = 4
 };
 
 CK_MECHANISM_TYPE cipher_to_nss[] = {
 	0,				/* CRYPTO_CIPHER_TYPE_NONE */
 	CKM_AES_CBC_PAD,		/* CRYPTO_CIPHER_TYPE_AES256 */
 	CKM_AES_CBC_PAD,		/* CRYPTO_CIPHER_TYPE_AES192 */
 	CKM_AES_CBC_PAD,		/* CRYPTO_CIPHER_TYPE_AES128 */
 	CKM_DES3_CBC_PAD 		/* CRYPTO_CIPHER_TYPE_3DES */
 };
 
 size_t nsscipher_key_len[] = {
 	0,				/* CRYPTO_CIPHER_TYPE_NONE */
 	AES_256_KEY_LENGTH,		/* CRYPTO_CIPHER_TYPE_AES256 */
 	AES_192_KEY_LENGTH,		/* CRYPTO_CIPHER_TYPE_AES192 */
 	AES_128_KEY_LENGTH,		/* CRYPTO_CIPHER_TYPE_AES128 */
 	24				/* CRYPTO_CIPHER_TYPE_3DES */
 };
 
 size_t nsscypher_block_len[] = {
 	0,				/* CRYPTO_CIPHER_TYPE_NONE */
 	AES_BLOCK_SIZE,			/* CRYPTO_CIPHER_TYPE_AES256 */
 	AES_BLOCK_SIZE,			/* CRYPTO_CIPHER_TYPE_AES192 */
 	AES_BLOCK_SIZE,			/* CRYPTO_CIPHER_TYPE_AES128 */
 	0				/* CRYPTO_CIPHER_TYPE_3DES */
 };
 
 /*
  * hash definitions and conversion tables
  */
 
 enum nsscrypto_hash_t {
 	CRYPTO_HASH_TYPE_NONE	= 0,
 	CRYPTO_HASH_TYPE_MD5	= 1,
 	CRYPTO_HASH_TYPE_SHA1	= 2,
 	CRYPTO_HASH_TYPE_SHA256	= 3,
 	CRYPTO_HASH_TYPE_SHA384	= 4,
 	CRYPTO_HASH_TYPE_SHA512	= 5
 };
 
 CK_MECHANISM_TYPE hash_to_nss[] = {
 	 0,				/* CRYPTO_HASH_TYPE_NONE */
 	CKM_MD5_HMAC,			/* CRYPTO_HASH_TYPE_MD5 */
 	CKM_SHA_1_HMAC,			/* CRYPTO_HASH_TYPE_SHA1 */
 	CKM_SHA256_HMAC,		/* CRYPTO_HASH_TYPE_SHA256 */
 	CKM_SHA384_HMAC,		/* CRYPTO_HASH_TYPE_SHA384 */
 	CKM_SHA512_HMAC			/* CRYPTO_HASH_TYPE_SHA512 */
 };
 
 size_t nsshash_len[] = {
 	 0,				/* CRYPTO_HASH_TYPE_NONE */
 	MD5_LENGTH,			/* CRYPTO_HASH_TYPE_MD5 */
 	SHA1_LENGTH,			/* CRYPTO_HASH_TYPE_SHA1 */
 	SHA256_LENGTH,			/* CRYPTO_HASH_TYPE_SHA256 */
 	SHA384_LENGTH,			/* CRYPTO_HASH_TYPE_SHA384 */
 	SHA512_LENGTH			/* CRYPTO_HASH_TYPE_SHA512 */
 };
 
 enum sym_key_type {
 	SYM_KEY_TYPE_CRYPT,
 	SYM_KEY_TYPE_HASH
 };
 
 struct nsscrypto_instance {
 	PK11SymKey   *nss_sym_key;
 	PK11SymKey   *nss_sym_key_sign;
 
 	unsigned char *private_key;
 
 	unsigned int private_key_len;
 
 	int crypto_cipher_type;
 
 	int crypto_hash_type;
 };
 
 /*
  * crypt/decrypt functions
  */
 
 static int nssstring_to_crypto_cipher_type(const char* crypto_cipher_type)
 {
 	if (strcmp(crypto_cipher_type, "none") == 0) {
 		return CRYPTO_CIPHER_TYPE_NONE;
 	} else if (strcmp(crypto_cipher_type, "aes256") == 0) {
 		return CRYPTO_CIPHER_TYPE_AES256;
 	} else if (strcmp(crypto_cipher_type, "aes192") == 0) {
 		return CRYPTO_CIPHER_TYPE_AES192;
 	} else if (strcmp(crypto_cipher_type, "aes128") == 0) {
 		return CRYPTO_CIPHER_TYPE_AES128;
 	} else if (strcmp(crypto_cipher_type, "3des") == 0) {
 		return CRYPTO_CIPHER_TYPE_3DES;
 	}
 	return -1;
 }
 
 static PK11SymKey *nssimport_symmetric_key(knet_handle_t knet_h, enum sym_key_type key_type)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 	SECItem key_item;
 	PK11SlotInfo *slot;
 	PK11SymKey *res_key;
 	CK_MECHANISM_TYPE cipher;
 	CK_ATTRIBUTE_TYPE operation;
 	CK_MECHANISM_TYPE wrap_mechanism;
 	int wrap_key_len;
 	PK11SymKey *wrap_key;
 	PK11Context *wrap_key_crypt_context;
 	SECItem tmp_sec_item;
 	SECItem wrapped_key;
 	int wrapped_key_len;
 	unsigned char wrapped_key_data[KNET_MAX_KEY_LEN];
 
 	memset(&key_item, 0, sizeof(key_item));
 	slot = NULL;
 	wrap_key = NULL;
 	res_key = NULL;
 	wrap_key_crypt_context = NULL;
 
 	key_item.type = siBuffer;
 	key_item.data = instance->private_key;
 
 	switch (key_type) {
 		case SYM_KEY_TYPE_CRYPT:
 			key_item.len = nsscipher_key_len[instance->crypto_cipher_type];
 			cipher = cipher_to_nss[instance->crypto_cipher_type];
 			operation = CKA_ENCRYPT|CKA_DECRYPT;
 			break;
 		case SYM_KEY_TYPE_HASH:
 			key_item.len = instance->private_key_len;
 			cipher = hash_to_nss[instance->crypto_hash_type];
 			operation = CKA_SIGN;
 			break;
 		default:
 			log_err(knet_h, KNET_SUB_NSSCRYPTO, "Import symmetric key failed. Unknown keyimport request");
 			goto exit_res_key;
 			break;
 	}
 
 	slot = (*_int_PK11_GetBestSlot)(cipher, NULL);
 	if (slot == NULL) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to find security slot (%d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto exit_res_key;
 	}
 
 	/*
 	 * Without FIPS it would be possible to just use
 	 * 	res_key = PK11_ImportSymKey(slot, cipher, PK11_OriginUnwrap, operation, &key_item, NULL);
 	 * with FIPS NSS Level 2 certification has to be "workarounded" (so it becomes Level 1) by using
 	 * following method:
 	 * 1. Generate wrap key
 	 * 2. Encrypt authkey with wrap key
 	 * 3. Unwrap encrypted authkey using wrap key
 	 */
 
 	/*
 	 * Generate wrapping key
 	 */
 	wrap_mechanism = (*_int_PK11_GetBestWrapMechanism)(slot);
 	wrap_key_len = (*_int_PK11_GetBestKeyLength)(slot, wrap_mechanism);
 	wrap_key = (*_int_PK11_KeyGen)(slot, wrap_mechanism, NULL, wrap_key_len, NULL);
 	if (wrap_key == NULL) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to generate wrapping key (%d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto exit_res_key;
 	}
 
 	/*
 	 * Encrypt authkey with wrapping key
 	 */
 
 	/*
 	 * Initialization of IV is not needed because PK11_GetBestWrapMechanism should return ECB mode
 	 */
 	memset(&tmp_sec_item, 0, sizeof(tmp_sec_item));
 	wrap_key_crypt_context = (*_int_PK11_CreateContextBySymKey)(wrap_mechanism, CKA_ENCRYPT,
 								    wrap_key, &tmp_sec_item);
 	if (wrap_key_crypt_context == NULL) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to create encrypt context (%d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto exit_res_key;
 	}
 
 	wrapped_key_len = (int)sizeof(wrapped_key_data);
 
 	if ((*_int_PK11_CipherOp)(wrap_key_crypt_context, wrapped_key_data, &wrapped_key_len,
 				  sizeof(wrapped_key_data), key_item.data, key_item.len) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to encrypt authkey (%d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto exit_res_key;
 	}
 
 	if ((*_int_PK11_Finalize)(wrap_key_crypt_context) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to finalize encryption of authkey (%d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto exit_res_key;
 	}
 
 	/*
 	 * Finally unwrap sym key
 	 */
 	memset(&tmp_sec_item, 0, sizeof(tmp_sec_item));
 	wrapped_key.data = wrapped_key_data;
 	wrapped_key.len = wrapped_key_len;
 
 	res_key = (*_int_PK11_UnwrapSymKey)(wrap_key, wrap_mechanism, &tmp_sec_item, &wrapped_key,
 					    cipher, operation, key_item.len);
 	if (res_key == NULL) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to import key into NSS (%d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 
 		if ((*_int_PR_GetError)() == SEC_ERROR_BAD_DATA) {
 			/*
 			 * Maximum key length for FIPS enabled softtoken is limited to
 			 * MAX_KEY_LEN (pkcs11i.h - 256) and checked in NSC_UnwrapKey. Returned
 			 * error is CKR_TEMPLATE_INCONSISTENT which is mapped to SEC_ERROR_BAD_DATA.
 			 */
 			log_err(knet_h, KNET_SUB_NSSCRYPTO, "Secret key is probably too long. "
 				"Try reduce it to 256 bytes");
 		}
 		goto exit_res_key;
 	}
 
 exit_res_key:
 	if (wrap_key_crypt_context != NULL) {
 		(*_int_PK11_DestroyContext)(wrap_key_crypt_context, PR_TRUE);
 	}
 
 	if (wrap_key != NULL) {
 		(*_int_PK11_FreeSymKey)(wrap_key);
 	}
 
 	if (slot != NULL) {
 		(*_int_PK11_FreeSlot)(slot);
 	}
 
 	return (res_key);
 }
 
 static int init_nss_crypto(knet_handle_t knet_h)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 
 	if (!cipher_to_nss[instance->crypto_cipher_type]) {
 		return 0;
 	}
 
 	instance->nss_sym_key = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_CRYPT);
 	if (instance->nss_sym_key == NULL) {
 		return -1;
 	}
 
 	return 0;
 }
 
 static int encrypt_nss(
 	knet_handle_t knet_h,
 	const struct iovec *iov,
 	int iovcnt,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 	PK11Context*	crypt_context = NULL;
 	SECItem		crypt_param;
 	SECItem		*nss_sec_param = NULL;
 	int		tmp_outlen = 0, tmp1_outlen = 0;
 	unsigned int	tmp2_outlen = 0;
 	unsigned char	*salt = buf_out;
 	unsigned char	*data = buf_out + SALT_SIZE;
 	int		err = -1;
 	int		i;
 
 	if ((*_int_PK11_GenerateRandom)(salt, SALT_SIZE) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to generate a random number (err %d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	crypt_param.type = siBuffer;
 	crypt_param.data = salt;
 	crypt_param.len = SALT_SIZE;
 
 	nss_sec_param = (*_int_PK11_ParamFromIV)(cipher_to_nss[instance->crypto_cipher_type],
 						 &crypt_param);
 	if (nss_sec_param == NULL) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to set up PKCS11 param (err %d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	/*
 	 * Create cipher context for encryption
 	 */
 	crypt_context = (*_int_PK11_CreateContextBySymKey)(cipher_to_nss[instance->crypto_cipher_type],
 							   CKA_ENCRYPT,
 							   instance->nss_sym_key,
 							   nss_sec_param);
 	if (!crypt_context) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d): %s",
 			   (int)cipher_to_nss[instance->crypto_cipher_type],
 			   (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	for (i=0; i<iovcnt; i++) {
 		if ((*_int_PK11_CipherOp)(crypt_context, data,
 					  &tmp_outlen,
 					  KNET_DATABUFSIZE_CRYPT,
 					  (unsigned char *)iov[i].iov_base,
 					  iov[i].iov_len) != SECSuccess) {
 			log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp failed (encrypt) crypt_type=%d (err %d): %s",
 				(int)cipher_to_nss[instance->crypto_cipher_type],
 				(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 			goto out;
 		}
 		tmp1_outlen = tmp1_outlen + tmp_outlen;
 	}
 
 	if ((*_int_PK11_DigestFinal)(crypt_context, data + tmp1_outlen,
 				     &tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal failed (encrypt) crypt_type=%d (err %d): %s",
 			(int)cipher_to_nss[instance->crypto_cipher_type],
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 
 	}
 
 	*buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE;
 
 	err = 0;
 
 out:
 	if (crypt_context) {
 		(*_int_PK11_DestroyContext)(crypt_context, PR_TRUE);
 	}
 	if (nss_sec_param) {
 		(*_int_SECITEM_FreeItem)(nss_sec_param, PR_TRUE);
 	}
 	return err;
 }
 
 static int decrypt_nss (
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 	PK11Context*	decrypt_context = NULL;
 	SECItem		decrypt_param;
 	int		tmp1_outlen = 0;
 	unsigned int	tmp2_outlen = 0;
 	unsigned char	*salt = (unsigned char *)buf_in;
 	unsigned char	*data = salt + SALT_SIZE;
 	int		datalen = buf_in_len - SALT_SIZE;
 	int		err = -1;
 
 	/* Create cipher context for decryption */
 	decrypt_param.type = siBuffer;
 	decrypt_param.data = salt;
 	decrypt_param.len = SALT_SIZE;
 
 	decrypt_context = (*_int_PK11_CreateContextBySymKey)(cipher_to_nss[instance->crypto_cipher_type],
 							     CKA_DECRYPT,
 							     instance->nss_sym_key, &decrypt_param);
 	if (!decrypt_context) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext (decrypt) failed (err %d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	if ((*_int_PK11_CipherOp)(decrypt_context, buf_out, &tmp1_outlen,
 				  KNET_DATABUFSIZE_CRYPT, data, datalen) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp (decrypt) failed (err %d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	if ((*_int_PK11_DigestFinal)(decrypt_context, buf_out + tmp1_outlen, &tmp2_outlen,
 				     KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal (decrypt) failed (err %d): %s",
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	*buf_out_len = tmp1_outlen + tmp2_outlen;
 
 	err = 0;
 
 out:
 	if (decrypt_context) {
 		(*_int_PK11_DestroyContext)(decrypt_context, PR_TRUE);
 	}
 
 	return err;
 }
 
 
 /*
  * hash/hmac/digest functions
  */
 
 static int nssstring_to_crypto_hash_type(const char* crypto_hash_type)
 {
 	if (strcmp(crypto_hash_type, "none") == 0) {
 		return CRYPTO_HASH_TYPE_NONE;
 	} else if (strcmp(crypto_hash_type, "md5") == 0) {
 		return CRYPTO_HASH_TYPE_MD5;
 	} else if (strcmp(crypto_hash_type, "sha1") == 0) {
 		return CRYPTO_HASH_TYPE_SHA1;
 	} else if (strcmp(crypto_hash_type, "sha256") == 0) {
 		return CRYPTO_HASH_TYPE_SHA256;
 	} else if (strcmp(crypto_hash_type, "sha384") == 0) {
 		return CRYPTO_HASH_TYPE_SHA384;
 	} else if (strcmp(crypto_hash_type, "sha512") == 0) {
 		return CRYPTO_HASH_TYPE_SHA512;
 	}
 
 	return -1;
 }
 
 static int init_nss_hash(knet_handle_t knet_h)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 
 	if (!hash_to_nss[instance->crypto_hash_type]) {
 		return 0;
 	}
 
 	instance->nss_sym_key_sign = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_HASH);
 	if (instance->nss_sym_key_sign == NULL) {
 		return -1;
 	}
 
 	return 0;
 }
 
 static int calculate_nss_hash(
 	knet_handle_t knet_h,
 	const unsigned char *buf,
 	const size_t buf_len,
 	unsigned char *hash)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 	PK11Context*	hash_context = NULL;
 	SECItem		hash_param;
 	unsigned int	hash_tmp_outlen = 0;
 	int		err = -1;
 
 	/* Now do the digest */
 	hash_param.type = siBuffer;
 	hash_param.data = 0;
 	hash_param.len = 0;
 
 	hash_context = (*_int_PK11_CreateContextBySymKey)(hash_to_nss[instance->crypto_hash_type],
 							  CKA_SIGN,
 							  instance->nss_sym_key_sign,
 							  &hash_param);
 
 	if (!hash_context) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (hash) hash_type=%d (err %d): %s",
 			(int)hash_to_nss[instance->crypto_hash_type],
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	if ((*_int_PK11_DigestBegin)(hash_context) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestBegin failed (hash) hash_type=%d (err %d): %s",
 			(int)hash_to_nss[instance->crypto_hash_type],
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	if ((*_int_PK11_DigestOp)(hash_context, buf, buf_len) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestOp failed (hash) hash_type=%d (err %d): %s",
 			(int)hash_to_nss[instance->crypto_hash_type],
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	if ((*_int_PK11_DigestFinal)(hash_context, hash,
 				     &hash_tmp_outlen, nsshash_len[instance->crypto_hash_type]) != SECSuccess) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinale failed (hash) hash_type=%d (err %d): %s",
 			(int)hash_to_nss[instance->crypto_hash_type],
 			(*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT));
 		goto out;
 	}
 
 	err = 0;
 
 out:
 	if (hash_context) {
 		(*_int_PK11_DestroyContext)(hash_context, PR_TRUE);
 	}
 
 	return err;
 }
 
 /*
  * global/glue nss functions
  */
 
 static int init_nss(knet_handle_t knet_h)
 {
 	if (init_nss_crypto(knet_h) < 0) {
 		return -1;
 	}
 
 	if (init_nss_hash(knet_h) < 0) {
 		return -1;
 	}
 
 	return 0;
 }
 
 /*
  * exported API
  */
 
 int nsscrypto_encrypt_and_sign (
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	struct iovec iov_in;
 
 	memset(&iov_in, 0, sizeof(iov_in));
 	iov_in.iov_base = (unsigned char *)buf_in;
 	iov_in.iov_len = buf_in_len;
 
 	return nsscrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len);
 }
 
 int nsscrypto_encrypt_and_signv (
 	knet_handle_t knet_h,
 	const struct iovec *iov_in,
 	int iovcnt_in,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 	int i;
 
 	if (cipher_to_nss[instance->crypto_cipher_type]) {
 		if (encrypt_nss(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len) < 0) {
 			return -1;
 		}
 	} else {
 		*buf_out_len = 0;
 		for (i=0; i<iovcnt_in; i++) {
 			memmove(buf_out + *buf_out_len, iov_in[i].iov_base, iov_in[i].iov_len);
 			*buf_out_len = *buf_out_len + iov_in[i].iov_len;
 		}
 	}
 
 	if (hash_to_nss[instance->crypto_hash_type]) {
 		if (calculate_nss_hash(knet_h, buf_out, *buf_out_len, buf_out + *buf_out_len) < 0) {
 			return -1;
 		}
 		*buf_out_len = *buf_out_len + nsshash_len[instance->crypto_hash_type];
 	}
 
 	return 0;
 }
 
 int nsscrypto_authenticate_and_decrypt (
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
 	ssize_t temp_len = buf_in_len;
 
 	if (hash_to_nss[instance->crypto_hash_type]) {
 		unsigned char tmp_hash[nsshash_len[instance->crypto_hash_type]];
 		ssize_t temp_buf_len = buf_in_len - nsshash_len[instance->crypto_hash_type];
 
 		if ((temp_buf_len < 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) {
 			log_err(knet_h, KNET_SUB_NSSCRYPTO, "Incorrect packet size.");
 			return -1;
 		}
 
 		if (calculate_nss_hash(knet_h, buf_in, temp_buf_len, tmp_hash) < 0) {
 			return -1;
 		}
 
 		if (memcmp(tmp_hash, buf_in + temp_buf_len, nsshash_len[instance->crypto_hash_type]) != 0) {
 			log_err(knet_h, KNET_SUB_NSSCRYPTO, "Digest does not match");
 			return -1;
 		}
 
 		temp_len = temp_len - nsshash_len[instance->crypto_hash_type];
 		*buf_out_len = temp_len;
 	}
 
 	if (cipher_to_nss[instance->crypto_cipher_type]) {
 		if (decrypt_nss(knet_h, buf_in, temp_len, buf_out, buf_out_len) < 0) {
 			return -1;
 		}
 	} else {
 		memmove(buf_out, buf_in, temp_len);
 		*buf_out_len = temp_len;
 	}
 
 	return 0;
 }
 
 int nsscrypto_init(
 	knet_handle_t knet_h,
 	struct knet_handle_crypto_cfg *knet_handle_crypto_cfg)
 {
 	struct nsscrypto_instance *nsscrypto_instance = NULL;
 
 	log_debug(knet_h, KNET_SUB_NSSCRYPTO,
 		  "Initizializing nss crypto module [%s/%s]",
 		  knet_handle_crypto_cfg->crypto_cipher_type,
 		  knet_handle_crypto_cfg->crypto_hash_type);
 
 	knet_h->crypto_instance->model_instance = malloc(sizeof(struct nsscrypto_instance));
 	if (!knet_h->crypto_instance->model_instance) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to allocate memory for nss model instance");
 		return -1;
 	}
 
 	nsscrypto_instance = knet_h->crypto_instance->model_instance;
 
 	memset(nsscrypto_instance, 0, sizeof(struct nsscrypto_instance));
 
 	nsscrypto_instance->crypto_cipher_type = nssstring_to_crypto_cipher_type(knet_handle_crypto_cfg->crypto_cipher_type);
 	if (nsscrypto_instance->crypto_cipher_type < 0) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto cipher type requested");
 		goto out_err;
 	}
 
 	nsscrypto_instance->crypto_hash_type = nssstring_to_crypto_hash_type(knet_handle_crypto_cfg->crypto_hash_type);
 	if (nsscrypto_instance->crypto_hash_type < 0) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto hash type requested");
 		goto out_err;
 	}
 
 	if ((nsscrypto_instance->crypto_cipher_type > 0) &&
 	    (nsscrypto_instance->crypto_hash_type == 0)) {
 		log_err(knet_h, KNET_SUB_NSSCRYPTO, "crypto communication requires hash specified");
 		goto out_err;
 	}
 
 	nsscrypto_instance->private_key = knet_handle_crypto_cfg->private_key;
 	nsscrypto_instance->private_key_len = knet_handle_crypto_cfg->private_key_len;
 
 	if (init_nss(knet_h) < 0) {
 		goto out_err;
 	}
 
 	knet_h->sec_header_size = 0;
 
 	if (nsscrypto_instance->crypto_hash_type > 0) {
 		knet_h->sec_header_size += nsshash_len[nsscrypto_instance->crypto_hash_type];
 		knet_h->sec_hash_size = nsshash_len[nsscrypto_instance->crypto_hash_type];
 	}
 
 	if (nsscrypto_instance->crypto_cipher_type > 0) {
 		int block_size;
 
 		if (nsscypher_block_len[nsscrypto_instance->crypto_cipher_type]) {
 			block_size = nsscypher_block_len[nsscrypto_instance->crypto_cipher_type];
 		} else {
 			block_size = (*_int_PK11_GetBlockSize)(nsscrypto_instance->crypto_cipher_type, NULL);
 			if (block_size < 0) {
 				goto out_err;
 			}
 		}
 
 		knet_h->sec_header_size += (block_size * 2);
 		knet_h->sec_header_size += SALT_SIZE;
 		knet_h->sec_salt_size = SALT_SIZE;
 		knet_h->sec_block_size = block_size;
 	}
 
 	return 0;
 
 out_err:
 	nsscrypto_fini(knet_h);
 	return -1;
 }
 
 void nsscrypto_fini(
 	knet_handle_t knet_h)
 {
 	struct nsscrypto_instance *nsscrypto_instance = knet_h->crypto_instance->model_instance;
 
 	if (nsscrypto_instance) {
 		if (nsscrypto_instance->nss_sym_key) {
 			(*_int_PK11_FreeSymKey)(nsscrypto_instance->nss_sym_key);
 			nsscrypto_instance->nss_sym_key = NULL;
 		}
 		if (nsscrypto_instance->nss_sym_key_sign) {
 			(*_int_PK11_FreeSymKey)(nsscrypto_instance->nss_sym_key_sign);
 			nsscrypto_instance->nss_sym_key_sign = NULL;
 		}
 		free(nsscrypto_instance);
 		knet_h->crypto_instance->model_instance = NULL;
 		knet_h->sec_header_size = 0;
 	}
 
 	return;
 }
 #endif
diff --git a/libknet/crypto_nss.h b/libknet/crypto_nss.h
index 9443fb50..d77a8d8b 100644
--- a/libknet/crypto_nss.h
+++ b/libknet/crypto_nss.h
@@ -1,47 +1,47 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_NSSCRYPTO_H__
 #define __KNET_NSSCRYPTO_H__
 
 #include "internals.h"
 
 struct nsscrypto_instance;
 
 int nsscrypto_load_lib(
 	knet_handle_t knet_h);
 
 int nsscrypto_init(
 	knet_handle_t knet_h,
 	struct knet_handle_crypto_cfg *knet_handle_crypto_cfg);
 
 void nsscrypto_fini(
 	knet_handle_t knet_h);
 
 int nsscrypto_authenticate_and_decrypt (
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len);
 
 int nsscrypto_encrypt_and_sign (
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len);
 
 int nsscrypto_encrypt_and_signv (
 	knet_handle_t knet_h,
 	const struct iovec *iov_in,
 	int iovcnt_in,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len);
 
 #endif
diff --git a/libknet/crypto_openssl.h b/libknet/crypto_openssl.h
index f314b9d8..cdb2fd44 100644
--- a/libknet/crypto_openssl.h
+++ b/libknet/crypto_openssl.h
@@ -1,47 +1,47 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_OPENSSLCRYPTO_H__
 #define __KNET_OPENSSLCRYPTO_H__
 
 #include "internals.h"
 
 struct opensslcrypto_instance;
 
 int opensslcrypto_load_lib(
 	knet_handle_t knet_h);
 
 int opensslcrypto_init(
 	knet_handle_t knet_h,
 	struct knet_handle_crypto_cfg *knet_handle_crypto_cfg);
 
 void opensslcrypto_fini(
 	knet_handle_t knet_h);
 
 int opensslcrypto_authenticate_and_decrypt (
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len);
 
 int opensslcrypto_encrypt_and_sign (
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len);
 
 int opensslcrypto_encrypt_and_signv (
 	knet_handle_t knet_h,
 	const struct iovec *iov_in,
 	int iovcnt_in,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len);
 
 #endif
diff --git a/libknet/internals.h b/libknet/internals.h
index 0a4d5cf1..048590aa 100644
--- a/libknet/internals.h
+++ b/libknet/internals.h
@@ -1,488 +1,488 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_INTERNALS_H__
 #define __KNET_INTERNALS_H__
 
 /*
  * NOTE: you shouldn't need to include this header normally
  */
 
 #include <pthread.h>
 #include "libknet.h"
 #include "onwire.h"
 #include "compat.h"
 
 #define KNET_DATABUFSIZE KNET_MAX_PACKET_SIZE + KNET_HEADER_ALL_SIZE
 
 #define KNET_DATABUFSIZE_CRYPT_PAD 1024
 #define KNET_DATABUFSIZE_CRYPT KNET_DATABUFSIZE + KNET_DATABUFSIZE_CRYPT_PAD
 
 #define KNET_DATABUFSIZE_COMPRESS_PAD 1024
 #define KNET_DATABUFSIZE_COMPRESS KNET_DATABUFSIZE + KNET_DATABUFSIZE_COMPRESS_PAD
 
 #define KNET_RING_RCVBUFF 8388608
 
 #define PCKT_FRAG_MAX UINT8_MAX
 #define PCKT_RX_BUFS  512
 
 #define KNET_EPOLL_MAX_EVENTS KNET_DATAFD_MAX
 
 typedef void *knet_transport_link_t; /* per link transport handle */
 typedef void *knet_transport_t;      /* per knet_h transport handle */
 struct  knet_transport_ops;          /* Forward because of circular dependancy */
 
 struct knet_mmsghdr {
 	struct msghdr msg_hdr;	/* Message header */
 	unsigned int  msg_len;	/* Number of bytes transmitted */
 };
 
 struct knet_link {
 	/* required */
 	struct sockaddr_storage src_addr;
 	struct sockaddr_storage dst_addr;
 	/* configurable */
 	unsigned int dynamic;			/* see KNET_LINK_DYN_ define above */
 	uint8_t  priority;			/* higher priority == preferred for A/P */
 	unsigned long long ping_interval;	/* interval */
 	unsigned long long pong_timeout;	/* timeout */
 	unsigned int latency_fix;		/* precision */
 	uint8_t pong_count;			/* how many ping/pong to send/receive before link is up */
 	uint64_t flags;
 	/* status */
 	struct knet_link_status status;
 	/* internals */
 	uint8_t link_id;
 	uint8_t transport_type;                 /* #defined constant from API */
 	knet_transport_link_t transport_link;   /* link_info_t from transport */
 	int outsock;
 	unsigned int configured:1;		/* set to 1 if src/dst have been configured transport initialized on this link*/
 	unsigned int transport_connected:1;	/* set to 1 if lower level transport is connected */
 	unsigned int latency_exp;
 	uint8_t received_pong;
 	struct timespec ping_last;
 	/* used by PMTUD thread as temp per-link variables and should always contain the onwire_len value! */
 	uint32_t proto_overhead;
 	struct timespec pmtud_last;
 	uint32_t last_ping_size;
 	uint32_t last_good_mtu;
 	uint32_t last_bad_mtu;
 	uint32_t last_sent_mtu;
 	uint32_t last_recv_mtu;
 	uint8_t has_valid_mtu;
 };
 
 #define KNET_CBUFFER_SIZE 4096
 
 struct knet_host_defrag_buf {
 	char buf[KNET_DATABUFSIZE];
 	uint8_t in_use;			/* 0 buffer is free, 1 is in use */
 	seq_num_t pckt_seq;		/* identify the pckt we are receiving */
 	uint8_t frag_recv;		/* how many frags did we receive */
 	uint8_t frag_map[PCKT_FRAG_MAX];/* bitmap of what we received? */
 	uint8_t	last_first;		/* special case if we receive the last fragment first */
 	uint16_t frag_size;		/* normal frag size (not the last one) */
 	uint16_t last_frag_size;	/* the last fragment might not be aligned with MTU size */
 	struct timespec last_update;	/* keep time of the last pckt */
 };
 
 struct knet_host {
 	/* required */
 	knet_node_id_t host_id;
 	/* configurable */
 	uint8_t link_handler_policy;
 	char name[KNET_MAX_HOST_LEN];
 	/* status */
 	struct knet_host_status status;
 	/* internals */
 	char circular_buffer[KNET_CBUFFER_SIZE];
 	seq_num_t rx_seq_num;
 	seq_num_t untimed_rx_seq_num;
 	seq_num_t timed_rx_seq_num;
 	uint8_t got_data;
 	/* defrag/reassembly buffers */
 	struct knet_host_defrag_buf defrag_buf[KNET_MAX_LINK];
 	char circular_buffer_defrag[KNET_CBUFFER_SIZE];
 	/* link stuff */
 	struct knet_link link[KNET_MAX_LINK];
 	uint8_t active_link_entries;
 	uint8_t active_links[KNET_MAX_LINK];
 	struct knet_host *next;
 };
 
 struct knet_sock {
 	int sockfd[2];   /* sockfd[0] will always be application facing
 			  * and sockfd[1] internal if sockpair has been created by knet */
 	int is_socket;   /* check if it's a socket for recvmmsg usage */
 	int is_created;  /* knet created this socket and has to clean up on exit/del */
 	int in_use;      /* set to 1 if it's use, 0 if free */
 	int has_error;   /* set to 1 if there were errors reading from the sock
 			  * and socket has been removed from epoll */
 };
 
 struct knet_fd_trackers {
 	uint8_t transport; /* transport type (UDP/SCTP...) */
 	uint8_t data_type; /* internal use for transport to define what data are associated
 			    * to this fd */
 	void *data;	   /* pointer to the data */
 };
 
 #define KNET_MAX_FDS KNET_MAX_HOST * KNET_MAX_LINK * 4
 
 #define KNET_MAX_COMPRESS_METHODS UINT8_MAX
 
 struct knet_handle {
 	knet_node_id_t host_id;
 	unsigned int enabled:1;
 	struct knet_sock sockfd[KNET_DATAFD_MAX];
 	int logfd;
 	uint8_t log_levels[KNET_MAX_SUBSYSTEMS];
 	int hostsockfd[2];
 	int dstsockfd[2];
 	int send_to_links_epollfd;
 	int recv_from_links_epollfd;
 	int dst_link_handler_epollfd;
 	unsigned int pmtud_interval;
 	unsigned int data_mtu;	/* contains the max data size that we can send onwire
 				 * without frags */
 	struct knet_host *host_head;
 	struct knet_host *host_index[KNET_MAX_HOST];
 	knet_transport_t transports[KNET_MAX_TRANSPORTS+1];
 	struct knet_transport_ops *transport_ops[KNET_MAX_TRANSPORTS+1];
 	struct knet_fd_trackers knet_transport_fd_tracker[KNET_MAX_FDS]; /* track status for each fd handled by transports */
 	struct knet_handle_stats stats;
 	uint32_t reconnect_int;
 	knet_node_id_t host_ids[KNET_MAX_HOST];
 	size_t host_ids_entries;
 	struct knet_header *recv_from_sock_buf;
 	struct knet_header *send_to_links_buf[PCKT_FRAG_MAX];
 	struct knet_header *recv_from_links_buf[PCKT_RX_BUFS];
 	struct knet_header *pingbuf;
 	struct knet_header *pmtudbuf;
 	pthread_t send_to_links_thread;
 	pthread_t recv_from_links_thread;
 	pthread_t heartbt_thread;
 	pthread_t dst_link_handler_thread;
 	pthread_t pmtud_link_handler_thread;
 	int lock_init_done;
 	pthread_rwlock_t global_rwlock;		/* global config lock */
 	pthread_mutex_t pmtud_mutex;		/* pmtud mutex to handle conditional send/recv + timeout */
 	pthread_cond_t pmtud_cond;		/* conditional for above */
 	pthread_mutex_t tx_mutex;		/* used to protect knet_send_sync and TX thread */
 	pthread_mutex_t hb_mutex;		/* used to protect heartbeat thread and seq_num broadcasting */
 	struct crypto_instance *crypto_instance;
 	size_t sec_header_size;
 	size_t sec_block_size;
 	size_t sec_hash_size;
 	size_t sec_salt_size;
 	unsigned char *send_to_links_buf_crypt[PCKT_FRAG_MAX];
 	unsigned char *recv_from_links_buf_crypt;
 	unsigned char *recv_from_links_buf_decrypt;
 	unsigned char *pingbuf_crypt;
 	unsigned char *pmtudbuf_crypt;
 	int compress_model;
 	int compress_level;
 	size_t compress_threshold;
 	void *compress_int_data[KNET_MAX_COMPRESS_METHODS]; /* for compress method private data */
 	unsigned char *recv_from_links_buf_decompress;
 	unsigned char *send_to_links_buf_compress;
 	seq_num_t tx_seq_num;
 	pthread_mutex_t tx_seq_num_mutex;
 	uint8_t has_loop_link;
 	uint8_t loop_link;
 	void *dst_host_filter_fn_private_data;
 	int (*dst_host_filter_fn) (
 		void *private_data,
 		const unsigned char *outdata,
 		ssize_t outdata_len,
 		uint8_t tx_rx,
 		knet_node_id_t this_host_id,
 		knet_node_id_t src_node_id,
 		int8_t *channel,
 		knet_node_id_t *dst_host_ids,
 		size_t *dst_host_ids_entries);
 	void *pmtud_notify_fn_private_data;
 	void (*pmtud_notify_fn) (
 		void *private_data,
 		unsigned int data_mtu);
 	void *host_status_change_notify_fn_private_data;
 	void (*host_status_change_notify_fn) (
 		void *private_data,
 		knet_node_id_t host_id,
 		uint8_t reachable,
 		uint8_t remote,
 		uint8_t external);
 	void *sock_notify_fn_private_data;
 	void (*sock_notify_fn) (
 		void *private_data,
 		int datafd,
 		int8_t channel,
 		uint8_t tx_rx,
 		int error,
 		int errorno);
 	int fini_in_progress;
 };
 
 extern pthread_rwlock_t shlib_rwlock;       /* global shared lib load lock */
 
 /*
  * NOTE: every single operation must be implementend
  *       for every protocol.
  */
 
 typedef struct knet_transport_ops {
 /*
  * transport generic information
  */
 	const char *transport_name;
 	const uint8_t transport_id;
 	uint32_t transport_mtu_overhead;
 /*
  * transport init must allocate the new transport
  * and perform all internal initializations
  * (threads, lists, etc).
  */
 	int (*transport_init)(knet_handle_t knet_h);
 /*
  * transport free must releases _all_ resources
  * allocated by tranport_init
  */
 	int (*transport_free)(knet_handle_t knet_h);
 
 /*
  * link operations should take care of all the
  * sockets and epoll management for a given link/transport set
  * transport_link_disable should return err = -1 and errno = EBUSY
  * if listener is still in use, and any other errno in case
  * the link cannot be disabled.
  *
  * set_config/clear_config are invoked in global write lock context
  */
 	int (*transport_link_set_config)(knet_handle_t knet_h, struct knet_link *link);
 	int (*transport_link_clear_config)(knet_handle_t knet_h, struct knet_link *link);
 
 /*
  * transport callback for incoming dynamic connections
  * this is called in global read lock context
  */
 	int (*transport_link_dyn_connect)(knet_handle_t knet_h, int sockfd, struct knet_link *link);
 
 /*
  * per transport error handling of recvmmsg
  * (see _handle_recv_from_links comments for details)
  */
 
 /*
  * transport_rx_sock_error is invoked when recvmmsg returns <= 0
  *
  * transport_rx_sock_error is invoked with both global_rdlock
  */
 
 	int (*transport_rx_sock_error)(knet_handle_t knet_h, int sockfd, int recv_err, int recv_errno);
 
 /*
  * transport_tx_sock_error is invoked with global_rwlock and
  * it's invoked when sendto or sendmmsg returns =< 0
  *
  * it should return:
  * -1 on internal error
  *  0 ignore error and continue
  *  1 retry
  *    any sleep or wait action should happen inside the transport code
  */
 	int (*transport_tx_sock_error)(knet_handle_t knet_h, int sockfd, int recv_err, int recv_errno);
 
 /*
  * this function is called on _every_ received packet
  * to verify if the packet is data or internal protocol error handling
  *
  * it should return:
  * -1 on error
  *  0 packet is not data and we should continue the packet process loop
  *  1 packet is not data and we should STOP the packet process loop
  *  2 packet is data and should be parsed as such
  *
  * transport_rx_is_data is invoked with both global_rwlock
  * and fd_tracker read lock (from RX thread)
  */
 	int (*transport_rx_is_data)(knet_handle_t knet_h, int sockfd, struct knet_mmsghdr *msg);
 } knet_transport_ops_t;
 
 socklen_t sockaddr_len(const struct sockaddr_storage *ss);
 
 /**
  * This is a kernel style list implementation.
  *
  * @author Steven Dake <sdake@redhat.com>
  */
 
 struct knet_list_head {
 	struct knet_list_head *next;
 	struct knet_list_head *prev;
 };
 
 /**
  * @def KNET_LIST_DECLARE()
  * Declare and initialize a list head.
  */
 #define KNET_LIST_DECLARE(name) \
     struct knet_list_head name = { &(name), &(name) }
 
 #define KNET_INIT_LIST_HEAD(ptr) do { \
 	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
 } while (0)
 
 /**
  * Initialize the list entry.
  *
  * Points next and prev pointers to head.
  * @param head pointer to the list head
  */
 static inline void knet_list_init(struct knet_list_head *head)
 {
 	head->next = head;
 	head->prev = head;
 }
 
 /**
  * Add this element to the list.
  *
  * @param element the new element to insert.
  * @param head pointer to the list head
  */
 static inline void knet_list_add(struct knet_list_head *element,
 			       struct knet_list_head *head)
 {
 	head->next->prev = element;
 	element->next = head->next;
 	element->prev = head;
 	head->next = element;
 }
 
 /**
  * Add to the list (but at the end of the list).
  *
  * @param element pointer to the element to add
  * @param head pointer to the list head
  * @see knet_list_add()
  */
 static inline void knet_list_add_tail(struct knet_list_head *element,
 				    struct knet_list_head *head)
 {
 	head->prev->next = element;
 	element->next = head;
 	element->prev = head->prev;
 	head->prev = element;
 }
 
 /**
  * Delete an entry from the list.
  *
  * @param _remove the list item to remove
  */
 static inline void knet_list_del(struct knet_list_head *_remove)
 {
 	_remove->next->prev = _remove->prev;
 	_remove->prev->next = _remove->next;
 }
 
 /**
  * Replace old entry by new one
  * @param old: the element to be replaced
  * @param new: the new element to insert
  */
 static inline void knet_list_replace(struct knet_list_head *old,
 		struct knet_list_head *new)
 {
 	new->next = old->next;
 	new->next->prev = new;
 	new->prev = old->prev;
 	new->prev->next = new;
 }
 
 /**
  * Tests whether list is the last entry in list head
  * @param list: the entry to test
  * @param head: the head of the list
  * @return boolean true/false
  */
 static inline int knet_list_is_last(const struct knet_list_head *list,
 		const struct knet_list_head *head)
 {
 	return list->next == head;
 }
 
 /**
  * A quick test to see if the list is empty (pointing to it's self).
  * @param head pointer to the list head
  * @return boolean true/false
  */
 static inline int32_t knet_list_empty(const struct knet_list_head *head)
 {
 	return head->next == head;
 }
 
 
 /**
  * Get the struct for this entry
  * @param ptr:	the &struct list_head pointer.
  * @param type:	the type of the struct this is embedded in.
  * @param member:	the name of the list_struct within the struct.
  */
 #define knet_list_entry(ptr,type,member)\
 	((type *)((char *)(ptr)-(char*)(&((type *)0)->member)))
 
 /**
  * Get the first element from a list
  * @param ptr:	the &struct list_head pointer.
  * @param type:	the type of the struct this is embedded in.
  * @param member:	the name of the list_struct within the struct.
  */
 #define knet_list_first_entry(ptr, type, member) \
 	knet_list_entry((ptr)->next, type, member)
 
 /**
  * Iterate over a list
  * @param pos:	the &struct list_head to use as a loop counter.
  * @param head:	the head for your list.
  */
 #define knet_list_for_each(pos, head) \
 	for (pos = (head)->next; pos != (head); pos = pos->next)
 
 /**
  * Iterate over a list backwards
  * @param pos:	the &struct list_head to use as a loop counter.
  * @param head:	the head for your list.
  */
 #define knet_list_for_each_reverse(pos, head) \
 	for (pos = (head)->prev; pos != (head); pos = pos->prev)
 
 /**
  * Iterate over a list safe against removal of list entry
  * @param pos:	the &struct list_head to use as a loop counter.
  * @param n:		another &struct list_head to use as temporary storage
  * @param head:	the head for your list.
  */
 #define knet_list_for_each_safe(pos, n, head) \
 	for (pos = (head)->next, n = pos->next; pos != (head); \
 		pos = n, n = pos->next)
 
 /**
  * Iterate over list of given type
  * @param pos:	the type * to use as a loop counter.
  * @param head:	the head for your list.
  * @param member:	the name of the list_struct within the struct.
  */
 #define knet_list_for_each_entry(pos, head, member)			\
 	for (pos = knet_list_entry((head)->next, typeof(*pos), member);	\
 	     &pos->member != (head);					\
 	     pos = knet_list_entry(pos->member.next, typeof(*pos), member))
 
 
 #endif
diff --git a/libknet/links.c b/libknet/links.c
index 7ccbeabc..8d7bfe77 100644
--- a/libknet/links.c
+++ b/libknet/links.c
@@ -1,1087 +1,1087 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <netdb.h>
 #include <string.h>
 #include <pthread.h>
 
 #include "internals.h"
 #include "logging.h"
 #include "links.h"
 #include "transports.h"
 #include "host.h"
 
 int _link_updown(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 		 unsigned int enabled, unsigned int connected)
 {
 	struct knet_link *link = &knet_h->host_index[host_id]->link[link_id];
 
 	if ((link->status.enabled == enabled) &&
 	    (link->status.connected == connected))
 		return 0;
 
 	link->status.enabled = enabled;
 	link->status.connected = connected;
 
 	_host_dstcache_update_async(knet_h, knet_h->host_index[host_id]);
 
 	if ((link->status.dynconnected) &&
 	    (!link->status.connected))
 		link->status.dynconnected = 0;
 
 	if (connected) {
 		time(&link->status.stats.last_up_times[link->status.stats.last_up_time_index]);
 		link->status.stats.up_count++;
 		if (++link->status.stats.last_up_time_index > MAX_LINK_EVENTS) {
 			link->status.stats.last_up_time_index = 0;
 		}
 	} else {
 		time(&link->status.stats.last_down_times[link->status.stats.last_down_time_index]);
 		link->status.stats.down_count++;
 		if (++link->status.stats.last_down_time_index > MAX_LINK_EVENTS) {
 			link->status.stats.last_down_time_index = 0;
 		}
 	}
 	return 0;
 }
 
 void _link_clear_stats(knet_handle_t knet_h)
 {
 	struct knet_host *host;
 	struct knet_link *link;
 	uint32_t host_id;
 	uint8_t link_id;
 
 	for (host_id = 0; host_id < KNET_MAX_HOST; host_id++) {
 		host = knet_h->host_index[host_id];
 		if (!host) {
 			continue;
 		}
 		for (link_id = 0; link_id < KNET_MAX_LINK; link_id++) {
 			link = &host->link[link_id];
 			memset(&link->status.stats, 0, sizeof(struct knet_link_stats));
 		}
 	}
 }
 
 int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			 uint8_t transport,
 			 struct sockaddr_storage *src_addr,
 			 struct sockaddr_storage *dst_addr,
 			 uint64_t flags)
 {
 	int savederrno = 0, err = 0, i;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!src_addr) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (transport >= KNET_MAX_TRANSPORTS) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!knet_h->transport_ops[transport]) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	if (transport == KNET_TRANSPORT_LOOPBACK && knet_h->host_id != host_id) {
 		log_err(knet_h, KNET_SUB_LINK, "Cannot create loopback link to remote node");
 		err = -1;
 		savederrno = EINVAL;
 		goto exit_unlock;
 	}
 
 	if (knet_h->host_id == host_id && knet_h->has_loop_link) {
 		log_err(knet_h, KNET_SUB_LINK, "Cannot create more than 1 link when loopback is active");
 		err = -1;
 		savederrno = EINVAL;
 		goto exit_unlock;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	if (transport == KNET_TRANSPORT_LOOPBACK && knet_h->host_id == host_id) {
 		for (i=0; i<KNET_MAX_LINK; i++) {
 			if (host->link[i].configured) {
 				log_err(knet_h, KNET_SUB_LINK, "Cannot add loopback link when other links are already configured.");
 				err = -1;
 				savederrno = EINVAL;
 				goto exit_unlock;
 			}
 		}
 	}
 
 	link = &host->link[link_id];
 
 	if (link->configured != 0) {
 		err =-1;
 		savederrno = EBUSY;
 		log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is currently configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	if (link->status.enabled != 0) {
 		err =-1;
 		savederrno = EBUSY;
 		log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is currently in use: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	memmove(&link->src_addr, src_addr, sizeof(struct sockaddr_storage));
 
 	err = knet_addrtostr(src_addr, sizeof(struct sockaddr_storage),
 			     link->status.src_ipaddr, KNET_MAX_HOST_LEN,
 			     link->status.src_port, KNET_MAX_PORT_LEN);
 	if (err) {
 		if (err == EAI_SYSTEM) {
 			savederrno = errno;
 			log_warn(knet_h, KNET_SUB_LINK,
 				 "Unable to resolve host: %u link: %u source addr/port: %s",
 				 host_id, link_id, strerror(savederrno));
 		} else {
 			savederrno = EINVAL;
 			log_warn(knet_h, KNET_SUB_LINK,
 				 "Unable to resolve host: %u link: %u source addr/port: %s",
 				 host_id, link_id, gai_strerror(err));
 		}
 		err = -1;
 		goto exit_unlock;
 	}
 
 	if (!dst_addr) {
 		link->dynamic = KNET_LINK_DYNIP;
 	} else {
 
 		link->dynamic = KNET_LINK_STATIC;
 
 		memmove(&link->dst_addr, dst_addr, sizeof(struct sockaddr_storage));
 		err = knet_addrtostr(dst_addr, sizeof(struct sockaddr_storage),
 				     link->status.dst_ipaddr, KNET_MAX_HOST_LEN,
 				     link->status.dst_port, KNET_MAX_PORT_LEN);
 		if (err) {
 			if (err == EAI_SYSTEM) {
 				savederrno = errno;
 				log_warn(knet_h, KNET_SUB_LINK,
 					 "Unable to resolve host: %u link: %u destination addr/port: %s",
 					 host_id, link_id, strerror(savederrno));
 			} else {
 				savederrno = EINVAL;
 				log_warn(knet_h, KNET_SUB_LINK,
 					 "Unable to resolve host: %u link: %u destination addr/port: %s",
 					 host_id, link_id, gai_strerror(err));
 			}
 			err = -1;
 			goto exit_unlock;
 		}
 	}
 
 	link->transport_type = transport;
 	link->transport_connected = 0;
 	link->proto_overhead = knet_h->transport_ops[link->transport_type]->transport_mtu_overhead;
 	link->pong_count = KNET_LINK_DEFAULT_PONG_COUNT;
 	link->has_valid_mtu = 0;
 	link->ping_interval = KNET_LINK_DEFAULT_PING_INTERVAL * 1000; /* microseconds */
 	link->pong_timeout = KNET_LINK_DEFAULT_PING_TIMEOUT * 1000; /* microseconds */
 	link->latency_fix = KNET_LINK_DEFAULT_PING_PRECISION;
 	link->latency_exp = KNET_LINK_DEFAULT_PING_PRECISION - \
 			    ((link->ping_interval * KNET_LINK_DEFAULT_PING_PRECISION) / 8000000);
 	link->flags = flags;
 
 	if (knet_h->transport_ops[link->transport_type]->transport_link_set_config(knet_h, link) < 0) {
 		savederrno = errno;
 		err = -1;
 		goto exit_unlock;
 	}
 	link->configured = 1;
 	log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u is configured",
 		  host_id, link_id);
 
 	if (transport == KNET_TRANSPORT_LOOPBACK) {
 		knet_h->has_loop_link = 1;
 		knet_h->loop_link = link_id;
 		host->status.reachable = 1;
 	}
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_get_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			 uint8_t *transport,
 			 struct sockaddr_storage *src_addr,
 			 struct sockaddr_storage *dst_addr,
 			 uint8_t *dynamic,
 			 uint64_t *flags)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!src_addr) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!dynamic) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!transport) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!flags) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	if ((link->dynamic == KNET_LINK_STATIC) && (!dst_addr)) {
 		savederrno = EINVAL;
 		err = -1;
 		goto exit_unlock;
 	}
 
 	memmove(src_addr, &link->src_addr, sizeof(struct sockaddr_storage));
 
 	*transport = link->transport_type;
 	*flags = link->flags;
 
 	if (link->dynamic == KNET_LINK_STATIC) {
 		*dynamic = 0;
 		memmove(dst_addr, &link->dst_addr, sizeof(struct sockaddr_storage));
 	} else {
 		*dynamic = 1;
 	}
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_clear_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (link->configured != 1) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	if (link->status.enabled != 0) {
 		err = -1;
 		savederrno = EBUSY;
 		log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is currently in use: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	if ((knet_h->transport_ops[link->transport_type]->transport_link_clear_config(knet_h, link) < 0) &&
 	    (errno != EBUSY)) {
 		savederrno = errno;
 		err = -1;
 		goto exit_unlock;
 	}
 
 	memset(link, 0, sizeof(struct knet_link));
 	link->link_id = link_id;
 
 	if (knet_h->has_loop_link && link_id == knet_h->loop_link) {
 		knet_h->has_loop_link = 0;
 		if (host->active_link_entries == 0) {
 			host->status.reachable = 0;
 		}
 	}
 
 	log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u config has been wiped",
 		  host_id, link_id);
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_set_enable(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			 unsigned int enabled)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (enabled > 1) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	if (link->status.enabled == enabled) {
 		err = 0;
 		goto exit_unlock;
 	}
 
 	err = _link_updown(knet_h, host_id, link_id, enabled, link->status.connected);
 	savederrno = errno;
 
 	if (enabled) {
 		goto exit_unlock;
 	}
 
 	log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u is disabled",
 		  host_id, link_id);
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_get_enable(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			 unsigned int *enabled)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!enabled) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	*enabled = link->status.enabled;
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_set_pong_count(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			     uint8_t pong_count)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (pong_count < 1) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link->pong_count = pong_count;
 
 	log_debug(knet_h, KNET_SUB_LINK,
 		  "host: %u link: %u pong count update: %u",
 		  host_id, link_id, link->pong_count);
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_get_pong_count(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			     uint8_t *pong_count)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!pong_count) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	*pong_count = link->pong_count;
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_set_ping_timers(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			      time_t interval, time_t timeout, unsigned int precision)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!interval) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!timeout) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!precision) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link->ping_interval = interval * 1000; /* microseconds */
 	link->pong_timeout = timeout * 1000; /* microseconds */
 	link->latency_fix = precision;
 	link->latency_exp = precision - \
 			    ((link->ping_interval * precision) / 8000000);
 
 	log_debug(knet_h, KNET_SUB_LINK,
 		  "host: %u link: %u timeout update - interval: %llu timeout: %llu precision: %u",
 		  host_id, link_id, link->ping_interval, link->pong_timeout, precision);
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_get_ping_timers(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			      time_t *interval, time_t *timeout, unsigned int *precision)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!interval) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!timeout) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!precision) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	*interval = link->ping_interval / 1000; /* microseconds */
 	*timeout = link->pong_timeout / 1000;
 	*precision = link->latency_fix;
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_set_priority(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			   uint8_t priority)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 	uint8_t old_priority;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	old_priority = link->priority;
 
 	if (link->priority == priority) {
 		err = 0;
 		goto exit_unlock;
 	}
 
 	link->priority = priority;
 
 	if (_host_dstcache_update_sync(knet_h, host)) {
 		savederrno = errno;
 		log_debug(knet_h, KNET_SUB_LINK,
 			  "Unable to update link priority (host: %u link: %u priority: %u): %s",
 			  host_id, link_id, link->priority, strerror(savederrno));
 		link->priority = old_priority;
 		err = -1;
 		goto exit_unlock;
 	}
 
 	log_debug(knet_h, KNET_SUB_LINK,
 		  "host: %u link: %u priority set to: %u",
 		  host_id, link_id, link->priority);
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_get_priority(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			   uint8_t *priority)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!priority) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	*priority = link->priority;
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_get_link_list(knet_handle_t knet_h, knet_node_id_t host_id,
 			    uint8_t *link_ids, size_t *link_ids_entries)
 {
 	int savederrno = 0, err = 0, i, count = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!link_ids) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!link_ids_entries) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	for (i = 0; i < KNET_MAX_LINK; i++) {
 		link = &host->link[i];
 		if (!link->configured) {
 			continue;
 		}
 		link_ids[count] = i;
 		count++;
 	}
 
 	*link_ids_entries = count;
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
 
 int knet_link_get_status(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
 			 struct knet_link_status *status, size_t struct_size)
 {
 	int savederrno = 0, err = 0;
 	struct knet_host *host;
 	struct knet_link *link;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (link_id >= KNET_MAX_LINK) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!status) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	host = knet_h->host_index[host_id];
 	if (!host) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
 			host_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	link = &host->link[link_id];
 
 	if (!link->configured) {
 		err = -1;
 		savederrno = EINVAL;
 		log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
 			host_id, link_id, strerror(savederrno));
 		goto exit_unlock;
 	}
 
 	memmove(status, &link->status, struct_size);
 
 	/* Calculate totals - no point in doing this on-the-fly */
 	status->stats.rx_total_packets =
 		status->stats.rx_data_packets +
 		status->stats.rx_ping_packets +
 		status->stats.rx_pong_packets +
 		status->stats.rx_pmtu_packets;
 	status->stats.tx_total_packets =
 		status->stats.tx_data_packets +
 		status->stats.tx_ping_packets +
 		status->stats.tx_pong_packets +
 		status->stats.tx_pmtu_packets;
 	status->stats.rx_total_bytes =
 		status->stats.rx_data_bytes +
 		status->stats.rx_ping_bytes +
 		status->stats.rx_pong_bytes +
 		status->stats.rx_pmtu_bytes;
 	status->stats.tx_total_bytes =
 		status->stats.tx_data_bytes +
 		status->stats.tx_ping_bytes +
 		status->stats.tx_pong_bytes +
 		status->stats.tx_pmtu_bytes;
 	status->stats.tx_total_errors =
 		status->stats.tx_data_errors +
 		status->stats.tx_ping_errors +
 		status->stats.tx_pong_errors +
 		status->stats.tx_pmtu_errors;
 	status->stats.tx_total_retries =
 		status->stats.tx_data_retries +
 		status->stats.tx_ping_retries +
 		status->stats.tx_pong_retries +
 		status->stats.tx_pmtu_retries;
 
 	/* Tell the caller our full size in case they have an old version */
 	status->size = sizeof(struct knet_link_status);
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	errno = savederrno;
 	return err;
 }
diff --git a/libknet/links.h b/libknet/links.h
index 119470a7..bd1b3d7d 100644
--- a/libknet/links.h
+++ b/libknet/links.h
@@ -1,23 +1,23 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_LINK_H__
 #define __KNET_LINK_H__
 
 #include "internals.h"
 
 #define KNET_LINK_STATIC             0 /* link has static ip on both ends */
 #define KNET_LINK_DYNIP              1 /* link has dynamic destination ip */
 
 int _link_updown(knet_handle_t knet_h, knet_node_id_t node_id, uint8_t link_id,
 		 unsigned int enabled, unsigned int connected);
 
 void _link_clear_stats(knet_handle_t knet_h);
 
 #endif
diff --git a/libknet/logging.c b/libknet/logging.c
index 3b7e2ffd..785b9fbb 100644
--- a/libknet/logging.c
+++ b/libknet/logging.c
@@ -1,256 +1,256 @@
 /*
- * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <strings.h>
 #include <string.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <stdarg.h>
 #include <errno.h>
 #include <stdio.h>
 
 #include "internals.h"
 #include "logging.h"
 
 struct pretty_names {
 	const char *name;
 	uint8_t val;
 };
 
 static struct pretty_names subsystem_names[] =
 {
 	{ "common", KNET_SUB_COMMON },
 	{ "handle", KNET_SUB_HANDLE },
 	{ "host", KNET_SUB_HOST },
 	{ "listener", KNET_SUB_LISTENER },
 	{ "link", KNET_SUB_LINK },
 	{ "transport", KNET_SUB_TRANSPORT },
 	{ "crypto", KNET_SUB_CRYPTO },
 	{ "compress", KNET_SUB_COMPRESS },
 	{ "filter", KNET_SUB_FILTER },
 	{ "dstcache", KNET_SUB_DSTCACHE },
 	{ "heartbeat", KNET_SUB_HEARTBEAT },
 	{ "pmtud", KNET_SUB_PMTUD },
 	{ "tx", KNET_SUB_TX },
 	{ "rx", KNET_SUB_RX },
 	{ "loopback", KNET_SUB_TRANSP_LOOPBACK },
 	{ "udp", KNET_SUB_TRANSP_UDP },
 	{ "sctp", KNET_SUB_TRANSP_SCTP },
 	{ "nsscrypto", KNET_SUB_NSSCRYPTO },
 	{ "opensslcrypto", KNET_SUB_OPENSSLCRYPTO },
 	{ "zlibcomp", KNET_SUB_ZLIBCOMP },
 	{ "lz4comp", KNET_SUB_LZ4COMP },
 	{ "lz4hccomp", KNET_SUB_LZ4HCCOMP },
 	{ "lzo2comp", KNET_SUB_LZO2COMP },
 	{ "lzmacomp", KNET_SUB_LZMACOMP },
 	{ "bzip2comp", KNET_SUB_BZIP2COMP },
 	{ "unknown", KNET_SUB_UNKNOWN }		/* unknown MUST always be last in this array */
 };
 
 const char *knet_log_get_subsystem_name(uint8_t subsystem)
 {
 	unsigned int i;
 
 	for (i = 0; i < KNET_MAX_SUBSYSTEMS; i++) {
 		if (subsystem_names[i].val == KNET_SUB_UNKNOWN) {
 			break;
 		}
 		if (subsystem_names[i].val == subsystem) {
 			return subsystem_names[i].name;
 		}
 	}
 	return "unknown";
 }
 
 uint8_t knet_log_get_subsystem_id(const char *name)
 {
 	unsigned int i;
 
 	for (i = 0; i < KNET_MAX_SUBSYSTEMS; i++) {
 		if (subsystem_names[i].val == KNET_SUB_UNKNOWN) {
 			break;
 		}
 		if (strcasecmp(name, subsystem_names[i].name) == 0) {
 			return subsystem_names[i].val;
 		}
 	}
 	return KNET_SUB_UNKNOWN;
 }
 
 static int is_valid_subsystem(uint8_t subsystem)
 {
 	unsigned int i;
 
 	for (i = 0; i < KNET_MAX_SUBSYSTEMS; i++) {
 		if ((subsystem != KNET_SUB_UNKNOWN) &&
 		    (subsystem_names[i].val == KNET_SUB_UNKNOWN)) {
 			break;
 		}
 		if (subsystem_names[i].val == subsystem) {
 			return 0;
 		}
 	}
 	return -1;
 }
 
 static struct pretty_names loglevel_names[] =
 {
 	{ "ERROR", KNET_LOG_ERR },
 	{ "WARNING", KNET_LOG_WARN },
 	{ "info", KNET_LOG_INFO },
 	{ "debug", KNET_LOG_DEBUG }
 };
 
 const char *knet_log_get_loglevel_name(uint8_t level)
 {
 	unsigned int i;
 
 	for (i = 0; i <= KNET_LOG_DEBUG; i++) {
 		if (loglevel_names[i].val == level) {
 			return loglevel_names[i].name;
 		}
 	}
 	return "ERROR";
 }
 
 uint8_t knet_log_get_loglevel_id(const char *name)
 {
 	unsigned int i;
 
 	for (i = 0; i <= KNET_LOG_DEBUG; i++) {
 		if (strcasecmp(name, loglevel_names[i].name) == 0) {
 			return loglevel_names[i].val;
 		}
 	}
 	return KNET_LOG_ERR;
 }
 
 int knet_log_set_loglevel(knet_handle_t knet_h, uint8_t subsystem,
 			  uint8_t level)
 {
 	int savederrno = 0;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (is_valid_subsystem(subsystem) < 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (level > KNET_LOG_DEBUG) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, subsystem, "Unable to get write lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	knet_h->log_levels[subsystem] = level;
 
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	return 0;
 }
 
 int knet_log_get_loglevel(knet_handle_t knet_h, uint8_t subsystem,
 			  uint8_t *level)
 {
 	int savederrno = 0;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (is_valid_subsystem(subsystem) < 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!level) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, subsystem, "Unable to get write lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	*level = knet_h->log_levels[subsystem];
 
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 	return 0;
 }
 
 void log_msg(knet_handle_t knet_h, uint8_t subsystem, uint8_t msglevel,
 	     const char *fmt, ...)
 {
 	va_list ap;
 	struct knet_log_msg msg;
 	size_t byte_cnt = 0;
 	int len, err;
 
 	if ((!knet_h) ||
 	    (subsystem == KNET_MAX_SUBSYSTEMS) ||
 	    (msglevel > knet_h->log_levels[subsystem]))
 			return;
 
 	/*
 	 * most logging calls will take place with locking in place.
 	 * if we get an EINVAL and locking is initialized, then
 	 * we are getting a real error and we need to stop
 	 */
 	err = pthread_rwlock_tryrdlock(&knet_h->global_rwlock);
 	if ((err == EAGAIN) && (knet_h->lock_init_done))
 		return;
 
 	if (knet_h->logfd <= 0)
 		goto out_unlock;
 
 	memset(&msg, 0, sizeof(struct knet_log_msg));
 	msg.subsystem = subsystem;
 	msg.msglevel = msglevel;
 
 	va_start(ap, fmt);
 	vsnprintf(msg.msg, sizeof(msg.msg) - 2, fmt, ap);
 	va_end(ap);
 
 	len = strlen(msg.msg);
 	msg.msg[len+1] = '\n';
 
 	while (byte_cnt < sizeof(struct knet_log_msg)) {
 		len = write(knet_h->logfd, &msg, sizeof(struct knet_log_msg) - byte_cnt);
 		if (len <= 0) {
 			goto out_unlock;
 		}
 
 		byte_cnt += len;
 	}
 
 out_unlock:
 	/*
 	 * unlock only if we are holding the lock
 	 */
 	if (!err)
 		pthread_rwlock_unlock(&knet_h->global_rwlock);
 
 	return;
 }
diff --git a/libknet/netutils.c b/libknet/netutils.c
index fbd1f2cb..cd7b616a 100644
--- a/libknet/netutils.c
+++ b/libknet/netutils.c
@@ -1,167 +1,167 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netdb.h>
 #include <errno.h>
 #include <string.h>
 
 #include "internals.h"
 #include "netutils.h"
 
 static int is_v4_mapped(const struct sockaddr_storage *ss, socklen_t salen)
 {
 	char map[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
 	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) ss;
 	return memcmp(&addr6->sin6_addr, map, 12);
 }
 
 int cmpaddr(const struct sockaddr_storage *ss1, socklen_t sslen1,
 	    const struct sockaddr_storage *ss2, socklen_t sslen2)
 {
 	int ss1_offset = 0, ss2_offset = 0;
 	struct sockaddr_in6 *ss1_addr6 = (struct sockaddr_in6 *)ss1;
 	struct sockaddr_in6 *ss2_addr6 = (struct sockaddr_in6 *)ss2;
 	struct sockaddr_in *ss1_addr = (struct sockaddr_in *)ss1;
 	struct sockaddr_in *ss2_addr = (struct sockaddr_in *)ss2;
 	char *addr1, *addr2;
 
 	if (ss1->ss_family == ss2->ss_family) {
 		return memcmp(ss1, ss2, sslen1);
 	}
 
 	if (ss1->ss_family == AF_INET6) {
 		if (is_v4_mapped(ss1, sslen1)) {
 			return 1;
 		}
 		addr1 = (char *)&ss1_addr6->sin6_addr;
 		ss1_offset = 12;
 	} else {
 		addr1 = (char *)&ss1_addr->sin_addr;
 	}
 
 	if (ss2->ss_family == AF_INET6) {
 		if (is_v4_mapped(ss2, sslen2)) {
 			return 1;
 		}
 		addr2 = (char *)&ss2_addr6->sin6_addr;
 		ss2_offset = 12;
 	} else {
 		addr2 = (char *)&ss2_addr->sin_addr;
 	}
 
 	return memcmp(addr1+ss1_offset, addr2+ss2_offset, 4);
 }
 
 int cpyaddrport(struct sockaddr_storage *dst, const struct sockaddr_storage *src)
 {
 	struct sockaddr_in6 *dst_addr6 = (struct sockaddr_in6 *)dst;
 	struct sockaddr_in6 *src_addr6 = (struct sockaddr_in6 *)src;
 
 	memset(dst, 0, sizeof(struct sockaddr_storage));
 
 	if (src->ss_family == AF_INET6) {
 		dst->ss_family = src->ss_family;
 		memmove(&dst_addr6->sin6_port, &src_addr6->sin6_port, sizeof(in_port_t));
 		memmove(&dst_addr6->sin6_addr, &src_addr6->sin6_addr, sizeof(struct in6_addr));
 	} else {
 		memmove(dst, src, sizeof(struct sockaddr_in));
 	}
 	return 0;
 }
 
 socklen_t sockaddr_len(const struct sockaddr_storage *ss)
 {
         if (ss->ss_family == AF_INET) {
 	        return sizeof(struct sockaddr_in);
 	} else {
 	        return sizeof(struct sockaddr_in6);
 	}
 }
 
 /*
  * exported APIs
  */
 
 int knet_strtoaddr(const char *host, const char *port, struct sockaddr_storage *ss, socklen_t sslen)
 {
 	int err;
 	struct addrinfo hints;
 	struct addrinfo *result = NULL;
 
 	if (!host) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!port) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!ss) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!sslen) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	memset(&hints, 0, sizeof(struct addrinfo));
 
 	hints.ai_family = AF_UNSPEC;
 	hints.ai_socktype = SOCK_DGRAM;
 	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
 
 	err = getaddrinfo(host, port, &hints, &result);
 
 	if (!err) {
 		memmove(ss, result->ai_addr,
 			(sslen < result->ai_addrlen) ? sslen : result->ai_addrlen);
 
 		freeaddrinfo(result);
 	}
 
 	return err;
 }
 
 int knet_addrtostr(const struct sockaddr_storage *ss, socklen_t sslen,
 		   char *addr_buf, size_t addr_buf_size,
 		   char *port_buf, size_t port_buf_size)
 {
 	if (!ss) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!sslen) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!addr_buf) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (!port_buf) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	return getnameinfo((struct sockaddr *)ss, sockaddr_len(ss), addr_buf, addr_buf_size,
 				port_buf, port_buf_size,
 				NI_NUMERICHOST | NI_NUMERICSERV);
 }
diff --git a/libknet/netutils.h b/libknet/netutils.h
index 395fabb7..4522bb9d 100644
--- a/libknet/netutils.h
+++ b/libknet/netutils.h
@@ -1,19 +1,19 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_NETUTILS_H__
 #define __KNET_NETUTILS_H__
 
 #include <sys/socket.h>
 
 int cmpaddr(const struct sockaddr_storage *ss1, socklen_t sslen1, const struct sockaddr_storage *ss2, socklen_t sslen2);
 int cpyaddrport(struct sockaddr_storage *dst, const struct sockaddr_storage *src);
 
 socklen_t knet_sockaddr_len(const struct sockaddr_storage *ss);
 #endif
diff --git a/libknet/tests/api_knet_handle_add_datafd.c b/libknet/tests/api_knet_handle_add_datafd.c
index 14dd89ab..a9199cfe 100644
--- a/libknet/tests/api_knet_handle_add_datafd.c
+++ b/libknet/tests/api_knet_handle_add_datafd.c
@@ -1,224 +1,224 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	int datafd = 0, i;
 	int8_t channel = 0;
 	int datafdmax[KNET_DATAFD_MAX];
 	int8_t channels[KNET_DATAFD_MAX];
 
 	printf("Test knet_handle_add_datafd incorrect knet_h\n");
 
 	if ((!knet_handle_add_datafd(NULL, &datafd, &channel)) || (errno != EINVAL)) {
 		printf("knet_handle_add_datafd accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_add_datafd with no datafd\n");
 
 	if ((!knet_handle_add_datafd(knet_h, NULL, &channel)) || (errno != EINVAL)) {
 		printf("knet_handle_add_datafd accepted invalid datafd or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_add_datafd with no channel\n");
 
 	if ((!knet_handle_add_datafd(knet_h, &datafd, NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_add_datafd accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_add_datafd with invalid channel\n");
 
 	channel = KNET_DATAFD_MAX;
 
 	if ((!knet_handle_add_datafd(knet_h, &datafd, &channel)) || (errno != EINVAL)) {
 		printf("knet_handle_add_datafd accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_add_datafd with no socknotify\n");
 
 	datafd = 0;
 	channel = -1;
 
 	if ((!knet_handle_add_datafd(knet_h, &datafd, &channel)) || (errno != EINVAL)) {
 		printf("knet_handle_add_datafd accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_add_datafd with automatic config values\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	datafd = 0;
 	channel = -1;
 
 	if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
 		printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("got datafd: %d channel: %d\n", datafd, channel);
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_add_datafd with duplicated datafd\n");
 
 	if ((!knet_handle_add_datafd(knet_h, &datafd, &channel)) || (errno != EEXIST)) {
 		printf("knet_handle_add_datafd accepted duplicated datafd or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_add_datafd with busy channel\n");
 
 	datafd = datafd + 1;
 
 	if ((!knet_handle_add_datafd(knet_h, &datafd, &channel)) || (errno != EBUSY)) {
 		printf("knet_handle_add_datafd accepted duplicated datafd or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	datafd = datafd - 1;
 
 	if (knet_handle_remove_datafd(knet_h, datafd) < 0) {
 		printf("knet_handle_remove_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_add_datafd with no available channels\n");
 
 	for (i = 0; i < KNET_DATAFD_MAX; i++) {
 		datafdmax[i] = 0;
 		channels[i] = -1;
 		if (knet_handle_add_datafd(knet_h, &datafdmax[i], &channels[i]) < 0) {
 			printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 			knet_handle_free(knet_h);
 			flush_logs(logfds[0], stdout);
 			close_logpipes(logfds);
 			exit(FAIL);
 		}
 	}
 
 	datafd = 0;
 	channel = -1;
 
 	if ((!knet_handle_add_datafd(knet_h, &datafd, &channel)) || (errno != EBUSY)) {
 		printf("knet_handle_add_datafd accepted entry with no available channels or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	for (i = 0; i < KNET_DATAFD_MAX; i++) {
 		if (knet_handle_remove_datafd(knet_h, datafdmax[i]) < 0) {
 			printf("knet_handle_remove_datafd failed: %s\n", strerror(errno));
 			knet_handle_free(knet_h);
 			flush_logs(logfds[0], stdout);
 			close_logpipes(logfds);
 			exit(FAIL);
 		}
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_clear_stats.c b/libknet/tests/api_knet_handle_clear_stats.c
index 7a5e92b6..7166baa5 100644
--- a/libknet/tests/api_knet_handle_clear_stats.c
+++ b/libknet/tests/api_knet_handle_clear_stats.c
@@ -1,282 +1,282 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <inttypes.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "netutils.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	int datafd = 0;
 	int8_t channel = 0;
 	struct knet_link_status link_status;
 	char send_buff[KNET_MAX_PACKET_SIZE];
 	char recv_buff[KNET_MAX_PACKET_SIZE];
 	ssize_t send_len = 0;
 	int recv_len = 0;
 	int savederrno;
 	struct sockaddr_storage lo;
 
 	if (make_local_sockaddr(&lo, 0) < 0) {
 		printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	memset(send_buff, 0, sizeof(send_buff));
 
 	printf("Test knet_handle_clear_stats incorrect knet_h\n");
 
 	if (!knet_handle_clear_stats(NULL, 0) || (errno != EINVAL)) {
 		printf("knet_handle_clear_stats accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_send with valid data\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
         }
 
 	datafd = 0;
 	channel = -1;
 
 	if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
 		printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) {
 		printf("Unable to configure link: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) {
 		printf("knet_link_set_enable failed: %s\n", strerror(errno));
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_handle_setfwd(knet_h, 1) < 0) {
 		printf("knet_handle_setfwd failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	while(knet_h->host_index[1]->status.reachable != 1) {
 		printf("waiting host to be reachable\n");
 		sleep(1);
 	}
 
 	send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel);
 	if (send_len <= 0) {
 		printf("knet_send failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (send_len != sizeof(send_buff)) {
 		printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	sleep(1);
 
 	recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel);
 	savederrno = errno;
 	if (recv_len != send_len) {
 		printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno);
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) {
 			printf("helgrind exception. this is normal due to possible timeouts\n");
 			exit(PASS);
 		}
 		exit(FAIL);
 	}
 
 	if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) {
 		printf("recv and send buffers are different!\n");
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	/* A sanity check on the stats */
 	if (knet_link_get_status(knet_h, 1, 0, &link_status, sizeof(link_status)) < 0) {
 		printf("knet_link_get_status failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (link_status.stats.tx_data_packets != 2 ||
 	    link_status.stats.rx_data_packets != 2 ||
 	    link_status.stats.tx_data_bytes < KNET_MAX_PACKET_SIZE ||
 	    link_status.stats.rx_data_bytes < KNET_MAX_PACKET_SIZE ||
 	    link_status.stats.tx_data_bytes > KNET_MAX_PACKET_SIZE*2 ||
 	    link_status.stats.rx_data_bytes > KNET_MAX_PACKET_SIZE*2) {
 	    printf("stats look wrong: tx_packets: %" PRIu64 " (%" PRIu64 " bytes), rx_packets: %" PRIu64 " (%" PRIu64 " bytes)\n",
 		   link_status.stats.tx_data_packets,
 		   link_status.stats.tx_data_bytes,
 		   link_status.stats.rx_data_packets,
 		   link_status.stats.rx_data_bytes);
 	}
 
 	printf("Test knet_clear_stats (link)\n");
 	if (knet_handle_clear_stats(knet_h, KNET_CLEARSTATS_HANDLE_AND_LINK) < 0) {
 		printf("knet_link_clear_stats failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 
 /* Check they've been cleared */
 	if (knet_link_get_status(knet_h, 1, 0, &link_status, sizeof(link_status)) < 0) {
 		printf("knet_link_get_status failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (link_status.stats.tx_data_packets != 0 ||
 	    link_status.stats.rx_data_packets != 0 ||
 	    link_status.stats.tx_data_bytes != 0 ||
 	    link_status.stats.rx_data_bytes != 0 ||
 	    link_status.stats.tx_data_bytes != 0 ||
 	    link_status.stats.rx_data_bytes != 0) {
 		printf("stats not cleared: tx_packets: %" PRIu64 " (%" PRIu64 " bytes), rx_packets: %" PRIu64 " (%" PRIu64 " bytes)\n",
 		       link_status.stats.tx_data_packets,
 		       link_status.stats.tx_data_bytes,
 		       link_status.stats.rx_data_packets,
 		       link_status.stats.rx_data_bytes);
 
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_link_set_enable(knet_h, 1, 0, 0);
 	knet_link_clear_config(knet_h, 1, 0);
 	knet_host_remove(knet_h, 1);
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_enable_pmtud_notify.c b/libknet/tests/api_knet_handle_enable_pmtud_notify.c
index 1d458b7f..818c0541 100644
--- a/libknet/tests/api_knet_handle_enable_pmtud_notify.c
+++ b/libknet/tests/api_knet_handle_enable_pmtud_notify.c
@@ -1,149 +1,149 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void pmtud_notify(void *priv_data,
 			 unsigned int data_mtu)
 {
 	return;
 }
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	printf("Test knet_handle_enable_pmtud_notify incorrect knet_h\n");
 
 	if ((!knet_handle_enable_pmtud_notify(NULL, NULL, pmtud_notify)) || (errno != EINVAL)) {
 		printf("knet_handle_enable_pmtud_notify accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_enable_pmtud_notify with no private_data\n");
 
 	if (knet_handle_enable_pmtud_notify(knet_h, NULL, pmtud_notify) < 0) {
 		printf("knet_handle_enable_pmtud_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->pmtud_notify_fn_private_data != NULL) {
 		printf("knet_handle_enable_pmtud_notify failed to unset private_data");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_enable_pmtud_notify with private_data\n");
 
 	if (knet_handle_enable_pmtud_notify(knet_h, &private_data, NULL) < 0) {
 		printf("knet_handle_enable_pmtud_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->pmtud_notify_fn_private_data != &private_data) {
 		printf("knet_handle_enable_pmtud_notify failed to set private_data");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_enable_pmtud_notify with no pmtud_notify fn\n");
 
 	if (knet_handle_enable_pmtud_notify(knet_h, NULL, NULL) < 0) {
 		printf("knet_handle_enable_pmtud_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->pmtud_notify_fn != NULL) {
 		printf("knet_handle_enable_pmtud_notify failed to unset pmtud_notify fn");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_enable_pmtud_notify with pmtud_notify fn\n");
 
 	if (knet_handle_enable_pmtud_notify(knet_h, NULL, pmtud_notify) < 0) {
 		printf("knet_handle_enable_pmtud_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->pmtud_notify_fn != &pmtud_notify) {
 		printf("knet_handle_enable_pmtud_notify failed to set pmtud_notify fn");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_enable_sock_notify.c b/libknet/tests/api_knet_handle_enable_sock_notify.c
index 0c0b2efd..a545dcd1 100644
--- a/libknet/tests/api_knet_handle_enable_sock_notify.c
+++ b/libknet/tests/api_knet_handle_enable_sock_notify.c
@@ -1,144 +1,144 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	printf("Test knet_handle_enable_sock_notify incorrect knet_h\n");
 
 	if ((!knet_handle_enable_sock_notify(NULL, NULL, sock_notify)) || (errno != EINVAL)) {
 		printf("knet_handle_enable_sock_notify accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_enable_sock_notify with no private_data\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, NULL, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->sock_notify_fn_private_data != NULL) {
 		printf("knet_handle_enable_sock_notify failed to unset private_data");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_enable_sock_notify with private_data\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->sock_notify_fn_private_data != &private_data) {
 		printf("knet_handle_enable_sock_notify failed to set private_data");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_enable_sock_notify with no sock_notify fn\n");
 
 	if ((!knet_handle_enable_sock_notify(knet_h, NULL, NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_enable_sock_notify accepted invalid sock_notify or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_enable_sock_notify with sock_notify fn\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, NULL, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->sock_notify_fn != &sock_notify) {
 		printf("knet_handle_enable_sock_notify failed to set sock_notify fn");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_free.c b/libknet/tests/api_knet_handle_free.c
index 907dbb9a..54dfe552 100644
--- a/libknet/tests/api_knet_handle_free.c
+++ b/libknet/tests/api_knet_handle_free.c
@@ -1,90 +1,90 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 #include "internals.h"
 
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	setup_logpipes(logfds);
 
 	printf("Test knet_handle_free with invalid knet_h\n");
 
 	if ((!knet_handle_free(NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_free failed to detect invalid parameter\n");
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_free with one host configured\n");
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("Unable to add new knet_host: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_handle_free(knet_h)) || (errno != EBUSY)) {
 		printf("knet_handle_free didn't return error or correct errno with one host configured: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	if (knet_host_remove(knet_h, 1) < 0) {
 		printf("Unable to remove knet_host: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_handle_free(knet_h) < 0) {
 		printf("knet_handle_free failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_get_channel.c b/libknet/tests/api_knet_handle_get_channel.c
index 07770d21..8f6089c3 100644
--- a/libknet/tests/api_knet_handle_get_channel.c
+++ b/libknet/tests/api_knet_handle_get_channel.c
@@ -1,152 +1,152 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	int datafd = 0;
 	int8_t channel = 0, old_channel = 0;
 
 	printf("Test knet_handle_get_channel incorrect knet_h\n");
 
 	if ((!knet_handle_get_channel(NULL, datafd, &channel)) || (errno != EINVAL)) {
 		printf("knet_handle_get_channel accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_get_channel with invalid datafd\n");
 
 	datafd = 0;
 
 	if ((!knet_handle_get_channel(knet_h, datafd, &channel)) || (errno != EINVAL)) {
 		printf("knet_handle_get_channel accepted invalid datafd or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_channel with invalid channel\n");
 
 	datafd = 10;
 
 	if ((!knet_handle_get_channel(knet_h, datafd, NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_get_channel accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_channel with unconfigured datafd/channel\n");
 
 	datafd = 10;
 
 	if ((!knet_handle_get_channel(knet_h, datafd, &channel)) || (errno != EINVAL)) {
 		printf("knet_handle_get_channel accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_channel with valid datafd\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
         }
 
 	datafd = 0;
 	old_channel = -1;
 
 	if (knet_handle_add_datafd(knet_h, &datafd, &old_channel) < 0) {
 		printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_handle_get_channel(knet_h, datafd, &channel) < 0) {
 		printf("knet_handle_get_channel failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (old_channel != channel) {
 		printf("knet_handle_get_channel got incorrect channel\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_get_datafd.c b/libknet/tests/api_knet_handle_get_datafd.c
index 3e536269..674662d7 100644
--- a/libknet/tests/api_knet_handle_get_datafd.c
+++ b/libknet/tests/api_knet_handle_get_datafd.c
@@ -1,152 +1,152 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	int datafd = 0, old_datafd;
 	int8_t channel = 0;
 
 	printf("Test knet_handle_get_datafd incorrect knet_h\n");
 
 	if ((!knet_handle_get_datafd(NULL, channel, &datafd)) || (errno != EINVAL)) {
 		printf("knet_handle_get_datafd accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_get_datafd with invalid channel (< 0)\n");
 
 	channel = 0;
 
 	if ((!knet_handle_get_datafd(knet_h, channel, &datafd)) || (errno != EINVAL)) {
 		printf("knet_handle_get_datafd accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_datafd with invalid channel (KNET_DATAFD_MAX)\n");
 
 	channel = KNET_DATAFD_MAX;
 
 	if ((!knet_handle_get_datafd(knet_h, channel, &datafd)) || (errno != EINVAL)) {
 		printf("knet_handle_get_datafd accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_datafd with unconfigured datafd/channel\n");
 
 	channel = 10;
 
 	if ((!knet_handle_get_datafd(knet_h, channel, &datafd)) || (errno != EINVAL)) {
 		printf("knet_handle_get_datafd accepted unconfigured channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_datafd with valid datafd\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
         }
 
 	old_datafd = 0;
 	channel = -1;
 
 	if (knet_handle_add_datafd(knet_h, &old_datafd, &channel) < 0) {
 		printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_handle_get_datafd(knet_h, channel, &datafd) < 0) {
 		printf("knet_handle_get_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (old_datafd != datafd) {
 		printf("knet_handle_get_datafd got incorrect channel\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_get_stats.c b/libknet/tests/api_knet_handle_get_stats.c
index 9efbb649..8b455593 100644
--- a/libknet/tests/api_knet_handle_get_stats.c
+++ b/libknet/tests/api_knet_handle_get_stats.c
@@ -1,110 +1,110 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "link.h"
 #include "netutils.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	struct knet_handle_stats test_byte_array[2];
 	struct knet_handle_stats ref_byte_array[2];
 	struct knet_handle_stats stats;
 
 	printf("Test knet_handle_get_stats incorrect knet_h\n");
 
 	memset(&stats, 0, sizeof(struct knet_handle_stats));
 
 	if ((!knet_handle_get_stats(NULL, &stats, sizeof(struct knet_handle_stats))) || (errno != EINVAL)) {
 		printf("knet_handle_get_stats accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_get_stats with NULL structure pointer\n");
 
 	if ((!knet_handle_get_stats(knet_h, NULL, 0) || (errno != EINVAL))) {
 		printf("knet_handle_get_stats accepted invalid stats address or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_stats with small structure size\n");
 
 	memset(test_byte_array, 0x55, sizeof(struct knet_handle_stats) * 2);
 	memset(ref_byte_array, 0x55, sizeof(struct knet_handle_stats) * 2);
 	if (knet_handle_get_stats(knet_h, (struct knet_handle_stats *)test_byte_array, sizeof(size_t)) < 0) {
 		printf("knet_handle_get_stats failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (memcmp(&test_byte_array[1], ref_byte_array, sizeof(struct knet_handle_stats))) {
 		printf("knet_handle_get_stats corrupted memory after stats structure\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_stats with valid input\n");
 
 	if (knet_handle_get_stats(knet_h, &stats, sizeof(struct knet_handle_stats)) < 0) {
 		printf("knet_handle_get_stats failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_get_transport_id_by_name.c b/libknet/tests/api_knet_handle_get_transport_id_by_name.c
index a7ce4100..ef326873 100644
--- a/libknet/tests/api_knet_handle_get_transport_id_by_name.c
+++ b/libknet/tests/api_knet_handle_get_transport_id_by_name.c
@@ -1,95 +1,95 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	uint8_t id;
 
 	printf("Test knet_handle_get_transport_id_by_name with incorrect knet_h\n");
 
 	if ((knet_handle_get_transport_id_by_name(NULL, "UDP") != KNET_MAX_TRANSPORTS) || (errno != EINVAL)) {
 		printf("knet_handle_get_transport_id_by_name accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_get_transport_id_by_name with no name\n");
 
 	if ((knet_handle_get_transport_id_by_name(knet_h, NULL) != KNET_MAX_TRANSPORTS) || (errno != EINVAL)) {
 		printf("knet_handle_get_transport_id_by_name accepted invalid transport or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_transport_id_by_name with incorrect name\n");
 
 	if ((knet_handle_get_transport_id_by_name(knet_h, "ARP") != KNET_MAX_TRANSPORTS) || (errno != EINVAL)) {
 		printf("knet_handle_get_transport_id_by_name accepted invalid transport or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_transport_id_by_name with correct values\n");
 
 	id = knet_handle_get_transport_id_by_name(knet_h, "UDP");
 	if (id != KNET_TRANSPORT_UDP) {
 		printf("knet_handle_get_transport_id_by_name failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_get_transport_name_by_id.c b/libknet/tests/api_knet_handle_get_transport_name_by_id.c
index 2a02f05a..f315407b 100644
--- a/libknet/tests/api_knet_handle_get_transport_name_by_id.c
+++ b/libknet/tests/api_knet_handle_get_transport_name_by_id.c
@@ -1,91 +1,91 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	const char *name = NULL;
 
 	printf("Test knet_handle_get_transport_name_by_id with incorrect knet_h\n");
 
 	if ((knet_handle_get_transport_name_by_id(NULL, KNET_TRANSPORT_UDP) != NULL) || (errno != EINVAL)) {
 		printf("knet_handle_get_transport_name_by_id accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_get_transport_name_by_id with incorrect transport\n");
 
 	if ((knet_handle_get_transport_name_by_id(knet_h, KNET_MAX_TRANSPORTS) != NULL) || (errno != EINVAL)) {
 		printf("knet_handle_get_transport_name_by_id accepted invalid transport or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_transport_name_by_id with correct values\n");
 
 	name = knet_handle_get_transport_name_by_id(knet_h, KNET_TRANSPORT_UDP);
 	if (!name) {
 		printf("knet_handle_get_transport_name_by_id failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	if (strcmp(name, "UDP")) {
 		printf("knet_handle_get_transport_name_by_id failed to get UDP transport name\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_get_transport_reconnect_interval.c b/libknet/tests/api_knet_handle_get_transport_reconnect_interval.c
index a3acd1cb..b77ddad7 100644
--- a/libknet/tests/api_knet_handle_get_transport_reconnect_interval.c
+++ b/libknet/tests/api_knet_handle_get_transport_reconnect_interval.c
@@ -1,90 +1,90 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	uint32_t msecs = 0;
 
 	printf("Test knet_handle_get_transport_reconnect_interval with incorrect knet_h\n");
 
 	if ((!knet_handle_get_transport_reconnect_interval(NULL, &msecs)) || (errno != EINVAL)) {
 		printf("knet_handle_get_transport_reconnect_interval accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_get_transport_reconnect_interval with incorrect msecs\n");
 
 	if ((!knet_handle_get_transport_reconnect_interval(knet_h, NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_get_transport_reconnect_interval accepted invalid msecs or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_get_transport_reconnect_interval with correct values\n");
 
 	if (knet_handle_get_transport_reconnect_interval(knet_h, &msecs) < 0) {
 		printf("knet_handle_get_transport_reconnect_interval failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	if (msecs != KNET_TRANSPORT_DEFAULT_RECONNECT_INTERVAL) {
 		printf("knet_handle_get_transport_reconnect_interval failed to set correct value\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_pmtud_get.c b/libknet/tests/api_knet_handle_pmtud_get.c
index b2172400..bb476e0c 100644
--- a/libknet/tests/api_knet_handle_pmtud_get.c
+++ b/libknet/tests/api_knet_handle_pmtud_get.c
@@ -1,87 +1,87 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	unsigned int data_mtu;
 
 	printf("Test knet_handle_pmtud_get incorrect knet_h\n");
 
 	if ((!knet_handle_pmtud_get(NULL, &data_mtu)) || (errno != EINVAL)) {
 		printf("knet_handle_pmtud_get accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_pmtud_get with no data_mtu\n");
 	if ((!knet_handle_pmtud_get(knet_h, NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_pmtud_get accepted invalid data_mtu or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	if (knet_handle_pmtud_get(knet_h, &data_mtu) < 0) {
 		printf("knet_handle_pmtud_get failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->data_mtu != data_mtu) {
 		printf("knet_handle_pmtud_get failed to set the value\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_pmtud_getfreq.c b/libknet/tests/api_knet_handle_pmtud_getfreq.c
index 7c018eb9..2fa4d64a 100644
--- a/libknet/tests/api_knet_handle_pmtud_getfreq.c
+++ b/libknet/tests/api_knet_handle_pmtud_getfreq.c
@@ -1,87 +1,87 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	unsigned int interval;
 
 	printf("Test knet_handle_pmtud_getfreq incorrect knet_h\n");
 
 	if ((!knet_handle_pmtud_getfreq(NULL, &interval)) || (errno != EINVAL)) {
 		printf("knet_handle_pmtud_getfreq accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_pmtud_getfreq with no interval\n");
 	if ((!knet_handle_pmtud_getfreq(knet_h, NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_pmtud_getfreq accepted invalid interval or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	if (knet_handle_pmtud_getfreq(knet_h, &interval) < 0) {
 		printf("knet_handle_pmtud_getfreq failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->pmtud_interval != interval) {
 		printf("knet_handle_pmtud_getfreq failed to set the value\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_pmtud_setfreq.c b/libknet/tests/api_knet_handle_pmtud_setfreq.c
index ac3fc86d..759c4f13 100644
--- a/libknet/tests/api_knet_handle_pmtud_setfreq.c
+++ b/libknet/tests/api_knet_handle_pmtud_setfreq.c
@@ -1,98 +1,98 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	printf("Test knet_handle_pmtud_setfreq incorrect knet_h\n");
 
 	if ((!knet_handle_pmtud_setfreq(NULL, 1)) || (errno != EINVAL)) {
 		printf("knet_handle_pmtud_setfreq accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_pmtud_setfreq with 0 (incorrect)\n");
 	if ((!knet_handle_pmtud_setfreq(NULL, 0)) || (errno != EINVAL)) {
 		printf("knet_handle_pmtud_setfreq accepted invalid PTMUd freq or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_pmtud_setfreq with 86401 (incorrect)\n");
 	if ((!knet_handle_pmtud_setfreq(NULL, 86401)) || (errno != EINVAL)) {
 		printf("knet_handle_pmtud_setfreq accepted invalid PTMUd freq or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_pmtud_setfreq with 1 (correct)\n");
 	if (knet_handle_pmtud_setfreq(knet_h, 1) < 0) {
 		printf("knet_handle_pmtud_setfreq failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->pmtud_interval != 1) {
 		printf("knet_handle_pmtud_setfreq failed to set the value\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_remove_datafd.c b/libknet/tests/api_knet_handle_remove_datafd.c
index 1461852c..51285c6b 100644
--- a/libknet/tests/api_knet_handle_remove_datafd.c
+++ b/libknet/tests/api_knet_handle_remove_datafd.c
@@ -1,130 +1,130 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	int datafd = 0;
 	int8_t channel = 0;
 
 	printf("Test knet_handle_remove_datafd incorrect knet_h\n");
 
 	if ((!knet_handle_remove_datafd(NULL, datafd)) || (errno != EINVAL)) {
 		printf("knet_handle_remove_datafd accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_remove_datafd with no datafd\n");
 
 	datafd = 0;
 
 	if ((!knet_handle_remove_datafd(knet_h, datafd)) || (errno != EINVAL)) {
 		printf("knet_handle_remove_datafd accepted invalid datafd or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_remove_datafd with invalid datafd\n");
 
 	datafd = 10;
 
 	if ((!knet_handle_remove_datafd(knet_h, datafd)) || (errno != EINVAL)) {
 		printf("knet_handle_remove_datafd accepted invalid channel or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_remove_datafd with valid datafd\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
         }
 
 	datafd = 0;
 	channel = -1;
 
 	if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
 		printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_handle_remove_datafd(knet_h, datafd) < 0) {
 		printf("knet_handle_remove_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_set_transport_reconnect_interval.c b/libknet/tests/api_knet_handle_set_transport_reconnect_interval.c
index 563e88f0..e5296f24 100644
--- a/libknet/tests/api_knet_handle_set_transport_reconnect_interval.c
+++ b/libknet/tests/api_knet_handle_set_transport_reconnect_interval.c
@@ -1,89 +1,89 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	printf("Test knet_handle_set_transport_reconnect_interval with incorrect knet_h\n");
 
 	if ((!knet_handle_set_transport_reconnect_interval(NULL, 1000)) || (errno != EINVAL)) {
 		printf("knet_handle_set_transport_reconnect_interval accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_handle_set_transport_reconnect_interval with incorrect msecs\n");
 
 	if ((!knet_handle_set_transport_reconnect_interval(knet_h, 0)) || (errno != EINVAL)) {
 		printf("knet_handle_set_transport_reconnect_interval accepted invalid msecs or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_set_transport_reconnect_interval with correct values\n");
 
 	if (knet_handle_set_transport_reconnect_interval(knet_h, 2000) < 0) {
 		printf("knet_handle_set_transport_reconnect_interval failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	if (knet_h->reconnect_int != 2000) {
 		printf("knet_handle_set_transport_reconnect_interval failed to set correct value\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_handle_setfwd.c b/libknet/tests/api_knet_handle_setfwd.c
index 438461cc..f0a177ee 100644
--- a/libknet/tests/api_knet_handle_setfwd.c
+++ b/libknet/tests/api_knet_handle_setfwd.c
@@ -1,109 +1,109 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 #include "internals.h"
 
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	printf("Test knet_handle_setfwd with invalid knet_h\n");
 
 	if ((!knet_handle_setfwd(NULL, 0)) || (errno != EINVAL)) {
 		printf("knet_handle_setfwd accepted invalid knet_h parameter\n");
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	printf("Test knet_handle_setfwd with invalid param (2) \n");
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_handle_setfwd(knet_h, 2)) || (errno != EINVAL)) {
 		printf("knet_handle_setfwd accepted invalid param for enabled: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_setfwd with valid param (1) \n");
 
 	if (knet_handle_setfwd(knet_h, 1) < 0) {
 		printf("knet_handle_setfwd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->enabled != 1) {
 		printf("knet_handle_setfwd failed to set correct value");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_setfwd with valid param (0) \n");
 
 	if (knet_handle_setfwd(knet_h, 0) < 0) {
 		printf("knet_handle_setfwd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->enabled != 0) {
 		printf("knet_handle_setfwd failed to set correct value");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_host_get_name_by_host_id.c b/libknet/tests/api_knet_host_get_name_by_host_id.c
index 03c93fa2..4988a962 100644
--- a/libknet/tests/api_knet_host_get_name_by_host_id.c
+++ b/libknet/tests/api_knet_host_get_name_by_host_id.c
@@ -1,109 +1,109 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	char name[KNET_MAX_HOST_LEN];
 
 	printf("Test knet_host_get_name_by_host_id incorrect knet_h\n");
 
 	if ((!knet_host_get_name_by_host_id(NULL, 1, name)) || (errno != EINVAL)) {
 		printf("knet_host_get_name_by_host_id accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_name_by_host_id with incorrect hostid 1\n");
 
 	if ((!knet_host_get_name_by_host_id(knet_h, 1, name)) || (errno != EINVAL)) {
 		printf("knet_host_get_name_by_host_id accepted invalid host_id or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_name_by_host_id with incorrect name\n");
 
 	if ((!knet_host_get_name_by_host_id(knet_h, 1, NULL)) || (errno != EINVAL)) {
 		printf("knet_host_get_name_by_host_id accepted invalid name or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_name_by_host_id with correct values for hostid 1: ");
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_get_name_by_host_id(knet_h, 1, name) < 0) {
 		printf("knet_host_get_name_by_host_id faild to retrive name: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("%s\n", name);
 
 	flush_logs(logfds[0], stdout);
 
 	knet_host_remove(knet_h, 1);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_host_get_policy.c b/libknet/tests/api_knet_host_get_policy.c
index 6a7f5cda..0e9f6d1e 100644
--- a/libknet/tests/api_knet_host_get_policy.c
+++ b/libknet/tests/api_knet_host_get_policy.c
@@ -1,125 +1,125 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	uint8_t policy;
 
 	printf("Test knet_host_get_policy incorrect knet_h\n");
 
 	if ((!knet_host_get_policy(NULL, 1, &policy)) || (errno != EINVAL)) {
 		printf("knet_host_get_policy accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_policy incorrect host_id\n");
 
 	if ((!knet_host_get_policy(knet_h, 1, &policy)) || (errno != EINVAL)) {
 		printf("knet_host_get_policy accepted invalid host_id or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_policy incorrect policy\n");
 
 	if ((!knet_host_get_policy(knet_h, 1, NULL)) || (errno != EINVAL)) {
 		printf("knet_host_get_policy accepted invalid policy or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_policy correct policy\n");
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_set_policy(knet_h, 1, KNET_LINK_POLICY_RR) < 0) {
 		printf("knet_host_set_policy failed to set RR policy for host 1: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_get_policy(knet_h, 1, &policy) < 0) {
 		printf("knet_host_get_policy failed for host 1: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (policy != KNET_LINK_POLICY_RR) {
 		printf("knet_host_get_policy policy for host 1 does not appear to be correct\n");
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_host_remove(knet_h, 1);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_host_get_status.c b/libknet/tests/api_knet_host_get_status.c
index f9b8ddd5..3c88ec97 100644
--- a/libknet/tests/api_knet_host_get_status.c
+++ b/libknet/tests/api_knet_host_get_status.c
@@ -1,108 +1,108 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "host.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	struct knet_host_status status;
 
 	printf("Test knet_host_get_status incorrect knet_h\n");
 
 	memset(&status, 0, sizeof(struct knet_host_status));
 
 	if ((!knet_host_get_status(NULL, 1, &status)) || (errno != EINVAL)) {
 		printf("knet_host_get_status accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_host_get_status with unconfigured host_id\n");
 
 	if ((!knet_host_get_status(knet_h, 1, &status)) || (errno != EINVAL)) {
 		printf("knet_host_get_status accepted invalid host_id or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_status with incorrect status\n");
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_host_get_status(knet_h, 1, NULL)) || (errno != EINVAL)) {
 		printf("knet_host_get_status accepted invalid status or returned incorrect error: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_get_status with correct values\n");
 
 	if (knet_host_get_status(knet_h, 1, &status) < 0) {
 		printf("knet_host_get_status failed: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_host_remove(knet_h, 1);
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_host_set_name.c b/libknet/tests/api_knet_host_set_name.c
index ffbde350..c21eda3f 100644
--- a/libknet/tests/api_knet_host_set_name.c
+++ b/libknet/tests/api_knet_host_set_name.c
@@ -1,179 +1,179 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	char longhostname[KNET_MAX_HOST_LEN+2];
 
 	printf("Test knet_host_set_name incorrect knet_h\n");
 
 	if ((!knet_host_set_name(NULL, 1, "test")) || (errno != EINVAL)) {
 		printf("knet_host_set_name accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_name with incorrect hostid 1\n");
 
 	if ((!knet_host_set_name(knet_h, 2, "test")) || (errno != EINVAL)) {
 		printf("knet_host_set_name accepted invalid host_id or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_name with correct values\n");
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_set_name(knet_h, 1, "test") < 0) {
 		printf("knet_host_set_name failed: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (strcmp("test", knet_h->host_index[1]->name)) {
 		printf("knet_host_set_name failed to copy name\n");
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_name with correct values (name change)\n");
 
 	if (knet_host_set_name(knet_h, 1, "tes") < 0) {
 		printf("knet_host_set_name failed: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (strcmp("tes", knet_h->host_index[1]->name)) {
 		printf("knet_host_set_name failed to change name\n");
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_name with NULL name\n");
 
 	if ((!knet_host_set_name(knet_h, 1, NULL)) || (errno != EINVAL)) {
 		printf("knet_host_set_name accepted invalid name or returned incorrect error: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_name with duplicate name\n");
 
 	if (knet_host_add(knet_h, 2) < 0) {
 		printf("knet_host_add failed error: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_host_set_name(knet_h, 2, "tes")) || (errno != EEXIST)) {
 		printf("knet_host_set_name accepted duplicated name or returned incorrect error: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 2);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_host_remove(knet_h, 2);
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_name with (too) long name\n");
 
 	memset(longhostname, 'a', sizeof(longhostname));
 	longhostname[KNET_MAX_HOST_LEN] = '\0';
 
 	if ((!knet_host_set_name(knet_h, 1, longhostname)) || (errno != EINVAL)) {
 		printf("knet_host_set_name accepted invalid (too long) name or returned incorrect error: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_host_remove(knet_h, 1);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_host_set_policy.c b/libknet/tests/api_knet_host_set_policy.c
index f1d0ccf7..e7e481cf 100644
--- a/libknet/tests/api_knet_host_set_policy.c
+++ b/libknet/tests/api_knet_host_set_policy.c
@@ -1,115 +1,115 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	printf("Test knet_host_set_policy incorrect knet_h\n");
 
 	if ((!knet_host_set_policy(NULL, 1, KNET_LINK_POLICY_PASSIVE)) || (errno != EINVAL)) {
 		printf("knet_host_set_policy accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_policy incorrect host_id\n");
 
 	if ((!knet_host_set_policy(knet_h, 1, KNET_LINK_POLICY_PASSIVE)) || (errno != EINVAL)) {
 		printf("knet_host_set_policy accepted invalid host_id or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_policy incorrect policy\n");
 
 	if ((!knet_host_set_policy(knet_h, 1, KNET_LINK_POLICY_RR + 1)) || (errno != EINVAL)) {
 		printf("knet_host_set_policy accepted invalid policy or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_host_set_policy correct policy\n");
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_set_policy(knet_h, 1, KNET_LINK_POLICY_RR) < 0) {
 		printf("knet_host_set_policy failed to set RR policy for host 1: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->host_index[1]->link_handler_policy != KNET_LINK_POLICY_RR) {
 		printf("knet_host_set_policy failed to set RR policy for host 1: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	knet_host_remove(knet_h, 1);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_link_clear_config.c b/libknet/tests/api_knet_link_clear_config.c
index ab413f0c..f56de055 100644
--- a/libknet/tests/api_knet_link_clear_config.c
+++ b/libknet/tests/api_knet_link_clear_config.c
@@ -1,174 +1,174 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "link.h"
 #include "netutils.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	struct sockaddr_storage src, dst;
 
 	if (make_local_sockaddr(&src, 0) < 0) {
 		printf("Unable to convert src to sockaddr: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	if (make_local_sockaddr(&dst, 1) < 0) {
 		printf("Unable to convert dst to sockaddr: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	printf("Test knet_link_clear_config incorrect knet_h\n");
 
 	if ((!knet_link_clear_config(NULL, 1, 0)) || (errno != EINVAL)) {
 		printf("knet_link_clear_config accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	printf("Test knet_link_clear_config with unconfigured host_id\n");
 
 	if ((!knet_link_clear_config(knet_h, 1, 0)) || (errno != EINVAL)) {
 		printf("knet_link_clear_config accepted invalid host_id or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_link_clear_config with incorrect linkid\n");
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("Unable to add host_id 1: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_link_clear_config(knet_h, 1, KNET_MAX_LINK)) || (errno != EINVAL)) {
 		printf("knet_link_clear_config accepted invalid linkid or returned incorrect error: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_link_clear_config with unconfigured linkid\n");
 
 	if ((!knet_link_clear_config(knet_h, 1, 0)) || (errno != EINVAL)) {
 		printf("knet_link_clear_config accepted unconfigured linkid or returned incorrect error: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_link_clear_config with enabled linkid\n");
 
 	if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &src, &dst, 0) < 0) {
 		printf("Unable to configure link: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) {
 		printf("Unable to enable link: %s\n", strerror(errno));
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_link_clear_config(knet_h, 1, 0) || (errno != EBUSY))) {
 		printf("knet_link_clear_config accepted invalid enabled link or returned incorrect error: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_link_clear_config with correct data\n");
 
 	if (knet_link_set_enable(knet_h, 1, 0, 0) < 0) {
 		printf("Unable to disable link: %s\n", strerror(errno));
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_clear_config(knet_h, 1, 0) < 0) {
 		printf("Unable to clear link config: %s\n", strerror(errno));
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_link_clear_config(knet_h, 1, 0);
 	knet_host_remove(knet_h, 1);
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_log_get_loglevel.c b/libknet/tests/api_knet_log_get_loglevel.c
index 60023a39..02bdc0af 100644
--- a/libknet/tests/api_knet_log_get_loglevel.c
+++ b/libknet/tests/api_knet_log_get_loglevel.c
@@ -1,102 +1,102 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 
 #include "libknet.h"
 #include "internals.h"
 
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	uint8_t level;
 	int logfds[2];
 
 	printf("Test knet_log_get_loglevel incorrect knet_h\n");
 
 	if ((!knet_log_get_loglevel(NULL, KNET_SUB_UNKNOWN, &level)) || (errno != EINVAL)) {
 		printf("knet_log_get_loglevel accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	printf("Test knet_log_get_loglevel incorrect subsystem\n");
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_INFO);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_log_get_loglevel(knet_h, KNET_SUB_UNKNOWN - 1, &level)) || (errno != EINVAL)) {
 		printf("knet_log_get_loglevel accepted invalid subsystem or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_log_get_loglevel incorrect log level\n");
 
 	if ((!knet_log_get_loglevel(knet_h, KNET_SUB_UNKNOWN, NULL)) || (errno != EINVAL)) {
 		printf("knet_log_get_loglevel accepted invalid log level or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_log_get_loglevel with valid parameters\n");
 
 	if (knet_log_get_loglevel(knet_h, KNET_SUB_UNKNOWN, &level ) < 0) {
 		printf("knet_log_get_loglevel failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->log_levels[KNET_SUB_UNKNOWN] != level) {
 		printf("knet_log_get_loglevel failed to get the right value\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_log_get_loglevel_name.c b/libknet/tests/api_knet_log_get_loglevel_name.c
index 6fe2a3d4..ce888102 100644
--- a/libknet/tests/api_knet_log_get_loglevel_name.c
+++ b/libknet/tests/api_knet_log_get_loglevel_name.c
@@ -1,47 +1,47 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "test-common.h"
 
 static void test(void)
 {
 	const char *res;
 
 	printf("Testing knet_log_get_loglevel_name normal lookup\n");
 	res = knet_log_get_loglevel_name(KNET_LOG_DEBUG);
 	if (strcmp(res, "debug")) {
 		printf("knet_log_get_loglevel_name failed to get correct log level name. got: %s expected: debug\n",
 		       res);
 		exit(FAIL);
 	}
 
 	printf("Testing knet_log_get_loglevel_name bad lookup\n");
 	res = knet_log_get_loglevel_name(KNET_LOG_DEBUG+1);
 	if (strcmp(res, "ERROR")) {
 		printf("knet_log_get_loglevel_name failed to get correct log level name. got: %s expected: ERROR\n",
 		       res);
 		exit(FAIL);
 	}
 }
 
 int main(int argc, char *argv[])
 {
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_log_get_subsystem_name.c b/libknet/tests/api_knet_log_get_subsystem_name.c
index 307feadf..dcbea12d 100644
--- a/libknet/tests/api_knet_log_get_subsystem_name.c
+++ b/libknet/tests/api_knet_log_get_subsystem_name.c
@@ -1,55 +1,55 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "test-common.h"
 
 static void test(void)
 {
 	const char *res;
 
 	printf("Testing knet_log_get_subsystem_name normal lookup\n");
 	res = knet_log_get_subsystem_name(KNET_SUB_NSSCRYPTO);
 	if (strcmp(res, "nsscrypto")) {
 		printf("knet_log_get_subsystem_name failed to get correct log subsystem name. got: %s expected: nsscrypto\n",
 		       res);
 		exit(FAIL);
 	}
 
 	printf("Testing knet_log_get_subsystem_name bad lookup (within boundaries)\n");
 	res = knet_log_get_subsystem_name(KNET_SUB_UNKNOWN - 1);
 	if (strcmp(res, "unknown")) {
 		printf("knet_log_get_subsystem_name failed to get correct log subsystem name. got: %s expected: common\n",
 		       res);
 		exit(FAIL);
 	}
 
 	printf("Testing knet_log_get_subsystem_name bad lookup (outside boundaries)\n");
 	res = knet_log_get_subsystem_name(KNET_MAX_SUBSYSTEMS);
 	if (strcmp(res, "unknown")) {
 		printf("knet_log_get_subsystem_name failed to get correct log subsystem name. got: %s expected: common\n",
 		       res);
 		exit(FAIL);
 	}
 }
 
 int main(int argc, char *argv[])
 {
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_log_set_loglevel.c b/libknet/tests/api_knet_log_set_loglevel.c
index cb5970d6..1eb32225 100644
--- a/libknet/tests/api_knet_log_set_loglevel.c
+++ b/libknet/tests/api_knet_log_set_loglevel.c
@@ -1,109 +1,109 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 
 #include "libknet.h"
 #include "internals.h"
 
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 
 	printf("Test knet_log_set_loglevel incorrect knet_h\n");
 
 	if ((!knet_log_set_loglevel(NULL, KNET_SUB_COMMON, KNET_LOG_DEBUG)) || (errno != EINVAL)) {
 		printf("knet_log_set_loglevel accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	printf("Test knet_log_set_loglevel incorrect subsystem\n");
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_INFO);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if ((!knet_log_set_loglevel(knet_h, KNET_SUB_UNKNOWN - 1, KNET_LOG_DEBUG)) || (errno != EINVAL)) {
 		printf("knet_log_set_loglevel accepted invalid subsystem or returned incorrect error: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		knet_handle_free(knet_h);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_log_set_loglevel incorrect log level\n");
 
 	if ((!knet_log_set_loglevel(knet_h, KNET_SUB_UNKNOWN, KNET_LOG_DEBUG + 1)) || (errno != EINVAL)) {
 		printf("knet_log_set_loglevel accepted invalid log level or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_log_set_loglevel with valid parameters\n");
 
 	if (knet_h->log_levels[KNET_SUB_UNKNOWN] != KNET_LOG_INFO) {
 		printf("knet_handle_new did not init log_levels correctly?\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_log_set_loglevel(knet_h, KNET_SUB_UNKNOWN, KNET_LOG_DEBUG) < 0) {
 		printf("knet_log_set_loglevel failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_h->log_levels[KNET_SUB_UNKNOWN] != KNET_LOG_DEBUG) {
 		printf("knet_log_set_loglevel did not set log level correctly\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_send_compress.c b/libknet/tests/api_knet_send_compress.c
index 23572507..71bd7d9a 100644
--- a/libknet/tests/api_knet_send_compress.c
+++ b/libknet/tests/api_knet_send_compress.c
@@ -1,277 +1,277 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <inttypes.h>
 
 #include "libknet.h"
 
 #include "compress.h"
 #include "internals.h"
 #include "netutils.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static void test(const char *model)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	int datafd = 0;
 	int8_t channel = 0;
 	struct knet_handle_stats stats;
 	char send_buff[KNET_MAX_PACKET_SIZE];
 	char recv_buff[KNET_MAX_PACKET_SIZE];
 	ssize_t send_len = 0;
 	int recv_len = 0;
 	int savederrno;
 	struct sockaddr_storage lo;
 	struct knet_handle_compress_cfg knet_handle_compress_cfg;
 
 	if (make_local_sockaddr(&lo, 0) < 0) {
 		printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	memset(send_buff, 0, sizeof(send_buff));
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_send with %s and valid data\n", model);
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 	strncpy(knet_handle_compress_cfg.compress_model, model, sizeof(knet_handle_compress_cfg.compress_model) - 1);
 	knet_handle_compress_cfg.compress_level = 4;
 	knet_handle_compress_cfg.compress_threshold = 0;
 
 	if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) < 0) {
 		printf("knet_handle_compress did not accept zlib compress mode with compress level 1 cfg\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
         }
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
         }
 
 	datafd = 0;
 	channel = -1;
 
 	if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
 		printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) {
 		printf("Unable to configure link: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) {
 		printf("knet_link_set_enable failed: %s\n", strerror(errno));
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_handle_setfwd(knet_h, 1) < 0) {
 		printf("knet_handle_setfwd failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	while(knet_h->host_index[1]->status.reachable != 1) {
 		printf("waiting host to be reachable\n");
 		sleep(1);
 	}
 
 	send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel);
 	if (send_len <= 0) {
 		printf("knet_send failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (send_len != sizeof(send_buff)) {
 		printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	sleep(1);
 
 	recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel);
 	savederrno = errno;
 	if (recv_len != send_len) {
 		printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno);
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) {
 			printf("helgrind exception. this is normal due to possible timeouts\n");
 			exit(PASS);
 		}
 		exit(FAIL);
 	}
 
 	if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) {
 		printf("recv and send buffers are different!\n");
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	/* A sanity check on the stats */
 	if (knet_handle_get_stats(knet_h, &stats, sizeof(stats)) < 0) {
 		printf("knet_handle_get_stats failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (strcmp(model, "none") == 0) {
 		if (stats.tx_compressed_packets != 0 ||
 		    stats.rx_compressed_packets != 0) {
 
 			printf("stats look wrong: s/b all 0 for model 'none' tx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp), rx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp)\n",
 			       stats.tx_compressed_packets,
 			       stats.tx_compressed_size_bytes,
 			       stats.tx_compressed_original_bytes,
 			       stats.rx_compressed_packets,
 			       stats.rx_compressed_size_bytes,
 			       stats.rx_compressed_original_bytes);
 		}
 	} else {
 		if (stats.tx_compressed_packets != 1 ||
 		    stats.rx_compressed_packets != 1 ||
 		    stats.tx_compressed_original_bytes < stats.tx_compressed_size_bytes ||
 		    stats.tx_compressed_original_bytes < stats.tx_compressed_size_bytes) {
 			printf("stats look wrong: tx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp), rx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp)\n",
 			       stats.tx_compressed_packets,
 			       stats.tx_compressed_size_bytes,
 			       stats.tx_compressed_original_bytes,
 			       stats.rx_compressed_packets,
 			       stats.rx_compressed_size_bytes,
 			       stats.rx_compressed_original_bytes);
 
 		}
 	}
 	flush_logs(logfds[0], stdout);
 
 	knet_link_set_enable(knet_h, 1, 0, 0);
 	knet_link_clear_config(knet_h, 1, 0);
 	knet_host_remove(knet_h, 1);
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test("none");
 
 #ifdef BUILDCOMPZLIB
 	test("zlib");
 #endif
 #ifdef BUILDCOMPLZ4
 	test("lz4");
 	test("lz4hc");
 #endif
 #ifdef BUILDCOMPLZO2
 	test("lzo2");
 #endif
 #ifdef BUILDCOMPLZMA
 	test("lzma");
 #endif
 #ifdef BUILDCOMPBZIP2
 	test("bzip2");
 #endif
 
 	return PASS;
 }
diff --git a/libknet/tests/api_knet_send_loopback.c b/libknet/tests/api_knet_send_loopback.c
index f9028364..77c5589f 100644
--- a/libknet/tests/api_knet_send_loopback.c
+++ b/libknet/tests/api_knet_send_loopback.c
@@ -1,384 +1,384 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <inttypes.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "netutils.h"
 #include "test-common.h"
 
 static int private_data;
 
 static void sock_notify(void *pvt_data,
 			int datafd,
 			int8_t channel,
 			uint8_t tx_rx,
 			int error,
 			int errorno)
 {
 	return;
 }
 
 static int dhost_filter(void *pvt_data,
 			const unsigned char *outdata,
 			ssize_t outdata_len,
 			uint8_t tx_rx,
 			knet_node_id_t this_host_id,
 			knet_node_id_t src_host_id,
 			int8_t *dst_channel,
 			knet_node_id_t *dst_host_ids,
 			size_t *dst_host_ids_entries)
 {
 	dst_host_ids[0] = 1;
 	*dst_host_ids_entries = 1;
 
 	return 0;
 }
 
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	int datafd = 0;
 	int8_t channel = 0;
 	struct knet_link_status link_status;
 	char send_buff[KNET_MAX_PACKET_SIZE];
 	char recv_buff[KNET_MAX_PACKET_SIZE];
 	ssize_t send_len = 0;
 	int recv_len = 0;
 	int savederrno;
 	struct sockaddr_storage lo;
 
 	if (make_local_sockaddr(&lo, 1) < 0) {
 		printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 	memset(send_buff, 0, sizeof(send_buff));
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
 
 	if (!knet_h) {
 		printf("knet_handle_new failed: %s\n", strerror(errno));
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test configuring multiple links with loopback\n");
 
 	if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
 		printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
         }
 
 	datafd = 0;
 	channel = -1;
 
 	if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
 		printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_host_add(knet_h, 1) < 0) {
 		printf("knet_host_add failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) < 0) {
 		printf("Unable to configure link: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_config(knet_h, 1, 1, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) == 0) {
 		printf("Managed to configure two LOOPBACK links - this is wrong\n");
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 	printf("Test configuring UDP link after loopback\n");
 
 	if (knet_link_set_config(knet_h, 1, 1, KNET_TRANSPORT_UDP, &lo, &lo, 0) == 0) {
 		printf("Managed to configure UDP and LOOPBACK links together: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 	printf("Test configuring UDP link before loopback\n");
 
 	if (knet_link_clear_config(knet_h, 1, 0) < 0) {
 		printf("Failed to clear existing LOOPBACK link: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) {
 		printf("Failed to configure UDP link for testing: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_config(knet_h, 1, 1, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) == 0) {
 		printf("Managed to configure LOOPBACK link after UDP: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 	printf("Test knet_send with valid data\n");
 
 	if (knet_link_clear_config(knet_h, 1, 0) < 0) {
 		printf("Failed to clear existing UDP link: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_LOOPBACK, &lo, &lo, 0) < 0) {
 		printf("Failed configure LOOPBACK link for sending: %s\n", strerror(errno));
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) {
 		printf("knet_link_set_enable failed: %s\n", strerror(errno));
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (knet_handle_setfwd(knet_h, 1) < 0) {
 		printf("knet_handle_setfwd failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	while(knet_h->host_index[1]->status.reachable != 1) {
 		printf("waiting host to be reachable\n");
 		sleep(1);
 	}
 
 	send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel);
 	if (send_len <= 0) {
 		printf("knet_send failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (send_len != sizeof(send_buff)) {
 		printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	sleep(1);
 
 	recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel);
 	savederrno = errno;
 	if (recv_len != send_len) {
 		printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno);
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) {
 			printf("helgrind exception. this is normal due to possible timeouts\n");
 			exit(PASS);
 		}
 		exit(FAIL);
 	}
 
 	if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) {
 		printf("recv and send buffers are different!\n");
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	/* A sanity check on the stats */
 	if (knet_link_get_status(knet_h, 1, 0, &link_status, sizeof(link_status)) < 0) {
 		printf("knet_link_get_status failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (link_status.stats.tx_data_packets != 1 ||
 	    link_status.stats.rx_data_packets != 0 ||
 	    link_status.stats.tx_data_bytes != KNET_MAX_PACKET_SIZE) {
 	    printf("stats look wrong: tx_packets: %" PRIu64 " (%" PRIu64 " bytes), rx_packets: %" PRIu64 " (%" PRIu64 " bytes)\n",
 		   link_status.stats.tx_data_packets,
 		   link_status.stats.tx_data_bytes,
 		   link_status.stats.rx_data_packets,
 		   link_status.stats.rx_data_bytes);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 
 	printf("Test knet_send with only localhost\n");
 
 	if (knet_handle_enable_filter(knet_h, NULL, dhost_filter) < 0) {
 		printf("knet_handle_enable_filter failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 	send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel);
 	if (send_len <= 0) {
 		printf("knet_send failed: %s\n", strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	if (send_len != sizeof(send_buff)) {
 		printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno));
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	sleep(1);
 
 	recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel);
 	savederrno = errno;
 	if (recv_len != send_len) {
 		printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno);
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) {
 			printf("helgrind exception. this is normal due to possible timeouts\n");
 			exit(PASS);
 		}
 		exit(FAIL);
 	}
 
 	if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) {
 		printf("recv and send buffers are different!\n");
 		knet_link_set_enable(knet_h, 1, 0, 0);
 		knet_link_clear_config(knet_h, 1, 0);
 		knet_host_remove(knet_h, 1);
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	knet_link_set_enable(knet_h, 1, 0, 0);
 	knet_link_clear_config(knet_h, 1, 0);
 	knet_host_remove(knet_h, 1);
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	need_root();
 
 	test();
 
 	return PASS;
 }
diff --git a/libknet/tests/int_timediff.c b/libknet/tests/int_timediff.c
index 16048bba..1e0ae9bd 100644
--- a/libknet/tests/int_timediff.c
+++ b/libknet/tests/int_timediff.c
@@ -1,60 +1,60 @@
 /*
- * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <stdio.h>
 #include <time.h>
 #include <stdlib.h>
 #include <pthread.h>
 
 #include "threads_common.h"
 
 #include "test-common.h"
 
 #define timespec_set(x, sec, nsec) \
 do { \
 	x.tv_sec = sec; \
 	x.tv_nsec = nsec; \
 } while (0);
 
 static void check_timespec_diff(void)
 {
 	unsigned long long diff;
 	struct timespec start, end;
 
 	timespec_set(start, 1, 30000);
 
 	timespec_set(end, start.tv_sec, start.tv_nsec + 10000);
 	timespec_diff(start, end, &diff);
 
 	printf("Checking 10000 == %llu\n", diff);
 
 	if (diff != 10000) {
 		printf("Failure!\n");
 		exit(FAIL);
 	}
 
 	timespec_set(end, start.tv_sec + 5, start.tv_nsec - 5000);
 	timespec_diff(start, end, &diff);
 
 	printf("Checking 4999995000 == %llu\n", diff);
 
 	if (diff != 4999995000llu) {
 		printf("Failure!\n");
 		exit(FAIL);
 	}
 }
 
 int main(int argc, char *argv[])
 {
 	check_timespec_diff();
 
 	return PASS;
 }
diff --git a/libknet/threads_common.c b/libknet/threads_common.c
index 8afe1aa2..f40d68b5 100644
--- a/libknet/threads_common.c
+++ b/libknet/threads_common.c
@@ -1,38 +1,38 @@
 /*
- * Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <pthread.h>
 #include <errno.h>
 #include <string.h>
 
 #include "internals.h"
 #include "logging.h"
 #include "threads_common.h"
 
 int shutdown_in_progress(knet_handle_t knet_h)
 {
 	int savederrno = 0;
 	int ret;
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_COMMON, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	ret = knet_h->fini_in_progress;
 
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 
 	return ret;
 }
diff --git a/libknet/threads_common.h b/libknet/threads_common.h
index 2b617957..348fa05c 100644
--- a/libknet/threads_common.h
+++ b/libknet/threads_common.h
@@ -1,28 +1,28 @@
 /*
- * Copyright (C) 2015-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_THREADS_COMMON_H__
 #define __KNET_THREADS_COMMON_H__
 
 #include "internals.h"
 
 #define KNET_THREADS_TIMERES 200000
 
 #define timespec_diff(start, end, diff) \
 do { \
 	if (end.tv_sec > start.tv_sec) \
 		*(diff) = ((end.tv_sec - start.tv_sec) * 1000000000llu) \
 					+ end.tv_nsec - start.tv_nsec; \
 	else \
 		*(diff) = end.tv_nsec - start.tv_nsec; \
 } while (0);
 
 int shutdown_in_progress(knet_handle_t knet_h);
 
 #endif
diff --git a/libknet/threads_dsthandler.h b/libknet/threads_dsthandler.h
index 45de4784..4c59f51a 100644
--- a/libknet/threads_dsthandler.h
+++ b/libknet/threads_dsthandler.h
@@ -1,15 +1,15 @@
 /*
- * Copyright (C) 2015-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_THREADS_DSTHANDLER_H__
 #define __KNET_THREADS_DSTHANDLER_H__
 
 void *_handle_dst_link_handler_thread(void *data);
 
 #endif
diff --git a/libknet/threads_heartbeat.h b/libknet/threads_heartbeat.h
index 92c5cb80..88668844 100644
--- a/libknet/threads_heartbeat.h
+++ b/libknet/threads_heartbeat.h
@@ -1,16 +1,16 @@
 /*
- * Copyright (C) 2015-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_THREADS_HEARTBEAT_H__
 #define __KNET_THREADS_HEARTBEAT_H__
 
 void _send_pings(knet_handle_t knet_h, int timed);
 void *_handle_heartbt_thread(void *data);
 
 #endif
diff --git a/libknet/threads_pmtud.h b/libknet/threads_pmtud.h
index 4f8bf1e8..3c7fd16d 100644
--- a/libknet/threads_pmtud.h
+++ b/libknet/threads_pmtud.h
@@ -1,15 +1,15 @@
 /*
- * Copyright (C) 2015-2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_THREADS_PMTUD_H__
 #define __KNET_THREADS_PMTUD_H__
 
 void *_handle_pmtud_link_thread(void *data);
 
 #endif
diff --git a/libknet/threads_rx.c b/libknet/threads_rx.c
index 3761c151..12d6a171 100644
--- a/libknet/threads_rx.c
+++ b/libknet/threads_rx.c
@@ -1,820 +1,820 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/uio.h>
 #include <pthread.h>
 
 #include "compat.h"
 #include "compress.h"
 #include "crypto.h"
 #include "host.h"
 #include "links.h"
 #include "logging.h"
 #include "transports.h"
 #include "threads_common.h"
 #include "threads_heartbeat.h"
 #include "threads_rx.h"
 #include "netutils.h"
 
 /*
  * RECV
  */
 
 /*
  *  return 1 if a > b
  *  return -1 if b > a
  *  return 0 if they are equal
  */
 static inline int timecmp(struct timespec a, struct timespec b)
 {
 	if (a.tv_sec != b.tv_sec) {
 		if (a.tv_sec > b.tv_sec) {
 			return 1;
 		} else {
 			return -1;
 		}
 	} else {
 		if (a.tv_nsec > b.tv_nsec) {
 			return 1;
 		} else if (a.tv_nsec < b.tv_nsec) {
 			return -1;
 		} else {
 			return 0;
 		}
 	}
 }
 
 /*
  * this functions needs to return an index (0 to 7)
  * to a knet_host_defrag_buf. (-1 on errors)
  */
 
 static int find_pckt_defrag_buf(knet_handle_t knet_h, struct knet_header *inbuf)
 {
 	struct knet_host *src_host = knet_h->host_index[inbuf->kh_node];
 	int i, oldest;
 
 	/*
 	 * check if there is a buffer already in use handling the same seq_num
 	 */
 	for (i = 0; i < KNET_MAX_LINK; i++) {
 		if (src_host->defrag_buf[i].in_use) {
 			if (src_host->defrag_buf[i].pckt_seq == inbuf->khp_data_seq_num) {
 				return i;
 			}
 		}
 	}
 
 	/*
 	 * If there is no buffer that's handling the current seq_num
 	 * either it's new or it's been reclaimed already.
 	 * check if it's been reclaimed/seen before using the defrag circular
 	 * buffer. If the pckt has been seen before, the buffer expired (ETIME)
 	 * and there is no point to try to defrag it again.
 	 */
 	if (!_seq_num_lookup(src_host, inbuf->khp_data_seq_num, 1, 0)) {
 		errno = ETIME;
 		return -1;
 	}
 
 	/*
 	 * register the pckt as seen
 	 */
 	_seq_num_set(src_host, inbuf->khp_data_seq_num, 1);
 
 	/*
 	 * see if there is a free buffer
 	 */
 	for (i = 0; i < KNET_MAX_LINK; i++) {
 		if (!src_host->defrag_buf[i].in_use) {
 			return i;
 		}
 	}
 
 	/*
 	 * at this point, there are no free buffers, the pckt is new
 	 * and we need to reclaim a buffer, and we will take the one
 	 * with the oldest timestamp. It's as good as any.
 	 */
 
 	oldest = 0;
 
 	for (i = 0; i < KNET_MAX_LINK; i++) {
 		if (timecmp(src_host->defrag_buf[i].last_update, src_host->defrag_buf[oldest].last_update) < 0) {
 			oldest = i;
 		}
 	}
 	src_host->defrag_buf[oldest].in_use = 0;
 	return oldest;
 }
 
 static int pckt_defrag(knet_handle_t knet_h, struct knet_header *inbuf, ssize_t *len)
 {
 	struct knet_host_defrag_buf *defrag_buf;
 	int defrag_buf_idx;
 
 	defrag_buf_idx = find_pckt_defrag_buf(knet_h, inbuf);
 	if (defrag_buf_idx < 0) {
 		if (errno == ETIME) {
 			log_debug(knet_h, KNET_SUB_RX, "Defrag buffer expired");
 		}
 		return 1;
 	}
 
 	defrag_buf = &knet_h->host_index[inbuf->kh_node]->defrag_buf[defrag_buf_idx];
 
 	/*
 	 * if the buf is not is use, then make sure it's clean
 	 */
 	if (!defrag_buf->in_use) {
 		memset(defrag_buf, 0, sizeof(struct knet_host_defrag_buf));
 		defrag_buf->in_use = 1;
 		defrag_buf->pckt_seq = inbuf->khp_data_seq_num;
 	}
 
 	/*
 	 * update timestamp on the buffer
 	 */
 	clock_gettime(CLOCK_MONOTONIC, &defrag_buf->last_update);
 
 	/*
 	 * check if we already received this fragment
 	 */
 	if (defrag_buf->frag_map[inbuf->khp_data_frag_seq]) {
 		/*
 		 * if we have received this fragment and we didn't clear the buffer
 		 * it means that we don't have all fragments yet
 		 */
 		return 1;
 	}
 
 	/*
 	 *  we need to handle the last packet with gloves due to its different size
 	 */
 
 	if (inbuf->khp_data_frag_seq == inbuf->khp_data_frag_num) {
 		defrag_buf->last_frag_size = *len;
 
 		/*
 		 * in the event when the last packet arrives first,
 		 * we still don't know the offset vs the other fragments (based on MTU),
 		 * so we store the fragment at the end of the buffer where it's safe
 		 * and take a copy of the len so that we can restore its offset later.
 		 * remember we can't use the local MTU for this calculation because pMTU
 		 * can be asymettric between the same hosts.
 		 */
 		if (!defrag_buf->frag_size) {
 			defrag_buf->last_first = 1;
 			memmove(defrag_buf->buf + (KNET_MAX_PACKET_SIZE - *len),
 			       inbuf->khp_data_userdata,
 			       *len);
 		}
 	} else {
 		defrag_buf->frag_size = *len;
 	}
 
 	memmove(defrag_buf->buf + ((inbuf->khp_data_frag_seq - 1) * defrag_buf->frag_size),
 	       inbuf->khp_data_userdata, *len);
 
 	defrag_buf->frag_recv++;
 	defrag_buf->frag_map[inbuf->khp_data_frag_seq] = 1;
 
 	/*
 	 * check if we received all the fragments
 	 */
 	if (defrag_buf->frag_recv == inbuf->khp_data_frag_num) {
 		/*
 		 * special case the last pckt
 		 */
 
 		if (defrag_buf->last_first) {
 			memmove(defrag_buf->buf + ((inbuf->khp_data_frag_num - 1) * defrag_buf->frag_size),
 			        defrag_buf->buf + (KNET_MAX_PACKET_SIZE - defrag_buf->last_frag_size),
 				defrag_buf->last_frag_size);
 		}
 
 		/*
 		 * recalculate packet lenght
 		 */
 
 		*len = ((inbuf->khp_data_frag_num - 1) * defrag_buf->frag_size) + defrag_buf->last_frag_size;
 
 		/*
 		 * copy the pckt back in the user data
 		 */
 		memmove(inbuf->khp_data_userdata, defrag_buf->buf, *len);
 
 		/*
 		 * free this buffer
 		 */
 		defrag_buf->in_use = 0;
 		return 0;
 	}
 
 	return 1;
 }
 
 static void _parse_recv_from_links(knet_handle_t knet_h, int sockfd, const struct knet_mmsghdr *msg)
 {
 	int err = 0, savederrno = 0;
 	ssize_t outlen;
 	struct knet_host *src_host;
 	struct knet_link *src_link;
 	unsigned long long latency_last;
 	knet_node_id_t dst_host_ids[KNET_MAX_HOST];
 	size_t dst_host_ids_entries = 0;
 	int bcast = 1;
 	struct timespec recvtime;
 	struct knet_header *inbuf = msg->msg_hdr.msg_iov->iov_base;
 	unsigned char *outbuf = (unsigned char *)msg->msg_hdr.msg_iov->iov_base;
 	ssize_t len = msg->msg_len;
 	struct knet_hostinfo *knet_hostinfo;
 	struct iovec iov_out[1];
 	int8_t channel;
 	struct sockaddr_storage pckt_src;
 	seq_num_t recv_seq_num;
 	int wipe_bufs = 0;
 
 	if (knet_h->crypto_instance) {
 		struct timespec start_time;
 		struct timespec end_time;
 		uint64_t crypt_time;
 
 		clock_gettime(CLOCK_MONOTONIC, &start_time);
 		if (crypto_authenticate_and_decrypt(knet_h,
 						    (unsigned char *)inbuf,
 						    len,
 						    knet_h->recv_from_links_buf_decrypt,
 						    &outlen) < 0) {
 			log_debug(knet_h, KNET_SUB_RX, "Unable to decrypt/auth packet");
 			return;
 		}
 		clock_gettime(CLOCK_MONOTONIC, &end_time);
 		timespec_diff(start_time, end_time, &crypt_time);
 
 		if (crypt_time < knet_h->stats.rx_crypt_time_min) {
 			knet_h->stats.rx_crypt_time_min = crypt_time;
 		}
 		if (crypt_time > knet_h->stats.rx_crypt_time_max) {
 			knet_h->stats.rx_crypt_time_max = crypt_time;
 		}
 		knet_h->stats.rx_crypt_time_ave =
 			(knet_h->stats.rx_crypt_time_ave * knet_h->stats.rx_crypt_packets +
 			 crypt_time) / (knet_h->stats.rx_crypt_packets+1);
 		knet_h->stats.rx_crypt_packets++;
 
 		len = outlen;
 		inbuf = (struct knet_header *)knet_h->recv_from_links_buf_decrypt;
 	}
 
 	if (len < (ssize_t)(KNET_HEADER_SIZE + 1)) {
 		log_debug(knet_h, KNET_SUB_RX, "Packet is too short: %ld", (long)len);
 		return;
 	}
 
 	if (inbuf->kh_version != KNET_HEADER_VERSION) {
 		log_debug(knet_h, KNET_SUB_RX, "Packet version does not match");
 		return;
 	}
 
 	inbuf->kh_node = ntohs(inbuf->kh_node);
 	src_host = knet_h->host_index[inbuf->kh_node];
 	if (src_host == NULL) {  /* host not found */
 		log_debug(knet_h, KNET_SUB_RX, "Unable to find source host for this packet");
 		return;
 	}
 
 	src_link = NULL;
 
 	src_link = src_host->link +
 		(inbuf->khp_ping_link % KNET_MAX_LINK);
 	if ((inbuf->kh_type & KNET_HEADER_TYPE_PMSK) != 0) {
 		if (src_link->dynamic == KNET_LINK_DYNIP) {
 			/*
 			 * cpyaddrport will only copy address and port of the incoming
 			 * packet and strip extra bits such as flow and scopeid
 			 */
 			cpyaddrport(&pckt_src, msg->msg_hdr.msg_name);
 
 			if (cmpaddr(&src_link->dst_addr, sockaddr_len(&src_link->dst_addr),
 				    &pckt_src, sockaddr_len(&pckt_src)) != 0) {
 				log_debug(knet_h, KNET_SUB_RX, "host: %u link: %u appears to have changed ip address",
 					  src_host->host_id, src_link->link_id);
 				memmove(&src_link->dst_addr, &pckt_src, sizeof(struct sockaddr_storage));
 				if (knet_addrtostr(&src_link->dst_addr, sockaddr_len(msg->msg_hdr.msg_name),
 						src_link->status.dst_ipaddr, KNET_MAX_HOST_LEN,
 						src_link->status.dst_port, KNET_MAX_PORT_LEN) != 0) {
 					log_debug(knet_h, KNET_SUB_RX, "Unable to resolve ???");
 					snprintf(src_link->status.dst_ipaddr, KNET_MAX_HOST_LEN - 1, "Unknown!!!");
 					snprintf(src_link->status.dst_port, KNET_MAX_PORT_LEN - 1, "??");
 				} else {
 					log_info(knet_h, KNET_SUB_RX,
 						 "host: %u link: %u new connection established from: %s %s",
 						 src_host->host_id, src_link->link_id,
 						 src_link->status.dst_ipaddr, src_link->status.dst_port);
 				}
 			}
 			/*
 			 * transport has already accepted the connection here
 			 * otherwise we would not be receiving packets
 			 */
 			knet_h->transport_ops[src_link->transport_type]->transport_link_dyn_connect(knet_h, sockfd, src_link);
 		}
 	}
 
 	switch (inbuf->kh_type) {
 	case KNET_HEADER_TYPE_HOST_INFO:
 	case KNET_HEADER_TYPE_DATA:
 		/*
 		 * TODO: should we accept data even if we can't reply to the other node?
 		 *       how would that work with SCTP and guaranteed delivery?
 		 */
 
 		if (!src_host->status.reachable) {
 			log_debug(knet_h, KNET_SUB_RX, "Source host %u not reachable yet", src_host->host_id);
 			//return;
 		}
 		inbuf->khp_data_seq_num = ntohs(inbuf->khp_data_seq_num);
 		channel = inbuf->khp_data_channel;
 		src_host->got_data = 1;
 
 		if (src_link) {
 			src_link->status.stats.rx_data_packets++;
 			src_link->status.stats.rx_data_bytes += len;
 		}
 
 		if (!_seq_num_lookup(src_host, inbuf->khp_data_seq_num, 0, 0)) {
 			if (src_host->link_handler_policy != KNET_LINK_POLICY_ACTIVE) {
 				log_debug(knet_h, KNET_SUB_RX, "Packet has already been delivered");
 			}
 			return;
 		}
 
 		if (inbuf->khp_data_frag_num > 1) {
 			/*
 			 * len as received from the socket also includes extra stuff
 			 * that the defrag code doesn't care about. So strip it
 			 * here and readd only for repadding once we are done
 			 * defragging
 			 */
 			len = len - KNET_HEADER_DATA_SIZE;
 			if (pckt_defrag(knet_h, inbuf, &len)) {
 				return;
 			}
 			len = len + KNET_HEADER_DATA_SIZE;
 		}
 
 		if (inbuf->khp_data_compress) {
 			ssize_t decmp_outlen = KNET_DATABUFSIZE_COMPRESS;
 			struct timespec start_time;
 			struct timespec end_time;
 			uint64_t compress_time;
 
 			clock_gettime(CLOCK_MONOTONIC, &start_time);
 			err = decompress(knet_h, inbuf->khp_data_compress,
 					 (const unsigned char *)inbuf->khp_data_userdata,
 					 len - KNET_HEADER_DATA_SIZE,
 					 knet_h->recv_from_links_buf_decompress,
 					 &decmp_outlen);
 			if (!err) {
 				/* Collect stats */
 				clock_gettime(CLOCK_MONOTONIC, &end_time);
 				timespec_diff(start_time, end_time, &compress_time);
 
 				if (compress_time < knet_h->stats.rx_compress_time_min) {
 					knet_h->stats.rx_compress_time_min = compress_time;
 				}
 				if (compress_time > knet_h->stats.rx_compress_time_max) {
 					knet_h->stats.rx_compress_time_max = compress_time;
 				}
 				knet_h->stats.rx_compress_time_ave =
 					(knet_h->stats.rx_compress_time_ave * knet_h->stats.rx_compressed_packets +
 					 compress_time) / (knet_h->stats.rx_compressed_packets+1);
 
 				knet_h->stats.rx_compressed_packets++;
 				knet_h->stats.rx_compressed_original_bytes += decmp_outlen;
 				knet_h->stats.rx_compressed_size_bytes += len - KNET_HEADER_SIZE;
 
 				memmove(inbuf->khp_data_userdata, knet_h->recv_from_links_buf_decompress, decmp_outlen);
 				len = decmp_outlen + KNET_HEADER_DATA_SIZE;
 			} else {
 				log_warn(knet_h, KNET_SUB_COMPRESS, "Unable to decompress packet (%d): %s",
 					 err, strerror(errno));
 				return;
 			}
 		}
 
 		if (inbuf->kh_type == KNET_HEADER_TYPE_DATA) {
 			if (knet_h->enabled != 1) /* data forward is disabled */
 				break;
 
 			if (knet_h->dst_host_filter_fn) {
 				size_t host_idx;
 				int found = 0;
 
 				bcast = knet_h->dst_host_filter_fn(
 						knet_h->dst_host_filter_fn_private_data,
 						(const unsigned char *)inbuf->khp_data_userdata,
 						len - KNET_HEADER_DATA_SIZE,
 						KNET_NOTIFY_RX,
 						knet_h->host_id,
 						inbuf->kh_node,
 						&channel,
 						dst_host_ids,
 						&dst_host_ids_entries);
 				if (bcast < 0) {
 					log_debug(knet_h, KNET_SUB_RX, "Error from dst_host_filter_fn: %d", bcast);
 					return;
 				}
 
 				if ((!bcast) && (!dst_host_ids_entries)) {
 					log_debug(knet_h, KNET_SUB_RX, "Message is unicast but no dst_host_ids_entries");
 					return;
 				}
 
 				/* check if we are dst for this packet */
 				if (!bcast) {
 					for (host_idx = 0; host_idx < dst_host_ids_entries; host_idx++) {
 						if (dst_host_ids[host_idx] == knet_h->host_id) {
 							found = 1;
 							break;
 						}
 					}
 					if (!found) {
 						log_debug(knet_h, KNET_SUB_RX, "Packet is not for us");
 						return;
 					}
 				}
 			}
 		}
 
 		if (inbuf->kh_type == KNET_HEADER_TYPE_DATA) {
 			if (!knet_h->sockfd[channel].in_use) {
 				log_debug(knet_h, KNET_SUB_RX,
 					  "received packet for channel %d but there is no local sock connected",
 					  channel);
 				return;
 			}
 
 			memset(iov_out, 0, sizeof(iov_out));
 			iov_out[0].iov_base = (void *) inbuf->khp_data_userdata;
 			iov_out[0].iov_len = len - KNET_HEADER_DATA_SIZE;
 
 			outlen = writev(knet_h->sockfd[channel].sockfd[knet_h->sockfd[channel].is_created], iov_out, 1);
 			if (outlen <= 0) {
 				knet_h->sock_notify_fn(knet_h->sock_notify_fn_private_data,
 						       knet_h->sockfd[channel].sockfd[0],
 						       channel,
 						       KNET_NOTIFY_RX,
 						       outlen,
 						       errno);
 				return;
 			}
 			if ((size_t)outlen == iov_out[0].iov_len) {
 				_seq_num_set(src_host, inbuf->khp_data_seq_num, 0);
 			}
 		} else { /* HOSTINFO */
 			knet_hostinfo = (struct knet_hostinfo *)inbuf->khp_data_userdata;
 			if (knet_hostinfo->khi_bcast == KNET_HOSTINFO_UCAST) {
 				bcast = 0;
 				knet_hostinfo->khi_dst_node_id = ntohs(knet_hostinfo->khi_dst_node_id);
 			}
 			if (!_seq_num_lookup(src_host, inbuf->khp_data_seq_num, 0, 0)) {
 				return;
 			}
 			_seq_num_set(src_host, inbuf->khp_data_seq_num, 0);
 			switch(knet_hostinfo->khi_type) {
 				case KNET_HOSTINFO_TYPE_LINK_UP_DOWN:
 					break;
 				case KNET_HOSTINFO_TYPE_LINK_TABLE:
 					break;
 				default:
 					log_warn(knet_h, KNET_SUB_RX, "Receiving unknown host info message from host %u", src_host->host_id);
 					break;
 			}
 		}
 		break;
 	case KNET_HEADER_TYPE_PING:
 		outlen = KNET_HEADER_PING_SIZE;
 		inbuf->kh_type = KNET_HEADER_TYPE_PONG;
 		inbuf->kh_node = htons(knet_h->host_id);
 		recv_seq_num = ntohs(inbuf->khp_ping_seq_num);
 		src_link->status.stats.rx_ping_packets++;
 		src_link->status.stats.rx_ping_bytes += len;
 
 		wipe_bufs = 0;
 
 		if (!inbuf->khp_ping_timed) {
 			/*
 			 * we might be receiving this message from all links, but we want
 			 * to process it only the first time
 			 */
 			if (recv_seq_num != src_host->untimed_rx_seq_num) {
 				/*
 				 * cache the untimed seq num
 				 */
 				src_host->untimed_rx_seq_num = recv_seq_num;
 				/*
 				 * if the host has received data in between
 				 * untimed ping, then we don't need to wipe the bufs
 				 */
 				if (src_host->got_data) {
 					src_host->got_data = 0;
 					wipe_bufs = 0;
 				} else {
 					wipe_bufs = 1;
 				}
 			}
 			_seq_num_lookup(src_host, recv_seq_num, 0, wipe_bufs);
 		} else {
 			/*
 			 * pings always arrives in bursts over all the link
 			 * catch the first of them to cache the seq num and
 			 * avoid duplicate processing
 			 */
 			if (recv_seq_num != src_host->timed_rx_seq_num) {
 				src_host->timed_rx_seq_num = recv_seq_num;
 
 				if (recv_seq_num == 0) {
 					_seq_num_lookup(src_host, recv_seq_num, 0, 1);
 				}
 			}
 		}
 
 		if (knet_h->crypto_instance) {
 			if (crypto_encrypt_and_sign(knet_h,
 						    (const unsigned char *)inbuf,
 						    len,
 						    knet_h->recv_from_links_buf_crypt,
 						    &outlen) < 0) {
 				log_debug(knet_h, KNET_SUB_RX, "Unable to encrypt pong packet");
 				break;
 			}
 			outbuf = knet_h->recv_from_links_buf_crypt;
 		}
 
 retry_pong:
 		len = sendto(src_link->outsock, outbuf, outlen, MSG_DONTWAIT | MSG_NOSIGNAL,
 				(struct sockaddr *) &src_link->dst_addr,
 				sizeof(struct sockaddr_storage));
 		savederrno = errno;
 		if (len != outlen) {
 			err = knet_h->transport_ops[src_link->transport_type]->transport_tx_sock_error(knet_h, src_link->outsock, len, savederrno);
 			switch(err) {
 				case -1: /* unrecoverable error */
 					log_debug(knet_h, KNET_SUB_RX,
 						  "Unable to send pong reply (sock: %d) packet (sendto): %d %s. recorded src ip: %s src port: %s dst ip: %s dst port: %s",
 						  src_link->outsock, errno, strerror(errno),
 						  src_link->status.src_ipaddr, src_link->status.src_port,
 						  src_link->status.dst_ipaddr, src_link->status.dst_port);
 					src_link->status.stats.tx_pong_errors++;
 					break;
 				case 0: /* ignore error and continue */
 					break;
 				case 1: /* retry to send those same data */
 					src_link->status.stats.tx_pong_retries++;
 					goto retry_pong;
 					break;
 			}
 		}
 		src_link->status.stats.tx_pong_packets++;
 		src_link->status.stats.tx_pong_bytes += outlen;
 		break;
 	case KNET_HEADER_TYPE_PONG:
 		src_link->status.stats.rx_pong_packets++;
 		src_link->status.stats.rx_pong_bytes += len;
 		clock_gettime(CLOCK_MONOTONIC, &src_link->status.pong_last);
 
 		memmove(&recvtime, &inbuf->khp_ping_time[0], sizeof(struct timespec));
 		timespec_diff(recvtime,
 				src_link->status.pong_last, &latency_last);
 
 		src_link->status.latency =
 			((src_link->status.latency * src_link->latency_exp) +
 			((latency_last / 1000llu) *
 				(src_link->latency_fix - src_link->latency_exp))) /
 					src_link->latency_fix;
 
 		if (src_link->status.latency < src_link->pong_timeout) {
 			if (!src_link->status.connected) {
 				if (src_link->received_pong >= src_link->pong_count) {
 					log_info(knet_h, KNET_SUB_RX, "host: %u link: %u is up",
 						 src_host->host_id, src_link->link_id);
 					_link_updown(knet_h, src_host->host_id, src_link->link_id, src_link->status.enabled, 1);
 				} else {
 					src_link->received_pong++;
 					log_debug(knet_h, KNET_SUB_RX, "host: %u link: %u received pong: %u",
 						  src_host->host_id, src_link->link_id, src_link->received_pong);
 				}
 			}
 		}
 		/* Calculate latency stats */
 		if (src_link->status.latency > src_link->status.stats.latency_max) {
 			src_link->status.stats.latency_max = src_link->status.latency;
 		}
 		if (src_link->status.latency < src_link->status.stats.latency_min) {
 			src_link->status.stats.latency_min = src_link->status.latency;
 		}
 		src_link->status.stats.latency_ave =
 			(src_link->status.stats.latency_ave * src_link->status.stats.latency_samples +
 			 src_link->status.latency) / (src_link->status.stats.latency_samples+1);
 		src_link->status.stats.latency_samples++;
 
 		break;
 	case KNET_HEADER_TYPE_PMTUD:
 		src_link->status.stats.rx_pmtu_packets++;
 		src_link->status.stats.rx_pmtu_bytes += len;
 		outlen = KNET_HEADER_PMTUD_SIZE;
 		inbuf->kh_type = KNET_HEADER_TYPE_PMTUD_REPLY;
 		inbuf->kh_node = htons(knet_h->host_id);
 
 		if (knet_h->crypto_instance) {
 			if (crypto_encrypt_and_sign(knet_h,
 						    (const unsigned char *)inbuf,
 						    len,
 						    knet_h->recv_from_links_buf_crypt,
 						    &outlen) < 0) {
 				log_debug(knet_h, KNET_SUB_RX, "Unable to encrypt PMTUd reply packet");
 				break;
 			}
 			outbuf = knet_h->recv_from_links_buf_crypt;
 		}
 
 retry_pmtud:
 		len = sendto(src_link->outsock, outbuf, outlen, MSG_DONTWAIT | MSG_NOSIGNAL,
 				(struct sockaddr *) &src_link->dst_addr,
 				sizeof(struct sockaddr_storage));
 		if (len != outlen) {
 			err = knet_h->transport_ops[src_link->transport_type]->transport_tx_sock_error(knet_h, src_link->outsock, len, savederrno);
 			switch(err) {
 				case -1: /* unrecoverable error */
 					log_debug(knet_h, KNET_SUB_RX,
 						  "Unable to send PMTUd reply (sock: %d) packet (sendto): %d %s. recorded src ip: %s src port: %s dst ip: %s dst port: %s",
 						  src_link->outsock, errno, strerror(errno),
 						  src_link->status.src_ipaddr, src_link->status.src_port,
 						  src_link->status.dst_ipaddr, src_link->status.dst_port);
 
 					src_link->status.stats.tx_pmtu_errors++;
 					break;
 				case 0: /* ignore error and continue */
 					src_link->status.stats.tx_pmtu_errors++;
 					break;
 				case 1: /* retry to send those same data */
 					src_link->status.stats.tx_pmtu_retries++;
 					goto retry_pmtud;
 					break;
 			}
 		}
 
 		break;
 	case KNET_HEADER_TYPE_PMTUD_REPLY:
 		src_link->status.stats.rx_pmtu_packets++;
 		src_link->status.stats.rx_pmtu_bytes += len;
 		if (pthread_mutex_lock(&knet_h->pmtud_mutex) != 0) {
 			log_debug(knet_h, KNET_SUB_RX, "Unable to get mutex lock");
 			break;
 		}
 		src_link->last_recv_mtu = inbuf->khp_pmtud_size;
 		pthread_cond_signal(&knet_h->pmtud_cond);
 		pthread_mutex_unlock(&knet_h->pmtud_mutex);
 		break;
 	default:
 		return;
 	}
 }
 
 static void _handle_recv_from_links(knet_handle_t knet_h, int sockfd, struct knet_mmsghdr *msg)
 {
 	int err, savederrno;
 	int i, msg_recv, transport;
 
 	if (pthread_rwlock_rdlock(&knet_h->global_rwlock) != 0) {
 		log_debug(knet_h, KNET_SUB_RX, "Unable to get global read lock");
 		return;
 	}
 
 	if (_is_valid_fd(knet_h, sockfd) < 1) {
 		/*
 		 * this is normal if a fd got an event and before we grab the read lock
 		 * and the link is removed by another thread
 		 */
 		goto exit_unlock;
 	}
 
 	transport = knet_h->knet_transport_fd_tracker[sockfd].transport;
 
 	/*
 	 * reset msg_namelen to buffer size because after recvmmsg
 	 * each msg_namelen will contain sizeof sockaddr_in or sockaddr_in6
 	 */
 
 	for (i = 0; i < PCKT_RX_BUFS; i++) {
 		msg[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
 	}
 
 	msg_recv = _recvmmsg(sockfd, &msg[0], PCKT_RX_BUFS, MSG_DONTWAIT | MSG_NOSIGNAL);
 	savederrno = errno;
 
 	/*
 	 * WARNING: man page for recvmmsg is wrong. Kernel implementation here:
 	 * recvmmsg can return:
 	 * -1 on error
 	 *  0 if the previous run of recvmmsg recorded an error on the socket
 	 *  N number of messages (see exception below).
 	 *
 	 * If there is an error from recvmsg after receiving a frame or more, the recvmmsg
 	 * loop is interrupted, error recorded in the socket (getsockopt(SO_ERROR) and
 	 * it will be visibile in the next run.
 	 *
 	 * Need to be careful how we handle errors at this stage.
 	 *
 	 * error messages need to be handled on a per transport/protocol base
 	 * at this point we have different layers of error handling
 	 * - msg_recv < 0 -> error from this run
 	 *   msg_recv = 0 -> error from previous run and error on socket needs to be cleared
 	 * - per-transport message data
 	 *   example: msg[i].msg_hdr.msg_flags & MSG_NOTIFICATION or msg_len for SCTP == EOF,
 	 *            but for UDP it is perfectly legal to receive a 0 bytes message.. go figure
 	 * - NOTE: on SCTP MSG_NOTIFICATION we get msg_recv == PCKT_FRAG_MAX messages and no
 	 *         errno set. That means the error api needs to be able to abort the loop below.
 	 */
 
 	if (msg_recv <= 0) {
 		knet_h->transport_ops[transport]->transport_rx_sock_error(knet_h, sockfd, msg_recv, savederrno);
 		goto exit_unlock;
 	}
 
 	for (i = 0; i < msg_recv; i++) {
 		err = knet_h->transport_ops[transport]->transport_rx_is_data(knet_h, sockfd, &msg[i]);
 
 		/*
 		 * TODO: make this section silent once we are confident
 		 *       all protocols packet handlers are good
 		 */
 
 		switch(err) {
 			case -1: /* on error */
 				log_debug(knet_h, KNET_SUB_RX, "Transport reported error parsing packet");
 				goto exit_unlock;
 				break;
 			case 0: /* packet is not data and we should continue the packet process loop */
 				log_debug(knet_h, KNET_SUB_RX, "Transport reported no data, continue");
 				break;
 			case 1: /* packet is not data and we should STOP the packet process loop */
 				log_debug(knet_h, KNET_SUB_RX, "Transport reported no data, stop");
 				goto exit_unlock;
 				break;
 			case 2: /* packet is data and should be parsed as such */
 				_parse_recv_from_links(knet_h, sockfd, &msg[i]);
 				break;
 		}
 	}
 
 exit_unlock:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 }
 
 void *_handle_recv_from_links_thread(void *data)
 {
 	int i, nev;
 	knet_handle_t knet_h = (knet_handle_t) data;
 	struct epoll_event events[KNET_EPOLL_MAX_EVENTS];
 	struct sockaddr_storage address[PCKT_RX_BUFS];
 	struct knet_mmsghdr msg[PCKT_RX_BUFS];
 	struct iovec iov_in[PCKT_RX_BUFS];
 
 	memset(&msg, 0, sizeof(msg));
 
 	for (i = 0; i < PCKT_RX_BUFS; i++) {
 		iov_in[i].iov_base = (void *)knet_h->recv_from_links_buf[i];
 		iov_in[i].iov_len = KNET_DATABUFSIZE;
 
 		memset(&msg[i].msg_hdr, 0, sizeof(struct msghdr));
 
 		msg[i].msg_hdr.msg_name = &address[i];
 		msg[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
 		msg[i].msg_hdr.msg_iov = &iov_in[i];
 		msg[i].msg_hdr.msg_iovlen = 1;
 	}
 
 	while (!shutdown_in_progress(knet_h)) {
 		nev = epoll_wait(knet_h->recv_from_links_epollfd, events, KNET_EPOLL_MAX_EVENTS, -1);
 
 		for (i = 0; i < nev; i++) {
 			_handle_recv_from_links(knet_h, events[i].data.fd, msg);
 		}
 	}
 
 	return NULL;
 }
diff --git a/libknet/threads_rx.h b/libknet/threads_rx.h
index 8b1a0ce0..5e8d7f16 100644
--- a/libknet/threads_rx.h
+++ b/libknet/threads_rx.h
@@ -1,15 +1,15 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_THREADS_RX_H__
 #define __KNET_THREADS_RX_H__
 
 void *_handle_recv_from_links_thread(void *data);
 
 #endif
diff --git a/libknet/threads_tx.c b/libknet/threads_tx.c
index f13867dd..969f6c03 100644
--- a/libknet/threads_tx.c
+++ b/libknet/threads_tx.c
@@ -1,736 +1,736 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <math.h>
 #include <string.h>
 #include <pthread.h>
 #include <unistd.h>
 #include <sys/uio.h>
 #include <errno.h>
 
 #include "compat.h"
 #include "compress.h"
 #include "crypto.h"
 #include "host.h"
 #include "link.h"
 #include "logging.h"
 #include "transports.h"
 #include "threads_common.h"
 #include "threads_heartbeat.h"
 #include "threads_tx.h"
 #include "netutils.h"
 
 /*
  * SEND
  */
 
 static int _dispatch_to_links(knet_handle_t knet_h, struct knet_host *dst_host, struct knet_mmsghdr *msg, int msgs_to_send)
 {
 	int link_idx, msg_idx, sent_msgs, prev_sent, progress;
 	int err = 0, savederrno = 0;
 	unsigned int i;
 	struct knet_mmsghdr *cur;
 	struct knet_link *cur_link;
 
 	for (link_idx = 0; link_idx < dst_host->active_link_entries; link_idx++) {
 		sent_msgs = 0;
 		prev_sent = 0;
 		progress = 1;
 
 		cur_link = &dst_host->link[dst_host->active_links[link_idx]];
 
 		if (cur_link->transport_type == KNET_TRANSPORT_LOOPBACK) {
 			continue;
 		}
 
 		msg_idx = 0;
 		while (msg_idx < msgs_to_send) {
 			msg[msg_idx].msg_hdr.msg_name = &cur_link->dst_addr;
 
 			/* Cast for Linux/BSD compatibility */
 			for (i=0; i<(unsigned int)msg[msg_idx].msg_hdr.msg_iovlen; i++) {
 				cur_link->status.stats.tx_data_bytes += msg[msg_idx].msg_hdr.msg_iov[i].iov_len;
 			}
 			cur_link->status.stats.tx_data_packets++;
 			msg_idx++;
 		}
 
 retry:
 		cur = &msg[prev_sent];
 
 		sent_msgs = _sendmmsg(dst_host->link[dst_host->active_links[link_idx]].outsock,
 				      &cur[0], msgs_to_send - prev_sent, MSG_DONTWAIT | MSG_NOSIGNAL);
 		savederrno = errno;
 
 		err = knet_h->transport_ops[dst_host->link[dst_host->active_links[link_idx]].transport_type]->transport_tx_sock_error(knet_h, dst_host->link[dst_host->active_links[link_idx]].outsock, sent_msgs, savederrno);
 		switch(err) {
 			case -1: /* unrecoverable error */
 				cur_link->status.stats.tx_data_errors++;
 				goto out_unlock;
 				break;
 			case 0: /* ignore error and continue */
 				break;
 			case 1: /* retry to send those same data */
 				cur_link->status.stats.tx_data_retries++;
 				goto retry;
 				break;
 		}
 
 		prev_sent = prev_sent + sent_msgs;
 
 		if ((sent_msgs >= 0) && (prev_sent < msgs_to_send)) {
 			if ((sent_msgs) || (progress)) {
 				if (sent_msgs) {
 					progress = 1;
 				} else {
 					progress = 0;
 				}
 #ifdef DEBUG
 				log_debug(knet_h, KNET_SUB_TX, "Unable to send all (%d/%d) data packets to host %s (%u) link %s:%s (%u)",
 					  sent_msgs, msg_idx,
 					  dst_host->name, dst_host->host_id,
 					  dst_host->link[dst_host->active_links[link_idx]].status.dst_ipaddr,
 					  dst_host->link[dst_host->active_links[link_idx]].status.dst_port,
 					  dst_host->link[dst_host->active_links[link_idx]].link_id);
 #endif
 				goto retry;
 			}
 			if (!progress) {
 				savederrno = EAGAIN;
 				err = -1;
 				goto out_unlock;
 			}
 		}
 
 		if ((dst_host->link_handler_policy == KNET_LINK_POLICY_RR) &&
 		    (dst_host->active_link_entries > 1)) {
 			uint8_t cur_link_id = dst_host->active_links[0];
 
 			memmove(&dst_host->active_links[0], &dst_host->active_links[1], KNET_MAX_LINK - 1);
 			dst_host->active_links[dst_host->active_link_entries - 1] = cur_link_id;
 
 			break;
 		}
 	}
 
 out_unlock:
 	errno = savederrno;
 	return err;
 }
 
 static int _parse_recv_from_sock(knet_handle_t knet_h, size_t inlen, int8_t channel, int is_sync)
 {
 	size_t outlen, frag_len;
 	struct knet_host *dst_host;
 	knet_node_id_t dst_host_ids_temp[KNET_MAX_HOST];
 	size_t dst_host_ids_entries_temp = 0;
 	knet_node_id_t dst_host_ids[KNET_MAX_HOST];
 	size_t dst_host_ids_entries = 0;
 	int bcast = 1;
 	struct knet_hostinfo *knet_hostinfo;
 	struct iovec iov_out[PCKT_FRAG_MAX][2];
 	int iovcnt_out = 2;
 	uint8_t frag_idx;
 	unsigned int temp_data_mtu;
 	size_t host_idx;
 	int send_mcast = 0;
 	struct knet_header *inbuf;
 	int savederrno = 0;
 	int err = 0;
 	seq_num_t tx_seq_num;
 	struct knet_mmsghdr msg[PCKT_FRAG_MAX];
 	int msgs_to_send, msg_idx;
 	unsigned int i;
 	int j;
 	int send_local = 0;
 	int data_compressed = 0;
 	size_t uncrypted_frag_size;
 
 	inbuf = knet_h->recv_from_sock_buf;
 
 	if ((knet_h->enabled != 1) &&
 	    (inbuf->kh_type != KNET_HEADER_TYPE_HOST_INFO)) { /* data forward is disabled */
 		log_debug(knet_h, KNET_SUB_TX, "Received data packet but forwarding is disabled");
 		savederrno = ECANCELED;
 		err = -1;
 		goto out_unlock;
 	}
 
 	/*
 	 * move this into a separate function to expand on
 	 * extra switching rules
 	 */
 	switch(inbuf->kh_type) {
 		case KNET_HEADER_TYPE_DATA:
 			if (knet_h->dst_host_filter_fn) {
 				bcast = knet_h->dst_host_filter_fn(
 						knet_h->dst_host_filter_fn_private_data,
 						(const unsigned char *)inbuf->khp_data_userdata,
 						inlen,
 						KNET_NOTIFY_TX,
 						knet_h->host_id,
 						knet_h->host_id,
 						&channel,
 						dst_host_ids_temp,
 						&dst_host_ids_entries_temp);
 				if (bcast < 0) {
 					log_debug(knet_h, KNET_SUB_TX, "Error from dst_host_filter_fn: %d", bcast);
 					savederrno = EFAULT;
 					err = -1;
 					goto out_unlock;
 				}
 
 				if ((!bcast) && (!dst_host_ids_entries_temp)) {
 					log_debug(knet_h, KNET_SUB_TX, "Message is unicast but no dst_host_ids_entries");
 					savederrno = EINVAL;
 					err = -1;
 					goto out_unlock;
 				}
 			}
 
 			/* Send to localhost if appropriate and enabled */
 			if (knet_h->has_loop_link) {
 				send_local = 0;
 				if (bcast) {
 					send_local = 1;
 				} else {
 					for (i=0; i< dst_host_ids_entries_temp; i++) {
 						if (dst_host_ids_temp[i] == knet_h->host_id) {
 							send_local = 1;
 						}
 					}
 				}
 				if (send_local) {
 					const unsigned char *buf = inbuf->khp_data_userdata;
 					ssize_t buflen = inlen;
 					struct knet_link *local_link;
 
 					local_link = knet_h->host_index[knet_h->host_id]->link;
 
 				local_retry:
 					err = write(knet_h->sockfd[channel].sockfd[knet_h->sockfd[channel].is_created], buf, buflen);
 					if (err < 0) {
 						log_err(knet_h, KNET_SUB_TRANSP_LOOPBACK, "send local failed. error=%s\n", strerror(errno));
 						local_link->status.stats.tx_data_errors++;
 					}
 					if (err > 0 && err < buflen) {
 						log_debug(knet_h, KNET_SUB_TRANSP_LOOPBACK, "send local incomplete=%d bytes of %zu\n", err, inlen);
 						local_link->status.stats.tx_data_retries++;
 						buf += err;
 						buflen -= err;
 						usleep(KNET_THREADS_TIMERES / 16);
 						goto local_retry;
 					}
 					if (err == buflen) {
 						local_link->status.stats.tx_data_packets++;
 						local_link->status.stats.tx_data_bytes += inlen;
 					}
 				}
 			}
 			break;
 		case KNET_HEADER_TYPE_HOST_INFO:
 			knet_hostinfo = (struct knet_hostinfo *)inbuf->khp_data_userdata;
 			if (knet_hostinfo->khi_bcast == KNET_HOSTINFO_UCAST) {
 				bcast = 0;
 				dst_host_ids_temp[0] = knet_hostinfo->khi_dst_node_id;
 				dst_host_ids_entries_temp = 1;
 				knet_hostinfo->khi_dst_node_id = htons(knet_hostinfo->khi_dst_node_id);
 			}
 			break;
 		default:
 			log_warn(knet_h, KNET_SUB_TX, "Receiving unknown messages from socket");
 			savederrno = ENOMSG;
 			err = -1;
 			goto out_unlock;
 			break;
 	}
 
 	if (is_sync) {
 		if ((bcast) ||
 		    ((!bcast) && (dst_host_ids_entries_temp > 1))) {
 			log_debug(knet_h, KNET_SUB_TX, "knet_send_sync is only supported with unicast packets for one destination");
 			savederrno = E2BIG;
 			err = -1;
 			goto out_unlock;
 		}
 	}
 
 	/*
 	 * check destinations hosts before spending time
 	 * in fragmenting/encrypting packets to save
 	 * time processing data for unreachable hosts.
 	 * for unicast, also remap the destination data
 	 * to skip unreachable hosts.
 	 */
 
 	if (!bcast) {
 		dst_host_ids_entries = 0;
 		for (host_idx = 0; host_idx < dst_host_ids_entries_temp; host_idx++) {
 			dst_host = knet_h->host_index[dst_host_ids_temp[host_idx]];
 			if (!dst_host) {
 				continue;
 			}
 			if (!(dst_host->host_id == knet_h->host_id &&
 			     knet_h->has_loop_link) &&
 			    dst_host->status.reachable) {
 				dst_host_ids[dst_host_ids_entries] = dst_host_ids_temp[host_idx];
 				dst_host_ids_entries++;
 			}
 		}
 		if (!dst_host_ids_entries) {
 			savederrno = EHOSTDOWN;
 			err = -1;
 			goto out_unlock;
 		}
 	} else {
 		send_mcast = 0;
 		for (dst_host = knet_h->host_head; dst_host != NULL; dst_host = dst_host->next) {
 			if (!(dst_host->host_id == knet_h->host_id &&
 			      knet_h->has_loop_link) &&
 			    dst_host->status.reachable) {
 				send_mcast = 1;
 				break;
 			}
 		}
 		if (!send_mcast) {
 			savederrno = EHOSTDOWN;
 			err = -1;
 			goto out_unlock;
 		}
 	}
 
 	if (!knet_h->data_mtu) {
 		/*
 		 * using MIN_MTU_V4 for data mtu is not completely accurate but safe enough
 		 */
 		log_debug(knet_h, KNET_SUB_TX,
 			  "Received data packet but data MTU is still unknown."
 			  " Packet might not be delivered."
 			  " Assuming mininum IPv4 mtu (%d)",
 			  KNET_PMTUD_MIN_MTU_V4);
 		temp_data_mtu = KNET_PMTUD_MIN_MTU_V4;
 	} else {
 		/*
 		 * take a copy of the mtu to avoid value changing under
 		 * our feet while we are sending a fragmented pckt
 		 */
 		temp_data_mtu = knet_h->data_mtu;
 	}
 
 	/*
 	 * compress data
 	 */
 	if ((knet_h->compress_model > 0) && (inlen > knet_h->compress_threshold)) {
 		size_t cmp_outlen = KNET_DATABUFSIZE_COMPRESS;
 		struct timespec start_time;
 		struct timespec end_time;
 		uint64_t compress_time;
 
 		clock_gettime(CLOCK_MONOTONIC, &start_time);
 		err = compress(knet_h,
 			       (const unsigned char *)inbuf->khp_data_userdata, inlen,
 			       knet_h->send_to_links_buf_compress, (ssize_t *)&cmp_outlen);
 		if (err < 0) {
 			log_warn(knet_h, KNET_SUB_COMPRESS, "Compression failed (%d): %s", err, strerror(errno));
 		} else {
 			/* Collect stats */
 			clock_gettime(CLOCK_MONOTONIC, &end_time);
 			timespec_diff(start_time, end_time, &compress_time);
 
 	                if (compress_time < knet_h->stats.tx_compress_time_min) {
 				knet_h->stats.tx_compress_time_min = compress_time;
 			}
 			if (compress_time > knet_h->stats.tx_compress_time_max) {
 				knet_h->stats.tx_compress_time_max = compress_time;
 			}
 			knet_h->stats.tx_compress_time_ave =
 				(unsigned long long)(knet_h->stats.tx_compress_time_ave * knet_h->stats.tx_compressed_packets +
 				 compress_time) / (knet_h->stats.tx_compressed_packets+1);
 
 			knet_h->stats.tx_compressed_packets++;
 			knet_h->stats.tx_compressed_original_bytes += inlen;
 			knet_h->stats.tx_compressed_size_bytes += cmp_outlen;
 
 			if (cmp_outlen < inlen) {
 				memmove(inbuf->khp_data_userdata, knet_h->send_to_links_buf_compress, cmp_outlen);
 				inlen = cmp_outlen;
 				data_compressed = 1;
 			}
 		}
 	}
 	if ((knet_h->compress_model > 0) && (inlen <= knet_h->compress_threshold)) {
 		knet_h->stats.tx_uncompressed_packets++;
 	}
 
 	/*
 	 * prepare the outgoing buffers
 	 */
 
 	frag_len = inlen;
 	frag_idx = 0;
 
 	inbuf->khp_data_bcast = bcast;
 	inbuf->khp_data_frag_num = ceil((float)inlen / temp_data_mtu);
 	inbuf->khp_data_channel = channel;
 	if (data_compressed) {
 		inbuf->khp_data_compress = knet_h->compress_model;
 	} else {
 		inbuf->khp_data_compress = 0;
 	}
 
 	if (pthread_mutex_lock(&knet_h->tx_seq_num_mutex)) {
 		log_debug(knet_h, KNET_SUB_TX, "Unable to get seq mutex lock");
 		goto out_unlock;
 	}
 	knet_h->tx_seq_num++;
 	/*
 	 * force seq_num 0 to detect a node that has crashed and rejoining
 	 * the knet instance. seq_num 0 will clear the buffers in the RX
 	 * thread
 	 */
 	if (knet_h->tx_seq_num == 0) {
 		knet_h->tx_seq_num++;
 	}
 	/*
 	 * cache the value in locked context
 	 */
 	tx_seq_num = knet_h->tx_seq_num;
 	inbuf->khp_data_seq_num = htons(knet_h->tx_seq_num);
 	pthread_mutex_unlock(&knet_h->tx_seq_num_mutex);
 
 	/*
 	 * forcefully broadcast a ping to all nodes every SEQ_MAX / 8
 	 * pckts.
 	 * this solves 2 problems:
 	 * 1) on TX socket overloads we generate extra pings to keep links alive
 	 * 2) in 3+ nodes setup, where all the traffic is flowing between node 1 and 2,
 	 *    node 3+ will be able to keep in sync on the TX seq_num even without
 	 *    receiving traffic or pings in betweens. This avoids issues with
 	 *    rollover of the circular buffer
 	 */
 
 	if (tx_seq_num % (SEQ_MAX / 8) == 0) {
 		_send_pings(knet_h, 0);
 	}
 
 	if (inbuf->khp_data_frag_num > 1) {
 		while (frag_idx < inbuf->khp_data_frag_num) {
 			/*
 			 * set the iov_base
 			 */
 			iov_out[frag_idx][0].iov_base = (void *)knet_h->send_to_links_buf[frag_idx];
 			iov_out[frag_idx][0].iov_len = KNET_HEADER_DATA_SIZE;
 			iov_out[frag_idx][1].iov_base = inbuf->khp_data_userdata + (temp_data_mtu * frag_idx);
 
 			/*
 			 * set the len
 			 */
 			if (frag_len > temp_data_mtu) {
 				iov_out[frag_idx][1].iov_len = temp_data_mtu;
 			} else {
 				iov_out[frag_idx][1].iov_len = frag_len;
 			}
 
 			/*
 			 * copy the frag info on all buffers
 			 */
 			knet_h->send_to_links_buf[frag_idx]->kh_type = inbuf->kh_type;
 			knet_h->send_to_links_buf[frag_idx]->khp_data_seq_num = inbuf->khp_data_seq_num;
 			knet_h->send_to_links_buf[frag_idx]->khp_data_frag_num = inbuf->khp_data_frag_num;
 			knet_h->send_to_links_buf[frag_idx]->khp_data_bcast = inbuf->khp_data_bcast;
 			knet_h->send_to_links_buf[frag_idx]->khp_data_channel = inbuf->khp_data_channel;
 			knet_h->send_to_links_buf[frag_idx]->khp_data_compress = inbuf->khp_data_compress;
 
 			frag_len = frag_len - temp_data_mtu;
 			frag_idx++;
 		}
 		iovcnt_out = 2;
 	} else {
 		iov_out[frag_idx][0].iov_base = (void *)inbuf;
 		iov_out[frag_idx][0].iov_len = frag_len + KNET_HEADER_DATA_SIZE;
 		iovcnt_out = 1;
 	}
 
 	if (knet_h->crypto_instance) {
 		struct timespec start_time;
 		struct timespec end_time;
 		uint64_t crypt_time;
 
 		frag_idx = 0;
 		while (frag_idx < inbuf->khp_data_frag_num) {
 			clock_gettime(CLOCK_MONOTONIC, &start_time);
 			if (crypto_encrypt_and_signv(
 					knet_h,
 					iov_out[frag_idx], iovcnt_out,
 					knet_h->send_to_links_buf_crypt[frag_idx],
 					(ssize_t *)&outlen) < 0) {
 				log_debug(knet_h, KNET_SUB_TX, "Unable to encrypt packet");
 				savederrno = ECHILD;
 				err = -1;
 				goto out_unlock;
 			}
 			clock_gettime(CLOCK_MONOTONIC, &end_time);
 			timespec_diff(start_time, end_time, &crypt_time);
 
 	                if (crypt_time < knet_h->stats.tx_crypt_time_min) {
 				knet_h->stats.tx_crypt_time_min = crypt_time;
 			}
 			if (crypt_time > knet_h->stats.tx_crypt_time_max) {
 				knet_h->stats.tx_crypt_time_max = crypt_time;
 			}
 			knet_h->stats.tx_crypt_time_ave =
 				(knet_h->stats.tx_crypt_time_ave * knet_h->stats.tx_crypt_packets +
 				 crypt_time) / (knet_h->stats.tx_crypt_packets+1);
 
 			uncrypted_frag_size = 0;
 			for (j=0; j < iovcnt_out; j++) {
 				uncrypted_frag_size += iov_out[frag_idx][j].iov_len;
 			}
 			knet_h->stats.tx_crypt_byte_overhead += (outlen - uncrypted_frag_size);
 			knet_h->stats.tx_crypt_packets++;
 
 			iov_out[frag_idx][0].iov_base = knet_h->send_to_links_buf_crypt[frag_idx];
 			iov_out[frag_idx][0].iov_len = outlen;
 			frag_idx++;
 		}
 		iovcnt_out = 1;
 	}
 
 	memset(&msg, 0, sizeof(msg));
 
 	msgs_to_send = inbuf->khp_data_frag_num;
 
 	msg_idx = 0;
 
 	while (msg_idx < msgs_to_send) {
 		msg[msg_idx].msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
 		msg[msg_idx].msg_hdr.msg_iov = &iov_out[msg_idx][0];
 		msg[msg_idx].msg_hdr.msg_iovlen = iovcnt_out;
 		msg_idx++;
 	}
 
 	if (!bcast) {
 		for (host_idx = 0; host_idx < dst_host_ids_entries; host_idx++) {
 			dst_host = knet_h->host_index[dst_host_ids[host_idx]];
 
 			err = _dispatch_to_links(knet_h, dst_host, &msg[0], msgs_to_send);
 			savederrno = errno;
 			if (err) {
 				goto out_unlock;
 			}
 		}
 	} else {
 		for (dst_host = knet_h->host_head; dst_host != NULL; dst_host = dst_host->next) {
 			if (dst_host->status.reachable) {
 				err = _dispatch_to_links(knet_h, dst_host, &msg[0], msgs_to_send);
 				savederrno = errno;
 				if (err) {
 					goto out_unlock;
 				}
 			}
 		}
 	}
 
 out_unlock:
 	errno = savederrno;
 	return err;
 }
 
 int knet_send_sync(knet_handle_t knet_h, const char *buff, const size_t buff_len, const int8_t channel)
 {
 	int savederrno = 0, err = 0;
 
 	if (!knet_h) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (buff == NULL) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (buff_len <= 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (buff_len > KNET_MAX_PACKET_SIZE) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (channel < 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (channel >= KNET_DATAFD_MAX) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_TX, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	if (!knet_h->sockfd[channel].in_use) {
 		savederrno = EINVAL;
 		err = -1;
 		goto out;
 	}
 
 	savederrno = pthread_mutex_lock(&knet_h->tx_mutex);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_TX, "Unable to get TX mutex lock: %s",
 			strerror(savederrno));
 		err = -1;
 		goto out;
 	}
 
 	knet_h->recv_from_sock_buf->kh_type = KNET_HEADER_TYPE_DATA;
 	memmove(knet_h->recv_from_sock_buf->khp_data_userdata, buff, buff_len);
 	err = _parse_recv_from_sock(knet_h, buff_len, channel, 1);
 	savederrno = errno;
 
 	pthread_mutex_unlock(&knet_h->tx_mutex);
 
 out:
 	pthread_rwlock_unlock(&knet_h->global_rwlock);
 
 	errno = savederrno;
 	return err;
 }
 
 static void _handle_send_to_links(knet_handle_t knet_h, struct msghdr *msg, int sockfd, int8_t channel, int type)
 {
 	ssize_t inlen = 0;
 	int savederrno = 0, docallback = 0;
 
 	if ((channel >= 0) &&
 	    (channel < KNET_DATAFD_MAX) &&
 	    (!knet_h->sockfd[channel].is_socket)) {
 		inlen = readv(sockfd, msg->msg_iov, 1);
 	} else {
 		inlen = recvmsg(sockfd, msg, MSG_DONTWAIT | MSG_NOSIGNAL);
 	}
 
 	if (inlen == 0) {
 		savederrno = 0;
 		docallback = 1;
 		goto out;
 	}
 	if (inlen < 0) {
 		savederrno = errno;
 		docallback = 1;
 		goto out;
 	}
 
 	knet_h->recv_from_sock_buf->kh_type = type;
 	_parse_recv_from_sock(knet_h, inlen, channel, 0);
 
 out:
 	if (inlen < 0) {
 		struct epoll_event ev;
 
 		memset(&ev, 0, sizeof(struct epoll_event));
 
 		if (epoll_ctl(knet_h->send_to_links_epollfd,
 			      EPOLL_CTL_DEL, knet_h->sockfd[channel].sockfd[knet_h->sockfd[channel].is_created], &ev)) {
 			log_err(knet_h, KNET_SUB_TX, "Unable to del datafd %d from linkfd epoll pool: %s",
 				knet_h->sockfd[channel].sockfd[0], strerror(savederrno));
 		} else {
 			knet_h->sockfd[channel].has_error = 1;
 		}
 
 	}
 
 	if (docallback) {
 		knet_h->sock_notify_fn(knet_h->sock_notify_fn_private_data,
 				       knet_h->sockfd[channel].sockfd[0],
 				       channel,
 				       KNET_NOTIFY_TX,
 				       inlen,
 				       savederrno);
 	}
 }
 
 void *_handle_send_to_links_thread(void *data)
 {
 	knet_handle_t knet_h = (knet_handle_t) data;
 	struct epoll_event events[KNET_EPOLL_MAX_EVENTS];
 	int i, nev, type;
 	int8_t channel;
 	struct iovec iov_in;
 	struct msghdr msg;
 	struct sockaddr_storage address;
 
 	memset(&iov_in, 0, sizeof(iov_in));
 	iov_in.iov_base = (void *)knet_h->recv_from_sock_buf->khp_data_userdata;
 	iov_in.iov_len = KNET_MAX_PACKET_SIZE;
 
 	memset(&msg, 0, sizeof(struct msghdr));
 	msg.msg_name = &address;
 	msg.msg_namelen = sizeof(struct sockaddr_storage);
 	msg.msg_iov = &iov_in;
 	msg.msg_iovlen = 1;
 
 	knet_h->recv_from_sock_buf->kh_version = KNET_HEADER_VERSION;
 	knet_h->recv_from_sock_buf->khp_data_frag_seq = 0;
 	knet_h->recv_from_sock_buf->kh_node = htons(knet_h->host_id);
 
 	for (i = 0; i < PCKT_FRAG_MAX; i++) {
 		knet_h->send_to_links_buf[i]->kh_version = KNET_HEADER_VERSION;
 		knet_h->send_to_links_buf[i]->khp_data_frag_seq = i + 1;
 		knet_h->send_to_links_buf[i]->kh_node = htons(knet_h->host_id);
 	}
 
 	while (!shutdown_in_progress(knet_h)) {
 		nev = epoll_wait(knet_h->send_to_links_epollfd, events, KNET_EPOLL_MAX_EVENTS + 1, -1);
 
 		if (pthread_rwlock_rdlock(&knet_h->global_rwlock) != 0) {
 			log_debug(knet_h, KNET_SUB_TX, "Unable to get read lock");
 			continue;
 		}
 
 		for (i = 0; i < nev; i++) {
 			if (events[i].data.fd == knet_h->hostsockfd[0]) {
 				type = KNET_HEADER_TYPE_HOST_INFO;
 				channel = -1;
 			} else {
 				type = KNET_HEADER_TYPE_DATA;
 				for (channel = 0; channel < KNET_DATAFD_MAX; channel++) {
 					if ((knet_h->sockfd[channel].in_use) &&
 					    (knet_h->sockfd[channel].sockfd[knet_h->sockfd[channel].is_created] == events[i].data.fd)) {
 						break;
 					}
 				}
 				if (channel >= KNET_DATAFD_MAX) {
 					log_debug(knet_h, KNET_SUB_TX, "No available channels");
 					continue; /* channel not found */
 				}
 			}
 			if (pthread_mutex_lock(&knet_h->tx_mutex) != 0) {
 				log_debug(knet_h, KNET_SUB_TX, "Unable to get mutex lock");
 				continue;
 			}
 			_handle_send_to_links(knet_h, &msg, events[i].data.fd, channel, type);
 			pthread_mutex_unlock(&knet_h->tx_mutex);
 		}
 		pthread_rwlock_unlock(&knet_h->global_rwlock);
 	}
 
 	return NULL;
 }
diff --git a/libknet/threads_tx.h b/libknet/threads_tx.h
index 82c64fe8..771f2ee2 100644
--- a/libknet/threads_tx.h
+++ b/libknet/threads_tx.h
@@ -1,15 +1,15 @@
 /*
- * Copyright (C) 2017 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2012-2017 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *          Federico Simoncelli <fsimon@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __KNET_THREADS_TX_H__
 #define __KNET_THREADS_TX_H__
 
 void *_handle_send_to_links_thread(void *data);
 
 #endif
diff --git a/libtap/libtap.h b/libtap/libtap.h
index 015ef9cb..63aecfd8 100644
--- a/libtap/libtap.h
+++ b/libtap/libtap.h
@@ -1,40 +1,40 @@
 /*
- * Copyright (C) 2010-2015 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+, LGPL-2.0+
  */
 
 #ifndef __LIBTAP_H__
 #define __LIBTAP_H__
 
 #include <sys/types.h>
 
 typedef struct _iface *tap_t;
 
 tap_t tap_open(char *dev, size_t dev_size, const char *updownpath);
 int tap_close(tap_t tap);
 
 tap_t tap_find(char *dev, size_t dev_size);
 
 int tap_get_fd(const tap_t tap);
 
 const char *tap_get_name(const tap_t tap);
 
 int tap_get_mtu(const tap_t tap);
 int tap_set_mtu(tap_t tap, const int mtu);
 int tap_reset_mtu(tap_t tap);
 
 int tap_get_mac(const tap_t tap, char **ether_addr);
 int tap_set_mac(tap_t tap, const char *ether_addr);
 int tap_reset_mac(tap_t tap);
 
 int tap_set_up(tap_t tap, char **error_preup, char **error_up);
 int tap_set_down(tap_t tap, char **error_down, char **error_postdown);
 
 int tap_add_ip(tap_t tap, const char *ip_addr, const char *prefix, char **error_string);
 int tap_del_ip(tap_t tap, const char *ip_addr, const char *prefix, char **error_string);
 int tap_get_ips(const tap_t tap, char **ip_addr_list, int *entries);
 
 #endif
diff --git a/libtap/tap_updown_bad/down.d/kronostest b/libtap/tap_updown_bad/down.d/kronostest
index 232759ac..bd48285e 100755
--- a/libtap/tap_updown_bad/down.d/kronostest
+++ b/libtap/tap_updown_bad/down.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 1
diff --git a/libtap/tap_updown_bad/post-down.d/kronostest b/libtap/tap_updown_bad/post-down.d/kronostest
index 232759ac..bd48285e 100755
--- a/libtap/tap_updown_bad/post-down.d/kronostest
+++ b/libtap/tap_updown_bad/post-down.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 1
diff --git a/libtap/tap_updown_bad/pre-up.d/kronostest b/libtap/tap_updown_bad/pre-up.d/kronostest
index 232759ac..bd48285e 100755
--- a/libtap/tap_updown_bad/pre-up.d/kronostest
+++ b/libtap/tap_updown_bad/pre-up.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 1
diff --git a/libtap/tap_updown_bad/up.d/kronostest b/libtap/tap_updown_bad/up.d/kronostest
index 232759ac..bd48285e 100755
--- a/libtap/tap_updown_bad/up.d/kronostest
+++ b/libtap/tap_updown_bad/up.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 1
diff --git a/libtap/tap_updown_good/down.d/kronostest b/libtap/tap_updown_good/down.d/kronostest
index b0ce74c6..b6ac8715 100755
--- a/libtap/tap_updown_good/down.d/kronostest
+++ b/libtap/tap_updown_good/down.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 0
diff --git a/libtap/tap_updown_good/post-down.d/kronostest b/libtap/tap_updown_good/post-down.d/kronostest
index b0ce74c6..b6ac8715 100755
--- a/libtap/tap_updown_good/post-down.d/kronostest
+++ b/libtap/tap_updown_good/post-down.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 0
diff --git a/libtap/tap_updown_good/pre-up.d/kronostest b/libtap/tap_updown_good/pre-up.d/kronostest
index b0ce74c6..b6ac8715 100755
--- a/libtap/tap_updown_good/pre-up.d/kronostest
+++ b/libtap/tap_updown_good/pre-up.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 0
diff --git a/libtap/tap_updown_good/up.d/kronostest b/libtap/tap_updown_good/up.d/kronostest
index b0ce74c6..b6ac8715 100755
--- a/libtap/tap_updown_good/up.d/kronostest
+++ b/libtap/tap_updown_good/up.d/kronostest
@@ -1,11 +1,11 @@
 #!/bin/bash
 
 #
-# Copyright (C) 2011-2015 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2010-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 exit 0
diff --git a/poc-code/access-list/Makefile.am b/poc-code/access-list/Makefile.am
index 35f15473..fc7a86fb 100644
--- a/poc-code/access-list/Makefile.am
+++ b/poc-code/access-list/Makefile.am
@@ -1,22 +1,22 @@
 #
-# Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 MAINTAINERCLEANFILES	= Makefile.in
 
 include $(top_srcdir)/build-aux/check.mk
 
 # override global LIBS that pulls in lots of craft we don't need here
 LIBS			=
 
 EXTRA_DIST		= test_ipcheck.txt
 
 noinst_PROGRAMS		= test_ipcheck
 
 noinst_HEADERS		= ipcheck.h
 
 test_ipcheck_SOURCES	= ipcheck.c test_ipcheck.c
diff --git a/poc-code/iov-hash/Makefile.am b/poc-code/iov-hash/Makefile.am
index b4642267..9e03b8e7 100644
--- a/poc-code/iov-hash/Makefile.am
+++ b/poc-code/iov-hash/Makefile.am
@@ -1,22 +1,22 @@
 #
-# Copyright (C) 2016 Red Hat, Inc.  All rights reserved.
+# Copyright (C) 2016-2017 Red Hat, Inc.  All rights reserved.
 #
 # Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
 #
 # This software licensed under GPL-2.0+, LGPL-2.0+
 #
 
 MAINTAINERCLEANFILES	= Makefile.in
 
 include $(top_srcdir)/build-aux/check.mk
 
 # override global LIBS that pulls in lots of craft we don't need here
 LIBS			=
 
 noinst_PROGRAMS		= nss_hash
 
 nss_hash_SOURCES	= main.c
 
 nss_hash_CFLAGS		= $(nss_CFLAGS)
 
 nss_hash_LDFLAGS	= $(nss_LIBS)