summary refs log tree commit diff
path: root/src/platform
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/nm-fake-platform.c35
-rw-r--r--src/platform/nm-linux-platform.c295
-rw-r--r--src/platform/nm-linux-platform.h2
-rw-r--r--src/platform/nm-platform-utils.c27
-rw-r--r--src/platform/nm-platform-utils.h4
-rw-r--r--src/platform/nm-platform.c128
-rw-r--r--src/platform/nm-platform.h84
-rw-r--r--src/platform/nmp-object.c13
-rw-r--r--src/platform/nmp-object.h8
-rw-r--r--src/platform/tests/monitor.c23
-rw-r--r--src/platform/tests/test-address.c28
-rw-r--r--src/platform/tests/test-cleanup.c24
-rw-r--r--src/platform/tests/test-common.c30
-rw-r--r--src/platform/tests/test-link.c36
-rw-r--r--src/platform/tests/test-nmp-object.c4
-rw-r--r--src/platform/tests/test-route.c25
-rw-r--r--src/platform/wifi/wifi-utils-nl80211.c3
-rw-r--r--src/platform/wifi/wifi-utils-wext.c6
-rw-r--r--src/platform/wifi/wifi-utils.c3
19 files changed, 475 insertions, 303 deletions
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index a4eae902..68b72b19 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -18,7 +18,9 @@
  * Copyright (C) 2012–2013 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-fake-platform.h"
 
 #include <errno.h>
 #include <unistd.h>
@@ -27,10 +29,9 @@
 #include <linux/rtnetlink.h>
 
 #include "nm-utils.h"
+
+#include "nm-core-utils.h"
 #include "nmp-object.h"
-#include "NetworkManagerUtils.h"
-#include "nm-fake-platform.h"
-#include "nm-default.h"
 
 #include "nm-test-utils.h"
 
@@ -173,10 +174,10 @@ link_init (NMFakePlatformLink *device, int ifindex, int type, const char *name)
 		strcpy (device->link.name, name);
 	switch (device->link.type) {
 	case NM_LINK_TYPE_DUMMY:
-		device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_NOARP);
+		device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_NOARP);
 		break;
 	default:
-		device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_NOARP);
+		device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_NOARP);
 		break;
 	}
 }
@@ -440,9 +441,9 @@ link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware)
 		g_error ("Unexpected device type: %d", device->link.type);
 	}
 
-	if (   NM_FLAGS_HAS (device->link.flags, IFF_UP) != !!up
+	if (   NM_FLAGS_HAS (device->link.n_ifi_flags, IFF_UP) != !!up
 	    || device->link.connected != connected) {
-		device->link.flags = NM_FLAGS_ASSIGN (device->link.flags, IFF_UP, up);
+		device->link.n_ifi_flags = NM_FLAGS_ASSIGN (device->link.n_ifi_flags, IFF_UP, up);
 		device->link.connected = connected;
 		link_changed (platform, device, TRUE);
 	}
@@ -460,8 +461,8 @@ link_set_down (NMPlatform *platform, int ifindex)
 		return FALSE;
 	}
 
-	if (NM_FLAGS_HAS (device->link.flags, IFF_UP) || device->link.connected) {
-		device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_UP);
+	if (NM_FLAGS_HAS (device->link.n_ifi_flags, IFF_UP) || device->link.connected) {
+		device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_UP);
 		device->link.connected = FALSE;
 
 		link_changed (platform, device, TRUE);
@@ -480,7 +481,7 @@ link_set_arp (NMPlatform *platform, int ifindex)
 		return FALSE;
 	}
 
-	device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_NOARP);
+	device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_NOARP);
 
 	link_changed (platform, device, TRUE);
 
@@ -497,7 +498,7 @@ link_set_noarp (NMPlatform *platform, int ifindex)
 		return FALSE;
 	}
 
-	device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_NOARP);
+	device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_NOARP);
 
 	link_changed (platform, device, TRUE);
 
@@ -509,7 +510,8 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t
 {
 	NMFakePlatformLink *device = link_get (platform, ifindex);
 
-	if (   len == 0
+	if (   !device
+	    || len == 0
 	    || len > NM_UTILS_HWADDR_LEN_MAX
 	    || !addr)
 		g_return_val_if_reached (FALSE);
@@ -611,7 +613,7 @@ link_enslave (NMPlatform *platform, int master, int slave)
 		device->link.master = master;
 
 		if (NM_IN_SET (master_device->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) {
-			device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_UP);
+			device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_UP);
 			device->link.connected = TRUE;
 		}
 
@@ -937,7 +939,8 @@ ip6_address_add (NMPlatform *platform,
                  int plen,
                  struct in6_addr peer_addr,
                  guint32 lifetime,
-                 guint32 preferred, guint flags)
+                 guint32 preferred,
+                 guint32 flags)
 {
 	NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
 	NMPlatformIP6Address address;
@@ -952,7 +955,7 @@ ip6_address_add (NMPlatform *platform,
 	address.timestamp = nm_utils_get_monotonic_timestamp_s ();
 	address.lifetime = lifetime;
 	address.preferred = preferred;
-	address.flags = flags;
+	address.n_ifa_flags = flags;
 
 	for (i = 0; i < priv->ip6_addresses->len; i++) {
 		NMPlatformIP6Address *item = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index f73c228b..196e75cb 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -17,7 +17,9 @@
  *
  * Copyright (C) 2012-2015 Red Hat, Inc.
  */
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-linux-platform.h"
 
 #include <errno.h>
 #include <unistd.h>
@@ -42,22 +44,21 @@
 #include <netlink/route/route.h>
 #include <gudev/gudev.h>
 
+#include "nm-utils.h"
 #include "nm-core-internal.h"
-#include "NetworkManagerUtils.h"
-#include "nm-linux-platform.h"
+#include "nm-setting-vlan.h"
+
+#include "nm-core-utils.h"
+#include "nmp-object.h"
 #include "nm-platform-utils.h"
-#include "NetworkManagerUtils.h"
-#include "nm-utils.h"
-#include "nm-default.h"
 #include "wifi/wifi-utils.h"
 #include "wifi/wifi-utils-wext.h"
-#include "nmp-object.h"
-
-/* This is only included for the translation of VLAN flags */
-#include "nm-setting-vlan.h"
 
 #define VLAN_FLAG_MVRP 0x8
 
+/* nm-internal error codes for libnl. Make sure they don't overlap. */
+#define _NLE_NM_NOBUFS 500
+
 /*********************************************************************************************/
 
 #define IFQDISCSIZ                      32
@@ -115,8 +116,26 @@
 #define _NMLOG_PREFIX_NAME                "platform-linux"
 #define _NMLOG_DOMAIN                     LOGD_PLATFORM
 #define _NMLOG2_DOMAIN                    LOGD_PLATFORM
-#define _NMLOG(level, ...)                _LOG(level, _NMLOG_DOMAIN,  platform, __VA_ARGS__)
-#define _NMLOG2(level, ...)               _LOG(level, _NMLOG2_DOMAIN, NULL,     __VA_ARGS__)
+#define _NMLOG(level, ...)                _LOG     (       level, _NMLOG_DOMAIN,  platform, __VA_ARGS__)
+#define _NMLOG_err(errsv, level, ...)     _LOG_err (errsv, level, _NMLOG_DOMAIN,  platform, __VA_ARGS__)
+#define _NMLOG2(level, ...)               _LOG     (       level, _NMLOG2_DOMAIN, NULL,     __VA_ARGS__)
+#define _NMLOG2_err(errsv, level, ...)    _LOG_err (errsv, level, _NMLOG2_DOMAIN, NULL,     __VA_ARGS__)
+
+
+#define _LOG_print(__level, __domain, __errsv, self, ...) \
+    G_STMT_START { \
+        char __prefix[32]; \
+        const char *__p_prefix = _NMLOG_PREFIX_NAME; \
+        const void *const __self = (self); \
+        \
+        if (__self && __self != nm_platform_try_get ()) { \
+            g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \
+            __p_prefix = __prefix; \
+        } \
+        _nm_log (__level, __domain, __errsv, \
+                 "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
+                 __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
+    } G_STMT_END
 
 #define _LOG(level, domain, self, ...) \
     G_STMT_START { \
@@ -124,20 +143,30 @@
         const NMLogDomain __domain = (domain); \
         \
         if (nm_logging_enabled (__level, __domain)) { \
-            char __prefix[32]; \
-            const char *__p_prefix = _NMLOG_PREFIX_NAME; \
-            const void *const __self = (self); \
+            _LOG_print (__level, __domain, 0, self, __VA_ARGS__); \
+        } \
+    } G_STMT_END
+
+#define _LOG_err(errsv, level, domain, self, ...) \
+    G_STMT_START { \
+        const NMLogLevel __level = (level); \
+        const NMLogDomain __domain = (domain); \
+        \
+        if (nm_logging_enabled (__level, __domain)) { \
+            int __errsv = (errsv); \
             \
-            if (__self && __self != nm_platform_try_get ()) { \
-                g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \
-                __p_prefix = __prefix; \
-            } \
-            _nm_log (__level, __domain, 0, \
-                     "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
-                     __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
+            /* The %m format specifier (GNU extension) would alread allow you to specify the error
+             * message conveniently (and nm_log would get that right too). But we don't want to depend
+             * on that, so instead append the message at the end.
+             * Currently users are expected not to use %m in the format string. */ \
+            _LOG_print (__level, __domain, __errsv, self, \
+                        _NM_UTILS_MACRO_FIRST (__VA_ARGS__) ": %s (%d)" \
+                        _NM_UTILS_MACRO_REST (__VA_ARGS__), \
+                        g_strerror (__errsv), __errsv); \
         } \
     } G_STMT_END
 
+
 #define LOG_FMT_IP_TUNNEL "adding %s '%s' parent %u local %s remote %s"
 
 /******************************************************************
@@ -257,17 +286,6 @@ _support_user_ipv6ll_detect (struct nlattr **tb)
  * Various utilities
  ******************************************************************/
 
-const NMIPAddr nm_ip_addr_zero = NMIPAddrInit;
-
-#define IPV4LL_NETWORK (htonl (0xA9FE0000L))
-#define IPV4LL_NETMASK (htonl (0xFFFF0000L))
-
-static gboolean
-ip4_address_is_link_local (in_addr_t addr)
-{
-	return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK;
-}
-
 static guint
 _nm_ip_config_source_to_rtprot (NMIPConfigSource source)
 {
@@ -579,7 +597,7 @@ _lookup_cached_link (const NMPCache *cache, int ifindex, gboolean *completed_fro
 	if (!*completed_from_cache) {
 		obj = ifindex > 0 && cache ? nmp_cache_lookup_link (cache, ifindex) : NULL;
 
-		if (obj && !obj->_link.netlink.is_in_netlink)
+		if (obj && obj->_link.netlink.is_in_netlink)
 			*link_cached = obj;
 		else
 			*link_cached = NULL;
@@ -605,8 +623,8 @@ _linktype_read_devtype (const char *sysfs_path)
 		end = strpbrk (cont, "\r\n");
 		if (end)
 			*end++ = '\0';
-		if (strncmp (cont, DEVTYPE_PREFIX, STRLEN (DEVTYPE_PREFIX)) == 0) {
-			cont += STRLEN (DEVTYPE_PREFIX);
+		if (strncmp (cont, DEVTYPE_PREFIX, NM_STRLEN (DEVTYPE_PREFIX)) == 0) {
+			cont += NM_STRLEN (DEVTYPE_PREFIX);
 			memmove (contents, cont, strlen (cont) + 1);
 			return contents;
 		}
@@ -732,13 +750,19 @@ _linktype_get_type (NMPlatform *platform,
 		if (wifi_utils_is_wifi (ifname, sysfs_path))
 			return NM_LINK_TYPE_WIFI;
 
-		/* Standard wired ethernet interfaces don't report an rtnl_link_type, so
-		 * only allow fallback to Ethernet if no type is given.  This should
-		 * prevent future virtual network drivers from being treated as Ethernet
-		 * when they should be Generic instead.
-		 */
-		if (arptype == ARPHRD_ETHER && !kind && !devtype)
-			return NM_LINK_TYPE_ETHERNET;
+		if (arptype == ARPHRD_ETHER) {
+			/* Standard wired ethernet interfaces don't report an rtnl_link_type, so
+			 * only allow fallback to Ethernet if no type is given.  This should
+			 * prevent future virtual network drivers from being treated as Ethernet
+			 * when they should be Generic instead.
+			 */
+			if (!kind && !devtype)
+				return NM_LINK_TYPE_ETHERNET;
+			/* The USB gadget interfaces behave and look like ordinary ethernet devices
+			 * aside from the DEVTYPE. */
+			if (!g_strcmp0 (devtype, "gadget"))
+				return NM_LINK_TYPE_ETHERNET;
+		}
 	}
 
 	return NM_LINK_TYPE_UNKNOWN;
@@ -1464,8 +1488,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
 		nl_info_data = li[IFLA_INFO_DATA];
 	}
 
-	obj->link.flags = ifi->ifi_flags;
-	obj->link.connected = NM_FLAGS_HAS (obj->link.flags, IFF_LOWER_UP);
+	obj->link.n_ifi_flags = ifi->ifi_flags;
+	obj->link.connected = NM_FLAGS_HAS (obj->link.n_ifi_flags, IFF_LOWER_UP);
 	obj->link.arptype = ifi->ifi_type;
 
 	obj->link.type = _linktype_get_type (platform,
@@ -1473,7 +1497,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
 	                                     nl_info_kind,
 	                                     obj->link.ifindex,
 	                                     obj->link.name,
-	                                     obj->link.flags,
+	                                     obj->link.n_ifi_flags,
 	                                     obj->link.arptype,
 	                                     completed_from_cache,
 	                                     &link_cached,
@@ -1650,9 +1674,9 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
 	obj->ip_address.source = NM_IP_CONFIG_SOURCE_KERNEL;
 
 	if (!is_v4) {
-		obj->ip6_address.flags = tb[IFA_FLAGS]
-		                         ? nla_get_u32 (tb[IFA_FLAGS])
-		                         : ifa->ifa_flags;
+		obj->ip6_address.n_ifa_flags = tb[IFA_FLAGS]
+		                               ? nla_get_u32 (tb[IFA_FLAGS])
+		                               : ifa->ifa_flags;
 	}
 
 	if (is_v4) {
@@ -2329,8 +2353,8 @@ static gboolean
 _support_kernel_extended_ifa_flags_get (void)
 {
 	if (_support_kernel_extended_ifa_flags_still_undecided ()) {
-		_LOG2W ("support: kernel-extended-ifa-flags: unable to detect kernel support for handling IPv6 temporary addresses. Assume none");
-		_support_kernel_extended_ifa_flags = 0;
+		_LOG2W ("support: kernel-extended-ifa-flags: unable to detect kernel support for handling IPv6 temporary addresses. Assume support");
+		_support_kernel_extended_ifa_flags = 1;
 	}
 	return _support_kernel_extended_ifa_flags;
 }
@@ -2427,8 +2451,11 @@ _log_dbg_sysctl_set_impl (NMPlatform *platform, const char *path, const char *va
 static gboolean
 sysctl_set (NMPlatform *platform, const char *path, const char *value)
 {
-	int fd, len, nwrote, tries;
+	int fd, tries;
+	gssize nwrote;
+	gsize len;
 	char *actual;
+	gs_free char *actual_free = NULL;
 
 	g_return_val_if_fail (path != NULL, FALSE);
 	g_return_val_if_fail (value != NULL, FALSE);
@@ -2458,10 +2485,16 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
 	 * sysctl support partial writes so the LF must be added to the string we're
 	 * about to write.
 	 */
-	actual = g_strdup_printf ("%s\n", value);
+	len = strlen (value) + 1;
+	if (len > 512)
+		actual = actual_free = g_malloc (len + 1);
+	else
+		actual = g_alloca (len + 1);
+	memcpy (actual, value, len - 1);
+	actual[len - 1] = '\n';
+	actual[len] = '\0';
 
 	/* Try to write the entire value three times if a partial write occurs */
-	len = strlen (actual);
 	for (tries = 0, nwrote = 0; tries < 3 && nwrote != len; tries++) {
 		nwrote = write (fd, actual, len);
 		if (nwrote == -1) {
@@ -2480,15 +2513,14 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
 		       path, value);
 	}
 
-	g_free (actual);
 	close (fd);
 	return (nwrote == len);
 }
 
 static GSList *sysctl_clear_cache_list;
 
-void
-_nm_linux_platform_sysctl_clear_cache (void)
+static void
+_nm_logging_clear_platform_logging_cache_impl (void)
 {
 	while (sysctl_clear_cache_list) {
 		NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (sysctl_clear_cache_list->data);
@@ -2508,6 +2540,7 @@ _log_dbg_sysctl_get_impl (NMPlatform *platform, const char *path, const char *co
 	const char *prev_value = NULL;
 
 	if (!priv->sysctl_get_prev_values) {
+		_nm_logging_clear_platform_logging_cache = _nm_logging_clear_platform_logging_cache_impl;
 		sysctl_clear_cache_list = g_slist_prepend (sysctl_clear_cache_list, platform);
 		priv->sysctl_get_prev_values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 	} else
@@ -2798,13 +2831,23 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
 
 static void
 delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform,
-                                                  WaitForNlResponseResult result)
+                                                  WaitForNlResponseResult fallback_result)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 
 	if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
-		while (priv->delayed_action.list_wait_for_nl_response->len > 0)
-			delayed_action_wait_for_nl_response_complete (platform, priv->delayed_action.list_wait_for_nl_response->len - 1, result);
+		while (priv->delayed_action.list_wait_for_nl_response->len > 0) {
+			const DelayedActionWaitForNlResponseData *data;
+			guint idx = priv->delayed_action.list_wait_for_nl_response->len - 1;
+			WaitForNlResponseResult r;
+
+			data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, idx);
+
+			/* prefer the result that we already have. */
+			r = data->seq_result ? : fallback_result;
+
+			delayed_action_wait_for_nl_response_complete (platform, idx, r);
+		}
 	}
 	nm_assert (!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);
@@ -3190,9 +3233,9 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 			if (   ops_type == NMP_CACHE_OPS_UPDATED
 			    && old && new /* <-- nonsensical, make coverity happy */
 			    && old->_link.netlink.is_in_netlink
-			    && NM_FLAGS_HAS (old->link.flags, IFF_LOWER_UP)
+			    && NM_FLAGS_HAS (old->link.n_ifi_flags, IFF_LOWER_UP)
 			    && new->_link.netlink.is_in_netlink
-			    && !NM_FLAGS_HAS (new->link.flags, IFF_LOWER_UP)) {
+			    && !NM_FLAGS_HAS (new->link.n_ifi_flags, IFF_LOWER_UP)) {
 				delayed_action_schedule (platform,
 				                         DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ROUTES |
 				                         DELAYED_ACTION_TYPE_REFRESH_ALL_IP6_ROUTES,
@@ -3235,6 +3278,19 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 				                         DELAYED_ACTION_TYPE_REFRESH_LINK,
 				                         GINT_TO_POINTER (new->link.ifindex));
 			}
+			if (   new->link.type == NM_LINK_TYPE_ETHERNET
+			    && new->link.addr.len == 0) {
+				/* Due to a kernel bug, we sometimes receive spurious NEWLINK
+				 * messages after a wifi interface has disappeared. Since the
+				 * link is not present anymore we can't determine its type and
+				 * thus it will show up as a Ethernet one, with no address
+				 * specified.  Request the link again to check if it really
+				 * exists.  https://bugzilla.redhat.com/show_bug.cgi?id=1302037
+				 */
+				delayed_action_schedule (platform,
+				                         DELAYED_ACTION_TYPE_REFRESH_LINK,
+				                         GINT_TO_POINTER (new->link.ifindex));
+			}
 		}
 		{
 			/* on enslave/release, we also refresh the master. */
@@ -3243,8 +3299,8 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 
 			changed_master =    (new && new->_link.netlink.is_in_netlink && new->link.master > 0 ? new->link.master : 0)
 			                 != (old && old->_link.netlink.is_in_netlink && old->link.master > 0 ? old->link.master : 0);
-			changed_connected =    (new && new->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (new->link.flags, IFF_LOWER_UP) : 2)
-			                    != (old && old->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (old->link.flags, IFF_LOWER_UP) : 2);
+			changed_connected =    (new && new->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (new->link.n_ifi_flags, IFF_LOWER_UP) : 2)
+			                    != (old && old->_link.netlink.is_in_netlink ? NM_FLAGS_HAS (old->link.n_ifi_flags, IFF_LOWER_UP) : 2);
 
 			if (changed_master || changed_connected) {
 				ifindex1 = (old && old->_link.netlink.is_in_netlink && old->link.master > 0) ? old->link.master : 0;
@@ -3455,7 +3511,7 @@ event_seq_check (NMPlatform *platform, struct nl_msg *msg, WaitForNlResponseResu
 }
 
 static void
-event_valid_msg (NMPlatform *platform, struct nl_msg *msg)
+event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_events)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	nm_auto_nmpobj NMPObject *obj = NULL;
@@ -3471,6 +3527,9 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg)
 	if (_support_kernel_extended_ifa_flags_still_undecided () && msghdr->nlmsg_type == RTM_NEWADDR)
 		_support_kernel_extended_ifa_flags_detect (msg);
 
+	if (!handle_events)
+		return;
+
 	if (NM_IN_SET (msghdr->nlmsg_type, RTM_DELLINK, RTM_DELADDR, RTM_DELROUTE)) {
 		/* The event notifies about a deleted object. We don't need to initialize all
 		 * fields of the object. */
@@ -4684,7 +4743,6 @@ link_vlan_change (NMPlatform *platform,
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	const NMPObject *obj_cache;
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
-	unsigned flags;
 	const NMPObjectLnkVlan *lnk;
 	guint new_n_ingress_map = 0;
 	guint new_n_egress_map = 0;
@@ -4702,7 +4760,6 @@ link_vlan_change (NMPlatform *platform,
 	}
 
 	lnk = obj_cache->_link.netlink.lnk ? &obj_cache->_link.netlink.lnk->_lnk_vlan : NULL;
-	flags = obj_cache->link.flags;
 
 	flags_set &= flags_mask;
 
@@ -4821,6 +4878,7 @@ tun_add (NMPlatform *platform, const char *name, gboolean tap,
 	if (out_link)
 		*out_link = obj ? &obj->link : NULL;
 
+	close (fd);
 	return !!obj;
 }
 
@@ -5139,7 +5197,7 @@ ip4_address_add (NMPlatform *platform,
 	                             plen,
 	                             &peer_addr,
 	                             0,
-	                             ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
+	                             nmp_utils_ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
 	                             lifetime,
 	                             preferred,
 	                             label);
@@ -5156,7 +5214,7 @@ ip6_address_add (NMPlatform *platform,
                  struct in6_addr peer_addr,
                  guint32 lifetime,
                  guint32 preferred,
-                 guint flags)
+                 guint32 flags)
 {
 	NMPObject obj_id;
 	nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
@@ -5492,8 +5550,7 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	struct nl_sock *sk = priv->nlh;
-	int n, err = 0, multipart = 0, interrupted = 0, nrecv = 0;
-	unsigned char *buf = NULL;
+	int n, err = 0, multipart = 0, interrupted = 0;
 	struct nlmsghdr *hdr;
 	WaitForNlResponseResult seq_result;
 
@@ -5503,34 +5560,44 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events)
 	initialize the variable. Thomas Graf.
 	*/
 	struct sockaddr_nl nla = {0};
-	struct nl_msg *msg = NULL;
-	struct ucred *creds = NULL;
+	nm_auto_free struct ucred *creds = NULL;
+	nm_auto_free unsigned char *buf = NULL;
 
 continue_reading:
+	g_clear_pointer (&buf, free);
+	g_clear_pointer (&creds, free);
 	errno = 0;
 	n = nl_recv (sk, &nla, &buf, &creds);
 
-	/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
-	if (n == 0 && errno == EAGAIN) {
-		/* EAGAIN is equal to EWOULDBLOCK. If it would not be, we'd have to
-		 * workaround libnl3 mapping EWOULDBLOCK to -NLE_FAILURE. */
-		G_STATIC_ASSERT (EAGAIN == EWOULDBLOCK);
-		n = -NLE_AGAIN;
+	switch (n) {
+	case 0:
+		/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
+		if (errno == EAGAIN) {
+			/* EAGAIN is equal to EWOULDBLOCK. If it would not be, we'd have to
+			 * workaround libnl3 mapping EWOULDBLOCK to -NLE_FAILURE. */
+			G_STATIC_ASSERT (EAGAIN == EWOULDBLOCK);
+			n = -NLE_AGAIN;
+		}
+		break;
+	case -NLE_NOMEM:
+		if (errno == ENOBUFS) {
+			/* we are very much interested in a overrun of the receive buffer.
+			 * nl_recv() maps all kinds of errors to NLE_NOMEM, so check also
+			 * for errno explicitly. And if so, hack our own return code to signal
+			 * the overrun. */
+			n = -_NLE_NM_NOBUFS;
+		}
+		break;
 	}
 
 	if (n <= 0)
 		return n;
 
-	if (!handle_events) {
-		/* we read until failure or there is nothing to read (EAGAIN). */
-		goto continue_reading;
-	}
-
 	hdr = (struct nlmsghdr *) buf;
 	while (nlmsg_ok (hdr, n)) {
+		nm_auto_nlmsg struct nl_msg *msg = NULL;
 		gboolean abort_parsing = FALSE;
 
-		nlmsg_free (msg);
 		msg = nlmsg_convert (hdr);
 		if (!msg) {
 			err = -NLE_NOMEM;
@@ -5539,13 +5606,13 @@ continue_reading:
 
 		nlmsg_set_proto (msg, NETLINK_ROUTE);
 		nlmsg_set_src (msg, &nla);
-		nrecv++;
 
 		if (!creds || creds->pid) {
 			if (creds)
-				_LOGD ("netlink: recvmsg: received non-kernel message (pid %d)", creds->pid);
+				_LOGT ("netlink: recvmsg: received non-kernel message (pid %d)", creds->pid);
 			else
-				_LOGD ("netlink: recvmsg: received message without credentials");
+				_LOGT ("netlink: recvmsg: received message without credentials");
+			err = 0;
 			goto stop;
 		}
 
@@ -5618,42 +5685,35 @@ continue_reading:
 			/* Valid message (not checking for MULTIPART bit to
 			 * get along with broken kernels. NL_SKIP has no
 			 * effect on this.  */
-			event_valid_msg (platform, msg);
+
+			event_valid_msg (platform, msg, handle_events);
+
 			seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
 		}
 
 		event_seq_check (platform, msg, seq_result);
-		err = 0;
-		hdr = nlmsg_next (hdr, &n);
 
 		if (abort_parsing)
-			goto out;
-	}
+			goto stop;
 
-	nlmsg_free (msg);
-	free (buf);
-	free (creds);
-	buf = NULL;
-	msg = NULL;
-	creds = NULL;
+		err = 0;
+		hdr = nlmsg_next (hdr, &n);
+	}
 
 	if (multipart) {
 		/* Multipart message not yet complete, continue reading */
 		goto continue_reading;
 	}
 stop:
-	err = 0;
+	if (!handle_events) {
+		/* when we don't handle events, we want to drain all messages from the socket
+		 * without handling the messages (but still check for sequence numbers).
+		 * Repeat reading. */
+		goto continue_reading;
+	}
 out:
-	nlmsg_free (msg);
-	free (buf);
-	free (creds);
-
 	if (interrupted)
 		err = -NLE_DUMP_INTR;
-
-	if (!err)
-		err = nrecv;
-
 	return err;
 }
 
@@ -5687,12 +5747,10 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks)
 				case -NLE_DUMP_INTR:
 					_LOGD ("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
 					break;
-				case -NLE_NOMEM:
+				case -_NLE_NM_NOBUFS:
 					_LOGI ("netlink: read: too many netlink events. Need to resynchronize platform cache");
-					/* Drain the event queue, we've lost events and are out of sync anyway and we'd
-					 * like to free up some space. We'll read in the status synchronously. */
-					delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
 					event_handler_recvmsgs (platform, FALSE);
+					delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
 					delayed_action_schedule (platform,
 					                         DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS |
 					                         DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES |
@@ -5728,9 +5786,10 @@ after_read:
 				i++;
 
 				if (   data_next.seq_number == 0
-				    || data_next.timeout_abs_ns > data->timeout_abs_ns)
+				    || data_next.timeout_abs_ns > data->timeout_abs_ns) {
 					data_next.seq_number = data->seq_number;
 					data_next.timeout_abs_ns = data->timeout_abs_ns;
+				}
 			}
 		}
 
@@ -5916,14 +5975,8 @@ constructed (GObject *_object)
 	nle = nl_socket_set_nonblocking (priv->nlh);
 	g_assert (!nle);
 
-	/* The default buffer size wasn't enough for the testsuites. It might just
-	 * as well happen with NetworkManager itself. For now let's hope 128KB is
-	 * good enough.
-	 *
-	 * FIXME: it's unclear that this is still actually needed. The testsuite
-	 * certainly doesn't fail for me. Maybe it can be removed.
-	 */
-	nle = nl_socket_set_buffer_size (priv->nlh, 131072, 0);
+	/* use 8 MB for receive socket kernel queue. */
+	nle = nl_socket_set_buffer_size (priv->nlh, 8*1024*1024, 0);
 	g_assert (!nle);
 
 	nle = nl_socket_add_memberships (priv->nlh,
diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h
index 81f9c738..a9e2cd82 100644
--- a/src/platform/nm-linux-platform.h
+++ b/src/platform/nm-linux-platform.h
@@ -50,6 +50,4 @@ GType nm_linux_platform_get_type (void);
 
 void nm_linux_platform_setup (void);
 
-void _nm_linux_platform_sysctl_clear_cache (void);
-
 #endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index 953ac8c5..0f2656f2 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -18,6 +18,8 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
+#include "nm-default.h"
+
 #include "nm-platform-utils.h"
 
 #include <string.h>
@@ -30,10 +32,9 @@
 #include <linux/version.h>
 
 #include "nm-utils.h"
-#include "NetworkManagerUtils.h"
-#include "nm-default.h"
 #include "nm-setting-wired.h"
 
+#include "nm-core-utils.h"
 
 /******************************************************************
  * ethtool
@@ -142,7 +143,8 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
 		struct ethtool_perm_addr e;
 		guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1];
 	} edata;
-	guint zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
+	static const guint8 zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
+	static guint8 ones[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
 
 	if (!ifname)
 		return FALSE;
@@ -161,6 +163,12 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
 	if (memcmp (edata.e.data, zeros, edata.e.size) == 0)
 		return FALSE;
 
+	/* Some drivers return a permanent address of all ones. Reject that too */
+	if (G_UNLIKELY (ones[0] != 0xFF))
+		memset (ones, 0xFF, sizeof (ones));
+	if (memcmp (edata.e.data, ones, edata.e.size) == 0)
+		return FALSE;
+
 	memcpy (buf, edata.e.data, edata.e.size);
 	*length = edata.e.size;
 	return TRUE;
@@ -408,6 +416,15 @@ out:
  * utils
  ******************************************************************/
 
+#define IPV4LL_NETWORK (htonl (0xA9FE0000L))
+#define IPV4LL_NETMASK (htonl (0xFFFF0000L))
+
+gboolean
+nmp_utils_ip4_address_is_link_local (in_addr_t addr)
+{
+	return (addr & IPV4LL_NETMASK) == IPV4LL_NETWORK;
+}
+
 /**
  * Takes a pair @timestamp and @duration, and returns the remaining duration based
  * on the new timestamp @now.
@@ -496,13 +513,13 @@ gboolean
 nmp_utils_device_exists (const char *name)
 {
 #define SYS_CLASS_NET "/sys/class/net/"
-	char sysdir[STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET;
+	char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET;
 
 	if (   !name
 	    || strlen (name) >= IFNAMSIZ
 	    || !nm_utils_is_valid_path_component (name))
 		g_return_val_if_reached (FALSE);
 
-	strcpy (&sysdir[STRLEN (SYS_CLASS_NET)], name);
+	strcpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], name);
 	return g_file_test (sysdir, G_FILE_TEST_EXISTS);
 }
diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h
index 3769a8e1..a9d29c04 100644
--- a/src/platform/nm-platform-utils.h
+++ b/src/platform/nm-platform-utils.h
@@ -21,8 +21,6 @@
 #ifndef __NM_PLATFORM_UTILS_H__
 #define __NM_PLATFORM_UTILS_H__
 
-#include "config.h"
-
 #include <gudev/gudev.h>
 
 #include "nm-platform.h"
@@ -69,4 +67,6 @@ gboolean nmp_utils_lifetime_get (guint32 timestamp,
 
 gboolean nmp_utils_device_exists (const char *name);
 
+gboolean nmp_utils_ip4_address_is_link_local (in_addr_t addr);
+
 #endif /* __NM_PLATFORM_UTILS_H__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 3bb44e1a..e3126442 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -18,7 +18,9 @@
  * Copyright (C) 2012 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nm-platform.h"
 
 #include <stdlib.h>
 #include <errno.h>
@@ -32,15 +34,19 @@
 #include <linux/if_tun.h>
 #include <linux/if_tunnel.h>
 
-#include "NetworkManagerUtils.h"
 #include "nm-utils.h"
-#include "nm-platform.h"
+#include "nm-core-internal.h"
+
+#include "nm-core-utils.h"
+#include "nm-enum-types.h"
 #include "nm-platform-utils.h"
 #include "nmp-object.h"
-#include "NetworkManagerUtils.h"
-#include "nm-default.h"
-#include "nm-enum-types.h"
-#include "nm-core-internal.h"
+
+/*****************************************************************************/
+
+const NMIPAddr nm_ip_addr_zero = NMIPAddrInit;
+
+/*****************************************************************************/
 
 #define ADDRESS_LIFETIME_PADDING 5
 
@@ -181,39 +187,26 @@ nm_platform_try_get (void)
 /******************************************************************/
 
 /**
- * nm_platform_error_to_string:
+ * _nm_platform_error_to_string:
  * @error_code: the error code to stringify.
  *
  * Returns: A string representation of the error.
  * For negative numbers, this function interprets
  * the code as -errno.
+ * For invalid (positive) numbers it returns NULL.
  */
-const char *
-nm_platform_error_to_string (NMPlatformError error)
-{
-	switch (error) {
-	case NM_PLATFORM_ERROR_SUCCESS:
-		return "success";
-	case NM_PLATFORM_ERROR_BUG:
-		return "bug";
-	case NM_PLATFORM_ERROR_UNSPECIFIED:
-		return "unspecified";
-	case NM_PLATFORM_ERROR_NOT_FOUND:
-		return "not-found";
-	case NM_PLATFORM_ERROR_EXISTS:
-		return "exists";
-	case NM_PLATFORM_ERROR_WRONG_TYPE:
-		return "wrong-type";
-	case NM_PLATFORM_ERROR_NOT_SLAVE:
-		return "not-slave";
-	case NM_PLATFORM_ERROR_NO_FIRMWARE:
-		return "no-firmware";
-	default:
-		if (error < 0)
-			return g_strerror (- ((int) error));
-		return "unknown";
-	}
-}
+NM_UTILS_LOOKUP_STR_DEFINE (_nm_platform_error_to_string, NMPlatformError,
+	NM_UTILS_LOOKUP_DEFAULT ( val < 0 ? g_strerror (- ((int) val)) : NULL ),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_SUCCESS,     "success"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_BUG,         "bug"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_UNSPECIFIED, "unspecified"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_NOT_FOUND,   "not-found"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_EXISTS,      "exists"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_WRONG_TYPE,  "wrong-type"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_NOT_SLAVE,   "not-slave"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_ERROR_NO_FIRMWARE, "no-firmware"),
+	NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_PLATFORM_ERROR_MININT),
+);
 
 /******************************************************************/
 
@@ -811,13 +804,13 @@ nm_platform_link_refresh (NMPlatform *self, int ifindex)
 	return TRUE;
 }
 
-static guint32
+static guint
 _link_get_flags (NMPlatform *self, int ifindex)
 {
 	const NMPlatformLink *pllink;
 
 	pllink = nm_platform_link_get (self, ifindex);
-	return pllink ? pllink->flags : IFF_NOARP;
+	return pllink ? pllink->n_ifi_flags : IFF_NOARP;
 }
 
 /**
@@ -2147,7 +2140,8 @@ nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_pe
 gboolean
 nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname, NMPlatformTunProperties *props)
 {
-	char *path, *val;
+	char path[256];
+	char *val;
 	gboolean success = TRUE;
 
 	_CHECK_SELF (self, klass, FALSE);
@@ -2160,11 +2154,9 @@ nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname
 
 	if (!ifname || !nm_utils_iface_valid_name (ifname))
 		return FALSE;
-	ifname = ASSERT_VALID_PATH_COMPONENT (ifname);
 
-	path = g_strdup_printf ("/sys/class/net/%s/owner", ifname);
+	nm_sprintf_buf (path, "/sys/class/net/%s/owner", ifname);
 	val = nm_platform_sysctl_get (self, path);
-	g_free (path);
 	if (val) {
 		props->owner = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
 		if (errno)
@@ -2173,9 +2165,8 @@ nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname
 	} else
 		success = FALSE;
 
-	path = g_strdup_printf ("/sys/class/net/%s/group", ifname);
+	nm_sprintf_buf (path, "/sys/class/net/%s/group", ifname);
 	val = nm_platform_sysctl_get (self, path);
-	g_free (path);
 	if (val) {
 		props->group = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1);
 		if (errno)
@@ -2184,9 +2175,8 @@ nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname
 	} else
 		success = FALSE;
 
-	path = g_strdup_printf ("/sys/class/net/%s/tun_flags", ifname);
+	nm_sprintf_buf (path, "/sys/class/net/%s/tun_flags", ifname);
 	val = nm_platform_sysctl_get (self, path);
-	g_free (path);
 	if (val) {
 		gint64 flags;
 
@@ -2461,7 +2451,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
                              struct in6_addr peer_address,
                              guint32 lifetime,
                              guint32 preferred,
-                             guint flags)
+                             guint32 flags)
 {
 	_CHECK_SELF (self, klass, FALSE);
 
@@ -2480,7 +2470,7 @@ nm_platform_ip6_address_add (NMPlatform *self,
 		addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */
 		addr.lifetime = lifetime;
 		addr.preferred = preferred;
-		addr.flags = flags;
+		addr.n_ifa_flags = flags;
 
 		_LOGD ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr, NULL, 0));
 	}
@@ -2701,7 +2691,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
 
 		if (!nm_platform_ip6_address_add (self, ifindex, known_address->address,
 		                                  known_address->plen, known_address->peer_address,
-		                                  lifetime, preferred, known_address->flags))
+		                                  lifetime, preferred, known_address->n_ifa_flags))
 			return FALSE;
 	}
 
@@ -2978,19 +2968,19 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 		return buf;
 
 	str_flags = g_string_new (NULL);
-	if (NM_FLAGS_HAS (link->flags, IFF_NOARP))
+	if (NM_FLAGS_HAS (link->n_ifi_flags, IFF_NOARP))
 		g_string_append (str_flags, "NOARP,");
-	if (NM_FLAGS_HAS (link->flags, IFF_UP))
+	if (NM_FLAGS_HAS (link->n_ifi_flags, IFF_UP))
 		g_string_append (str_flags, "UP");
 	else
 		g_string_append (str_flags, "DOWN");
 	if (link->connected)
 		g_string_append (str_flags, ",LOWER_UP");
 
-	if (link->flags) {
+	if (link->n_ifi_flags) {
 		char str_flags_buf[64];
 
-		nm_platform_link_flags2str (link->flags, str_flags_buf, sizeof (str_flags_buf));
+		nm_platform_link_flags2str (link->n_ifi_flags, str_flags_buf, sizeof (str_flags_buf));
 		g_string_append_printf (str_flags, ";%s", str_flags_buf);
 	}
 
@@ -3006,21 +2996,6 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 	else
 		parent[0] = 0;
 
-	if (link->inet6_addr_gen_mode_inv) {
-		switch (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv)) {
-			case 0:
-				g_snprintf (str_addrmode, sizeof (str_addrmode), " addrgenmode eui64");
-				break;
-			case 1:
-				g_snprintf (str_addrmode, sizeof (str_addrmode), " addrgenmode none");
-				break;
-			default:
-				g_snprintf (str_addrmode, sizeof (str_addrmode), " addrgenmode %d", _nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv));
-				break;
-		}
-	} else
-		str_addrmode[0] = '\0';
-
 	if (link->addr.len)
 		str_addr = nm_utils_hwaddr_ntoa (link->addr.data, MIN (link->addr.len, sizeof (link->addr.data)));
 	if (link->inet6_token.is_valid)
@@ -3036,10 +3011,10 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 	            " mtu %d"
 	            "%s" /* master */
 	            " arp %u" /* arptype */
-	            "%s%s" /* link->type */
+	            " %s" /* link->type */
 	            "%s%s" /* kind */
 	            "%s" /* is-in-udev */
-	            "%s" /* addr-gen-mode */
+	            "%s%s" /* addr-gen-mode */
 	            "%s%s" /* addr */
 	            "%s%s" /* inet6_token */
 	            "%s%s" /* driver */
@@ -3050,12 +3025,12 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
 	            str_flags->str,
 	            link->mtu, master,
 	            link->arptype,
-	            str_link_type ? " " : "",
 	            str_if_set (str_link_type, "???"),
-	            link->kind ? (g_strcmp0 (str_link_type, link->kind) ? "/" : "*") : "",
+	            link->kind ? (g_strcmp0 (str_link_type, link->kind) ? "/" : "*") : "?",
 	            link->kind && g_strcmp0 (str_link_type, link->kind) ? link->kind : "",
 	            link->initialized ? " init" : " not-init",
-	            str_addrmode,
+	            link->inet6_addr_gen_mode_inv ? " addrgenmode " : "",
+	            link->inet6_addr_gen_mode_inv ? nm_platform_link_inet6_addrgenmode2str (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv), str_addrmode, sizeof (str_addrmode)) : "",
 	            str_addr ? " addr " : "",
 	            str_addr ? str_addr : "",
 	            str_inet6_token ? " inet6token " : "",
@@ -3444,6 +3419,7 @@ NM_UTILS_ENUM2STR_DEFINE (nm_platform_link_inet6_addrgenmode2str, guint8,
 	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_NONE, "none"),
 	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"),
 	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"),
+	NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_RANDOM, "random"),
 );
 
 NM_UTILS_FLAGS2STR_DEFINE (nm_platform_addr_flags2str, unsigned,
@@ -3503,11 +3479,11 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu
 
 	_to_string_dev (NULL, address->ifindex, str_dev, sizeof (str_dev));
 
-	nm_platform_addr_flags2str (address->flags, &s_flags[STRLEN (S_FLAGS_PREFIX)], sizeof (s_flags) - STRLEN (S_FLAGS_PREFIX));
-	if (s_flags[STRLEN (S_FLAGS_PREFIX)] == '\0')
+	nm_platform_addr_flags2str (address->n_ifa_flags, &s_flags[NM_STRLEN (S_FLAGS_PREFIX)], sizeof (s_flags) - NM_STRLEN (S_FLAGS_PREFIX));
+	if (s_flags[NM_STRLEN (S_FLAGS_PREFIX)] == '\0')
 		s_flags[0] = '\0';
 	else
-		memcpy (s_flags, S_FLAGS_PREFIX, STRLEN (S_FLAGS_PREFIX));
+		memcpy (s_flags, S_FLAGS_PREFIX, NM_STRLEN (S_FLAGS_PREFIX));
 
 	str_lft_p = _lifetime_to_string (address->timestamp,
 	                                 address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT,
@@ -3708,7 +3684,7 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
 	_CMP_FIELD_STR (a, b, name);
 	_CMP_FIELD (a, b, master);
 	_CMP_FIELD (a, b, parent);
-	_CMP_FIELD (a, b, flags);
+	_CMP_FIELD (a, b, n_ifi_flags);
 	_CMP_FIELD (a, b, connected);
 	_CMP_FIELD (a, b, mtu);
 	_CMP_FIELD_BOOL (a, b, initialized);
@@ -3871,7 +3847,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
 	_CMP_FIELD (a, b, timestamp);
 	_CMP_FIELD (a, b, lifetime);
 	_CMP_FIELD (a, b, preferred);
-	_CMP_FIELD (a, b, flags);
+	_CMP_FIELD (a, b, n_ifa_flags);
 	return 0;
 }
 
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 8ac129a0..b94c440a 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -27,11 +27,11 @@
 #include <linux/if_link.h>
 
 #include "nm-dbus-interface.h"
-#include "nm-default.h"
-#include "NetworkManagerUtils.h"
-#include "nm-setting-vlan.h"
 #include "nm-core-types-internal.h"
 
+#include "nm-core-utils.h"
+#include "nm-setting-vlan.h"
+
 #define NM_TYPE_PLATFORM            (nm_platform_get_type ())
 #define NM_PLATFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
 #define NM_PLATFORM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PLATFORM, NMPlatformClass))
@@ -61,6 +61,7 @@ typedef struct _NMPlatform NMPlatform;
 #define NM_IN6_ADDR_GEN_MODE_EUI64             0    /* IN6_ADDR_GEN_MODE_EUI64 */
 #define NM_IN6_ADDR_GEN_MODE_NONE              1    /* IN6_ADDR_GEN_MODE_NONE */
 #define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY    2    /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */
+#define NM_IN6_ADDR_GEN_MODE_RANDOM            3    /* IN6_ADDR_GEN_MODE_RANDOM */
 
 #define NM_IFF_MULTI_QUEUE                     0x0100 /* IFF_MULTI_QUEUE */
 
@@ -118,7 +119,6 @@ struct _NMPlatformLink {
 	/* NMPlatform initializes this field with a static string. */
 	const char *driver;
 
-	gboolean initialized;
 	int master;
 
 	/* rtnl_link_get_link(), IFLA_LINK.
@@ -126,6 +126,11 @@ struct _NMPlatformLink {
 	 * this field be set to (negative) NM_PLATFORM_LINK_OTHER_NETNS. */
 	int parent;
 
+	/* IFF_* flags. Note that the flags in 'struct ifinfomsg' are declared as 'unsigned'. */
+	guint n_ifi_flags;
+
+	guint mtu;
+
 	/* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */
 	guint32 arptype;
 
@@ -146,15 +151,11 @@ struct _NMPlatformLink {
 	 * initialized with memset(0) has and unset value.*/
 	guint8 inet6_addr_gen_mode_inv;
 
-	/* IFF_* flags as u32. Note that ifi_flags in 'struct ifinfomsg' is declared as 'unsigned',
-	 * but libnl stores the flag internally as u32.  */
-	guint32 flags;
-
-	/* @connected is mostly identical to (@flags & IFF_UP). Except for bridge/bond masters,
+	/* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters,
 	 * where we coerce the link as disconnect if it has no slaves. */
-	gboolean connected;
+	bool connected:1;
 
-	guint mtu;
+	bool initialized:1;
 };
 
 typedef enum { /*< skip >*/
@@ -268,7 +269,7 @@ struct _NMPlatformIP6Address {
 	__NMPlatformIPAddress_COMMON;
 	struct in6_addr address;
 	struct in6_addr peer_address;
-	guint flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */
+	guint32 n_ifa_flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */
 };
 
 typedef union {
@@ -362,16 +363,16 @@ extern const NMPlatformVTableRoute nm_platform_vtable_route_v4;
 extern const NMPlatformVTableRoute nm_platform_vtable_route_v6;
 
 typedef struct {
+	in_addr_t local;
+	in_addr_t remote;
 	int parent_ifindex;
 	guint16 input_flags;
 	guint16 output_flags;
 	guint32 input_key;
 	guint32 output_key;
-	in_addr_t local;
-	in_addr_t remote;
 	guint8 ttl;
 	guint8 tos;
-	gboolean path_mtu_discovery;
+	bool path_mtu_discovery:1;
 } NMPlatformLnkGre;
 
 typedef struct {
@@ -380,42 +381,42 @@ typedef struct {
 } NMPlatformLnkInfiniband;
 
 typedef struct {
-	int parent_ifindex;
 	struct in6_addr local;
 	struct in6_addr remote;
+	int parent_ifindex;
 	guint8 ttl;
 	guint8 tclass;
 	guint8 encap_limit;
-	guint flow_label;
 	guint8 proto;
+	guint flow_label;
 } NMPlatformLnkIp6Tnl;
 
 typedef struct {
-	int parent_ifindex;
 	in_addr_t local;
 	in_addr_t remote;
+	int parent_ifindex;
 	guint8 ttl;
 	guint8 tos;
-	gboolean path_mtu_discovery;
+	bool path_mtu_discovery:1;
 } NMPlatformLnkIpIp;
 
 typedef struct {
 	guint mode;
-	gboolean no_promisc;
-	gboolean tap;
+	bool no_promisc:1;
+	bool tap:1;
 } NMPlatformLnkMacvlan;
 
 typedef NMPlatformLnkMacvlan NMPlatformLnkMacvtap;
 
 typedef struct {
-	int parent_ifindex;
 	in_addr_t local;
 	in_addr_t remote;
+	int parent_ifindex;
 	guint8 ttl;
 	guint8 tos;
-	gboolean path_mtu_discovery;
-	guint16 flags;
 	guint8 proto;
+	bool path_mtu_discovery:1;
+	guint16 flags;
 } NMPlatformLnkSit;
 
 typedef struct {
@@ -425,33 +426,33 @@ typedef struct {
 } NMPlatformLnkVlan;
 
 typedef struct {
-	int parent_ifindex;
-	guint32 id;
-	in_addr_t group;
-	in_addr_t local;
 	struct in6_addr group6;
 	struct in6_addr local6;
-	guint8 tos;
-	guint8 ttl;
-	gboolean learning;
+	in_addr_t group;
+	in_addr_t local;
+	int parent_ifindex;
+	guint32 id;
 	guint32 ageing;
 	guint32 limit;
 	guint16 dst_port;
 	guint16 src_port_min;
 	guint16 src_port_max;
-	gboolean proxy;
-	gboolean rsc;
-	gboolean l2miss;
-	gboolean l3miss;
+	guint8 tos;
+	guint8 ttl;
+	bool learning:1;
+	bool proxy:1;
+	bool rsc:1;
+	bool l2miss:1;
+	bool l3miss:1;
 } NMPlatformLnkVxlan;
 
 typedef struct {
 	gint64 owner;
 	gint64 group;
 	const char *mode;
-	gboolean no_pi;
-	gboolean vnet_hdr;
-	gboolean multi_queue;
+	bool no_pi:1;
+	bool vnet_hdr:1;
+	bool multi_queue:1;
 } NMPlatformTunProperties;
 
 /******************************************************************/
@@ -593,7 +594,7 @@ typedef struct {
 	                             struct in6_addr peer_address,
 	                             guint32 lifetime,
 	                             guint32 preferred_lft,
-	                             guint flags);
+	                             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);
@@ -666,7 +667,8 @@ _nm_platform_uint8_inv (guint8 scope)
 
 const char *nm_link_type_to_string (NMLinkType link_type);
 
-const char *nm_platform_error_to_string (NMPlatformError error);
+const char *_nm_platform_error_to_string (NMPlatformError error);
+#define nm_platform_error_to_string(error) NM_UTILS_LOOKUP_STR (_nm_platform_error_to_string, error)
 
 gboolean nm_platform_sysctl_set (NMPlatform *self, const char *path, const char *value);
 char *nm_platform_sysctl_get (NMPlatform *self, const char *path);
@@ -859,7 +861,7 @@ gboolean nm_platform_ip6_address_add (NMPlatform *self,
                                       struct in6_addr peer_address,
                                       guint32 lifetime,
                                       guint32 preferred_lft,
-                                      guint flags);
+                                      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_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 892fd9dd..b7b04490 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -18,16 +18,17 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
+
+#include "nmp-object.h"
 
 #include <unistd.h>
 
-#include "nm-default.h"
-#include "nmp-object.h"
-#include "nm-platform-utils.h"
-#include "NetworkManagerUtils.h"
 #include "nm-utils.h"
 
+#include "nm-core-utils.h"
+#include "nm-platform-utils.h"
+
 /*********************************************************************************************/
 
 #define _NMLOG_DOMAIN LOGD_PLATFORM
@@ -1256,7 +1257,7 @@ nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *m
 
 	/* if native IFF_LOWER_UP is down, link.connected must also be down
 	 * regardless of the slaves. */
-	if (!NM_FLAGS_HAS (master->link.flags, IFF_LOWER_UP))
+	if (!NM_FLAGS_HAS (master->link.n_ifi_flags, IFF_LOWER_UP))
 		return !!master->link.connected;
 
 	if (potential_slave && NMP_OBJECT_GET_TYPE (potential_slave) != NMP_OBJECT_TYPE_LINK)
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index ab1cc2fe..7758798f 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -21,15 +21,11 @@
 #ifndef __NMP_OBJECT_H__
 #define __NMP_OBJECT_H__
 
-#include "config.h"
-
-#include "nm-platform.h"
-#include "nm-multi-index.h"
-#include "nm-macros-internal.h"
-
 #include <netlink/netlink.h>
 #include <gudev/gudev.h>
 
+#include "nm-platform.h"
+#include "nm-multi-index.h"
 
 typedef enum { /*< skip >*/
 	NMP_OBJECT_TO_STRING_ID,
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c
index 5cc3114c..3af34be4 100644
--- a/src/platform/tests/monitor.c
+++ b/src/platform/tests/monitor.c
@@ -1,9 +1,28 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2015 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <stdlib.h>
 #include <syslog.h>
 
-#include "nm-default.h"
 #include "nm-linux-platform.h"
 
 #include "nm-test-utils.h"
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
index 566bb479..3b52a7be 100644
--- a/src/platform/tests/test-address.c
+++ b/src/platform/tests/test-address.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2015 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include "test-common.h"
 
@@ -255,7 +275,8 @@ test_ip4_address_peer (void)
 	/* Add/delete notification */
 	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer, lifetime, preferred, NULL);
 	accept_signal (address_added);
-	g_assert ((a = 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_peer);
+	g_assert (a);
 	g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2));
 
 	nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
@@ -263,7 +284,8 @@ test_ip4_address_peer (void)
 	nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr_peer2, lifetime, preferred, NULL);
 	accept_signal (address_added);
 	g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer));
-	g_assert ((a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2)));
+	a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr_peer2);
+	g_assert (a);
 
 	nmtstp_ip_address_assert_lifetime ((NMPlatformIPAddress *) a, -1, lifetime, preferred);
 
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index 9e624a02..6ad24478 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include "test-common.h"
 
@@ -25,7 +45,7 @@ test_cleanup_internal (void)
 	int preferred = NM_PLATFORM_LIFETIME_PERMANENT;
 	int metric = 20;
 	int mss = 1000;
-	guint flags = 0;
+	guint32 flags = 0;
 
 	inet_pton (AF_INET, "192.0.2.1", &addr4);
 	inet_pton (AF_INET, "192.0.3.0", &network4);
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index 09a57f87..268a5c92 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <sys/mount.h>
 #include <sched.h>
@@ -39,7 +59,7 @@ add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCall
 	data->ifindex = ifindex;
 	data->ifname = ifname;
 
-	g_assert (data->handler_id >= 0);
+	g_assert (data->handler_id > 0);
 
 	return data;
 }
@@ -544,7 +564,7 @@ _ip_address_add (gboolean external_command,
                  guint32 lifetime,
                  guint32 preferred,
                  const char *label,
-                 guint flags)
+                 guint32 flags)
 {
 	gint64 end_time;
 
@@ -1008,7 +1028,7 @@ nmtstp_ip6_address_add (gboolean external_command,
                         struct in6_addr peer_address,
                         guint32 lifetime,
                         guint32 preferred,
-                        guint flags)
+                        guint32 flags)
 {
 	_ip_address_add (external_command,
 	                 FALSE,
@@ -1262,7 +1282,7 @@ nmtstp_link_set_updown (gboolean external_command,
 		plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex);
 		g_assert (plink);
 
-		if (NM_FLAGS_HAS (plink->flags, IFF_UP) == !!up)
+		if (NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP) == !!up)
 			break;
 
 		/* for internal command, we expect not to reach this line.*/
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 8b496262..3fa5ad50 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -1,4 +1,24 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <sched.h>
 
@@ -290,9 +310,17 @@ test_slave (int master, int type, SignalData *master_changed)
 	ensure_no_signal (link_removed);
 	g_assert (nm_platform_link_release (NM_PLATFORM_GET, master, ifindex));
 	g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, 0);
-	accept_signals (link_added, 0, 1);
-	accept_signals (link_changed, 1, 3);
-	accept_signals (link_removed, 0, 1);
+	if (link_changed->received_count > 0) {
+		accept_signals (link_added, 0, 1);
+		accept_signals (link_changed, 1, 3);
+		accept_signals (link_removed, 0, 1);
+	} else {
+		/* Due to https://bugzilla.redhat.com/show_bug.cgi?id=1285719 , kernel might send a
+		 * wrong RTM_DELLINK message so that we instead see an removed+added signal. */
+		accept_signal (link_added);
+		ensure_no_signal (link_changed);
+		accept_signal (link_removed);
+	}
 	accept_signals (master_changed, 1, 2);
 
 	ensure_no_signal (master_changed);
diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c
index eba2383b..3b44abb8 100644
--- a/src/platform/tests/test-nmp-object.c
+++ b/src/platform/tests/test-nmp-object.c
@@ -18,10 +18,10 @@
  * Copyright (C) 2015 Red Hat, Inc.
  */
 
-#include "nmp-object.h"
-
 #include "nm-default.h"
 
+#include "nmp-object.h"
+
 #include "nm-test-utils.h"
 
 struct {
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 60a0c15c..f5fa024b 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -1,10 +1,31 @@
-#include "config.h"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager audit support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
 
 #include <linux/rtnetlink.h>
 
+#include "nm-core-utils.h"
 #include "test-common.h"
+
 #include "nm-test-utils.h"
-#include "NetworkManagerUtils.h"
 
 #define DEVICE_NAME "nm-test-device"
 
diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c
index e05104f3..79f217a8 100644
--- a/src/platform/wifi/wifi-utils-nl80211.c
+++ b/src/platform/wifi/wifi-utils-nl80211.c
@@ -20,7 +20,7 @@
  * Copyright (C) 2011 Intel Corporation. All rights reserved.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <string.h>
@@ -32,7 +32,6 @@
 #include <netlink/msg.h>
 #include <linux/nl80211.h>
 
-#include "nm-default.h"
 #include "wifi-utils-private.h"
 #include "wifi-utils-nl80211.h"
 #include "nm-platform.h"
diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c
index 96bcf53d..029601e4 100644
--- a/src/platform/wifi/wifi-utils-wext.c
+++ b/src/platform/wifi/wifi-utils-wext.c
@@ -19,7 +19,7 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <errno.h>
 #include <string.h>
@@ -28,8 +28,6 @@
 #include <unistd.h>
 #include <math.h>
 
-
-#include "nm-default.h"
 #include "wifi-utils-private.h"
 #include "wifi-utils-wext.h"
 #include "nm-utils.h"
@@ -315,7 +313,7 @@ wext_qual_to_percent (const struct iw_quality *qual,
 			noise = qual->noise - 0x100;
 		else if ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID))
 			noise = max_qual->noise - 0x100;
-		noise = CLAMP (noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM);
+		noise = CLAMP (noise, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM - 1);
 
 		/* A sort of signal-to-noise ratio calculation */
 		level_percent = (int) (100 - 70 * (((double)max_level - (double)level) /
diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c
index 5f2f61b0..38e5a054 100644
--- a/src/platform/wifi/wifi-utils.c
+++ b/src/platform/wifi/wifi-utils.c
@@ -19,13 +19,12 @@
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
-#include "config.h"
+#include "nm-default.h"
 
 #include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
 
-#include "nm-default.h"
 #include "wifi-utils.h"
 #include "wifi-utils-private.h"
 #include "wifi-utils-nl80211.h"