Blame SOURCES/bz1508435-load-ip-tables-handling.patch

00db14
From dd9a0db422716dd9bbc329a6e2f23ee3d55d2008 Mon Sep 17 00:00:00 2001
00db14
From: Quentin Armitage <quentin@armitage.org.uk>
00db14
Date: Mon, 27 Mar 2017 11:26:44 +0100
00db14
Subject: [PATCH 1/3] Handle not being able to load ip_tables or ip6_tables
00db14
 modules
00db14
00db14
When running in a docker container it isn't possible to load kernel
00db14
modules, so we need to cleanly handle a failure to load the modules.
00db14
00db14
Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
00db14
---
00db14
 keepalived/core/global_data.c            |   2 -
00db14
 keepalived/include/global_data.h         |   2 -
00db14
 keepalived/include/vrrp.h                |   5 +
00db14
 keepalived/include/vrrp_ipset.h          |   4 +-
00db14
 keepalived/include/vrrp_iptables.h       |   7 +-
00db14
 keepalived/include/vrrp_iptables_calls.h |   2 +-
00db14
 keepalived/vrrp/vrrp.c                   |  53 ++++++--
00db14
 keepalived/vrrp/vrrp_daemon.c            |  13 +-
00db14
 keepalived/vrrp/vrrp_ipaddress.c         | 137 ++++++++++++++++---
00db14
 keepalived/vrrp/vrrp_ipset.c             |  73 +++++++---
00db14
 keepalived/vrrp/vrrp_iptables.c          | 225 +++++++++++++++++++------------
00db14
 keepalived/vrrp/vrrp_iptables_calls.c    | 108 +++++++--------
00db14
 12 files changed, 421 insertions(+), 210 deletions(-)
00db14
00db14
diff --git a/keepalived/core/global_data.c b/keepalived/core/global_data.c
00db14
index d934f286..21c06c1c 100644
00db14
--- a/keepalived/core/global_data.c
00db14
+++ b/keepalived/core/global_data.c
00db14
@@ -98,8 +98,6 @@ set_vrrp_defaults(data_t * data)
00db14
 	data->vrrp_higher_prio_send_advert = false;
00db14
 	data->vrrp_version = VRRP_VERSION_2;
00db14
 	strcpy(data->vrrp_iptables_inchain, "INPUT");
00db14
-	data->block_ipv4 = false;
00db14
-	data->block_ipv6 = false;
00db14
 #ifdef _HAVE_LIBIPSET_
00db14
 	data->using_ipsets = true;
00db14
 	strcpy(data->vrrp_ipset_address, "keepalived");
00db14
diff --git a/keepalived/include/global_data.h b/keepalived/include/global_data.h
00db14
index 6547ddac..eea34f75 100644
00db14
--- a/keepalived/include/global_data.h
00db14
+++ b/keepalived/include/global_data.h
00db14
@@ -99,8 +99,6 @@ typedef struct _data {
00db14
 	int				vrrp_version;	/* VRRP version (2 or 3) */
00db14
 	char				vrrp_iptables_inchain[XT_EXTENSION_MAXNAMELEN];
00db14
 	char				vrrp_iptables_outchain[XT_EXTENSION_MAXNAMELEN];
00db14
-	bool				block_ipv4;
00db14
-	bool				block_ipv6;
00db14
 #ifdef _HAVE_LIBIPSET_
00db14
 	bool				using_ipsets;
00db14
 	char				vrrp_ipset_address[IPSET_MAXNAMELEN];
00db14
diff --git a/keepalived/include/vrrp.h b/keepalived/include/vrrp.h
00db14
index 6e874689..ab757277 100644
00db14
--- a/keepalived/include/vrrp.h
00db14
+++ b/keepalived/include/vrrp.h
00db14
@@ -313,6 +313,10 @@ typedef struct _vrrp_t {
00db14
 
00db14
 #define VRRP_ISUP(V)		(VRRP_IF_ISUP(V) && VRRP_SCRIPT_ISUP(V))
00db14
 
00db14
+/* Global variables */
00db14
+extern bool block_ipv4;
00db14
+extern bool block_ipv6;
00db14
+
00db14
 /* prototypes */
00db14
 extern vrrphdr_t *vrrp_get_header(sa_family_t, char *, unsigned *);
00db14
 extern int open_vrrp_send_socket(sa_family_t, int, ifindex_t, bool);
00db14
@@ -327,6 +331,7 @@ extern void vrrp_state_backup(vrrp_t *, char *, ssize_t);
00db14
 extern void vrrp_state_goto_master(vrrp_t *);
00db14
 extern void vrrp_state_leave_master(vrrp_t *);
00db14
 extern bool vrrp_complete_init(void);
00db14
+extern void vrrp_restore_interfaces_startup(void);
00db14
 extern void restore_vrrp_interfaces(void);
00db14
 extern void shutdown_vrrp_instances(void);
00db14
 extern void clear_diff_vrrp(void);
00db14
diff --git a/keepalived/include/vrrp_ipset.h b/keepalived/include/vrrp_ipset.h
00db14
index 9ee1095a..6cc320ef 100644
00db14
--- a/keepalived/include/vrrp_ipset.h
00db14
+++ b/keepalived/include/vrrp_ipset.h
00db14
@@ -27,8 +27,8 @@
00db14
 #include <libipset/session.h>
00db14
 #include "vrrp_ipaddress.h"
00db14
 
00db14
-int add_ipsets(bool);
00db14
-int remove_ipsets(void);
00db14
+bool add_ipsets(bool);
00db14
+bool remove_ipsets(void);
00db14
 bool has_ipset_setname(struct ipset_session*, const char *);
00db14
 bool ipset_init(void);
00db14
 struct ipset_session* ipset_session_start(void);
00db14
diff --git a/keepalived/include/vrrp_iptables.h b/keepalived/include/vrrp_iptables.h
00db14
index 2a7681b3..dbbd6fe7 100644
00db14
--- a/keepalived/include/vrrp_iptables.h
00db14
+++ b/keepalived/include/vrrp_iptables.h
00db14
@@ -37,12 +37,11 @@ struct ipt_handle;
00db14
 #define	IPTABLES_MAX_TRIES	3	/* How many times to try adding/deleting when get EAGAIN */
00db14
 
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
-extern bool using_libiptc;		/* Set if using libiptc - for dynamic linking */
00db14
+extern bool using_libip4tc;		/* Set if using lib4iptc - for dynamic linking */
00db14
+extern bool using_libip6tc;		/* Set if using lib4iptc - for dynamic linking */
00db14
 #endif
00db14
-extern bool use_ip4tables;		/* Set if using iptables */
00db14
-extern bool use_ip6tables;		/* Set if using ip6tables */
00db14
 
00db14
-bool iptables_init_lib(void);
00db14
+void iptables_init_lib(void);
00db14
 void iptables_fini(void);
00db14
 void iptables_startup(bool);
00db14
 void iptables_cleanup(void);
00db14
diff --git a/keepalived/include/vrrp_iptables_calls.h b/keepalived/include/vrrp_iptables_calls.h
00db14
index 34052fac..ef4e0183 100644
00db14
--- a/keepalived/include/vrrp_iptables_calls.h
00db14
+++ b/keepalived/include/vrrp_iptables_calls.h
00db14
@@ -34,7 +34,6 @@
00db14
 
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
 #ifdef _LIBXTABLES_DYNAMIC_ 
00db14
-extern bool xtables_load(void);
00db14
 extern void xtables_unload(void);
00db14
 #endif
00db14
 extern bool load_xtables_module(const char *, const char *);
00db14
@@ -50,6 +49,7 @@ extern int ip6tables_is_chain(struct ip6tc_handle* handle, const char* chain_nam
00db14
 extern int ip6tables_process_entry( struct ip6tc_handle* handle, const char* chain_name, unsigned int rulenum, const char* target_name, const ip_address_t* src_ip_address, const ip_address_t* dst_ip_address, const char* in_iface, const char* out_iface, uint16_t protocol, uint8_t type, int cmd, bool force);
00db14
 extern int ip4tables_add_rules(struct iptc_handle* handle, const char* chain_name, unsigned int rulenum, uint8_t dim, uint8_t src_dst, const char* target_name, const char* set_name, uint16_t protocol, uint8_t param, int cmd, bool ignore_errors);
00db14
 extern int ip6tables_add_rules(struct ip6tc_handle* handle, const char* chain_name, unsigned int rulenum, uint8_t dim, uint8_t src_dst, const char* target_name, const char* set_name, uint16_t protocol, uint8_t param, int cmd, bool ignore_errors);
00db14
+extern void check_chains_exist_lib(void);
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
 extern bool iptables_lib_init(void);
00db14
 #endif
00db14
diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c
00db14
index 3d2bfe41..38895af8 100644
00db14
--- a/keepalived/vrrp/vrrp.c
00db14
+++ b/keepalived/vrrp/vrrp.c
00db14
@@ -72,6 +72,10 @@
00db14
 #include <netinet/ip6.h>
00db14
 #include <stdint.h>
00db14
 
00db14
+/* Set if need to block ip addresses and are able to do so */
00db14
+bool block_ipv4;
00db14
+bool block_ipv6;
00db14
+
00db14
 /* add/remove Virtual IP addresses */
00db14
 static bool
00db14
 vrrp_handle_ipaddress(vrrp_t * vrrp, int cmd, int type)
00db14
@@ -124,7 +128,11 @@ vrrp_handle_accept_mode(vrrp_t *vrrp, int cmd, bool force)
00db14
 
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
 		do {
00db14
-			h = iptables_open();
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+			if ((vrrp->family == AF_INET && using_libip4tc) ||
00db14
+			    (vrrp->family == AF_INET6 && using_libip6tc))
00db14
+#endif
00db14
+				h = iptables_open();
00db14
 #endif
00db14
 			/* As accept is false, add iptable rule to drop packets destinated to VIPs and eVIPs */
00db14
 			if (!LIST_ISEMPTY(vrrp->vip))
00db14
@@ -132,7 +140,10 @@ vrrp_handle_accept_mode(vrrp_t *vrrp, int cmd, bool force)
00db14
 			if (!LIST_ISEMPTY(vrrp->evip))
00db14
 				handle_iptable_rule_to_iplist(h, vrrp->evip, cmd, force);
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
-			res = iptables_close(h);
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+			if (h)
00db14
+#endif
00db14
+				res = iptables_close(h);
00db14
 		} while (res == EAGAIN && ++tries < IPTABLES_MAX_TRIES);
00db14
 #endif
00db14
 		vrrp->iptable_rules_set = (cmd == IPADDRESS_ADD);
00db14
@@ -2363,10 +2374,12 @@ vrrp_complete_instance(vrrp_t * vrrp)
00db14
 	if (vrrp->base_priority != VRRP_PRIO_OWNER && !vrrp->accept) {
00db14
 //TODO = we have a problem since SNMP may change accept mode
00db14
 //it can also change priority
00db14
-		if (vrrp->saddr.ss_family == AF_INET)
00db14
-			global_data->block_ipv4 = true;
00db14
+		if (!global_data->vrrp_iptables_inchain[0])
00db14
+			log_message(LOG_INFO, "(%s): Unable to set no_accept mode since iptables chain name unset", vrrp->iname);
00db14
+		else if (vrrp->family == AF_INET)
00db14
+			block_ipv4 = true;
00db14
 		else
00db14
-			global_data->block_ipv6 = true;
00db14
+			block_ipv6 = true;
00db14
 	}
00db14
 	if (!LIST_ISEMPTY(vrrp->vip)) {
00db14
 		for (e = LIST_HEAD(vrrp->vip); e; ELEMENT_NEXT(e)) {
00db14
@@ -2390,7 +2403,6 @@ vrrp_complete_instance(vrrp_t * vrrp)
00db14
 	if (!reload && interface_already_existed) {
00db14
 // TODO - consider reload
00db14
 		vrrp->vipset = true;	/* Set to force address removal */
00db14
-		vrrp_restore_interface(vrrp, false, true);
00db14
 	}
00db14
 
00db14
 	/* See if we need to set promote_secondaries */
00db14
@@ -2452,12 +2464,6 @@ vrrp_complete_init(void)
00db14
 	if (global_data->vrrp_garp_interval || global_data->vrrp_gna_interval)
00db14
 		set_default_garp_delay();
00db14
 
00db14
-#ifdef _HAVE_LIBIPTC_
00db14
-	/* Make sure we don't have any old iptables/ipsets settings left around */
00db14
-	if (!reload)
00db14
-		iptables_cleanup();
00db14
-#endif
00db14
-
00db14
 	/* Mark any scripts as insecure */
00db14
 	check_vrrp_script_security();
00db14
 
00db14
@@ -2623,6 +2629,18 @@ vrrp_complete_init(void)
00db14
 	return true;
00db14
 }
00db14
 
00db14
+void vrrp_restore_interfaces_startup(void)
00db14
+{
00db14
+	element e;
00db14
+	vrrp_t *vrrp;
00db14
+
00db14
+	for (e = LIST_HEAD(vrrp_data->vrrp); e; ELEMENT_NEXT(e)) {
00db14
+		vrrp = ELEMENT_DATA(e);
00db14
+		if (vrrp->vipset)
00db14
+			vrrp_restore_interface(vrrp, false, true);
00db14
+	}
00db14
+}
00db14
+
00db14
 /* Try to find a VRRP instance */
00db14
 static vrrp_t *
00db14
 vrrp_exist(vrrp_t *old_vrrp)
00db14
@@ -2690,12 +2708,19 @@ clear_diff_vrrp_vip(vrrp_t *old_vrrp, vrrp_t *vrrp)
00db14
 
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
 	do {
00db14
-		h = iptables_open();
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		if ((vrrp->family == AF_INET && using_libip4tc) ||
00db14
+		    (vrrp->family == AF_INET6 && using_libip6tc))
00db14
+#endif
00db14
+			h = iptables_open();
00db14
 #endif
00db14
 		clear_diff_vrrp_vip_list(vrrp, h, old_vrrp->vip, vrrp->vip);
00db14
 		clear_diff_vrrp_vip_list(vrrp, h, old_vrrp->evip, vrrp->evip);
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
-		res = iptables_close(h);
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		if (h)
00db14
+#endif
00db14
+			res = iptables_close(h);
00db14
 	} while (res == EAGAIN && ++tries < IPTABLES_MAX_TRIES);
00db14
 #endif
00db14
 }
00db14
diff --git a/keepalived/vrrp/vrrp_daemon.c b/keepalived/vrrp/vrrp_daemon.c
00db14
index 1c2f9e89..1e9282a7 100644
00db14
--- a/keepalived/vrrp/vrrp_daemon.c
00db14
+++ b/keepalived/vrrp/vrrp_daemon.c
00db14
@@ -202,8 +202,6 @@ start_vrrp(void)
00db14
 	if (global_data->vrrp_no_swap)
00db14
 		set_process_dont_swap(4096);	/* guess a stack size to reserve */
00db14
 
00db14
-	iptables_init();
00db14
-
00db14
 #ifdef _WITH_SNMP_
00db14
 	if (!reload && (global_data->enable_snmp_keepalived || global_data->enable_snmp_rfcv2 || global_data->enable_snmp_rfcv3)) {
00db14
 		vrrp_snmp_agent_init(global_data->snmp_socket);
00db14
@@ -266,10 +264,21 @@ start_vrrp(void)
00db14
 		return;
00db14
 	}
00db14
 
00db14
+	/* We need to delay the init of iptables to after vrrp_complete_init()
00db14
+	 * has been called so we know whether we want IPv4 and/or IPv6 */
00db14
+	iptables_init();
00db14
+
00db14
+	/* Make sure we don't have any old iptables/ipsets settings left around */
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
+	if (!reload)
00db14
+		iptables_cleanup();
00db14
+
00db14
 	iptables_startup(reload);
00db14
 #endif
00db14
 
00db14
+	if (!reload)
00db14
+		vrrp_restore_interfaces_startup();
00db14
+
00db14
 	/* clear_diff_vrrp must be called after vrrp_complete_init, since the latter
00db14
 	 * sets ifa_index on the addresses, which is used for the address comparison */
00db14
 	if (reload)
00db14
diff --git a/keepalived/vrrp/vrrp_ipaddress.c b/keepalived/vrrp/vrrp_ipaddress.c
00db14
index eb332e72..c72ea736 100644
00db14
--- a/keepalived/vrrp/vrrp_ipaddress.c
00db14
+++ b/keepalived/vrrp/vrrp_ipaddress.c
00db14
@@ -27,6 +27,7 @@
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
 #include "vrrp_iptables.h"
00db14
 #endif
00db14
+#include "vrrp.h"
00db14
 #include "keepalived_netlink.h"
00db14
 #include "vrrp_data.h"
00db14
 #include "logger.h"
00db14
@@ -38,11 +39,16 @@
00db14
 #if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
00db14
 #include "utils.h"
00db14
 #endif
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+#include "vrrp_iptables.h"
00db14
+#endif
00db14
 
00db14
 #define INFINITY_LIFE_TIME      0xFFFFFFFF
00db14
 
00db14
-bool iptables_cmd_available = true;
00db14
-bool ip6tables_cmd_available = true;
00db14
+#if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
00db14
+static bool iptables_cmd_available;
00db14
+static bool ip6tables_cmd_available;
00db14
+#endif
00db14
 
00db14
 char *
00db14
 ipaddresstos(char *buf, ip_address_t *ipaddress)
00db14
@@ -250,9 +256,6 @@ handle_iptable_rule_to_vip_cmd(ip_address_t *ipaddress, int cmd, bool force)
00db14
 	char *addr_str;
00db14
 	char *ifname = NULL;
00db14
 
00db14
-	if (global_data->vrrp_iptables_inchain[0] == '\0')
00db14
-		return;
00db14
-
00db14
 	if (IP_IS6(ipaddress)) {
00db14
 		if (!ip6tables_cmd_available)
00db14
 			return;
00db14
@@ -316,9 +319,18 @@ handle_iptable_rule_to_vip(ip_address_t *ipaddr, int cmd,
00db14
 #endif
00db14
 												   bool force)
00db14
 {
00db14
+	if (IP_IS6(ipaddr)) {
00db14
+		if (!block_ipv6)
00db14
+			return;
00db14
+	} else {
00db14
+		if (!block_ipv4)
00db14
+			return;
00db14
+	}
00db14
+
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
-	if (using_libiptc)
00db14
+	if ((IP_IS6(ipaddr) && using_libip6tc) ||
00db14
+	    (!IP_IS6(ipaddr) && using_libip4tc))
00db14
 #endif
00db14
 	{
00db14
 		handle_iptable_rule_to_vip_lib(ipaddr, cmd, h, force);
00db14
@@ -612,31 +624,122 @@ clear_diff_saddresses(void)
00db14
 	clear_diff_address(NULL, old_vrrp_data->static_addresses, vrrp_data->static_addresses);
00db14
 }
00db14
 
00db14
+static void
00db14
+check_chains_exist(void)
00db14
+{
00db14
+#ifdef _HAVE_LIBIPTC_
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+	if (using_libip4tc || using_libip6tc)
00db14
+#endif
00db14
+		check_chains_exist_lib();
00db14
+#endif
00db14
+
00db14
+#if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
00db14
+	char *argv[4];
00db14
+
00db14
+	argv[1] = "-nL";
00db14
+	argv[2] = global_data->vrrp_iptables_inchain;
00db14
+	argv[3] = NULL;
00db14
+
00db14
+	if (block_ipv4)
00db14
+	{
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		if (!using_libip4tc)
00db14
+#endif
00db14
+		{
00db14
+			argv[0] = "iptables";
00db14
+
00db14
+			if (fork_exec(argv) < 0) {
00db14
+				log_message(LOG_INFO, "iptables chain %s does not exist", global_data->vrrp_iptables_inchain);
00db14
+				block_ipv4 = false;
00db14
+			}
00db14
+			else if (global_data->vrrp_iptables_outchain[0]) {
00db14
+				argv[2] = global_data->vrrp_iptables_outchain;
00db14
+				if (fork_exec(argv) < 0) {
00db14
+					log_message(LOG_INFO, "iptables chain %s does not exist", global_data->vrrp_iptables_outchain);
00db14
+					block_ipv4 = false;
00db14
+				}
00db14
+			}
00db14
+		}
00db14
+	}
00db14
+
00db14
+	if (block_ipv6)
00db14
+	{
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		if (!using_libip6tc)
00db14
+#endif
00db14
+		{
00db14
+			argv[0] = "ip6tables";
00db14
+			argv[2] = global_data->vrrp_iptables_inchain;
00db14
+
00db14
+			if (fork_exec(argv) < 0) {
00db14
+				log_message(LOG_INFO, "ip6tables chain %s does not exist", global_data->vrrp_iptables_inchain);
00db14
+				block_ipv6 = false;
00db14
+			}
00db14
+			else if (global_data->vrrp_iptables_outchain[0]) {
00db14
+				argv[2] = global_data->vrrp_iptables_outchain;
00db14
+				if (fork_exec(argv) < 0) {
00db14
+					log_message(LOG_INFO, "ip6tables chain %s does not exist", global_data->vrrp_iptables_outchain);
00db14
+					block_ipv6 = false;
00db14
+				}
00db14
+			}
00db14
+		}
00db14
+	}
00db14
+#endif
00db14
+}
00db14
+
00db14
 void
00db14
 iptables_init(void)
00db14
 {
00db14
-#ifdef _HAVE_LIBIPTC_
00db14
-	if (iptables_init_lib())
00db14
+	if (!block_ipv4 && !block_ipv6) {
00db14
+#ifdef _HAVE_LIBIPSET_
00db14
+		global_data->using_ipsets = false;
00db14
+#endif
00db14
 		return;
00db14
+	}
00db14
+
00db14
+#ifdef _HAVE_LIBIPTC_
00db14
+	iptables_init_lib();
00db14
 #endif
00db14
 
00db14
 #if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
00db14
 	char *argv[3];
00db14
 
00db14
-	/* We can't use libiptc, so check iptables command available */
00db14
-	argv[0] = "iptables";
00db14
+	/* If can't use libiptc, check iptables command available */
00db14
 	argv[1] = "-V";
00db14
 	argv[2] = NULL;
00db14
 
00db14
-	if (fork_exec(argv) < 0) {
00db14
-		log_message(LOG_INFO, "iptables command not available - can't filter IPv4 VIP address destinations");
00db14
-		iptables_cmd_available = false;
00db14
+	if (block_ipv4
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		       && !using_libip4tc
00db14
+#endif
00db14
+				       )
00db14
+	{
00db14
+		argv[0] = "iptables";
00db14
+		if (!(iptables_cmd_available = (fork_exec(argv) >= 0))) {
00db14
+			log_message(LOG_INFO, "iptables command not available - can't filter IPv4 VIP address destinations");
00db14
+			block_ipv4 = false;
00db14
+		}
00db14
 	}
00db14
 
00db14
-	argv[0] = "ip6tables";
00db14
-	if (fork_exec(argv) < 0) {
00db14
-		log_message(LOG_INFO, "ip6tables command not available - can't filter IPv6 VIP address destinations");
00db14
-		ip6tables_cmd_available = false;
00db14
+	if (block_ipv6
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		       && !using_libip6tc
00db14
+#endif
00db14
+					 )
00db14
+	{
00db14
+		argv[0] = "ip6tables";
00db14
+		if (!(ip6tables_cmd_available = (fork_exec(argv) >= 0))) {
00db14
+			log_message(LOG_INFO, "ip6tables command not available - can't filter IPv6 VIP address destinations");
00db14
+			block_ipv6 = false;
00db14
+		}
00db14
 	}
00db14
 #endif
00db14
+
00db14
+	if (block_ipv4 || block_ipv6)
00db14
+		check_chains_exist();
00db14
+#ifdef _HAVE_LIBIPSET_
00db14
+	else
00db14
+		global_data->using_ipsets = false;
00db14
+#endif
00db14
 }
00db14
diff --git a/keepalived/vrrp/vrrp_ipset.c b/keepalived/vrrp/vrrp_ipset.c
00db14
index 194809f0..1c3e4990 100644
00db14
--- a/keepalived/vrrp/vrrp_ipset.c
00db14
+++ b/keepalived/vrrp/vrrp_ipset.c
00db14
@@ -38,12 +38,14 @@
00db14
 #include <linux/types.h>        /* For __beXX types in userland */
00db14
 #include <linux/netfilter.h>    /* For nf_inet_addr */
00db14
 #include <stdint.h>
00db14
+#include <stdio.h>
00db14
 
00db14
 #include "logger.h"
00db14
 #include "global_data.h"
00db14
 #include "vrrp_iptables.h"
00db14
 #include "vrrp_ipset.h"
00db14
 #include "vrrp_ipaddress.h"
00db14
+#include "vrrp.h"
00db14
 #include "main.h"
00db14
 
00db14
 #ifdef _LIBIPSET_DYNAMIC_
00db14
@@ -146,7 +148,7 @@ has_ipset_setname(struct ipset_session* session, const char *setname)
00db14
 	return ipset_cmd1(session, IPSET_CMD_HEADER, 0) == 0;
00db14
 }
00db14
 
00db14
-static int create_sets(const char* addr4, const char* addr6, const char* addr_if6, bool reload)
00db14
+static bool create_sets(const char* addr4, const char* addr6, const char* addr_if6, bool reload)
00db14
 {
00db14
 	struct ipset_session *session;
00db14
 
00db14
@@ -161,12 +163,12 @@ static int create_sets(const char* addr4, const char* addr6, const char* addr_if
00db14
 	if (!reload)
00db14
 		ipset_envopt_parse(session, IPSET_ENV_EXIST, NULL);
00db14
 
00db14
-	if (use_ip4tables) {
00db14
+	if (block_ipv4) {
00db14
 		if (!reload || !has_ipset_setname(session, addr4))
00db14
 			ipset_create(session, addr4, "hash:ip", NFPROTO_IPV4);
00db14
 	}
00db14
 
00db14
-	if (use_ip6tables) {
00db14
+	if (block_ipv6) {
00db14
 		if (!reload || !has_ipset_setname(session, addr6))
00db14
 			ipset_create(session, addr6, "hash:ip", NFPROTO_IPV6);
00db14
 		if (!reload || !has_ipset_setname(session, addr_if6)) {
00db14
@@ -184,6 +186,30 @@ static int create_sets(const char* addr4, const char* addr6, const char* addr_if
00db14
 	return true;
00db14
 }
00db14
 
00db14
+static
00db14
+bool set_match_loaded(void)
00db14
+{
00db14
+	char buf[XT_FUNCTION_MAXNAMELEN+1];
00db14
+	FILE *fp;
00db14
+	bool found = false;
00db14
+
00db14
+	fp = fopen( "/proc/net/ip_tables_matches", "r");
00db14
+	if (!fp)
00db14
+		return false;
00db14
+
00db14
+	while (fgets(buf, sizeof(buf), fp)) {
00db14
+		if ((buf[3] == '\0' || buf[3] == '\n') &&
00db14
+		    !strncmp(buf, "set", 3)) {
00db14
+			found = true;
00db14
+			break;
00db14
+		}
00db14
+	}
00db14
+
00db14
+	fclose(fp);
00db14
+
00db14
+	return found;
00db14
+}
00db14
+
00db14
 bool ipset_init(void)
00db14
 {
00db14
 #ifdef _LIBIPSET_DYNAMIC_
00db14
@@ -213,44 +239,47 @@ bool ipset_init(void)
00db14
 		return false;
00db14
 	}
00db14
 
00db14
-	int err = false;
00db14
-	if (!(ipset_session_init_addr = dlsym(libipset_handle, "ipset_session_init"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_init"); err = true;}
00db14
-	if (!(ipset_session_fini_addr = dlsym(libipset_handle, "ipset_session_fini"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_fini"); err = true;}
00db14
-	if (!(ipset_session_data_addr = dlsym(libipset_handle,"ipset_session_data"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_data"); err = true;}
00db14
-	if (!(ipset_session_error_addr = dlsym(libipset_handle,"ipset_session_error"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_error"); err = true;}
00db14
-	if (!(ipset_envopt_parse_addr = dlsym(libipset_handle,"ipset_envopt_parse"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_envopt_parse"); err = true;}
00db14
-	if (!(ipset_type_get_addr = dlsym(libipset_handle,"ipset_type_get"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_type_get"); err = true;}
00db14
-	if (!(ipset_data_set_addr = dlsym(libipset_handle,"ipset_data_set"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_data_set"); err = true;}
00db14
-	if (!(ipset_cmd_addr = dlsym(libipset_handle,"ipset_cmd"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_cmd"); err = true;}
00db14
-	if (!(ipset_load_types_addr = dlsym(libipset_handle,"ipset_load_types"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_load_types"); err = true;}
00db14
-	if (err) {
00db14
-		log_message(LOG_INFO, "Failed to dynamic link an ipset function");
00db14
+	if (!(ipset_session_init_addr = dlsym(libipset_handle, "ipset_session_init")) ||
00db14
+	    !(ipset_session_fini_addr = dlsym(libipset_handle, "ipset_session_fini")) ||
00db14
+	    !(ipset_session_data_addr = dlsym(libipset_handle,"ipset_session_data")) ||
00db14
+	    !(ipset_session_error_addr = dlsym(libipset_handle,"ipset_session_error")) ||
00db14
+	    !(ipset_envopt_parse_addr = dlsym(libipset_handle,"ipset_envopt_parse")) ||
00db14
+	    !(ipset_type_get_addr = dlsym(libipset_handle,"ipset_type_get")) ||
00db14
+	    !(ipset_data_set_addr = dlsym(libipset_handle,"ipset_data_set")) ||
00db14
+	    !(ipset_cmd_addr = dlsym(libipset_handle,"ipset_cmd")) ||
00db14
+	    !(ipset_load_types_addr = dlsym(libipset_handle,"ipset_load_types"))) {
00db14
+		log_message(LOG_INFO, "Failed to dynamic link an ipset function - %s", dlerror());
00db14
 		return false;
00db14
 	}
00db14
 #endif
00db14
 
00db14
 	ipset_load_types();
00db14
 
00db14
-	if (!load_xtables_module("xt_set", "ipsets"))
00db14
+	if (!set_match_loaded() && !load_xtables_module("xt_set", "ipsets")) {
00db14
+		log_message(LOG_INFO, "Unable to load module xt_set - not using ipsets");
00db14
 		return false;
00db14
+	}
00db14
 
00db14
 	return true;
00db14
 }
00db14
 
00db14
-int remove_ipsets(void)
00db14
+bool remove_ipsets(void)
00db14
 {
00db14
 	struct ipset_session *session;
00db14
 
00db14
+	if (!global_data->using_ipsets)
00db14
+		return true;
00db14
+
00db14
 	session = ipset_session_init(printf);
00db14
 	if (!session) {
00db14
 		log_message(LOG_INFO, "Cannot initialize ipset session.");
00db14
 		return false;
00db14
 	}
00db14
 
00db14
-	if (use_ip4tables)
00db14
+	if (block_ipv4)
00db14
 		ipset_destroy(session, global_data->vrrp_ipset_address);
00db14
 
00db14
-	if (use_ip6tables) {
00db14
+	if (block_ipv6) {
00db14
 		ipset_destroy(session, global_data->vrrp_ipset_address6);
00db14
 		ipset_destroy(session, global_data->vrrp_ipset_address_iface6);
00db14
 	}
00db14
@@ -260,7 +289,7 @@ int remove_ipsets(void)
00db14
 	return true;
00db14
 }
00db14
 
00db14
-int add_ipsets(bool reload)
00db14
+bool add_ipsets(bool reload)
00db14
 {
00db14
 	return create_sets(global_data->vrrp_ipset_address, global_data->vrrp_ipset_address6, global_data->vrrp_ipset_address_iface6, reload);
00db14
 }
00db14
@@ -281,12 +310,12 @@ void ipset_entry(struct ipset_session* session, int cmd, const ip_address_t* add
00db14
 	char *iface = NULL;
00db14
 
00db14
 	if (addr->ifa.ifa_family == AF_INET) {
00db14
-		if (!use_ip4tables)
00db14
+		if (!block_ipv4)
00db14
 			return;
00db14
 		set = global_data->vrrp_ipset_address;
00db14
 	}
00db14
 	else if (IN6_IS_ADDR_LINKLOCAL(&addr->u.sin6_addr)) {
00db14
-		if (!use_ip6tables)
00db14
+		if (!block_ipv6)
00db14
 			return;
00db14
 
00db14
 		set = global_data->vrrp_ipset_address_iface6;
00db14
diff --git a/keepalived/vrrp/vrrp_iptables.c b/keepalived/vrrp/vrrp_iptables.c
00db14
index 2c218cac..60ff6c8c 100644
00db14
--- a/keepalived/vrrp/vrrp_iptables.c
00db14
+++ b/keepalived/vrrp/vrrp_iptables.c
00db14
@@ -59,6 +59,10 @@
00db14
 #include <xtables.h>
00db14
 #include <libipset/linux_ip_set.h>
00db14
 #endif
00db14
+#include <sys/stat.h>
00db14
+#include <sys/vfs.h>
00db14
+#include <linux/magic.h>
00db14
+#include <stdbool.h>
00db14
 
00db14
 #include "vrrp_iptables.h"
00db14
 #include "vrrp_iptables_calls.h"
00db14
@@ -81,10 +85,9 @@ struct ipt_handle {
00db14
 
00db14
 /* If the chains don't exist, or modules not loaded, we can't use iptables/ip6tables */
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
-bool using_libiptc = true;
00db14
+bool using_libip4tc = false;
00db14
+bool using_libip6tc = false;
00db14
 #endif
00db14
-bool use_ip4tables = true;
00db14
-bool use_ip6tables = true;
00db14
 
00db14
 #ifdef _HAVE_LIBIPSET_
00db14
 static
00db14
@@ -105,10 +108,13 @@ void add_del_rules(int cmd, bool ignore_errors)
00db14
 	struct iptc_handle *h4;
00db14
 	struct ip6tc_handle *h6;
00db14
 
00db14
-	if (use_ip4tables &&
00db14
-	    global_data->block_ipv4 &&
00db14
+	if (block_ipv4 &&
00db14
 	    (global_data->vrrp_iptables_inchain[0] ||
00db14
-	     global_data->vrrp_iptables_outchain[0])) {
00db14
+	     global_data->vrrp_iptables_outchain[0])
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+	    && using_libip4tc
00db14
+#endif
00db14
+			      ) {
00db14
 		if ((h4 = ip4tables_open("filter"))) {
00db14
 			if (global_data->vrrp_iptables_inchain[0])
00db14
 				ip4tables_add_rules(h4, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_DROP, global_data->vrrp_ipset_address, IPPROTO_NONE, 0, cmd, ignore_errors);
00db14
@@ -118,10 +124,13 @@ void add_del_rules(int cmd, bool ignore_errors)
00db14
 		}
00db14
 	}
00db14
 
00db14
-	if (use_ip6tables &&
00db14
-	    global_data->block_ipv6 &&
00db14
+	if (block_ipv6 &&
00db14
 	    (global_data->vrrp_iptables_inchain[0] ||
00db14
-	     global_data->vrrp_iptables_outchain[0])) {
00db14
+	     global_data->vrrp_iptables_outchain[0])
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+	    && using_libip6tc
00db14
+#endif
00db14
+			     ) {
00db14
 		if ((h6 = ip6tables_open("filter"))) {
00db14
 			if (global_data->vrrp_iptables_inchain[0]) {
00db14
 #ifdef HAVE_IPSET_ATTR_IFACE
00db14
@@ -185,58 +194,64 @@ int iptables_close(struct ipt_handle* h)
00db14
 	return res;
00db14
 }
00db14
 
00db14
-static void check_chains_exist(void)
00db14
+void check_chains_exist_lib(void)
00db14
 {
00db14
 	struct iptc_handle *h4;
00db14
 	struct ip6tc_handle *h6;
00db14
 
00db14
-	if (global_data->block_ipv4) {
00db14
-		h4 = ip4tables_open("filter");
00db14
-
00db14
-		if (!h4) {
00db14
-			log_message(LOG_INFO, "WARNING, ip_tables module not installed - can't filter IPv4 addresses");
00db14
-			use_ip4tables = false;
00db14
-		} else {
00db14
-			if (global_data->vrrp_iptables_inchain[0] &&
00db14
-			    !ip4tables_is_chain(h4, global_data->vrrp_iptables_inchain)) {
00db14
-				log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
00db14
-				use_ip4tables = false;
00db14
-			}
00db14
-			if (global_data->vrrp_iptables_outchain[0] &&
00db14
-			    !ip4tables_is_chain(h4, global_data->vrrp_iptables_outchain)) {
00db14
-				log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
00db14
-				use_ip4tables = false;
00db14
+	if (block_ipv4) {
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		if (using_libip4tc)
00db14
+#endif
00db14
+		{
00db14
+			h4 = ip4tables_open("filter");
00db14
+
00db14
+			if (!h4) {
00db14
+				log_message(LOG_INFO, "WARNING, ip_tables module not installed - can't filter IPv4 addresses");
00db14
+				block_ipv4 = false;
00db14
+			} else {
00db14
+				if (global_data->vrrp_iptables_inchain[0] &&
00db14
+				    !ip4tables_is_chain(h4, global_data->vrrp_iptables_inchain)) {
00db14
+					log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
00db14
+					block_ipv4 = false;
00db14
+				}
00db14
+				if (global_data->vrrp_iptables_outchain[0] &&
00db14
+				    !ip4tables_is_chain(h4, global_data->vrrp_iptables_outchain)) {
00db14
+					log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
00db14
+					block_ipv4 = false;
00db14
+				}
00db14
+
00db14
+				ip4tables_close(h4, false);
00db14
 			}
00db14
-
00db14
-			ip4tables_close(h4, false);
00db14
 		}
00db14
 	}
00db14
-	else
00db14
-		use_ip4tables = false;
00db14
-
00db14
-	if (global_data->block_ipv6) {
00db14
-		h6 = ip6tables_open("filter");
00db14
-
00db14
-		if (!h6) {
00db14
-			log_message(LOG_INFO, "WARNING, ip6_tables module not installed - can't filter IPv6 addresses");
00db14
-			use_ip6tables = false;
00db14
-		} else {
00db14
-			if (global_data->vrrp_iptables_inchain[0] &&
00db14
-			    !ip6tables_is_chain(h6, global_data->vrrp_iptables_inchain)) {
00db14
-				log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
00db14
-				use_ip6tables = false;
00db14
-			}
00db14
-			if (global_data->vrrp_iptables_outchain[0] &&
00db14
-			    !ip6tables_is_chain(h6, global_data->vrrp_iptables_outchain)) {
00db14
-				log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
00db14
-				use_ip6tables = false;
00db14
-			}
00db14
 
00db14
-			ip6tables_close(h6, false);
00db14
+	if (block_ipv6) {
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+		if (using_libip6tc)
00db14
+#endif
00db14
+		{
00db14
+			h6 = ip6tables_open("filter");
00db14
+
00db14
+			if (!h6) {
00db14
+				log_message(LOG_INFO, "WARNING, ip6_tables module not installed - can't filter IPv6 addresses");
00db14
+				block_ipv6 = false;
00db14
+			} else {
00db14
+				if (global_data->vrrp_iptables_inchain[0] &&
00db14
+				    !ip6tables_is_chain(h6, global_data->vrrp_iptables_inchain)) {
00db14
+					log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
00db14
+					block_ipv6 = false;
00db14
+				}
00db14
+				if (global_data->vrrp_iptables_outchain[0] &&
00db14
+				    !ip6tables_is_chain(h6, global_data->vrrp_iptables_outchain)) {
00db14
+					log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
00db14
+					block_ipv6 = false;
00db14
+				}
00db14
+
00db14
+				ip6tables_close(h6, false);
00db14
+			}
00db14
 		}
00db14
 	}
00db14
-	else
00db14
-		use_ip6tables = false;
00db14
 }
00db14
 
00db14
 static int iptables_entry(struct ipt_handle* h, const char* chain_name, unsigned int rulenum, char* target_name, const ip_address_t* src_ip_address, const ip_address_t* dst_ip_address, const char* in_iface, const char* out_iface, uint16_t protocol, uint8_t type, int cmd, bool force)
00db14
@@ -303,11 +318,8 @@ handle_iptable_rule_to_vip_lib(ip_address_t *ipaddress, int cmd, struct ipt_hand
00db14
 	char *ifname = NULL;
00db14
 
00db14
 	/* If iptables for the address family isn't in use, skip */
00db14
-	if ((ipaddress->ifa.ifa_family == AF_INET && !use_ip4tables) ||
00db14
-	    (ipaddress->ifa.ifa_family == AF_INET6 && !use_ip6tables))
00db14
-		return;
00db14
-
00db14
-	if (global_data->vrrp_iptables_inchain[0] == '\0')
00db14
+	if ((ipaddress->ifa.ifa_family == AF_INET && !block_ipv4) ||
00db14
+	    (ipaddress->ifa.ifa_family == AF_INET6 && !block_ipv6))
00db14
 		return;
00db14
 
00db14
 #ifdef _HAVE_LIBIPSET_
00db14
@@ -343,33 +355,28 @@ handle_iptable_rule_to_vip_lib(ip_address_t *ipaddress, int cmd, struct ipt_hand
00db14
 			IPPROTO_NONE, 0, cmd, force);
00db14
 }
00db14
 
00db14
+#ifdef _HAVE_LIBIPSET_
00db14
 static void
00db14
-iptables_remove_structure(
00db14
-#ifndef _HAVE_LIBIPSET_
00db14
-			  __attribute__((unused))
00db14
-#endif
00db14
-						 bool ignore_errors)
00db14
+iptables_remove_structure(bool ignore_errors)
00db14
 {
00db14
-#ifdef _HAVE_LIBIPSET_
00db14
 	if (global_data->using_ipsets) {
00db14
 		add_del_rules(IPADDRESS_DEL, ignore_errors);
00db14
 		add_del_sets(IPADDRESS_DEL, false);
00db14
 	}
00db14
-#endif
00db14
 }
00db14
+#endif
00db14
 
00db14
 void
00db14
-iptables_startup(bool reload)
00db14
+iptables_startup(
00db14
+#ifndef _HAVE_LIBIPSET_
00db14
+		 __attribute__((unused))
00db14
+#endif
00db14
+					 bool reload)
00db14
 {
00db14
-	if (!reload) {
00db14
-		check_chains_exist();
00db14
 #ifdef _HAVE_LIBIPSET_
00db14
-		if (!use_ip4tables && !use_ip6tables)
00db14
-			global_data->using_ipsets = false;
00db14
-#endif
00db14
-	}
00db14
+	if (!block_ipv4 && !block_ipv6)
00db14
+		global_data->using_ipsets = false;
00db14
 
00db14
-#ifdef _HAVE_LIBIPSET_
00db14
 	if (global_data->using_ipsets) {
00db14
 		add_del_sets(IPADDRESS_ADD, reload);
00db14
 		add_del_rules(IPADDRESS_ADD, false);
00db14
@@ -380,50 +387,94 @@ iptables_startup(bool reload)
00db14
 void
00db14
 iptables_cleanup(void)
00db14
 {
00db14
+#ifdef _HAVE_LIBIPSET_
00db14
 	iptables_remove_structure(true);
00db14
+#endif
00db14
+}
00db14
+
00db14
+/* return true if a given file exists within procfs */
00db14
+/* Taken from iptables code */
00db14
+static
00db14
+bool proc_file_exists(const char *filename)
00db14
+{
00db14
+	struct stat s;
00db14
+	struct statfs f;
00db14
+
00db14
+	if (lstat(filename, &s))
00db14
+		return false;
00db14
+	if (!S_ISREG(s.st_mode))
00db14
+		return false;
00db14
+	if (statfs(filename, &f))
00db14
+		return false;
00db14
+	if (f.f_type != PROC_SUPER_MAGIC)
00db14
+		return false;
00db14
+
00db14
+	return true;
00db14
 }
00db14
 
00db14
-bool
00db14
+void
00db14
 iptables_init_lib(void)
00db14
 {
00db14
-#ifdef _LIBXTABLES_DYNAMIC_
00db14
-	xtables_load();
00db14
+	if (block_ipv4) {
00db14
+		if (!proc_file_exists("/proc/net/ip_tables_names") &&
00db14
+		    !load_xtables_module("ip_tables", "iptables"))
00db14
+#ifdef _LIBIPTC_DYNAMIC_
00db14
+			using_libip4tc = false;
00db14
+		else
00db14
+			using_libip4tc = true;
00db14
+#else
00db14
+		{
00db14
+			block_ipv4 = false;
00db14
+			log_message(LOG_INFO, "Unable to load module ip_tables");
00db14
+		}
00db14
 #endif
00db14
+	}
00db14
 
00db14
+	if (block_ipv6) {
00db14
+		if (!proc_file_exists("/proc/net/ip6_tables_names") &&
00db14
+		    !load_xtables_module("ip6_tables", "ip6tables"))
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
-	if (!iptables_lib_init()) {
00db14
-		using_libiptc = false;
00db14
-#ifdef _LIBXTABLES_DYNAMIC_
00db14
-		xtables_unload();
00db14
+			using_libip6tc = false;
00db14
+		else
00db14
+			using_libip6tc = true;
00db14
+#else
00db14
+		{
00db14
+			block_ipv6 = false;
00db14
+			log_message(LOG_INFO, "Unable to load module ip_tables");
00db14
+		}
00db14
 #endif
00db14
-		return false;
00db14
 	}
00db14
-#endif
00db14
 
00db14
-	if (!load_xtables_module("ip_tables", "iptables")) {
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
-		using_libiptc = false;
00db14
-#endif
00db14
+	if ((!block_ipv4 && !block_ipv6) ||
00db14
+	    (!using_libip4tc && !using_libip6tc) ||
00db14
+	    !iptables_lib_init()) {
00db14
 #ifdef _LIBXTABLES_DYNAMIC_
00db14
 		xtables_unload();
00db14
 #endif
00db14
-		return false;
00db14
+
00db14
+#ifdef _HAVE_LIBIPSET_
00db14
+		global_data->using_ipsets = false;
00db14
+#endif
00db14
+
00db14
+		return;
00db14
 	}
00db14
+#endif
00db14
 
00db14
 #ifdef _HAVE_LIBIPSET_
00db14
-	if (!ipset_init())
00db14
+	if (global_data->using_ipsets && !ipset_init())
00db14
 		global_data->using_ipsets = false;
00db14
 #endif
00db14
 
00db14
 #ifdef _LIBXTABLES_DYNAMIC_
00db14
 	xtables_unload();
00db14
 #endif
00db14
-
00db14
-	return true;
00db14
 }
00db14
 
00db14
 void
00db14
 iptables_fini(void)
00db14
 {
00db14
+#ifdef _HAVE_LIBIPSET_
00db14
 	iptables_remove_structure(false);
00db14
+#endif
00db14
 }
00db14
diff --git a/keepalived/vrrp/vrrp_iptables_calls.c b/keepalived/vrrp/vrrp_iptables_calls.c
00db14
index fb5c98df..ff6b7e6e 100644
00db14
--- a/keepalived/vrrp/vrrp_iptables_calls.c
00db14
+++ b/keepalived/vrrp/vrrp_iptables_calls.c
00db14
@@ -37,22 +37,18 @@
00db14
 #include <xtables.h>
00db14
 #include <libiptc/libiptc.h>
00db14
 #include <libiptc/libip6tc.h>
00db14
-#ifdef _HAVE_LIBIPSET_
00db14
 #include <libipset/linux_ip_set.h>
00db14
 #if defined XT_SET_H_ADD_IP_SET_H_GUARD
00db14
 #define _IP_SET_H
00db14
 #elif defined XT_SET_H_ADD_UAPI_IP_SET_H_GUARD
00db14
 #define _UAPI_IP_SET_H
00db14
 #endif
00db14
+#ifdef _HAVE_LIBIPSET_
00db14
 #include <linux/netfilter/xt_set.h>
00db14
 #endif
00db14
 #include <unistd.h>
00db14
 #include <signal.h>
00db14
 #include <stdint.h>
00db14
-#ifdef _LIBXTABLES_DYNAMIC_
00db14
-#include <sys/types.h>
00db14
-#include <sys/stat.h>
00db14
-#endif
00db14
 
00db14
 #include "vrrp_iptables_calls.h"
00db14
 #include "memory.h"
00db14
@@ -63,6 +59,7 @@
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
 #include "global_data.h"
00db14
 #endif
00db14
+#include "vrrp_iptables.h"
00db14
 
00db14
 /* We sometimes get a resource_busy on iptc_commit. This appears to happen
00db14
  * when someone else is also updating it.
00db14
@@ -406,6 +403,7 @@ int ip6tables_process_entry( struct ip6tc_handle* handle, const char* chain_name
00db14
 
00db14
 #ifdef _HAVE_LIBIPTC_
00db14
 #ifdef _LIBXTABLES_DYNAMIC_ 
00db14
+static
00db14
 bool xtables_load(void)
00db14
 {
00db14
 	if (libxtables_handle)
00db14
@@ -418,7 +416,7 @@ bool xtables_load(void)
00db14
 	}
00db14
 
00db14
 	if (!(xtables_insmod_addr = dlsym(libxtables_handle, "xtables_insmod"))) {
00db14
-		log_message(LOG_INFO, "Failed to dynamic link xtables_insmod");
00db14
+		log_message(LOG_INFO, "Failed to dynamic link xtables_insmod - %s", dlerror());
00db14
 		dlclose(libxtables_handle);
00db14
 		libxtables_handle = NULL;
00db14
 
00db14
@@ -438,25 +436,18 @@ void xtables_unload(void)
00db14
 }
00db14
 #endif
00db14
 
00db14
-bool load_xtables_module(const char *module,
00db14
+bool
00db14
+load_xtables_module(const char *module,
00db14
 #ifndef _LIBXTABLES_DYNAMIC_
00db14
-					    __attribute__((unused))
00db14
+					__attribute__((unused))
00db14
 #endif
00db14
-								    const char *function)
00db14
+								const char *function)
00db14
 {
00db14
 	struct sigaction act, old_act;
00db14
 	bool res = true;
00db14
-#ifdef _LIBXTABLES_DYNAMIC_
00db14
-	struct stat stat_buf;
00db14
-	char module_path[32] = "/sys/module/";
00db14
-
00db14
-	if (!libxtables_handle) {
00db14
-		/* See if the module is loaded anyway */
00db14
-		strcat(module_path, module);
00db14
-		if (!stat(module_path, &stat_buf) &&
00db14
-		    (stat_buf.st_mode & S_IFDIR))
00db14
-			return true;
00db14
 
00db14
+#ifdef _LIBXTABLES_DYNAMIC_
00db14
+	if (!libxtables_handle && !xtables_load()) {
00db14
 		log_message(LOG_INFO, "Module %s cannot be loaded; not using %s", module, function);
00db14
 		return false;
00db14
 	}
00db14
@@ -882,47 +873,50 @@ int ip6tables_add_rules(struct ip6tc_handle* handle, const char* chain_name, uns
00db14
 #ifdef _LIBIPTC_DYNAMIC_
00db14
 bool iptables_lib_init(void)
00db14
 {
00db14
-	if (libip4tc_handle)
00db14
-		return true;
00db14
-
00db14
-	/* Attempt to open the ip4tc library */
00db14
-	if (!(libip4tc_handle = dlopen("libip4tc.so", RTLD_NOW)) &&
00db14
-	    !(libip4tc_handle = dlopen(IP4TC_LIB_NAME, RTLD_NOW))) {
00db14
-		log_message(LOG_INFO, "Unable to load ip4tc library - %s", dlerror());
00db14
-		return false;
00db14
-	}
00db14
-
00db14
-	if (!(iptc_init_addr = dlsym(libip4tc_handle, "iptc_init")) ||
00db14
-	    !(iptc_free_addr = dlsym(libip4tc_handle, "iptc_free")) ||
00db14
-	    !(iptc_is_chain_addr = dlsym(libip4tc_handle,"iptc_is_chain")) ||
00db14
-	    !(iptc_insert_entry_addr = dlsym(libip4tc_handle,"iptc_insert_entry")) ||
00db14
-	    !(iptc_append_entry_addr = dlsym(libip4tc_handle,"iptc_append_entry")) ||
00db14
-	    !(iptc_delete_entry_addr = dlsym(libip4tc_handle,"iptc_delete_entry")) ||
00db14
-	    !(iptc_commit_addr = dlsym(libip4tc_handle,"iptc_commit")) ||
00db14
-	    !(iptc_strerror_addr = dlsym(libip4tc_handle,"iptc_strerror")))
00db14
-		log_message(LOG_INFO, "Failed to dynamic link an iptc function");
00db14
-
00db14
-	/* Attempt to open the ip6tc library */
00db14
-	if (!(libip6tc_handle = dlopen("libip6tc.so", RTLD_NOW)) &&
00db14
-	    !(libip6tc_handle = dlopen(IP6TC_LIB_NAME, RTLD_NOW))) {
00db14
-		log_message(LOG_INFO, "Unable to load ip6tc library - %s", dlerror());
00db14
-
00db14
-		if (global_data->block_ipv4)
00db14
+	if (!libip4tc_handle && block_ipv4) {
00db14
+		/* Attempt to open the ip4tc library */
00db14
+		if (!(libip4tc_handle = dlopen("libip4tc.so", RTLD_NOW)) &&
00db14
+		    !(libip4tc_handle = dlopen(IP4TC_LIB_NAME, RTLD_NOW))) {
00db14
+			log_message(LOG_INFO, "Unable to load ip4tc library - %s", dlerror());
00db14
+			using_libip4tc = false;
00db14
+		}
00db14
+		else if (!(iptc_init_addr = dlsym(libip4tc_handle, "iptc_init")) ||
00db14
+			 !(iptc_free_addr = dlsym(libip4tc_handle, "iptc_free")) ||
00db14
+			 !(iptc_is_chain_addr = dlsym(libip4tc_handle,"iptc_is_chain")) ||
00db14
+			 !(iptc_insert_entry_addr = dlsym(libip4tc_handle,"iptc_insert_entry")) ||
00db14
+			 !(iptc_append_entry_addr = dlsym(libip4tc_handle,"iptc_append_entry")) ||
00db14
+			 !(iptc_delete_entry_addr = dlsym(libip4tc_handle,"iptc_delete_entry")) ||
00db14
+			 !(iptc_commit_addr = dlsym(libip4tc_handle,"iptc_commit")) ||
00db14
+			 !(iptc_strerror_addr = dlsym(libip4tc_handle,"iptc_strerror"))) {
00db14
+			log_message(LOG_INFO, "Failed to dynamic link an iptc function - %s", dlerror());
00db14
+			using_libip4tc = false;
00db14
 			dlclose(libip4tc_handle);
00db14
-
00db14
-		return false;
00db14
+			libip4tc_handle = NULL;
00db14
+		}
00db14
 	}
00db14
 
00db14
-	if (!(ip6tc_init_addr = dlsym(libip6tc_handle, "ip6tc_init")) ||
00db14
-	    !(ip6tc_free_addr = dlsym(libip6tc_handle, "ip6tc_free")) ||
00db14
-	    !(ip6tc_is_chain_addr = dlsym(libip6tc_handle,"ip6tc_is_chain")) ||
00db14
-	    !(ip6tc_insert_entry_addr = dlsym(libip6tc_handle,"ip6tc_insert_entry")) ||
00db14
-	    !(ip6tc_append_entry_addr = dlsym(libip6tc_handle,"ip6tc_append_entry")) ||
00db14
-	    !(ip6tc_delete_entry_addr = dlsym(libip6tc_handle,"ip6tc_delete_entry")) ||
00db14
-	    !(ip6tc_commit_addr = dlsym(libip6tc_handle,"ip6tc_commit")) ||
00db14
-	    !(ip6tc_strerror_addr = dlsym(libip6tc_handle,"ip6tc_strerror")))
00db14
-		log_message(LOG_INFO, "Failed to dynamic link an ip6tc function");
00db14
+	if (!libip6tc_handle && block_ipv6) {
00db14
+		/* Attempt to open the ip6tc library */
00db14
+		if (!(libip6tc_handle = dlopen("libip6tc.so", RTLD_NOW)) &&
00db14
+		    !(libip6tc_handle = dlopen(IP6TC_LIB_NAME, RTLD_NOW))) {
00db14
+			log_message(LOG_INFO, "Unable to load ip6tc library - %s", dlerror());
00db14
+			using_libip6tc = false;
00db14
+		}
00db14
+		else if (!(ip6tc_init_addr = dlsym(libip6tc_handle, "ip6tc_init")) ||
00db14
+			 !(ip6tc_free_addr = dlsym(libip6tc_handle, "ip6tc_free")) ||
00db14
+			 !(ip6tc_is_chain_addr = dlsym(libip6tc_handle,"ip6tc_is_chain")) ||
00db14
+			 !(ip6tc_insert_entry_addr = dlsym(libip6tc_handle,"ip6tc_insert_entry")) ||
00db14
+			 !(ip6tc_append_entry_addr = dlsym(libip6tc_handle,"ip6tc_append_entry")) ||
00db14
+			 !(ip6tc_delete_entry_addr = dlsym(libip6tc_handle,"ip6tc_delete_entry")) ||
00db14
+			 !(ip6tc_commit_addr = dlsym(libip6tc_handle,"ip6tc_commit")) ||
00db14
+			 !(ip6tc_strerror_addr = dlsym(libip6tc_handle,"ip6tc_strerror"))) {
00db14
+			log_message(LOG_INFO, "Failed to dynamic link an ip6tc function - %s", dlerror());
00db14
+			using_libip6tc = false;
00db14
+			dlclose(libip6tc_handle);
00db14
+			libip6tc_handle = NULL;
00db14
+		}
00db14
+	}
00db14
 
00db14
-	return true;
00db14
+	return libip4tc_handle || libip6tc_handle;
00db14
 }
00db14
 #endif
00db14
-- 
00db14
2.13.5
00db14