summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/nm-device.c1
-rw-r--r--src/devices/tests/test-arping.c6
-rw-r--r--src/devices/tests/test-lldp.c4
-rw-r--r--src/devices/wwan/nm-modem-broadband.c6
-rw-r--r--src/dhcp-manager/nm-dhcp-systemd.c3
-rw-r--r--src/dhcp-manager/nm-dhcp-utils.c5
-rw-r--r--src/dhcp-manager/tests/test-dhcp-utils.c2
-rw-r--r--src/dns-manager/nm-dns-dnsmasq.c10
-rw-r--r--src/dnsmasq-manager/nm-dnsmasq-utils.c2
-rw-r--r--src/dnsmasq-manager/tests/test-dnsmasq-utils.c24
-rw-r--r--src/nm-core-utils.c27
-rw-r--r--src/nm-core-utils.h13
-rw-r--r--src/nm-iface-helper.c3
-rw-r--r--src/nm-ip4-config.c14
-rw-r--r--src/nm-ip4-config.h2
-rw-r--r--src/nm-ip6-config.c44
-rw-r--r--src/nm-ip6-config.h2
-rw-r--r--src/nm-route-manager.c2
-rw-r--r--src/platform/nm-fake-platform.c37
-rw-r--r--src/platform/nm-linux-platform.c468
-rw-r--r--src/platform/nm-linux-platform.h2
-rw-r--r--src/platform/nm-platform-utils.c45
-rw-r--r--src/platform/nm-platform-utils.h3
-rw-r--r--src/platform/nm-platform.c52
-rw-r--r--src/platform/nm-platform.h56
-rw-r--r--src/platform/nmp-object.c222
-rw-r--r--src/platform/nmp-object.h50
-rw-r--r--src/platform/tests/Makefile.am16
-rw-r--r--src/platform/tests/Makefile.in216
-rw-r--r--src/platform/tests/test-address.c46
-rw-r--r--src/platform/tests/test-cleanup.c4
-rw-r--r--src/platform/tests/test-common.c570
-rw-r--r--src/platform/tests/test-common.h105
-rw-r--r--src/platform/tests/test-general.c4
-rw-r--r--src/platform/tests/test-link.c66
-rw-r--r--src/platform/tests/test-route.c46
-rw-r--r--src/ppp-manager/nm-ppp-manager.c14
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c52
-rw-r--r--src/tests/test-general.c117
-rw-r--r--src/tests/test-ip4-config.c88
-rw-r--r--src/tests/test-route-manager.c4
-rw-r--r--src/vpn-manager/nm-vpn-connection.c20
42 files changed, 1531 insertions, 942 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index dde9af94..3d949ec2 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -5725,6 +5725,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self)
 			if (discovered_route->plen > 0) {
 				memset (&route, 0, sizeof (route));
 				route.network = discovered_route->network;
+				nm_assert (discovered_route->plen <= 128);
 				route.plen = discovered_route->plen;
 				route.gateway = discovered_route->gateway;
 				route.source = NM_IP_CONFIG_SOURCE_RDISC;
diff --git a/src/devices/tests/test-arping.c b/src/devices/tests/test-arping.c
index 72d28a7a..244d0715 100644
--- a/src/devices/tests/test-arping.c
+++ b/src/devices/tests/test-arping.c
@@ -79,7 +79,7 @@ test_arping_common (test_fixture *fixture, TestInfo *info)
 		g_assert (nm_arping_manager_add_address (manager, info->addresses[i]));
 
 	for (i = 0; info->peer_addresses[i]; i++) {
-		nmtstp_ip4_address_add (FALSE, fixture->ifindex1, info->peer_addresses[i],
+		nmtstp_ip4_address_add (NULL, FALSE, fixture->ifindex1, info->peer_addresses[i],
 		                        24, 0, 3600, 1800, 0, NULL);
 	}
 
@@ -126,13 +126,13 @@ fixture_teardown (test_fixture *fixture, gconstpointer user_data)
 }
 
 void
-init_tests (int *argc, char ***argv)
+_nmtstp_init_tests (int *argc, char ***argv)
 {
 	nmtst_init_with_logging (argc, argv, NULL, "ALL");
 }
 
 void
-setup_tests (void)
+_nmtstp_setup_tests (void)
 {
 	g_test_add ("/arping/1", test_fixture, NULL, fixture_setup, test_arping_1, fixture_teardown);
 	g_test_add ("/arping/2", test_fixture, NULL, fixture_setup, test_arping_2, fixture_teardown);
diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c
index 1b7f536d..bff85e6c 100644
--- a/src/devices/tests/test-lldp.c
+++ b/src/devices/tests/test-lldp.c
@@ -435,13 +435,13 @@ _test_recv_fixture_teardown (TestRecvFixture *fixture, gconstpointer user_data)
 /*****************************************************************************/
 
 void
-init_tests (int *argc, char ***argv)
+_nmtstp_init_tests (int *argc, char ***argv)
 {
 	nmtst_init_assert_logging (argc, argv, "WARN", "ALL");
 }
 
 void
-setup_tests (void)
+_nmtstp_setup_tests (void)
 {
 #define _TEST_ADD_RECV(testpath, testdata) \
 	g_test_add (testpath, TestRecvFixture, testdata, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown)
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index 769e6a27..9539fefd 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -870,7 +870,8 @@ static_stage3_ip4_done (NMModemBroadband *self)
 	address.peer_address = address_network;
 	address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config);
 	address.source = NM_IP_CONFIG_SOURCE_WWAN;
-	nm_ip4_config_add_address (config, &address);
+	if (address.plen <= 32)
+		nm_ip4_config_add_address (config, &address);
 
 	nm_log_info (LOGD_MB, "  address %s/%d", address_string, address.plen);
 
@@ -960,7 +961,8 @@ stage3_ip6_done (NMModemBroadband *self)
 	config = nm_ip6_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port));
 
 	address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv6_config);
-	nm_ip6_config_add_address (config, &address);
+	if (address.plen <= 128)
+		nm_ip6_config_add_address (config, &address);
 
 	nm_log_info (LOGD_MB, "  address %s/%d", address_string, address.plen);
 
diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c
index 91fa8803..5d49c27e 100644
--- a/src/dhcp-manager/nm-dhcp-systemd.c
+++ b/src/dhcp-manager/nm-dhcp-systemd.c
@@ -312,7 +312,8 @@ lease_to_ip4_config (const char *iface,
 				continue;
 			route.network = a.s_addr;
 
-			if (sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0)
+			if (   sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0
+			    || plen > 32)
 				continue;
 			route.plen = plen;
 
diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c
index be563a69..a88a7e6d 100644
--- a/src/dhcp-manager/nm-dhcp-utils.c
+++ b/src/dhcp-manager/nm-dhcp-utils.c
@@ -60,7 +60,7 @@ ip4_process_dhcpcd_rfc3442_routes (const char *str,
 			*slash = '\0';
 			errno = 0;
 			rt_cidr = strtol (slash + 1, NULL, 10);
-			if ((errno == EINVAL) || (errno == ERANGE)) {
+			if (errno || rt_cidr > 32) {
 				nm_log_warn (LOGD_DHCP4, "DHCP provided invalid classless static route cidr: '%s'", slash + 1);
 				continue;
 			}
@@ -382,7 +382,8 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
 	in_addr_t addr;
 	NMPlatformIP4Address address;
 	char *str = NULL;
-	guint32 gwaddr = 0, plen = 0;
+	guint32 gwaddr = 0;
+	guint8 plen = 0;
 
 	g_return_val_if_fail (options != NULL, NULL);
 
diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c
index 162f2dd4..f477c061 100644
--- a/src/dhcp-manager/tests/test-dhcp-utils.c
+++ b/src/dhcp-manager/tests/test-dhcp-utils.c
@@ -208,6 +208,8 @@ ip4_test_route (NMIP4Config *ip4_config,
 	const NMPlatformIP4Route *route;
 	guint32 tmp;
 
+	g_assert (expected_prefix <= 32);
+
 	route = nm_ip4_config_get_route (ip4_config, route_num);
 	g_assert (inet_pton (AF_INET, expected_dest, &tmp) > 0);
 	g_assert (route->network == tmp);
diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c
index 460feaac..5ead5ecf 100644
--- a/src/dns-manager/nm-dns-dnsmasq.c
+++ b/src/dns-manager/nm-dns-dnsmasq.c
@@ -131,18 +131,18 @@ ip6_addr_to_string (const struct in6_addr *addr, const char *iface)
 	char *buf;
 
 	if (IN6_IS_ADDR_V4MAPPED (addr)) {
-		/* inet_ntop is probably supposed to do this for us, but it doesn't */
 		buf = g_malloc (INET_ADDRSTRLEN);
 		nm_utils_inet4_ntop (addr->s6_addr32[3], buf);
 	} else if (!iface || !iface[0] || !IN6_IS_ADDR_LINKLOCAL (addr)) {
 		buf = g_malloc (INET6_ADDRSTRLEN);
 		nm_utils_inet6_ntop (addr, buf);
 	} else {
-		/* If we got a scope identifier, we need use '%' instead of
-		 * '@', since dnsmasq supports '%' in server= addresses
-		 * only since version 2.58 and up
+		/* Need to scope the address with %<zone-id>. Before dnsmasq 2.58,
+		 * only '@' was supported as delimiter. Since 2.58, '@' and '%'
+		 * are supported. Due to a bug, since 2.73 only '%' works properly
+		 * as "server" address.
 		 */
-		buf = g_strconcat (nm_utils_inet6_ntop (addr, NULL), "@", iface, NULL);
+		buf = g_strconcat (nm_utils_inet6_ntop (addr, NULL), "%", iface, NULL);
 	}
 	return buf;
 }
diff --git a/src/dnsmasq-manager/nm-dnsmasq-utils.c b/src/dnsmasq-manager/nm-dnsmasq-utils.c
index bf8faecd..3786f37d 100644
--- a/src/dnsmasq-manager/nm-dnsmasq-utils.c
+++ b/src/dnsmasq-manager/nm-dnsmasq-utils.c
@@ -34,7 +34,7 @@ nm_dnsmasq_utils_get_range (const NMPlatformIP4Address *addr,
                             char **out_error_desc)
 {
 	guint32 host = addr->address;
-	guint32 prefix = addr->plen;
+	guint8 prefix = addr->plen;
 	guint32 netmask = nm_utils_ip4_prefix_to_netmask (prefix);
 	guint32 first, last, reserved;
 
diff --git a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
index 850ae4f6..aeec5879 100644
--- a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
+++ b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
@@ -26,14 +26,6 @@
 
 #include "nm-test-utils.h"
 
-static NMPlatformIP4Address *
-_set_addr (NMPlatformIP4Address *addr, const char *address, int plen)
-{
-	memset (addr, 0, sizeof (*addr));
-	nm_platform_ip4_address_set_addr (addr, nmtst_inet4_from_string (address), plen);
-	return addr;
-}
-
 static void
 test_address_ranges (void)
 {
@@ -42,50 +34,50 @@ test_address_ranges (void)
 	char last[INET_ADDRSTRLEN];
 	char *error_desc = NULL;
 
-	_set_addr (&addr, "192.168.0.1", 24);
+	addr = *nmtst_platform_ip4_address ("192.168.0.1", NULL, 24);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
 	g_assert (error_desc == NULL);
 	g_assert_cmpstr (first, ==, "192.168.0.10");
 	g_assert_cmpstr (last, ==, "192.168.0.254");
 
-	_set_addr (&addr, "192.168.0.99", 24);
+	addr = *nmtst_platform_ip4_address ("192.168.0.99", NULL, 24);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
 	g_assert (error_desc == NULL);
 	g_assert_cmpstr (first, ==, "192.168.0.108");
 	g_assert_cmpstr (last, ==, "192.168.0.254");
 
-	_set_addr (&addr, "192.168.0.254", 24);
+	addr = *nmtst_platform_ip4_address ("192.168.0.254", NULL, 24);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
 	g_assert (error_desc == NULL);
 	g_assert_cmpstr (first, ==, "192.168.0.1");
 	g_assert_cmpstr (last, ==, "192.168.0.245");
 
 	/* Smaller networks */
-	_set_addr (&addr, "1.2.3.1", 30);
+	addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 30);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
 	g_assert (error_desc == NULL);
 	g_assert_cmpstr (first, ==, "1.2.3.2");
 	g_assert_cmpstr (last, ==, "1.2.3.2");
 
-	_set_addr (&addr, "1.2.3.1", 29);
+	addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 29);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
 	g_assert (error_desc == NULL);
 	g_assert_cmpstr (first, ==, "1.2.3.2");
 	g_assert_cmpstr (last, ==, "1.2.3.6");
 
-	_set_addr (&addr, "1.2.3.1", 28);
+	addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 28);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
 	g_assert (error_desc == NULL);
 	g_assert_cmpstr (first, ==, "1.2.3.3");
 	g_assert_cmpstr (last, ==, "1.2.3.14");
 
-	_set_addr (&addr, "1.2.3.1", 26);
+	addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 26);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc));
 	g_assert (error_desc == NULL);
 	g_assert_cmpstr (first, ==, "1.2.3.8");
 	g_assert_cmpstr (last, ==, "1.2.3.62");
 
-	_set_addr (&addr, "1.2.3.1", 31);
+	addr = *nmtst_platform_ip4_address ("1.2.3.1", NULL, 31);
 	g_assert (nm_dnsmasq_utils_get_range (&addr, first, last, &error_desc) == FALSE);
 	g_assert (error_desc);
 	g_free (error_desc);
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
index 6cdd00e0..714aaa92 100644
--- a/src/nm-core-utils.c
+++ b/src/nm-core-utils.c
@@ -233,7 +233,6 @@ nm_ethernet_address_is_valid (gconstpointer addr, gssize len)
 	return TRUE;
 }
 
-
 /* nm_utils_ip4_address_clear_host_address:
  * @addr: source ip6 address
  * @plen: prefix length of network
@@ -279,6 +278,32 @@ nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_
 	return dst;
 }
 
+gboolean
+nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
+{
+	int nbytes;
+	guint8 t, m;
+
+	if (plen >= 128)
+		return memcmp (addr_a, addr_b, sizeof (struct in6_addr)) == 0;
+
+	nbytes = plen / 8;
+	if (nbytes) {
+		if (memcmp (addr_a, addr_b, nbytes) != 0)
+			return FALSE;
+	}
+
+	plen = plen % 8;
+	if (plen == 0)
+		return TRUE;
+
+	m = ~((1 << (8 - plen)) - 1);
+	t = ((((const guint8 *) addr_a))[nbytes]) ^ ((((const guint8 *) addr_b))[nbytes]);
+	return (t & m) == 0;
+}
+
+/*****************************************************************************/
+
 void
 nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
 {
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index f77b43e2..280be047 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -100,6 +100,7 @@ gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
 
 in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
 const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
+gboolean nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
 
 /**
  * nm_utils_ip6_route_metric_normalize:
@@ -220,11 +221,13 @@ fcn_name (lookup_type val, char *buf, gsize len) \
 
 /*****************************************************************************/
 
-#define NM_UTILS_LOOKUP_DEFAULT(v)      return (v)
-#define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached (v)
-#define NM_UTILS_LOOKUP_ITEM(v, n)     (void) 0; case v: return (n); (void) 0
-#define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, ""n"")
-#define NM_UTILS_LOOKUP_ITEM_IGNORE(v) (void) 0; case v: break; (void) 0
+#define NM_UTILS_LOOKUP_DEFAULT(v)            return (v)
+#define NM_UTILS_LOOKUP_DEFAULT_WARN(v)       g_return_val_if_reached (v)
+#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v)  { nm_assert_not_reached (); return (v); }
+#define NM_UTILS_LOOKUP_ITEM(v, n)            (void) 0; case v: return (n); (void) 0
+#define NM_UTILS_LOOKUP_STR_ITEM(v, n)        NM_UTILS_LOOKUP_ITEM(v, ""n"")
+#define NM_UTILS_LOOKUP_ITEM_IGNORE(v)        (void) 0; case v: break; (void) 0
+#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER()   (void) 0; default: break; (void) 0
 
 #define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \
 scope result_type \
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 5a697537..20f7729a 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -213,7 +213,8 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da
 			 * local configuration or user preferences are, so sending routes
 			 * with a prefix length of 0 is quite rude and thus ignored.
 			 */
-			if (discovered_route->plen > 0) {
+			if (   discovered_route->plen > 0
+			    && discovered_route->plen <= 128) {
 				memset (&route, 0, sizeof (route));
 				route.network = discovered_route->network;
 				route.plen = discovered_route->plen;
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 4b27edf7..75caf7e3 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -365,6 +365,8 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu
 				if (addr->plen == 0)
 					continue;
 
+				nm_assert (addr->plen <= 32);
+
 				route.ifindex = ifindex;
 				route.source = NM_IP_CONFIG_SOURCE_KERNEL;
 
@@ -466,6 +468,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
 		nm_ip_address_get_address_binary (s_addr, &address.address);
 		address.peer_address = address.address;
 		address.plen = nm_ip_address_get_prefix (s_addr);
+		nm_assert (address.plen <= 32);
 		address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
 		address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
 		address.source = NM_IP_CONFIG_SOURCE_USER;
@@ -486,7 +489,12 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
 
 		memset (&route, 0, sizeof (route));
 		nm_ip_route_get_dest_binary (s_route, &route.network);
+
 		route.plen = nm_ip_route_get_prefix (s_route);
+		nm_assert (route.plen <= 32);
+		if (route.plen == 0)
+			continue;
+
 		nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
 		if (nm_ip_route_get_metric (s_route) == -1)
 			route.metric = default_route_metric;
@@ -494,8 +502,6 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
 			route.metric = nm_ip_route_get_metric (s_route);
 		route.source = NM_IP_CONFIG_SOURCE_USER;
 
-		g_assert (route.plen > 0);
-
 		nm_ip4_config_add_route (config, &route);
 	}
 
@@ -1328,7 +1334,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail)
 }
 
 gboolean
-nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, int plen)
+nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, guint8 plen)
 {
 	guint naddresses = nm_ip4_config_get_num_addresses (config);
 	int i;
@@ -1567,7 +1573,7 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
 	int i;
 
 	g_return_if_fail (new != NULL);
-	g_return_if_fail (new->plen > 0);
+	g_return_if_fail (new->plen > 0 && new->plen <= 32);
 	g_assert (priv->ifindex);
 
 	for (i = 0; i < priv->routes->len; i++ ) {
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index 02bc8b07..b1a57687 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -79,7 +79,7 @@ void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMe
 void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src);
 void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src);
 gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes);
-gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, int plen);
+gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, guint8 plen);
 void nm_ip4_config_dump (const NMIP4Config *config, const char *detail);
 
 /* Gateways */
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 6d83bd53..8e7bd22c 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -95,24 +95,6 @@ nm_ip6_config_get_ifindex (const NMIP6Config *config)
 
 /******************************************************************/
 
-static gboolean
-same_prefix (const struct in6_addr *address1, const struct in6_addr *address2, int plen)
-{
-	const guint8 *bytes1 = (const guint8 *) address1;
-	const guint8 *bytes2 = (const guint8 *) address2;
-	int nbytes = plen / 8;
-	int nbits = plen % 8;
-	int masked1 = bytes1[nbytes] >> (8 - nbits);
-	int masked2 = bytes2[nbytes] >> (8 - nbits);
-
-	if (nbytes && memcmp (bytes1, bytes2, nbytes))
-		return FALSE;
-
-	return masked1 == masked2;
-}
-
-/******************************************************************/
-
 /**
  * nm_ip6_config_capture_resolv_conf():
  * @nameservers: array of struct in6_addr
@@ -472,6 +454,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
 		memset (&address, 0, sizeof (address));
 		nm_ip_address_get_address_binary (s_addr, &address.address);
 		address.plen = nm_ip_address_get_prefix (s_addr);
+		nm_assert (address.plen <= 128);
 		address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
 		address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
 		address.source = NM_IP_CONFIG_SOURCE_USER;
@@ -488,7 +471,12 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
 
 		memset (&route, 0, sizeof (route));
 		nm_ip_route_get_dest_binary (s_route, &route.network);
+
 		route.plen = nm_ip_route_get_prefix (s_route);
+		nm_assert (route.plen <= 128);
+		if (route.plen == 0)
+			continue;
+
 		nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
 		if (nm_ip_route_get_metric (s_route) == -1)
 			route.metric = default_route_metric;
@@ -496,8 +484,6 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
 			route.metric = nm_ip_route_get_metric (s_route);
 		route.source = NM_IP_CONFIG_SOURCE_USER;
 
-		g_assert (route.plen > 0);
-
 		nm_ip6_config_add_route (config, &route);
 	}
 
@@ -708,16 +694,20 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
 }
 
 gboolean
-nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *network, int plen)
+nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *network, guint8 plen)
 {
 	int num = nm_ip6_config_get_num_addresses (config);
 	int i;
 
+	nm_assert (network);
+	nm_assert (plen <= 128);
+
 	for (i = 0; i < num; i++) {
 		const NMPlatformIP6Address *item = nm_ip6_config_get_address (config, i);
 
-		if (item->plen <= plen && same_prefix (&item->address, network, item->plen) &&
-		    !(item->n_ifa_flags & IFA_F_NOPREFIXROUTE))
+		if (   item->plen <= plen
+		    && !NM_FLAGS_HAS (item->n_ifa_flags, IFA_F_NOPREFIXROUTE)
+		    && nm_utils_ip6_address_same_prefix (&item->address, network, item->plen))
 			return TRUE;
 	}
 
@@ -1415,7 +1405,7 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
 	int i;
 
 	g_return_if_fail (new != NULL);
-	g_return_if_fail (new->plen > 0);
+	g_return_if_fail (new->plen > 0 && new->plen <= 128);
 	g_assert (priv->ifindex);
 
 	for (i = 0; i < priv->routes->len; i++ ) {
@@ -1473,7 +1463,6 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct
 {
 	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
 	guint i;
-	struct in6_addr network2, host2;
 	NMPlatformIP6Route *best_route = NULL;
 
 	g_return_val_if_fail (host && !IN6_IS_ADDR_UNSPECIFIED (host), NULL);
@@ -1487,10 +1476,7 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct
 		if (best_route && best_route->plen > item->plen)
 			continue;
 
-		nm_utils_ip6_address_clear_host_address (&host2, host, item->plen);
-		nm_utils_ip6_address_clear_host_address (&network2, &item->network, item->plen);
-
-		if (!IN6_ARE_ADDR_EQUAL (&network2, &host2))
+		if (!nm_utils_ip6_address_same_prefix (host, &item->network, item->plen))
 			continue;
 
 		if (best_route &&
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index 5ca64ac3..5e66d500 100644
--- a/src/nm-ip6-config.h
+++ b/src/nm-ip6-config.h
@@ -81,7 +81,7 @@ void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMe
 void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src);
 void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src);
 gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);
-int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, int plen);
+int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, guint8 plen);
 void nm_ip6_config_dump (const NMIP6Config *config, const char *detail);
 
 /* Gateways */
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index 3cf24118..05e28c74 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -221,7 +221,7 @@ _v6_route_dest_cmp (const NMPlatformIP6Route *r1, const NMPlatformIP6Route *r2)
 	CMP_AND_RETURN_INT (r1->plen, r2->plen);
 
 	nm_utils_ip6_address_clear_host_address (&n1, &r1->network, r1->plen);
-	nm_utils_ip6_address_clear_host_address (&n2, &r2->network, r2->plen);
+	nm_utils_ip6_address_clear_host_address (&n2, &r2->network, r2->plen );
 	return memcmp (&n1, &n2, sizeof (n1));
 }
 
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index fdb11eac..15d9c543 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -91,17 +91,17 @@ static void link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboo
 static gboolean ip6_address_add (NMPlatform *platform,
                                  int ifindex,
                                  struct in6_addr addr,
-                                 int plen,
+                                 guint8 plen,
                                  struct in6_addr peer_addr,
                                  guint32 lifetime,
                                  guint32 preferred,
                                  guint flags);
-static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen);
+static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen);
 
 /******************************************************************/
 
 static gboolean
-_ip4_address_equal_peer_net (in_addr_t peer1, in_addr_t peer2, int plen)
+_ip4_address_equal_peer_net (in_addr_t peer1, in_addr_t peer2, guint8 plen)
 {
 	return ((peer1 ^ peer2) & nm_utils_ip4_prefix_to_netmask (plen)) == 0;
 }
@@ -886,7 +886,7 @@ static gboolean
 ip4_address_add (NMPlatform *platform,
                  int ifindex,
                  in_addr_t addr,
-                 int plen,
+                 guint8 plen,
                  in_addr_t peer_addr,
                  guint32 lifetime,
                  guint32 preferred,
@@ -938,7 +938,7 @@ static gboolean
 ip6_address_add (NMPlatform *platform,
                  int ifindex,
                  struct in6_addr addr,
-                 int plen,
+                 guint8 plen,
                  struct in6_addr peer_addr,
                  guint32 lifetime,
                  guint32 preferred,
@@ -982,7 +982,7 @@ ip6_address_add (NMPlatform *platform,
 }
 
 static gboolean
-ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
+ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
@@ -1007,7 +1007,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen,
 }
 
 static gboolean
-ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
+ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
@@ -1031,7 +1031,7 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int
 }
 
 static const NMPlatformIP4Address *
-ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
+ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
@@ -1050,7 +1050,7 @@ ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in
 }
 
 static const NMPlatformIP6Address *
-ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
+ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
@@ -1058,8 +1058,9 @@ ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int pl
 	for (i = 0; i < priv->ip6_addresses->len; i++) {
 		NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
 
-		if (address->ifindex == ifindex && address->plen == plen &&
-				IN6_ARE_ADDR_EQUAL (&address->address, &addr))
+		if (   address->ifindex == ifindex
+		    && address->plen == plen
+		    && IN6_ARE_ADDR_EQUAL (&address->address, &addr))
 			return address;
 	}
 
@@ -1129,7 +1130,7 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
 }
 
 static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
+ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
@@ -1153,7 +1154,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
 }
 
 static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
+ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
@@ -1180,7 +1181,7 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
 
 static gboolean
 ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
-               in_addr_t network, int plen, in_addr_t gateway,
+               in_addr_t network, guint8 plen, in_addr_t gateway,
                in_addr_t pref_src, guint32 metric, guint32 mss)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
@@ -1188,6 +1189,8 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
 	guint i;
 	guint8 scope;
 
+	g_assert (plen <= 32);
+
 	scope = gateway == 0 ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
 
 	memset (&route, 0, sizeof (route));
@@ -1247,7 +1250,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
 
 static gboolean
 ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
-               struct in6_addr network, int plen, struct in6_addr gateway,
+               struct in6_addr network, guint8 plen, struct in6_addr gateway,
                guint32 metric, guint32 mss)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
@@ -1313,7 +1316,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
 }
 
 static const NMPlatformIP4Route *
-ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
+ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
@@ -1332,7 +1335,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, g
 }
 
 static const NMPlatformIP6Route *
-ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
+ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	int i;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 3282e698..ded019e6 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -176,13 +176,22 @@
  * Forward declarations and enums
  ******************************************************************/
 
+enum {
+	DELAYED_ACTION_IDX_REFRESH_ALL_LINKS,
+	DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES,
+	DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ADDRESSES,
+	DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ROUTES,
+	DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ROUTES,
+	_DELAYED_ACTION_IDX_REFRESH_ALL_NUM,
+};
+
 typedef enum {
 	DELAYED_ACTION_TYPE_NONE                        = 0,
-	DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS           = (1LL << 0),
-	DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES   = (1LL << 1),
-	DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES   = (1LL << 2),
-	DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES      = (1LL << 3),
-	DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES      = (1LL << 4),
+	DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS           = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_LINKS),
+	DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES   = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES),
+	DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES   = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ADDRESSES),
+	DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES      = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ROUTES),
+	DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES      = (1LL << DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ROUTES),
 	DELAYED_ACTION_TYPE_REFRESH_LINK                = (1LL << 5),
 	DELAYED_ACTION_TYPE_MASTER_CONNECTED            = (1LL << 6),
 	DELAYED_ACTION_TYPE_READ_NETLINK                = (1LL << 7),
@@ -198,6 +207,10 @@ typedef enum {
 	DELAYED_ACTION_TYPE_MAX                         = __DELAYED_ACTION_TYPE_MAX -1,
 } DelayedActionType;
 
+#define FOR_EACH_DELAYED_ACTION(iflags, flags_all) \
+	for ((iflags) = (DelayedActionType) 0x1LL; (iflags) <= DELAYED_ACTION_TYPE_MAX; (iflags) <<= 1) \
+		if (NM_FLAGS_HAS (flags_all, iflags))
+
 typedef enum {
 	/* Negative values are errors from kernel. Add dummy member to
 	 * make enum signed. */
@@ -290,49 +303,9 @@ _support_user_ipv6ll_detect (struct nlattr **tb)
  * Various utilities
  ******************************************************************/
 
-static guint
-_nm_ip_config_source_to_rtprot (NMIPConfigSource source)
-{
-	switch (source) {
-	case NM_IP_CONFIG_SOURCE_UNKNOWN:
-		return RTPROT_UNSPEC;
-	case NM_IP_CONFIG_SOURCE_KERNEL:
-	case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
-		return RTPROT_KERNEL;
-	case NM_IP_CONFIG_SOURCE_DHCP:
-		return RTPROT_DHCP;
-	case NM_IP_CONFIG_SOURCE_RDISC:
-		return RTPROT_RA;
-
-	default:
-		return RTPROT_STATIC;
-	}
-}
-
-static NMIPConfigSource
-_nm_ip_config_source_from_rtprot (guint rtprot)
-{
-	switch (rtprot) {
-	case RTPROT_UNSPEC:
-		return NM_IP_CONFIG_SOURCE_UNKNOWN;
-	case RTPROT_KERNEL:
-		return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
-	case RTPROT_REDIRECT:
-		return NM_IP_CONFIG_SOURCE_KERNEL;
-	case RTPROT_RA:
-		return NM_IP_CONFIG_SOURCE_RDISC;
-	case RTPROT_DHCP:
-		return NM_IP_CONFIG_SOURCE_DHCP;
-
-	default:
-		return NM_IP_CONFIG_SOURCE_USER;
-	}
-}
-
 static void
-clear_host_address (int family, const void *network, int plen, void *dst)
+clear_host_address (int family, const void *network, guint8 plen, void *dst)
 {
-	g_return_if_fail (plen == (guint8)plen);
 	g_return_if_fail (network);
 
 	switch (family) {
@@ -1641,6 +1614,9 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
 	           ? sizeof (in_addr_t)
 	           : sizeof (struct in6_addr);
 
+	if (ifa->ifa_prefixlen > (is_v4 ? 32 : 128))
+		goto errout;
+
 	/*****************************************************************/
 
 	obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ADDRESS : NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
@@ -1779,6 +1755,9 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
 	           ? sizeof (in_addr_t)
 	           : sizeof (struct in6_addr);
 
+	if (rtm->rtm_dst_len > (is_v4 ? 32 : 128))
+		goto errout;
+
 	/*****************************************************************
 	 * parse nexthops. Only handle routes with one nh.
 	 *****************************************************************/
@@ -1906,7 +1885,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
 		 * */
 		obj->ip_route.source = _NM_IP_CONFIG_SOURCE_RTM_F_CLONED;
 	} else
-		obj->ip_route.source = _nm_ip_config_source_from_rtprot (rtm->rtm_protocol);
+		obj->ip_route.source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol);
 
 	obj_result = obj;
 	obj = NULL;
@@ -2158,7 +2137,7 @@ _nl_msg_new_address (int nlmsg_type,
                      int family,
                      int ifindex,
                      gconstpointer address,
-                     int plen,
+                     guint8 plen,
                      gconstpointer peer_address,
                      guint32 flags,
                      int scope,
@@ -2255,7 +2234,7 @@ _nl_msg_new_route (int nlmsg_type,
                    NMIPConfigSource source,
                    unsigned char scope,
                    gconstpointer network,
-                   int plen,
+                   guint8 plen,
                    gconstpointer gateway,
                    guint32 metric,
                    guint32 mss,
@@ -2266,7 +2245,7 @@ _nl_msg_new_route (int nlmsg_type,
 		.rtm_family = family,
 		.rtm_tos = 0,
 		.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
-		.rtm_protocol = _nm_ip_config_source_to_rtprot (source),
+		.rtm_protocol = nmp_utils_ip_config_source_to_rtprot (source),
 		.rtm_scope = scope,
 		.rtm_type = RTN_UNICAST,
 		.rtm_flags = 0,
@@ -2369,9 +2348,10 @@ _support_kernel_extended_ifa_flags_get (void)
 
 typedef struct {
 	guint32 seq_number;
-	gint64 timeout_abs_ns;
 	WaitForNlResponseResult seq_result;
+	gint64 timeout_abs_ns;
 	WaitForNlResponseResult *out_seq_result;
+	gint *out_refresh_all_in_progess;
 } DelayedActionWaitForNlResponseData;
 
 typedef struct _NMLinuxPlatformPrivate NMLinuxPlatformPrivate;
@@ -2379,7 +2359,10 @@ typedef struct _NMLinuxPlatformPrivate NMLinuxPlatformPrivate;
 struct _NMLinuxPlatformPrivate {
 	struct nl_sock *nlh;
 	guint32 nlh_seq_next;
+#ifdef NM_MORE_LOGGING
 	guint32 nlh_seq_last_handled;
+#endif
+	guint32 nlh_seq_last_seen;
 	NMPCache *cache;
 	GIOChannel *event_channel;
 	guint event_id;
@@ -2390,10 +2373,18 @@ struct _NMLinuxPlatformPrivate {
 	GUdevClient *udev_client;
 
 	struct {
+		/* which delayed actions are scheduled, as marked in @flags.
+		 * Some types have additional arguments in the fields below. */
 		DelayedActionType flags;
+
+		/* counter that a refresh all action is in progress, separated
+		 * by type. */
+		gint refresh_all_in_progess[_DELAYED_ACTION_IDX_REFRESH_ALL_NUM];
+
 		GPtrArray *list_master_connected;
 		GPtrArray *list_refresh_link;
 		GArray *list_wait_for_nl_response;
+
 		gint is_handling;
 	} delayed_action;
 
@@ -2412,12 +2403,21 @@ NM_LINUX_PLATFORM_GET_PRIVATE (const void *self)
 
 G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM)
 
+NMPlatform *
+nm_linux_platform_new (gboolean netns_support)
+{
+	return g_object_new (NM_TYPE_LINUX_PLATFORM,
+	                     NM_PLATFORM_REGISTER_SINGLETON, FALSE,
+	                     NM_PLATFORM_NETNS_SUPPORT, netns_support,
+	                     NULL);
+}
+
 void
 nm_linux_platform_setup (void)
 {
 	g_object_new (NM_TYPE_LINUX_PLATFORM,
-	              NM_PLATFORM_NETNS_SUPPORT, FALSE,
 	              NM_PLATFORM_REGISTER_SINGLETON, TRUE,
+	              NM_PLATFORM_NETNS_SUPPORT, FALSE,
 	              NULL);
 }
 
@@ -2733,49 +2733,51 @@ do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cach
 
 /******************************************************************/
 
-static DelayedActionType
-delayed_action_refresh_from_object_type (NMPObjectType obj_type)
-{
-	switch (obj_type) {
-	case NMP_OBJECT_TYPE_LINK:          return DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS;
-	case NMP_OBJECT_TYPE_IP4_ADDRESS:   return DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES;
-	case NMP_OBJECT_TYPE_IP6_ADDRESS:   return DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES;
-	case NMP_OBJECT_TYPE_IP4_ROUTE:     return DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES;
-	case NMP_OBJECT_TYPE_IP6_ROUTE:     return DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES;
-	default: g_return_val_if_reached (DELAYED_ACTION_TYPE_NONE);
-	}
-}
-
-static NMPObjectType
-delayed_action_refresh_to_object_type (DelayedActionType action_type)
-{
-	switch (action_type) {
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS:             return NMP_OBJECT_TYPE_LINK;
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES:     return NMP_OBJECT_TYPE_IP4_ADDRESS;
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES:     return NMP_OBJECT_TYPE_IP6_ADDRESS;
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES:        return NMP_OBJECT_TYPE_IP4_ROUTE;
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES:        return NMP_OBJECT_TYPE_IP6_ROUTE;
-	default: g_return_val_if_reached (NMP_OBJECT_TYPE_UNKNOWN);
-	}
-}
-
-static const char *
-delayed_action_to_string (DelayedActionType action_type)
-{
-	switch (action_type) {
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS              : return "refresh-all-links";
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES      : return "refresh-all-ip4-addresses";
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES      : return "refresh-all-ip6-addresses";
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES         : return "refresh-all-ip4-routes";
-	case DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES         : return "refresh-all-ip6-routes";
-	case DELAYED_ACTION_TYPE_REFRESH_LINK                   : return "refresh-link";
-	case DELAYED_ACTION_TYPE_MASTER_CONNECTED               : return "master-connected";
-	case DELAYED_ACTION_TYPE_READ_NETLINK                   : return "read-netlink";
-	case DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE           : return "wait-for-nl-response";
-	default:
-		return "unknown";
-	}
-}
+_NM_UTILS_LOOKUP_DEFINE (static, delayed_action_refresh_from_object_type, NMPObjectType, DelayedActionType,
+	NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (DELAYED_ACTION_TYPE_NONE),
+	NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_LINK,        DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS),
+	NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP4_ADDRESS, DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES),
+	NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP6_ADDRESS, DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES),
+	NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP4_ROUTE,   DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES),
+	NM_UTILS_LOOKUP_ITEM (NMP_OBJECT_TYPE_IP6_ROUTE,   DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES),
+	NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (),
+);
+
+_NM_UTILS_LOOKUP_DEFINE (static, delayed_action_refresh_to_object_type, DelayedActionType, NMPObjectType,
+	NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (NMP_OBJECT_TYPE_UNKNOWN),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS,         NMP_OBJECT_TYPE_LINK),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, NMP_OBJECT_TYPE_IP4_ADDRESS),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, NMP_OBJECT_TYPE_IP6_ADDRESS),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES,    NMP_OBJECT_TYPE_IP4_ROUTE),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES,    NMP_OBJECT_TYPE_IP6_ROUTE),
+	NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (),
+);
+
+_NM_UTILS_LOOKUP_DEFINE (static, delayed_action_refresh_all_to_idx, DelayedActionType, guint,
+	NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT (0),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS,         DELAYED_ACTION_IDX_REFRESH_ALL_LINKS),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ADDRESSES),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES,    DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ROUTES),
+	NM_UTILS_LOOKUP_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES,    DELAYED_ACTION_IDX_REFRESH_ALL_IP6_ROUTES),
+	NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (),
+);
+
+NM_UTILS_LOOKUP_STR_DEFINE_STATIC (delayed_action_to_string, DelayedActionType,
+	NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS,         "refresh-all-links"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES, "refresh-all-ip4-addresses"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ADDRESSES, "refresh-all-ip6-addresses"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES,    "refresh-all-ip4-routes"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES,    "refresh-all-ip6-routes"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_REFRESH_LINK,              "refresh-link"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_MASTER_CONNECTED,          "master-connected"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_READ_NETLINK,              "read-netlink"),
+	NM_UTILS_LOOKUP_STR_ITEM (DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE,      "wait-for-nl-response"),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (DELAYED_ACTION_TYPE_NONE),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (DELAYED_ACTION_TYPE_REFRESH_ALL),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (__DELAYED_ACTION_TYPE_MAX),
+);
 
 static const char *
 delayed_action_to_string_full (DelayedActionType action_type, gpointer user_data, char *buf, gsize buf_size)
@@ -2826,6 +2828,24 @@ delayed_action_to_string_full (DelayedActionType action_type, gpointer user_data
 
 /*****************************************************************************/
 
+static gboolean
+delayed_action_refresh_all_in_progress (NMPlatform *platform, DelayedActionType action_type)
+{
+	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+
+	nm_assert (nm_utils_is_power_of_two (action_type));
+	nm_assert (NM_FLAGS_ANY (action_type, DELAYED_ACTION_TYPE_REFRESH_ALL));
+	nm_assert (!NM_FLAGS_ANY (action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL));
+
+	if (NM_FLAGS_ANY (priv->delayed_action.flags, action_type))
+		return TRUE;
+
+	if (priv->delayed_action.refresh_all_in_progess[delayed_action_refresh_all_to_idx (action_type)] > 0)
+		return TRUE;
+
+	return FALSE;
+}
+
 static void
 delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
                                               guint idx,
@@ -2833,7 +2853,6 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	DelayedActionWaitForNlResponseData *data;
-	WaitForNlResponseResult *out_seq_result;
 
 	nm_assert (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
 	nm_assert (idx < priv->delayed_action.list_wait_for_nl_response->len);
@@ -2843,16 +2862,16 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
 
 	_LOGt_delayed_action (DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE, data, "complete");
 
-	out_seq_result = data->out_seq_result;
-
-	g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
-	/* Note: @data is invalidated at this point */
-
-	if (priv->delayed_action.list_wait_for_nl_response->len <= 0)
+	if (priv->delayed_action.list_wait_for_nl_response->len <= 1)
 		priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE;
+	if (data->out_seq_result)
+		*data->out_seq_result = seq_result;
+	if (data->out_refresh_all_in_progess) {
+		nm_assert (*data->out_refresh_all_in_progess > 0);
+		*data->out_refresh_all_in_progess -= 1;
+	}
 
-	if (out_seq_result)
-		*out_seq_result = seq_result;
+	g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
 }
 
 static void
@@ -2961,9 +2980,8 @@ delayed_action_handle_one (NMPlatform *platform)
 		priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL;
 
 		if (_LOGt_ENABLED ()) {
-			for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
-				if (NM_FLAGS_HAS (flags, iflags))
-					_LOGt_delayed_action (iflags, NULL, "handle");
+			FOR_EACH_DELAYED_ACTION (iflags, flags) {
+				_LOGt_delayed_action (iflags, NULL, "handle");
 			}
 		}
 
@@ -3048,9 +3066,8 @@ delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gp
 	priv->delayed_action.flags |= action_type;
 
 	if (_LOGt_ENABLED ()) {
-		for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
-			if (NM_FLAGS_HAS (action_type, iflags))
-				_LOGt_delayed_action (iflags, user_data, "schedule");
+		FOR_EACH_DELAYED_ACTION (iflags, action_type) {
+			_LOGt_delayed_action (iflags, user_data, "schedule");
 		}
 	}
 }
@@ -3058,12 +3075,14 @@ delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gp
 static void
 delayed_action_schedule_WAIT_FOR_NL_RESPONSE (NMPlatform *platform,
                                               guint32 seq_number,
-                                              WaitForNlResponseResult *out_seq_result)
+                                              WaitForNlResponseResult *out_seq_result,
+                                              gint *out_refresh_all_in_progess)
 {
 	DelayedActionWaitForNlResponseData data = {
 		.seq_number = seq_number,
 		.timeout_abs_ns = nm_utils_get_monotonic_timestamp_ns () + (200 * (NM_UTILS_NS_PER_SECOND / 1000)),
 		.out_seq_result = out_seq_result,
+		.out_refresh_all_in_progess = out_refresh_all_in_progess,
 	};
 
 	delayed_action_schedule (platform,
@@ -3150,7 +3169,7 @@ cache_prune_candidates_prune (NMPlatform *platform)
 static void
 cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data)
 {
-	NMPlatform *platform = NM_PLATFORM (user_data);
+	NMPlatform *platform = user_data;
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	const NMPClass *klass;
 	char str_buf[sizeof (_nm_utils_to_string_buffer)];
@@ -3162,6 +3181,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 	nm_assert (ops_type != NMP_CACHE_OPS_REMOVED || (new == NULL && NMP_OBJECT_IS_VALID (old) && nmp_object_is_alive (old)));
 	nm_assert (ops_type != NMP_CACHE_OPS_UPDATED || (NMP_OBJECT_IS_VALID (old) && nmp_object_is_alive (old) && NMP_OBJECT_IS_VALID (new) && nmp_object_is_alive (new)));
 	nm_assert (new == NULL || old == NULL || nmp_object_id_equal (new, old));
+	nm_assert (!old || !new || NMP_OBJECT_GET_CLASS (old) == NMP_OBJECT_GET_CLASS (new));
 
 	klass = old ? NMP_OBJECT_GET_CLASS (old) : NMP_OBJECT_GET_CLASS (new);
 
@@ -3368,17 +3388,56 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 				                         NULL);
 			}
 		}
+		break;
 	default:
 		break;
 	}
 }
 
+static void
+cache_post (NMPlatform *platform,
+            struct nlmsghdr *msghdr,
+            NMPCacheOpsType cache_op,
+            NMPObject *obj,
+            NMPObject *obj_cache)
+{
+	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+
+	nm_assert (NMP_OBJECT_IS_VALID (obj));
+	nm_assert (!obj_cache || nmp_object_id_equal (obj, obj_cache));
+
+	if (msghdr->nlmsg_type == RTM_NEWROUTE) {
+		DelayedActionType action_type;
+
+		action_type = NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP4_ROUTE
+		                  ? DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES
+		                  : DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES;
+		if (   !delayed_action_refresh_all_in_progress (platform, action_type)
+		    && nmp_cache_find_other_route_for_same_destination (priv->cache, obj)) {
+			/* via `iproute route change` the user can update an existing route which effectively
+			 * means that a new object (with a different ID) comes into existance, replacing the
+			 * old on. In other words, as the ID of the object changes, we really see a new
+			 * object with the old one deleted.
+			 * However, kernel decides not to send a RTM_DELROUTE event for that.
+			 *
+			 * To hack around that, check if the update leaves us with multiple routes for the
+			 * same network/plen,metric part. In that case, we cannot do better then requesting
+			 * all routes anew, which sucks.
+			 *
+			 * One mitigation to avoid a dump is only to request a new dump, if we are not in
+			 * the middle of an ongoing dump (delayed_action_refresh_all_in_progress). */
+			delayed_action_schedule (platform, action_type, NULL);
+		}
+	}
+}
+
 /******************************************************************/
 
 static int
 _nl_send_auto_with_seq (NMPlatform *platform,
                         struct nl_msg *nlmsg,
-                        WaitForNlResponseResult *out_seq_result)
+                        WaitForNlResponseResult *out_seq_result,
+                        gint *out_refresh_all_in_progess)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	guint32 seq;
@@ -3393,7 +3452,7 @@ _nl_send_auto_with_seq (NMPlatform *platform,
 
 	if (nle >= 0) {
 		nle = 0;
-		delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result);
+		delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result, out_refresh_all_in_progess);
 	} else
 		_LOGD ("netlink: send: failed sending message: %s (%d)", nl_geterror (nle), nle);
 
@@ -3427,7 +3486,7 @@ do_request_link_no_delayed_actions (NMPlatform *platform, int ifindex, const cha
 	                          0,
 	                          0);
 	if (nlmsg)
-		_nl_send_auto_with_seq (platform, nlmsg, NULL);
+		_nl_send_auto_with_seq (platform, nlmsg, NULL, NULL);
 }
 
 static void
@@ -3446,48 +3505,51 @@ do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType actio
 	nm_assert (!NM_FLAGS_ANY (action_type, ~DELAYED_ACTION_TYPE_REFRESH_ALL));
 	action_type &= DELAYED_ACTION_TYPE_REFRESH_ALL;
 
-	for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
-		if (NM_FLAGS_HAS (action_type, iflags))
-			cache_prune_candidates_record_all (platform, delayed_action_refresh_to_object_type (iflags));
+	FOR_EACH_DELAYED_ACTION (iflags, action_type) {
+		cache_prune_candidates_record_all (platform, delayed_action_refresh_to_object_type (iflags));
 	}
 
-	for (iflags = (DelayedActionType) 0x1LL; iflags <= DELAYED_ACTION_TYPE_MAX; iflags <<= 1) {
-		if (NM_FLAGS_HAS (action_type, iflags)) {
-			NMPObjectType obj_type = delayed_action_refresh_to_object_type (iflags);
-			const NMPClass *klass = nmp_class_from_type (obj_type);
-			nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
-			struct rtgenmsg gmsg = {
-				.rtgen_family = klass->addr_family,
-			};
-			int nle;
-
-			/* clear any delayed action that request a refresh of this object type. */
-			priv->delayed_action.flags &= ~iflags;
-			_LOGt_delayed_action (iflags, NULL, "handle (do-request-all)");
-			if (obj_type == NMP_OBJECT_TYPE_LINK) {
-				priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK;
-				g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0);
-				_LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, NULL, "clear (do-request-all)");
-			}
+	FOR_EACH_DELAYED_ACTION (iflags, action_type) {
+		NMPObjectType obj_type = delayed_action_refresh_to_object_type (iflags);
+		const NMPClass *klass = nmp_class_from_type (obj_type);
+		nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+		struct rtgenmsg gmsg = {
+			.rtgen_family = klass->addr_family,
+		};
+		int nle;
+		gint *out_refresh_all_in_progess;
 
-			event_handler_read_netlink (platform, FALSE);
+		out_refresh_all_in_progess = &priv->delayed_action.refresh_all_in_progess[delayed_action_refresh_all_to_idx (iflags)];
+		nm_assert (*out_refresh_all_in_progess >= 0);
+		*out_refresh_all_in_progess += 1;
 
-			/* reimplement
-			 *   nl_rtgen_request (sk, klass->rtm_gettype, klass->addr_family, NLM_F_DUMP);
-			 * because we need the sequence number.
-			 */
-			nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
-			if (!nlmsg)
-				goto next;
+		/* clear any delayed action that request a refresh of this object type. */
+		priv->delayed_action.flags &= ~iflags;
+		_LOGt_delayed_action (iflags, NULL, "handle (do-request-all)");
+		if (obj_type == NMP_OBJECT_TYPE_LINK) {
+			priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK;
+			g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0);
+			_LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, NULL, "clear (do-request-all)");
+		}
 
-			nle = nlmsg_append (nlmsg, &gmsg, sizeof (gmsg), NLMSG_ALIGNTO);
-			if (nle < 0)
-				goto next;
+		event_handler_read_netlink (platform, FALSE);
 
-			_nl_send_auto_with_seq (platform, nlmsg, NULL);
+		/* reimplement
+		 *   nl_rtgen_request (sk, klass->rtm_gettype, klass->addr_family, NLM_F_DUMP);
+		 * because we need the sequence number.
+		 */
+		nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
+		if (!nlmsg)
+			continue;
+
+		nle = nlmsg_append (nlmsg, &gmsg, sizeof (gmsg), NLMSG_ALIGNTO);
+		if (nle < 0)
+			continue;
+
+		if (_nl_send_auto_with_seq (platform, nlmsg, NULL, out_refresh_all_in_progess) < 0) {
+			nm_assert (*out_refresh_all_in_progess > 0);
+			*out_refresh_all_in_progess -= 1;
 		}
-next:
-		;
 	}
 }
 
@@ -3499,14 +3561,41 @@ do_request_one_type (NMPlatform *platform, NMPObjectType obj_type)
 }
 
 static void
-event_seq_check (NMPlatform *platform, struct nl_msg *msg, WaitForNlResponseResult seq_result)
+event_seq_check_refresh_all (NMPlatform *platform, guint32 seq_number)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	DelayedActionWaitForNlResponseData *data;
-	guint32 seq_number;
 	guint i;
 
-	seq_number = nlmsg_hdr (msg)->nlmsg_seq;
+	if (NM_IN_SET (seq_number, 0, priv->nlh_seq_last_seen))
+		return;
+
+	if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
+		nm_assert (priv->delayed_action.list_wait_for_nl_response->len > 0);
+
+		for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) {
+			data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
+
+			if (data->seq_number == priv->nlh_seq_last_seen) {
+				if (data->out_refresh_all_in_progess) {
+					nm_assert (*data->out_refresh_all_in_progess > 0);
+					*data->out_refresh_all_in_progess -= 1;
+					data->out_refresh_all_in_progess = NULL;
+					break;
+				}
+			}
+		}
+	}
+
+	priv->nlh_seq_last_seen = seq_number;
+}
+
+static void
+event_seq_check (NMPlatform *platform, guint32 seq_number, WaitForNlResponseResult seq_result)
+{
+	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+	DelayedActionWaitForNlResponseData *data;
+	guint i;
 
 	if (seq_number == 0)
 		return;
@@ -3531,9 +3620,11 @@ event_seq_check (NMPlatform *platform, struct nl_msg *msg, WaitForNlResponseResu
 		}
 	}
 
+#ifdef NM_MORE_LOGGING
 	if (seq_number != priv->nlh_seq_last_handled)
 		_LOGt ("netlink: recvmsg: unwaited sequence number %u", seq_number);
 	priv->nlh_seq_last_handled = seq_number;
+#endif
 }
 
 static void
@@ -3581,6 +3672,9 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
 	case RTM_NEWADDR:
 	case RTM_NEWROUTE:
 		cache_op = nmp_cache_update_netlink (priv->cache, obj, &obj_cache, &was_visible, cache_pre_hook, platform);
+
+		cache_post (platform, msghdr, cache_op, obj, obj_cache);
+
 		do_emit_signal (platform, obj_cache, cache_op, was_visible);
 		break;
 
@@ -3730,7 +3824,7 @@ do_add_link_with_lookup (NMPlatform *platform,
 		}
 	}
 
-	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
+	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
 	if (nle < 0) {
 		_LOGE ("do-add-link[%s/%s]: failed sending netlink request \"%s\" (%d)",
 		       name,
@@ -3781,7 +3875,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
 
 	event_handler_read_netlink (platform, FALSE);
 
-	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
+	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
 	if (nle < 0) {
 		_LOGE ("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)",
 		       NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
@@ -3834,7 +3928,7 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
 
 	event_handler_read_netlink (platform, FALSE);
 
-	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
+	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
 	if (nle < 0) {
 		_LOGE ("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)",
 		       NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
@@ -3895,7 +3989,7 @@ do_change_link (NMPlatform *platform,
 		return NM_PLATFORM_ERROR_UNSPECIFIED;
 
 retry:
-	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result);
+	nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
 	if (nle < 0) {
 		_LOGE ("do-change-link[%d]: failure sending netlink request \"%s\" (%d)",
 		       ifindex,
@@ -3964,7 +4058,7 @@ link_add (NMPlatform *platform,
 	       name, nm_link_type_to_string (type), (int) type);
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -4356,7 +4450,7 @@ vlan_add (NMPlatform *platform,
 	       name, parent, vlan_id, (unsigned int) vlan_flags);
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -4400,7 +4494,7 @@ link_gre_add (NMPlatform *platform,
 	       nm_utils_inet4_ntop (props->remote, buffer));
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -4456,7 +4550,7 @@ link_ip6tnl_add (NMPlatform *platform,
 	       nm_utils_inet6_ntop (&props->remote, buffer));
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -4516,7 +4610,7 @@ link_ipip_add (NMPlatform *platform,
 	       nm_utils_inet4_ntop (props->remote, buffer));
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -4566,7 +4660,7 @@ link_macvlan_add (NMPlatform *platform,
 	       props->mode);
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -4616,7 +4710,7 @@ link_sit_add (NMPlatform *platform,
 	       nm_utils_inet4_ntop (props->remote, buffer));
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -4665,7 +4759,7 @@ link_vxlan_add (NMPlatform *platform,
 	       name, props->parent_ifindex, props->id);
 
 	nlmsg = _nl_msg_new_link (RTM_NEWLINK,
-	                          NLM_F_CREATE,
+	                          NLM_F_CREATE | NLM_F_EXCL,
 	                          0,
 	                          name,
 	                          0,
@@ -5266,7 +5360,7 @@ static gboolean
 ip4_address_add (NMPlatform *platform,
                  int ifindex,
                  in_addr_t addr,
-                 int plen,
+                 guint8 plen,
                  in_addr_t peer_addr,
                  guint32 lifetime,
                  guint32 preferred,
@@ -5297,7 +5391,7 @@ static gboolean
 ip6_address_add (NMPlatform *platform,
                  int ifindex,
                  struct in6_addr addr,
-                 int plen,
+                 guint8 plen,
                  struct in6_addr peer_addr,
                  guint32 lifetime,
                  guint32 preferred,
@@ -5324,7 +5418,7 @@ ip6_address_add (NMPlatform *platform,
 }
 
 static gboolean
-ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
+ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
 {
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
 	NMPObject obj_id;
@@ -5349,7 +5443,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen,
 }
 
 static gboolean
-ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
+ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
 {
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
 	NMPObject obj_id;
@@ -5374,7 +5468,7 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int
 }
 
 static const NMPlatformIP4Address *
-ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
+ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 plen, in_addr_t peer_address)
 {
 	NMPObject obj_id;
 	const NMPObject *obj;
@@ -5387,7 +5481,7 @@ ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in
 }
 
 static const NMPlatformIP6Address *
-ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
+ip6_address_get (NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
 {
 	NMPObject obj_id;
 	const NMPObject *obj;
@@ -5454,7 +5548,7 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl
 
 static gboolean
 ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
-               in_addr_t network, int plen, in_addr_t gateway,
+               in_addr_t network, guint8 plen, in_addr_t gateway,
                in_addr_t pref_src, guint32 metric, guint32 mss)
 {
 	NMPObject obj_id;
@@ -5479,7 +5573,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
 
 static gboolean
 ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
-               struct in6_addr network, int plen, struct in6_addr gateway,
+               struct in6_addr network, guint8 plen, struct in6_addr gateway,
                guint32 metric, guint32 mss)
 {
 	NMPObject obj_id;
@@ -5503,7 +5597,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
 }
 
 static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
+ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
@@ -5559,7 +5653,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
 }
 
 static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
+ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
 {
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
 	NMPObject obj_id;
@@ -5587,7 +5681,7 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
 }
 
 static const NMPlatformIP4Route *
-ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
+ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
 {
 	NMPObject obj_id;
 	const NMPObject *obj;
@@ -5600,7 +5694,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, g
 }
 
 static const NMPlatformIP6Route *
-ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
+ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
 {
 	NMPObject obj_id;
 	const NMPObject *obj;
@@ -5684,6 +5778,8 @@ continue_reading:
 	while (nlmsg_ok (hdr, n)) {
 		nm_auto_nlmsg struct nl_msg *msg = NULL;
 		gboolean abort_parsing = FALSE;
+		gboolean process_valid_msg = FALSE;
+		guint32 seq_number;
 
 		msg = nlmsg_convert (hdr);
 		if (!msg) {
@@ -5768,7 +5864,21 @@ continue_reading:
 				seq_result = -errsv;
 			} else
 				seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
-		} else {
+		} else
+			process_valid_msg = TRUE;
+
+		seq_number = nlmsg_hdr (msg)->nlmsg_seq;
+
+		/* check whether the seq number is different from before, and
+		 * whether the previous number (@nlh_seq_last_seen) is a pending
+		 * refresh-all request. In that case, the pending request is thereby
+		 * completed.
+		 *
+		 * We must do that before processing the message with event_valid_msg(),
+		 * because we must track the completion of the pending request before that. */
+		event_seq_check_refresh_all (platform, seq_number);
+
+		if (process_valid_msg) {
 			/* Valid message (not checking for MULTIPART bit to
 			 * get along with broken kernels. NL_SKIP has no
 			 * effect on this.  */
@@ -5778,7 +5888,7 @@ continue_reading:
 			seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
 		}
 
-		event_seq_check (platform, msg, seq_result);
+		event_seq_check (platform, seq_number, seq_result);
 
 		if (abort_parsing)
 			goto stop;
diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h
index a9e2cd82..4ae2fd14 100644
--- a/src/platform/nm-linux-platform.h
+++ b/src/platform/nm-linux-platform.h
@@ -48,6 +48,8 @@ typedef struct {
 
 GType nm_linux_platform_get_type (void);
 
+NMPlatform *nm_linux_platform_new (gboolean netns_support);
+
 void nm_linux_platform_setup (void);
 
 #endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index d0c92a78..b4542adf 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -30,6 +30,7 @@
 #include <linux/sockios.h>
 #include <linux/mii.h>
 #include <linux/version.h>
+#include <linux/rtnetlink.h>
 
 #include "nm-utils.h"
 #include "nm-setting-wired.h"
@@ -412,6 +413,10 @@ out:
 	return g_intern_string (driver);
 }
 
+/******************************************************************************
+ * utils
+ *****************************************************************************/
+
 gboolean
 nmp_utils_device_exists (const char *name)
 {
@@ -427,3 +432,43 @@ nmp_utils_device_exists (const char *name)
 	nm_utils_ifname_cpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], name);
 	return g_file_test (sysdir, G_FILE_TEST_EXISTS);
 }
+
+guint
+nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source)
+{
+	switch (source) {
+	case NM_IP_CONFIG_SOURCE_UNKNOWN:
+		return RTPROT_UNSPEC;
+	case NM_IP_CONFIG_SOURCE_KERNEL:
+	case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
+		return RTPROT_KERNEL;
+	case NM_IP_CONFIG_SOURCE_DHCP:
+		return RTPROT_DHCP;
+	case NM_IP_CONFIG_SOURCE_RDISC:
+		return RTPROT_RA;
+
+	default:
+		return RTPROT_STATIC;
+	}
+}
+
+NMIPConfigSource
+nmp_utils_ip_config_source_from_rtprot (guint rtprot)
+{
+	switch (rtprot) {
+	case RTPROT_UNSPEC:
+		return NM_IP_CONFIG_SOURCE_UNKNOWN;
+	case RTPROT_KERNEL:
+		return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
+	case RTPROT_REDIRECT:
+		return NM_IP_CONFIG_SOURCE_KERNEL;
+	case RTPROT_RA:
+		return NM_IP_CONFIG_SOURCE_RDISC;
+	case RTPROT_DHCP:
+		return NM_IP_CONFIG_SOURCE_DHCP;
+
+	default:
+		return NM_IP_CONFIG_SOURCE_USER;
+	}
+}
+
diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h
index 976bd8db..f2594747 100644
--- a/src/platform/nm-platform-utils.h
+++ b/src/platform/nm-platform-utils.h
@@ -54,4 +54,7 @@ const char *nmp_utils_udev_get_driver (GUdevDevice *device);
 
 gboolean nmp_utils_device_exists (const char *name);
 
+guint            nmp_utils_ip_config_source_to_rtprot   (NMIPConfigSource source);
+NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint rtprot);
+
 #endif /* __NM_PLATFORM_UTILS_H__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 5a399b31..69b0d420 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2459,8 +2459,10 @@ nm_platform_ethtool_get_link_speed (NMPlatform *self, const char *ifname, guint3
 /******************************************************************/
 
 void
-nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, int plen)
+nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, guint8 plen)
 {
+	nm_assert (plen <= 32);
+
 	addr->address = address;
 	addr->peer_address = address;
 	addr->plen = plen;
@@ -2499,7 +2501,7 @@ gboolean
 nm_platform_ip4_address_add (NMPlatform *self,
                              int ifindex,
                              in_addr_t address,
-                             int plen,
+                             guint8 plen,
                              in_addr_t peer_address,
                              guint32 lifetime,
                              guint32 preferred,
@@ -2509,7 +2511,7 @@ nm_platform_ip4_address_add (NMPlatform *self,
 	_CHECK_SELF (self, klass, FALSE);
 
 	g_return_val_if_fail (ifindex > 0, FALSE);
-	g_return_val_if_fail (plen > 0, FALSE);
+	g_return_val_if_fail (plen <= 32, FALSE);
 	g_return_val_if_fail (lifetime > 0, FALSE);
 	g_return_val_if_fail (preferred <= lifetime, FALSE);
 	g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE);
@@ -2537,7 +2539,7 @@ gboolean
 nm_platform_ip6_address_add (NMPlatform *self,
                              int ifindex,
                              struct in6_addr address,
-                             int plen,
+                             guint8 plen,
                              struct in6_addr peer_address,
                              guint32 lifetime,
                              guint32 preferred,
@@ -2546,7 +2548,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
 	_CHECK_SELF (self, klass, FALSE);
 
 	g_return_val_if_fail (ifindex > 0, FALSE);
-	g_return_val_if_fail (plen > 0, FALSE);
+	g_return_val_if_fail (plen <= 128, FALSE);
 	g_return_val_if_fail (lifetime > 0, FALSE);
 	g_return_val_if_fail (preferred <= lifetime, FALSE);
 
@@ -2568,7 +2570,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
 }
 
 gboolean
-nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address)
+nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address)
 {
 	char str_dev[TO_STRING_DEV_BUF_SIZE];
 	char str_peer2[NM_UTILS_INET_ADDRSTRLEN];
@@ -2577,7 +2579,7 @@ nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address
 	_CHECK_SELF (self, klass, FALSE);
 
 	g_return_val_if_fail (ifindex > 0, FALSE);
-	g_return_val_if_fail (plen > 0, FALSE);
+	g_return_val_if_fail (plen <= 32, FALSE);
 
 	_LOGD ("address: deleting IPv4 address %s/%d, %sifindex %d%s",
 	       nm_utils_inet4_ntop (address, NULL), plen,
@@ -2589,14 +2591,14 @@ nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address
 }
 
 gboolean
-nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen)
+nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen)
 {
 	char str_dev[TO_STRING_DEV_BUF_SIZE];
 
 	_CHECK_SELF (self, klass, FALSE);
 
 	g_return_val_if_fail (ifindex > 0, FALSE);
-	g_return_val_if_fail (plen > 0, FALSE);
+	g_return_val_if_fail (plen <= 128, FALSE);
 
 	_LOGD ("address: deleting IPv6 address %s/%d, ifindex %d%s",
 	       nm_utils_inet6_ntop (&address, NULL), plen, ifindex,
@@ -2605,21 +2607,21 @@ nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr a
 }
 
 const NMPlatformIP4Address *
-nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, guint32 peer_address)
+nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, guint32 peer_address)
 {
 	_CHECK_SELF (self, klass, NULL);
 
-	g_return_val_if_fail (plen > 0, NULL);
+	g_return_val_if_fail (plen <= 32, NULL);
 
 	return klass->ip4_address_get (self, ifindex, address, plen, peer_address);
 }
 
 const NMPlatformIP6Address *
-nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen)
+nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen)
 {
 	_CHECK_SELF (self, klass, NULL);
 
-	g_return_val_if_fail (plen > 0, NULL);
+	g_return_val_if_fail (plen <= 128, NULL);
 
 	return klass->ip6_address_get (self, ifindex, address, plen);
 }
@@ -2854,13 +2856,13 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
 gboolean
 nm_platform_ip4_route_add (NMPlatform *self,
                            int ifindex, NMIPConfigSource source,
-                           in_addr_t network, int plen,
+                           in_addr_t network, guint8 plen,
                            in_addr_t gateway, in_addr_t pref_src,
                            guint32 metric, guint32 mss)
 {
 	_CHECK_SELF (self, klass, FALSE);
 
-	g_return_val_if_fail (0 <= plen && plen <= 32, FALSE);
+	g_return_val_if_fail (plen <= 32, FALSE);
 
 	if (_LOGD_ENABLED ()) {
 		NMPlatformIP4Route route = { 0 };
@@ -2882,12 +2884,12 @@ nm_platform_ip4_route_add (NMPlatform *self,
 gboolean
 nm_platform_ip6_route_add (NMPlatform *self,
                            int ifindex, NMIPConfigSource source,
-                           struct in6_addr network, int plen, struct in6_addr gateway,
+                           struct in6_addr network, guint8 plen, struct in6_addr gateway,
                            guint32 metric, guint32 mss)
 {
 	_CHECK_SELF (self, klass, FALSE);
 
-	g_return_val_if_fail (0 <= plen && plen <= 128, FALSE);
+	g_return_val_if_fail (plen <= 128, FALSE);
 
 	if (_LOGD_ENABLED ()) {
 		NMPlatformIP6Route route = { 0 };
@@ -2906,7 +2908,7 @@ nm_platform_ip6_route_add (NMPlatform *self,
 }
 
 gboolean
-nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric)
+nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
 {
 	char str_dev[TO_STRING_DEV_BUF_SIZE];
 
@@ -2919,7 +2921,7 @@ nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network,
 }
 
 gboolean
-nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric)
+nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
 {
 	char str_dev[TO_STRING_DEV_BUF_SIZE];
 
@@ -2932,7 +2934,7 @@ nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr net
 }
 
 const NMPlatformIP4Route *
-nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric)
+nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
 {
 	_CHECK_SELF (self, klass, FALSE);
 
@@ -2940,7 +2942,7 @@ nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int
 }
 
 const NMPlatformIP6Route *
-nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric)
+nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
 {
 	_CHECK_SELF (self, klass, FALSE);
 
@@ -3631,7 +3633,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
 	            "%s%s" /* scope */
 	            "%s%s" /* pref-src */
 	            "",
-	            s_network, route->plen,
+	            s_network,
+	            route->plen,
 	            s_gateway,
 	            str_dev,
 	            route->metric,
@@ -3678,7 +3681,8 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
 	            " mss %"G_GUINT32_FORMAT
 	            " src %s" /* source */
 	            "",
-	            s_network, route->plen,
+	            s_network,
+	            route->plen,
 	            s_gateway,
 	            str_dev,
 	            route->metric,
@@ -4257,7 +4261,7 @@ nm_platform_class_init (NMPlatformClass *platform_class)
 	g_object_class_install_property
 	 (object_class, PROP_NETNS_SUPPORT,
 	     g_param_spec_boolean (NM_PLATFORM_NETNS_SUPPORT, "", "",
-	                           FALSE,
+	                           NM_PLATFORM_NETNS_SUPPORT_DEFAULT,
 	                           G_PARAM_WRITABLE |
 	                           G_PARAM_CONSTRUCT_ONLY |
 	                           G_PARAM_STATIC_STRINGS));
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 15bd2fde..9f055b04 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -40,6 +40,8 @@
 #define NM_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PLATFORM))
 #define NM_PLATFORM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PLATFORM, NMPlatformClass))
 
+#define NM_PLATFORM_NETNS_SUPPORT_DEFAULT    FALSE
+
 /******************************************************************/
 
 #define NM_PLATFORM_NETNS_SUPPORT      "netns-support"
@@ -226,7 +228,7 @@ typedef struct {
 	 * IFA_FLAGS attribute. */ \
 	guint32 n_ifa_flags; \
 	\
-	int plen; \
+	guint8 plen; \
 	;
 
 /**
@@ -302,7 +304,7 @@ typedef union {
 #define __NMPlatformIPRoute_COMMON \
 	__NMPlatformObject_COMMON; \
 	NMIPConfigSource source; \
-	int plen; \
+	guint8 plen; \
 	guint32 metric; \
 	guint32 mss; \
 	;
@@ -593,7 +595,7 @@ typedef struct {
 	gboolean (*ip4_address_add) (NMPlatform *,
 	                             int ifindex,
 	                             in_addr_t address,
-	                             int plen,
+	                             guint8 plen,
 	                             in_addr_t peer_address,
 	                             guint32 lifetime,
 	                             guint32 preferred_lft,
@@ -602,28 +604,28 @@ typedef struct {
 	gboolean (*ip6_address_add) (NMPlatform *,
 	                             int ifindex,
 	                             struct in6_addr address,
-	                             int plen,
+	                             guint8 plen,
 	                             struct in6_addr peer_address,
 	                             guint32 lifetime,
 	                             guint32 preferred_lft,
 	                             guint32 flags);
-	gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
-	gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
-	const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
-	const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
+	gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
+	gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
+	const NMPlatformIP4Address *(*ip4_address_get) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
+	const NMPlatformIP6Address *(*ip6_address_get) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
 
 	GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
 	GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
 	gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
-	                           in_addr_t network, int plen, in_addr_t gateway,
+	                           in_addr_t network, guint8 plen, in_addr_t gateway,
 	                           in_addr_t pref_src, guint32 metric, guint32 mss);
 	gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
-	                           struct in6_addr network, int plen, struct in6_addr gateway,
+	                           struct in6_addr network, guint8 plen, struct in6_addr gateway,
 	                           guint32 metric, guint32 mss);
-	gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric);
-	gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric);
-	const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric);
-	const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric);
+	gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
+	gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
+	const NMPlatformIP4Route *(*ip4_route_get) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
+	const NMPlatformIP6Route *(*ip6_route_get) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
 
 	gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
 	gboolean (*check_support_user_ipv6ll) (NMPlatform *);
@@ -835,10 +837,10 @@ guint32     nm_platform_mesh_get_channel      (NMPlatform *self, int ifindex);
 gboolean    nm_platform_mesh_set_channel      (NMPlatform *self, int ifindex, guint32 channel);
 gboolean    nm_platform_mesh_set_ssid         (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len);
 
-void                   nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, int plen);
+void                   nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, guint8 plen);
 const struct in6_addr *nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr);
 
-const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
+const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
 
 NMPlatformError nm_platform_link_gre_add (NMPlatform *self,
                                           const char *name,
@@ -862,13 +864,13 @@ NMPlatformError nm_platform_link_sit_add (NMPlatform *self,
                                           const NMPlatformLnkSit *props,
                                           const NMPlatformLink **out_link);
 
-const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
+const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen);
 GArray *nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex);
 GArray *nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex);
 gboolean nm_platform_ip4_address_add (NMPlatform *self,
                                       int ifindex,
                                       in_addr_t address,
-                                      int plen,
+                                      guint8 plen,
                                       in_addr_t peer_address,
                                       guint32 lifetime,
                                       guint32 preferred_lft,
@@ -877,29 +879,29 @@ gboolean nm_platform_ip4_address_add (NMPlatform *self,
 gboolean nm_platform_ip6_address_add (NMPlatform *self,
                                       int ifindex,
                                       struct in6_addr address,
-                                      int plen,
+                                      guint8 plen,
                                       struct in6_addr peer_address,
                                       guint32 lifetime,
                                       guint32 preferred_lft,
                                       guint32 flags);
-gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
-gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
+gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
+gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen);
 gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses);
 gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, gboolean keep_link_local);
 gboolean nm_platform_address_flush (NMPlatform *self, int ifindex);
 
-const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric);
-const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric);
+const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
+const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
 GArray *nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
 GArray *nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
 gboolean nm_platform_ip4_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
-                                    in_addr_t network, int plen, in_addr_t gateway,
+                                    in_addr_t network, guint8 plen, in_addr_t gateway,
                                     in_addr_t pref_src, guint32 metric, guint32 mss);
 gboolean nm_platform_ip6_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
-                                    struct in6_addr network, int plen, struct in6_addr gateway,
+                                    struct in6_addr network, guint8 plen, struct in6_addr gateway,
                                     guint32 metric, guint32 mss);
-gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, int plen, guint32 metric);
-gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, int plen, guint32 metric);
+gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
+gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
 
 const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len);
 const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index adeb3aab..eb7e1ca4 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -343,7 +343,7 @@ _vt_cmd_obj_stackinit_id_link (NMPObject *obj, const NMPObject *src)
 }
 
 const NMPObject *
-nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, int plen, guint32 peer_address)
+nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address)
 {
 	nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL);
 	obj->ip4_address.ifindex = ifindex;
@@ -360,7 +360,7 @@ _vt_cmd_obj_stackinit_id_ip4_address (NMPObject *obj, const NMPObject *src)
 }
 
 const NMPObject *
-nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, int plen)
+nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, guint8 plen)
 {
 	nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
 	obj->ip4_address.ifindex = ifindex;
@@ -377,7 +377,7 @@ _vt_cmd_obj_stackinit_id_ip6_address (NMPObject *obj, const NMPObject *src)
 }
 
 const NMPObject *
-nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, int plen, guint32 metric)
+nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric)
 {
 	nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
 	obj->ip4_route.ifindex = ifindex;
@@ -394,7 +394,7 @@ _vt_cmd_obj_stackinit_id_ip4_route (NMPObject *obj, const NMPObject *src)
 }
 
 const NMPObject *
-nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, int plen, guint32 metric)
+nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric)
 {
 	nmp_object_stackinit (obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
 	obj->ip6_route.ifindex = ifindex;
@@ -952,26 +952,46 @@ _vt_cmd_obj_is_visible_link (const NMPObject *obj)
 
 /******************************************************************/
 
+#define _STRUCT_SIZE(struct_type, field) \
+	(G_STRUCT_OFFSET (struct_type, field) + sizeof (((struct_type *) NULL)->field))
+
+_NM_UTILS_LOOKUP_DEFINE (static, _nmp_cache_id_size_by_type, NMPCacheIdType, guint,
+	NM_UTILS_LOOKUP_DEFAULT (({ nm_assert_not_reached (); sizeof (NMPCacheId); })),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_OBJECT_TYPE,                            _STRUCT_SIZE (NMPCacheId, object_type)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,               _STRUCT_SIZE (NMPCacheId, object_type)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT,              _STRUCT_SIZE (NMPCacheId, object_type)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT,            _STRUCT_SIZE (NMPCacheId, object_type)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX,           _STRUCT_SIZE (NMPCacheId, object_type_by_ifindex)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT,   _STRUCT_SIZE (NMPCacheId, object_type_by_ifindex)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT, _STRUCT_SIZE (NMPCacheId, object_type_by_ifindex)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_LINK_BY_IFNAME,                         _STRUCT_SIZE (NMPCacheId, link_by_ifname)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4,              _STRUCT_SIZE (NMPCacheId, routes_by_destination_ip4)),
+	NM_UTILS_LOOKUP_ITEM (NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6,              _STRUCT_SIZE (NMPCacheId, routes_by_destination_ip6)),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (NMP_CACHE_ID_TYPE_NONE),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (__NMP_CACHE_ID_TYPE_MAX),
+);
+
 gboolean
 nmp_cache_id_equal (const NMPCacheId *a, const NMPCacheId *b)
 {
-	/* just memcmp() the entire id. This is potentially dangerous, because
-	 * the struct is not __attribute__((packed)) and not all types have the
-	 * same size. It is important, to memset() the entire struct to 0,
-	 * not only the relevant fields.
-	 *
-	 * You anyway should use the nmp_cache_id_init_*() functions on a stack-allocated
-	 * struct. */
-	return memcmp (a, b, sizeof (NMPCacheId)) == 0;
+	if (a->_id_type != b->_id_type)
+		return FALSE;
+	return memcmp (a, b, _nmp_cache_id_size_by_type (a->_id_type)) == 0;
 }
 
 guint
 nmp_cache_id_hash (const NMPCacheId *id)
 {
 	guint hash = 5381;
-	guint i;
+	guint i, n;
 
-	for (i = 0; i < sizeof (NMPCacheId); i++)
+	/* for hashing we only iterate over the actually set bytes and skip the
+	 * zero padding at the end (which depends on the type of the id).
+	 *
+	 * For the equal implementation, we don't care about that and compare the
+	 * entire NMPCacheId sized struct. */
+	n = _nmp_cache_id_size_by_type (id->_id_type);
+	for (i = 0; i < n; i++)
 		hash = ((hash << 5) + hash) + ((char *) id)[i]; /* hash * 33 + c */
 	return hash;
 }
@@ -980,27 +1000,42 @@ NMPCacheId *
 nmp_cache_id_clone (const NMPCacheId *id)
 {
 	NMPCacheId *id2;
+	guint n;
 
-	id2 = g_slice_new (NMPCacheId);
-	memcpy (id2, id, sizeof (NMPCacheId));
+	n = _nmp_cache_id_size_by_type (id->_id_type);
+	id2 = g_slice_alloc (n);
+	memcpy (id2, id, n);
 	return id2;
 }
 
 void
 nmp_cache_id_destroy (NMPCacheId *id)
 {
-	g_slice_free (NMPCacheId, id);
+	guint n;
+
+	n = _nmp_cache_id_size_by_type (id->_id_type);
+	g_slice_free1 (n, id);
 }
 
 /******************************************************************/
 
 NMPCacheId _nmp_cache_id_static;
 
-static NMPCacheId *
+static void
 _nmp_cache_id_init (NMPCacheId *id, NMPCacheIdType id_type)
 {
 	memset (id, 0, sizeof (NMPCacheId));
 	id->_id_type = id_type;
+}
+
+NMPCacheId *
+nmp_cache_id_copy (NMPCacheId *id, const NMPCacheId *src)
+{
+	guint n;
+
+	memset (id, 0, sizeof (NMPCacheId));
+	n = _nmp_cache_id_size_by_type (src->_id_type);
+	memcpy (id, src, n);
 	return id;
 }
 
@@ -1028,7 +1063,7 @@ nmp_cache_id_init_addrroute_visible_by_ifindex (NMPCacheId *id,
 
 	_nmp_cache_id_init (id, NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX);
 	id->object_type_by_ifindex.obj_type = obj_type;
-	id->object_type_by_ifindex.ifindex = ifindex;
+	memcpy (&id->object_type_by_ifindex._misaligned_ifindex, &ifindex, sizeof (int));
 	return id;
 }
 
@@ -1055,7 +1090,7 @@ nmp_cache_id_init_routes_visible (NMPCacheId *id,
 		g_return_val_if_reached (NULL);
 
 	id->object_type_by_ifindex.obj_type = obj_type;
-	id->object_type_by_ifindex.ifindex = ifindex;
+	memcpy (&id->object_type_by_ifindex._misaligned_ifindex, &ifindex, sizeof (int));
 	return id;
 }
 
@@ -1077,6 +1112,33 @@ nmp_cache_id_init_link_by_ifname (NMPCacheId *id,
 	return id;
 }
 
+NMPCacheId *
+nmp_cache_id_init_routes_by_destination_ip4 (NMPCacheId *id,
+                                             guint32 network,
+                                             guint8 plen,
+                                             guint32 metric)
+{
+	_nmp_cache_id_init (id, NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4);
+	id->routes_by_destination_ip4.plen = plen;
+	memcpy (&id->routes_by_destination_ip4._misaligned_metric,  &metric, sizeof (guint32));
+	memcpy (&id->routes_by_destination_ip4._misaligned_network, &network, sizeof (guint32));
+	return id;
+}
+
+NMPCacheId *
+nmp_cache_id_init_routes_by_destination_ip6 (NMPCacheId *id,
+                                             const struct in6_addr *network,
+                                             guint8 plen,
+                                             guint32 metric)
+{
+	_nmp_cache_id_init (id, NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6);
+	id->routes_by_destination_ip4.plen = plen;
+	memcpy (&id->routes_by_destination_ip6._misaligned_metric,  &metric, sizeof (guint32));
+	if (network)
+		memcpy (&id->routes_by_destination_ip6._misaligned_network, network, sizeof (struct in6_addr));
+	return id;
+}
+
 /******************************************************************/
 
 static gboolean
@@ -1100,6 +1162,13 @@ _nmp_object_init_cache_id (const NMPObject *obj, NMPCacheIdType id_type, NMPCach
 	}
 }
 
+static const guint8 _supported_cache_ids_link[] = {
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE,
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
+	NMP_CACHE_ID_TYPE_LINK_BY_IFNAME,
+	0,
+};
+
 static gboolean
 _vt_cmd_obj_init_cache_id_link (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id)
 {
@@ -1117,6 +1186,13 @@ _vt_cmd_obj_init_cache_id_link (const NMPObject *obj, NMPCacheIdType id_type, NM
 	return TRUE;
 }
 
+static const guint8 _supported_cache_ids_ipx_address[] = {
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE,
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
+	NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX,
+	0,
+};
+
 static gboolean
 _vt_cmd_obj_init_cache_id_ipx_address (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id)
 {
@@ -1135,6 +1211,30 @@ _vt_cmd_obj_init_cache_id_ipx_address (const NMPObject *obj, NMPCacheIdType id_t
 	return TRUE;
 }
 
+static const guint8 _supported_cache_ids_ip4_route[] = {
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE,
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
+	NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4,
+	0,
+};
+
+static const guint8 _supported_cache_ids_ip6_route[] = {
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE,
+	NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY,
+	NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT,
+	NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6,
+	0,
+};
+
 static gboolean
 _vt_cmd_obj_init_cache_id_ipx_route (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id)
 {
@@ -1178,6 +1278,18 @@ _vt_cmd_obj_init_cache_id_ipx_route (const NMPObject *obj, NMPCacheIdType id_typ
 			return TRUE;
 		}
 		break;
+	case NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4:
+		if (NMP_OBJECT_GET_CLASS (obj)->obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) {
+			*out_id = nmp_cache_id_init_routes_by_destination_ip4 (id, obj->ip4_route.network, obj->ip_route.plen, obj->ip_route.metric);
+			return TRUE;
+		}
+		return FALSE;
+	case NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6:
+		if (NMP_OBJECT_GET_CLASS (obj)->obj_type == NMP_OBJECT_TYPE_IP6_ROUTE) {
+			*out_id = nmp_cache_id_init_routes_by_destination_ip6 (id, &obj->ip6_route.network, obj->ip_route.plen, obj->ip_route.metric);
+			return TRUE;
+		}
+		return FALSE;
 	default:
 		return FALSE;
 	}
@@ -1346,6 +1458,51 @@ nmp_cache_lookup_link (const NMPCache *cache, int ifindex)
 	return nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&obj_needle, ifindex));
 }
 
+/**
+ * nmp_cache_find_other_route_for_same_destination:
+ * @cache:
+ * @route:
+ *
+ * Look into the cache whether there is a route to the same destination,
+ * in terms of network/plen,metric.
+ *
+ * Returns: (transfer none): the first found route object from the cache
+ *   that has the same (network/plen,metric) values as @route, but has different
+ *   ID. Or %NULL, if no such route exists.
+ */
+const NMPObject *
+nmp_cache_find_other_route_for_same_destination (const NMPCache *cache, const NMPObject *route)
+{
+	NMPCacheId cache_id;
+	const NMPlatformObject *const *list;
+
+	nm_assert (cache);
+
+	switch (NMP_OBJECT_GET_TYPE (route)) {
+	case NMP_OBJECT_TYPE_IP4_ROUTE:
+		nmp_cache_id_init_routes_by_destination_ip4 (&cache_id, route->ip4_route.network, route->ip_route.plen, route->ip_route.metric);
+		break;
+	case NMP_OBJECT_TYPE_IP6_ROUTE:
+		nmp_cache_id_init_routes_by_destination_ip6 (&cache_id, &route->ip6_route.network, route->ip_route.plen, route->ip_route.metric);
+		break;
+	default:
+		g_return_val_if_reached (NULL);
+	}
+
+	list = nmp_cache_lookup_multi (cache, &cache_id, NULL);
+	if (list) {
+		for (; *list; list++) {
+			const NMPObject *candidate = NMP_OBJECT_UP_CAST (*list);
+
+			nm_assert (NMP_OBJECT_GET_CLASS (route) == NMP_OBJECT_GET_CLASS (candidate));
+
+			if (!nmp_object_id_equal (route, candidate))
+				return candidate;
+		}
+	}
+	return NULL;
+}
+
 const NMPObject *
 nmp_cache_lookup_link_full (const NMPCache *cache,
                             int ifindex,
@@ -1425,13 +1582,13 @@ nmp_cache_lookup_all_to_hash (const NMPCache *cache,
 static void
 _nmp_cache_update_cache (NMPCache *cache, NMPObject *obj, gboolean remove)
 {
-	NMPCacheIdType id_type;
+	const guint8 *id_type;
 
-	for (id_type = 0; id_type <= NMP_CACHE_ID_TYPE_MAX; id_type++) {
+	for (id_type = NMP_OBJECT_GET_CLASS (obj)->supported_cache_ids; *id_type; id_type++) {
 		NMPCacheId cache_id_storage;
 		const NMPCacheId *cache_id;
 
-		if (!_nmp_object_init_cache_id (obj, id_type, &cache_id_storage, &cache_id))
+		if (!_nmp_object_init_cache_id (obj, *id_type, &cache_id_storage, &cache_id))
 			continue;
 		if (!cache_id)
 			continue;
@@ -1480,19 +1637,19 @@ _nmp_cache_update_remove (NMPCache *cache, NMPObject *obj)
 static void
 _nmp_cache_update_update (NMPCache *cache, NMPObject *obj, const NMPObject *new)
 {
-	NMPCacheIdType id_type;
+	const guint8 *id_type;
 
 	nm_assert (NMP_OBJECT_GET_CLASS (obj) == NMP_OBJECT_GET_CLASS (new));
 	nm_assert (obj->is_cached);
 	nm_assert (!new->is_cached);
 
-	for (id_type = 0; id_type <= NMP_CACHE_ID_TYPE_MAX; id_type++) {
+	for (id_type = NMP_OBJECT_GET_CLASS (obj)->supported_cache_ids; *id_type; id_type++) {
 		NMPCacheId cache_id_storage_obj, cache_id_storage_new;
 		const NMPCacheId *cache_id_obj, *cache_id_new;
 
-		if (!_nmp_object_init_cache_id (obj, id_type, &cache_id_storage_obj, &cache_id_obj))
+		if (!_nmp_object_init_cache_id (obj, *id_type, &cache_id_storage_obj, &cache_id_obj))
 			continue;
-		if (!_nmp_object_init_cache_id (new, id_type, &cache_id_storage_new, &cache_id_new))
+		if (!_nmp_object_init_cache_id (new, *id_type, &cache_id_storage_new, &cache_id_new))
 			g_assert_not_reached ();
 		if (!nm_multi_index_move (cache->idx_multi, (NMMultiIndexId *) cache_id_obj, (NMMultiIndexId *) cache_id_new, &obj->object))
 			g_assert_not_reached ();
@@ -1891,13 +2048,13 @@ ASSERT_nmp_cache_is_consistent (const NMPCache *cache)
 
 	g_hash_table_iter_init (&iter_hash, cache->idx_main);
 	while (g_hash_table_iter_next (&iter_hash, (gpointer *) &obj, NULL)) {
-		NMPCacheIdType id_type;
+		const guint8 *id_type;
 
 		g_assert (NMP_OBJECT_IS_VALID (obj));
 		g_assert (nmp_object_is_alive (obj));
 
-		for (id_type = 0; id_type <= NMP_CACHE_ID_TYPE_MAX; id_type++) {
-			if (!_nmp_object_init_cache_id (obj, id_type, &cache_id_storage, &cache_id))
+		for (id_type = NMP_OBJECT_GET_CLASS (obj)->supported_cache_ids; *id_type; id_type++) {
+			if (!_nmp_object_init_cache_id (obj, *id_type, &cache_id_storage, &cache_id))
 				continue;
 			if (!cache_id)
 				continue;
@@ -1943,6 +2100,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.rtm_gettype                        = RTM_GETLINK,
 		.signal_type_id                     = NM_PLATFORM_SIGNAL_ID_LINK,
 		.signal_type                        = NM_PLATFORM_SIGNAL_LINK_CHANGED,
+		.supported_cache_ids                = _supported_cache_ids_link,
 		.cmd_obj_init_cache_id              = _vt_cmd_obj_init_cache_id_link,
 		.cmd_obj_cmp                        = _vt_cmd_obj_cmp_link,
 		.cmd_obj_copy                       = _vt_cmd_obj_copy_link,
@@ -1967,6 +2125,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.rtm_gettype                        = RTM_GETADDR,
 		.signal_type_id                     = NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS,
 		.signal_type                        = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
+		.supported_cache_ids                = _supported_cache_ids_ipx_address,
 		.cmd_obj_init_cache_id              = _vt_cmd_obj_init_cache_id_ipx_address,
 		.cmd_obj_stackinit_id               = _vt_cmd_obj_stackinit_id_ip4_address,
 		.cmd_obj_is_alive                   = _vt_cmd_obj_is_alive_ipx_address,
@@ -1986,6 +2145,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.rtm_gettype                        = RTM_GETADDR,
 		.signal_type_id                     = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
 		.signal_type                        = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
+		.supported_cache_ids                = _supported_cache_ids_ipx_address,
 		.cmd_obj_init_cache_id              = _vt_cmd_obj_init_cache_id_ipx_address,
 		.cmd_obj_stackinit_id               = _vt_cmd_obj_stackinit_id_ip6_address,
 		.cmd_obj_is_alive                   = _vt_cmd_obj_is_alive_ipx_address,
@@ -2005,6 +2165,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.rtm_gettype                        = RTM_GETROUTE,
 		.signal_type_id                     = NM_PLATFORM_SIGNAL_ID_IP4_ROUTE,
 		.signal_type                        = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
+		.supported_cache_ids                = _supported_cache_ids_ip4_route,
 		.cmd_obj_init_cache_id              = _vt_cmd_obj_init_cache_id_ipx_route,
 		.cmd_obj_stackinit_id               = _vt_cmd_obj_stackinit_id_ip4_route,
 		.cmd_obj_is_alive                   = _vt_cmd_obj_is_alive_ipx_route,
@@ -2024,6 +2185,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.rtm_gettype                        = RTM_GETROUTE,
 		.signal_type_id                     = NM_PLATFORM_SIGNAL_ID_IP6_ROUTE,
 		.signal_type                        = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
+		.supported_cache_ids                = _supported_cache_ids_ip6_route,
 		.cmd_obj_init_cache_id              = _vt_cmd_obj_init_cache_id_ipx_route,
 		.cmd_obj_stackinit_id               = _vt_cmd_obj_stackinit_id_ip6_route,
 		.cmd_obj_is_alive                   = _vt_cmd_obj_is_alive_ipx_route,
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index 6d5b9627..c5241037 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -57,6 +57,8 @@ typedef enum { /*< skip >*/
  * matching v4/v6 and ifindex -- or maybe not at all if it isn't visible.
  * */
 typedef enum { /*< skip >*/
+	NMP_CACHE_ID_TYPE_NONE,
+
 	/* all the objects of a certain type */
 	NMP_CACHE_ID_TYPE_OBJECT_TYPE,
 
@@ -77,6 +79,17 @@ typedef enum { /*< skip >*/
 	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT,
 	NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT,
 
+	/* Consider all the destination fields of a route, that is, the ID without the ifindex
+	 * and gateway (meaning: network/plen,metric).
+	 * The reason for this is that `ip route change` can replace an existing route
+	 * and modify it's ifindex/gateway. Effectively, that means it deletes an existing
+	 * route and adds a different one (as the ID of the route changes). However, it only
+	 * sends one RTM_NEWADDR notification without notifying about the deletion. We detect
+	 * that by having this index to contain overlapping routes which require special
+	 * cache-resync. */
+	NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4,
+	NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6,
+
 	__NMP_CACHE_ID_TYPE_MAX,
 	NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1,
 } NMPCacheIdType;
@@ -87,7 +100,7 @@ typedef struct {
 	union {
 		NMMultiIndexId base;
 		guint8 _id_type; /* NMPCacheIdType as guint8 */
-		struct {
+		struct _nm_packed {
 			/* NMP_CACHE_ID_TYPE_OBJECT_TYPE */
 			/* NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY */
 			/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT */
@@ -95,19 +108,33 @@ typedef struct {
 			guint8 _id_type;
 			guint8 obj_type; /* NMPObjectType as guint8 */
 		} object_type;
-		struct {
+		struct _nm_packed {
 			/* NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX */
 			/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT */
 			/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT */
 			guint8 _id_type;
 			guint8 obj_type; /* NMPObjectType as guint8 */
-			int ifindex;
+			int _misaligned_ifindex;
 		} object_type_by_ifindex;
-		struct {
+		struct _nm_packed {
 			/* NMP_CACHE_ID_TYPE_LINK_BY_IFNAME */
 			guint8 _id_type;
 			char ifname_short[IFNAMSIZ - 1]; /* don't include the trailing NUL so the struct fits in 4 bytes. */
 		} link_by_ifname;
+		struct _nm_packed {
+			/* NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6 */
+			guint8 _id_type;
+			guint8 plen;
+			guint32 _misaligned_metric;
+			guint32 _misaligned_network;
+		} routes_by_destination_ip4;
+		struct _nm_packed {
+			/* NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4 */
+			guint8 _id_type;
+			guint8 plen;
+			guint32 _misaligned_metric;
+			struct in6_addr _misaligned_network;
+		} routes_by_destination_ip6;
 	};
 } NMPCacheId;
 
@@ -124,6 +151,8 @@ typedef struct {
 	const char *obj_type_name;
 	const char *signal_type;
 
+	const guint8 *supported_cache_ids;
+
 	/* Only for NMPObjectLnk* types. */
 	NMLinkType lnk_link_type;
 
@@ -341,10 +370,10 @@ NMPObject *nmp_object_new_link (int ifindex);
 const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, const NMPlatformObject *plobj);
 const NMPObject *nmp_object_stackinit_id  (NMPObject *obj, const NMPObject *src);
 const NMPObject *nmp_object_stackinit_id_link (NMPObject *obj, int ifindex);
-const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, int plen, guint32 peer_address);
-const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, int plen);
-const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, int plen, guint32 metric);
-const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, int plen, guint32 metric);
+const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address);
+const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, guint8 plen);
+const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric);
+const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric);
 
 const char *nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size);
 int nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2);
@@ -375,16 +404,21 @@ guint nmp_cache_id_hash (const NMPCacheId *id);
 NMPCacheId *nmp_cache_id_clone (const NMPCacheId *id);
 void nmp_cache_id_destroy (NMPCacheId *id);
 
+NMPCacheId *nmp_cache_id_copy (NMPCacheId *id, const NMPCacheId *src);
 NMPCacheId *nmp_cache_id_init_object_type (NMPCacheId *id, NMPObjectType obj_type, gboolean visible_only);
 NMPCacheId *nmp_cache_id_init_addrroute_visible_by_ifindex (NMPCacheId *id, NMPObjectType obj_type, int ifindex);
 NMPCacheId *nmp_cache_id_init_routes_visible (NMPCacheId *id, NMPObjectType obj_type, gboolean with_default, gboolean with_non_default, int ifindex);
 NMPCacheId *nmp_cache_id_init_link_by_ifname (NMPCacheId *id, const char *ifname);
+NMPCacheId *nmp_cache_id_init_routes_by_destination_ip4 (NMPCacheId *id, guint32 network, guint8 plen, guint32 metric);
+NMPCacheId *nmp_cache_id_init_routes_by_destination_ip6 (NMPCacheId *id, const struct in6_addr *network, guint8 plen, guint32 metric);
 
 const NMPlatformObject *const *nmp_cache_lookup_multi (const NMPCache *cache, const NMPCacheId *cache_id, guint *out_len);
 GArray *nmp_cache_lookup_multi_to_array (const NMPCache *cache, NMPObjectType obj_type, const NMPCacheId *cache_id);
 const NMPObject *nmp_cache_lookup_obj (const NMPCache *cache, const NMPObject *obj);
 const NMPObject *nmp_cache_lookup_link (const NMPCache *cache, int ifindex);
 
+const NMPObject *nmp_cache_find_other_route_for_same_destination (const NMPCache *cache, const NMPObject *route);
+
 const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache,
                                              int ifindex,
                                              const char *ifname,
diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am
index ebf20e15..5af4ce91 100644
--- a/src/platform/tests/Makefile.am
+++ b/src/platform/tests/Makefile.am
@@ -50,56 +50,56 @@ EXTRA_DIST = test-common.h
 monitor_SOURCES = monitor.c $(PLATFORM_SOURCES)
 monitor_LDADD = $(PLATFORM_LDADD)
 
-test_link_fake_SOURCES = test-link.c $(TEST_SOURCES)
+test_link_fake_SOURCES = $(TEST_SOURCES) test-link.c
 test_link_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 test_link_fake_LDADD = $(PLATFORM_LDADD)
 
-test_link_linux_SOURCES = test-link.c $(TEST_SOURCES)
+test_link_linux_SOURCES = $(TEST_SOURCES) test-link.c
 test_link_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
 	-DKERNEL_HACKS=1
 test_link_linux_LDADD = $(PLATFORM_LDADD)
 
-test_address_fake_SOURCES = test-address.c $(TEST_SOURCES)
+test_address_fake_SOURCES = $(TEST_SOURCES) test-address.c
 test_address_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 test_address_fake_LDADD = $(PLATFORM_LDADD)
 
-test_address_linux_SOURCES = test-address.c $(TEST_SOURCES)
+test_address_linux_SOURCES = $(TEST_SOURCES) test-address.c
 test_address_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
 	-DKERNEL_HACKS=1
 test_address_linux_LDADD = $(PLATFORM_LDADD)
 
-test_route_fake_SOURCES = test-route.c $(TEST_SOURCES)
+test_route_fake_SOURCES = $(TEST_SOURCES) test-route.c
 test_route_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 test_route_fake_LDADD = $(PLATFORM_LDADD)
 
-test_route_linux_SOURCES = test-route.c $(TEST_SOURCES)
+test_route_linux_SOURCES = $(TEST_SOURCES) test-route.c
 test_route_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
 	-DKERNEL_HACKS=1
 test_route_linux_LDADD = $(PLATFORM_LDADD)
 
-test_cleanup_fake_SOURCES = test-cleanup.c $(TEST_SOURCES)
+test_cleanup_fake_SOURCES = $(TEST_SOURCES) test-cleanup.c
 test_cleanup_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 test_cleanup_fake_LDADD = $(PLATFORM_LDADD)
 
-test_cleanup_linux_SOURCES = test-cleanup.c $(TEST_SOURCES)
+test_cleanup_linux_SOURCES = $(TEST_SOURCES) test-cleanup.c
 test_cleanup_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in
index 7c4b72ea..60cd6d82 100644
--- a/src/platform/tests/Makefile.in
+++ b/src/platform/tests/Makefile.in
@@ -137,8 +137,8 @@ am__objects_2 = test_address_fake-nm-platform.$(OBJEXT) \
 	test_address_fake-nm-linux-platform.$(OBJEXT)
 am__objects_3 = test_address_fake-test-common.$(OBJEXT) \
 	$(am__objects_2)
-am_test_address_fake_OBJECTS =  \
-	test_address_fake-test-address.$(OBJEXT) $(am__objects_3)
+am_test_address_fake_OBJECTS = $(am__objects_3) \
+	test_address_fake-test-address.$(OBJEXT)
 test_address_fake_OBJECTS = $(am_test_address_fake_OBJECTS)
 test_address_fake_DEPENDENCIES = $(PLATFORM_LDADD)
 am__objects_4 = test_address_linux-nm-platform.$(OBJEXT) \
@@ -146,8 +146,8 @@ am__objects_4 = test_address_linux-nm-platform.$(OBJEXT) \
 	test_address_linux-nm-linux-platform.$(OBJEXT)
 am__objects_5 = test_address_linux-test-common.$(OBJEXT) \
 	$(am__objects_4)
-am_test_address_linux_OBJECTS =  \
-	test_address_linux-test-address.$(OBJEXT) $(am__objects_5)
+am_test_address_linux_OBJECTS = $(am__objects_5) \
+	test_address_linux-test-address.$(OBJEXT)
 test_address_linux_OBJECTS = $(am_test_address_linux_OBJECTS)
 test_address_linux_DEPENDENCIES = $(PLATFORM_LDADD)
 am__objects_6 = test_cleanup_fake-nm-platform.$(OBJEXT) \
@@ -155,8 +155,8 @@ am__objects_6 = test_cleanup_fake-nm-platform.$(OBJEXT) \
 	test_cleanup_fake-nm-linux-platform.$(OBJEXT)
 am__objects_7 = test_cleanup_fake-test-common.$(OBJEXT) \
 	$(am__objects_6)
-am_test_cleanup_fake_OBJECTS =  \
-	test_cleanup_fake-test-cleanup.$(OBJEXT) $(am__objects_7)
+am_test_cleanup_fake_OBJECTS = $(am__objects_7) \
+	test_cleanup_fake-test-cleanup.$(OBJEXT)
 test_cleanup_fake_OBJECTS = $(am_test_cleanup_fake_OBJECTS)
 test_cleanup_fake_DEPENDENCIES = $(PLATFORM_LDADD)
 am__objects_8 = test_cleanup_linux-nm-platform.$(OBJEXT) \
@@ -164,8 +164,8 @@ am__objects_8 = test_cleanup_linux-nm-platform.$(OBJEXT) \
 	test_cleanup_linux-nm-linux-platform.$(OBJEXT)
 am__objects_9 = test_cleanup_linux-test-common.$(OBJEXT) \
 	$(am__objects_8)
-am_test_cleanup_linux_OBJECTS =  \
-	test_cleanup_linux-test-cleanup.$(OBJEXT) $(am__objects_9)
+am_test_cleanup_linux_OBJECTS = $(am__objects_9) \
+	test_cleanup_linux-test-cleanup.$(OBJEXT)
 test_cleanup_linux_OBJECTS = $(am_test_cleanup_linux_OBJECTS)
 test_cleanup_linux_DEPENDENCIES = $(PLATFORM_LDADD)
 am_test_general_OBJECTS = test-general.$(OBJEXT)
@@ -176,8 +176,8 @@ am__objects_10 = test_link_fake-nm-platform.$(OBJEXT) \
 	test_link_fake-nm-linux-platform.$(OBJEXT)
 am__objects_11 = test_link_fake-test-common.$(OBJEXT) \
 	$(am__objects_10)
-am_test_link_fake_OBJECTS = test_link_fake-test-link.$(OBJEXT) \
-	$(am__objects_11)
+am_test_link_fake_OBJECTS = $(am__objects_11) \
+	test_link_fake-test-link.$(OBJEXT)
 test_link_fake_OBJECTS = $(am_test_link_fake_OBJECTS)
 test_link_fake_DEPENDENCIES = $(PLATFORM_LDADD)
 am__objects_12 = test_link_linux-nm-platform.$(OBJEXT) \
@@ -185,8 +185,8 @@ am__objects_12 = test_link_linux-nm-platform.$(OBJEXT) \
 	test_link_linux-nm-linux-platform.$(OBJEXT)
 am__objects_13 = test_link_linux-test-common.$(OBJEXT) \
 	$(am__objects_12)
-am_test_link_linux_OBJECTS = test_link_linux-test-link.$(OBJEXT) \
-	$(am__objects_13)
+am_test_link_linux_OBJECTS = $(am__objects_13) \
+	test_link_linux-test-link.$(OBJEXT)
 test_link_linux_OBJECTS = $(am_test_link_linux_OBJECTS)
 test_link_linux_DEPENDENCIES = $(PLATFORM_LDADD)
 am_test_nmp_object_OBJECTS = test-nmp-object.$(OBJEXT)
@@ -198,8 +198,8 @@ am__objects_14 = test_route_fake-nm-platform.$(OBJEXT) \
 	test_route_fake-nm-linux-platform.$(OBJEXT)
 am__objects_15 = test_route_fake-test-common.$(OBJEXT) \
 	$(am__objects_14)
-am_test_route_fake_OBJECTS = test_route_fake-test-route.$(OBJEXT) \
-	$(am__objects_15)
+am_test_route_fake_OBJECTS = $(am__objects_15) \
+	test_route_fake-test-route.$(OBJEXT)
 test_route_fake_OBJECTS = $(am_test_route_fake_OBJECTS)
 test_route_fake_DEPENDENCIES = $(PLATFORM_LDADD)
 am__objects_16 = test_route_linux-nm-platform.$(OBJEXT) \
@@ -207,8 +207,8 @@ am__objects_16 = test_route_linux-nm-platform.$(OBJEXT) \
 	test_route_linux-nm-linux-platform.$(OBJEXT)
 am__objects_17 = test_route_linux-test-common.$(OBJEXT) \
 	$(am__objects_16)
-am_test_route_linux_OBJECTS = test_route_linux-test-route.$(OBJEXT) \
-	$(am__objects_17)
+am_test_route_linux_OBJECTS = $(am__objects_17) \
+	test_route_linux-test-route.$(OBJEXT)
 test_route_linux_OBJECTS = $(am_test_route_linux_OBJECTS)
 test_route_linux_DEPENDENCIES = $(PLATFORM_LDADD)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -776,56 +776,56 @@ PLATFORM_LDADD = \
 EXTRA_DIST = test-common.h
 monitor_SOURCES = monitor.c $(PLATFORM_SOURCES)
 monitor_LDADD = $(PLATFORM_LDADD)
-test_link_fake_SOURCES = test-link.c $(TEST_SOURCES)
+test_link_fake_SOURCES = $(TEST_SOURCES) test-link.c
 test_link_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 
 test_link_fake_LDADD = $(PLATFORM_LDADD)
-test_link_linux_SOURCES = test-link.c $(TEST_SOURCES)
+test_link_linux_SOURCES = $(TEST_SOURCES) test-link.c
 test_link_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
 	-DKERNEL_HACKS=1
 
 test_link_linux_LDADD = $(PLATFORM_LDADD)
-test_address_fake_SOURCES = test-address.c $(TEST_SOURCES)
+test_address_fake_SOURCES = $(TEST_SOURCES) test-address.c
 test_address_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 
 test_address_fake_LDADD = $(PLATFORM_LDADD)
-test_address_linux_SOURCES = test-address.c $(TEST_SOURCES)
+test_address_linux_SOURCES = $(TEST_SOURCES) test-address.c
 test_address_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
 	-DKERNEL_HACKS=1
 
 test_address_linux_LDADD = $(PLATFORM_LDADD)
-test_route_fake_SOURCES = test-route.c $(TEST_SOURCES)
+test_route_fake_SOURCES = $(TEST_SOURCES) test-route.c
 test_route_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 
 test_route_fake_LDADD = $(PLATFORM_LDADD)
-test_route_linux_SOURCES = test-route.c $(TEST_SOURCES)
+test_route_linux_SOURCES = $(TEST_SOURCES) test-route.c
 test_route_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
 	-DKERNEL_HACKS=1
 
 test_route_linux_LDADD = $(PLATFORM_LDADD)
-test_cleanup_fake_SOURCES = test-cleanup.c $(TEST_SOURCES)
+test_cleanup_fake_SOURCES = $(TEST_SOURCES) test-cleanup.c
 test_cleanup_fake_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_fake_platform_setup \
 	-DKERNEL_HACKS=0
 
 test_cleanup_fake_LDADD = $(PLATFORM_LDADD)
-test_cleanup_linux_SOURCES = test-cleanup.c $(TEST_SOURCES)
+test_cleanup_linux_SOURCES = $(TEST_SOURCES) test-cleanup.c
 test_cleanup_linux_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-DSETUP=nm_linux_platform_setup \
@@ -1047,20 +1047,6 @@ nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_address_fake-test-address.o: test-address.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-address.o -MD -MP -MF $(DEPDIR)/test_address_fake-test-address.Tpo -c -o test_address_fake-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-address.Tpo $(DEPDIR)/test_address_fake-test-address.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_fake-test-address.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
-
-test_address_fake-test-address.obj: test-address.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-address.obj -MD -MP -MF $(DEPDIR)/test_address_fake-test-address.Tpo -c -o test_address_fake-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-address.Tpo $(DEPDIR)/test_address_fake-test-address.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_fake-test-address.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
-
 test_address_fake-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_address_fake-test-common.Tpo -c -o test_address_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-common.Tpo $(DEPDIR)/test_address_fake-test-common.Po
@@ -1117,19 +1103,19 @@ test_address_fake-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_address_linux-test-address.o: test-address.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-address.o -MD -MP -MF $(DEPDIR)/test_address_linux-test-address.Tpo -c -o test_address_linux-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-address.Tpo $(DEPDIR)/test_address_linux-test-address.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_linux-test-address.o' libtool=no @AMDEPBACKSLASH@
+test_address_fake-test-address.o: test-address.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-address.o -MD -MP -MF $(DEPDIR)/test_address_fake-test-address.Tpo -c -o test_address_fake-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-address.Tpo $(DEPDIR)/test_address_fake-test-address.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_fake-test-address.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
 
-test_address_linux-test-address.obj: test-address.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-address.obj -MD -MP -MF $(DEPDIR)/test_address_linux-test-address.Tpo -c -o test_address_linux-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-address.Tpo $(DEPDIR)/test_address_linux-test-address.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_linux-test-address.obj' libtool=no @AMDEPBACKSLASH@
+test_address_fake-test-address.obj: test-address.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_fake-test-address.obj -MD -MP -MF $(DEPDIR)/test_address_fake-test-address.Tpo -c -o test_address_fake-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_fake-test-address.Tpo $(DEPDIR)/test_address_fake-test-address.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_fake-test-address.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_fake-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
 
 test_address_linux-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_address_linux-test-common.Tpo -c -o test_address_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
@@ -1187,19 +1173,19 @@ test_address_linux-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_cleanup_fake-test-cleanup.o: test-cleanup.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-cleanup.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo -c -o test_cleanup_fake-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo $(DEPDIR)/test_cleanup_fake-test-cleanup.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_fake-test-cleanup.o' libtool=no @AMDEPBACKSLASH@
+test_address_linux-test-address.o: test-address.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-address.o -MD -MP -MF $(DEPDIR)/test_address_linux-test-address.Tpo -c -o test_address_linux-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-address.Tpo $(DEPDIR)/test_address_linux-test-address.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_linux-test-address.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-address.o `test -f 'test-address.c' || echo '$(srcdir)/'`test-address.c
 
-test_cleanup_fake-test-cleanup.obj: test-cleanup.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-cleanup.obj -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo -c -o test_cleanup_fake-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo $(DEPDIR)/test_cleanup_fake-test-cleanup.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_fake-test-cleanup.obj' libtool=no @AMDEPBACKSLASH@
+test_address_linux-test-address.obj: test-address.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_address_linux-test-address.obj -MD -MP -MF $(DEPDIR)/test_address_linux-test-address.Tpo -c -o test_address_linux-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_address_linux-test-address.Tpo $(DEPDIR)/test_address_linux-test-address.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-address.c' object='test_address_linux-test-address.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_address_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_address_linux-test-address.obj `if test -f 'test-address.c'; then $(CYGPATH_W) 'test-address.c'; else $(CYGPATH_W) '$(srcdir)/test-address.c'; fi`
 
 test_cleanup_fake-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-common.Tpo -c -o test_cleanup_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
@@ -1257,19 +1243,19 @@ test_cleanup_fake-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_cleanup_linux-test-cleanup.o: test-cleanup.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-cleanup.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo -c -o test_cleanup_linux-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo $(DEPDIR)/test_cleanup_linux-test-cleanup.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_linux-test-cleanup.o' libtool=no @AMDEPBACKSLASH@
+test_cleanup_fake-test-cleanup.o: test-cleanup.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-cleanup.o -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo -c -o test_cleanup_fake-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo $(DEPDIR)/test_cleanup_fake-test-cleanup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_fake-test-cleanup.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
 
-test_cleanup_linux-test-cleanup.obj: test-cleanup.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-cleanup.obj -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo -c -o test_cleanup_linux-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo $(DEPDIR)/test_cleanup_linux-test-cleanup.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_linux-test-cleanup.obj' libtool=no @AMDEPBACKSLASH@
+test_cleanup_fake-test-cleanup.obj: test-cleanup.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_fake-test-cleanup.obj -MD -MP -MF $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo -c -o test_cleanup_fake-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_fake-test-cleanup.Tpo $(DEPDIR)/test_cleanup_fake-test-cleanup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_fake-test-cleanup.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_fake-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
 
 test_cleanup_linux-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-common.Tpo -c -o test_cleanup_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
@@ -1327,19 +1313,19 @@ test_cleanup_linux-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_link_fake-test-link.o: test-link.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-link.o -MD -MP -MF $(DEPDIR)/test_link_fake-test-link.Tpo -c -o test_link_fake-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-link.Tpo $(DEPDIR)/test_link_fake-test-link.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_fake-test-link.o' libtool=no @AMDEPBACKSLASH@
+test_cleanup_linux-test-cleanup.o: test-cleanup.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-cleanup.o -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo -c -o test_cleanup_linux-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo $(DEPDIR)/test_cleanup_linux-test-cleanup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_linux-test-cleanup.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-cleanup.o `test -f 'test-cleanup.c' || echo '$(srcdir)/'`test-cleanup.c
 
-test_link_fake-test-link.obj: test-link.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-link.obj -MD -MP -MF $(DEPDIR)/test_link_fake-test-link.Tpo -c -o test_link_fake-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-link.Tpo $(DEPDIR)/test_link_fake-test-link.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_fake-test-link.obj' libtool=no @AMDEPBACKSLASH@
+test_cleanup_linux-test-cleanup.obj: test-cleanup.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_cleanup_linux-test-cleanup.obj -MD -MP -MF $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo -c -o test_cleanup_linux-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_cleanup_linux-test-cleanup.Tpo $(DEPDIR)/test_cleanup_linux-test-cleanup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-cleanup.c' object='test_cleanup_linux-test-cleanup.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cleanup_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_cleanup_linux-test-cleanup.obj `if test -f 'test-cleanup.c'; then $(CYGPATH_W) 'test-cleanup.c'; else $(CYGPATH_W) '$(srcdir)/test-cleanup.c'; fi`
 
 test_link_fake-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_link_fake-test-common.Tpo -c -o test_link_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
@@ -1397,19 +1383,19 @@ test_link_fake-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_link_linux-test-link.o: test-link.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-link.o -MD -MP -MF $(DEPDIR)/test_link_linux-test-link.Tpo -c -o test_link_linux-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-link.Tpo $(DEPDIR)/test_link_linux-test-link.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_linux-test-link.o' libtool=no @AMDEPBACKSLASH@
+test_link_fake-test-link.o: test-link.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-link.o -MD -MP -MF $(DEPDIR)/test_link_fake-test-link.Tpo -c -o test_link_fake-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-link.Tpo $(DEPDIR)/test_link_fake-test-link.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_fake-test-link.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
 
-test_link_linux-test-link.obj: test-link.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-link.obj -MD -MP -MF $(DEPDIR)/test_link_linux-test-link.Tpo -c -o test_link_linux-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-link.Tpo $(DEPDIR)/test_link_linux-test-link.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_linux-test-link.obj' libtool=no @AMDEPBACKSLASH@
+test_link_fake-test-link.obj: test-link.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_fake-test-link.obj -MD -MP -MF $(DEPDIR)/test_link_fake-test-link.Tpo -c -o test_link_fake-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_fake-test-link.Tpo $(DEPDIR)/test_link_fake-test-link.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_fake-test-link.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_fake-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
 
 test_link_linux-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_link_linux-test-common.Tpo -c -o test_link_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
@@ -1467,19 +1453,19 @@ test_link_linux-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_route_fake-test-route.o: test-route.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-route.o -MD -MP -MF $(DEPDIR)/test_route_fake-test-route.Tpo -c -o test_route_fake-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-route.Tpo $(DEPDIR)/test_route_fake-test-route.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_fake-test-route.o' libtool=no @AMDEPBACKSLASH@
+test_link_linux-test-link.o: test-link.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-link.o -MD -MP -MF $(DEPDIR)/test_link_linux-test-link.Tpo -c -o test_link_linux-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-link.Tpo $(DEPDIR)/test_link_linux-test-link.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_linux-test-link.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-link.o `test -f 'test-link.c' || echo '$(srcdir)/'`test-link.c
 
-test_route_fake-test-route.obj: test-route.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-route.obj -MD -MP -MF $(DEPDIR)/test_route_fake-test-route.Tpo -c -o test_route_fake-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-route.Tpo $(DEPDIR)/test_route_fake-test-route.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_fake-test-route.obj' libtool=no @AMDEPBACKSLASH@
+test_link_linux-test-link.obj: test-link.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_link_linux-test-link.obj -MD -MP -MF $(DEPDIR)/test_link_linux-test-link.Tpo -c -o test_link_linux-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_link_linux-test-link.Tpo $(DEPDIR)/test_link_linux-test-link.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-link.c' object='test_link_linux-test-link.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_link_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_link_linux-test-link.obj `if test -f 'test-link.c'; then $(CYGPATH_W) 'test-link.c'; else $(CYGPATH_W) '$(srcdir)/test-link.c'; fi`
 
 test_route_fake-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-common.o -MD -MP -MF $(DEPDIR)/test_route_fake-test-common.Tpo -c -o test_route_fake-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
@@ -1537,19 +1523,19 @@ test_route_fake-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
-test_route_linux-test-route.o: test-route.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-route.o -MD -MP -MF $(DEPDIR)/test_route_linux-test-route.Tpo -c -o test_route_linux-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-route.Tpo $(DEPDIR)/test_route_linux-test-route.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_linux-test-route.o' libtool=no @AMDEPBACKSLASH@
+test_route_fake-test-route.o: test-route.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-route.o -MD -MP -MF $(DEPDIR)/test_route_fake-test-route.Tpo -c -o test_route_fake-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-route.Tpo $(DEPDIR)/test_route_fake-test-route.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_fake-test-route.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
 
-test_route_linux-test-route.obj: test-route.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-route.obj -MD -MP -MF $(DEPDIR)/test_route_linux-test-route.Tpo -c -o test_route_linux-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-route.Tpo $(DEPDIR)/test_route_linux-test-route.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_linux-test-route.obj' libtool=no @AMDEPBACKSLASH@
+test_route_fake-test-route.obj: test-route.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_fake-test-route.obj -MD -MP -MF $(DEPDIR)/test_route_fake-test-route.Tpo -c -o test_route_fake-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_fake-test-route.Tpo $(DEPDIR)/test_route_fake-test-route.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_fake-test-route.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_fake_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_fake-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
 
 test_route_linux-test-common.o: test-common.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-common.o -MD -MP -MF $(DEPDIR)/test_route_linux-test-common.Tpo -c -o test_route_linux-test-common.o `test -f 'test-common.c' || echo '$(srcdir)/'`test-common.c
@@ -1607,6 +1593,20 @@ test_route_linux-nm-linux-platform.obj: ../nm-linux-platform.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-nm-linux-platform.obj `if test -f '../nm-linux-platform.c'; then $(CYGPATH_W) '../nm-linux-platform.c'; else $(CYGPATH_W) '$(srcdir)/../nm-linux-platform.c'; fi`
 
+test_route_linux-test-route.o: test-route.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-route.o -MD -MP -MF $(DEPDIR)/test_route_linux-test-route.Tpo -c -o test_route_linux-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-route.Tpo $(DEPDIR)/test_route_linux-test-route.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_linux-test-route.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-route.o `test -f 'test-route.c' || echo '$(srcdir)/'`test-route.c
+
+test_route_linux-test-route.obj: test-route.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_route_linux-test-route.obj -MD -MP -MF $(DEPDIR)/test_route_linux-test-route.Tpo -c -o test_route_linux-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_route_linux-test-route.Tpo $(DEPDIR)/test_route_linux-test-route.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-route.c' object='test_route_linux-test-route.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_route_linux_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_route_linux-test-route.obj `if test -f 'test-route.c'; then $(CYGPATH_W) 'test-route.c'; else $(CYGPATH_W) '$(srcdir)/test-route.c'; fi`
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
index 83a0bfd3..05a14448 100644
--- a/src/platform/tests/test-address.c
+++ b/src/platform/tests/test-address.c
@@ -94,12 +94,12 @@ test_ip4_address_general (void)
 
 	/* Add address */
 	g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
+	nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
 	g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
 	accept_signal (address_added);
 
 	/* Add address again (aka update) */
-	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, 0, NULL);
+	nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, 0, NULL);
 	accept_signals (address_changed, 0, 1);
 
 	/* Test address listing */
@@ -114,12 +114,12 @@ test_ip4_address_general (void)
 	g_array_unref (addresses);
 
 	/* Remove address */
-	nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
+	nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr);
 	g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
 	accept_signal (address_removed);
 
 	/* Remove address again */
-	nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
+	nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr);
 
 	free_signal (address_added);
 	free_signal (address_changed);
@@ -144,12 +144,12 @@ test_ip6_address_general (void)
 
 	/* Add address */
 	g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
-	nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
+	nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
 	g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
 	accept_signal (address_added);
 
 	/* Add address again (aka update) */
-	nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
+	nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
 	accept_signals (address_changed, 0, 1);
 
 	/* Test address listing */
@@ -163,12 +163,12 @@ test_ip6_address_general (void)
 	g_array_unref (addresses);
 
 	/* Remove address */
-	nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
+	nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN);
 	g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
 	accept_signal (address_removed);
 
 	/* Remove address again */
-	nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
+	nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN);
 
 	/* ensure not pending signal. */
 	accept_signals (address_changed, 0, 1);
@@ -197,15 +197,15 @@ test_ip4_address_general_2 (void)
 	g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, DEVICE_IFINDEX, NULL));
 
 	/* Add/delete notification */
-	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
+	nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
 	accept_signal (address_added);
 	g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
-	nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
+	nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr);
 	accept_signal (address_removed);
 	g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
 
 	/* Add/delete conflict */
-	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
+	nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, 0, NULL);
 	g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
 	accept_signal (address_added);
 
@@ -227,20 +227,20 @@ test_ip6_address_general_2 (void)
 	inet_pton (AF_INET6, IP6_ADDRESS, &addr);
 
 	/* Add/delete notification */
-	nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
+	nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
 	accept_signal (address_added);
 	g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
 
-	nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
+	nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN);
 	accept_signal (address_removed);
 	g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
 
 	/* Add/delete conflict */
-	nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
+	nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0);
 	accept_signal (address_added);
 	g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
 
-	nmtstp_ip6_address_add (EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
+	nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags);
 	ensure_no_signal (address_added);
 	g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
 
@@ -273,7 +273,7 @@ test_ip4_address_peer (void)
 	accept_signals (address_added, 0, G_MAXINT);
 
 	/* Add/delete notification */
-	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, 0, NULL);
+	nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, 0, NULL);
 	accept_signal (address_added);
 	a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer);
 	g_assert (a);
@@ -281,7 +281,7 @@ test_ip4_address_peer (void)
 
 	nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
 
-	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, 0, NULL);
+	nmtstp_ip4_address_add (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, 0, NULL);
 	accept_signal (address_added);
 	g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
 	a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2);
@@ -290,7 +290,7 @@ test_ip4_address_peer (void)
 	nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
 
 	g_assert (addr != addr_peer);
-	nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr_peer);
+	nmtstp_ip4_address_del (NULL, EX, ifindex, addr, IP4_PLEN, addr_peer);
 	accept_signal (address_removed);
 	g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
 	g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
@@ -308,7 +308,7 @@ test_ip4_address_peer_zero (void)
 	in_addr_t addr, addr_peer;
 	guint32 lifetime = 2000;
 	guint32 preferred = 1000;
-	const int plen = 24;
+	const gint8 plen = 24;
 	const char *label = NULL;
 	in_addr_t peers[3], r_peers[3];
 	int i;
@@ -328,7 +328,7 @@ test_ip4_address_peer_zero (void)
 	for (i = 0; i < G_N_ELEMENTS (peers); i++) {
 		g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
 
-		nmtstp_ip4_address_add (EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label);
+		nmtstp_ip4_address_add (NULL, EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label);
 
 		addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
 		g_assert (addrs);
@@ -343,7 +343,7 @@ test_ip4_address_peer_zero (void)
 	for (i = 0; i < G_N_ELEMENTS (peers); i++) {
 		g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
 
-		nmtstp_ip4_address_del (EX, ifindex, addr, plen, r_peers[i]);
+		nmtstp_ip4_address_del (NULL, EX, ifindex, addr, plen, r_peers[i]);
 
 		addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
 		g_assert (addrs);
@@ -355,7 +355,7 @@ test_ip4_address_peer_zero (void)
 /*****************************************************************************/
 
 void
-init_tests (int *argc, char ***argv)
+_nmtstp_init_tests (int *argc, char ***argv)
 {
 	nmtst_init_with_logging (argc, argv, NULL, "ALL");
 }
@@ -412,7 +412,7 @@ _g_test_add_func (const char *testpath,
 }
 
 void
-setup_tests (void)
+_nmtstp_setup_tests (void)
 {
 	_g_test_add_func ("/address/ipv4/general", test_ip4_address_general);
 	_g_test_add_func ("/address/ipv6/general", test_ip6_address_general);
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index 4036daad..3b52487a 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -107,13 +107,13 @@ test_cleanup_internal (void)
 }
 
 void
-init_tests (int *argc, char ***argv)
+_nmtstp_init_tests (int *argc, char ***argv)
 {
 	nmtst_init_with_logging (argc, argv, NULL, "ALL");
 }
 
 void
-setup_tests (void)
+_nmtstp_setup_tests (void)
 {
 	nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
 	g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME));
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index e9fffe90..b1947a6d 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -27,11 +27,11 @@
 
 #include "test-common.h"
 
-#include "nm-test-utils.h"
-
 #define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)"
 #define SIGNAL_DATA_ARG(data) (data)->name, nm_platform_signal_change_type_to_string ((data)->change_type), (data)->ifindex, (data)->ifname ? " ifname '" : "", (data)->ifname ? (data)->ifname : "", (data)->ifname ? "'" : "", (data)->received_count
 
+/*****************************************************************************/
+
 gboolean
 nmtstp_is_root_test (void)
 {
@@ -47,6 +47,20 @@ nmtstp_is_sysfs_writable (void)
 	       || (access ("/sys/devices", W_OK) == 0);
 }
 
+static void
+_init_platform (NMPlatform **platform, gboolean external_command)
+{
+	g_assert (platform);
+	if (!*platform)
+		*platform = NM_PLATFORM_GET;
+	g_assert (NM_IS_PLATFORM (*platform));
+
+	if (external_command)
+		g_assert (NM_IS_LINUX_PLATFORM (*platform));
+}
+
+/*****************************************************************************/
+
 SignalData *
 add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname)
 {
@@ -180,8 +194,10 @@ link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlat
 		g_error ("Added/changed link not found in the local cache.");
 }
 
+/*****************************************************************************/
+
 gboolean
-ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric)
+nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric)
 {
 	gs_free char *arg_network = NULL;
 	const char *argv[] = {
@@ -205,7 +221,7 @@ ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric)
 	g_assert (!strstr (ifname, " metric "));
 	g_assert (plen >= 0 && plen <= 32);
 
-	if (!NM_IS_LINUX_PLATFORM (nm_platform_get ())) {
+	if (!nmtstp_is_root_test ()) {
 		/* If we don't test against linux-platform, we don't actually configure any
 		 * routes in the system. */
 		return -1;
@@ -259,15 +275,17 @@ ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric)
 }
 
 void
-_assert_ip4_route_exists (const char *file, guint line, const char *func, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric)
+_nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric)
 {
 	int ifindex;
 	gboolean exists_checked;
 
+	_init_platform (&platform, FALSE);
+
 	/* Check for existance of the route by spawning iproute2. Do this because platform
 	 * code might be entirely borked, but we expect ip-route to give a correct result.
 	 * If the ip command cannot be found, we accept this as success. */
-	exists_checked = ip4_route_exists (ifname, network, plen, metric);
+	exists_checked = nmtstp_ip4_route_exists (ifname, network, plen, metric);
 	if (exists_checked != -1 && !exists_checked != !exists) {
 		g_error ("[%s:%u] %s(): We expect the ip4 route %s/%d metric %u %s, but it %s",
 		         file, line, func,
@@ -276,9 +294,9 @@ _assert_ip4_route_exists (const char *file, guint line, const char *func, gboole
 		         exists ? "doesn't" : "does");
 	}
 
-	ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, ifname);
+	ifindex = nm_platform_link_get_ifindex (platform, ifname);
 	g_assert (ifindex > 0);
-	if (!nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric) != !exists) {
+	if (!nm_platform_ip4_route_get (platform, ifindex, network, plen, metric) != !exists) {
 		g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u %s, but platform thinks %s",
 		         file, line, func,
 		         nm_utils_inet4_ntop (network, NULL), plen, metric,
@@ -287,6 +305,8 @@ _assert_ip4_route_exists (const char *file, guint line, const char *func, gboole
 	}
 }
 
+/*****************************************************************************/
+
 int
 nmtstp_run_command (const char *format, ...)
 {
@@ -309,7 +329,7 @@ nmtstp_run_command (const char *format, ...)
 
 typedef struct {
 	GMainLoop *loop;
-	gboolean timeout;
+	guint signal_counts;
 	guint id;
 } WaitForSignalData;
 
@@ -323,6 +343,8 @@ _wait_for_signal_cb (NMPlatform *platform,
 {
 	WaitForSignalData *data = user_data;
 
+	data->signal_counts++;
+	nm_clear_g_source (&data->id);
 	g_main_loop_quit (data->loop);
 }
 
@@ -331,20 +353,19 @@ _wait_for_signal_timeout (gpointer user_data)
 {
 	WaitForSignalData *data = user_data;
 
-	data->timeout = TRUE;
+	g_assert (data->id);
 	data->id = 0;
 	g_main_loop_quit (data->loop);
 	return G_SOURCE_REMOVE;
 }
 
-gboolean
+guint
 nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms)
 {
 	WaitForSignalData data = { 0 };
 	gulong id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route;
 
-	if (!platform)
-		platform = NM_PLATFORM_GET;
+	_init_platform (&platform, FALSE);
 
 	data.loop = g_main_loop_new (NULL, FALSE);
 
@@ -359,33 +380,34 @@ nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms)
 
 	g_main_loop_run (data.loop);
 
+	g_assert (!data.id);
 	g_assert (nm_clear_g_signal_handler (platform, &id_link));
 	g_assert (nm_clear_g_signal_handler (platform, &id_ip4_address));
 	g_assert (nm_clear_g_signal_handler (platform, &id_ip6_address));
 	g_assert (nm_clear_g_signal_handler (platform, &id_ip4_route));
 	g_assert (nm_clear_g_signal_handler (platform, &id_ip6_route));
 
-	if (nm_clear_g_source (&data.id))
-		g_assert (timeout_ms != 0 && !data.timeout);
-
 	g_clear_pointer (&data.loop, g_main_loop_unref);
 
-	return !data.timeout;
+	/* return the number of signals, or 0 if timeout was reached .*/
+	return data.signal_counts;
 }
 
-gboolean
+guint
 nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms)
 {
 	gint64 now;
+	guint signal_counts;
 
 	while (TRUE) {
 		now = nm_utils_get_monotonic_timestamp_ms ();
 
 		if (until_ms < now)
-			return FALSE;
+			return 0;
 
-		if (nmtstp_wait_for_signal (platform, MAX (1, until_ms - now)))
-			return TRUE;
+		signal_counts = nmtstp_wait_for_signal (platform, MAX (1, until_ms - now));
+		if (signal_counts)
+			return signal_counts;
 	}
 }
 
@@ -401,10 +423,12 @@ nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType
 	const NMPlatformLink *plink;
 	gint64 now;
 
+	_init_platform (&platform, FALSE);
+
 	while (TRUE) {
 		now = nm_utils_get_monotonic_timestamp_ms ();
 
-		plink = nm_platform_link_get_by_ifname (platform ?: NM_PLATFORM_GET, ifname);
+		plink = nm_platform_link_get_by_ifname (platform, ifname);
 		if (   plink
 		    && (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type))
 			return plink;
@@ -432,6 +456,8 @@ nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NML
 	return plink;
 }
 
+/*****************************************************************************/
+
 int
 nmtstp_run_command_check_external_global (void)
 {
@@ -460,6 +486,8 @@ nmtstp_run_command_check_external (int external_command)
 	return (nmtst_get_rand_int () % 2) == 0;
 }
 
+/*****************************************************************************/
+
 #define CHECK_LIFETIME_MAX_DIFF    2
 
 gboolean
@@ -556,8 +584,11 @@ nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr,
 	g_assert (nmtstp_ip_address_check_lifetime (addr, n, expected_lifetime, expected_preferred));
 }
 
+/*****************************************************************************/
+
 static void
-_ip_address_add (gboolean external_command,
+_ip_address_add (NMPlatform *platform,
+                 gboolean external_command,
                  gboolean is_v4,
                  int ifindex,
                  const NMIPAddr *address,
@@ -572,6 +603,8 @@ _ip_address_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		const char *ifname;
 		gs_free char *s_valid = NULL;
@@ -579,7 +612,7 @@ _ip_address_add (gboolean external_command,
 		gs_free char *s_label = NULL;
 		char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN];
 
-		ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
+		ifname = nm_platform_link_get_name (platform, ifindex);
 		g_assert (ifname);
 
 		if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT)
@@ -628,7 +661,7 @@ _ip_address_add (gboolean external_command,
 		gboolean success;
 
 		if (is_v4) {
-			success = nm_platform_ip4_address_add (NM_PLATFORM_GET,
+			success = nm_platform_ip4_address_add (platform,
 			                                       ifindex,
 			                                       address->addr4,
 			                                       plen,
@@ -639,7 +672,7 @@ _ip_address_add (gboolean external_command,
 			                                       label);
 		} else {
 			g_assert (label == NULL);
-			success = nm_platform_ip6_address_add (NM_PLATFORM_GET,
+			success = nm_platform_ip6_address_add (platform,
 			                                       ifindex,
 			                                       address->addr6,
 			                                       plen,
@@ -656,14 +689,14 @@ _ip_address_add (gboolean external_command,
 	do {
 
 		if (external_command)
-			nm_platform_process_events (NM_PLATFORM_GET);
+			nm_platform_process_events (platform);
 
 		/* let's wait until we see the address as we added it. */
 		if (is_v4) {
 			const NMPlatformIP4Address *a;
 
 			g_assert (flags == 0);
-			a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
+			a = nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4);
 			if (   a
 			    && a->peer_address == peer_address->addr4
 			    && nmtstp_ip_address_check_lifetime ((NMPlatformIPAddress*) a, -1, lifetime, preferred)
@@ -675,7 +708,7 @@ _ip_address_add (gboolean external_command,
 			g_assert (label == NULL);
 			g_assert (flags == 0);
 
-			a = nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen);
+			a = nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen);
 			if (   a
 			    && !memcmp (nm_platform_ip6_address_get_peer (a),
 			                (IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) || IN6_ARE_ADDR_EQUAL (&address->addr6, &peer_address->addr6))
@@ -688,10 +721,188 @@ _ip_address_add (gboolean external_command,
 		/* for internal command, we expect not to reach this line.*/
 		g_assert (external_command);
 
-		g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time));
+		nmtstp_assert_wait_for_signal_until (platform, end_time);
+	} while (TRUE);
+}
+
+void
+nmtstp_ip4_address_add (NMPlatform *platform,
+                        gboolean external_command,
+                        int ifindex,
+                        in_addr_t address,
+                        int plen,
+                        in_addr_t peer_address,
+                        guint32 lifetime,
+                        guint32 preferred,
+                        guint32 flags,
+                        const char *label)
+{
+	_ip_address_add (platform,
+	                 external_command,
+	                 TRUE,
+	                 ifindex,
+	                 (NMIPAddr *) &address,
+	                 plen,
+	                 (NMIPAddr *) &peer_address,
+	                 lifetime,
+	                 preferred,
+	                 flags,
+	                 label);
+}
+
+void
+nmtstp_ip6_address_add (NMPlatform *platform,
+                        gboolean external_command,
+                        int ifindex,
+                        struct in6_addr address,
+                        int plen,
+                        struct in6_addr peer_address,
+                        guint32 lifetime,
+                        guint32 preferred,
+                        guint32 flags)
+{
+	_ip_address_add (platform,
+	                 external_command,
+	                 FALSE,
+	                 ifindex,
+	                 (NMIPAddr *) &address,
+	                 plen,
+	                 (NMIPAddr *) &peer_address,
+	                 lifetime,
+	                 preferred,
+	                 flags,
+	                 NULL);
+}
+
+/*****************************************************************************/
+
+static void
+_ip_address_del (NMPlatform *platform,
+                 gboolean external_command,
+                 gboolean is_v4,
+                 int ifindex,
+                 const NMIPAddr *address,
+                 int plen,
+                 const NMIPAddr *peer_address)
+{
+	gint64 end_time;
+
+	external_command = nmtstp_run_command_check_external (external_command);
+
+	_init_platform (&platform, external_command);
+
+	if (external_command) {
+		const char *ifname;
+		char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN];
+		int success;
+		gboolean had_address;
+
+		ifname = nm_platform_link_get_name (platform, ifindex);
+		g_assert (ifname);
+
+		/* let's wait until we see the address as we added it. */
+		if (is_v4)
+			had_address = !!nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4);
+		else
+			had_address = !!nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen);
+
+		if (is_v4) {
+			success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s",
+			                              nm_utils_inet4_ntop (address->addr4, b1),
+			                              peer_address->addr4 != address->addr4 ? " peer " : "",
+			                              peer_address->addr4 != address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "",
+			                              plen,
+			                              ifname);
+		} else {
+			g_assert (!peer_address);
+			success = nmtstp_run_command ("ip address delete %s/%d dev %s",
+			                              nm_utils_inet6_ntop (&address->addr6, b1),
+			                              plen,
+			                              ifname);
+		}
+		g_assert (success == 0 || !had_address);
+	} else {
+		gboolean success;
+
+		if (is_v4) {
+			success = nm_platform_ip4_address_delete (platform,
+			                                          ifindex,
+			                                          address->addr4,
+			                                          plen,
+			                                          peer_address->addr4);
+		} else {
+			g_assert (!peer_address);
+			success = nm_platform_ip6_address_delete (platform,
+			                                          ifindex,
+			                                          address->addr6,
+			                                          plen);
+		}
+		g_assert (success);
+	}
+
+	/* Let's wait until we get the result */
+	end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
+	do {
+		if (external_command)
+			nm_platform_process_events (platform);
+
+		/* let's wait until we see the address as we added it. */
+		if (is_v4) {
+			const NMPlatformIP4Address *a;
+
+			a = nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4);
+			if (!a)
+				break;
+		} else {
+			const NMPlatformIP6Address *a;
+
+			a = nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen);
+			if (!a)
+				break;
+		}
+
+		/* for internal command, we expect not to reach this line.*/
+		g_assert (external_command);
+
+		nmtstp_assert_wait_for_signal_until (platform, end_time);
 	} while (TRUE);
 }
 
+void
+nmtstp_ip4_address_del (NMPlatform *platform,
+                        gboolean external_command,
+                        int ifindex,
+                        in_addr_t address,
+                        int plen,
+                        in_addr_t peer_address)
+{
+	_ip_address_del (platform,
+	                 external_command,
+	                 TRUE,
+	                 ifindex,
+	                 (NMIPAddr *) &address,
+	                 plen,
+	                 (NMIPAddr *) &peer_address);
+}
+
+void
+nmtstp_ip6_address_del (NMPlatform *platform,
+                        gboolean external_command,
+                        int ifindex,
+                        struct in6_addr address,
+                        int plen)
+{
+	_ip_address_del (platform,
+	                 external_command,
+	                 FALSE,
+	                 ifindex,
+	                 (NMIPAddr *) &address,
+	                 plen,
+	                 NULL);
+}
+
+/*****************************************************************************/
+
 #define _assert_pllink(platform, success, pllink, name, type) \
 	G_STMT_START { \
 		const NMPlatformLink *_pllink = (pllink); \
@@ -706,7 +917,8 @@ _ip_address_add (gboolean external_command,
 	} G_STMT_END
 
 const NMPlatformLink *
-nmtstp_link_dummy_add (gboolean external_command,
+nmtstp_link_dummy_add (NMPlatform *platform,
+                       gboolean external_command,
                        const char *name)
 {
 	const NMPlatformLink *pllink = NULL;
@@ -716,21 +928,24 @@ nmtstp_link_dummy_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		success = !nmtstp_run_command ("ip link add %s type dummy",
 		                                name);
 		if (success)
-			pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_DUMMY, 100);
+			pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_DUMMY, 100);
 	} else
-		success = nm_platform_link_dummy_add (NM_PLATFORM_GET, name, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
+		success = nm_platform_link_dummy_add (platform, name, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
 
 	g_assert (success);
-	_assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_DUMMY);
+	_assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_DUMMY);
 	return pllink;
 }
 
 const NMPlatformLink *
-nmtstp_link_gre_add (gboolean external_command,
+nmtstp_link_gre_add (NMPlatform *platform,
+                     gboolean external_command,
                      const char *name,
                      const NMPlatformLnkGre *lnk)
 {
@@ -742,11 +957,13 @@ nmtstp_link_gre_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		gs_free char *dev = NULL;
 
 		if (lnk->parent_ifindex)
-			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex));
+			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex));
 
 		success = !nmtstp_run_command ("ip tunnel add %s mode gre %s local %s remote %s ttl %u tos %02x %s",
 		                                name,
@@ -757,17 +974,18 @@ nmtstp_link_gre_add (gboolean external_command,
 		                                lnk->tos,
 		                                lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc");
 		if (success)
-			pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_GRE, 100);
+			pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_GRE, 100);
 	} else
-		success = nm_platform_link_gre_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
+		success = nm_platform_link_gre_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
 
-	_assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_GRE);
+	_assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_GRE);
 
 	return pllink;
 }
 
 const NMPlatformLink *
-nmtstp_link_ip6tnl_add (gboolean external_command,
+nmtstp_link_ip6tnl_add (NMPlatform *platform,
+                        gboolean external_command,
                         const char *name,
                         const NMPlatformLnkIp6Tnl *lnk)
 {
@@ -779,12 +997,14 @@ nmtstp_link_ip6tnl_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		gs_free char *dev = NULL;
 		const char *mode;
 
 		if (lnk->parent_ifindex)
-			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex));
+			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex));
 
 		switch (lnk->proto) {
 		case IPPROTO_IPIP:
@@ -808,17 +1028,18 @@ nmtstp_link_ip6tnl_add (gboolean external_command,
 		                                lnk->encap_limit,
 		                                lnk->flow_label);
 		if (success)
-			pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_IP6TNL, 100);
+			pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_IP6TNL, 100);
 	} else
-		success = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
+		success = nm_platform_link_ip6tnl_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
 
-	_assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_IP6TNL);
+	_assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_IP6TNL);
 
 	return pllink;
 }
 
 const NMPlatformLink *
-nmtstp_link_ipip_add (gboolean external_command,
+nmtstp_link_ipip_add (NMPlatform *platform,
+                      gboolean external_command,
                       const char *name,
                       const NMPlatformLnkIpIp *lnk)
 {
@@ -830,11 +1051,13 @@ nmtstp_link_ipip_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		gs_free char *dev = NULL;
 
 		if (lnk->parent_ifindex)
-			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex));
+			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex));
 
 		success = !nmtstp_run_command ("ip tunnel add %s mode ipip %s local %s remote %s ttl %u tos %02x %s",
 		                                name,
@@ -845,17 +1068,18 @@ nmtstp_link_ipip_add (gboolean external_command,
 		                                lnk->tos,
 		                                lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc");
 		if (success)
-			pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_IPIP, 100);
+			pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_IPIP, 100);
 	} else
-		success = nm_platform_link_ipip_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
+		success = nm_platform_link_ipip_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
 
-	_assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_IPIP);
+	_assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_IPIP);
 
 	return pllink;
 }
 
 const NMPlatformLink *
-nmtstp_link_macvlan_add (gboolean external_command,
+nmtstp_link_macvlan_add (NMPlatform *platform,
+                         gboolean external_command,
                          const char *name,
                          int parent,
                          const NMPlatformLnkMacvlan *lnk)
@@ -868,6 +1092,8 @@ nmtstp_link_macvlan_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	link_type = lnk->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN;
 
 	if (external_command) {
@@ -879,7 +1105,7 @@ nmtstp_link_macvlan_add (gboolean external_command,
 				[MACVLAN_MODE_PASSTHRU] = "passthru",
 		};
 
-		dev = nm_platform_link_get_name (NM_PLATFORM_GET, parent);
+		dev = nm_platform_link_get_name (platform, parent);
 		g_assert (dev);
 		g_assert_cmpint (lnk->mode, <, G_N_ELEMENTS (modes));
 
@@ -890,17 +1116,18 @@ nmtstp_link_macvlan_add (gboolean external_command,
 		                                modes[lnk->mode],
 		                                lnk->no_promisc ? "nopromisc" : "");
 		if (success)
-			pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, link_type, 100);
+			pllink = nmtstp_assert_wait_for_link (platform, name, link_type, 100);
 	} else
-		success = nm_platform_link_macvlan_add (NM_PLATFORM_GET, name, parent, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
+		success = nm_platform_link_macvlan_add (platform, name, parent, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
 
-	_assert_pllink (NM_PLATFORM_GET, success, pllink, name, link_type);
+	_assert_pllink (platform, success, pllink, name, link_type);
 
 	return pllink;
 }
 
 const NMPlatformLink *
-nmtstp_link_sit_add (gboolean external_command,
+nmtstp_link_sit_add (NMPlatform *platform,
+                     gboolean external_command,
                      const char *name,
                      const NMPlatformLnkSit *lnk)
 {
@@ -912,13 +1139,15 @@ nmtstp_link_sit_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		const char *dev = "";
 
 		if (lnk->parent_ifindex) {
 			const char *parent_name;
 
-			parent_name = nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex);
+			parent_name = nm_platform_link_get_name (platform, lnk->parent_ifindex);
 			g_assert (parent_name);
 			dev = nm_sprintf_bufa (100, " dev %s", parent_name);
 		}
@@ -932,17 +1161,18 @@ nmtstp_link_sit_add (gboolean external_command,
 		                                lnk->tos,
 		                                lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc");
 		if (success)
-			pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_SIT, 100);
+			pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_SIT, 100);
 	} else
-		success = nm_platform_link_sit_add (NM_PLATFORM_GET, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
+		success = nm_platform_link_sit_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
 
-	_assert_pllink (NM_PLATFORM_GET, success, pllink, name, NM_LINK_TYPE_SIT);
+	_assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_SIT);
 
 	return pllink;
 }
 
 const NMPlatformLink *
-nmtstp_link_vxlan_add (gboolean external_command,
+nmtstp_link_vxlan_add (NMPlatform *platform,
+                       gboolean external_command,
                        const char *name,
                        const NMPlatformLnkVxlan *lnk)
 {
@@ -954,12 +1184,14 @@ nmtstp_link_vxlan_add (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		gs_free char *dev = NULL;
 		gs_free char *local = NULL, *remote = NULL;
 
 		if (lnk->parent_ifindex)
-			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex));
+			dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex));
 
 		if (lnk->local)
 			local = g_strdup_printf ("%s", nm_utils_inet4_ntop (lnk->local, NULL));
@@ -985,12 +1217,12 @@ nmtstp_link_vxlan_add (gboolean external_command,
 		/* Older versions of iproute2 don't support adding vxlan devices.
 		 * On failure, fallback to using platform code. */
 		if (err == 0)
-			pllink = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, name, NM_LINK_TYPE_VXLAN, 100);
+			pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VXLAN, 100);
 		else
 			_LOGI ("Adding vxlan device via iproute2 failed. Assume iproute2 is not up to the task.");
 	}
 	if (!pllink) {
-		plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, name, lnk, &pllink);
+		plerr = nm_platform_link_vxlan_add (platform, name, lnk, &pllink);
 		g_assert_cmpint (plerr, ==, NM_PLATFORM_ERROR_SUCCESS);
 		g_assert (pllink);
 	}
@@ -1000,168 +1232,7 @@ nmtstp_link_vxlan_add (gboolean external_command,
 	return pllink;
 }
 
-void
-nmtstp_ip4_address_add (gboolean external_command,
-                        int ifindex,
-                        in_addr_t address,
-                        int plen,
-                        in_addr_t peer_address,
-                        guint32 lifetime,
-                        guint32 preferred,
-                        guint32 flags,
-                        const char *label)
-{
-	_ip_address_add (external_command,
-	                 TRUE,
-	                 ifindex,
-	                 (NMIPAddr *) &address,
-	                 plen,
-	                 (NMIPAddr *) &peer_address,
-	                 lifetime,
-	                 preferred,
-	                 flags,
-	                 label);
-}
-
-void
-nmtstp_ip6_address_add (gboolean external_command,
-                        int ifindex,
-                        struct in6_addr address,
-                        int plen,
-                        struct in6_addr peer_address,
-                        guint32 lifetime,
-                        guint32 preferred,
-                        guint32 flags)
-{
-	_ip_address_add (external_command,
-	                 FALSE,
-	                 ifindex,
-	                 (NMIPAddr *) &address,
-	                 plen,
-	                 (NMIPAddr *) &peer_address,
-	                 lifetime,
-	                 preferred,
-	                 flags,
-	                 NULL);
-}
-
-static void
-_ip_address_del (gboolean external_command,
-                 gboolean is_v4,
-                 int ifindex,
-                 const NMIPAddr *address,
-                 int plen,
-                 const NMIPAddr *peer_address)
-{
-	gint64 end_time;
-
-	external_command = nmtstp_run_command_check_external (external_command);
-
-	if (external_command) {
-		const char *ifname;
-		char b1[NM_UTILS_INET_ADDRSTRLEN], b2[NM_UTILS_INET_ADDRSTRLEN];
-		int success;
-		gboolean had_address;
-
-		ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
-		g_assert (ifname);
-
-		/* let's wait until we see the address as we added it. */
-		if (is_v4)
-			had_address = !!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
-		else
-			had_address = !!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen);
-
-		if (is_v4) {
-			success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s",
-			                              nm_utils_inet4_ntop (address->addr4, b1),
-			                              peer_address->addr4 != address->addr4 ? " peer " : "",
-			                              peer_address->addr4 != address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "",
-			                              plen,
-			                              ifname);
-		} else {
-			g_assert (!peer_address);
-			success = nmtstp_run_command ("ip address delete %s/%d dev %s",
-			                              nm_utils_inet6_ntop (&address->addr6, b1),
-			                              plen,
-			                              ifname);
-		}
-		g_assert (success == 0 || !had_address);
-	} else {
-		gboolean success;
-
-		if (is_v4) {
-			success = nm_platform_ip4_address_delete (NM_PLATFORM_GET,
-			                                          ifindex,
-			                                          address->addr4,
-			                                          plen,
-			                                          peer_address->addr4);
-		} else {
-			g_assert (!peer_address);
-			success = nm_platform_ip6_address_delete (NM_PLATFORM_GET,
-			                                          ifindex,
-			                                          address->addr6,
-			                                          plen);
-		}
-		g_assert (success);
-	}
-
-	/* Let's wait until we get the result */
-	end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
-	do {
-		if (external_command)
-			nm_platform_process_events (NM_PLATFORM_GET);
-
-		/* let's wait until we see the address as we added it. */
-		if (is_v4) {
-			const NMPlatformIP4Address *a;
-
-			a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
-			if (!a)
-				break;
-		} else {
-			const NMPlatformIP6Address *a;
-
-			a = nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, address->addr6, plen);
-			if (!a)
-				break;
-		}
-
-		/* for internal command, we expect not to reach this line.*/
-		g_assert (external_command);
-
-		g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time));
-	} while (TRUE);
-}
-
-void
-nmtstp_ip4_address_del (gboolean external_command,
-                        int ifindex,
-                        in_addr_t address,
-                        int plen,
-                        in_addr_t peer_address)
-{
-	_ip_address_del (external_command,
-	                 TRUE,
-	                 ifindex,
-	                 (NMIPAddr *) &address,
-	                 plen,
-	                 (NMIPAddr *) &peer_address);
-}
-
-void
-nmtstp_ip6_address_del (gboolean external_command,
-                        int ifindex,
-                        struct in6_addr address,
-                        int plen)
-{
-	_ip_address_del (external_command,
-	                 FALSE,
-	                 ifindex,
-	                 (NMIPAddr *) &address,
-	                 plen,
-	                 NULL);
-}
+/*****************************************************************************/
 
 const NMPlatformLink *
 nmtstp_link_get_typed (NMPlatform *platform,
@@ -1171,8 +1242,7 @@ nmtstp_link_get_typed (NMPlatform *platform,
 {
 	const NMPlatformLink *pllink = NULL;
 
-	if (!platform)
-		platform = NM_PLATFORM_GET;
+	_init_platform (&platform, FALSE);
 
 	if (ifindex > 0) {
 		pllink = nm_platform_link_get (platform, ifindex);
@@ -1210,8 +1280,11 @@ nmtstp_link_get (NMPlatform *platform,
 	return nmtstp_link_get_typed (platform, ifindex, name, NM_LINK_TYPE_NONE);
 }
 
+/*****************************************************************************/
+
 void
-nmtstp_link_del (gboolean external_command,
+nmtstp_link_del (NMPlatform *platform,
+                 gboolean external_command,
                  int ifindex,
                  const char *name)
 {
@@ -1220,19 +1293,21 @@ nmtstp_link_del (gboolean external_command,
 	gboolean success;
 	gs_free char *name_copy = NULL;
 
-	pllink = nmtstp_link_get (NM_PLATFORM_GET, ifindex, name);
+	external_command = nmtstp_run_command_check_external (external_command);
+
+	_init_platform (&platform, external_command);
+
+	pllink = nmtstp_link_get (platform, ifindex, name);
 
 	g_assert (pllink);
 
 	name = name_copy = g_strdup (pllink->name);
 	ifindex = pllink->ifindex;
 
-	external_command = nmtstp_run_command_check_external (external_command);
-
 	if (external_command) {
 		nmtstp_run_command_check ("ip link delete %s", name);
 	} else {
-		success = nm_platform_link_delete (NM_PLATFORM_GET, ifindex);
+		success = nm_platform_link_delete (platform, ifindex);
 		g_assert (success);
 	}
 
@@ -1240,22 +1315,25 @@ nmtstp_link_del (gboolean external_command,
 	end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
 	do {
 		if (external_command)
-			nm_platform_process_events (NM_PLATFORM_GET);
+			nm_platform_process_events (platform);
 
-		if (!nm_platform_link_get (NM_PLATFORM_GET, ifindex)) {
-			g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, name));
+		if (!nm_platform_link_get (platform, ifindex)) {
+			g_assert (!nm_platform_link_get_by_ifname (platform, name));
 			break;
 		}
 
 		/* for internal command, we expect not to reach this line.*/
 		g_assert (external_command);
 
-		g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time));
+		nmtstp_assert_wait_for_signal_until (platform, end_time);
 	} while (TRUE);
 }
 
+/*****************************************************************************/
+
 void
-nmtstp_link_set_updown (gboolean external_command,
+nmtstp_link_set_updown (NMPlatform *platform,
+                        gboolean external_command,
                         int ifindex,
                         gboolean up)
 {
@@ -1264,10 +1342,12 @@ nmtstp_link_set_updown (gboolean external_command,
 
 	external_command = nmtstp_run_command_check_external (external_command);
 
+	_init_platform (&platform, external_command);
+
 	if (external_command) {
 		const char *ifname;
 
-		ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
+		ifname = nm_platform_link_get_name (platform, ifindex);
 		g_assert (ifname);
 
 		nmtstp_run_command_check ("ip link set %s %s",
@@ -1275,19 +1355,19 @@ nmtstp_link_set_updown (gboolean external_command,
 		                          up ? "up" : "down");
 	} else {
 		if (up)
-			g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL));
+			g_assert (nm_platform_link_set_up (platform, ifindex, NULL));
 		else
-			g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex));
+			g_assert (nm_platform_link_set_down (platform, ifindex));
 	}
 
 	/* Let's wait until we get the result */
 	end_time = nm_utils_get_monotonic_timestamp_ms () + 250;
 	do {
 		if (external_command)
-			nm_platform_process_events (NM_PLATFORM_GET);
+			nm_platform_process_events (platform);
 
 		/* let's wait until we see the address as we added it. */
-		plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex);
+		plink = nm_platform_link_get (platform, ifindex);
 		g_assert (plink);
 
 		if (NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP) == !!up)
@@ -1296,7 +1376,7 @@ nmtstp_link_set_updown (gboolean external_command,
 		/* for internal command, we expect not to reach this line.*/
 		g_assert (external_command);
 
-		g_assert (nmtstp_wait_for_signal_until (NM_PLATFORM_GET, end_time));
+		nmtstp_assert_wait_for_signal_until (platform, end_time);
 	} while (TRUE);
 }
 
@@ -1513,7 +1593,7 @@ main (int argc, char **argv)
 	int result;
 	const char *program = *argv;
 
-	init_tests (&argc, &argv);
+	_nmtstp_init_tests (&argc, &argv);
 
 	if (   nmtstp_is_root_test ()
 	    && (geteuid () != 0 || getegid () != 0)) {
@@ -1571,7 +1651,7 @@ main (int argc, char **argv)
 
 	SETUP ();
 
-	setup_tests ();
+	_nmtstp_setup_tests ();
 
 	result = g_test_run ();
 
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
index 82561193..0e3cf10b 100644
--- a/src/platform/tests/test-common.h
+++ b/src/platform/tests/test-common.h
@@ -4,7 +4,6 @@
 #include <string.h>
 #include <arpa/inet.h>
 
-#include "nm-default.h"
 #include "nm-platform.h"
 #include "nm-fake-platform.h"
 #include "nm-linux-platform.h"
@@ -38,16 +37,6 @@
 
 /*********************************************************************************************/
 
-typedef struct {
-	gulong handler_id;
-	const char *name;
-	NMPlatformSignalChangeType change_type;
-	gint received_count;
-	GMainLoop *loop;
-	int ifindex;
-	const char *ifname;
-} SignalData;
-
 gboolean nmtstp_is_root_test (void);
 gboolean nmtstp_is_sysfs_writable (void);
 
@@ -64,6 +53,16 @@ int nmtstp_namespace_get_fd_for_process (pid_t pid, const char *ns_name);
 
 /******************************************************************************/
 
+typedef struct {
+	gulong handler_id;
+	const char *name;
+	NMPlatformSignalChangeType change_type;
+	gint received_count;
+	GMainLoop *loop;
+	int ifindex;
+	const char *ifname;
+} SignalData;
+
 SignalData *add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname);
 #define add_signal(name, change_type, callback) add_signal_full (name, change_type, (GCallback) callback, 0, NULL)
 #define add_signal_ifindex(name, change_type, callback, ifindex) add_signal_full (name, change_type, (GCallback) callback, ifindex, NULL)
@@ -81,27 +80,49 @@ void _free_signal (const char *file, int line, const char *func, SignalData *dat
 #define ensure_no_signal(data) _ensure_no_signal(__FILE__, __LINE__, G_STRFUNC, data)
 #define free_signal(data) _free_signal(__FILE__, __LINE__, G_STRFUNC, data)
 
-gboolean ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric);
-
-void _assert_ip4_route_exists (const char *file, guint line, const char *func, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric);
-#define assert_ip4_route_exists(exists, ifname, network, plen, metric) _assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, exists, ifname, network, plen, metric)
-
 void link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *received, NMPlatformSignalChangeType change_type, SignalData *data);
 
+/*****************************************************************************/
+
 int nmtstp_run_command (const char *format, ...) __attribute__((__format__ (__printf__, 1, 2)));
 #define nmtstp_run_command_check(...) do { g_assert_cmpint (nmtstp_run_command (__VA_ARGS__), ==, 0); } while (0)
 
-gboolean nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms);
-gboolean nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms);
+/*****************************************************************************/
+
+guint nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms);
+guint nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms);
 const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms);
 const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms);
 
+#define nmtstp_assert_wait_for_signal(platform, timeout_ms) \
+	G_STMT_START { \
+		if (nmtstp_wait_for_signal (platform, timeout_ms) == 0) \
+			g_assert_not_reached (); \
+	} G_STMT_END
+
+#define nmtstp_assert_wait_for_signal_until(platform, until_ms) \
+	G_STMT_START { \
+		if (nmtstp_wait_for_signal_until (platform, until_ms) == 0) \
+			g_assert_not_reached (); \
+	} G_STMT_END
+
 const NMPlatformLink *nmtstp_assert_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms);
 const NMPlatformLink *nmtstp_assert_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms);
 
+/*****************************************************************************/
+
 int nmtstp_run_command_check_external_global (void);
 gboolean nmtstp_run_command_check_external (int external_command);
 
+/*****************************************************************************/
+
+gboolean nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric);
+
+void _nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric);
+#define nmtstp_assert_ip4_route_exists(platform, exists, ifname, network, plen, metric) _nmtstp_assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, exists, ifname, network, plen, metric)
+
+/*****************************************************************************/
+
 gboolean nmtstp_ip_address_check_lifetime (const NMPlatformIPAddress *addr,
                                            gint64 now,
                                            guint32 expected_lifetime,
@@ -110,7 +131,9 @@ void nmtstp_ip_address_assert_lifetime (const NMPlatformIPAddress *addr,
                                         gint64 now,
                                         guint32 expected_lifetime,
                                         guint32 expected_preferred);
-void nmtstp_ip4_address_add (gboolean external_command,
+
+void nmtstp_ip4_address_add (NMPlatform *platform,
+                             gboolean external_command,
                              int ifindex,
                              in_addr_t address,
                              int plen,
@@ -119,7 +142,8 @@ void nmtstp_ip4_address_add (gboolean external_command,
                              guint32 preferred,
                              guint32 flags,
                              const char *label);
-void nmtstp_ip6_address_add (gboolean external_command,
+void nmtstp_ip6_address_add (NMPlatform *platform,
+                             gboolean external_command,
                              int ifindex,
                              struct in6_addr address,
                              int plen,
@@ -127,49 +151,64 @@ void nmtstp_ip6_address_add (gboolean external_command,
                              guint32 lifetime,
                              guint32 preferred,
                              guint32 flags);
-void nmtstp_ip4_address_del (gboolean external_command,
+void nmtstp_ip4_address_del (NMPlatform *platform,
+                             gboolean external_command,
                              int ifindex,
                              in_addr_t address,
                              int plen,
                              in_addr_t peer_address);
-void nmtstp_ip6_address_del (gboolean external_command,
+void nmtstp_ip6_address_del (NMPlatform *platform,
+                             gboolean external_command,
                              int ifindex,
                              struct in6_addr address,
                              int plen);
 
+/*****************************************************************************/
+
 const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type);
 const NMPlatformLink *nmtstp_link_get (NMPlatform *platform, int ifindex, const char *name);
 
-void nmtstp_link_set_updown (gboolean external_command,
+void nmtstp_link_set_updown (NMPlatform *platform,
+                             gboolean external_command,
                              int ifindex,
                              gboolean up);
 
-const NMPlatformLink *nmtstp_link_dummy_add (gboolean external_command,
+const NMPlatformLink *nmtstp_link_dummy_add (NMPlatform *platform,
+                                             gboolean external_command,
                                              const char *name);
-const NMPlatformLink *nmtstp_link_gre_add (gboolean external_command,
+const NMPlatformLink *nmtstp_link_gre_add (NMPlatform *platform,
+                                           gboolean external_command,
                                            const char *name,
                                            const NMPlatformLnkGre *lnk);
-const NMPlatformLink *nmtstp_link_ip6tnl_add (gboolean external_command,
+const NMPlatformLink *nmtstp_link_ip6tnl_add (NMPlatform *platform,
+                                              gboolean external_command,
                                               const char *name,
                                               const NMPlatformLnkIp6Tnl *lnk);
-const NMPlatformLink *nmtstp_link_ipip_add (gboolean external_command,
+const NMPlatformLink *nmtstp_link_ipip_add (NMPlatform *platform,
+                                            gboolean external_command,
                                             const char *name,
                                             const NMPlatformLnkIpIp *lnk);
-const NMPlatformLink *nmtstp_link_macvlan_add (gboolean external_command,
+const NMPlatformLink *nmtstp_link_macvlan_add (NMPlatform *platform,
+                                               gboolean external_command,
                                                const char *name,
                                                int parent,
                                                const NMPlatformLnkMacvlan *lnk);
-const NMPlatformLink *nmtstp_link_sit_add (gboolean external_command,
+const NMPlatformLink *nmtstp_link_sit_add (NMPlatform *platform,
+                                           gboolean external_command,
                                            const char *name,
                                            const NMPlatformLnkSit *lnk);
-const NMPlatformLink *nmtstp_link_vxlan_add (gboolean external_command,
+const NMPlatformLink *nmtstp_link_vxlan_add (NMPlatform *platform,
+                                             gboolean external_command,
                                              const char *name,
                                              const NMPlatformLnkVxlan *lnk);
 
-void nmtstp_link_del (gboolean external_command,
+void nmtstp_link_del (NMPlatform *platform,
+                      gboolean external_command,
                       int ifindex,
                       const char *name);
 
-void init_tests (int *argc, char ***argv);
-void setup_tests (void);
+/*****************************************************************************/
+
+void _nmtstp_init_tests (int *argc, char ***argv);
+void _nmtstp_setup_tests (void);
 
diff --git a/src/platform/tests/test-general.c b/src/platform/tests/test-general.c
index 66f72fa5..d8d92561 100644
--- a/src/platform/tests/test-general.c
+++ b/src/platform/tests/test-general.c
@@ -35,7 +35,7 @@ test_init_linux_platform (void)
 {
 	gs_unref_object NMPlatform *platform = NULL;
 
-	platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NULL);
+	platform = nm_linux_platform_new (NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
 }
 
 /******************************************************************/
@@ -46,7 +46,7 @@ test_link_get_all (void)
 	gs_unref_object NMPlatform *platform = NULL;
 	gs_unref_array GArray *links = NULL;
 
-	platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NULL);
+	platform = nm_linux_platform_new (NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
 
 	links = nm_platform_link_get_all (platform);
 }
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 94695edc..9d548aab 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -343,7 +343,7 @@ test_slave (int master, int type, SignalData *master_changed)
 	ensure_no_signal (link_added);
 	ensure_no_signal (link_changed);
 	ensure_no_signal (link_removed);
-	nmtstp_link_del (-1, ifindex, NULL);
+	nmtstp_link_del (NULL, -1, ifindex, NULL);
 	accept_signals (master_changed, 0, 1);
 	accept_signals (link_changed, 0, 1);
 	accept_signal (link_removed);
@@ -437,7 +437,7 @@ test_software (NMLinkType link_type, const char *link_typename)
 	free_signal (link_changed);
 
 	/* Delete */
-	nmtstp_link_del (-1, ifindex, DEVICE_NAME);
+	nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
 	accept_signal (link_removed);
 
 	/* Delete again */
@@ -448,7 +448,7 @@ test_software (NMLinkType link_type, const char *link_typename)
 	if (link_type == NM_LINK_TYPE_VLAN) {
 		SignalData *link_removed_parent = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, vlan_parent);
 
-		nmtstp_link_del (-1, vlan_parent, NULL);
+		nmtstp_link_del (NULL, -1, vlan_parent, NULL);
 		accept_signal (link_removed_parent);
 		free_signal (link_removed_parent);
 	}
@@ -531,7 +531,7 @@ test_bridge_addr (void)
 	g_assert_cmpint (plink->addr.len, ==, sizeof (addr));
 	g_assert (!memcmp (plink->addr.data, addr, sizeof (addr)));
 
-	nmtstp_link_del (-1, link.ifindex, link.name);
+	nmtstp_link_del (NULL, -1, link.ifindex, link.name);
 }
 
 /*****************************************************************************/
@@ -606,7 +606,7 @@ test_internal (void)
 	accept_signal (link_changed);
 
 	/* Delete device */
-	nmtstp_link_del (-1, ifindex, DEVICE_NAME);
+	nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
 	accept_signal (link_removed);
 
 	/* Try to delete again */
@@ -717,7 +717,7 @@ test_software_detect (gconstpointer user_data)
 			gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip_gre", NULL) != 0;
 		}
 
-		if (!nmtstp_link_gre_add (ext, DEVICE_NAME, &lnk_gre)) {
+		if (!nmtstp_link_gre_add (NULL, ext, DEVICE_NAME, &lnk_gre)) {
 			if (gracefully_skip) {
 				g_test_skip ("Cannot create gre tunnel because of missing ip_gre module (modprobe ip_gre)");
 				goto out_delete_parent;
@@ -741,7 +741,7 @@ test_software_detect (gconstpointer user_data)
 		lnk_ipip.tos = 32;
 		lnk_ipip.path_mtu_discovery = FALSE;
 
-		if (!nmtstp_link_ipip_add (ext, DEVICE_NAME, &lnk_ipip)) {
+		if (!nmtstp_link_ipip_add (NULL, ext, DEVICE_NAME, &lnk_ipip)) {
 			if (gracefully_skip) {
 				g_test_skip ("Cannot create ipip tunnel because of missing ipip module (modprobe ipip)");
 				goto out_delete_parent;
@@ -767,7 +767,7 @@ test_software_detect (gconstpointer user_data)
 		lnk_ip6tnl.flow_label = 1337;
 		lnk_ip6tnl.proto = IPPROTO_IPV6;
 
-		if (!nmtstp_link_ip6tnl_add (ext, DEVICE_NAME, &lnk_ip6tnl)) {
+		if (!nmtstp_link_ip6tnl_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
 			if (gracefully_skip) {
 				g_test_skip ("Cannot create ip6tnl tunnel because of missing ip6_tunnel module (modprobe ip6_tunnel)");
 				goto out_delete_parent;
@@ -783,7 +783,7 @@ test_software_detect (gconstpointer user_data)
 		lnk_macvlan.no_promisc = FALSE;
 		lnk_macvlan.tap = FALSE;
 
-		if (!nmtstp_link_macvlan_add (ext, DEVICE_NAME, ifindex_parent, &lnk_macvlan))
+		if (!nmtstp_link_macvlan_add (NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvlan))
 			g_error ("Failed adding MACVLAN interface");
 		break;
 	}
@@ -794,7 +794,7 @@ test_software_detect (gconstpointer user_data)
 		lnk_macvtap.no_promisc = FALSE;
 		lnk_macvtap.tap = TRUE;
 
-		if (!nmtstp_link_macvlan_add (ext, DEVICE_NAME, ifindex_parent, &lnk_macvtap))
+		if (!nmtstp_link_macvlan_add (NULL, ext, DEVICE_NAME, ifindex_parent, &lnk_macvtap))
 			g_error ("Failed adding MACVTAP interface");
 		break;
 	}
@@ -814,7 +814,7 @@ test_software_detect (gconstpointer user_data)
 			gracefully_skip = nm_utils_modprobe (NULL, TRUE, "sit", NULL) != 0;
 		}
 
-		if (!nmtstp_link_sit_add (ext, DEVICE_NAME, &lnk_sit)) {
+		if (!nmtstp_link_sit_add (NULL, ext, DEVICE_NAME, &lnk_sit)) {
 			if (gracefully_skip) {
 				g_test_skip ("Cannot create sit tunnel because of missing sit module (modprobe sit)");
 				goto out_delete_parent;
@@ -853,7 +853,7 @@ test_software_detect (gconstpointer user_data)
 			break;
 		}
 
-		g_assert (nmtstp_link_vxlan_add (ext, DEVICE_NAME, &lnk_vxlan));
+		g_assert (nmtstp_link_vxlan_add (NULL, ext, DEVICE_NAME, &lnk_vxlan));
 		break;
 	}
 	default:
@@ -862,7 +862,7 @@ test_software_detect (gconstpointer user_data)
 
 	ifindex = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, DEVICE_NAME, test_data->link_type, 100)->ifindex;
 
-	nmtstp_link_set_updown (-1, ifindex_parent, TRUE);
+	nmtstp_link_set_updown (NULL, -1, ifindex_parent, TRUE);
 
 	for (i_step = 0; i_step < 5; i_step++) {
 
@@ -880,7 +880,7 @@ test_software_detect (gconstpointer user_data)
 				 * https://bugzilla.redhat.com/show_bug.cgi?id=1277131 */
 				g_usleep (1);
 			}
-			nmtstp_link_set_updown (-1, ifindex, set_up);
+			nmtstp_link_set_updown (NULL, -1, ifindex, set_up);
 		}
 
 		lnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, test_data->link_type, &plink);
@@ -1017,9 +1017,9 @@ test_software_detect (gconstpointer user_data)
 		}
 	}
 
-	nmtstp_link_del (-1, ifindex, DEVICE_NAME);
+	nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
 out_delete_parent:
-	nmtstp_link_del (-1, ifindex_parent, PARENT_NAME);
+	nmtstp_link_del (NULL, -1, ifindex_parent, PARENT_NAME);
 }
 
 static void
@@ -1597,8 +1597,8 @@ test_vlan_set_xgress (void)
 		_assert_vlan_flags (ifindex, NM_VLAN_FLAG_REORDER_HEADERS | NM_VLAN_FLAG_GVRP);
 	}
 
-	nmtstp_link_del (-1, ifindex, DEVICE_NAME);
-	nmtstp_link_del (-1, ifindex_parent, PARENT_NAME);
+	nmtstp_link_del (NULL, -1, ifindex, DEVICE_NAME);
+	nmtstp_link_del (NULL, -1, ifindex_parent, PARENT_NAME);
 }
 
 /*****************************************************************************/
@@ -1625,7 +1625,7 @@ test_create_many_links_do (guint n_devices)
 			 * while adding all the links. */
 			nmtstp_run_command_check ("ip link add %s type dummy", name);
 		} else
-			nmtstp_link_dummy_add (EX, name);
+			nmtstp_link_dummy_add (NULL, EX, name);
 	}
 
 	_LOGI (">>> process events after creating devices...");
@@ -1654,7 +1654,7 @@ test_create_many_links_do (guint n_devices)
 		if (EX == 2)
 			nmtstp_run_command_check ("ip link delete %s", name);
 		else
-			nmtstp_link_del (EX, g_array_index (ifindexes, int, i), name);
+			nmtstp_link_del (NULL, EX, g_array_index (ifindexes, int, i), name);
 	}
 
 	_LOGI (">>> process events after deleting devices...");
@@ -1743,7 +1743,7 @@ test_nl_bugs_veth (void)
 	});
 
 out:
-	nmtstp_link_del (-1, ifindex_veth0, IFACE_VETH0);
+	nmtstp_link_del (NULL, -1, ifindex_veth0, IFACE_VETH0);
 	g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth0, IFACE_VETH0));
 	g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_veth1, IFACE_VETH1));
 	nmtstp_namespace_handle_release (ns_handle);
@@ -1768,7 +1768,7 @@ test_nl_bugs_spuroius_newlink (void)
 	nmtstp_run_command_check ("ip link add %s type bond", IFACE_BOND0);
 	ifindex_bond0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex;
 
-	nmtstp_link_set_updown (-1, ifindex_bond0, TRUE);
+	nmtstp_link_set_updown (NULL, -1, ifindex_bond0, TRUE);
 
 	nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BOND0);
 	NMTST_WAIT_ASSERT (100, {
@@ -1796,7 +1796,7 @@ again:
 	}
 
 	g_assert (!nmtstp_link_get (NM_PLATFORM_GET, ifindex_bond0, IFACE_BOND0));
-	nmtstp_link_del (-1, ifindex_dummy0, IFACE_DUMMY0);
+	nmtstp_link_del (NULL, -1, ifindex_dummy0, IFACE_DUMMY0);
 }
 
 /*****************************************************************************/
@@ -1818,7 +1818,7 @@ test_nl_bugs_spuroius_dellink (void)
 	nmtstp_run_command_check ("ip link add %s type bridge", IFACE_BRIDGE0);
 	ifindex_bridge0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100)->ifindex;
 
-	nmtstp_link_set_updown (-1, ifindex_bridge0, TRUE);
+	nmtstp_link_set_updown (NULL, -1, ifindex_bridge0, TRUE);
 
 	nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BRIDGE0);
 	NMTST_WAIT_ASSERT (100, {
@@ -1850,8 +1850,8 @@ again:
 		goto again;
 	}
 
-	nmtstp_link_del (-1, ifindex_bridge0, IFACE_BRIDGE0);
-	nmtstp_link_del (-1, ifindex_dummy0, IFACE_DUMMY0);
+	nmtstp_link_del (NULL, -1, ifindex_bridge0, IFACE_BRIDGE0);
+	nmtstp_link_del (NULL, -1, ifindex_dummy0, IFACE_DUMMY0);
 }
 
 /******************************************************************/
@@ -1880,7 +1880,7 @@ _test_netns_create_platform (void)
 	netns = nmp_netns_new ();
 	g_assert (NMP_IS_NETNS (netns));
 
-	platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
+	platform = nm_linux_platform_new (TRUE);
 	g_assert (NM_IS_LINUX_PLATFORM (platform));
 
 	nmp_netns_pop (netns);
@@ -1932,7 +1932,7 @@ test_netns_general (gpointer fixture, gconstpointer test_data)
 	if (_test_netns_check_skip ())
 		return;
 
-	platform_1 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
+	platform_1 = nm_linux_platform_new (TRUE);
 	platform_2 = _test_netns_create_platform ();
 
 	/* add some dummy devices. The "other-*" devices are there to bump the ifindex */
@@ -2028,7 +2028,7 @@ test_netns_set_netns (gpointer fixture, gconstpointer test_data)
 	if (_test_netns_check_skip ())
 		return;
 
-	platforms[0] = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
+	platforms[0] = platform_0 = nm_linux_platform_new (TRUE);
 	platforms[1] = platform_1 = _test_netns_create_platform ();
 	platforms[2] = platform_2 = _test_netns_create_platform ();
 
@@ -2125,7 +2125,7 @@ test_netns_push (gpointer fixture, gconstpointer test_data)
 	if (_test_netns_check_skip ())
 		return;
 
-	pl[0].platform = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
+	pl[0].platform = platform_0 = nm_linux_platform_new (TRUE);
 	pl[1].platform = platform_1 = _test_netns_create_platform ();
 	pl[2].platform = platform_2 = _test_netns_create_platform ();
 
@@ -2257,7 +2257,7 @@ test_netns_bind_to_path (gpointer fixture, gconstpointer test_data)
 	if (_test_netns_check_skip ())
 		return;
 
-	platforms[0] = platform_0 = g_object_new (NM_TYPE_LINUX_PLATFORM, NM_PLATFORM_NETNS_SUPPORT, TRUE, NULL);
+	platforms[0] = platform_0 = nm_linux_platform_new (TRUE);
 	platforms[1] = platform_1 = _test_netns_create_platform ();
 	platforms[2] = platform_2 = _test_netns_create_platform ();
 
@@ -2293,13 +2293,13 @@ test_netns_bind_to_path (gpointer fixture, gconstpointer test_data)
 /*****************************************************************************/
 
 void
-init_tests (int *argc, char ***argv)
+_nmtstp_init_tests (int *argc, char ***argv)
 {
 	nmtst_init_with_logging (argc, argv, NULL, "ALL");
 }
 
 void
-setup_tests (void)
+_nmtstp_setup_tests (void)
 {
 	nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
 	nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, SLAVE_NAME));
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 85851854..a50392a6 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -82,50 +82,50 @@ test_ip4_route_metric0 (void)
 	int mss = 1000;
 
 	/* No routes initially */
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
 
 	/* add the first route */
 	g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss));
 	accept_signal (route_added);
 
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
-	assert_ip4_route_exists (TRUE,  DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE,  DEVICE_NAME, network, plen, metric);
 
 	/* Deleting route with metric 0 does nothing */
 	g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
 	ensure_no_signal (route_removed);
 
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
-	assert_ip4_route_exists (TRUE,  DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE,  DEVICE_NAME, network, plen, metric);
 
 	/* add the second route */
 	g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss));
 	accept_signal (route_added);
 
-	assert_ip4_route_exists (TRUE,  DEVICE_NAME, network, plen, 0);
-	assert_ip4_route_exists (TRUE,  DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE,  DEVICE_NAME, network, plen, 0);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE,  DEVICE_NAME, network, plen, metric);
 
 	/* Delete route with metric 0 */
 	g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
 	accept_signal (route_removed);
 
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
-	assert_ip4_route_exists (TRUE,  DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE,  DEVICE_NAME, network, plen, metric);
 
 	/* Delete route with metric 0 again (we expect nothing to happen) */
 	g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
 	ensure_no_signal (route_removed);
 
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
-	assert_ip4_route_exists (TRUE,  DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE,  DEVICE_NAME, network, plen, metric);
 
 	/* Delete the other route */
 	g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
 	accept_signal (route_removed);
 
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
 
 	free_signal (route_added);
 	free_signal (route_changed);
@@ -142,7 +142,7 @@ test_ip4_route (void)
 	GArray *routes;
 	NMPlatformIP4Route rts[3];
 	in_addr_t network;
-	int plen = 24;
+	guint8 plen = 24;
 	in_addr_t gateway;
 	/* Choose a high metric so that we hopefully don't conflict. */
 	int metric = 22986;
@@ -156,9 +156,9 @@ test_ip4_route (void)
 	accept_signal (route_added);
 
 	/* Add route */
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
 	g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
-	assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
 	accept_signal (route_added);
 
 	/* Add route again */
@@ -166,9 +166,9 @@ test_ip4_route (void)
 	accept_signals (route_changed, 0, 1);
 
 	/* Add default route */
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, 0, 0, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, 0, 0, metric);
 	g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
-	assert_ip4_route_exists (TRUE, DEVICE_NAME, 0, 0, metric);
+	nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, 0, 0, metric);
 	accept_signal (route_added);
 
 	/* Add default route again */
@@ -208,7 +208,7 @@ test_ip4_route (void)
 
 	/* Remove route */
 	g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
-	assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
+	nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
 	accept_signal (route_removed);
 
 	/* Remove route again */
@@ -229,7 +229,7 @@ test_ip6_route (void)
 	GArray *routes;
 	NMPlatformIP6Route rts[3];
 	struct in6_addr network;
-	int plen = 64;
+	guint8 plen = 64;
 	struct in6_addr gateway;
 	/* Choose a high metric so that we hopefully don't conflict. */
 	int metric = 22987;
@@ -329,13 +329,13 @@ test_ip4_zero_gateway (void)
 /*****************************************************************************/
 
 void
-init_tests (int *argc, char ***argv)
+_nmtstp_init_tests (int *argc, char ***argv)
 {
 	nmtst_init_with_logging (argc, argv, NULL, "ALL");
 }
 
 void
-setup_tests (void)
+_nmtstp_setup_tests (void)
 {
 	SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME);
 
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 16e34f11..89a7addf 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -481,7 +481,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
 	if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_PREFIX, "u", &u32))
 		address.plen = u32;
 
-	if (address.address && address.plen) {
+	if (address.address && address.plen && address.plen <= 32) {
 		address.source = NM_IP_CONFIG_SOURCE_PPP;
 		nm_ip4_config_add_address (config, &address);
 	} else {
@@ -554,6 +554,7 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
 	NMPlatformIP6Address addr;
 	struct in6_addr a;
 	NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
+	gboolean has_peer = FALSE;
 
 	_LOGI ("(IPv6 Config Get) reply received.");
 
@@ -567,9 +568,12 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
 	if (iid_value_to_ll6_addr (config_dict, NM_PPP_IP6_CONFIG_PEER_IID, &a, NULL)) {
 		nm_ip6_config_set_gateway (config, &a);
 		addr.peer_address = a;
+		has_peer = TRUE;
 	}
 
 	if (iid_value_to_ll6_addr (config_dict, NM_PPP_IP6_CONFIG_OUR_IID, &addr.address, &iid)) {
+		if (!has_peer)
+			addr.peer_address = addr.address;
 		nm_ip6_config_add_address (config, &addr);
 
 		if (set_ip_config_common (manager, config_dict, NM_PPP_IP6_CONFIG_INTERFACE, NULL)) {
@@ -1064,8 +1068,14 @@ nm_ppp_manager_start (NMPPPManager *manager,
 	}
 	
 	pppoe_setting = nm_connection_get_setting_pppoe (connection);
-	if (pppoe_setting)
+	if (pppoe_setting) {
+		/* We can't modify the applied connection's setting, make a copy */
+		if (!s_ppp_created) {
+			s_ppp = NM_SETTING_PPP (nm_setting_duplicate ((NMSetting *) s_ppp));
+			s_ppp_created = TRUE;
+		}
 		pppoe_fill_defaults (s_ppp);
+	}
 
 	adsl_setting = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
 
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index 41ffa27d..39e981f9 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -358,7 +358,7 @@ read_full_ip4_address (shvarFile *ifcfg,
 {
 	char *ip_tag, *prefix_tag, *netmask_tag, *gw_tag;
 	char *ip = NULL;
-	long prefix = 0;
+	int prefix = 0;
 	gboolean success = FALSE;
 	char *value;
 	guint32 tmp;
@@ -395,47 +395,40 @@ read_full_ip4_address (shvarFile *ifcfg,
 	/* Prefix */
 	value = svGetValue (ifcfg, prefix_tag, FALSE);
 	if (value) {
-		errno = 0;
-		prefix = strtol (value, NULL, 10);
-		if (errno || prefix < 0) {
+		prefix = _nm_utils_ascii_str_to_int64 (value, 10, 0, 32, -1);
+		if (prefix < 0) {
 			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 			             "Invalid IP4 prefix '%s'", value);
 			g_free (value);
 			goto done;
 		}
 		g_free (value);
-	}
-
-	/* Fall back to NETMASK if no PREFIX was specified */
-	if (prefix == 0) {
+	} else {
+		/* Fall back to NETMASK if no PREFIX was specified */
 		if (!read_ip4_address (ifcfg, netmask_tag, &value, error))
 			goto done;
 		if (value) {
 			inet_pton (AF_INET, value, &tmp);
 			prefix = nm_utils_ip4_netmask_to_prefix (tmp);
 			g_free (value);
-		}
-	}
-
-	if (prefix == 0 && base_addr)
-		prefix = nm_ip_address_get_prefix (base_addr);
-
-	/* Try to autodetermine the prefix for the address' class */
-	if (prefix == 0) {
-		if (inet_pton (AF_INET, ip, &tmp) == 1) {
-			prefix = nm_utils_ip4_get_default_prefix (tmp);
+		} else {
+			if (base_addr)
+				prefix = nm_ip_address_get_prefix (base_addr);
+			else {
+				/* Try to autodetermine the prefix for the address' class */
+				if (inet_pton (AF_INET, ip, &tmp) == 1) {
+					prefix = nm_utils_ip4_get_default_prefix (tmp);
 
-			PARSE_WARNING ("missing %s, assuming %s/%ld", prefix_tag, ip, prefix);
+					PARSE_WARNING ("missing %s, assuming %s/%d", prefix_tag, ip, prefix);
+				} else {
+					g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+					             "Missing IP4 prefix");
+					goto done;
+				}
+			}
 		}
 	}
 
-	/* Validate the prefix */
-	if (prefix == 0) {
-		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
-		             "Missing IP4 prefix");
-		goto done;
-	}
-
 	*out_address = nm_ip_address_new (AF_INET, ip, prefix, error);
 	if (*out_address)
 		success = TRUE;
@@ -717,7 +710,7 @@ parse_full_ip6_address (shvarFile *ifcfg,
 {
 	char **list;
 	char *ip_val, *prefix_val;
-	long prefix;
+	int prefix;
 	gboolean success = FALSE;
 
 	g_return_val_if_fail (addr_str != NULL, FALSE);
@@ -737,9 +730,8 @@ parse_full_ip6_address (shvarFile *ifcfg,
 
 	prefix_val = list[1];
 	if (prefix_val) {
-		errno = 0;
-		prefix = strtol (prefix_val, NULL, 10);
-		if (errno || prefix <= 0 || prefix > 128) {
+		prefix = _nm_utils_ascii_str_to_int64 (prefix_val, 10, 0, 128, -1);
+		if (prefix < 0) {
 			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 			             "Invalid IP6 prefix '%s'", prefix_val);
 			goto error;
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
index b2512590..a45357e8 100644
--- a/src/tests/test-general.c
+++ b/src/tests/test-general.c
@@ -98,6 +98,122 @@ test_nm_utils_ip6_address_clear_host_address (void)
 	g_rand_free (r);
 }
 
+/*****************************************************************************/
+
+static void
+_test_same_prefix (const char *a1, const char *a2, guint8 plen)
+{
+	struct in6_addr a = *nmtst_inet6_from_string (a1);
+	struct in6_addr b = *nmtst_inet6_from_string (a2);
+
+	g_assert (nm_utils_ip6_address_same_prefix (&a, &b, plen));
+}
+
+static void
+test_nm_utils_ip6_address_same_prefix (void)
+{
+	guint n, i;
+	const guint N = 100;
+	union {
+		guint8 ptr[sizeof (struct in6_addr)];
+		struct in6_addr val;
+	} a, b, addrmask, addrmask_bit;
+	guint8 plen;
+
+	/* test#1 */
+	for (n = 0; n < N; n++) {
+		gboolean is_same = n < N / 2;
+		gboolean result;
+
+		nmtst_rand_buf (NULL, a.ptr, sizeof (a));
+		nmtst_rand_buf (NULL, b.ptr, sizeof (b));
+again_plen:
+		plen = nmtst_get_rand_int () % 129;
+		if (!is_same && NM_IN_SET (plen, 0, 128))
+			goto again_plen;
+
+		if (plen < 128) {
+			for (i = 0; (i + 1) * 8 <= plen; i++)
+				b.ptr[i] = a.ptr[i];
+			if (plen % 8) {
+				guint8 mask;
+
+				g_assert (i < sizeof (a));
+				mask = ~((1 << (8 - (plen % 8))) - 1);
+				b.ptr[i] = (a.ptr[i] & mask) | (b.ptr[i] & ~mask);
+				if (!is_same) {
+					mask = (1 << (8 - (plen % 8)));
+					b.ptr[i] = (b.ptr[i] & ~mask) | ~(b.ptr[i] & mask);
+				}
+			} else if (!is_same) {
+				g_assert (i > 0);
+
+				b.ptr[i - 1] = (b.ptr[i - 1] & ~0x1) | ~(b.ptr[i - 1] & 0x1);
+			}
+		} else
+			b = a;
+
+		result = nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen);
+		g_assert (result == is_same);
+		g_assert (NM_IN_SET (result, TRUE, FALSE));
+	}
+
+	/* test#2 */
+	for (n = 0; n < N; n++) {
+		nmtst_rand_buf (NULL, a.ptr, sizeof (a));
+		nmtst_rand_buf (NULL, b.ptr, sizeof (b));
+		plen = nmtst_get_rand_int () % 129;
+
+		memset (addrmask.ptr, 0xFF, sizeof (addrmask));
+		nm_utils_ip6_address_clear_host_address (&addrmask.val, &addrmask.val, plen);
+
+		for (i = 0; i < sizeof (a); i++)
+			b.ptr[i] = (a.ptr[i] & addrmask.ptr[i]) | (b.ptr[i] & ~addrmask.ptr[i]);
+
+		g_assert (nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen) == TRUE);
+	}
+
+	/* test#3 */
+	for (n = 0; n < N; n++) {
+		gboolean reached = FALSE;
+
+		nmtst_rand_buf (NULL, a.ptr, sizeof (a));
+		nmtst_rand_buf (NULL, b.ptr, sizeof (b));
+		plen = nmtst_get_rand_int () % 129;
+
+		if (!plen)
+			continue;
+
+		memset (addrmask.ptr, 0xFF, sizeof (addrmask));
+		nm_utils_ip6_address_clear_host_address (&addrmask.val, &addrmask.val, plen);
+
+		memset (addrmask_bit.ptr, 0xFF, sizeof (addrmask_bit));
+		nm_utils_ip6_address_clear_host_address (&addrmask_bit.val, &addrmask_bit.val, plen - 1);
+
+		for (i = 0; i < sizeof (a); i++)
+			b.ptr[i] = (a.ptr[i] & addrmask.ptr[i]) | (b.ptr[i] & ~addrmask.ptr[i]);
+
+		/* flip the last bit. */
+		for (i = 0; i < sizeof (a); i++) {
+			guint8 mask = addrmask.ptr[i] ^ addrmask_bit.ptr[i];
+			if (mask) {
+				g_assert (!reached);
+				g_assert (nm_utils_is_power_of_two (mask));
+				reached = TRUE;
+				b.ptr[i] = (b.ptr[i] & ~mask) | ~(b.ptr[i] & mask);
+			}
+		}
+		g_assert (reached);
+
+		g_assert (nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen) == FALSE);
+	}
+
+	/* test#4 */
+	_test_same_prefix ("::", "::1", 10);
+	_test_same_prefix ("abcd::", "abcd::1", 10);
+}
+
+/*****************************************************************************/
 
 static void
 test_nm_utils_log_connection_diff (void)
@@ -1257,6 +1373,7 @@ main (int argc, char **argv)
 	g_test_add_func ("/general/nm_utils_strbuf_append", test_nm_utils_strbuf_append);
 
 	g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
+	g_test_add_func ("/general/nm_utils_ip6_address_same_prefix", test_nm_utils_ip6_address_same_prefix);
 	g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff);
 
 	g_test_add_func ("/general/connection-match/basic", test_connection_match_basic);
diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c
index 2b743c8c..9d38dc27 100644
--- a/src/tests/test-ip4-config.c
+++ b/src/tests/test-ip4-config.c
@@ -28,44 +28,6 @@
 
 #include "nm-test-utils.h"
 
-static void
-addr_init (NMPlatformIP4Address *a, const char *addr, const char *peer, guint plen)
-{
-	memset (a, 0, sizeof (*a));
-	g_assert (inet_pton (AF_INET, addr, (void *) &a->address) == 1);
-	if (peer)
-		g_assert (inet_pton (AF_INET, peer, (void *) &a->peer_address) == 1);
-	else
-		a->peer_address = a->address;
-	a->plen = plen;
-}
-
-static void
-route_new (NMPlatformIP4Route *route, const char *network, guint plen, const char *gw)
-{
-	guint n;
-
-	g_assert (route);
-	memset (route, 0, sizeof (*route));
-	g_assert (inet_pton (AF_INET, network, (void *) &n) == 1);
-	route->network = n;
-	route->plen = plen;
-	if (gw) {
-		n = 0;
-		g_assert (inet_pton (AF_INET, gw, (void *) &n) == 1);
-		route->gateway = n;
-	}
-}
-
-static guint32
-addr_to_num (const char *addr)
-{
-	guint n;
-
-	g_assert (inet_pton (AF_INET, addr, (void *) &n) == 1);
-	return n;
-}
-
 static NMIP4Config *
 build_test_config (void)
 {
@@ -76,29 +38,29 @@ build_test_config (void)
 	/* Build up the config to subtract */
 	config = nm_ip4_config_new (1);
 
-	addr_init (&addr, "192.168.1.10", "1.2.3.4", 24);
+	addr = *nmtst_platform_ip4_address ("192.168.1.10", "1.2.3.4", 24);
 	nm_ip4_config_add_address (config, &addr);
-	
-	route_new (&route, "10.0.0.0", 8, "192.168.1.1");
+
+	route = *nmtst_platform_ip4_route ("10.0.0.0", 8, "192.168.1.1");
 	nm_ip4_config_add_route (config, &route);
 
-	route_new (&route, "172.16.0.0", 16, "192.168.1.1");
+	route = *nmtst_platform_ip4_route ("172.16.0.0", 16, "192.168.1.1");
 	nm_ip4_config_add_route (config, &route);
 
-	nm_ip4_config_set_gateway (config, addr_to_num ("192.168.1.1"));
+	nm_ip4_config_set_gateway (config, nmtst_inet4_from_string ("192.168.1.1"));
 
-	nm_ip4_config_add_nameserver (config, addr_to_num ("4.2.2.1"));
-	nm_ip4_config_add_nameserver (config, addr_to_num ("4.2.2.2"));
+	nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("4.2.2.1"));
+	nm_ip4_config_add_nameserver (config, nmtst_inet4_from_string ("4.2.2.2"));
 	nm_ip4_config_add_domain (config, "foobar.com");
 	nm_ip4_config_add_domain (config, "baz.com");
 	nm_ip4_config_add_search (config, "blahblah.com");
 	nm_ip4_config_add_search (config, "beatbox.com");
 
-	nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.9"));
-	nm_ip4_config_add_nis_server (config, addr_to_num ("1.2.3.10"));
+	nm_ip4_config_add_nis_server (config, nmtst_inet4_from_string ("1.2.3.9"));
+	nm_ip4_config_add_nis_server (config, nmtst_inet4_from_string ("1.2.3.10"));
 
-	nm_ip4_config_add_wins (config, addr_to_num ("4.2.3.9"));
-	nm_ip4_config_add_wins (config, addr_to_num ("4.2.3.10"));
+	nm_ip4_config_add_wins (config, nmtst_inet4_from_string ("4.2.3.9"));
+	nm_ip4_config_add_wins (config, nmtst_inet4_from_string ("4.2.3.10"));
 
 	return config;
 }
@@ -116,12 +78,12 @@ test_subtract (void)
 	const char *expected_route_dest = "8.7.6.5";
 	guint32 expected_route_plen = 8;
 	const char *expected_route_next_hop = "192.168.1.1";
-	guint32 expected_ns1 = addr_to_num ("8.8.8.8");
-	guint32 expected_ns2 = addr_to_num ("8.8.8.9");
+	guint32 expected_ns1 = nmtst_inet4_from_string ("8.8.8.8");
+	guint32 expected_ns2 = nmtst_inet4_from_string ("8.8.8.9");
 	const char *expected_domain = "wonderfalls.com";
 	const char *expected_search = "somewhere.com";
-	guint32 expected_nis = addr_to_num ("1.2.3.13");
-	guint32 expected_wins = addr_to_num ("2.3.4.5");
+	guint32 expected_nis = nmtst_inet4_from_string ("1.2.3.13");
+	guint32 expected_wins = nmtst_inet4_from_string ("2.3.4.5");
 	guint32 expected_mss = 1400;
 	guint32 expected_mtu = 1492;
 
@@ -129,10 +91,10 @@ test_subtract (void)
 
 	/* add a couple more things to the test config */
 	dst = build_test_config ();
-	addr_init (&addr, expected_addr, NULL, expected_addr_plen);
+	addr = *nmtst_platform_ip4_address (expected_addr, NULL, expected_addr_plen);
 	nm_ip4_config_add_address (dst, &addr);
-	
-	route_new (&route, expected_route_dest, expected_route_plen, expected_route_next_hop);
+
+	route = *nmtst_platform_ip4_route (expected_route_dest, expected_route_plen, expected_route_next_hop);
 	nm_ip4_config_add_route (dst, &route);
 
 	nm_ip4_config_add_nameserver (dst, expected_ns1);
@@ -152,7 +114,7 @@ test_subtract (void)
 	g_assert_cmpuint (nm_ip4_config_get_num_addresses (dst), ==, 1);
 	test_addr = nm_ip4_config_get_address (dst, 0);
 	g_assert (test_addr != NULL);
-	g_assert_cmpuint (test_addr->address, ==, addr_to_num (expected_addr));
+	g_assert_cmpuint (test_addr->address, ==, nmtst_inet4_from_string (expected_addr));
 	g_assert_cmpuint (test_addr->peer_address, ==, test_addr->address);
 	g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
 
@@ -161,9 +123,9 @@ test_subtract (void)
 	g_assert_cmpuint (nm_ip4_config_get_num_routes (dst), ==, 1);
 	test_route = nm_ip4_config_get_route (dst, 0);
 	g_assert (test_route != NULL);
-	g_assert_cmpuint (test_route->network, ==, addr_to_num (expected_route_dest));
+	g_assert_cmpuint (test_route->network, ==, nmtst_inet4_from_string (expected_route_dest));
 	g_assert_cmpuint (test_route->plen, ==, expected_route_plen);
-	g_assert_cmpuint (test_route->gateway, ==, addr_to_num (expected_route_next_hop));
+	g_assert_cmpuint (test_route->gateway, ==, nmtst_inet4_from_string (expected_route_next_hop));
 
 	g_assert_cmpuint (nm_ip4_config_get_num_nameservers (dst), ==, 2);
 	g_assert_cmpuint (nm_ip4_config_get_nameserver (dst, 0), ==, expected_ns1);
@@ -198,7 +160,7 @@ test_compare_with_source (void)
 	b = nm_ip4_config_new (2);
 
 	/* Address */
-	addr_init (&addr, "1.2.3.4", NULL, 24);
+	addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24);
 	addr.source = NM_IP_CONFIG_SOURCE_USER;
 	nm_ip4_config_add_address (a, &addr);
 
@@ -206,7 +168,7 @@ test_compare_with_source (void)
 	nm_ip4_config_add_address (b, &addr);
 
 	/* Route */
-	route_new (&route, "10.0.0.0", 8, "192.168.1.1");
+	route = *nmtst_platform_ip4_route ("10.0.0.0", 8, "192.168.1.1");
 	route.source = NM_IP_CONFIG_SOURCE_USER;
 	nm_ip4_config_add_route (a, &route);
 
@@ -230,7 +192,7 @@ test_add_address_with_source (void)
 	a = nm_ip4_config_new (1);
 
 	/* Test that a higher priority source is not overwritten */
-	addr_init (&addr, "1.2.3.4", NULL, 24);
+	addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24);
 	addr.source = NM_IP_CONFIG_SOURCE_USER;
 	nm_ip4_config_add_address (a, &addr);
 
@@ -270,7 +232,7 @@ test_add_route_with_source (void)
 	a = nm_ip4_config_new (1);
 
 	/* Test that a higher priority source is not overwritten */
-	route_new (&route, "1.2.3.4", 24, "1.2.3.1");
+	route = *nmtst_platform_ip4_route ("1.2.3.4", 24, "1.2.3.1");
 	route.source = NM_IP_CONFIG_SOURCE_USER;
 	nm_ip4_config_add_route (a, &route);
 
diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c
index b32775da..c753174d 100644
--- a/src/tests/test-route-manager.c
+++ b/src/tests/test-route-manager.c
@@ -906,13 +906,13 @@ fixture_teardown (test_fixture *fixture, gconstpointer user_data)
 /*****************************************************************************/
 
 void
-init_tests (int *argc, char ***argv)
+_nmtstp_init_tests (int *argc, char ***argv)
 {
 	nmtst_init_assert_logging (argc, argv, "WARN", "ALL");
 }
 
 void
-setup_tests (void)
+_nmtstp_setup_tests (void)
 {
 	g_test_add ("/route-manager/ip4", test_fixture, NULL, fixture_setup, test_ip4, fixture_teardown);
 	g_test_add ("/route-manager/ip6", test_fixture, NULL, fixture_setup, test_ip6, fixture_teardown);
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index cbc7c69d..2945ad34 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -1387,11 +1387,11 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
 	if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, "u", &u32))
 		address.plen = u32;
 
-	if (address.address && address.plen) {
+	if (address.address && address.plen && address.plen <= 32) {
 		address.source = NM_IP_CONFIG_SOURCE_VPN;
 		nm_ip4_config_add_address (config, &address);
 	} else {
-		_LOGE ("invalid IP4 config received!");
+		_LOGW ("invalid IP4 config received!");
 		g_object_unref (config);
 		nm_vpn_connection_config_maybe_complete (self, FALSE);
 		return;
@@ -1439,6 +1439,9 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
 				route.metric = route_metric;
 				route.source = NM_IP_CONFIG_SOURCE_VPN;
 
+				if (route.plen > 32)
+					break;
+
 				/* Ignore host routes to the VPN gateway since NM adds one itself
 				 * below.  Since NM knows more about the routing situation than
 				 * the VPN server, we want to use the NM created route instead of
@@ -1448,7 +1451,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
 					nm_ip4_config_add_route (config, &route);
 				break;
 			default:
-				_LOGW ("VPN connection: received invalid IPv4 route");
+				break;
 			}
 			g_variant_unref (v);
 		}
@@ -1521,11 +1524,11 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
 	if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_PREFIX, "u", &u32))
 		address.plen = u32;
 
-	if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen) {
+	if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen && address.plen <= 128) {
 		address.source = NM_IP_CONFIG_SOURCE_VPN;
 		nm_ip6_config_add_address (config, &address);
 	} else {
-		_LOGE ("invalid IP6 config received!");
+		_LOGW ("invalid IP6 config received!");
 		g_object_unref (config);
 		nm_vpn_connection_config_maybe_complete (self, FALSE);
 		return;
@@ -1565,10 +1568,11 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
 
 			memset (&route, 0, sizeof (route));
 
-			if (!ip6_addr_from_variant (dest, &route.network)) {
-				_LOGW ("VPN connection: received invalid IPv6 dest address");
+			if (!ip6_addr_from_variant (dest, &route.network))
+				goto next;
+
+			if (prefix > 128)
 				goto next;
-			}
 
 			route.plen = prefix;
 			ip6_addr_from_variant (next_hop, &route.gateway);