Blob Blame History Raw
From 44f2b1782e3d7afe7ede3779e7b9896cbd6c26c7 Mon Sep 17 00:00:00 2001
From: Quentin Armitage <quentin@armitage.org.uk>
Date: Fri, 15 Dec 2017 21:14:24 +0000
Subject: [PATCH] Fix removing left-over addresses if keepalived aborts

Issue #718 reported that if keepalived terminates abnormally when
it has vrrp instances in master state, it doesn't remove the
left-over VIPs and eVIPs when it restarts. This is despite
commit f4c10426c saying that it resolved this problem.

It turns out that commit f4c10426c did resolve the problem for VIPs
or eVIPs, although it did resolve the issue for iptables and ipset
configuration.

This commit now really resolves the problem, and residual VIPs and
eVIPs are removed at startup.

Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
---
 keepalived/include/vrrp_ipaddress.h |  2 +-
 keepalived/vrrp/vrrp.c              | 16 ++++++++--------
 keepalived/vrrp/vrrp_daemon.c       |  6 +++---
 keepalived/vrrp/vrrp_ipaddress.c    |  6 +++---
 4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/keepalived/include/vrrp_ipaddress.h b/keepalived/include/vrrp_ipaddress.h
index 900dfd7f..4d613652 100644
--- a/keepalived/include/vrrp_ipaddress.h
+++ b/keepalived/include/vrrp_ipaddress.h
@@ -93,7 +93,7 @@ struct ipt_handle;	// AAGH - TODO
 /* prototypes */
 extern char *ipaddresstos(char *, ip_address_t *);
 extern int netlink_ipaddress(ip_address_t *, int);
-extern bool netlink_iplist(list, int);
+extern bool netlink_iplist(list, int, bool);
 extern void handle_iptable_rule_to_iplist(struct ipt_handle *, list, int, bool force);
 extern void free_ipaddress(void *);
 extern void dump_ipaddress(void *);
diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c
index 3d2bfe41..d58c3690 100644
--- a/keepalived/vrrp/vrrp.c
+++ b/keepalived/vrrp/vrrp.c
@@ -74,13 +74,13 @@
 
 /* add/remove Virtual IP addresses */
 static bool
-vrrp_handle_ipaddress(vrrp_t * vrrp, int cmd, int type)
+vrrp_handle_ipaddress(vrrp_t * vrrp, int cmd, int type, bool force)
 {
 	if (__test_bit(LOG_DETAIL_BIT, &debug))
 		log_message(LOG_INFO, "VRRP_Instance(%s) %s protocol %s", vrrp->iname,
 		       (cmd == IPADDRESS_ADD) ? "setting" : "removing",
 		       (type == VRRP_VIP_TYPE) ? "VIPs." : "E-VIPs.");
-	return netlink_iplist((type == VRRP_VIP_TYPE) ? vrrp->vip : vrrp->evip, cmd);
+	return netlink_iplist((type == VRRP_VIP_TYPE) ? vrrp->vip : vrrp->evip, cmd, force);
 }
 
 #ifdef _HAVE_FIB_ROUTING_
@@ -1283,9 +1283,9 @@ vrrp_state_become_master(vrrp_t * vrrp)
 	/* add the ip addresses */
 	vrrp_handle_accept_mode(vrrp, IPADDRESS_ADD, false);
 	if (!LIST_ISEMPTY(vrrp->vip))
-		vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_VIP_TYPE);
+		vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_VIP_TYPE, false);
 	if (!LIST_ISEMPTY(vrrp->evip))
-		vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_EVIP_TYPE);
+		vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_EVIP_TYPE, false);
 	vrrp->vipset = 1;
 
 #ifdef _HAVE_FIB_ROUTING_
@@ -1403,9 +1403,9 @@ vrrp_restore_interface(vrrp_t * vrrp, bool advF, bool force)
 	    __test_bit(DONT_RELEASE_VRRP_BIT, &debug) ||
 	    __test_bit(RELEASE_VIPS_BIT, &debug)) {
 		if (!LIST_ISEMPTY(vrrp->vip))
-			vrrp_handle_ipaddress(vrrp, IPADDRESS_DEL, VRRP_VIP_TYPE);
+			vrrp_handle_ipaddress(vrrp, IPADDRESS_DEL, VRRP_VIP_TYPE, force);
 		if (!LIST_ISEMPTY(vrrp->evip))
-			vrrp_handle_ipaddress(vrrp, IPADDRESS_DEL, VRRP_EVIP_TYPE);
+			vrrp_handle_ipaddress(vrrp, IPADDRESS_DEL, VRRP_EVIP_TYPE, force);
 		vrrp_handle_accept_mode(vrrp, IPADDRESS_DEL, force);
 		vrrp->vipset = 0;
 	}
@@ -2740,9 +2740,9 @@ restore_vrrp_state(vrrp_t *old_vrrp, vrrp_t *vrrp)
 	if (vrrp->vipset) {
 		vrrp_handle_accept_mode(vrrp, IPADDRESS_ADD, false);
 		if (!LIST_ISEMPTY(vrrp->vip))
-			added_ip_addr = vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_VIP_TYPE);
+			added_ip_addr = vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_VIP_TYPE, false);
 		if (!LIST_ISEMPTY(vrrp->evip)) {
-			if (vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_EVIP_TYPE))
+			if (vrrp_handle_ipaddress(vrrp, IPADDRESS_ADD, VRRP_EVIP_TYPE, false))
 				added_ip_addr = true;
 		}
 #ifdef _HAVE_FIB_ROUTING_
diff --git a/keepalived/vrrp/vrrp_daemon.c b/keepalived/vrrp/vrrp_daemon.c
index 1c2f9e89..32bf4560 100644
--- a/keepalived/vrrp/vrrp_daemon.c
+++ b/keepalived/vrrp/vrrp_daemon.c
@@ -103,7 +103,7 @@ stop_vrrp(int status)
 	netlink_rulelist(vrrp_data->static_rules, IPRULE_DEL, false);
 	netlink_rtlist(vrrp_data->static_routes, IPROUTE_DEL);
 #endif
-	netlink_iplist(vrrp_data->static_addresses, IPADDRESS_DEL);
+	netlink_iplist(vrrp_data->static_addresses, IPADDRESS_DEL, false);
 
 #ifdef _WITH_SNMP_
 	if (global_data->enable_snmp_keepalived || global_data->enable_snmp_rfcv2 || global_data->enable_snmp_rfcv3)
@@ -245,7 +245,7 @@ start_vrrp(void)
 	}
 	else {
 		/* Clear leftover static entries */
-		netlink_iplist(vrrp_data->static_addresses, IPADDRESS_DEL);
+		netlink_iplist(vrrp_data->static_addresses, IPADDRESS_DEL, false);
 #ifdef _HAVE_FIB_ROUTING_
 		netlink_rtlist(vrrp_data->static_routes, IPROUTE_DEL);
 		netlink_error_ignore = ENOENT;
@@ -286,7 +286,7 @@ start_vrrp(void)
 #endif
 
 	/* Set static entries */
-	netlink_iplist(vrrp_data->static_addresses, IPADDRESS_ADD);
+	netlink_iplist(vrrp_data->static_addresses, IPADDRESS_ADD, false);
 #ifdef _HAVE_FIB_ROUTING_
 	netlink_rtlist(vrrp_data->static_routes, IPROUTE_ADD);
 	netlink_rulelist(vrrp_data->static_rules, IPRULE_ADD, false);
diff --git a/keepalived/vrrp/vrrp_ipaddress.c b/keepalived/vrrp/vrrp_ipaddress.c
index eb332e72..e8dca912 100644
--- a/keepalived/vrrp/vrrp_ipaddress.c
+++ b/keepalived/vrrp/vrrp_ipaddress.c
@@ -143,7 +143,7 @@ netlink_ipaddress(ip_address_t *ipaddress, int cmd)
 
 /* Add/Delete a list of IP addresses */
 bool
-netlink_iplist(list ip_list, int cmd)
+netlink_iplist(list ip_list, int cmd, bool force)
 {
 	ip_address_t *ipaddr;
 	element e;
@@ -161,7 +161,7 @@ netlink_iplist(list ip_list, int cmd)
 		ipaddr = ELEMENT_DATA(e);
 		if ((cmd == IPADDRESS_ADD && !ipaddr->set) ||
 		    (cmd == IPADDRESS_DEL &&
-		     (ipaddr->set || __test_bit(DONT_RELEASE_VRRP_BIT, &debug)))) {
+		     (force || ipaddr->set || __test_bit(DONT_RELEASE_VRRP_BIT, &debug)))) {
 			if (netlink_ipaddress(ipaddr, cmd) > 0) {
 				ipaddr->set = !(cmd == IPADDRESS_DEL);
 				changed_entries = true;
@@ -581,7 +581,7 @@ clear_diff_address(struct ipt_handle *h, list l, list n)
 	/* All addresses removed */
 	if (LIST_ISEMPTY(n)) {
 		log_message(LOG_INFO, "Removing a complete VIP or e-VIP block");
-		netlink_iplist(l, IPADDRESS_DEL);
+		netlink_iplist(l, IPADDRESS_DEL, false);
 		handle_iptable_rule_to_iplist(h, l, IPADDRESS_DEL, false);
 		return;
 	}
-- 
2.25.1