diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..56e9f4a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/keepalived-1.3.5.tar.gz
diff --git a/.keepalived.metadata b/.keepalived.metadata
new file mode 100644
index 0000000..d210999
--- /dev/null
+++ b/.keepalived.metadata
@@ -0,0 +1 @@
+5a373d8f5d382700cf53b827947a92a7f4cef148 SOURCES/keepalived-1.3.5.tar.gz
diff --git a/README.md b/README.md
deleted file mode 100644
index 0e7897f..0000000
--- a/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The master branch has no content
- 
-Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6
- 
-If you find this file in a distro specific branch, it means that no content has been checked in yet
diff --git a/SOURCES/bz1419049-fix-unused-variables.patch b/SOURCES/bz1419049-fix-unused-variables.patch
new file mode 100644
index 0000000..17ae5da
--- /dev/null
+++ b/SOURCES/bz1419049-fix-unused-variables.patch
@@ -0,0 +1,32 @@
+From 6e855aa91876e6a41324e870439f2c185318be88 Mon Sep 17 00:00:00 2001
+From: Ryan O'Hara <rohara@redhat.com>
+Date: Wed, 15 Mar 2017 14:46:33 -0500
+Subject: [PATCH] Fix unused variables
+
+---
+ keepalived/vrrp/vrrp_snmp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/keepalived/vrrp/vrrp_snmp.c b/keepalived/vrrp/vrrp_snmp.c
+index 7956f66..84aa00e 100644
+--- a/keepalived/vrrp/vrrp_snmp.c
++++ b/keepalived/vrrp/vrrp_snmp.c
+@@ -1112,13 +1112,13 @@ vrrp_snmp_encap(struct variable *vp, oid *name, size_t *length,
+ {
+ #if HAVE_DECL_LWTUNNEL_ENCAP_MPLS
+ 	static char labels[11*MAX_MPLS_LABELS];
+-#endif
+ 	char *op;
++	unsigned i;
++#endif
+ 	ip_route_t *route;
+ 	nexthop_t *nh;
+ 	encap_t *encap;
+ 	int state = HEADER_STATE_STATIC_ROUTE;
+-	unsigned i;
+ 	static struct counter64 c64;
+ 
+ 	if (vp->name[vp->namelen - 3] == 7) {
+-- 
+2.9.3
+
diff --git a/SOURCES/bz1477563-fix-keepalived_script-user.patch b/SOURCES/bz1477563-fix-keepalived_script-user.patch
new file mode 100644
index 0000000..49ee81a
--- /dev/null
+++ b/SOURCES/bz1477563-fix-keepalived_script-user.patch
@@ -0,0 +1,729 @@
+From 99f31a89d2f5803fe2d6229f2557e72efb3ef95f Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Tue, 28 Mar 2017 09:11:44 +0100
+Subject: [PATCH] Make dynamic flag bool
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+
+Fix releasing malloc'd memory for saved core pattern
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+
+Fix detecting default script uid/gid
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+
+Don't complain about keepalived_script user if not needed
+
+keepalived logged a warning every time if the keepalived_script user
+didn't exist. We only need that warning if there is a script that uses
+the default user, and an alternative defult user isn't specified.
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ doc/keepalived.conf.SYNOPSIS    |  30 +++++----
+ doc/man/man5/keepalived.conf.5  |   4 +-
+ keepalived/check/check_misc.c   |  72 ++++++++++++++++-----
+ keepalived/check/check_parser.c |   9 +--
+ keepalived/core/global_parser.c |  49 +-------------
+ keepalived/core/main.c          |  15 +----
+ keepalived/include/check_misc.h |   2 +-
+ keepalived/include/main.h       |   2 -
+ keepalived/vrrp/vrrp_data.c     |   3 +-
+ keepalived/vrrp/vrrp_parser.c   |  46 ++++++++++---
+ keepalived/vrrp/vrrp_print.c    |   1 +
+ lib/notify.c                    | 140 ++++++++++++++++++++++++++++++++++------
+ lib/notify.h                    |   7 +-
+ 13 files changed, 242 insertions(+), 138 deletions(-)
+
+diff --git a/doc/keepalived.conf.SYNOPSIS b/doc/keepalived.conf.SYNOPSIS
+index 5b1dfb8..90eb83d 100644
+--- a/doc/keepalived.conf.SYNOPSIS
++++ b/doc/keepalived.conf.SYNOPSIS
+@@ -568,12 +568,14 @@ virtual_server group <STRING>      {	# VS group declaration
+         weight <INTEGER>		# weight to use (default: 1)
+         inhibit_on_failure		# Set weight to 0 on healthchecker
+ 					#  failure
+-        notify_up <STRING>|<QUOTED-STRING> # Script to launch when
+-					   #  healthchecker consider service
+-					   #  as up.
+-        notify_down <STRING>|<QUOTED-STRING> # Script to launch when
+-					     #  healthchecker consider service
+-					     #  as down.
++        notify_up <STRING>|<QUOTED-STRING> [username [groupname]]
++					# Script to launch when
++					#  healthchecker consider service
++					#  as up.
++        notify_down <STRING>|<QUOTED-STRING> [username [groupname]]
++					# Script to launch when
++					#  healthchecker consider service
++					#  as down.
+ 
+         HTTP_GET|SSL_GET {		# HTTP and SSL healthcheckers
+             url {			# A set of url to test
+@@ -603,8 +605,8 @@ virtual_server group <STRING>      {	# VS group declaration
+     real_server <IP ADDRESS> <PORT> {	# Idem
+         weight <INTEGER>		# Idem
+         inhibit_on_failure		# Idem
+-        notify_up <STRING>|<QUOTED-STRING> # Idem
+-        notify_down <STRING>|<QUOTED-STRING> # Idem
++        notify_up <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
++        notify_down <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
+ 
+         TCP_CHECK {			# TCP healthchecker
+             connect_ip <IP ADDRESS> # IP address to connect
+@@ -620,8 +622,8 @@ virtual_server group <STRING>      {	# VS group declaration
+     real_server <IP ADDRESS> <PORT> {	# Idem
+         weight <INTEGER>		# Idem
+         inhibit_on_failure		# Idem
+-        notify_up <STRING>|<QUOTED-STRING> # Idem
+-        notify_down <STRING>|<QUOTED-STRING> # Idem
++        notify_up <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
++        notify_down <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
+ 
+         SMTP_CHECK {                   # SMTP healthchecker
+             connect_ip <IP ADDRESS>     # Optional IP address to connect to
+@@ -658,8 +660,8 @@ virtual_server group <STRING>      {	# VS group declaration
+     real_server <IP ADDRESS> <PORT> {	# Idem
+         weight <INTEGER>		# Idem
+         inhibit_on_failure		# Idem
+-        notify_up <STRING>|<QUOTED-STRING> # Idem
+-        notify_down <STRING>|<QUOTED-STRING> # Idem
++        notify_up <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
++        notify_down <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
+ 
+         DNS_CHECK {                     # DNS healthchecker
+             connect_ip <IP ADDRESS>     # Optional IP address to connect to
+@@ -677,8 +679,8 @@ virtual_server group <STRING>      {	# VS group declaration
+     real_server <IP ADDRESS> <PORT> {	# Idem
+         weight <INTEGER>		# Idem
+         inhibit_on_failure		# Idem
+-        notify_up <STRING>|<QUOTED-STRING> # Idem
+-        notify_down <STRING>|<QUOTED-STRING> # Idem
++        notify_up <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
++        notify_down <STRING>|<QUOTED-STRING> [username [groupname]] # Idem
+ 
+         MISC_CHECK {				# MISC healthchecker
+             misc_path <STRING>|<QUOTED-STRING>	# External system script or program
+diff --git a/doc/man/man5/keepalived.conf.5 b/doc/man/man5/keepalived.conf.5
+index 9ce2206..be33063 100644
+--- a/doc/man/man5/keepalived.conf.5
++++ b/doc/man/man5/keepalived.conf.5
+@@ -711,10 +711,10 @@ A virtual_server can be a declaration of one of
+ 
+            # Script to execute when healthchecker
+            # considers service as up.
+-           notify_up <STRING>|<QUOTED-STRING>
++           notify_up <STRING>|<QUOTED-STRING> [username [groupname]]
+            # Script to execute when healthchecker
+            # considers service as down.
+-           notify_down <STRING>|<QUOTED-STRING>
++           notify_down <STRING>|<QUOTED-STRING> [username [groupname]]
+ 
+            uthreshold <INTEGER> # maximum number of connections to server
+            lthreshold <INTEGER> # minimum number of connections to server
+diff --git a/keepalived/check/check_misc.c b/keepalived/check/check_misc.c
+index ccb9b63..a041d81 100644
+--- a/keepalived/check/check_misc.c
++++ b/keepalived/check/check_misc.c
+@@ -44,6 +44,11 @@ static int misc_check_thread(thread_t *);
+ static int misc_check_child_thread(thread_t *);
+ static int misc_check_child_timeout_thread(thread_t *);
+ 
++static bool script_user_set;
++static bool remove_script;
++static misc_checker_t *misck_checker;
++
++
+ /* Configuration stream handling */
+ static void
+ free_misc_check(void *data)
+@@ -70,49 +75,83 @@ dump_misc_check(void *data)
+ static void
+ misc_check_handler(__attribute__((unused)) vector_t *strvec)
+ {
+-	misc_checker_t *misck_checker = (misc_checker_t *) MALLOC(sizeof (misc_checker_t));
+-
+-	misck_checker->uid = default_script_uid;
+-	misck_checker->gid = default_script_gid;
++	misck_checker = (misc_checker_t *) MALLOC(sizeof (misc_checker_t));
+ 
+-	/* queue new checker */
+-	queue_checker(free_misc_check, dump_misc_check, misc_check_thread,
+-		      misck_checker, NULL);
++	script_user_set = false;
+ }
+ 
+ static void
+ misc_path_handler(vector_t *strvec)
+ {
+-	misc_checker_t *misck_checker = CHECKER_GET();
++	if (!misck_checker)
++		return;
++
+ 	misck_checker->path = CHECKER_VALUE_STRING(strvec);
+ }
+ 
+ static void
+ misc_timeout_handler(vector_t *strvec)
+ {
+-	misc_checker_t *misck_checker = CHECKER_GET();
++	if (!misck_checker)
++		return;
++
+ 	misck_checker->timeout = CHECKER_VALUE_UINT(strvec) * TIMER_HZ;
+ }
+ 
+ static void
+ misc_dynamic_handler(__attribute__((unused)) vector_t *strvec)
+ {
+-	misc_checker_t *misck_checker = CHECKER_GET();
+-	misck_checker->dynamic = 1;
++	if (!misck_checker)
++		return;
++
++	misck_checker->dynamic = true;
+ }
+ 
+ static void
+ misc_user_handler(vector_t *strvec)
+ {
+-	misc_checker_t *misck_checker = CHECKER_GET();
++	if (!misck_checker)
++		return;
+ 
+ 	if (vector_size(strvec) < 2) {
+ 		log_message(LOG_INFO, "No user specified for misc checker script %s", misck_checker->path);
+ 		return;
+ 	}
+ 
+-	if (set_script_uid_gid(strvec, 1, &misck_checker->uid, &misck_checker->gid))
+-		log_message(LOG_INFO, "Failed to set uid/gid for misc checker script %s", misck_checker->path);
++	if (set_script_uid_gid(strvec, 1, &misck_checker->uid, &misck_checker->gid)) {
++		log_message(LOG_INFO, "Failed to set uid/gid for misc checker script %s - removing", misck_checker->path);
++		FREE(misck_checker);
++		misck_checker = NULL;
++	}
++	else
++		script_user_set = true;
++}
++
++static void
++misc_end_handler(void)
++{
++	if (!misck_checker)
++		return;
++
++	if (!script_user_set)
++	{
++log_message(LOG_INFO, "remove_script 1 %d", remove_script);
++		if ( set_default_script_user(NULL, NULL, global_data->script_security)) {
++			log_message(LOG_INFO, "Unable to set default user for misc script %s - removing", misck_checker->path);
++			FREE(misck_checker);
++			misck_checker = NULL;
++			return;
++		}
++
++log_message(LOG_INFO, "Setting uid.gid");
++		misck_checker->uid = default_script_uid;
++		misck_checker->gid = default_script_gid;
++	}
++
++	/* queue new checker */
++	queue_checker(free_misc_check, dump_misc_check, misc_check_thread, misck_checker, NULL);
++	misck_checker = NULL;
++log_message(LOG_INFO, "Leaving misc_end_handler");
+ }
+ 
+ void
+@@ -125,6 +164,7 @@ install_misc_check_keyword(void)
+ 	install_keyword("misc_dynamic", &misc_dynamic_handler);
+ 	install_keyword("warmup", &warmup_handler);
+ 	install_keyword("user", &misc_user_handler);
++	install_sublevel_end_handler(&misc_end_handler);
+ 	install_sublevel_end();
+ }
+ 
+@@ -251,13 +291,13 @@ misc_check_child_thread(thread_t * thread)
+ 		int status;
+ 		status = WEXITSTATUS(wait_status);
+ 		if (status == 0 ||
+-		    (misck_checker->dynamic == 1 && status >= 2 && status <= 255)) {
++		    (misck_checker->dynamic && status >= 2 && status <= 255)) {
+ 			/*
+ 			 * The actual weight set when using misc_dynamic is two less than
+ 			 * the exit status returned.  Effective range is 0..253.
+ 			 * Catch legacy case of status being 0 but misc_dynamic being set.
+ 			 */
+-			if (misck_checker->dynamic == 1 && status != 0)
++			if (misck_checker->dynamic && status != 0)
+ 				update_svr_wgt(status - 2, checker->vs,
+ 					       checker->rs, true);
+ 
+diff --git a/keepalived/check/check_parser.c b/keepalived/check/check_parser.c
+index 2adac98..382861c 100644
+--- a/keepalived/check/check_parser.c
++++ b/keepalived/check/check_parser.c
+@@ -322,14 +322,7 @@ inhibit_handler(__attribute__((unused)) vector_t *strvec)
+ static inline notify_script_t*
+ set_check_notify_script(vector_t *strvec)
+ {
+-	notify_script_t *script = notify_script_init(strvec, default_script_uid, default_script_gid);
+-
+-	if (vector_size(strvec) > 2 ) {
+-		if (set_script_uid_gid(strvec, 2, &script->uid, &script->gid))
+-			log_message(LOG_INFO, "Invalid user/group for quorum/notify script %s", script->name);
+-	}
+-
+-	return script;
++	return notify_script_init(strvec, "quorum/notify", global_data->script_security);
+ }
+ static void
+ notify_up_handler(vector_t *strvec)
+diff --git a/keepalived/core/global_parser.c b/keepalived/core/global_parser.c
+index 45d4cfb..a59fbc0 100644
+--- a/keepalived/core/global_parser.c
++++ b/keepalived/core/global_parser.c
+@@ -701,53 +701,6 @@ use_pid_dir_handler(__attribute__((unused)) vector_t *strvec)
+ 	use_pid_dir = true;
+ }
+ 
+-bool
+-set_script_uid_gid(vector_t *strvec, unsigned keyword_offset, uid_t *uid_p, gid_t *gid_p)
+-{
+-	char *username;
+-	char *groupname;
+-	uid_t uid;
+-	gid_t gid;
+-	struct passwd pwd;
+-	struct passwd *pwd_p;
+-	struct group grp;
+-	struct group *grp_p;
+-	int ret;
+-	char buf[getpwnam_buf_len];
+-
+-	username = strvec_slot(strvec, keyword_offset);
+-
+-	if ((ret = getpwnam_r(username, &pwd, buf, sizeof(buf), &pwd_p))) {
+-		log_message(LOG_INFO, "Unable to resolve script username '%s' - ignoring", username);
+-		return true;
+-	}
+-	if (!pwd_p) {
+-		log_message(LOG_INFO, "Script user '%s' does not exist", username);
+-		return true;
+-	}
+-
+-	uid = pwd.pw_uid;
+-	gid = pwd.pw_gid;
+-
+-	if (vector_size(strvec) > keyword_offset + 1) {
+-		groupname = strvec_slot(strvec, keyword_offset + 1);
+-		if ((ret = getgrnam_r(groupname, &grp, buf, sizeof(buf), &grp_p))) {
+-			log_message(LOG_INFO, "Unable to resolve script group name '%s' - ignoring", groupname);
+-			return true;
+-		}
+-		if (!grp_p) {
+-			log_message(LOG_INFO, "Script group '%s' does not exist", groupname);
+-			return true;
+-		}
+-		gid = grp.gr_gid;
+-	}
+-
+-	*uid_p = uid;
+-	*gid_p = gid;
+-
+-	return false;
+-}
+-
+ static void
+ script_user_handler(vector_t *strvec)
+ {
+@@ -756,7 +709,7 @@ script_user_handler(vector_t *strvec)
+ 		return;
+ 	}
+ 
+-	if (set_script_uid_gid(strvec, 1, &default_script_uid, &default_script_gid))
++	if (set_default_script_user(strvec_slot(strvec, 1), vector_size(strvec) > 2 ? strvec_slot(strvec, 2) : NULL, true))
+ 		log_message(LOG_INFO, "Error setting global script uid/gid");
+ }
+ 
+diff --git a/keepalived/core/main.c b/keepalived/core/main.c
+index 55eb263..95bb76a 100644
+--- a/keepalived/core/main.c
++++ b/keepalived/core/main.c
+@@ -119,6 +119,9 @@ free_parent_mallocs_startup(bool am_child)
+ #else
+ 		free(syslog_ident);
+ #endif
++
++		if (orig_core_dump_pattern)
++			FREE_PTR(orig_core_dump_pattern);
+ 	}
+ 
+ 	if (free_main_pidfile) {
+@@ -765,7 +768,6 @@ keepalived_main(int argc, char **argv)
+ 	bool report_stopped = true;
+ 	struct utsname uname_buf;
+ 	char *end;
+-	long buf_len;
+ 
+ 	/* Init debugging level */
+ 	debug = 0;
+@@ -814,17 +816,6 @@ keepalived_main(int argc, char **argv)
+ 
+ 	netlink_set_recv_buf_size();
+ 
+-	set_default_script_user(&default_script_uid, &default_script_gid);
+-
+-	/* Get buffer length needed for getpwnam_r/getgrnam_r */
+-	if ((buf_len = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1)
+-		getpwnam_buf_len = 1024;	/* A safe default if no value is returned */
+-	else
+-		getpwnam_buf_len = (size_t)buf_len;
+-	if ((buf_len = sysconf(_SC_GETGR_R_SIZE_MAX)) != -1 &&
+-	    (size_t)buf_len > getpwnam_buf_len)
+-		getpwnam_buf_len = (size_t)buf_len;
+-
+ 	/* Some functionality depends on kernel version, so get the version here */
+ 	if (uname(&uname_buf))
+ 		log_message(LOG_INFO, "Unable to get uname() information - error %d", errno);
+diff --git a/keepalived/include/check_misc.h b/keepalived/include/check_misc.h
+index ed0d962..ec97149 100644
+--- a/keepalived/include/check_misc.h
++++ b/keepalived/include/check_misc.h
+@@ -36,7 +36,7 @@
+ typedef struct _misc_checker {
+ 	char			*path;
+ 	unsigned long		timeout;
+-	int			dynamic;	/* 0: old-style, 1: exit code from checker affects weight */
++	bool			dynamic;	/* false: old-style, true: exit code from checker affects weight */
+ 	bool			forcing_termination; /* Set if we have sent the process a SIGTERM */
+ 	uid_t			uid;		/* uid for script execution */
+ 	gid_t			gid;		/* gid for script execution */
+diff --git a/keepalived/include/main.h b/keepalived/include/main.h
+index d125566..eebde77 100644
+--- a/keepalived/include/main.h
++++ b/keepalived/include/main.h
+@@ -73,8 +73,6 @@ extern bool namespace_with_ipsets;	/* override for namespaces with ipsets on Lin
+ #endif
+ extern char *instance_name;		/* keepalived instance name */
+ extern bool use_pid_dir;		/* pid files in /var/run/keepalived */
+-extern uid_t default_script_uid;	/* Default user/group for script execution */
+-extern gid_t default_script_gid;
+ extern unsigned os_major;		/* Kernel version */
+ extern unsigned os_minor;
+ extern unsigned os_release;
+diff --git a/keepalived/vrrp/vrrp_data.c b/keepalived/vrrp/vrrp_data.c
+index 76f17a4..b5c59df 100644
+--- a/keepalived/vrrp/vrrp_data.c
++++ b/keepalived/vrrp/vrrp_data.c
+@@ -160,8 +160,7 @@ dump_vscript(void *data)
+ 		str = (vscript->result >= vscript->rise) ? "GOOD" : "BAD";
+ 	}
+ 	log_message(LOG_INFO, "   Status = %s", str);
+-	if (vscript->uid || vscript->gid)
+-		log_message(LOG_INFO, "   Script uid:gid = %d:%d", vscript->uid, vscript->gid);
++	log_message(LOG_INFO, "   Script uid:gid = %d:%d", vscript->uid, vscript->gid);
+ 
+ }
+ 
+diff --git a/keepalived/vrrp/vrrp_parser.c b/keepalived/vrrp/vrrp_parser.c
+index 7a38315..c774dec 100644
+--- a/keepalived/vrrp/vrrp_parser.c
++++ b/keepalived/vrrp/vrrp_parser.c
+@@ -48,6 +48,9 @@
+ #include "bitops.h"
+ #include "notify.h"
+ 
++static bool script_user_set;
++static bool remove_script;
++
+ /* Static addresses handler */
+ static void
+ static_addresses_handler(__attribute__((unused)) vector_t *strvec)
+@@ -120,14 +123,7 @@ vrrp_group_handler(vector_t *strvec)
+ static inline notify_script_t*
+ set_vrrp_notify_script(vector_t *strvec)
+ {
+-	notify_script_t *script = notify_script_init(strvec, default_script_uid, default_script_gid);
+-
+-	if (vector_size(strvec) > 2) {
+-		if (set_script_uid_gid(strvec, 2, &script->uid, &script->gid))
+-			log_message(LOG_INFO, "Invalid user/group for notify script %s", script->name);
+-	}
+-
+-	return script;
++	return notify_script_init(strvec, "notify", global_data->script_security);
+ }
+ 
+ static void
+@@ -680,6 +676,8 @@ static void
+ vrrp_script_handler(vector_t *strvec)
+ {
+ 	alloc_vrrp_script(strvec_slot(strvec, 1));
++	script_user_set = false;
++	remove_script = false;
+ }
+ static void
+ vrrp_vscript_script_handler(vector_t *strvec)
+@@ -731,8 +729,35 @@ static void
+ vrrp_vscript_user_handler(vector_t *strvec)
+ {
+ 	vrrp_script_t *vscript = LIST_TAIL_DATA(vrrp_data->vrrp_script);
+-	if (set_script_uid_gid(strvec, 1, &vscript->uid, &vscript->gid))
+-		log_message(LOG_INFO, "Unable to set uid/gid for script %s", vscript->script);
++	if (set_script_uid_gid(strvec, 1, &vscript->uid, &vscript->gid)) {
++		log_message(LOG_INFO, "Unable to set uid/gid for script %s - disabling", vscript->script);
++		remove_script = true;
++	}
++	else
++		script_user_set = true;
++}
++static void
++vrrp_vscript_end_handler(void)
++{
++	vrrp_script_t *vscript = LIST_TAIL_DATA(vrrp_data->vrrp_script);
++
++	if (script_user_set)
++		return;
++
++	if (!remove_script &&
++	     set_default_script_user(NULL, NULL, global_data->script_security)) {
++		log_message(LOG_INFO, "Unable to set default user for track script %s - removing", vscript->script);
++		remove_script = true;
++	}
++
++	if (remove_script) {
++		free_list_element(vrrp_data->vrrp_script, vrrp_data->vrrp_script->tail);
++		return;
++	}
++
++	vscript->uid = default_script_uid;
++	vscript->gid = default_script_gid;
++
+ }
+ static void
+ vrrp_vscript_init_fail_handler(__attribute__((unused)) vector_t *strvec)
+@@ -964,6 +989,7 @@ init_vrrp_keywords(bool active)
+ 	install_keyword("fall", &vrrp_vscript_fall_handler);
+ 	install_keyword("user", &vrrp_vscript_user_handler);
+ 	install_keyword("init_fail", &vrrp_vscript_init_fail_handler);
++	install_sublevel_end_handler(&vrrp_vscript_end_handler);
+ }
+ 
+ vector_t *
+diff --git a/keepalived/vrrp/vrrp_print.c b/keepalived/vrrp/vrrp_print.c
+index 7adb701..54da044 100644
+--- a/keepalived/vrrp/vrrp_print.c
++++ b/keepalived/vrrp/vrrp_print.c
+@@ -92,6 +92,7 @@ vscript_print(FILE *file, void *data)
+ 	fprintf(file, "   Rise = %d\n", vscript->rise);
+ 	fprintf(file, "   Full = %d\n", vscript->fall);
+ 	fprintf(file, "   Insecure = %s\n", vscript->insecure ? "yes" : "no");
++	fprintf(file, "   uid:gid = %d:%d\n", vscript->uid, vscript->gid);
+ 
+ 	switch (vscript->result) {
+ 	case VRRP_SCRIPT_STATUS_INIT:
+diff --git a/lib/notify.c b/lib/notify.c
+index d92c50d..a8742fe 100644
+--- a/lib/notify.c
++++ b/lib/notify.c
+@@ -44,10 +44,15 @@
+ #include "vector.h"
+ #include "parser.h"
+ 
+-size_t getpwnam_buf_len;				/* Buffer length needed for getpwnam_r/getgrname_r */
+ 
++uid_t default_script_uid;				/* Default user/group for script execution */
++gid_t default_script_gid;
++static bool default_script_uid_set = false;
++static bool default_user_fail = false;			/* Set if failed to set default user,
++							   unless it defaults to root */
+ static char *path;
+ static bool path_is_malloced;
++static size_t getpwnam_buf_len;				/* Buffer length needed for getpwnam_r/getgrname_r */
+ 
+ /* perform a system call */
+ static int
+@@ -565,40 +570,135 @@ check_notify_script_secure(notify_script_t **script_p, bool script_security, boo
+ 	return flags;
+ }
+ 
+-/* The default script user/group is keepalived_script if it exists, or root otherwise */
+-void
+-set_default_script_user(uid_t *uid, gid_t *gid)
++static void
++set_pwnam_buf_len(void)
++{
++	long buf_len;
++
++	/* Get buffer length needed for getpwnam_r/getgrnam_r */
++	if ((buf_len = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1)
++		getpwnam_buf_len = 1024;	/* A safe default if no value is returned */
++	else
++		getpwnam_buf_len = (size_t)buf_len;
++	if ((buf_len = sysconf(_SC_GETGR_R_SIZE_MAX)) != -1 &&
++	    (size_t)buf_len > getpwnam_buf_len)
++		getpwnam_buf_len = (size_t)buf_len;
++}
++
++bool
++set_uid_gid(const char *username, const char *groupname, uid_t *uid_p, gid_t *gid_p, bool default_user)
+ {
+-	char buf[getpwnam_buf_len];
+-	char *default_user_name = "keepalived_script";
++	uid_t uid;
++	gid_t gid;
+ 	struct passwd pwd;
+ 	struct passwd *pwd_p;
++	struct group grp;
++	struct group *grp_p;
++	int ret;
++	bool using_default_default_user = false;
++
++	if (!getpwnam_buf_len)
++		set_pwnam_buf_len();
+ 
+-	if (getpwnam_r(default_user_name, &pwd, buf, sizeof(buf), &pwd_p)) {
+-		log_message(LOG_INFO, "Unable to resolve default script username '%s' - ignoring", default_user_name);
+-		return;
++	{
++		char buf[getpwnam_buf_len];
++
++		if (default_user && !username) {
++			using_default_default_user = true;
++			username = "keepalived_script";
++		}
++
++		if ((ret = getpwnam_r(username, &pwd, buf, sizeof(buf), &pwd_p))) {
++			log_message(LOG_INFO, "Unable to resolve %sscript username '%s' - ignoring", default_user ? "default " : "", username);
++			return true;
++		}
++		if (!pwd_p) {
++			if (using_default_default_user)
++				log_message(LOG_INFO, "WARNING - default user '%s' for script execution does not exist - please create.", username);
++			else
++				log_message(LOG_INFO, "%script user '%s' does not exist", default_user ? "Default s" : "S", username);
++			return true;
++		}
++
++		uid = pwd.pw_uid;
++		gid = pwd.pw_gid;
++
++		if (groupname) {
++			if ((ret = getgrnam_r(groupname, &grp, buf, sizeof(buf), &grp_p))) {
++				log_message(LOG_INFO, "Unable to resolve %sscript group name '%s' - ignoring", default_user ? "default " : "", groupname);
++				return true;
++			}
++			if (!grp_p) {
++				log_message(LOG_INFO, "%script group '%s' does not exist", default_user ? "Default s" : "S", groupname);
++				return true;
++			}
++			gid = grp.gr_gid;
++		}
++
++		*uid_p = uid;
++		*gid_p = gid;
+ 	}
+-	if (!pwd_p) {
+-		/* The username does not exist */
+-		log_message(LOG_INFO, "WARNING - default user '%s' for script execution does not exist - please create.", default_user_name);
+-		return;
++
++	return false;
++}
++
++bool
++set_default_script_user(const char *username, const char *groupname, bool script_security)
++{
++	if (!default_script_uid_set || username) {
++		/* Even if we fail to set it, there is no point in trying again */
++		default_script_uid_set = true;
++
++		if (set_uid_gid(username, groupname, &default_script_uid, &default_script_gid, true)) {
++			if (username || script_security)
++				default_user_fail = true;
++		}
++		else
++			default_user_fail = false;
+ 	}
+ 
+-	*uid = pwd.pw_uid;
+-	*gid = pwd.pw_gid;
++	return default_user_fail;
++}
++
++bool
++set_script_uid_gid(vector_t *strvec, unsigned keyword_offset, uid_t *uid_p, gid_t *gid_p)
++{
++	char *username;
++	char *groupname;
++
++	username = strvec_slot(strvec, keyword_offset);
++	if (vector_size(strvec) > keyword_offset + 1)
++		groupname = strvec_slot(strvec, keyword_offset + 1);
++	else
++		groupname = NULL;
+ 
+-	log_message(LOG_INFO, "Setting default script user to '%s', uid:gid %d:%d", default_user_name, pwd.pw_uid, pwd.pw_gid);
++	return set_uid_gid(username, groupname, uid_p, gid_p, false);
+ }
+ 
+ notify_script_t*
+-notify_script_init(vector_t *strvec, uid_t uid, gid_t gid)
++notify_script_init(vector_t *strvec, const char *type, bool script_security)
+ {
+ 	notify_script_t *script = MALLOC(sizeof(notify_script_t));
+ 
+ 	script->name = set_value(strvec);
+-	script->uid = uid;
+-	script->gid = gid;
++
++	if (vector_size(strvec) > 2) {
++		if (set_script_uid_gid(strvec, 2, &script->uid, &script->gid)) {
++			log_message(LOG_INFO, "Invalid user/group for %s script %s - ignoring", type, script->name);
++			FREE(script);
++			return NULL;
++		}
++        }
++	else {
++		if (set_default_script_user(NULL, NULL, script_security)) {
++			log_message(LOG_INFO, "Failed to set default user for %s script %s - ignoring", type, script->name);
++			FREE(script);
++			return NULL;
++		}
++
++		script->uid = default_script_uid;
++		script->gid = default_script_gid;
++	}
+ 
+ 	return script;
+ }
+-
+diff --git a/lib/notify.h b/lib/notify.h
+index ac07edb..3d092ea 100644
+--- a/lib/notify.h
++++ b/lib/notify.h
+@@ -56,7 +56,8 @@ free_notify_script(notify_script_t **script)
+ }
+ 
+ /* Global variables */
+-extern size_t getpwnam_buf_len;		/* Buffer length needed for getpwnam_r/getgrnam_r */
++extern uid_t default_script_uid;        /* Default user/group for script execution */
++extern gid_t default_script_gid;
+ 
+ /* prototypes */
+ extern int system_call_script(thread_master_t *, int (*) (thread_t *), void *, unsigned long, const char*, uid_t, gid_t);
+@@ -64,7 +65,7 @@ extern int notify_exec(const notify_script_t *);
+ extern void script_killall(thread_master_t *, int);
+ extern int check_script_secure(notify_script_t *, bool, bool);
+ extern int check_notify_script_secure(notify_script_t **, bool, bool);
+-extern void set_default_script_user(uid_t *, gid_t *);
+-extern notify_script_t* notify_script_init(vector_t *, uid_t, gid_t);
++extern bool set_default_script_user(const char *, const char *, bool);
++extern notify_script_t* notify_script_init(vector_t *, const char *, bool);
+ 
+ #endif
+-- 
+2.9.4
+
diff --git a/SOURCES/bz1477572-fix-man-page-vrrp_ipsets.patch b/SOURCES/bz1477572-fix-man-page-vrrp_ipsets.patch
new file mode 100644
index 0000000..55ba6c3
--- /dev/null
+++ b/SOURCES/bz1477572-fix-man-page-vrrp_ipsets.patch
@@ -0,0 +1,29 @@
+From 431ba58daf11771195d0b494b0b0b3655a9b25cd Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Wed, 2 Aug 2017 16:18:32 +0100
+Subject: [PATCH] Fix keepalived.doc(5) man page
+
+Ryan O'Hara identified that 'vrrp_ipset' should be 'vrrp_ipsets'
+in the man page.
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ doc/man/man5/keepalived.conf.5 | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/doc/man/man5/keepalived.conf.5 b/doc/man/man5/keepalived.conf.5
+index 5f044af..c7b9d2e 100644
+--- a/doc/man/man5/keepalived.conf.5
++++ b/doc/man/man5/keepalived.conf.5
+@@ -151,7 +151,7 @@ and
+  # If no names are specified, ipsets will not be used, otherwise any omitted
+  # names will be constructed by adding "_if" and/or "6" to previously specified
+  # names.
+- vrrp_ipset [keepalived [keepalived6 [keepalived_if6]]]
++ vrrp_ipsets [keepalived [keepalived6 [keepalived_if6]]]
+ 
+  # The following enables checking that when in unicast mode, the source
+  # address of a VRRP packet is one of our unicast peers.
+-- 
+2.9.4
+
diff --git a/SOURCES/bz1477587-exclude-mismatch-vips.patch b/SOURCES/bz1477587-exclude-mismatch-vips.patch
new file mode 100644
index 0000000..abbb6c2
--- /dev/null
+++ b/SOURCES/bz1477587-exclude-mismatch-vips.patch
@@ -0,0 +1,38 @@
+From f42914b07166db123b55a4acd31f4a6eb280d0f8 Mon Sep 17 00:00:00 2001
+From: Ryan O'Hara <rohara@redhat.com>
+Date: Mon, 11 Dec 2017 12:36:26 -0600
+Subject: [PATCH] Exclude mixed family VIPs from VRRP advertisements
+
+In previous releases of keepalived, it was allowed to have both IPv5
+and IPv6 addresses in the 'virtual_ipaddress' block. The address count
+in VRRP advertisements would reflect all VIPS, both IPv4 and IPv6, but
+the address list would contain empty addresses for any VIP that did
+not match the VRRP instance family. In VRRPv3 this is not allowed, and
+recent releases will simply ignore any VIP that does not match the
+instance family causing those VIPs to not be created in the interface.
+
+Rather than ignore the VIP of mismatched family, this patch will move
+non-matching VIP to the excluded list causing them to not be included
+in the VRRP advertisements but still create them when in MASTER state.
+---
+ keepalived/vrrp/vrrp_parser.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/keepalived/vrrp/vrrp_parser.c b/keepalived/vrrp/vrrp_parser.c
+index 7a383153..d2cd720a 100644
+--- a/keepalived/vrrp/vrrp_parser.c
++++ b/keepalived/vrrp/vrrp_parser.c
+@@ -641,8 +641,9 @@ vrrp_vip_handler(__attribute__((unused)) vector_t *strvec)
+ 				if (vrrp->family == AF_UNSPEC)
+ 					vrrp->family = address_family;
+ 				else if (address_family != vrrp->family) {
+-					log_message(LOG_INFO, "(%s): address family must match VRRP instance [%s] - ignoring", vrrp->iname, str);
++					log_message(LOG_WARNING, "(%s): address family does not match VRRP instance [%s]", vrrp->iname, str);
+ 					free_list_element(vrrp->vip, vrrp->vip->tail);
++					alloc_vrrp_evip(vec);
+ 				}
+ 			}
+ 
+-- 
+2.14.2
+
diff --git a/SOURCES/bz1508435-load-ip-tables-handling.patch b/SOURCES/bz1508435-load-ip-tables-handling.patch
new file mode 100644
index 0000000..27b82a2
--- /dev/null
+++ b/SOURCES/bz1508435-load-ip-tables-handling.patch
@@ -0,0 +1,1154 @@
+From dd9a0db422716dd9bbc329a6e2f23ee3d55d2008 Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Mon, 27 Mar 2017 11:26:44 +0100
+Subject: [PATCH 1/3] Handle not being able to load ip_tables or ip6_tables
+ modules
+
+When running in a docker container it isn't possible to load kernel
+modules, so we need to cleanly handle a failure to load the modules.
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ keepalived/core/global_data.c            |   2 -
+ keepalived/include/global_data.h         |   2 -
+ keepalived/include/vrrp.h                |   5 +
+ keepalived/include/vrrp_ipset.h          |   4 +-
+ keepalived/include/vrrp_iptables.h       |   7 +-
+ keepalived/include/vrrp_iptables_calls.h |   2 +-
+ keepalived/vrrp/vrrp.c                   |  53 ++++++--
+ keepalived/vrrp/vrrp_daemon.c            |  13 +-
+ keepalived/vrrp/vrrp_ipaddress.c         | 137 ++++++++++++++++---
+ keepalived/vrrp/vrrp_ipset.c             |  73 +++++++---
+ keepalived/vrrp/vrrp_iptables.c          | 225 +++++++++++++++++++------------
+ keepalived/vrrp/vrrp_iptables_calls.c    | 108 +++++++--------
+ 12 files changed, 421 insertions(+), 210 deletions(-)
+
+diff --git a/keepalived/core/global_data.c b/keepalived/core/global_data.c
+index d934f286..21c06c1c 100644
+--- a/keepalived/core/global_data.c
++++ b/keepalived/core/global_data.c
+@@ -98,8 +98,6 @@ set_vrrp_defaults(data_t * data)
+ 	data->vrrp_higher_prio_send_advert = false;
+ 	data->vrrp_version = VRRP_VERSION_2;
+ 	strcpy(data->vrrp_iptables_inchain, "INPUT");
+-	data->block_ipv4 = false;
+-	data->block_ipv6 = false;
+ #ifdef _HAVE_LIBIPSET_
+ 	data->using_ipsets = true;
+ 	strcpy(data->vrrp_ipset_address, "keepalived");
+diff --git a/keepalived/include/global_data.h b/keepalived/include/global_data.h
+index 6547ddac..eea34f75 100644
+--- a/keepalived/include/global_data.h
++++ b/keepalived/include/global_data.h
+@@ -99,8 +99,6 @@ typedef struct _data {
+ 	int				vrrp_version;	/* VRRP version (2 or 3) */
+ 	char				vrrp_iptables_inchain[XT_EXTENSION_MAXNAMELEN];
+ 	char				vrrp_iptables_outchain[XT_EXTENSION_MAXNAMELEN];
+-	bool				block_ipv4;
+-	bool				block_ipv6;
+ #ifdef _HAVE_LIBIPSET_
+ 	bool				using_ipsets;
+ 	char				vrrp_ipset_address[IPSET_MAXNAMELEN];
+diff --git a/keepalived/include/vrrp.h b/keepalived/include/vrrp.h
+index 6e874689..ab757277 100644
+--- a/keepalived/include/vrrp.h
++++ b/keepalived/include/vrrp.h
+@@ -313,6 +313,10 @@ typedef struct _vrrp_t {
+ 
+ #define VRRP_ISUP(V)		(VRRP_IF_ISUP(V) && VRRP_SCRIPT_ISUP(V))
+ 
++/* Global variables */
++extern bool block_ipv4;
++extern bool block_ipv6;
++
+ /* prototypes */
+ extern vrrphdr_t *vrrp_get_header(sa_family_t, char *, unsigned *);
+ extern int open_vrrp_send_socket(sa_family_t, int, ifindex_t, bool);
+@@ -327,6 +331,7 @@ extern void vrrp_state_backup(vrrp_t *, char *, ssize_t);
+ extern void vrrp_state_goto_master(vrrp_t *);
+ extern void vrrp_state_leave_master(vrrp_t *);
+ extern bool vrrp_complete_init(void);
++extern void vrrp_restore_interfaces_startup(void);
+ extern void restore_vrrp_interfaces(void);
+ extern void shutdown_vrrp_instances(void);
+ extern void clear_diff_vrrp(void);
+diff --git a/keepalived/include/vrrp_ipset.h b/keepalived/include/vrrp_ipset.h
+index 9ee1095a..6cc320ef 100644
+--- a/keepalived/include/vrrp_ipset.h
++++ b/keepalived/include/vrrp_ipset.h
+@@ -27,8 +27,8 @@
+ #include <libipset/session.h>
+ #include "vrrp_ipaddress.h"
+ 
+-int add_ipsets(bool);
+-int remove_ipsets(void);
++bool add_ipsets(bool);
++bool remove_ipsets(void);
+ bool has_ipset_setname(struct ipset_session*, const char *);
+ bool ipset_init(void);
+ struct ipset_session* ipset_session_start(void);
+diff --git a/keepalived/include/vrrp_iptables.h b/keepalived/include/vrrp_iptables.h
+index 2a7681b3..dbbd6fe7 100644
+--- a/keepalived/include/vrrp_iptables.h
++++ b/keepalived/include/vrrp_iptables.h
+@@ -37,12 +37,11 @@ struct ipt_handle;
+ #define	IPTABLES_MAX_TRIES	3	/* How many times to try adding/deleting when get EAGAIN */
+ 
+ #ifdef _LIBIPTC_DYNAMIC_
+-extern bool using_libiptc;		/* Set if using libiptc - for dynamic linking */
++extern bool using_libip4tc;		/* Set if using lib4iptc - for dynamic linking */
++extern bool using_libip6tc;		/* Set if using lib4iptc - for dynamic linking */
+ #endif
+-extern bool use_ip4tables;		/* Set if using iptables */
+-extern bool use_ip6tables;		/* Set if using ip6tables */
+ 
+-bool iptables_init_lib(void);
++void iptables_init_lib(void);
+ void iptables_fini(void);
+ void iptables_startup(bool);
+ void iptables_cleanup(void);
+diff --git a/keepalived/include/vrrp_iptables_calls.h b/keepalived/include/vrrp_iptables_calls.h
+index 34052fac..ef4e0183 100644
+--- a/keepalived/include/vrrp_iptables_calls.h
++++ b/keepalived/include/vrrp_iptables_calls.h
+@@ -34,7 +34,6 @@
+ 
+ #ifdef _HAVE_LIBIPTC_
+ #ifdef _LIBXTABLES_DYNAMIC_ 
+-extern bool xtables_load(void);
+ extern void xtables_unload(void);
+ #endif
+ extern bool load_xtables_module(const char *, const char *);
+@@ -50,6 +49,7 @@ extern int ip6tables_is_chain(struct ip6tc_handle* handle, const char* chain_nam
+ 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);
+ 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);
+ 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);
++extern void check_chains_exist_lib(void);
+ #ifdef _LIBIPTC_DYNAMIC_
+ extern bool iptables_lib_init(void);
+ #endif
+diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c
+index 3d2bfe41..38895af8 100644
+--- a/keepalived/vrrp/vrrp.c
++++ b/keepalived/vrrp/vrrp.c
+@@ -72,6 +72,10 @@
+ #include <netinet/ip6.h>
+ #include <stdint.h>
+ 
++/* Set if need to block ip addresses and are able to do so */
++bool block_ipv4;
++bool block_ipv6;
++
+ /* add/remove Virtual IP addresses */
+ static bool
+ vrrp_handle_ipaddress(vrrp_t * vrrp, int cmd, int type)
+@@ -124,7 +128,11 @@ vrrp_handle_accept_mode(vrrp_t *vrrp, int cmd, bool force)
+ 
+ #ifdef _HAVE_LIBIPTC_
+ 		do {
+-			h = iptables_open();
++#ifdef _LIBIPTC_DYNAMIC_
++			if ((vrrp->family == AF_INET && using_libip4tc) ||
++			    (vrrp->family == AF_INET6 && using_libip6tc))
++#endif
++				h = iptables_open();
+ #endif
+ 			/* As accept is false, add iptable rule to drop packets destinated to VIPs and eVIPs */
+ 			if (!LIST_ISEMPTY(vrrp->vip))
+@@ -132,7 +140,10 @@ vrrp_handle_accept_mode(vrrp_t *vrrp, int cmd, bool force)
+ 			if (!LIST_ISEMPTY(vrrp->evip))
+ 				handle_iptable_rule_to_iplist(h, vrrp->evip, cmd, force);
+ #ifdef _HAVE_LIBIPTC_
+-			res = iptables_close(h);
++#ifdef _LIBIPTC_DYNAMIC_
++			if (h)
++#endif
++				res = iptables_close(h);
+ 		} while (res == EAGAIN && ++tries < IPTABLES_MAX_TRIES);
+ #endif
+ 		vrrp->iptable_rules_set = (cmd == IPADDRESS_ADD);
+@@ -2363,10 +2374,12 @@ vrrp_complete_instance(vrrp_t * vrrp)
+ 	if (vrrp->base_priority != VRRP_PRIO_OWNER && !vrrp->accept) {
+ //TODO = we have a problem since SNMP may change accept mode
+ //it can also change priority
+-		if (vrrp->saddr.ss_family == AF_INET)
+-			global_data->block_ipv4 = true;
++		if (!global_data->vrrp_iptables_inchain[0])
++			log_message(LOG_INFO, "(%s): Unable to set no_accept mode since iptables chain name unset", vrrp->iname);
++		else if (vrrp->family == AF_INET)
++			block_ipv4 = true;
+ 		else
+-			global_data->block_ipv6 = true;
++			block_ipv6 = true;
+ 	}
+ 	if (!LIST_ISEMPTY(vrrp->vip)) {
+ 		for (e = LIST_HEAD(vrrp->vip); e; ELEMENT_NEXT(e)) {
+@@ -2390,7 +2403,6 @@ vrrp_complete_instance(vrrp_t * vrrp)
+ 	if (!reload && interface_already_existed) {
+ // TODO - consider reload
+ 		vrrp->vipset = true;	/* Set to force address removal */
+-		vrrp_restore_interface(vrrp, false, true);
+ 	}
+ 
+ 	/* See if we need to set promote_secondaries */
+@@ -2452,12 +2464,6 @@ vrrp_complete_init(void)
+ 	if (global_data->vrrp_garp_interval || global_data->vrrp_gna_interval)
+ 		set_default_garp_delay();
+ 
+-#ifdef _HAVE_LIBIPTC_
+-	/* Make sure we don't have any old iptables/ipsets settings left around */
+-	if (!reload)
+-		iptables_cleanup();
+-#endif
+-
+ 	/* Mark any scripts as insecure */
+ 	check_vrrp_script_security();
+ 
+@@ -2623,6 +2629,18 @@ vrrp_complete_init(void)
+ 	return true;
+ }
+ 
++void vrrp_restore_interfaces_startup(void)
++{
++	element e;
++	vrrp_t *vrrp;
++
++	for (e = LIST_HEAD(vrrp_data->vrrp); e; ELEMENT_NEXT(e)) {
++		vrrp = ELEMENT_DATA(e);
++		if (vrrp->vipset)
++			vrrp_restore_interface(vrrp, false, true);
++	}
++}
++
+ /* Try to find a VRRP instance */
+ static vrrp_t *
+ vrrp_exist(vrrp_t *old_vrrp)
+@@ -2690,12 +2708,19 @@ clear_diff_vrrp_vip(vrrp_t *old_vrrp, vrrp_t *vrrp)
+ 
+ #ifdef _HAVE_LIBIPTC_
+ 	do {
+-		h = iptables_open();
++#ifdef _LIBIPTC_DYNAMIC_
++		if ((vrrp->family == AF_INET && using_libip4tc) ||
++		    (vrrp->family == AF_INET6 && using_libip6tc))
++#endif
++			h = iptables_open();
+ #endif
+ 		clear_diff_vrrp_vip_list(vrrp, h, old_vrrp->vip, vrrp->vip);
+ 		clear_diff_vrrp_vip_list(vrrp, h, old_vrrp->evip, vrrp->evip);
+ #ifdef _HAVE_LIBIPTC_
+-		res = iptables_close(h);
++#ifdef _LIBIPTC_DYNAMIC_
++		if (h)
++#endif
++			res = iptables_close(h);
+ 	} while (res == EAGAIN && ++tries < IPTABLES_MAX_TRIES);
+ #endif
+ }
+diff --git a/keepalived/vrrp/vrrp_daemon.c b/keepalived/vrrp/vrrp_daemon.c
+index 1c2f9e89..1e9282a7 100644
+--- a/keepalived/vrrp/vrrp_daemon.c
++++ b/keepalived/vrrp/vrrp_daemon.c
+@@ -202,8 +202,6 @@ start_vrrp(void)
+ 	if (global_data->vrrp_no_swap)
+ 		set_process_dont_swap(4096);	/* guess a stack size to reserve */
+ 
+-	iptables_init();
+-
+ #ifdef _WITH_SNMP_
+ 	if (!reload && (global_data->enable_snmp_keepalived || global_data->enable_snmp_rfcv2 || global_data->enable_snmp_rfcv3)) {
+ 		vrrp_snmp_agent_init(global_data->snmp_socket);
+@@ -266,10 +264,21 @@ start_vrrp(void)
+ 		return;
+ 	}
+ 
++	/* We need to delay the init of iptables to after vrrp_complete_init()
++	 * has been called so we know whether we want IPv4 and/or IPv6 */
++	iptables_init();
++
++	/* Make sure we don't have any old iptables/ipsets settings left around */
+ #ifdef _HAVE_LIBIPTC_
++	if (!reload)
++		iptables_cleanup();
++
+ 	iptables_startup(reload);
+ #endif
+ 
++	if (!reload)
++		vrrp_restore_interfaces_startup();
++
+ 	/* clear_diff_vrrp must be called after vrrp_complete_init, since the latter
+ 	 * sets ifa_index on the addresses, which is used for the address comparison */
+ 	if (reload)
+diff --git a/keepalived/vrrp/vrrp_ipaddress.c b/keepalived/vrrp/vrrp_ipaddress.c
+index eb332e72..c72ea736 100644
+--- a/keepalived/vrrp/vrrp_ipaddress.c
++++ b/keepalived/vrrp/vrrp_ipaddress.c
+@@ -27,6 +27,7 @@
+ #ifdef _HAVE_LIBIPTC_
+ #include "vrrp_iptables.h"
+ #endif
++#include "vrrp.h"
+ #include "keepalived_netlink.h"
+ #include "vrrp_data.h"
+ #include "logger.h"
+@@ -38,11 +39,16 @@
+ #if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
+ #include "utils.h"
+ #endif
++#ifdef _LIBIPTC_DYNAMIC_
++#include "vrrp_iptables.h"
++#endif
+ 
+ #define INFINITY_LIFE_TIME      0xFFFFFFFF
+ 
+-bool iptables_cmd_available = true;
+-bool ip6tables_cmd_available = true;
++#if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
++static bool iptables_cmd_available;
++static bool ip6tables_cmd_available;
++#endif
+ 
+ char *
+ ipaddresstos(char *buf, ip_address_t *ipaddress)
+@@ -250,9 +256,6 @@ handle_iptable_rule_to_vip_cmd(ip_address_t *ipaddress, int cmd, bool force)
+ 	char *addr_str;
+ 	char *ifname = NULL;
+ 
+-	if (global_data->vrrp_iptables_inchain[0] == '\0')
+-		return;
+-
+ 	if (IP_IS6(ipaddress)) {
+ 		if (!ip6tables_cmd_available)
+ 			return;
+@@ -316,9 +319,18 @@ handle_iptable_rule_to_vip(ip_address_t *ipaddr, int cmd,
+ #endif
+ 												   bool force)
+ {
++	if (IP_IS6(ipaddr)) {
++		if (!block_ipv6)
++			return;
++	} else {
++		if (!block_ipv4)
++			return;
++	}
++
+ #ifdef _HAVE_LIBIPTC_
+ #ifdef _LIBIPTC_DYNAMIC_
+-	if (using_libiptc)
++	if ((IP_IS6(ipaddr) && using_libip6tc) ||
++	    (!IP_IS6(ipaddr) && using_libip4tc))
+ #endif
+ 	{
+ 		handle_iptable_rule_to_vip_lib(ipaddr, cmd, h, force);
+@@ -612,31 +624,122 @@ clear_diff_saddresses(void)
+ 	clear_diff_address(NULL, old_vrrp_data->static_addresses, vrrp_data->static_addresses);
+ }
+ 
++static void
++check_chains_exist(void)
++{
++#ifdef _HAVE_LIBIPTC_
++#ifdef _LIBIPTC_DYNAMIC_
++	if (using_libip4tc || using_libip6tc)
++#endif
++		check_chains_exist_lib();
++#endif
++
++#if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
++	char *argv[4];
++
++	argv[1] = "-nL";
++	argv[2] = global_data->vrrp_iptables_inchain;
++	argv[3] = NULL;
++
++	if (block_ipv4)
++	{
++#ifdef _LIBIPTC_DYNAMIC_
++		if (!using_libip4tc)
++#endif
++		{
++			argv[0] = "iptables";
++
++			if (fork_exec(argv) < 0) {
++				log_message(LOG_INFO, "iptables chain %s does not exist", global_data->vrrp_iptables_inchain);
++				block_ipv4 = false;
++			}
++			else if (global_data->vrrp_iptables_outchain[0]) {
++				argv[2] = global_data->vrrp_iptables_outchain;
++				if (fork_exec(argv) < 0) {
++					log_message(LOG_INFO, "iptables chain %s does not exist", global_data->vrrp_iptables_outchain);
++					block_ipv4 = false;
++				}
++			}
++		}
++	}
++
++	if (block_ipv6)
++	{
++#ifdef _LIBIPTC_DYNAMIC_
++		if (!using_libip6tc)
++#endif
++		{
++			argv[0] = "ip6tables";
++			argv[2] = global_data->vrrp_iptables_inchain;
++
++			if (fork_exec(argv) < 0) {
++				log_message(LOG_INFO, "ip6tables chain %s does not exist", global_data->vrrp_iptables_inchain);
++				block_ipv6 = false;
++			}
++			else if (global_data->vrrp_iptables_outchain[0]) {
++				argv[2] = global_data->vrrp_iptables_outchain;
++				if (fork_exec(argv) < 0) {
++					log_message(LOG_INFO, "ip6tables chain %s does not exist", global_data->vrrp_iptables_outchain);
++					block_ipv6 = false;
++				}
++			}
++		}
++	}
++#endif
++}
++
+ void
+ iptables_init(void)
+ {
+-#ifdef _HAVE_LIBIPTC_
+-	if (iptables_init_lib())
++	if (!block_ipv4 && !block_ipv6) {
++#ifdef _HAVE_LIBIPSET_
++		global_data->using_ipsets = false;
++#endif
+ 		return;
++	}
++
++#ifdef _HAVE_LIBIPTC_
++	iptables_init_lib();
+ #endif
+ 
+ #if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_
+ 	char *argv[3];
+ 
+-	/* We can't use libiptc, so check iptables command available */
+-	argv[0] = "iptables";
++	/* If can't use libiptc, check iptables command available */
+ 	argv[1] = "-V";
+ 	argv[2] = NULL;
+ 
+-	if (fork_exec(argv) < 0) {
+-		log_message(LOG_INFO, "iptables command not available - can't filter IPv4 VIP address destinations");
+-		iptables_cmd_available = false;
++	if (block_ipv4
++#ifdef _LIBIPTC_DYNAMIC_
++		       && !using_libip4tc
++#endif
++				       )
++	{
++		argv[0] = "iptables";
++		if (!(iptables_cmd_available = (fork_exec(argv) >= 0))) {
++			log_message(LOG_INFO, "iptables command not available - can't filter IPv4 VIP address destinations");
++			block_ipv4 = false;
++		}
+ 	}
+ 
+-	argv[0] = "ip6tables";
+-	if (fork_exec(argv) < 0) {
+-		log_message(LOG_INFO, "ip6tables command not available - can't filter IPv6 VIP address destinations");
+-		ip6tables_cmd_available = false;
++	if (block_ipv6
++#ifdef _LIBIPTC_DYNAMIC_
++		       && !using_libip6tc
++#endif
++					 )
++	{
++		argv[0] = "ip6tables";
++		if (!(ip6tables_cmd_available = (fork_exec(argv) >= 0))) {
++			log_message(LOG_INFO, "ip6tables command not available - can't filter IPv6 VIP address destinations");
++			block_ipv6 = false;
++		}
+ 	}
+ #endif
++
++	if (block_ipv4 || block_ipv6)
++		check_chains_exist();
++#ifdef _HAVE_LIBIPSET_
++	else
++		global_data->using_ipsets = false;
++#endif
+ }
+diff --git a/keepalived/vrrp/vrrp_ipset.c b/keepalived/vrrp/vrrp_ipset.c
+index 194809f0..1c3e4990 100644
+--- a/keepalived/vrrp/vrrp_ipset.c
++++ b/keepalived/vrrp/vrrp_ipset.c
+@@ -38,12 +38,14 @@
+ #include <linux/types.h>        /* For __beXX types in userland */
+ #include <linux/netfilter.h>    /* For nf_inet_addr */
+ #include <stdint.h>
++#include <stdio.h>
+ 
+ #include "logger.h"
+ #include "global_data.h"
+ #include "vrrp_iptables.h"
+ #include "vrrp_ipset.h"
+ #include "vrrp_ipaddress.h"
++#include "vrrp.h"
+ #include "main.h"
+ 
+ #ifdef _LIBIPSET_DYNAMIC_
+@@ -146,7 +148,7 @@ has_ipset_setname(struct ipset_session* session, const char *setname)
+ 	return ipset_cmd1(session, IPSET_CMD_HEADER, 0) == 0;
+ }
+ 
+-static int create_sets(const char* addr4, const char* addr6, const char* addr_if6, bool reload)
++static bool create_sets(const char* addr4, const char* addr6, const char* addr_if6, bool reload)
+ {
+ 	struct ipset_session *session;
+ 
+@@ -161,12 +163,12 @@ static int create_sets(const char* addr4, const char* addr6, const char* addr_if
+ 	if (!reload)
+ 		ipset_envopt_parse(session, IPSET_ENV_EXIST, NULL);
+ 
+-	if (use_ip4tables) {
++	if (block_ipv4) {
+ 		if (!reload || !has_ipset_setname(session, addr4))
+ 			ipset_create(session, addr4, "hash:ip", NFPROTO_IPV4);
+ 	}
+ 
+-	if (use_ip6tables) {
++	if (block_ipv6) {
+ 		if (!reload || !has_ipset_setname(session, addr6))
+ 			ipset_create(session, addr6, "hash:ip", NFPROTO_IPV6);
+ 		if (!reload || !has_ipset_setname(session, addr_if6)) {
+@@ -184,6 +186,30 @@ static int create_sets(const char* addr4, const char* addr6, const char* addr_if
+ 	return true;
+ }
+ 
++static
++bool set_match_loaded(void)
++{
++	char buf[XT_FUNCTION_MAXNAMELEN+1];
++	FILE *fp;
++	bool found = false;
++
++	fp = fopen( "/proc/net/ip_tables_matches", "r");
++	if (!fp)
++		return false;
++
++	while (fgets(buf, sizeof(buf), fp)) {
++		if ((buf[3] == '\0' || buf[3] == '\n') &&
++		    !strncmp(buf, "set", 3)) {
++			found = true;
++			break;
++		}
++	}
++
++	fclose(fp);
++
++	return found;
++}
++
+ bool ipset_init(void)
+ {
+ #ifdef _LIBIPSET_DYNAMIC_
+@@ -213,44 +239,47 @@ bool ipset_init(void)
+ 		return false;
+ 	}
+ 
+-	int err = false;
+-	if (!(ipset_session_init_addr = dlsym(libipset_handle, "ipset_session_init"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_init"); err = true;}
+-	if (!(ipset_session_fini_addr = dlsym(libipset_handle, "ipset_session_fini"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_fini"); err = true;}
+-	if (!(ipset_session_data_addr = dlsym(libipset_handle,"ipset_session_data"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_data"); err = true;}
+-	if (!(ipset_session_error_addr = dlsym(libipset_handle,"ipset_session_error"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_session_error"); err = true;}
+-	if (!(ipset_envopt_parse_addr = dlsym(libipset_handle,"ipset_envopt_parse"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_envopt_parse"); err = true;}
+-	if (!(ipset_type_get_addr = dlsym(libipset_handle,"ipset_type_get"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_type_get"); err = true;}
+-	if (!(ipset_data_set_addr = dlsym(libipset_handle,"ipset_data_set"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_data_set"); err = true;}
+-	if (!(ipset_cmd_addr = dlsym(libipset_handle,"ipset_cmd"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_cmd"); err = true;}
+-	if (!(ipset_load_types_addr = dlsym(libipset_handle,"ipset_load_types"))) {log_message(LOG_INFO, "Failed to dynamic link ipset_load_types"); err = true;}
+-	if (err) {
+-		log_message(LOG_INFO, "Failed to dynamic link an ipset function");
++	if (!(ipset_session_init_addr = dlsym(libipset_handle, "ipset_session_init")) ||
++	    !(ipset_session_fini_addr = dlsym(libipset_handle, "ipset_session_fini")) ||
++	    !(ipset_session_data_addr = dlsym(libipset_handle,"ipset_session_data")) ||
++	    !(ipset_session_error_addr = dlsym(libipset_handle,"ipset_session_error")) ||
++	    !(ipset_envopt_parse_addr = dlsym(libipset_handle,"ipset_envopt_parse")) ||
++	    !(ipset_type_get_addr = dlsym(libipset_handle,"ipset_type_get")) ||
++	    !(ipset_data_set_addr = dlsym(libipset_handle,"ipset_data_set")) ||
++	    !(ipset_cmd_addr = dlsym(libipset_handle,"ipset_cmd")) ||
++	    !(ipset_load_types_addr = dlsym(libipset_handle,"ipset_load_types"))) {
++		log_message(LOG_INFO, "Failed to dynamic link an ipset function - %s", dlerror());
+ 		return false;
+ 	}
+ #endif
+ 
+ 	ipset_load_types();
+ 
+-	if (!load_xtables_module("xt_set", "ipsets"))
++	if (!set_match_loaded() && !load_xtables_module("xt_set", "ipsets")) {
++		log_message(LOG_INFO, "Unable to load module xt_set - not using ipsets");
+ 		return false;
++	}
+ 
+ 	return true;
+ }
+ 
+-int remove_ipsets(void)
++bool remove_ipsets(void)
+ {
+ 	struct ipset_session *session;
+ 
++	if (!global_data->using_ipsets)
++		return true;
++
+ 	session = ipset_session_init(printf);
+ 	if (!session) {
+ 		log_message(LOG_INFO, "Cannot initialize ipset session.");
+ 		return false;
+ 	}
+ 
+-	if (use_ip4tables)
++	if (block_ipv4)
+ 		ipset_destroy(session, global_data->vrrp_ipset_address);
+ 
+-	if (use_ip6tables) {
++	if (block_ipv6) {
+ 		ipset_destroy(session, global_data->vrrp_ipset_address6);
+ 		ipset_destroy(session, global_data->vrrp_ipset_address_iface6);
+ 	}
+@@ -260,7 +289,7 @@ int remove_ipsets(void)
+ 	return true;
+ }
+ 
+-int add_ipsets(bool reload)
++bool add_ipsets(bool reload)
+ {
+ 	return create_sets(global_data->vrrp_ipset_address, global_data->vrrp_ipset_address6, global_data->vrrp_ipset_address_iface6, reload);
+ }
+@@ -281,12 +310,12 @@ void ipset_entry(struct ipset_session* session, int cmd, const ip_address_t* add
+ 	char *iface = NULL;
+ 
+ 	if (addr->ifa.ifa_family == AF_INET) {
+-		if (!use_ip4tables)
++		if (!block_ipv4)
+ 			return;
+ 		set = global_data->vrrp_ipset_address;
+ 	}
+ 	else if (IN6_IS_ADDR_LINKLOCAL(&addr->u.sin6_addr)) {
+-		if (!use_ip6tables)
++		if (!block_ipv6)
+ 			return;
+ 
+ 		set = global_data->vrrp_ipset_address_iface6;
+diff --git a/keepalived/vrrp/vrrp_iptables.c b/keepalived/vrrp/vrrp_iptables.c
+index 2c218cac..60ff6c8c 100644
+--- a/keepalived/vrrp/vrrp_iptables.c
++++ b/keepalived/vrrp/vrrp_iptables.c
+@@ -59,6 +59,10 @@
+ #include <xtables.h>
+ #include <libipset/linux_ip_set.h>
+ #endif
++#include <sys/stat.h>
++#include <sys/vfs.h>
++#include <linux/magic.h>
++#include <stdbool.h>
+ 
+ #include "vrrp_iptables.h"
+ #include "vrrp_iptables_calls.h"
+@@ -81,10 +85,9 @@ struct ipt_handle {
+ 
+ /* If the chains don't exist, or modules not loaded, we can't use iptables/ip6tables */
+ #ifdef _LIBIPTC_DYNAMIC_
+-bool using_libiptc = true;
++bool using_libip4tc = false;
++bool using_libip6tc = false;
+ #endif
+-bool use_ip4tables = true;
+-bool use_ip6tables = true;
+ 
+ #ifdef _HAVE_LIBIPSET_
+ static
+@@ -105,10 +108,13 @@ void add_del_rules(int cmd, bool ignore_errors)
+ 	struct iptc_handle *h4;
+ 	struct ip6tc_handle *h6;
+ 
+-	if (use_ip4tables &&
+-	    global_data->block_ipv4 &&
++	if (block_ipv4 &&
+ 	    (global_data->vrrp_iptables_inchain[0] ||
+-	     global_data->vrrp_iptables_outchain[0])) {
++	     global_data->vrrp_iptables_outchain[0])
++#ifdef _LIBIPTC_DYNAMIC_
++	    && using_libip4tc
++#endif
++			      ) {
+ 		if ((h4 = ip4tables_open("filter"))) {
+ 			if (global_data->vrrp_iptables_inchain[0])
+ 				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);
+@@ -118,10 +124,13 @@ void add_del_rules(int cmd, bool ignore_errors)
+ 		}
+ 	}
+ 
+-	if (use_ip6tables &&
+-	    global_data->block_ipv6 &&
++	if (block_ipv6 &&
+ 	    (global_data->vrrp_iptables_inchain[0] ||
+-	     global_data->vrrp_iptables_outchain[0])) {
++	     global_data->vrrp_iptables_outchain[0])
++#ifdef _LIBIPTC_DYNAMIC_
++	    && using_libip6tc
++#endif
++			     ) {
+ 		if ((h6 = ip6tables_open("filter"))) {
+ 			if (global_data->vrrp_iptables_inchain[0]) {
+ #ifdef HAVE_IPSET_ATTR_IFACE
+@@ -185,58 +194,64 @@ int iptables_close(struct ipt_handle* h)
+ 	return res;
+ }
+ 
+-static void check_chains_exist(void)
++void check_chains_exist_lib(void)
+ {
+ 	struct iptc_handle *h4;
+ 	struct ip6tc_handle *h6;
+ 
+-	if (global_data->block_ipv4) {
+-		h4 = ip4tables_open("filter");
+-
+-		if (!h4) {
+-			log_message(LOG_INFO, "WARNING, ip_tables module not installed - can't filter IPv4 addresses");
+-			use_ip4tables = false;
+-		} else {
+-			if (global_data->vrrp_iptables_inchain[0] &&
+-			    !ip4tables_is_chain(h4, global_data->vrrp_iptables_inchain)) {
+-				log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
+-				use_ip4tables = false;
+-			}
+-			if (global_data->vrrp_iptables_outchain[0] &&
+-			    !ip4tables_is_chain(h4, global_data->vrrp_iptables_outchain)) {
+-				log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
+-				use_ip4tables = false;
++	if (block_ipv4) {
++#ifdef _LIBIPTC_DYNAMIC_
++		if (using_libip4tc)
++#endif
++		{
++			h4 = ip4tables_open("filter");
++
++			if (!h4) {
++				log_message(LOG_INFO, "WARNING, ip_tables module not installed - can't filter IPv4 addresses");
++				block_ipv4 = false;
++			} else {
++				if (global_data->vrrp_iptables_inchain[0] &&
++				    !ip4tables_is_chain(h4, global_data->vrrp_iptables_inchain)) {
++					log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
++					block_ipv4 = false;
++				}
++				if (global_data->vrrp_iptables_outchain[0] &&
++				    !ip4tables_is_chain(h4, global_data->vrrp_iptables_outchain)) {
++					log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
++					block_ipv4 = false;
++				}
++
++				ip4tables_close(h4, false);
+ 			}
+-
+-			ip4tables_close(h4, false);
+ 		}
+ 	}
+-	else
+-		use_ip4tables = false;
+-
+-	if (global_data->block_ipv6) {
+-		h6 = ip6tables_open("filter");
+-
+-		if (!h6) {
+-			log_message(LOG_INFO, "WARNING, ip6_tables module not installed - can't filter IPv6 addresses");
+-			use_ip6tables = false;
+-		} else {
+-			if (global_data->vrrp_iptables_inchain[0] &&
+-			    !ip6tables_is_chain(h6, global_data->vrrp_iptables_inchain)) {
+-				log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
+-				use_ip6tables = false;
+-			}
+-			if (global_data->vrrp_iptables_outchain[0] &&
+-			    !ip6tables_is_chain(h6, global_data->vrrp_iptables_outchain)) {
+-				log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
+-				use_ip6tables = false;
+-			}
+ 
+-			ip6tables_close(h6, false);
++	if (block_ipv6) {
++#ifdef _LIBIPTC_DYNAMIC_
++		if (using_libip6tc)
++#endif
++		{
++			h6 = ip6tables_open("filter");
++
++			if (!h6) {
++				log_message(LOG_INFO, "WARNING, ip6_tables module not installed - can't filter IPv6 addresses");
++				block_ipv6 = false;
++			} else {
++				if (global_data->vrrp_iptables_inchain[0] &&
++				    !ip6tables_is_chain(h6, global_data->vrrp_iptables_inchain)) {
++					log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
++					block_ipv6 = false;
++				}
++				if (global_data->vrrp_iptables_outchain[0] &&
++				    !ip6tables_is_chain(h6, global_data->vrrp_iptables_outchain)) {
++					log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
++					block_ipv6 = false;
++				}
++
++				ip6tables_close(h6, false);
++			}
+ 		}
+ 	}
+-	else
+-		use_ip6tables = false;
+ }
+ 
+ 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)
+@@ -303,11 +318,8 @@ handle_iptable_rule_to_vip_lib(ip_address_t *ipaddress, int cmd, struct ipt_hand
+ 	char *ifname = NULL;
+ 
+ 	/* If iptables for the address family isn't in use, skip */
+-	if ((ipaddress->ifa.ifa_family == AF_INET && !use_ip4tables) ||
+-	    (ipaddress->ifa.ifa_family == AF_INET6 && !use_ip6tables))
+-		return;
+-
+-	if (global_data->vrrp_iptables_inchain[0] == '\0')
++	if ((ipaddress->ifa.ifa_family == AF_INET && !block_ipv4) ||
++	    (ipaddress->ifa.ifa_family == AF_INET6 && !block_ipv6))
+ 		return;
+ 
+ #ifdef _HAVE_LIBIPSET_
+@@ -343,33 +355,28 @@ handle_iptable_rule_to_vip_lib(ip_address_t *ipaddress, int cmd, struct ipt_hand
+ 			IPPROTO_NONE, 0, cmd, force);
+ }
+ 
++#ifdef _HAVE_LIBIPSET_
+ static void
+-iptables_remove_structure(
+-#ifndef _HAVE_LIBIPSET_
+-			  __attribute__((unused))
+-#endif
+-						 bool ignore_errors)
++iptables_remove_structure(bool ignore_errors)
+ {
+-#ifdef _HAVE_LIBIPSET_
+ 	if (global_data->using_ipsets) {
+ 		add_del_rules(IPADDRESS_DEL, ignore_errors);
+ 		add_del_sets(IPADDRESS_DEL, false);
+ 	}
+-#endif
+ }
++#endif
+ 
+ void
+-iptables_startup(bool reload)
++iptables_startup(
++#ifndef _HAVE_LIBIPSET_
++		 __attribute__((unused))
++#endif
++					 bool reload)
+ {
+-	if (!reload) {
+-		check_chains_exist();
+ #ifdef _HAVE_LIBIPSET_
+-		if (!use_ip4tables && !use_ip6tables)
+-			global_data->using_ipsets = false;
+-#endif
+-	}
++	if (!block_ipv4 && !block_ipv6)
++		global_data->using_ipsets = false;
+ 
+-#ifdef _HAVE_LIBIPSET_
+ 	if (global_data->using_ipsets) {
+ 		add_del_sets(IPADDRESS_ADD, reload);
+ 		add_del_rules(IPADDRESS_ADD, false);
+@@ -380,50 +387,94 @@ iptables_startup(bool reload)
+ void
+ iptables_cleanup(void)
+ {
++#ifdef _HAVE_LIBIPSET_
+ 	iptables_remove_structure(true);
++#endif
++}
++
++/* return true if a given file exists within procfs */
++/* Taken from iptables code */
++static
++bool proc_file_exists(const char *filename)
++{
++	struct stat s;
++	struct statfs f;
++
++	if (lstat(filename, &s))
++		return false;
++	if (!S_ISREG(s.st_mode))
++		return false;
++	if (statfs(filename, &f))
++		return false;
++	if (f.f_type != PROC_SUPER_MAGIC)
++		return false;
++
++	return true;
+ }
+ 
+-bool
++void
+ iptables_init_lib(void)
+ {
+-#ifdef _LIBXTABLES_DYNAMIC_
+-	xtables_load();
++	if (block_ipv4) {
++		if (!proc_file_exists("/proc/net/ip_tables_names") &&
++		    !load_xtables_module("ip_tables", "iptables"))
++#ifdef _LIBIPTC_DYNAMIC_
++			using_libip4tc = false;
++		else
++			using_libip4tc = true;
++#else
++		{
++			block_ipv4 = false;
++			log_message(LOG_INFO, "Unable to load module ip_tables");
++		}
+ #endif
++	}
+ 
++	if (block_ipv6) {
++		if (!proc_file_exists("/proc/net/ip6_tables_names") &&
++		    !load_xtables_module("ip6_tables", "ip6tables"))
+ #ifdef _LIBIPTC_DYNAMIC_
+-	if (!iptables_lib_init()) {
+-		using_libiptc = false;
+-#ifdef _LIBXTABLES_DYNAMIC_
+-		xtables_unload();
++			using_libip6tc = false;
++		else
++			using_libip6tc = true;
++#else
++		{
++			block_ipv6 = false;
++			log_message(LOG_INFO, "Unable to load module ip_tables");
++		}
+ #endif
+-		return false;
+ 	}
+-#endif
+ 
+-	if (!load_xtables_module("ip_tables", "iptables")) {
+ #ifdef _LIBIPTC_DYNAMIC_
+-		using_libiptc = false;
+-#endif
++	if ((!block_ipv4 && !block_ipv6) ||
++	    (!using_libip4tc && !using_libip6tc) ||
++	    !iptables_lib_init()) {
+ #ifdef _LIBXTABLES_DYNAMIC_
+ 		xtables_unload();
+ #endif
+-		return false;
++
++#ifdef _HAVE_LIBIPSET_
++		global_data->using_ipsets = false;
++#endif
++
++		return;
+ 	}
++#endif
+ 
+ #ifdef _HAVE_LIBIPSET_
+-	if (!ipset_init())
++	if (global_data->using_ipsets && !ipset_init())
+ 		global_data->using_ipsets = false;
+ #endif
+ 
+ #ifdef _LIBXTABLES_DYNAMIC_
+ 	xtables_unload();
+ #endif
+-
+-	return true;
+ }
+ 
+ void
+ iptables_fini(void)
+ {
++#ifdef _HAVE_LIBIPSET_
+ 	iptables_remove_structure(false);
++#endif
+ }
+diff --git a/keepalived/vrrp/vrrp_iptables_calls.c b/keepalived/vrrp/vrrp_iptables_calls.c
+index fb5c98df..ff6b7e6e 100644
+--- a/keepalived/vrrp/vrrp_iptables_calls.c
++++ b/keepalived/vrrp/vrrp_iptables_calls.c
+@@ -37,22 +37,18 @@
+ #include <xtables.h>
+ #include <libiptc/libiptc.h>
+ #include <libiptc/libip6tc.h>
+-#ifdef _HAVE_LIBIPSET_
+ #include <libipset/linux_ip_set.h>
+ #if defined XT_SET_H_ADD_IP_SET_H_GUARD
+ #define _IP_SET_H
+ #elif defined XT_SET_H_ADD_UAPI_IP_SET_H_GUARD
+ #define _UAPI_IP_SET_H
+ #endif
++#ifdef _HAVE_LIBIPSET_
+ #include <linux/netfilter/xt_set.h>
+ #endif
+ #include <unistd.h>
+ #include <signal.h>
+ #include <stdint.h>
+-#ifdef _LIBXTABLES_DYNAMIC_
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#endif
+ 
+ #include "vrrp_iptables_calls.h"
+ #include "memory.h"
+@@ -63,6 +59,7 @@
+ #ifdef _LIBIPTC_DYNAMIC_
+ #include "global_data.h"
+ #endif
++#include "vrrp_iptables.h"
+ 
+ /* We sometimes get a resource_busy on iptc_commit. This appears to happen
+  * when someone else is also updating it.
+@@ -406,6 +403,7 @@ int ip6tables_process_entry( struct ip6tc_handle* handle, const char* chain_name
+ 
+ #ifdef _HAVE_LIBIPTC_
+ #ifdef _LIBXTABLES_DYNAMIC_ 
++static
+ bool xtables_load(void)
+ {
+ 	if (libxtables_handle)
+@@ -418,7 +416,7 @@ bool xtables_load(void)
+ 	}
+ 
+ 	if (!(xtables_insmod_addr = dlsym(libxtables_handle, "xtables_insmod"))) {
+-		log_message(LOG_INFO, "Failed to dynamic link xtables_insmod");
++		log_message(LOG_INFO, "Failed to dynamic link xtables_insmod - %s", dlerror());
+ 		dlclose(libxtables_handle);
+ 		libxtables_handle = NULL;
+ 
+@@ -438,25 +436,18 @@ void xtables_unload(void)
+ }
+ #endif
+ 
+-bool load_xtables_module(const char *module,
++bool
++load_xtables_module(const char *module,
+ #ifndef _LIBXTABLES_DYNAMIC_
+-					    __attribute__((unused))
++					__attribute__((unused))
+ #endif
+-								    const char *function)
++								const char *function)
+ {
+ 	struct sigaction act, old_act;
+ 	bool res = true;
+-#ifdef _LIBXTABLES_DYNAMIC_
+-	struct stat stat_buf;
+-	char module_path[32] = "/sys/module/";
+-
+-	if (!libxtables_handle) {
+-		/* See if the module is loaded anyway */
+-		strcat(module_path, module);
+-		if (!stat(module_path, &stat_buf) &&
+-		    (stat_buf.st_mode & S_IFDIR))
+-			return true;
+ 
++#ifdef _LIBXTABLES_DYNAMIC_
++	if (!libxtables_handle && !xtables_load()) {
+ 		log_message(LOG_INFO, "Module %s cannot be loaded; not using %s", module, function);
+ 		return false;
+ 	}
+@@ -882,47 +873,50 @@ int ip6tables_add_rules(struct ip6tc_handle* handle, const char* chain_name, uns
+ #ifdef _LIBIPTC_DYNAMIC_
+ bool iptables_lib_init(void)
+ {
+-	if (libip4tc_handle)
+-		return true;
+-
+-	/* Attempt to open the ip4tc library */
+-	if (!(libip4tc_handle = dlopen("libip4tc.so", RTLD_NOW)) &&
+-	    !(libip4tc_handle = dlopen(IP4TC_LIB_NAME, RTLD_NOW))) {
+-		log_message(LOG_INFO, "Unable to load ip4tc library - %s", dlerror());
+-		return false;
+-	}
+-
+-	if (!(iptc_init_addr = dlsym(libip4tc_handle, "iptc_init")) ||
+-	    !(iptc_free_addr = dlsym(libip4tc_handle, "iptc_free")) ||
+-	    !(iptc_is_chain_addr = dlsym(libip4tc_handle,"iptc_is_chain")) ||
+-	    !(iptc_insert_entry_addr = dlsym(libip4tc_handle,"iptc_insert_entry")) ||
+-	    !(iptc_append_entry_addr = dlsym(libip4tc_handle,"iptc_append_entry")) ||
+-	    !(iptc_delete_entry_addr = dlsym(libip4tc_handle,"iptc_delete_entry")) ||
+-	    !(iptc_commit_addr = dlsym(libip4tc_handle,"iptc_commit")) ||
+-	    !(iptc_strerror_addr = dlsym(libip4tc_handle,"iptc_strerror")))
+-		log_message(LOG_INFO, "Failed to dynamic link an iptc function");
+-
+-	/* Attempt to open the ip6tc library */
+-	if (!(libip6tc_handle = dlopen("libip6tc.so", RTLD_NOW)) &&
+-	    !(libip6tc_handle = dlopen(IP6TC_LIB_NAME, RTLD_NOW))) {
+-		log_message(LOG_INFO, "Unable to load ip6tc library - %s", dlerror());
+-
+-		if (global_data->block_ipv4)
++	if (!libip4tc_handle && block_ipv4) {
++		/* Attempt to open the ip4tc library */
++		if (!(libip4tc_handle = dlopen("libip4tc.so", RTLD_NOW)) &&
++		    !(libip4tc_handle = dlopen(IP4TC_LIB_NAME, RTLD_NOW))) {
++			log_message(LOG_INFO, "Unable to load ip4tc library - %s", dlerror());
++			using_libip4tc = false;
++		}
++		else if (!(iptc_init_addr = dlsym(libip4tc_handle, "iptc_init")) ||
++			 !(iptc_free_addr = dlsym(libip4tc_handle, "iptc_free")) ||
++			 !(iptc_is_chain_addr = dlsym(libip4tc_handle,"iptc_is_chain")) ||
++			 !(iptc_insert_entry_addr = dlsym(libip4tc_handle,"iptc_insert_entry")) ||
++			 !(iptc_append_entry_addr = dlsym(libip4tc_handle,"iptc_append_entry")) ||
++			 !(iptc_delete_entry_addr = dlsym(libip4tc_handle,"iptc_delete_entry")) ||
++			 !(iptc_commit_addr = dlsym(libip4tc_handle,"iptc_commit")) ||
++			 !(iptc_strerror_addr = dlsym(libip4tc_handle,"iptc_strerror"))) {
++			log_message(LOG_INFO, "Failed to dynamic link an iptc function - %s", dlerror());
++			using_libip4tc = false;
+ 			dlclose(libip4tc_handle);
+-
+-		return false;
++			libip4tc_handle = NULL;
++		}
+ 	}
+ 
+-	if (!(ip6tc_init_addr = dlsym(libip6tc_handle, "ip6tc_init")) ||
+-	    !(ip6tc_free_addr = dlsym(libip6tc_handle, "ip6tc_free")) ||
+-	    !(ip6tc_is_chain_addr = dlsym(libip6tc_handle,"ip6tc_is_chain")) ||
+-	    !(ip6tc_insert_entry_addr = dlsym(libip6tc_handle,"ip6tc_insert_entry")) ||
+-	    !(ip6tc_append_entry_addr = dlsym(libip6tc_handle,"ip6tc_append_entry")) ||
+-	    !(ip6tc_delete_entry_addr = dlsym(libip6tc_handle,"ip6tc_delete_entry")) ||
+-	    !(ip6tc_commit_addr = dlsym(libip6tc_handle,"ip6tc_commit")) ||
+-	    !(ip6tc_strerror_addr = dlsym(libip6tc_handle,"ip6tc_strerror")))
+-		log_message(LOG_INFO, "Failed to dynamic link an ip6tc function");
++	if (!libip6tc_handle && block_ipv6) {
++		/* Attempt to open the ip6tc library */
++		if (!(libip6tc_handle = dlopen("libip6tc.so", RTLD_NOW)) &&
++		    !(libip6tc_handle = dlopen(IP6TC_LIB_NAME, RTLD_NOW))) {
++			log_message(LOG_INFO, "Unable to load ip6tc library - %s", dlerror());
++			using_libip6tc = false;
++		}
++		else if (!(ip6tc_init_addr = dlsym(libip6tc_handle, "ip6tc_init")) ||
++			 !(ip6tc_free_addr = dlsym(libip6tc_handle, "ip6tc_free")) ||
++			 !(ip6tc_is_chain_addr = dlsym(libip6tc_handle,"ip6tc_is_chain")) ||
++			 !(ip6tc_insert_entry_addr = dlsym(libip6tc_handle,"ip6tc_insert_entry")) ||
++			 !(ip6tc_append_entry_addr = dlsym(libip6tc_handle,"ip6tc_append_entry")) ||
++			 !(ip6tc_delete_entry_addr = dlsym(libip6tc_handle,"ip6tc_delete_entry")) ||
++			 !(ip6tc_commit_addr = dlsym(libip6tc_handle,"ip6tc_commit")) ||
++			 !(ip6tc_strerror_addr = dlsym(libip6tc_handle,"ip6tc_strerror"))) {
++			log_message(LOG_INFO, "Failed to dynamic link an ip6tc function - %s", dlerror());
++			using_libip6tc = false;
++			dlclose(libip6tc_handle);
++			libip6tc_handle = NULL;
++		}
++	}
+ 
+-	return true;
++	return libip4tc_handle || libip6tc_handle;
+ }
+ #endif
+-- 
+2.13.5
+
diff --git a/SOURCES/bz1508435-no-segfault-ip_vs-load.patch b/SOURCES/bz1508435-no-segfault-ip_vs-load.patch
new file mode 100644
index 0000000..b894b25
--- /dev/null
+++ b/SOURCES/bz1508435-no-segfault-ip_vs-load.patch
@@ -0,0 +1,168 @@
+From 19d0482859d9068b893104b9f8beeaba709aec2d Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Mon, 27 Mar 2017 11:28:02 +0100
+Subject: [PATCH 2/3] Don't segfault if unable to load ip_vs module
+
+In a docker container it isn't possible to load a kernel module. The
+check code was detecting that it couldn't load the module, but the
+checker process, when cleaning up prior to exiting, was assuming that
+certain pointers had been initialised which hadn't been when an error
+was detected so early in the initialisation.
+
+This commit adds testing for uninitialised pointers during the exit
+sequence.
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ keepalived/check/check_api.c         | 3 +++
+ keepalived/check/check_daemon.c      | 8 +++++---
+ keepalived/check/check_data.c        | 7 ++++++-
+ keepalived/check/ipvswrapper.c       | 9 ++++++---
+ keepalived/check/ipwrapper.c         | 6 ++++--
+ keepalived/check/libipvs.c           | 5 ++++-
+ keepalived/core/keepalived_netlink.c | 7 ++++---
+ 7 files changed, 32 insertions(+), 13 deletions(-)
+
+diff --git a/keepalived/check/check_api.c b/keepalived/check/check_api.c
+index 51d8cc71..b7081fd0 100644
+--- a/keepalived/check/check_api.c
++++ b/keepalived/check/check_api.c
+@@ -224,6 +224,9 @@ init_checkers_queue(void)
+ void
+ free_checkers_queue(void)
+ {
++	if (!checkers_queue)
++		return;
++
+ 	free_list(&checkers_queue);
+ 	ncheckers = 0;
+ }
+diff --git a/keepalived/check/check_daemon.c b/keepalived/check/check_daemon.c
+index a87fd4cd..a3ff8cab 100644
+--- a/keepalived/check/check_daemon.c
++++ b/keepalived/check/check_daemon.c
+@@ -74,7 +74,7 @@ stop_check(int status)
+ 		clear_services();
+ 	ipvs_stop();
+ #ifdef _WITH_SNMP_CHECKER_
+-	if (global_data->enable_snmp_checker)
++	if (global_data && global_data->enable_snmp_checker)
+ 		check_snmp_agent_close();
+ #endif
+ 
+@@ -82,8 +82,10 @@ stop_check(int status)
+ 	pidfile_rm(checkers_pidfile);
+ 
+ 	/* Clean data */
+-	free_global_data(global_data);
+-	free_check_data(check_data);
++	if (global_data)
++		free_global_data(global_data);
++	if (check_data)
++		free_check_data(check_data);
+ 	free_parent_mallocs_exit();
+ 
+ 	/*
+diff --git a/keepalived/check/check_data.c b/keepalived/check/check_data.c
+index 0c3f1940..6ce87229 100644
+--- a/keepalived/check/check_data.c
++++ b/keepalived/check/check_data.c
+@@ -51,7 +51,12 @@ alloc_ssl(void)
+ void
+ free_ssl(void)
+ {
+-	ssl_data_t *ssl = check_data->ssl;
++	ssl_data_t *ssl;
++       
++	if (!check_data)
++		return;
++
++	ssl = check_data->ssl;
+ 
+ 	if (!ssl)
+ 		return;
+diff --git a/keepalived/check/ipvswrapper.c b/keepalived/check/ipvswrapper.c
+index cd7f169e..20757c94 100644
+--- a/keepalived/check/ipvswrapper.c
++++ b/keepalived/check/ipvswrapper.c
+@@ -165,9 +165,12 @@ void
+ ipvs_stop(void)
+ {
+ 	/* Clean up the room */
+-	FREE(srule);
+-	FREE(drule);
+-	FREE(daemonrule);
++	if (srule)
++		FREE(srule);
++	if (drule)
++		FREE(drule);
++	if (daemonrule)
++		FREE(daemonrule);
+ 	ipvs_close();
+ }
+ 
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index 0c2fc46b..ecf12713 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -138,10 +138,12 @@ void
+ clear_services(void)
+ {
+ 	element e;
+-	list l = check_data->vs;
+ 	virtual_server_t *vs;
+ 
+-	for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
++	if (!check_data || !check_data->vs)
++		return;
++
++	for (e = LIST_HEAD(check_data->vs); e; ELEMENT_NEXT(e)) {
+ 		vs = ELEMENT_DATA(e);
+ 		clear_service_vs(vs);
+ 	}
+diff --git a/keepalived/check/libipvs.c b/keepalived/check/libipvs.c
+index 2250e2b4..8722f7a6 100644
+--- a/keepalived/check/libipvs.c
++++ b/keepalived/check/libipvs.c
+@@ -1157,7 +1157,10 @@ void ipvs_close(void)
+ 	if (try_nl)
+ 		return;
+ #endif
+-	close(sockfd);
++	if (sockfd != -1) {
++		close(sockfd);
++		sockfd = -1;
++	}
+ }
+ 
+ const char *ipvs_strerror(int err)
+diff --git a/keepalived/core/keepalived_netlink.c b/keepalived/core/keepalived_netlink.c
+index 41e63b85..0f465cf5 100644
+--- a/keepalived/core/keepalived_netlink.c
++++ b/keepalived/core/keepalived_netlink.c
+@@ -251,9 +251,12 @@ netlink_socket(nl_handle_t *nl, int flags, int group, ...)
+ }
+ 
+ /* Close a netlink socket */
+-static int
++static void
+ netlink_close(nl_handle_t *nl)
+ {
++	if (!nl)
++		return;
++
+ 	/* First of all release pending thread */
+ 	thread_cancel(nl->thread);
+ 
+@@ -269,8 +272,6 @@ netlink_close(nl_handle_t *nl)
+ #endif
+ 		close(nl->fd);
+ #endif
+-
+-	return 0;
+ }
+ 
+ #ifdef _WITH_VRRP_
+-- 
+2.13.5
+
diff --git a/SOURCES/bz1508435-remove-ipset-handling.patch b/SOURCES/bz1508435-remove-ipset-handling.patch
new file mode 100644
index 0000000..2cc4f94
--- /dev/null
+++ b/SOURCES/bz1508435-remove-ipset-handling.patch
@@ -0,0 +1,30 @@
+From dcb5af32ea618c42e353f399962bdd6dc1c8a7d9 Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Mon, 27 Mar 2017 20:44:50 +0100
+Subject: [PATCH 3/3] Don't attempt to remove ipsets if ipset handling not
+ initialised
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ keepalived/vrrp/vrrp_ipset.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/keepalived/vrrp/vrrp_ipset.c b/keepalived/vrrp/vrrp_ipset.c
+index 1c3e4990..b40bc836 100644
+--- a/keepalived/vrrp/vrrp_ipset.c
++++ b/keepalived/vrrp/vrrp_ipset.c
+@@ -270,6 +270,11 @@ bool remove_ipsets(void)
+ 	if (!global_data->using_ipsets)
+ 		return true;
+ 
++#ifdef _LIBIPSET_DYNAMIC_
++	if (!libipset_handle)
++		return true;
++#endif
++
+ 	session = ipset_session_init(printf);
+ 	if (!session) {
+ 		log_message(LOG_INFO, "Cannot initialize ipset session.");
+-- 
+2.13.5
+
diff --git a/SOURCES/keepalived.service b/SOURCES/keepalived.service
new file mode 100644
index 0000000..1b3e587
--- /dev/null
+++ b/SOURCES/keepalived.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=LVS and VRRP High Availability Monitor
+After=syslog.target network-online.target
+
+[Service]
+Type=forking
+PIDFile=/var/run/keepalived.pid
+KillMode=process
+EnvironmentFile=-/etc/sysconfig/keepalived
+ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
diff --git a/SPECS/keepalived.spec b/SPECS/keepalived.spec
new file mode 100644
index 0000000..4e0a046
--- /dev/null
+++ b/SPECS/keepalived.spec
@@ -0,0 +1,384 @@
+%bcond_without snmp
+%bcond_without vrrp
+%bcond_without sha1
+%bcond_with profile
+%bcond_with debug
+
+%global _hardened_build 1
+
+Name: keepalived
+Summary: Load balancer and high availability service
+Version: 1.3.5
+Release: 6%{?dist}
+License: GPLv2+
+URL: http://www.keepalived.org/
+Group: System Environment/Daemons
+
+Source0: http://www.keepalived.org/software/keepalived-%{version}.tar.gz
+Source1: keepalived.service
+
+Patch0: bz1419049-fix-unused-variables.patch
+Patch1: bz1477572-fix-man-page-vrrp_ipsets.patch
+Patch2: bz1477563-fix-keepalived_script-user.patch
+Patch3: bz1508435-load-ip-tables-handling.patch
+Patch4: bz1508435-no-segfault-ip_vs-load.patch
+Patch5: bz1508435-remove-ipset-handling.patch
+Patch6: bz1477587-exclude-mismatch-vips.patch
+
+Requires: ipset-libs
+Requires(post): systemd
+Requires(preun): systemd
+Requires(postun): systemd
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+%if %{with snmp}
+BuildRequires: net-snmp
+BuildRequires: net-snmp-devel
+%endif
+BuildRequires: systemd-units
+BuildRequires: openssl-devel
+BuildRequires: libnl3-devel
+BuildRequires: ipset-devel
+BuildRequires: iptables-devel
+BuildRequires: libnfnetlink-devel
+
+%description
+Keepalived provides simple and robust facilities for load balancing
+and high availability.  The load balancing framework relies on the
+well-known and widely used Linux Virtual Server (IPVS) kernel module
+providing layer-4 (transport layer) load balancing.  Keepalived
+implements a set of checkers to dynamically and adaptively maintain
+and manage a load balanced server pool according their health.
+Keepalived also implements the Virtual Router Redundancy Protocol
+(VRRPv2) to achieve high availability with director failover.
+
+%prep
+%setup -q
+%patch0 -p1
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+
+%build
+%configure \
+    %{?with_debug:--enable-debug} \
+    %{?with_profile:--enable-profile} \
+    %{!?with_vrrp:--disable-vrrp} \
+    %{?with_snmp:--enable-snmp --enable-snmp-rfc} \
+    %{?with_sha1:--enable-sha1}
+%{__make} %{?_smp_mflags} STRIP=/bin/true
+
+%install
+%{__rm} -rf %{buildroot}
+%{__rm} -rf doc/samples/*.pem
+%{__make} install DESTDIR=%{buildroot}
+%{__rm} -rf %{buildroot}%{_initrddir}/
+%{__rm} -rf %{buildroot}%{_sysconfdir}/keepalived/samples/
+%{__install} -p -D -m 0644 %{SOURCE1} %{buildroot}%{_unitdir}/keepalived.service
+%{__mkdir_p} %{buildroot}%{_libexecdir}/keepalived
+
+%if %{with snmp}
+%{__mkdir_p} %{buildroot}%{_datadir}/snmp/mibs/
+%endif
+
+%clean
+%{__rm} -rf %{buildroot}
+
+%post
+%systemd_post keepalived.service
+
+%preun
+%systemd_preun keepalived.service
+
+%postun
+%systemd_postun_with_restart keepalived.service
+
+%files
+%defattr(-,root,root,-)
+%doc AUTHOR ChangeLog CONTRIBUTORS COPYING README TODO
+%doc doc/keepalived.conf.SYNOPSIS doc/NOTE_vrrp_vmac.txt doc/samples/
+%dir %{_sysconfdir}/keepalived/
+%dir %{_libexecdir}/keepalived/
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/keepalived/keepalived.conf
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/keepalived
+%{_unitdir}/keepalived.service
+%if %{with snmp}
+%{_datadir}/snmp/mibs/KEEPALIVED-MIB.txt
+%{_datadir}/snmp/mibs/VRRP-MIB.txt
+%{_datadir}/snmp/mibs/VRRPv3-MIB.txt
+%endif
+%attr(0755,root,root) %{_bindir}/genhash
+%attr(0755,root,root) %{_sbindir}/keepalived
+%{_mandir}/man1/genhash.1*
+%{_mandir}/man5/keepalived.conf.5*
+%{_mandir}/man8/keepalived.8*
+
+%changelog
+* Wed Jan 31 2018 Ryan O'Hara <rohara@redhat.com> - 1.3.5-6
+- Add net-snmp as BuildRequires (#1536252)
+
+* Mon Dec 11 2017 Ryan O'Hara <rohara@redhat.com> - 1.3.5-5
+- Exclude VIPs of non-matching address family (#1477587)
+
+* Thu Nov 16 2017 Ryan O'Hara <rohara@redhat.com> - 1.3.5-4
+- Fix bugs related to failures when load modules and/or segfaults (#1508435)
+
+* Wed Aug 02 2017 Ryan O'Hara <rohara@redhat.com> - 1.3.5-3
+- Don't complain about keepalived_script user if not needed (#1477563)
+
+* Wed Aug 02 2017 Ryan O'Hara <rohara@redhat.com> - 1.3.5-2
+- Fix ipset-libs dependency and vrrp_ipset in man page (#1477572)
+
+* Wed Mar 22 2017 Ryan O'Hara <rohara@redhat.com> - 1.3.5-1
+- Rebase to upstream version 1.3.5 (#1419049)
+
+* Thu Mar 16 2017 Ryan O'Hara <rohara@redhat.com> - 1.3.4-2
+- Start keepalived after network-online.target (#1425828)
+
+* Wed Mar 15 2017 Ryan O'Hara <rohara@redhat.com> - 1.3.4-1
+- Rebase to upstream version 1.3.4 (#1419049)
+
+* Fri Jul 01 2016 Ryan O'Hara <rohara@redhat.com> - 1.2.13-8
+- Add PIDFile to systemd unit file (#1336190)
+
+* Thu Jun 25 2015 Ryan O'Hara <rohara@redhat.com> - 1.2.13-7
+- Set global default values after parsing config file (#1181107)
+
+* Tue Nov 18 2014 Ryan O'Hara <rohara@redhat.com> - 1.2.13-6
+- Fix typo in changelog
+
+* Mon Nov 10 2014 Ryan O'Hara <rohara@redhat.com> - 1.2.13-5
+- Bump release number (#1158114)
+
+* Thu Nov 06 2014 Ryan O'Hara <rohara@redhat.com> - 1.2.13-4
+- Create /usr/libexec/keepalived directory (#1158114)
+
+* Tue Sep 30 2014 Ryan O'Hara <rohara@redhat.com> - 1.2.13-3
+- Minor spec file modifications (#1067693, #1067145)
+
+* Tue Sep 30 2014 Ryan O'Hara <rohara@redhat.com> - 1.2.13-2
+- Add SNMP subsystem option to man page (#1085535)
+
+* Thu Aug 07 2014 Ryan O'Hara <rohara@redhat.com> - 1.2.13-1
+- Rebase to upstream version 1.2.13 (#1111716)
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.2.10-2
+- Mass rebuild 2014-01-24
+
+* Tue Jan 14 2014 Ryan O'Hara <rohara@redhat.com> - 1.2.10-1
+- Rebase to upstream version 1.2.10 (#1052359)
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.2.8-2
+- Mass rebuild 2013-12-27
+
+* Thu Sep 05 2013 Ryan O'Hara <rohara@redhat.com> - 1.2.8-1
+- Update to 1.2.8.
+
+* Mon Jul 22 2013 Ryan O'Hara <rohara@redhat.com> - 1.2.7-8
+- Fix macro in keepalived.conf.5 man page.
+
+* Mon Jul 22 2013 Ryan O'Hara <rohara@redhat.com> - 1.2.7-7
+- Fix systemd requirements.
+
+* Mon Jul 22 2013 Ryan O'Hara <rohara@redhat.com> - 1.2.7-6
+- Install the systemd unit file, not the init script.
+
+* Mon Apr 22 2013 Ryan O'Hara <rohara@redhat.com> - 1.2.7-5
+- Build with PIE flags (#955150)
+
+* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.7-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
+
+* Wed Jan 2 2013 Ryan O'Hara <rohara@redhat.com> - 1.2.7-3
+- Update spec file.
+- Add option to prevent respawn of child processes.
+- Remove duplicate command-line option code.
+- Use popt to generate usage message.
+- Fix pointer arithmetic for VRRP packets.
+- Fix comparison of primary IP address.
+- Fix loading of SSL certificate.
+- Fix typo in error message.
+- Update FSF address in GPLv2 license.
+- Remove debug message from if_get_by_ifname.
+
+* Mon Sep 24 2012 Václav Pavlín <vpavlin@redhat.com> - 1.2.7-2
+- Scriptlets replaced with new systemd macros (#850173).
+
+* Tue Sep 04 2012 Ryan O'Hara <rohara@redhat.com> - 1.2.7-1
+- Update to 1.2.7.
+- Fix systemd service file (#769726).
+
+* Mon Aug 20 2012 Ryan O'Hara <rohara@redhat.com> - 1.2.6-1
+- Update to 1.2.6.
+
+* Tue Aug 14 2012 Ryan O'Hara <rohara@redhat.com> - 1.2.5-2
+- Install KEEPALIVED-MIB as KEEPALIVED-MIB.txt.
+
+* Mon Aug 13 2012 Ryan O'Hara <rohara@redhat.com> - 1.2.5-1
+- Update to 1.2.5.
+
+* Wed Aug 01 2012 Ryan O'Hara <rohara@redhat.com> - 1.2.4-1
+- Update to 1.2.4.
+
+* Mon Jul 23 2012 Ryan O'Hara <rohara@redhat.com> - 1.2.3-1
+- Update to 1.2.3.
+
+* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.2-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Tue May 08 2012 Ryan O'Hara <rohara@redhat.com> - 1.2.2-5
+- Fix IPv4 address comparison (#768119).
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.2-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Mon Sep 19 2011 Tom Callaway <spot@fedoraproject.org> - 1.2.2-3
+- convert to systemd
+- fix ip_vs.h path searching in configure
+
+* Sat Jul 23 2011 Matthias Saou <http://freshrpms.net/> 1.2.2-2
+- Build against libnl for Fedora. RHEL's libnl is too old.
+
+* Sat May 21 2011 Matthias Saou <http://freshrpms.net/> 1.2.2-1
+- Update to 1.2.2.
+
+* Mon Feb 07 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.20-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Sun Jan 16 2011 Dan Horák <dan[at]danny.cz> 1.1.20-2
+- exclude arches where we don't provide 32-bit kernel
+
+* Tue Jan 11 2011 Matthias Saou <http://freshrpms.net/> 1.2.1-1
+- Update to 1.2.1, now with IPv6 support.
+
+* Sun May 23 2010 Matthias Saou <http://freshrpms.net/> 1.1.20-1
+- Update to 1.1.20 (#589923).
+- Update BR conditional for RHEL6.
+- No longer include goodies/arpreset.pl, it's gone from the sources.
+
+* Tue Dec  8 2009 Matthias Saou <http://freshrpms.net/> 1.1.19-3
+- Update init script to have keepalived start after the local MTA (#526512).
+- Simplify the kernel source detection, to avoid running rpm from rpmbuild.
+
+* Tue Nov 24 2009 Matthias Saou <http://freshrpms.net/> 1.1.19-2
+- Include patch to remove obsolete -k option to modprobe (#528465).
+
+* Wed Oct 21 2009 Matthias Saou <http://freshrpms.net/> 1.1.19-1
+- Update to 1.1.19.
+
+* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 1.1.17-3
+- rebuilt with new openssl
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.17-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Sun Apr 12 2009 Matthias Saou <http://freshrpms.net/> 1.1.17-1
+- Update to 1.1.17.
+- Update init script all the way.
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org>
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Sat Jan 17 2009 Tomas Mraz <tmraz@redhat.com> 1.1.15-7
+- rebuild with new openssl
+
+* Mon Dec 22 2008 Matthias Saou <http://freshrpms.net/> 1.1.15-6
+- Fork the init script to be (mostly for now) LSB compliant (#246966).
+
+* Thu Apr 24 2008 Matthias Saou <http://freshrpms.net/> 1.1.15-5
+- Add glob to the kerneldir location, since it contains the arch for F9+.
+
+* Tue Feb 19 2008 Fedora Release Engineering <rel-eng@fedoraproject.org>
+- Autorebuild for GCC 4.3
+
+* Wed Dec 05 2007 Release Engineering <rel-eng at fedoraproject dot org>
+- Rebuild for deps
+
+* Mon Oct 22 2007 Matthias Saou <http://freshrpms.net/> 1.1.15-2
+- Update to latest upstream sources, identical except for the included spec.
+
+* Mon Sep 17 2007 Matthias Saou <http://freshrpms.net/> 1.1.15-1
+- Update to 1.1.15.
+- Remove merged genhashman and include patches.
+
+* Fri Sep 14 2007 Matthias Saou <http://freshrpms.net/> 1.1.14-2
+- Include patch from Shinji Tanaka to fix conf include from inside some
+  directives like vrrp_instance.
+
+* Thu Sep 13 2007 Matthias Saou <http://freshrpms.net/> 1.1.14-1
+- Update to 1.1.14.
+- Remove all upstreamed patches.
+- Remove our init script and sysconfig files, use the same now provided by the
+  upstream package (will need to patch for LSB stuff soonish).
+- Include new goodies/arpreset.pl in %%doc.
+- Add missing scriplet requirements.
+
+* Wed Aug 22 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-8
+- Rebuild for new BuildID feature.
+
+* Sun Aug  5 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-7
+- Update License field.
+
+* Mon Mar 26 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-6
+- Fix doc/samples/sample.misccheck.smbcheck.sh mode (600 -> 644).
+
+* Thu Mar 22 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-5
+- Include types patch to fix compile on F7 (David Woodhouse).
+- Fix up file modes (main binary 700 -> 755 and config 600 -> 640).
+
+* Tue Feb 13 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-4
+- Add missing \n to the kernel define, for when multiple kernels are installed.
+- Pass STRIP=/bin/true to "make" in order to get a useful debuginfo package.
+
+* Tue Feb 13 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-3
+- Add %%check section to make sure any build without LVS support will fail.
+
+* Mon Feb  5 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-2
+- Use our own init script, include a sysconfig entry used by it for options.
+
+* Thu Jan 25 2007 Matthias Saou <http://freshrpms.net/> 1.1.13-1
+- Update to 1.1.13.
+- Change mode of configuration file to 0600.
+- Don't include all of "doc" since it meant re-including all man pages.
+- Don't include samples in the main configuration path, they're in %%doc.
+- Include patch to add an optional label to interfaces.
+
+* Sat Apr 08 2006 Dries Verachtert <dries@ulyssis.org> - 1.1.12-1.2
+- Rebuild for Fedora Core 5.
+
+* Sun Mar 12 2006 Dag Wieers <dag@wieers.com> - 1.1.12-1
+- Updated to release 1.1.12.
+
+* Fri Mar 04 2005 Dag Wieers <dag@wieers.com> - 1.1.11-1
+- Updated to release 1.1.11.
+
+* Wed Feb 23 2005 Dag Wieers <dag@wieers.com> - 1.1.10-2
+- Fixed IPVS/LVS support. (Joe Sauer)
+
+* Tue Feb 15 2005 Dag Wieers <dag@wieers.com> - 1.1.10-1
+- Updated to release 1.1.10.
+
+* Mon Feb 07 2005 Dag Wieers <dag@wieers.com> - 1.1.9-1
+- Updated to release 1.1.9.
+
+* Sun Oct 17 2004 Dag Wieers <dag@wieers.com> - 1.1.7-2
+- Fixes to build with kernel IPVS support. (Tim Verhoeven)
+
+* Fri Sep 24 2004 Dag Wieers <dag@wieers.com> - 1.1.7-1
+- Updated to release 1.1.7. (Mathieu Lubrano)
+
+* Mon Feb 23 2004 Dag Wieers <dag@wieers.com> - 1.1.6-0
+- Updated to release 1.1.6.
+
+* Mon Jan 26 2004 Dag Wieers <dag@wieers.com> - 1.1.5-0
+- Updated to release 1.1.5.
+
+* Mon Dec 29 2003 Dag Wieers <dag@wieers.com> - 1.1.4-0
+- Updated to release 1.1.4.
+
+* Fri Jun 06 2003 Dag Wieers <dag@wieers.com> - 1.0.3-0
+- Initial package. (using DAR)
+