about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in9
-rw-r--r--src/NetworkManagerUtils.c88
-rw-r--r--src/NetworkManagerUtils.h2
-rw-r--r--src/devices/adsl/Makefile.am1
-rw-r--r--src/devices/adsl/Makefile.in2
-rw-r--r--src/devices/bluetooth/Makefile.am2
-rw-r--r--src/devices/bluetooth/Makefile.in9
-rw-r--r--src/devices/bluetooth/nm-bluez-device.c4
-rw-r--r--src/devices/nm-device-bond.c14
-rw-r--r--src/devices/nm-device-bridge.c4
-rw-r--r--src/devices/nm-device-ethernet.c17
-rw-r--r--src/devices/nm-device-infiniband.c4
-rw-r--r--src/devices/nm-device-vlan.c44
-rw-r--r--src/devices/nm-device.c291
-rw-r--r--src/devices/nm-device.h1
-rw-r--r--src/devices/team/Makefile.am1
-rw-r--r--src/devices/team/Makefile.in5
-rw-r--r--src/devices/team/nm-device-team.c4
-rw-r--r--src/devices/wifi/Makefile.am1
-rw-r--r--src/devices/wifi/Makefile.in2
-rw-r--r--src/devices/wifi/nm-device-wifi-glue.h12
-rw-r--r--src/devices/wifi/nm-device-wifi.c62
-rw-r--r--src/devices/wifi/nm-wifi-ap-utils.c4
-rw-r--r--src/devices/wifi/nm-wifi-ap.c5
-rw-r--r--src/devices/wifi/tests/Makefile.am1
-rw-r--r--src/devices/wifi/tests/Makefile.in2
-rw-r--r--src/devices/wifi/tests/test-wifi-ap-utils.c137
-rw-r--r--src/devices/wimax/Makefile.am1
-rw-r--r--src/devices/wimax/Makefile.in2
-rw-r--r--src/devices/wwan/Makefile.am4
-rw-r--r--src/devices/wwan/Makefile.in5
-rw-r--r--src/devices/wwan/nm-modem-broadband.c17
-rw-r--r--src/dhcp-manager/Makefile.in1
-rw-r--r--src/dhcp-manager/nm-dhcp-systemd.c13
-rw-r--r--src/dhcp-manager/systemd-dhcp/nm-sd-adapt.c73
-rw-r--r--src/dhcp-manager/systemd-dhcp/nm-sd-adapt.h15
-rw-r--r--src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-client.c10
-rw-r--r--src/dhcp-manager/systemd-dhcp/src/shared/macro.h9
-rw-r--r--src/dhcp-manager/tests/Makefile.am1
-rw-r--r--src/dhcp-manager/tests/Makefile.in2
-rw-r--r--src/dnsmasq-manager/nm-dnsmasq-manager.c1
-rw-r--r--src/dnsmasq-manager/tests/Makefile.am1
-rw-r--r--src/dnsmasq-manager/tests/Makefile.in2
-rw-r--r--src/main.c35
-rw-r--r--src/nm-agent-manager-glue.h12
-rw-r--r--src/nm-config-data.c27
-rw-r--r--src/nm-config-data.h5
-rw-r--r--src/nm-config.c16
-rw-r--r--src/nm-config.h3
-rw-r--r--src/nm-default-route-manager.c94
-rw-r--r--src/nm-dispatcher.c4
-rw-r--r--src/nm-ip6-config.c6
-rw-r--r--src/nm-logging.c5
-rw-r--r--src/nm-logging.h48
-rw-r--r--src/nm-manager-glue.h42
-rw-r--r--src/nm-manager.c43
-rw-r--r--src/nm-policy.c10
-rw-r--r--src/nm-ppp-manager-glue.h12
-rw-r--r--src/nm-route-manager.c30
-rw-r--r--src/nm-settings-connection-glue.h12
-rw-r--r--src/nm-settings-glue.h18
-rw-r--r--src/org.freedesktop.NetworkManager.conf2
-rw-r--r--src/platform/Makefile.in1
-rw-r--r--src/platform/nm-linux-platform.c199
-rw-r--r--src/platform/nm-platform-utils.c29
-rw-r--r--src/platform/nm-platform.c6
-rw-r--r--src/platform/nmp-object.c6
-rw-r--r--src/platform/tests/Makefile.am1
-rw-r--r--src/platform/tests/Makefile.in8
-rw-r--r--src/platform/tests/test-link.c47
-rw-r--r--src/ppp-manager/Makefile.am1
-rw-r--r--src/ppp-manager/Makefile.in2
-rw-r--r--src/rdisc/Makefile.in1
-rw-r--r--src/rdisc/tests/Makefile.am1
-rw-r--r--src/rdisc/tests/Makefile.in2
-rw-r--r--src/settings/nm-agent-manager.c37
-rw-r--r--src/settings/plugins/Makefile.in1
-rw-r--r--src/settings/plugins/example/Makefile.am1
-rw-r--r--src/settings/plugins/example/Makefile.in2
-rw-r--r--src/settings/plugins/ibft/Makefile.am1
-rw-r--r--src/settings/plugins/ibft/Makefile.in2
-rw-r--r--src/settings/plugins/ibft/tests/Makefile.am1
-rw-r--r--src/settings/plugins/ibft/tests/Makefile.in2
-rw-r--r--src/settings/plugins/ifcfg-rh/Makefile.am1
-rw-r--r--src/settings/plugins/ifcfg-rh/Makefile.in2
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c136
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.c10
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/Makefile.am1
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/Makefile.in2
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am6
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in7
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-17
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore8
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-116
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore1
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c173
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c30
-rw-r--r--src/settings/plugins/ifcfg-suse/Makefile.am1
-rw-r--r--src/settings/plugins/ifcfg-suse/Makefile.in2
-rw-r--r--src/settings/plugins/ifnet/Makefile.am1
-rw-r--r--src/settings/plugins/ifnet/Makefile.in2
-rw-r--r--src/settings/plugins/ifnet/tests/Makefile.am1
-rw-r--r--src/settings/plugins/ifnet/tests/Makefile.in2
-rw-r--r--src/settings/plugins/ifupdown/Makefile.am1
-rw-r--r--src/settings/plugins/ifupdown/Makefile.in2
-rw-r--r--src/settings/plugins/ifupdown/tests/Makefile.am1
-rw-r--r--src/settings/plugins/ifupdown/tests/Makefile.in2
-rw-r--r--src/settings/plugins/keyfile/Makefile.am1
-rw-r--r--src/settings/plugins/keyfile/Makefile.in2
-rw-r--r--src/settings/plugins/keyfile/tests/Makefile.am1
-rw-r--r--src/settings/plugins/keyfile/tests/Makefile.in2
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Makefile.am1
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Makefile.in2
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags15
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile.c30
-rw-r--r--src/supplicant-manager/nm-supplicant-config.c22
-rw-r--r--src/supplicant-manager/nm-supplicant-config.h4
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c64
-rw-r--r--src/supplicant-manager/tests/Makefile.am4
-rw-r--r--src/supplicant-manager/tests/Makefile.in201
-rw-r--r--src/supplicant-manager/tests/certs/Makefile.am6
-rw-r--r--src/supplicant-manager/tests/certs/Makefile.in596
-rw-r--r--src/supplicant-manager/tests/certs/test-ca-cert.pem27
-rw-r--r--src/supplicant-manager/tests/certs/test-cert.p12bin0 -> 4092 bytes
-rw-r--r--src/supplicant-manager/tests/test-supplicant-config.c143
-rw-r--r--src/tests/Makefile.am1
-rw-r--r--src/tests/Makefile.in2
-rw-r--r--src/tests/config/Makefile.am1
-rw-r--r--src/tests/config/Makefile.in2
-rw-r--r--src/tests/config/test-config.c87
-rw-r--r--src/tests/test-general-with-expect.c25
-rw-r--r--src/tests/test-general.c78
-rw-r--r--src/vpn-manager/nm-vpn-connection.c12
134 files changed, 2710 insertions, 696 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7339058c..e8279e77 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,6 +39,7 @@ endif
 
 AM_CPPFLAGS =				\
 	-I$(top_srcdir)/include		\
+	-I$(top_builddir)/include		\
 	-I$(top_srcdir)/libnm-core	\
 	-I$(top_builddir)/libnm-core	\
 	-I$(top_srcdir)/callouts	\
@@ -117,6 +118,7 @@ libsystemd_dhcp_la_SOURCES = \
 
 libsystemd_dhcp_la_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include		\
 	$(SYSTEMD_DHCP_CFLAGS) \
 	$(GLIB_CFLAGS)
 
diff --git a/src/Makefile.in b/src/Makefile.in
index 2b999969..34ba856c 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -654,6 +654,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -800,9 +801,10 @@ SUBDIRS = . devices/adsl dhcp-manager ppp-manager settings/plugins \
 
 # add each subdirectory that contains a libNM source file. $(sort) is being used
 # primarily for its side effect of removing duplicates.
-AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libnm-core \
-	-I$(top_builddir)/libnm-core -I$(top_srcdir)/callouts \
-	-DPREFIX=\"$(prefix)\" -DG_LOG_DOMAIN=\""NetworkManager"\" \
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include \
+	-I$(top_srcdir)/libnm-core -I$(top_builddir)/libnm-core \
+	-I$(top_srcdir)/callouts -DPREFIX=\"$(prefix)\" \
+	-DG_LOG_DOMAIN=\""NetworkManager"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(foreach \
 	d,$(sort $(dir \
@@ -888,6 +890,7 @@ libsystemd_dhcp_la_SOURCES = \
 
 libsystemd_dhcp_la_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include		\
 	$(SYSTEMD_DHCP_CFLAGS) \
 	$(GLIB_CFLAGS)
 
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 63741dc3..15e03276 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -1878,6 +1878,9 @@ remove_from_hash (GHashTable *s_hash,
                   const char *s_name,
                   const char *p_name)
 {
+	if (!p_hash)
+		return;
+
 	g_hash_table_remove (p_hash, p_name);
 	if (g_hash_table_size (p_hash) == 0)
 		g_hash_table_remove (s_hash, s_name);
@@ -2033,6 +2036,85 @@ check_connection_mac_address (NMConnection *orig,
 	return FALSE;
 }
 
+static gboolean
+check_connection_cloned_mac_address (NMConnection *orig,
+                              NMConnection *candidate,
+                              GHashTable *settings)
+{
+	GHashTable *props;
+	const char *orig_mac = NULL, *cand_mac = NULL;
+	NMSettingWired *s_wired_orig, *s_wired_cand;
+
+	props = check_property_in_hash (settings,
+	                                NM_SETTING_WIRED_SETTING_NAME,
+	                                NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
+	if (!props)
+		return TRUE;
+
+	/* If one of the MAC addresses is NULL, we accept that connection */
+	s_wired_orig = nm_connection_get_setting_wired (orig);
+	if (s_wired_orig)
+		orig_mac = nm_setting_wired_get_cloned_mac_address (s_wired_orig);
+
+	s_wired_cand = nm_connection_get_setting_wired (candidate);
+	if (s_wired_cand)
+		cand_mac = nm_setting_wired_get_cloned_mac_address (s_wired_cand);
+
+	if (!orig_mac || !cand_mac) {
+		remove_from_hash (settings, props,
+		                  NM_SETTING_WIRED_SETTING_NAME,
+		                  NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+check_connection_s390_props (NMConnection *orig,
+                             NMConnection *candidate,
+                             GHashTable *settings)
+{
+	GHashTable *props1, *props2, *props3;
+	NMSettingWired *s_wired_orig, *s_wired_cand;
+
+	props1 = check_property_in_hash (settings,
+	                                 NM_SETTING_WIRED_SETTING_NAME,
+	                                 NM_SETTING_WIRED_S390_SUBCHANNELS);
+	props2 = check_property_in_hash (settings,
+	                                 NM_SETTING_WIRED_SETTING_NAME,
+	                                 NM_SETTING_WIRED_S390_NETTYPE);
+	props3 = check_property_in_hash (settings,
+	                                 NM_SETTING_WIRED_SETTING_NAME,
+	                                 NM_SETTING_WIRED_S390_OPTIONS);
+	if (!props1 && !props2 && !props3)
+		return TRUE;
+
+	/* If the generated connection did not contain wired setting,
+	 * allow it to match to a connection with a wired setting,
+	 * but default (empty) s390-* properties */
+	s_wired_orig = nm_connection_get_setting_wired (orig);
+	s_wired_cand = nm_connection_get_setting_wired (candidate);
+	if (!s_wired_orig && s_wired_cand) {
+		const char * const *subchans = nm_setting_wired_get_s390_subchannels (s_wired_cand);
+		const char *nettype = nm_setting_wired_get_s390_nettype (s_wired_cand);
+		guint32 num_options = nm_setting_wired_get_num_s390_options (s_wired_cand);
+
+		if ((!subchans || !*subchans) && !nettype && num_options == 0) {
+			remove_from_hash (settings, props1,
+			                  NM_SETTING_WIRED_SETTING_NAME,
+			                  NM_SETTING_WIRED_S390_SUBCHANNELS);
+			remove_from_hash (settings, props2,
+			                  NM_SETTING_WIRED_SETTING_NAME,
+			                  NM_SETTING_WIRED_S390_NETTYPE);
+			remove_from_hash (settings, props3,
+			                  NM_SETTING_WIRED_SETTING_NAME,
+			                  NM_SETTING_WIRED_S390_OPTIONS);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
 static NMConnection *
 check_possible_match (NMConnection *orig,
                       NMConnection *candidate,
@@ -2053,6 +2135,12 @@ check_possible_match (NMConnection *orig,
 	if (!check_connection_mac_address (orig, candidate, settings))
 		return NULL;
 
+	if (!check_connection_cloned_mac_address (orig, candidate, settings))
+		return NULL;
+
+	if (!check_connection_s390_props (orig, candidate, settings))
+		return NULL;
+
 	if (g_hash_table_size (settings) == 0)
 		return candidate;
 	else
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index 70f62d47..1b7d924a 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -188,7 +188,7 @@ struct _NMUtilsIPv6IfaceId {
 	};
 };
 
-#define NM_UTILS_IPV6_IFACE_ID_INIT { .id = 0 }
+#define NM_UTILS_IPV6_IFACE_ID_INIT { { .id = 0 } }
 
 gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
                                                  const guint8 *hwaddr,
diff --git a/src/devices/adsl/Makefile.am b/src/devices/adsl/Makefile.am
index 07a8f9ee..d7457c88 100644
--- a/src/devices/adsl/Makefile.am
+++ b/src/devices/adsl/Makefile.am
@@ -8,6 +8,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/devices \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/include \
+	-I$(top_builddir)/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-adsl"\" \
diff --git a/src/devices/adsl/Makefile.in b/src/devices/adsl/Makefile.in
index 6f7fe174..b6e944f8 100644
--- a/src/devices/adsl/Makefile.in
+++ b/src/devices/adsl/Makefile.in
@@ -341,6 +341,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -487,6 +488,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/devices \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/include \
+	-I$(top_builddir)/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-adsl"\" \
diff --git a/src/devices/bluetooth/Makefile.am b/src/devices/bluetooth/Makefile.am
index 8ab561ac..e6e378f0 100644
--- a/src/devices/bluetooth/Makefile.am
+++ b/src/devices/bluetooth/Makefile.am
@@ -10,11 +10,13 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/src/devices/wwan \
 	-I${top_srcdir}/include \
+	-I$(top_builddir)/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-bluetooth"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS)
 
 GLIB_GENERATED = nm-bt-enum-types.h nm-bt-enum-types.c
diff --git a/src/devices/bluetooth/Makefile.in b/src/devices/bluetooth/Makefile.in
index 6233a751..bdc3b5cb 100644
--- a/src/devices/bluetooth/Makefile.in
+++ b/src/devices/bluetooth/Makefile.in
@@ -361,6 +361,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -504,12 +505,12 @@ with_valgrind = @with_valgrind@
 AM_CPPFLAGS = -I${top_srcdir}/src -I${top_builddir}/src \
 	-I${top_srcdir}/src/devices -I${top_srcdir}/src/settings \
 	-I${top_srcdir}/src/platform -I${top_srcdir}/src/devices/wwan \
-	-I${top_srcdir}/include -I${top_builddir}/libnm-core \
-	-I${top_srcdir}/libnm-core \
+	-I${top_srcdir}/include -I$(top_builddir)/include \
+	-I${top_builddir}/libnm-core -I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-bluetooth"\" \
 	-DNETWORKMANAGER_COMPILATION \
-	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(DBUS_CFLAGS) \
-	$(am__append_1)
+	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS) $(am__append_1)
 GLIB_GENERATED = nm-bt-enum-types.h nm-bt-enum-types.c
 GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
 GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
index d5426052..89ad8270 100644
--- a/src/devices/bluetooth/nm-bluez-device.c
+++ b/src/devices/bluetooth/nm-bluez-device.c
@@ -603,8 +603,10 @@ nm_bluez_device_connect_finish (NMBluezDevice *self,
 		return NULL;
 
 	device = (const char *) g_simple_async_result_get_op_res_gpointer (simple);
-	if (device && priv->bluez_version == 5)
+	if (device && priv->bluez_version == 5) {
 		priv->connected = TRUE;
+		g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_CONNECTED);
+	}
 
 	return device;
 }
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 7f139424..afcba3b3 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -572,6 +572,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 {
 	const char *iface = nm_connection_get_interface_name (connection);
 	NMPlatformError plerr;
+	const NMPlatformLink *plink;
 
 	g_assert (iface);
 
@@ -584,14 +585,15 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 		             nm_platform_error_to_string (plerr));
 		return NULL;
 	}
+	plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
 
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
-		                              NM_DEVICE_IFACE, iface,
-		                              NM_DEVICE_DRIVER, "bonding",
-		                              NM_DEVICE_TYPE_DESC, "Bond",
-		                              NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
-		                              NM_DEVICE_IS_MASTER, TRUE,
-		                              NULL);
+	                                  NM_DEVICE_PLATFORM_DEVICE, plink,
+	                                  NM_DEVICE_DRIVER, "bonding",
+	                                  NM_DEVICE_TYPE_DESC, "Bond",
+	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
+	                                  NM_DEVICE_IS_MASTER, TRUE,
+	                                  NULL);
 }
 
 NM_DEVICE_FACTORY_DEFINE_INTERNAL (BOND, Bond, bond,
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index e1cafd60..d6435530 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -498,6 +498,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 	const char *mac_address_str;
 	guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX];
 	NMPlatformError plerr;
+	const NMPlatformLink *plink;
 
 	g_assert (iface);
 
@@ -523,9 +524,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 		             nm_platform_error_to_string (plerr));
 		return NULL;
 	}
+	plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
 
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
-	                                  NM_DEVICE_IFACE, iface,
+	                                  NM_DEVICE_PLATFORM_DEVICE, plink,
 	                                  NM_DEVICE_DRIVER, "bridge",
 	                                  NM_DEVICE_TYPE_DESC, "Bridge",
 	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index beb86e11..8a023843 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -560,15 +560,18 @@ build_supplicant_config (NMDeviceEthernet *self)
 	NMSupplicantConfig *config = NULL;
 	NMSetting8021x *security;
 	NMConnection *connection;
+	guint32 mtu;
 
 	connection = nm_device_get_connection (NM_DEVICE (self));
 	g_assert (connection);
 	con_uuid = nm_connection_get_uuid (connection);
+	mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET,
+	                                nm_device_get_ifindex (NM_DEVICE (self)));
 
 	config = nm_supplicant_config_new ();
 
 	security = nm_connection_get_setting_802_1x (connection);
-	if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, TRUE)) {
+	if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, mtu, TRUE)) {
 		_LOGW (LOGD_DEVICE, "Couldn't add 802.1X security setting to supplicant config.");
 		g_object_unref (config);
 		config = NULL;
@@ -1195,15 +1198,22 @@ wake_on_lan_enable (NMDevice *device)
 	value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
 	                                               "ethernet.wake-on-lan",
 	                                               device);
+
 	if (value) {
 		wol = _nm_utils_ascii_str_to_int64 (value, 10,
 		                                    NM_SETTING_WIRED_WAKE_ON_LAN_NONE,
-		                                    NM_SETTING_WIRED_WAKE_ON_LAN_ALL,
+		                                    G_MAXINT32,
 		                                    NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT);
+
+		if (   NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS)
+		    && !nm_utils_is_power_of_two (wol)) {
+			nm_log_dbg (LOGD_ETHER, "invalid default value %u for wake-on-lan", (guint) wol);
+			wol = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT;
+		}
 		if (wol != NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)
 			goto found;
 	}
-	wol = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
+	wol = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE;
 found:
 	return nmp_utils_ethtool_set_wake_on_lan (nm_device_get_iface (device), wol, password);
 }
@@ -1474,6 +1484,7 @@ new_default_connection (NMDevice *self)
 	              NM_SETTING_CONNECTION_ID, defname,
 	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
 	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+	              NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN,
 	              NM_SETTING_CONNECTION_UUID, uuid,
 	              NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL),
 	              NULL);
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
index 2d519f61..c1571fd9 100644
--- a/src/devices/nm-device-infiniband.c
+++ b/src/devices/nm-device-infiniband.c
@@ -327,6 +327,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 	int p_key, parent_ifindex;
 	const char *iface;
 	NMPlatformError plerr;
+	const NMPlatformLink *plink;
 
 	if (!NM_IS_DEVICE_INFINIBAND (parent)) {
 		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
@@ -352,9 +353,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 		             nm_platform_error_to_string (plerr));
 		return NULL;
 	}
+	plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
 
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND,
-	                                  NM_DEVICE_IFACE, iface,
+	                                  NM_DEVICE_PLATFORM_DEVICE, plink,
 	                                  NM_DEVICE_DRIVER, nm_device_get_driver (parent),
 	                                  NM_DEVICE_TYPE_DESC, "InfiniBand",
 	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND,
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index e523e6bb..b330397f 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -56,6 +56,7 @@ typedef struct {
 
 	NMDevice *parent;
 	guint parent_state_id;
+	guint parent_hwaddr_id;
 	int vlan_id;
 } NMDeviceVlanPrivate;
 
@@ -88,6 +89,36 @@ parent_state_changed (NMDevice *parent,
 }
 
 static void
+parent_hwaddr_changed (NMDevice *parent,
+                       GParamSpec *pspec,
+                       gpointer user_data)
+{
+	NMDeviceVlan *self = NM_DEVICE_VLAN (user_data);
+	NMConnection *connection;
+	NMSettingWired *s_wired;
+	const char *cloned_mac = NULL;
+
+	/* Never touch assumed devices */
+	if (nm_device_uses_assumed_connection (self))
+		return;
+
+	connection = nm_device_get_connection (self);
+	if (!connection)
+		return;
+
+	/* Update the VLAN MAC only if configuration does not specify one */
+	s_wired = nm_connection_get_setting_wired (connection);
+	if (s_wired)
+		cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
+
+	if (!cloned_mac) {
+		_LOGD (LOGD_VLAN, "parent hardware address changed");
+		nm_device_set_hw_addr (self, nm_device_get_hw_address (parent),
+		                       "set", LOGD_VLAN);
+	}
+}
+
+static void
 nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean construct)
 {
 	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
@@ -96,10 +127,8 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr
 	if (parent == priv->parent)
 		return;
 
-	if (priv->parent_state_id) {
-		g_signal_handler_disconnect (priv->parent, priv->parent_state_id);
-		priv->parent_state_id = 0;
-	}
+	nm_clear_g_signal_handler (priv->parent, &priv->parent_state_id);
+	nm_clear_g_signal_handler (priv->parent, &priv->parent_hwaddr_id);
 	g_clear_object (&priv->parent);
 
 	if (parent) {
@@ -109,6 +138,9 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr
 		                                          G_CALLBACK (parent_state_changed),
 		                                          device);
 
+		priv->parent_hwaddr_id = g_signal_connect (priv->parent, "notify::" NM_DEVICE_HW_ADDRESS,
+		                                           G_CALLBACK (parent_hwaddr_changed), device);
+
 		/* Set parent-dependent unmanaged flag */
 		if (construct) {
 			nm_device_set_initial_unmanaged_flag (device,
@@ -666,6 +698,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 	NMSettingVlan *s_vlan;
 	gs_free char *iface = NULL;
 	NMPlatformError plerr;
+	const NMPlatformLink *plink;
 
 	if (!NM_IS_DEVICE (parent)) {
 		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
@@ -696,9 +729,10 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
 		             nm_platform_error_to_string (plerr));
 		return NULL;
 	}
+	plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
 
 	device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN,
-	                                    NM_DEVICE_IFACE, iface,
+	                                    NM_DEVICE_PLATFORM_DEVICE, plink,
 	                                    NM_DEVICE_VLAN_INT_PARENT_DEVICE, parent,
 	                                    NM_DEVICE_DRIVER, "8021q",
 	                                    NM_DEVICE_TYPE_DESC, "VLAN",
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 58895821..9b69d5ab 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -95,6 +95,7 @@ enum {
 	REMOVED,
 	RECHECK_AUTO_ACTIVATE,
 	RECHECK_ASSUME,
+	LINK_INITIALIZED,
 	LAST_SIGNAL,
 };
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -342,6 +343,7 @@ typedef struct {
 	/* master interface for bridge/bond/team slave */
 	NMDevice *      master;
 	gboolean        enslaved;
+	gboolean        master_ready_handled;
 	guint           master_ready_id;
 
 	/* slave management */
@@ -1142,8 +1144,9 @@ nm_device_finish_init (NMDevice *self)
 
 	/* Do not manage externally created software devices until they are IFF_UP */
 	if (   NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)
-	    && !nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex)
-	    && priv->ifindex > 0)
+	    && priv->ifindex > 0
+	    && (   !priv->up
+	        || !priv->platform_link_initialized))
 		nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE);
 
 	if (priv->master)
@@ -1158,8 +1161,8 @@ nm_device_finish_init (NMDevice *self)
 			 * Currently it can happen that NM deletes 127.0.0.1 address. */
 			nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_DEFAULT, TRUE);
 		} else if (priv->platform_link_initialized || (priv->is_nm_owned && nm_device_is_software (self))) {
-			nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged);
-			nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_DEFAULT, platform_unmanaged);
+			if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged))
+				nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_DEFAULT, platform_unmanaged);
 		} else {
 			/* Hardware and externally-created software links stay unmanaged
 			 * until they are fully initialized by the platform. NM created
@@ -1322,9 +1325,7 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier)
 		link_disconnect_action_cancel (self);
 		klass->carrier_changed (self, TRUE);
 
-		if (priv->carrier_wait_id) {
-			g_source_remove (priv->carrier_wait_id);
-			priv->carrier_wait_id = 0;
+		if (nm_clear_g_source (&priv->carrier_wait_id)) {
 			nm_device_remove_pending_action (self, "carrier wait", TRUE);
 			_carrier_wait_check_queued_act_request (self);
 		}
@@ -1373,6 +1374,8 @@ device_link_changed (NMDevice *self)
 	NMPlatformLink info;
 	const NMPlatformLink *pllink;
 	int ifindex;
+	gboolean emit_link_initialized = FALSE;
+	gboolean was_up;
 
 	priv->device_link_changed_id = 0;
 
@@ -1448,8 +1451,29 @@ device_link_changed (NMDevice *self)
 	if (ip_ifname_changed)
 		update_dynamic_ip_setup (self);
 
-	if (priv->up != NM_FLAGS_HAS (info.flags, IFF_UP)) {
-		priv->up = NM_FLAGS_HAS (info.flags, IFF_UP);
+	if (priv->ifindex > 0 && !priv->platform_link_initialized && info.initialized) {
+		priv->platform_link_initialized = TRUE;
+
+		if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged)) {
+			nm_device_set_unmanaged (self,
+			                         NM_UNMANAGED_DEFAULT,
+			                         platform_unmanaged,
+			                         NM_DEVICE_STATE_REASON_USER_REQUESTED);
+		}
+
+		nm_device_set_unmanaged (self,
+		                         NM_UNMANAGED_PLATFORM_INIT,
+		                         FALSE,
+		                         NM_DEVICE_STATE_REASON_NOW_MANAGED);
+
+		emit_link_initialized = TRUE;
+	}
+
+	was_up = priv->up;
+	priv->up = NM_FLAGS_HAS (info.flags, IFF_UP);
+
+	if (   priv->platform_link_initialized
+	    && (emit_link_initialized || priv->up != was_up)) {
 
 		/* Manage externally-created software interfaces only when they are IFF_UP */
 		g_assert (priv->ifindex > 0);
@@ -1491,21 +1515,8 @@ device_link_changed (NMDevice *self)
 		}
 	}
 
-	if (priv->ifindex > 0 && !priv->platform_link_initialized && info.initialized) {
-		priv->platform_link_initialized = TRUE;
-
-		if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged)) {
-			nm_device_set_unmanaged (self,
-			                         NM_UNMANAGED_DEFAULT,
-			                         platform_unmanaged,
-			                         NM_DEVICE_STATE_REASON_USER_REQUESTED);
-		}
-
-		nm_device_set_unmanaged (self,
-		                         NM_UNMANAGED_PLATFORM_INIT,
-		                         FALSE,
-		                         NM_DEVICE_STATE_REASON_NOW_MANAGED);
-	}
+	if (emit_link_initialized)
+		g_signal_emit (self, signals[LINK_INITIALIZED], 0);
 
 	return G_SOURCE_REMOVE;
 }
@@ -1894,9 +1905,10 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success)
 	if (activating) {
 		priv->ip4_state = IP_DONE;
 		priv->ip6_state = IP_DONE;
-		nm_device_queue_state (self,
-		                       success ? NM_DEVICE_STATE_SECONDARIES : NM_DEVICE_STATE_FAILED,
-		                       NM_DEVICE_STATE_REASON_NONE);
+		if (success)
+			nm_device_queue_state (self, NM_DEVICE_STATE_SECONDARIES, NM_DEVICE_STATE_REASON_NONE);
+		else
+			nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
 	} else
 		nm_device_queue_recheck_assume (self);
 }
@@ -2613,19 +2625,23 @@ activation_source_schedule (NMDevice *self, GSourceFunc func, int family)
 		act_source_func = &priv->act_source_func;
 	}
 
-	if (*act_source_id)
-		_LOGE (LOGD_DEVICE, "activation stage already scheduled");
-
-	/* Don't bother rescheduling the same function that's about to
-	 * run anyway.  Fixes issues with crappy wireless drivers sending
-	 * streams of associate events before NM has had a chance to process
-	 * the first one.
-	 */
-	if (!*act_source_id || (*act_source_func != func)) {
-		activation_source_clear (self, TRUE, family);
-		*act_source_id = g_idle_add (func, self);
-		*act_source_func = func;
+	if (*act_source_id) {
+		if (*act_source_func == func) {
+			/* Don't bother rescheduling the same function that's about to
+			 * run anyway.  Fixes issues with crappy wireless drivers sending
+			 * streams of associate events before NM has had a chance to process
+			 * the first one.
+			 */
+			_LOGD (LOGD_DEVICE, "activation stage already scheduled");
+			return;
+		} else {
+			_LOGW (LOGD_DEVICE, "a different activation stage already scheduled");
+			activation_source_clear (self, TRUE, family);
+		}
 	}
+
+	*act_source_id = g_idle_add (func, self);
+	*act_source_func = func;
 }
 
 static gboolean
@@ -2655,19 +2671,22 @@ get_ip_config_may_fail (NMDevice *self, int family)
 }
 
 static void
-master_ready_cb (NMActiveConnection *active,
-                 GParamSpec *pspec,
-                 NMDevice *self)
+master_ready (NMDevice *self,
+              NMActiveConnection *active)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
 	NMActiveConnection *master;
 
-	g_assert (priv->state == NM_DEVICE_STATE_PREPARE);
+	g_return_if_fail (priv->state == NM_DEVICE_STATE_PREPARE);
+	g_return_if_fail (!priv->master_ready_handled);
 
 	/* Notify a master device that it has a new slave */
-	g_assert (nm_active_connection_get_master_ready (active));
+	g_return_if_fail (nm_active_connection_get_master_ready (active));
 	master = nm_active_connection_get_master (active);
 
+	priv->master_ready_handled = TRUE;
+	nm_clear_g_signal_handler (active, &priv->master_ready_id);
+
 	priv->master = g_object_ref (nm_active_connection_get_device (master));
 	nm_device_master_add_slave (priv->master,
 	                            self,
@@ -2676,11 +2695,14 @@ master_ready_cb (NMActiveConnection *active,
 	_LOGD (LOGD_DEVICE, "master connection ready; master device %s",
 	       nm_device_get_iface (priv->master));
 
-	if (priv->master_ready_id) {
-		g_signal_handler_disconnect (active, priv->master_ready_id);
-		priv->master_ready_id = 0;
-	}
+}
 
+static void
+master_ready_cb (NMActiveConnection *active,
+                 GParamSpec *pspec,
+                 NMDevice *self)
+{
+	master_ready (self, active);
 	nm_device_activate_schedule_stage2_device_config (self);
 }
 
@@ -2728,23 +2750,7 @@ nm_device_activate_stage1_device_prepare (gpointer user_data)
 		g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
 	}
 
-	if (nm_active_connection_get_master (active)) {
-		/* If the master connection is ready for slaves, attach ourselves */
-		if (nm_active_connection_get_master_ready (active))
-			master_ready_cb (active, NULL, self);
-		else {
-			_LOGD (LOGD_DEVICE, "waiting for master connection to become ready");
-
-			/* Attach a signal handler and wait for the master connection to begin activating */
-			g_assert (priv->master_ready_id == 0);
-			priv->master_ready_id = g_signal_connect (active,
-			                                          "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY,
-			                                          (GCallback) master_ready_cb,
-			                                          self);
-			/* Postpone */
-		}
-	} else
-		nm_device_activate_schedule_stage2_device_config (self);
+	nm_device_activate_schedule_stage2_device_config (self);
 
 out:
 	_LOGD (LOGD_DEVICE, "Activation: Stage 1 of 5 (Device Prepare) complete.");
@@ -2862,6 +2868,31 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self)
 	priv = NM_DEVICE_GET_PRIVATE (self);
 	g_return_if_fail (priv->act_request);
 
+	if (!priv->master_ready_handled) {
+		NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request);
+
+		if (!nm_active_connection_get_master (active)) {
+			g_warn_if_fail (!priv->master_ready_id);
+			priv->master_ready_handled = TRUE;
+		} else {
+			/* If the master connection is ready for slaves, attach ourselves */
+			if (nm_active_connection_get_master_ready (active))
+				master_ready (self, active);
+			else {
+				_LOGD (LOGD_DEVICE, "waiting for master connection to become ready");
+
+				if (priv->master_ready_id == 0) {
+					priv->master_ready_id = g_signal_connect (active,
+					                                          "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY,
+					                                          (GCallback) master_ready_cb,
+					                                          self);
+				}
+				/* Postpone */
+				return;
+			}
+		}
+	}
+
 	activation_source_schedule (self, nm_device_activate_stage2_device_config, 0);
 
 	_LOGD (LOGD_DEVICE, "Activation: Stage 2 of 5 (Device Configure) scheduled...");
@@ -3467,6 +3498,16 @@ dhcp4_fail (NMDevice *self, gboolean timeout)
 		return;
 	}
 
+	/* Instead of letting an assumed connection fail (which means that the
+	 * device will transition to the ACTIVATED state without IP configuration),
+	 * retry DHCP again.
+	 */
+	if (nm_device_uses_assumed_connection (self)) {
+		_LOGI (LOGD_DHCP4, "Scheduling DHCPv4 restart because the connection is assumed");
+		priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self);
+		return;
+	}
+
 	if (timeout || (priv->ip4_state == IP_CONF))
 		nm_device_activate_schedule_ip4_config_timeout (self);
 	else if (priv->ip4_state == IP_DONE)
@@ -4141,6 +4182,16 @@ dhcp6_fail (NMDevice *self, gboolean timeout)
 			return;
 		}
 
+		/* Instead of letting an assumed connection fail (which means that the
+		 * device will transition to the ACTIVATED state without IP configuration),
+		 * retry DHCP again.
+		 */
+		if (nm_device_uses_assumed_connection (self)) {
+			_LOGI (LOGD_DHCP6, "Scheduling DHCPv6 restart because the connection is assumed");
+			priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self);
+			return;
+		}
+
 		if (timeout || (priv->ip6_state == IP_CONF))
 			nm_device_activate_schedule_ip6_config_timeout (self);
 		else if (priv->ip6_state == IP_DONE)
@@ -4513,7 +4564,12 @@ linklocal6_start (NMDevice *self)
 
 	check_and_add_ipv6ll_addr (self);
 
-	priv->linklocal6_timeout_id = g_timeout_add_seconds (5, linklocal6_timeout_cb, self);
+	/* Depending on the network and what the 'dad_transmits' and 'retrans_time_ms'
+	 * sysctl values are, DAD for the IPv6LL address may take quite a while.
+	 * FIXME: use dad/retrans sysctl values if they are higher than a minimum time.
+	 * (rh #1101809)
+	 */
+	priv->linklocal6_timeout_id = g_timeout_add_seconds (15, linklocal6_timeout_cb, self);
 
 	return NM_ACT_STAGE_RETURN_POSTPONE;
 }
@@ -5060,7 +5116,6 @@ act_stage3_ip6_config_start (NMDevice *self,
                              NMDeviceStateReason *reason)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-	const char *ip_iface;
 	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
 	NMConnection *connection;
 	const char *method;
@@ -5071,8 +5126,6 @@ act_stage3_ip6_config_start (NMDevice *self,
 
 	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
-	ip_iface = nm_device_get_ip_iface (self);
-
 	connection = nm_device_get_connection (self);
 	g_assert (connection);
 
@@ -5347,11 +5400,13 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
 	}
 
 	/* IPv4 */
-	if (!nm_device_activate_stage3_ip4_start (self))
+	if (   nm_device_activate_ip4_state_in_wait (self)
+	    && !nm_device_activate_stage3_ip4_start (self))
 		goto out;
 
 	/* IPv6 */
-	if (!nm_device_activate_stage3_ip6_start (self))
+	if (   nm_device_activate_ip6_state_in_wait (self)
+	    && !nm_device_activate_stage3_ip6_start (self))
 		goto out;
 
 	nm_device_check_ip_failed (self, TRUE);
@@ -6003,10 +6058,8 @@ clear_act_request (NMDevice *self)
 
 	nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
 
-	if (priv->master_ready_id) {
-		g_signal_handler_disconnect (priv->act_request, priv->master_ready_id);
-		priv->master_ready_id = 0;
-	}
+	priv->master_ready_handled = FALSE;
+	nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id);
 
 	g_clear_object (&priv->act_request);
 	g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION);
@@ -6302,7 +6355,7 @@ _carrier_wait_check_queued_act_request (NMDevice *self)
 	priv->queued_act_request_is_waiting_for_carrier = FALSE;
 	if (!priv->carrier) {
 		_LOGD (LOGD_DEVICE, "Cancel queued activation request as we have no carrier after timeout");
-		g_clear_object (&priv->queued_act_request);
+		_clear_queued_act_request (priv);
 	} else {
 		_LOGD (LOGD_DEVICE, "Activate queued activation request as we now have carrier");
 		queued_req = priv->queued_act_request;
@@ -6326,6 +6379,8 @@ _carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
 		return FALSE;
 
 	connection = nm_act_request_get_connection (req);
+	if (!connection_requires_carrier (connection))
+		return FALSE;
 
 	if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL, NULL)) {
 		/* We passed all @flags we have, and no @specific_object.
@@ -6457,7 +6512,6 @@ nm_device_set_ip4_config (NMDevice *self,
                           NMDeviceStateReason *reason)
 {
 	NMDevicePrivate *priv;
-	const char *ip_iface;
 	NMIP4Config *old_config = NULL;
 	gboolean has_changes = FALSE;
 	gboolean success = TRUE;
@@ -6467,7 +6521,6 @@ nm_device_set_ip4_config (NMDevice *self,
 	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
 
 	priv = NM_DEVICE_GET_PRIVATE (self);
-	ip_iface = nm_device_get_ip_iface (self);
 	ip_ifindex = nm_device_get_ip_ifindex (self);
 
 	old_config = priv->ip4_config;
@@ -6592,7 +6645,6 @@ nm_device_set_ip6_config (NMDevice *self,
                           NMDeviceStateReason *reason)
 {
 	NMDevicePrivate *priv;
-	const char *ip_iface;
 	NMIP6Config *old_config = NULL;
 	gboolean has_changes = FALSE;
 	gboolean success = TRUE;
@@ -6602,7 +6654,6 @@ nm_device_set_ip6_config (NMDevice *self,
 	g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
 
 	priv = NM_DEVICE_GET_PRIVATE (self);
-	ip_iface = nm_device_get_ip_iface (self);
 	ip_ifindex = nm_device_get_ip_ifindex (self);
 
 	old_config = priv->ip6_config;
@@ -7058,9 +7109,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
 	 * a timeout is reached.
 	 */
 	if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
-		if (priv->carrier_wait_id)
-			g_source_remove (priv->carrier_wait_id);
-		else
+		if (!nm_clear_g_source (&priv->carrier_wait_id))
 			nm_device_add_pending_action (self, "carrier wait", TRUE);
 		priv->carrier_wait_id = g_timeout_add_seconds (5, carrier_wait_timeout, self);
 	}
@@ -8032,16 +8081,23 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
 	NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
 
 	priv->default_route.v4_has = FALSE;
-	priv->default_route.v4_is_assumed = TRUE;
 	priv->default_route.v6_has = FALSE;
-	priv->default_route.v6_is_assumed = TRUE;
 
-	priv->v4_commit_first_time = TRUE;
-	priv->v6_commit_first_time = TRUE;
+	if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
+		priv->default_route.v4_is_assumed = FALSE;
+		priv->default_route.v6_is_assumed = FALSE;
+		nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self);
+		nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self);
+	}
 
+	priv->default_route.v4_is_assumed = TRUE;
+	priv->default_route.v6_is_assumed = TRUE;
 	nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self);
 	nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self);
 
+	priv->v4_commit_first_time = TRUE;
+	priv->v6_commit_first_time = TRUE;
+
 	/* Clean up IP configs; this does not actually deconfigure the
 	 * interface; the caller must flush routes and addresses explicitly.
 	 */
@@ -8206,15 +8262,9 @@ nm_device_spawn_iface_helper (NMDevice *self)
 	dhcp4_address = find_dhcp4_address (self);
 
 	method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
-	if (   priv->ip4_config
-	    && priv->ip4_state == IP_DONE
-	    && g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0
-	    && priv->dhcp4_client
-	    && dhcp4_address) {
+	if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) {
 		NMSettingIPConfig *s_ip4;
-		GBytes *client_id;
 		char *hex_client_id;
-		const char *hostname;
 
 		s_ip4 = nm_connection_get_setting_ip4_config (connection);
 		g_assert (s_ip4);
@@ -8227,29 +8277,30 @@ nm_device_spawn_iface_helper (NMDevice *self)
 		if (nm_setting_ip_config_get_may_fail (s_ip4) == FALSE)
 			g_ptr_array_add (argv, g_strdup ("--dhcp4-required"));
 
-		client_id = nm_dhcp_client_get_client_id (priv->dhcp4_client);
-		if (client_id) {
-			g_ptr_array_add (argv, g_strdup ("--dhcp4-clientid"));
-			hex_client_id = bin2hexstr (g_bytes_get_data (client_id, NULL),
-			                            g_bytes_get_size (client_id));
-			g_ptr_array_add (argv, hex_client_id);
-		}
+		if (priv->dhcp4_client) {
+			const char *hostname;
+			GBytes *client_id;
+
+			client_id = nm_dhcp_client_get_client_id (priv->dhcp4_client);
+			if (client_id) {
+				g_ptr_array_add (argv, g_strdup ("--dhcp4-clientid"));
+				hex_client_id = bin2hexstr (g_bytes_get_data (client_id, NULL),
+				                            g_bytes_get_size (client_id));
+				g_ptr_array_add (argv, hex_client_id);
+			}
 
-		hostname = nm_dhcp_client_get_hostname (priv->dhcp4_client);
-		if (hostname) {
-			g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname"));
-			g_ptr_array_add (argv, g_strdup (hostname));
+			hostname = nm_dhcp_client_get_hostname (priv->dhcp4_client);
+			if (hostname) {
+				g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname"));
+				g_ptr_array_add (argv, g_strdup (hostname));
+			}
 		}
 
 		configured = TRUE;
 	}
 
 	method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
-	if (   priv->ip6_config
-	    && priv->ip6_state == IP_DONE
-	    && g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
-	    && priv->rdisc
-	    && priv->ac_ip6_config) {
+	if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
 		NMSettingIPConfig *s_ip6;
 		char *hex_iid;
 		NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
@@ -8611,6 +8662,14 @@ _set_state_full (NMDevice *self,
 		nm_dispatcher_call (DISPATCHER_ACTION_UP, nm_act_request_get_connection (req), self, NULL, NULL, NULL);
 		break;
 	case NM_DEVICE_STATE_FAILED:
+		/* Usually upon failure the activation chain is interrupted in
+		 * one of the stages; but in some cases the device fails for
+		 * external events (as a failure of master connection) while
+		 * the activation sequence is running and so we need to ensure
+		 * that the chain is terminated here.
+		 */
+		_cancel_activation (self);
+
 		if (nm_device_uses_assumed_connection (self)) {
 			/* Avoid tearing down assumed connection, assume it's connected */
 			nm_device_queue_state (self,
@@ -9195,10 +9254,7 @@ dispose (GObject *object)
 
 	g_hash_table_remove_all (priv->available_connections);
 
-	if (priv->carrier_wait_id) {
-		g_source_remove (priv->carrier_wait_id);
-		priv->carrier_wait_id = 0;
-	}
+	nm_clear_g_source (&priv->carrier_wait_id);
 
 	_clear_queued_act_request (priv);
 
@@ -9822,6 +9878,13 @@ nm_device_class_init (NMDeviceClass *klass)
 		              0, NULL, NULL, NULL,
 		              G_TYPE_NONE, 0);
 
+	signals[LINK_INITIALIZED] =
+		g_signal_new (NM_DEVICE_LINK_INITIALIZED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              0, NULL, NULL, NULL,
+		              G_TYPE_NONE, 0);
+
 	nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
 	                                        G_TYPE_FROM_CLASS (klass),
 	                                        &dbus_glib_nm_device_object_info);
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index e9d5b948..49cef8e1 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -74,6 +74,7 @@
 #define NM_DEVICE_REMOVED               "removed"
 #define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
 #define NM_DEVICE_RECHECK_ASSUME        "recheck-assume"
+#define NM_DEVICE_LINK_INITIALIZED      "link-initialized"
 
 G_BEGIN_DECLS
 
diff --git a/src/devices/team/Makefile.am b/src/devices/team/Makefile.am
index 6fea9b3f..46c5fe1d 100644
--- a/src/devices/team/Makefile.am
+++ b/src/devices/team/Makefile.am
@@ -8,6 +8,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/devices \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/include \
+	-I$(top_builddir)/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-team"\" \
diff --git a/src/devices/team/Makefile.in b/src/devices/team/Makefile.in
index 342c41ee..7305b05a 100644
--- a/src/devices/team/Makefile.in
+++ b/src/devices/team/Makefile.in
@@ -345,6 +345,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -487,8 +488,8 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 AM_CPPFLAGS = -I${top_srcdir}/src -I${top_builddir}/src \
 	-I${top_srcdir}/src/devices -I${top_srcdir}/src/platform \
-	-I${top_srcdir}/include -I${top_builddir}/libnm-core \
-	-I${top_srcdir}/libnm-core \
+	-I${top_srcdir}/include -I$(top_builddir)/include \
+	-I${top_builddir}/libnm-core -I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-team"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(DBUS_CFLAGS) \
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index 09b2dd7d..1950fd2a 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -710,6 +710,7 @@ nm_device_team_new_for_connection (NMConnection *connection, GError **error)
 {
 	const char *iface = nm_connection_get_interface_name (connection);
 	NMPlatformError plerr;
+	const NMPlatformLink *plink;
 
 	g_assert (iface);
 
@@ -722,9 +723,10 @@ nm_device_team_new_for_connection (NMConnection *connection, GError **error)
 		             nm_platform_error_to_string (plerr));
 		return NULL;
 	}
+	plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
 
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM,
-	                                  NM_DEVICE_IFACE, iface,
+	                                  NM_DEVICE_PLATFORM_DEVICE, plink,
 	                                  NM_DEVICE_DRIVER, "team",
 	                                  NM_DEVICE_TYPE_DESC, "Team",
 	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TEAM,
diff --git a/src/devices/wifi/Makefile.am b/src/devices/wifi/Makefile.am
index 230c00ac..4ac59e3d 100644
--- a/src/devices/wifi/Makefile.am
+++ b/src/devices/wifi/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/src/supplicant-manager \
 	-I${top_srcdir}/include \
+	-I$(top_builddir)/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \
diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in
index b679bfc2..82ebad74 100644
--- a/src/devices/wifi/Makefile.in
+++ b/src/devices/wifi/Makefile.in
@@ -385,6 +385,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -534,6 +535,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/src/supplicant-manager \
 	-I${top_srcdir}/include \
+	-I$(top_builddir)/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \
diff --git a/src/devices/wifi/nm-device-wifi-glue.h b/src/devices/wifi/nm-device-wifi-glue.h
index 3d0f63db..8f8da2af 100644
--- a/src/devices/wifi/nm-device-wifi-glue.h
+++ b/src/devices/wifi/nm-device-wifi-glue.h
@@ -74,9 +74,9 @@ dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER (GClosure     *closure
                                                              gpointer     arg_1,
                                                              gpointer     arg_2,
                                                              gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
@@ -121,9 +121,9 @@ dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER (GClosure     *closure,
                                                     gpointer     arg_1,
                                                     gpointer     arg_2,
                                                     gpointer     data2);
-  register GMarshalFunc_VOID__BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__BOXED_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index dde743b1..15d41206 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -499,7 +499,7 @@ update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap)
 }
 
 static void
-set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_available_connections, gboolean force_remove_old_ap)
+set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_available_connections)
 {
 	NMDeviceWifiPrivate *priv;
 	NMAccessPoint *old_ap;
@@ -530,7 +530,7 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai
 	if (old_ap) {
 		NM80211Mode mode = nm_ap_get_mode (old_ap);
 
-		if (force_remove_old_ap || mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap)) {
+		if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap)) {
 			remove_access_point (self, old_ap);
 			if (recheck_available_connections)
 				nm_device_recheck_available_connections (NM_DEVICE (self));
@@ -629,7 +629,7 @@ periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap)
 		       new_bssid ? new_bssid : "(none)",
 		       new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)");
 
-		set_current_ap (self, new_ap, TRUE, FALSE);
+		set_current_ap (self, new_ap, TRUE);
 	}
 
 	new_rate = nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex);
@@ -690,7 +690,7 @@ remove_all_aps (NMDeviceWifi *self)
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
 	if (priv->ap_list) {
-		set_current_ap (self, NULL, FALSE, FALSE);
+		set_current_ap (self, NULL, FALSE);
 
 		while (priv->ap_list)
 			remove_access_point (self, NM_AP (priv->ap_list->data));
@@ -728,7 +728,7 @@ deactivate (NMDevice *device)
 	 * was non-broadcasting or something) get rid of it, because 'fake'
 	 * APs should only live for as long as we're connected to them.
 	 **/
-	set_current_ap (self, NULL, TRUE, FALSE);
+	set_current_ap (self, NULL, TRUE);
 
 	/* Clear any critical protocol notification in the Wi-Fi stack */
 	nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE);
@@ -958,8 +958,6 @@ complete_connection (NMDevice *device,
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	NMSettingWireless *s_wifi;
-	NMSettingWirelessSecurity *s_wsec;
-	NMSetting8021x *s_8021x;
 	const char *setting_mac;
 	char *str_ssid = NULL;
 	NMAccessPoint *ap = NULL;
@@ -971,8 +969,6 @@ complete_connection (NMDevice *device,
 	const char *perm_hw_addr;
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
-	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	s_8021x = nm_connection_get_setting_802_1x (connection);
 
 	if (!specific_object) {
 		/* If not given a specific object, we need at minimum an SSID */
@@ -1548,6 +1544,9 @@ request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options)
 static gboolean
 request_wireless_scan_periodic (gpointer user_data)
 {
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (user_data);
+
+	priv->pending_scan_id = 0;
 	request_wireless_scan (user_data, NULL);
 	return FALSE;
 }
@@ -1650,7 +1649,7 @@ try_fill_ssid_for_hidden_ap (NMAccessPoint *ap)
 	g_return_if_fail (nm_ap_get_ssid (ap) == NULL);
 
 	bssid = nm_ap_get_address (ap);
-	g_assert (bssid);
+	g_return_if_fail (bssid);
 
 	/* Look for this AP's BSSID in the seen-bssids list of a connection,
 	 * and if a match is found, copy over the SSID */
@@ -1692,11 +1691,9 @@ merge_scanned_ap (NMDeviceWifi *self,
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	NMAccessPoint *found_ap = NULL;
 	const GByteArray *ssid;
-	const char *bssid;
 	gboolean strict_match = TRUE;
 
 	/* Let the manager try to fill in the SSID from seen-bssids lists */
-	bssid = nm_ap_get_address (merge_ap);
 	ssid = nm_ap_get_ssid (merge_ap);
 	if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) {
 		/* Try to fill the SSID from the AP database */
@@ -1706,12 +1703,12 @@ merge_scanned_ap (NMDeviceWifi *self,
 		if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) {
 			/* Yay, matched it, no longer treat as hidden */
 			_LOGD (LOGD_WIFI_SCAN, "matched hidden AP %s => '%s'",
-			       str_if_set (bssid, "(none)"), nm_utils_escape_ssid (ssid->data, ssid->len));
+			       nm_ap_get_address (merge_ap), nm_utils_escape_ssid (ssid->data, ssid->len));
 			nm_ap_set_broadcast (merge_ap, FALSE);
 		} else {
 			/* Didn't have an entry for this AP in the database */
 			_LOGD (LOGD_WIFI_SCAN, "failed to match hidden AP %s",
-			       str_if_set (bssid, "(none)"));
+			       nm_ap_get_address (merge_ap));
 		}
 	}
 
@@ -1730,7 +1727,7 @@ merge_scanned_ap (NMDeviceWifi *self,
 	if (found_ap) {
 		_LOGD (LOGD_WIFI_SCAN, "merging AP '%s' %s (%p) with existing (%p)",
 		            ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
-		            str_if_set (bssid, "(none)"),
+		            nm_ap_get_address (merge_ap),
 		            merge_ap,
 		            found_ap);
 
@@ -1753,7 +1750,7 @@ merge_scanned_ap (NMDeviceWifi *self,
 		/* New entry in the list */
 		_LOGD (LOGD_WIFI_SCAN, "adding new AP '%s' %s (%p)",
 		       ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
-		       str_if_set (bssid, "(none)"), merge_ap);
+		       nm_ap_get_address (merge_ap), merge_ap);
 
 		g_object_ref (merge_ap);
 		priv->ap_list = g_slist_prepend (priv->ap_list, merge_ap);
@@ -1872,7 +1869,7 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
 		merge_scanned_ap (self, ap);
 		g_object_unref (ap);
 	} else
-		_LOGW (LOGD_WIFI_SCAN, "invalid AP properties received");
+		_LOGD (LOGD_WIFI_SCAN, "invalid AP properties received for %s", object_path);
 
 	/* Remove outdated access points */
 	schedule_scanlist_cull (self);
@@ -2010,11 +2007,21 @@ link_timeout_cb (gpointer user_data)
 
 	/* If the access point failed, and wasn't found by the supplicant when it
 	 * attempted to reconnect, then it's probably out of range or turned off.
-	 * Remove it from the list and if it's actually still present, it'll be
-	 * found in the next scan.
 	 */
-	if (priv->ssid_found == FALSE && priv->current_ap)
-		set_current_ap (self, NULL, TRUE, TRUE);
+	if (priv->ssid_found == FALSE && priv->current_ap) {
+		NMAccessPoint *old_ap = g_object_ref (priv->current_ap);
+
+		set_current_ap (self, NULL, TRUE);
+
+		/* If it was an external entity and the supplicant doesn't know about
+		 * it, remove it from the scan list.  If it's still around, it'll get
+		 * found in the next scan.
+		 */
+		if (    nm_ap_get_mode (old_ap) == NM_802_11_MODE_INFRA
+		    && g_object_get_data (G_OBJECT (old_ap), WPAS_REMOVED_TAG))
+			remove_access_point (self, old_ap);
+		g_object_unref (old_ap);
+	}
 
 	nm_device_state_changed (device,
 	                         NM_DEVICE_STATE_FAILED,
@@ -2486,13 +2493,16 @@ build_supplicant_config (NMDeviceWifi *self,
 	if (s_wireless_sec) {
 		NMSetting8021x *s_8021x;
 		const char *con_uuid = nm_connection_get_uuid (connection);
+		guint32 mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET,
+		                                        nm_device_get_ifindex (NM_DEVICE (self)));
 
 		g_assert (con_uuid);
 		s_8021x = nm_connection_get_setting_802_1x (connection);
 		if (!nm_supplicant_config_add_setting_wireless_security (config,
 		                                                         s_wireless_sec,
 		                                                         s_8021x,
-		                                                         con_uuid)) {
+		                                                         con_uuid,
+		                                                         mtu)) {
 			_LOGE (LOGD_WIFI, "Couldn't add 802-11-wireless-security setting to supplicant config.");
 			goto error;
 		}
@@ -2609,14 +2619,14 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	priv->ap_list = g_slist_prepend (priv->ap_list, ap);
 	nm_ap_export_to_dbus (ap);
 	g_object_freeze_notify (G_OBJECT (self));
-	set_current_ap (self, ap, FALSE, FALSE);
+	set_current_ap (self, ap, FALSE);
 	emit_ap_added_removed (self, ACCESS_POINT_ADDED, ap, TRUE);
 	g_object_thaw_notify (G_OBJECT (self));
 	nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap));
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 
 done:
-	set_current_ap (self, ap, TRUE, FALSE);
+	set_current_ap (self, ap, TRUE);
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
@@ -3004,10 +3014,10 @@ done:
 		 * then the fake one and reset it. Reset the fake current_ap to NULL
 		 * now, which will remove the fake ap.
 		 **/
-		set_current_ap (self, NULL, TRUE, FALSE);
+		set_current_ap (self, NULL, TRUE);
 	}
 
-	/* No need to update seen BSSIDs cache, that is done by set_current_ap() already */
+	update_seen_bssids_cache (self, priv->current_ap);
 
 	/* Reset scan interval to something reasonable */
 	priv->scan_interval = SCAN_INTERVAL_MIN + (SCAN_INTERVAL_STEP * 2);
diff --git a/src/devices/wifi/nm-wifi-ap-utils.c b/src/devices/wifi/nm-wifi-ap-utils.c
index 9ac7052e..1a772fb7 100644
--- a/src/devices/wifi/nm-wifi-ap-utils.c
+++ b/src/devices/wifi/nm-wifi-ap-utils.c
@@ -549,11 +549,11 @@ nm_ap_utils_complete_connection (const GByteArray *ap_ssid,
 	s_8021x = nm_connection_get_setting_802_1x (connection);
 
 	/* Fill in missing SSID */
-	ap_ssid_bytes = g_bytes_new (ap_ssid->data, ap_ssid->len);
+	ap_ssid_bytes = ap_ssid ? g_bytes_new (ap_ssid->data, ap_ssid->len) : NULL;
 	ssid = nm_setting_wireless_get_ssid (s_wifi);
 	if (!ssid)
 		g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_SSID, ap_ssid_bytes, NULL);
-	else if (!g_bytes_equal (ssid, ap_ssid_bytes)) {
+	else if (!ap_ssid_bytes || !g_bytes_equal (ssid, ap_ssid_bytes)) {
 		g_set_error_literal (error,
 		                     NM_CONNECTION_ERROR,
 		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index 1485f4c1..72430021 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -476,9 +476,10 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
 
 	nm_ap_set_supplicant_path (ap, supplicant_path);
 
-	/* ignore APs with invalid BSSIDs */
+	/* ignore APs with invalid or missing BSSIDs */
 	addr = nm_ap_get_address (ap);
-	if (   nm_utils_hwaddr_matches (addr, -1, bad_bssid1, ETH_ALEN)
+	if (   !addr
+	    || nm_utils_hwaddr_matches (addr, -1, bad_bssid1, ETH_ALEN)
 	    || nm_utils_hwaddr_matches (addr, -1, bad_bssid2, ETH_ALEN)) {
 		g_object_unref (ap);
 		return NULL;
diff --git a/src/devices/wifi/tests/Makefile.am b/src/devices/wifi/tests/Makefile.am
index 2a7d7849..f76bdbf5 100644
--- a/src/devices/wifi/tests/Makefile.am
+++ b/src/devices/wifi/tests/Makefile.am
@@ -1,5 +1,6 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I${top_srcdir}/src/platform \
diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in
index f807ee77..f2488c7d 100644
--- a/src/devices/wifi/tests/Makefile.in
+++ b/src/devices/wifi/tests/Makefile.in
@@ -511,6 +511,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -653,6 +654,7 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I${top_srcdir}/src/platform \
diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c
index 3c405e26..26e130c4 100644
--- a/src/devices/wifi/tests/test-wifi-ap-utils.c
+++ b/src/devices/wifi/tests/test-wifi-ap-utils.c
@@ -1364,10 +1364,10 @@ main (int argc, char **argv)
 	                      test_open_ap_leap_connection_1);
 	g_test_add_func ("/wifi/open_ap/leap_connection/2",
 	                 test_open_ap_leap_connection_2);
-	g_test_add_data_func ("/wifi/open_ap/wep_connection",
+	g_test_add_data_func ("/wifi/open_ap/wep_connection_true",
 	                      (gconstpointer) TRUE,
 	                      test_open_ap_wep_connection);
-	g_test_add_data_func ("/wifi/open_ap/wep_connection",
+	g_test_add_data_func ("/wifi/open_ap/wep_connection_false",
 	                      (gconstpointer) FALSE,
 	                      test_open_ap_wep_connection);
 
@@ -1441,104 +1441,57 @@ main (int argc, char **argv)
 	                      (gconstpointer) IDX_PRIV,
 	                      test_ap_wpa_eap_connection_5);
 
+#define ADD_FUNC(func) do { \
+		gchar *name_idx = g_strdup_printf ("/wifi/wpa_psk/" G_STRINGIFY (func) "/%zd", i); \
+		g_test_add_data_func (name_idx, (gconstpointer) i, func); \
+		g_free (name_idx); \
+	} while (0)
+
 	/* WPA-PSK tests */
 	for (i = IDX_WPA_PSK_PTKIP_GTKIP; i <= IDX_WPA_RSN_PSK_PCCMP_GCCMP; i++) {
-		g_test_add_data_func ("/wifi/wpa_psk/empty_connection",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_empty_connection);
-		g_test_add_data_func ("/wifi/wpa_psk/leap_connection/1",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_leap_connection_1);
-		g_test_add_data_func ("/wifi/wpa_psk/leap_connection/2",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_leap_connection_2);
-
-		g_test_add_data_func ("/wifi/wpa_psk/dynamic_wep_connection",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_dynamic_wep_connection);
-
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/1",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_1);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/2",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_2);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/3",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_3);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/4",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_4);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_psk_connection/5",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_5);
-
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/1",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_1);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/2",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_2);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/3",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_3);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/4",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_4);
-		g_test_add_data_func ("/wifi/wpa_psk/wpa_eap_connection/5",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_5);
+		ADD_FUNC(test_wpa_ap_empty_connection);
+		ADD_FUNC(test_wpa_ap_leap_connection_1);
+		ADD_FUNC(test_wpa_ap_leap_connection_2);
+		ADD_FUNC(test_wpa_ap_dynamic_wep_connection);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_1);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_2);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_3);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_4);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_5);
+		ADD_FUNC(test_ap_wpa_eap_connection_1);
+		ADD_FUNC(test_ap_wpa_eap_connection_2);
+		ADD_FUNC(test_ap_wpa_eap_connection_3);
+		ADD_FUNC(test_ap_wpa_eap_connection_4);
+		ADD_FUNC(test_ap_wpa_eap_connection_5);
 	}
 
+#undef ADD_FUNC
+#define ADD_FUNC(func) do { \
+		gchar *name_idx = g_strdup_printf ("/wifi/rsn_psk/" G_STRINGIFY (func) "/%zd", i); \
+		g_test_add_data_func (name_idx, (gconstpointer) i, func); \
+		g_free (name_idx); \
+	} while (0)
+
 	/* RSN-PSK tests */
 	for (i = IDX_WPA_RSN_PSK_PTKIP_PCCMP_GTKIP; i <= IDX_RSN_PSK_PTKIP_PCCMP_GTKIP; i++) {
-		g_test_add_data_func ("/wifi/rsn_psk/empty_connection",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_empty_connection);
-		g_test_add_data_func ("/wifi/rsn_psk/leap_connection/1",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_leap_connection_1);
-		g_test_add_data_func ("/wifi/rsn_psk/leap_connection/2",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_leap_connection_2);
-
-		g_test_add_data_func ("/wifi/rsn_psk/dynamic_wep_connection",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_dynamic_wep_connection);
-
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/1",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_1);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/2",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_2);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/3",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_3);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/4",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_4);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_psk_connection/5",
-		                      (gconstpointer) i,
-		                      test_wpa_ap_wpa_psk_connection_5);
-
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/1",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_1);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/2",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_2);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/3",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_3);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/4",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_4);
-		g_test_add_data_func ("/wifi/rsn_psk/wpa_eap_connection/5",
-		                      (gconstpointer) i,
-		                      test_ap_wpa_eap_connection_5);
+		ADD_FUNC(test_wpa_ap_empty_connection);
+		ADD_FUNC(test_wpa_ap_leap_connection_1);
+		ADD_FUNC(test_wpa_ap_leap_connection_2);
+		ADD_FUNC(test_wpa_ap_dynamic_wep_connection);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_1);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_2);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_3);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_4);
+		ADD_FUNC(test_wpa_ap_wpa_psk_connection_5);
+		ADD_FUNC(test_ap_wpa_eap_connection_1);
+		ADD_FUNC(test_ap_wpa_eap_connection_2);
+		ADD_FUNC(test_ap_wpa_eap_connection_3);
+		ADD_FUNC(test_ap_wpa_eap_connection_4);
+		ADD_FUNC(test_ap_wpa_eap_connection_5);
 	}
 
+#undef ADD_FUNC
+
 	/* Scanned signal strength conversion tests */
 	g_test_add_func ("/wifi/strength/dbm",
 	                 test_strength_dbm);
diff --git a/src/devices/wimax/Makefile.am b/src/devices/wimax/Makefile.am
index 555b5ff2..0ecd1158 100644
--- a/src/devices/wimax/Makefile.am
+++ b/src/devices/wimax/Makefile.am
@@ -4,6 +4,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/devices \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/include \
+	-I${top_builddir}/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wimax"\" \
diff --git a/src/devices/wimax/Makefile.in b/src/devices/wimax/Makefile.in
index 8ad4b4e2..b1b57a79 100644
--- a/src/devices/wimax/Makefile.in
+++ b/src/devices/wimax/Makefile.in
@@ -339,6 +339,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -485,6 +486,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/devices \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/include \
+	-I${top_builddir}/include \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wimax"\" \
diff --git a/src/devices/wwan/Makefile.am b/src/devices/wwan/Makefile.am
index 7e5b190b..055b07b9 100644
--- a/src/devices/wwan/Makefile.am
+++ b/src/devices/wwan/Makefile.am
@@ -9,12 +9,14 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/settings \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/include \
-	-I${top_builddir}/libnm-core \
+	-I$(top_builddir)/include \
 	-I${top_srcdir}/libnm-core \
+	-I${top_builddir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
 	$(MM_GLIB_CFLAGS)
 
 BUILT_SOURCES = $(null)
diff --git a/src/devices/wwan/Makefile.in b/src/devices/wwan/Makefile.in
index 227c622f..571b1b7d 100644
--- a/src/devices/wwan/Makefile.in
+++ b/src/devices/wwan/Makefile.in
@@ -350,6 +350,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -497,12 +498,14 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/settings \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/include \
-	-I${top_builddir}/libnm-core \
+	-I$(top_builddir)/include \
 	-I${top_srcdir}/libnm-core \
+	-I${top_builddir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
 	$(MM_GLIB_CFLAGS)
 
 BUILT_SOURCES = $(null) $(GLIB_GENERATED) nm-device-modem-glue.h
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index 4bb72fd1..ec4f4a2f 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -1146,6 +1146,19 @@ sim_changed (MMModem *modem, GParamSpec *pspec, gpointer user_data)
 }
 
 static void
+supported_ip_families_changed (MMModem *modem, GParamSpec *pspec, gpointer user_data)
+{
+	NMModemBroadband *self = NM_MODEM_BROADBAND (user_data);
+
+	g_return_if_fail (modem == self->priv->modem_iface);
+
+	g_object_set (G_OBJECT (self),
+	              NM_MODEM_IP_TYPES,
+	              mm_ip_family_to_nm (mm_modem_get_supported_ip_families (modem)),
+	              NULL);
+}
+
+static void
 nm_modem_broadband_init (NMModemBroadband *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
@@ -1176,6 +1189,10 @@ set_property (GObject *object,
 		                  G_CALLBACK (sim_changed),
 		                  self);
 		sim_changed (self->priv->modem_iface, NULL, self);
+		g_signal_connect (self->priv->modem_iface,
+		                  "notify::supported-ip-families",
+		                  G_CALLBACK (supported_ip_families_changed),
+		                  self);
 
 		/* Note: don't grab the Simple iface here; the Modem interface is the
 		 * only one assumed to be always valid and available */
diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in
index 8c6e059c..6a2cad49 100644
--- a/src/dhcp-manager/Makefile.in
+++ b/src/dhcp-manager/Makefile.in
@@ -336,6 +336,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c
index 2bd0d72f..571765f7 100644
--- a/src/dhcp-manager/nm-dhcp-systemd.c
+++ b/src/dhcp-manager/nm-dhcp-systemd.c
@@ -397,6 +397,7 @@ nm_dhcp_systemd_get_lease_ip_configs (const char *iface,
 		ip4_config = lease_to_ip4_config (lease, NULL, default_route_metric, FALSE, NULL);
 		if (ip4_config)
 			leases = g_slist_append (leases, ip4_config);
+		sd_dhcp_lease_unref (lease);
 	}
 
 	return leases;
@@ -532,6 +533,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
 	struct in_addr last_addr = { 0 };
 	const char *hostname;
 	int r, i;
+	gboolean success = FALSE;
 
 	g_assert (priv->client4 == NULL);
 	g_assert (priv->client6 == NULL);
@@ -618,8 +620,6 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
 		}
 	}
 
-	if (lease)
-		sd_dhcp_lease_unref (lease);
 
 	/* Add requested options */
 	for (i = 0; dhcp4_requests[i].name; i++) {
@@ -642,12 +642,13 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
 		goto error;
 	}
 
-	return TRUE;
+	success = TRUE;
 
 error:
-	sd_dhcp_client_unref (priv->client4);
-	priv->client4 = NULL;
-	return FALSE;
+	sd_dhcp_lease_unref (lease);
+	if (!success)
+		priv->client4 = sd_dhcp_client_unref (priv->client4);
+	return success;
 }
 
 static void
diff --git a/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.c b/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.c
index a6d81727..3870342c 100644
--- a/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.c
+++ b/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.c
@@ -31,12 +31,28 @@ struct sd_event_source {
 	gpointer user_data;
 
 	GIOChannel *channel;
-	sd_event_io_handler_t io_cb;
 
-	uint64_t usec;
-	sd_event_time_handler_t time_cb;
+	union {
+		struct {
+			sd_event_io_handler_t cb;
+		} io;
+		struct {
+			sd_event_time_handler_t cb;
+			uint64_t usec;
+		} time;
+	};
 };
 
+static struct sd_event_source *
+source_new (void)
+{
+	struct sd_event_source *source;
+
+	source = g_slice_new0 (struct sd_event_source);
+	source->refcount = 1;
+	return source;
+}
+
 int
 sd_event_source_set_priority (sd_event_source *s, int64_t priority)
 {
@@ -62,7 +78,7 @@ sd_event_source_unref (sd_event_source *s)
 			 */
 			g_io_channel_unref (s->channel);
 		}
-		g_free (s);
+		g_slice_free (struct sd_event_source, s);
 	}
 	return NULL;
 }
@@ -81,6 +97,7 @@ static gboolean
 io_ready (GIOChannel *channel, GIOCondition condition, struct sd_event_source *source)
 {
 	int r, revents = 0;
+	gboolean result;
 
 	if (condition & G_IO_IN)
 		revents |= EPOLLIN;
@@ -93,13 +110,18 @@ io_ready (GIOChannel *channel, GIOCondition condition, struct sd_event_source *s
 	if (condition & G_IO_HUP)
 		revents |= EPOLLHUP;
 
-	r = source->io_cb (source, g_io_channel_unix_get_fd (channel), revents, source->user_data);
-	if (r < 0) {
+	source->refcount++;
+
+	r = source->io.cb (source, g_io_channel_unix_get_fd (channel), revents, source->user_data);
+	if (r < 0 || source->refcount <= 1) {
 		source->id = 0;
-		return G_SOURCE_REMOVE;
-	}
+		result = G_SOURCE_REMOVE;
+	} else
+		result = G_SOURCE_CONTINUE;
 
-	return G_SOURCE_CONTINUE;
+	sd_event_source_unref (source);
+
+	return result;
 }
 
 int
@@ -109,13 +131,16 @@ sd_event_add_io (sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_e
 	GIOChannel *channel;
 	GIOCondition condition = 0;
 
+	/* systemd supports floating sd_event_source by omitting the @s argument.
+	 * We don't have such users and don't implement floating references. */
+	g_return_val_if_fail (s, -EINVAL);
+
 	channel = g_io_channel_unix_new (fd);
 	if (!channel)
 		return -EINVAL;
 
-	source = g_new0 (struct sd_event_source, 1);
-	source->refcount = 1;
-	source->io_cb = callback;
+	source = source_new ();
+	source->io.cb = callback;
 	source->user_data = userdata;
 	source->channel = channel;
 
@@ -141,15 +166,14 @@ sd_event_add_io (sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_e
 static gboolean
 time_ready (struct sd_event_source *source)
 {
-	int r;
+	source->refcount++;
 
-	r = source->time_cb (source, source->usec, source->user_data);
-	if (r < 0) {
-		source->id = 0;
-		return G_SOURCE_REMOVE;
-	}
+	source->time.cb (source, source->time.usec, source->user_data);
+	source->id = 0;
+
+	sd_event_source_unref (source);
 
-	return G_SOURCE_CONTINUE;
+	return G_SOURCE_REMOVE;
 }
 
 int
@@ -158,11 +182,14 @@ sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t us
 	struct sd_event_source *source;
 	uint64_t n = now (clock);
 
-	source = g_new0 (struct sd_event_source, 1);
-	source->refcount = 1;
-	source->time_cb = callback;
+	/* systemd supports floating sd_event_source by omitting the @s argument.
+	 * We don't have such users and don't implement floating references. */
+	g_return_val_if_fail (s, -EINVAL);
+
+	source = source_new ();
+	source->time.cb = callback;
 	source->user_data = userdata;
-	source->usec = usec;
+	source->time.usec = usec;
 
 	if (usec > 1000)
 		usec = n < usec - 1000 ? usec - n : 1000;
diff --git a/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.h b/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.h
index f8856a1b..5e91c307 100644
--- a/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.h
+++ b/src/dhcp-manager/systemd-dhcp/nm-sd-adapt.h
@@ -35,6 +35,7 @@
 #endif
 #include <unistd.h>
 #include <sys/syscall.h>
+#include <time.h>
 
 #include "nm-logging.h"
 
@@ -43,6 +44,12 @@
 #define BPF_XOR 0xa0
 #endif
 
+#ifndef CLOCK_BOOTTIME
+#define CLOCK_BOOTTIME 7
+#endif
+
+/*****************************************************************************/
+
 static inline guint32
 _slog_level_to_nm (int slevel)
 {
@@ -75,18 +82,20 @@ G_STMT_START { \
 
 #define log_assert_failed(e, file, line, func) \
 G_STMT_START { \
-	nm_log_err (LOGD_DHCP, #file ":" #line "(" #func "): assertion failed: " # e); \
+	nm_log_err (LOGD_DHCP, "%s:%d (%s): assertion failed: %s", (""file), (line), (func), G_STRINGIFY (e)); \
 	g_assert (FALSE); \
 } G_STMT_END
 
 #define log_assert_failed_unreachable(t, file, line, func) \
 G_STMT_START { \
-	nm_log_err (LOGD_DHCP, #file ":" #line "(" #func "): assert unreachable: " # t); \
+	nm_log_err (LOGD_DHCP, "%s:%d (%s): assert unreachable: %s", (""file), (line), (func), G_STRINGIFY (t)); \
 	g_assert_not_reached (); \
 } G_STMT_END
 
 #define log_assert_failed_return(e, file, line, func) \
-	nm_log_err (LOGD_DHCP, #file ":" #line "(" #func "): assert return: " # e); \
+G_STMT_START { \
+	nm_log_err (LOGD_DHCP, "%s:%d (%s): assert return: %s", (""file), (line), (func), G_STRINGIFY (e)); \
+} G_STMT_END
 
 #define log_oom nm_log_err(LOGD_CORE, "%s:%s/%s: OOM", __FILE__, __LINE__, __func__)
 
diff --git a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-client.c b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-client.c
index 6c5a6ab5..6754fe19 100644
--- a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-client.c
@@ -285,6 +285,11 @@ static void client_notify(sd_dhcp6_client *client, int event) {
 static int client_reset(sd_dhcp6_client *client) {
         assert_return(client, -EINVAL);
 
+	if (client->lease) {
+		dhcp6_lease_clear_timers(&client->lease->ia);
+		client->lease = sd_dhcp6_lease_unref(client->lease);
+	}
+
         client->receive_message =
                 sd_event_source_unref(client->receive_message);
 
@@ -828,7 +833,10 @@ static int client_receive_advertise(sd_dhcp6_client *client,
 
         r = dhcp6_lease_get_preference(client->lease, &pref_lease);
         if (!client->lease || r < 0 || pref_advertise > pref_lease) {
-                sd_dhcp6_lease_unref(client->lease);
+                if (client->lease) {
+                        dhcp6_lease_clear_timers(&client->lease->ia);
+                        sd_dhcp6_lease_unref(client->lease);
+                }
                 client->lease = lease;
                 lease = NULL;
                 r = 0;
diff --git a/src/dhcp-manager/systemd-dhcp/src/shared/macro.h b/src/dhcp-manager/systemd-dhcp/src/shared/macro.h
index e6cf6eec..bdda4dce 100644
--- a/src/dhcp-manager/systemd-dhcp/src/shared/macro.h
+++ b/src/dhcp-manager/systemd-dhcp/src/shared/macro.h
@@ -46,6 +46,7 @@
 #define _alignas_(x) __attribute__((aligned(__alignof(x))))
 #define _cleanup_(x) __attribute__((cleanup(x)))
 
+#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined (__clang__)
 /* Temporarily disable some warnings */
 #define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT                     \
         _Pragma("GCC diagnostic push");                                 \
@@ -69,6 +70,14 @@
 
 #define REENABLE_WARNING                                                \
         _Pragma("GCC diagnostic pop")
+#else
+#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT
+#define DISABLE_WARNING_FORMAT_NONLITERAL
+#define DISABLE_WARNING_MISSING_PROTOTYPES
+#define DISABLE_WARNING_NONNULL
+#define DISABLE_WARNING_SHADOW
+#define REENABLE_WARNING
+#endif
 
 /* automake test harness */
 #define EXIT_TEST_SKIP 77
diff --git a/src/dhcp-manager/tests/Makefile.am b/src/dhcp-manager/tests/Makefile.am
index 8aa79a29..4c4c7e81 100644
--- a/src/dhcp-manager/tests/Makefile.am
+++ b/src/dhcp-manager/tests/Makefile.am
@@ -1,5 +1,6 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I${top_builddir}/include \
 	-I${top_srcdir}/libnm-core \
 	-I${top_builddir}/libnm-core \
 	-I$(top_srcdir)/src/dhcp-manager \
diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in
index 6125aea8..c98dbd5f 100644
--- a/src/dhcp-manager/tests/Makefile.in
+++ b/src/dhcp-manager/tests/Makefile.in
@@ -516,6 +516,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -658,6 +659,7 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I${top_builddir}/include \
 	-I${top_srcdir}/libnm-core \
 	-I${top_builddir}/libnm-core \
 	-I$(top_srcdir)/src/dhcp-manager \
diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c
index a85631bc..0cc698d9 100644
--- a/src/dnsmasq-manager/nm-dnsmasq-manager.c
+++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c
@@ -203,6 +203,7 @@ dm_watch_cb (GPid pid, gint status, gpointer user_data)
 	}
   
 	priv->pid = 0;
+	priv->dm_watch_id = 0;
 
 	g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_DNSMASQ_STATUS_DEAD);
 }
diff --git a/src/dnsmasq-manager/tests/Makefile.am b/src/dnsmasq-manager/tests/Makefile.am
index b51de6aa..e9200007 100644
--- a/src/dnsmasq-manager/tests/Makefile.am
+++ b/src/dnsmasq-manager/tests/Makefile.am
@@ -1,5 +1,6 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I${top_builddir}/include \
 	-I${top_srcdir}/libnm-core \
 	-I${top_builddir}/libnm-core \
 	-I$(top_srcdir)/src/dnsmasq-manager \
diff --git a/src/dnsmasq-manager/tests/Makefile.in b/src/dnsmasq-manager/tests/Makefile.in
index 8e6bb12e..fb2cd1d1 100644
--- a/src/dnsmasq-manager/tests/Makefile.in
+++ b/src/dnsmasq-manager/tests/Makefile.in
@@ -510,6 +510,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -652,6 +653,7 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I${top_builddir}/include \
 	-I${top_srcdir}/libnm-core \
 	-I${top_builddir}/libnm-core \
 	-I$(top_srcdir)/src/dnsmasq-manager \
diff --git a/src/main.c b/src/main.c
index 495262ef..53d2cf64 100644
--- a/src/main.c
+++ b/src/main.c
@@ -72,6 +72,7 @@ static gboolean configure_and_quit = FALSE;
 
 static struct {
 	gboolean show_version;
+	gboolean print_config;
 	gboolean become_daemon;
 	gboolean debug;
 	gboolean g_fatal_warnings;
@@ -228,6 +229,28 @@ manager_configure_quit (NMManager *manager, gpointer user_data)
 	configure_and_quit = TRUE;
 }
 
+static int
+print_config (NMConfigCmdLineOptions *config_cli)
+{
+	gs_unref_object NMConfig *config = NULL;
+	gs_free_error GError *error = NULL;
+	NMConfigData *config_data;
+
+	nm_logging_setup ("OFF", "ALL", NULL, NULL);
+
+	config = nm_config_new (config_cli, &error);
+	if (config == NULL) {
+		fprintf (stderr, _("Failed to read configuration: %s\n"),
+		         (error && error->message) ? error->message : _("unknown"));
+		return 7;
+	}
+
+	config_data = nm_config_get_data (config);
+	fprintf (stdout, "# NetworkManager configuration: %s\n", nm_config_data_get_config_description (config_data));
+	nm_config_data_log (config_data, "", "", stdout);
+	return 0;
+}
+
 static void
 do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli)
 {
@@ -243,10 +266,10 @@ do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli)
 		{ "pid-file", 'p', 0, G_OPTION_ARG_FILENAME, &global_opt.pidfile, N_("Specify the location of a PID file"), N_(NM_DEFAULT_PID_FILE) },
 		{ "state-file", 0, 0, G_OPTION_ARG_FILENAME, &global_opt.state_file, N_("State file location"), N_(NM_DEFAULT_SYSTEM_STATE_FILE) },
 		{ "run-from-build-dir", 0, 0, G_OPTION_ARG_NONE, &global_opt.run_from_build_dir, "Run from build directory", NULL },
+		{ "print-config", 0, 0, G_OPTION_ARG_NONE, &global_opt.print_config, N_("Print NetworkManager configuration and exit"), NULL },
 		{NULL}
 	};
 
-	config_cli = nm_config_cmd_line_options_new ();
 	if (!nm_main_utils_early_setup ("NetworkManager",
 	                                argc,
 	                                argv,
@@ -302,6 +325,14 @@ main (int argc, char *argv[])
 		exit (0);
 	}
 
+	if (global_opt.print_config) {
+		int result;
+
+		result = print_config (config_cli);
+		nm_config_cmd_line_options_free (config_cli);
+		exit (result);
+	}
+
 	nm_main_utils_ensure_root ();
 
 	nm_main_utils_ensure_not_running_pidfile (global_opt.pidfile);
@@ -423,7 +454,7 @@ main (int argc, char *argv[])
 	dbus_glib_global_set_disable_legacy_property_access ();
 
 	nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config)));
-	nm_config_data_log (nm_config_get_data (config), "CONFIG: ");
+	nm_config_data_log (nm_config_get_data (config), "CONFIG: ", "  ", NULL);
 	nm_log_dbg (LOGD_CORE, "WEXT support is %s",
 #if HAVE_WEXT
 	             "enabled"
diff --git a/src/nm-agent-manager-glue.h b/src/nm-agent-manager-glue.h
index 6e884c8a..e6431f53 100644
--- a/src/nm-agent-manager-glue.h
+++ b/src/nm-agent-manager-glue.h
@@ -79,9 +79,9 @@ dbus_glib_marshal_nm_agent_manager_VOID__STRING_UINT_POINTER (GClosure     *clos
                                                           guint        arg_2,
                                                           gpointer     arg_3,
                                                           gpointer     data2);
-  register GMarshalFunc_VOID__STRING_UINT_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__STRING_UINT_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 4);
 
@@ -124,9 +124,9 @@ dbus_glib_marshal_nm_agent_manager_VOID__STRING_POINTER (GClosure     *closure,
                                                      gpointer     arg_1,
                                                      gpointer     arg_2,
                                                      gpointer     data2);
-  register GMarshalFunc_VOID__STRING_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__STRING_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
diff --git a/src/nm-config-data.c b/src/nm-config-data.c
index dc20064b..ffe00ec2 100644
--- a/src/nm-config-data.c
+++ b/src/nm-config-data.c
@@ -292,22 +292,34 @@ _nm_config_data_log_sort (const char **pa, const char **pb, gpointer dummy)
 }
 
 void
-nm_config_data_log (const NMConfigData *self, const char *prefix)
+nm_config_data_log (const NMConfigData *self,
+                    const char *prefix,
+                    const char *key_prefix,
+                    /* FILE* */ gpointer print_stream)
 {
 	NMConfigDataPrivate *priv;
 	gs_strfreev char **groups = NULL;
 	gsize ngroups;
 	guint g, k;
+	FILE *stream = print_stream;
 
 	g_return_if_fail (NM_IS_CONFIG_DATA (self));
 
-	if (!nm_logging_enabled (LOGL_DEBUG, LOGD_CORE))
+	if (!stream && !nm_logging_enabled (LOGL_DEBUG, LOGD_CORE))
 		return;
 
 	if (!prefix)
 		prefix = "";
+	if (!key_prefix)
+		key_prefix = "";
 
-#define _LOG(...) _nm_log (LOGL_DEBUG, LOGD_CORE, 0, "%s"_NM_UTILS_MACRO_FIRST(__VA_ARGS__), prefix _NM_UTILS_MACRO_REST (__VA_ARGS__))
+#define _LOG(stream, prefix, ...) \
+	G_STMT_START { \
+		if (!stream) \
+			_nm_log (LOGL_DEBUG, LOGD_CORE, 0, "%s"_NM_UTILS_MACRO_FIRST(__VA_ARGS__)"%s", prefix _NM_UTILS_MACRO_REST (__VA_ARGS__), ""); \
+		else \
+			fprintf (stream, "%s"_NM_UTILS_MACRO_FIRST(__VA_ARGS__)"%s", prefix _NM_UTILS_MACRO_REST (__VA_ARGS__), "\n"); \
+	} G_STMT_END
 
 	priv = NM_CONFIG_DATA_GET_PRIVATE (self);
 
@@ -322,14 +334,15 @@ nm_config_data_log (const NMConfigData *self, const char *prefix)
 		                   NULL);
 	}
 
-	_LOG ("config-data[%p]: %lu groups", self, (unsigned long) ngroups);
+	if (!stream)
+		_LOG (stream, prefix, "config-data[%p]: %lu groups", self, (unsigned long) ngroups);
 
 	for (g = 0; g < ngroups; g++) {
 		const char *group = groups[g];
 		gs_strfreev char **keys = NULL;
 
-		_LOG ("");
-		_LOG ("[%s]", group);
+		_LOG (stream, prefix, "");
+		_LOG (stream, prefix, "[%s]", group);
 
 		keys = g_key_file_get_keys (priv->keyfile, group, NULL, NULL);
 		for (k = 0; keys && keys[k]; k++) {
@@ -337,7 +350,7 @@ nm_config_data_log (const NMConfigData *self, const char *prefix)
 			gs_free char *value = NULL;
 
 			value = g_key_file_get_value (priv->keyfile, group, key, NULL);
-			_LOG ("  %s=%s", key, value);
+			_LOG (stream, prefix, "%s%s=%s", key_prefix, key, value);
 		}
 	}
 
diff --git a/src/nm-config-data.h b/src/nm-config-data.h
index cc7f95e2..73e789bd 100644
--- a/src/nm-config-data.h
+++ b/src/nm-config-data.h
@@ -97,7 +97,10 @@ NMConfigData *nm_config_data_new_update_no_auto_default (const NMConfigData *bas
 
 NMConfigChangeFlags nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data);
 
-void nm_config_data_log (const NMConfigData *config_data, const char *prefix);
+void nm_config_data_log (const NMConfigData *self,
+                               const char *prefix,
+                               const char *key_prefix,
+                               /* FILE* */ gpointer print_stream);
 
 const char *nm_config_data_get_config_main_file (const NMConfigData *config_data);
 const char *nm_config_data_get_config_description (const NMConfigData *config_data);
diff --git a/src/nm-config.c b/src/nm-config.c
index 86b3d929..561d80c1 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -1028,7 +1028,7 @@ _set_config_data (NMConfig *self, NMConfigData *new_data, int signal)
 	if (new_data) {
 		nm_log_info (LOGD_CORE, "config: update %s (%s)", nm_config_data_get_config_description (new_data),
 		             (log_str = nm_config_change_flags_to_string (changes)));
-		nm_config_data_log (new_data, "CONFIG: ");
+		nm_config_data_log (new_data, "CONFIG: ", "  ", NULL);
 		priv->config_data = new_data;
 	} else if (had_new_data)
 		nm_log_info (LOGD_CORE, "config: signal %s (no changes from disk)", (log_str = nm_config_change_flags_to_string (changes)));
@@ -1212,9 +1212,19 @@ nm_config_class_init (NMConfigClass *config_class)
 	    g_signal_new (NM_CONFIG_SIGNAL_CONFIG_CHANGED,
 	                  G_OBJECT_CLASS_TYPE (object_class),
 	                  G_SIGNAL_RUN_FIRST,
-	                  G_STRUCT_OFFSET (NMConfigClass, config_changed),
+	                  0,
 	                  NULL, NULL, NULL,
-	                  G_TYPE_NONE, 3, NM_TYPE_CONFIG_DATA, NM_TYPE_CONFIG_CHANGE_FLAGS, NM_TYPE_CONFIG_DATA);
+	                  G_TYPE_NONE,
+	                  3,
+	                  NM_TYPE_CONFIG_DATA,
+	                  /* Use plain guint type for changes argument. This avoids
+	                   * glib/ffi bug https://bugzilla.redhat.com/show_bug.cgi?id=1260577 */
+	                  /* NM_TYPE_CONFIG_CHANGE_FLAGS, */
+	                  G_TYPE_UINT,
+	                  NM_TYPE_CONFIG_DATA);
+
+	G_STATIC_ASSERT_EXPR (sizeof (guint) == sizeof (NMConfigChangeFlags));
+	G_STATIC_ASSERT_EXPR (((gint64) ((NMConfigChangeFlags) -1)) > ((gint64) 0));
 }
 
 static void
diff --git a/src/nm-config.h b/src/nm-config.h
index 5b096f16..5d65e7a9 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -71,9 +71,6 @@ struct _NMConfig {
 
 typedef struct {
 	GObjectClass parent;
-
-	/* Signals */
-	void (*config_changed) (NMConfig *config, GHashTable *changes, NMConfigData *old_data);
 } NMConfigClass;
 
 GType nm_config_get_type (void);
diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c
index 96a8c855..c5b2e408 100644
--- a/src/nm-default-route-manager.c
+++ b/src/nm-default-route-manager.c
@@ -78,27 +78,51 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get,
         const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \
         \
         if (nm_logging_enabled (__level, __domain)) { \
-            char __ch = __addr_family == AF_INET ? '4' : (__addr_family == AF_INET6 ? '6' : '-'); \
-            char __prefix[30] = _NMLOG_PREFIX_NAME; \
+            char __prefix_buf[100]; \
             \
-            if ((self) != singleton_instance) \
-                g_snprintf (__prefix, sizeof (__prefix), ""_NMLOG_PREFIX_NAME"%c[%p]", __ch, (self)); \
-            else \
-                __prefix[STRLEN (_NMLOG_PREFIX_NAME)] = __ch; \
             _nm_log (__level, __domain, 0, \
                      "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
-                     __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+                     self != singleton_instance \
+                        ? nm_sprintf_buf (__prefix_buf, "%s%c[%p]", \
+                                          _NMLOG2_PREFIX_NAME, \
+                                          __addr_family == AF_INET ? '4' : (__addr_family == AF_INET6 ? '6' : '-'), \
+                                          self) \
+                        : _NMLOG2_PREFIX_NAME \
+                     _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
         } \
     } G_STMT_END
 
-#define LOG_ENTRY_FMT  "entry[%u/%s:%p:%s:%c:%csync]"
-#define LOG_ENTRY_ARGS(entry_idx, entry) \
-		(entry_idx), \
-		NM_IS_DEVICE ((entry)->source.pointer) ? "dev" : "vpn", \
-		(entry)->source.pointer, \
-		NM_IS_DEVICE ((entry)->source.pointer) ? nm_device_get_iface ((entry)->source.device) : nm_vpn_connection_get_connection_id ((entry)->source.vpn), \
-		((entry)->never_default ? '0' : '1'), \
-		((entry)->synced ? '+' : '-')
+#define _NMLOG2_PREFIX_NAME   _NMLOG_PREFIX_NAME
+#undef  _NMLOG2_ENABLED
+#define _NMLOG2_ENABLED       _NMLOG_ENABLED
+#define _NMLOG2(level, vtable, entry_idx, entry, ...) \
+    G_STMT_START { \
+        const int __addr_family = (vtable)->vt->addr_family; \
+        const NMLogLevel __level = (level); \
+        const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \
+        \
+        if (nm_logging_enabled (__level, __domain)) { \
+            char __prefix_buf[100]; \
+            guint __entry_idx = (entry_idx); \
+            const Entry *const __entry = (entry); \
+            \
+            _nm_log (__level, __domain, 0, \
+                     "%s: entry[%u/%s:%p:%s:%c:%csync]: "_NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
+                     self != singleton_instance \
+                        ? nm_sprintf_buf (__prefix_buf, "%s%c[%p]", \
+                                          _NMLOG2_PREFIX_NAME, \
+                                          __addr_family == AF_INET ? '4' : (__addr_family == AF_INET6 ? '6' : '-'), \
+                                          self) \
+                        : _NMLOG2_PREFIX_NAME, \
+                     __entry_idx, \
+                     NM_IS_DEVICE (__entry->source.pointer) ? "dev" : "vpn", \
+                     __entry->source.pointer, \
+                     NM_IS_DEVICE (__entry->source.pointer) ? nm_device_get_iface (__entry->source.device) : nm_vpn_connection_get_connection_id (__entry->source.vpn), \
+                     (__entry->never_default ? '0' : '1'), \
+                     (__entry->synced ? '+' : '-') \
+                     _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+        } \
+    } G_STMT_END
 
 /***********************************************************************************/
 
@@ -552,25 +576,25 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c
 			 * or none. Hence, we only have to remember what is going to change. */
 			g_array_append_val (changed_metrics, expected_metric);
 			if (old_entry) {
-				_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": sync:update %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
-				       vtable->vt->route_to_string (&entry->route), (guint) old_entry->effective_metric,
-				       (guint) expected_metric);
+				_LOG2D (vtable, i, entry, "sync:update %s (%u -> %u)",
+				        vtable->vt->route_to_string (&entry->route), (guint) old_entry->effective_metric,
+				        (guint) expected_metric);
 			} else {
-				_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": sync:add    %s (%u)", LOG_ENTRY_ARGS (i, entry),
-				       vtable->vt->route_to_string (&entry->route), (guint) expected_metric);
+				_LOG2D (vtable, i, entry, "sync:add    %s (%u)",
+				        vtable->vt->route_to_string (&entry->route), (guint) expected_metric);
 			}
 		} else if (entry->effective_metric != expected_metric) {
 			g_array_append_val (changed_metrics, entry->effective_metric);
 			g_array_append_val (changed_metrics, expected_metric);
-			_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": sync:metric %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
-			       vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric,
-			       (guint) expected_metric);
+			_LOG2D (vtable, i, entry, "sync:metric %s (%u -> %u)",
+			        vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric,
+			        (guint) expected_metric);
 		} else {
 			if (!_vt_routes_has_entry (vtable, routes, entry)) {
 				g_array_append_val (changed_metrics, entry->effective_metric);
-				_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": sync:re-add %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
-				       vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric,
-				       (guint) entry->effective_metric);
+				_LOG2D (vtable, i, entry, "sync:re-add %s (%u -> %u)",
+				        vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric,
+				        (guint) entry->effective_metric);
 			}
 		}
 
@@ -633,11 +657,10 @@ _entry_at_idx_update (const VTableIP *vtable, NMDefaultRouteManager *self, guint
 	if (!entry->synced && !entry->never_default)
 		entry->effective_metric = entry->route.rx.metric;
 
-	_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": %s %s (%"G_GUINT32_FORMAT")",
-	       LOG_ENTRY_ARGS (entry_idx, entry),
-	       old_entry ? "record:update" : "record:add   ",
-	       vtable->vt->route_to_string (&entry->route),
-	       entry->effective_metric);
+	_LOG2D (vtable, entry_idx, entry, "%s %s (%"G_GUINT32_FORMAT")",
+	        old_entry ? "record:update" : "record:add   ",
+	        vtable->vt->route_to_string (&entry->route),
+	        entry->effective_metric);
 
 	g_ptr_array_sort_with_data (entries, _sort_entries_cmp, NULL);
 
@@ -657,8 +680,8 @@ _entry_at_idx_remove (const VTableIP *vtable, NMDefaultRouteManager *self, guint
 
 	entry = g_ptr_array_index (entries, entry_idx);
 
-	_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": record:remove %s (%u)", LOG_ENTRY_ARGS (entry_idx, entry),
-	       vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric);
+	_LOG2D (vtable, entry_idx, entry, "record:remove %s (%u)",
+	        vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric);
 
 	/* Remove the entry from the list (but don't free it yet) */
 	g_ptr_array_index (entries, entry_idx) = NULL;
@@ -718,9 +741,8 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self,
 	if (   entry
 	    && entry->route.rx.ifindex != ip_ifindex) {
 		/* Strange... the ifindex changed... Remove the device and start again. */
-		_LOGD (vtable->vt->addr_family, "ifindex of "LOG_ENTRY_FMT" changed: %d -> %d",
-		       LOG_ENTRY_ARGS (entry_idx, entry),
-		       entry->route.rx.ifindex, ip_ifindex);
+		_LOG2D (vtable, entry_idx, entry, "ifindex changed: %d -> %d",
+		        entry->route.rx.ifindex, ip_ifindex);
 
 		g_object_freeze_notify (G_OBJECT (self));
 		_entry_at_idx_remove (vtable, self, entry_idx);
diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c
index 13352ded..78aa204e 100644
--- a/src/nm-dispatcher.c
+++ b/src/nm-dispatcher.c
@@ -444,10 +444,6 @@ _dispatcher_call (DispatcherAction action,
 		                : (callback ? " (with callback)" : ""));
 	}
 
-	/* VPN actions require at least an IPv4 config (for now) */
-	if (action == DISPATCHER_ACTION_VPN_UP)
-		g_return_val_if_fail (vpn_ip4_config != NULL, FALSE);
-
 	if (!_get_monitor_by_action(action)->has_scripts) {
 		if (blocking == FALSE && (out_call_id || callback)) {
 			info = g_malloc0 (sizeof (*info));
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 9647268d..ef256231 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -635,8 +635,10 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
 		nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i));
 
 	/* nameservers */
-	for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++)
-		nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
+	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+		for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++)
+			nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
+	}
 
 	/* default gateway */
 	if (nm_ip6_config_get_gateway (src))
diff --git a/src/nm-logging.c b/src/nm-logging.c
index fa770344..b8433a25 100644
--- a/src/nm-logging.c
+++ b/src/nm-logging.c
@@ -381,8 +381,11 @@ _nm_log_impl (const char *file,
 		return;
 
 	/* Make sure that %m maps to the specified error */
-	if (error != 0)
+	if (error != 0) {
+		if (error < 0)
+			error = -error;
 		errno = error;
+	}
 
 	va_start (args, fmt);
 	msg = g_strdup_vprintf (fmt, args);
diff --git a/src/nm-logging.h b/src/nm-logging.h
index 40218062..077209f9 100644
--- a/src/nm-logging.h
+++ b/src/nm-logging.h
@@ -173,27 +173,59 @@ void     nm_logging_syslog_closelog  (void);
  * might want to undef this and redefine it. */
 #define _NMLOG_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG_DOMAIN)) )
 
-#define _LOGt(...)          _NMLOG (LOGL_TRACE, __VA_ARGS__)
+#define _LOGT(...)          _NMLOG (LOGL_TRACE, __VA_ARGS__)
 #define _LOGD(...)          _NMLOG (LOGL_DEBUG, __VA_ARGS__)
 #define _LOGI(...)          _NMLOG (LOGL_INFO , __VA_ARGS__)
 #define _LOGW(...)          _NMLOG (LOGL_WARN , __VA_ARGS__)
 #define _LOGE(...)          _NMLOG (LOGL_ERR  , __VA_ARGS__)
 
-#define _LOGt_ENABLED(...)  _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
+#define _LOGT_ENABLED(...)  _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
 #define _LOGD_ENABLED(...)  _NMLOG_ENABLED (LOGL_DEBUG, ##__VA_ARGS__)
 #define _LOGI_ENABLED(...)  _NMLOG_ENABLED (LOGL_INFO , ##__VA_ARGS__)
 #define _LOGW_ENABLED(...)  _NMLOG_ENABLED (LOGL_WARN , ##__VA_ARGS__)
 #define _LOGE_ENABLED(...)  _NMLOG_ENABLED (LOGL_ERR  , ##__VA_ARGS__)
 
-/* _LOGt() and _LOGT() both log with level TRACE, but the latter is disabled by default,
+/* _LOGT() and _LOGt() both log with level TRACE, but the latter is disabled by default,
  * unless building with --with-more-logging. */
 #ifdef NM_MORE_LOGGING
-#define _LOGT_ENABLED(...)  _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
-#define _LOGT(...)          _NMLOG (LOGL_TRACE, __VA_ARGS__)
+#define _LOGt_ENABLED(...)  _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
+#define _LOGt(...)          _NMLOG (LOGL_TRACE, __VA_ARGS__)
+#else
+/* still call the logging macros to get compile time checks, but they will be optimized out. */
+#define _LOGt_ENABLED(...)  ( FALSE && (_NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) )
+#define _LOGt(...)          G_STMT_START { if (FALSE) { _NMLOG (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
+#endif
+
+/*****************************************************************************/
+
+/* Some implementation define a second set of logging macros, for a separate
+ * use. As with the _LOGD() macro familiy above, the exact implementation
+ * depends on the file that uses them.
+ * Still, it encourages a common pattern to have the common set of macros
+ * like _LOG2D(), _LOG2I(), etc. and have _LOG2t() which by default
+ * is disabled at compile time. */
+
+#define _NMLOG2_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG2_DOMAIN)) )
+
+#define _LOG2T(...)          _NMLOG2 (LOGL_TRACE, __VA_ARGS__)
+#define _LOG2D(...)          _NMLOG2 (LOGL_DEBUG, __VA_ARGS__)
+#define _LOG2I(...)          _NMLOG2 (LOGL_INFO , __VA_ARGS__)
+#define _LOG2W(...)          _NMLOG2 (LOGL_WARN , __VA_ARGS__)
+#define _LOG2E(...)          _NMLOG2 (LOGL_ERR  , __VA_ARGS__)
+
+#define _LOG2T_ENABLED(...)  _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
+#define _LOG2D_ENABLED(...)  _NMLOG2_ENABLED (LOGL_DEBUG, ##__VA_ARGS__)
+#define _LOG2I_ENABLED(...)  _NMLOG2_ENABLED (LOGL_INFO , ##__VA_ARGS__)
+#define _LOG2W_ENABLED(...)  _NMLOG2_ENABLED (LOGL_WARN , ##__VA_ARGS__)
+#define _LOG2E_ENABLED(...)  _NMLOG2_ENABLED (LOGL_ERR  , ##__VA_ARGS__)
+
+#ifdef NM_MORE_LOGGING
+#define _LOG2t_ENABLED(...)  _NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)
+#define _LOG2t(...)          _NMLOG2 (LOGL_TRACE, __VA_ARGS__)
 #else
-/* still call the logging macros to get compile time checks, but they will be optimize out. */
-#define _LOGT_ENABLED(...)  ( FALSE && (_NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) )
-#define _LOGT(...)          G_STMT_START { if (FALSE) { _NMLOG (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
+/* still call the logging macros to get compile time checks, but they will be optimized out. */
+#define _LOG2t_ENABLED(...)  ( FALSE && (_NMLOG2_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) )
+#define _LOG2t(...)          G_STMT_START { if (FALSE) { _NMLOG2 (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END
 #endif
 
 /*****************************************************************************/
diff --git a/src/nm-manager-glue.h b/src/nm-manager-glue.h
index f7840c9f..37a6cf1f 100644
--- a/src/nm-manager-glue.h
+++ b/src/nm-manager-glue.h
@@ -74,9 +74,9 @@ dbus_glib_marshal_nm_manager_VOID__BOXED_POINTER (GClosure     *closure,
                                                     gpointer     arg_1,
                                                     gpointer     arg_2,
                                                     gpointer     data2);
-  register GMarshalFunc_VOID__BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__BOXED_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
@@ -118,9 +118,9 @@ dbus_glib_marshal_nm_manager_VOID__BOOLEAN_POINTER (GClosure     *closure,
                                                       gboolean     arg_1,
                                                       gpointer     arg_2,
                                                       gpointer     data2);
-  register GMarshalFunc_VOID__BOOLEAN_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__BOOLEAN_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
@@ -168,9 +168,9 @@ dbus_glib_marshal_nm_manager_VOID__BOXED_BOXED_BOXED_POINTER (GClosure     *clos
                                                                 gpointer     arg_3,
                                                                 gpointer     arg_4,
                                                                 gpointer     data2);
-  register GMarshalFunc_VOID__BOXED_BOXED_BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__BOXED_BOXED_BOXED_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 5);
 
@@ -215,9 +215,9 @@ dbus_glib_marshal_nm_manager_VOID__STRING_STRING_POINTER (GClosure     *closure,
                                                             gpointer     arg_2,
                                                             gpointer     arg_3,
                                                             gpointer     data2);
-  register GMarshalFunc_VOID__STRING_STRING_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__STRING_STRING_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 4);
 
@@ -261,9 +261,9 @@ dbus_glib_marshal_nm_manager_BOOLEAN__STRING_POINTER_POINTER (GClosure     *clos
                                                                     gpointer     arg_2,
                                                                     gpointer     arg_3,
                                                                     gpointer     data2);
-  register GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
@@ -309,9 +309,9 @@ dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER (GClosure     *closure,
                                                              gpointer     arg_1,
                                                              gpointer     arg_2,
                                                              gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
@@ -357,9 +357,9 @@ dbus_glib_marshal_nm_manager_BOOLEAN__POINTER_POINTER_POINTER (GClosure     *clo
                                                                      gpointer     arg_2,
                                                                      gpointer     arg_3,
                                                                      gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_BOOLEAN__POINTER_POINTER_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 34ec0819..cc52ea78 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -853,6 +853,14 @@ device_removed_cb (NMDevice *device, gpointer user_data)
 }
 
 static void
+device_link_initialized_cb (NMDevice *device, gpointer user_data)
+{
+	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (user_data);
+
+	nm_settings_device_added (priv->settings, device);
+}
+
+static void
 aipd_handle_event (DBusGProxy *proxy,
                    const char *event,
                    const char *iface,
@@ -1813,6 +1821,10 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
 	                  G_CALLBACK (device_removed_cb),
 	                  self);
 
+	g_signal_connect (device, NM_DEVICE_LINK_INITIALIZED,
+	                  G_CALLBACK (device_link_initialized_cb),
+	                  self);
+
 	g_signal_connect (device, "notify::" NM_DEVICE_IP_IFACE,
 	                  G_CALLBACK (device_ip_iface_changed),
 	                  self);
@@ -1871,6 +1883,9 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
 		                         NM_DEVICE_STATE_REASON_NOW_MANAGED);
 	}
 
+	/* Try to generate a default connection. If this fails because the link is
+	 * not initialized, we will retry again in device_link_initialized_cb().
+	 */
 	nm_settings_device_added (priv->settings, device);
 	g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
 	g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES);
@@ -2073,20 +2088,24 @@ nm_manager_get_connection_device (NMManager *self,
 
 static NMDevice *
 nm_manager_get_best_device_for_connection (NMManager *self,
-                                           NMConnection *connection)
+                                           NMConnection *connection,
+                                           gboolean for_user_request)
 {
 	const GSList *devices, *iter;
 	NMDevice *act_device = nm_manager_get_connection_device (self, connection);
+	NMDeviceCheckConAvailableFlags flags;
 
 	if (act_device)
 		return act_device;
 
+	flags = for_user_request ? NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST : NM_DEVICE_CHECK_CON_AVAILABLE_NONE;
+
 	/* Pick the first device that's compatible with the connection. */
 	devices = nm_manager_get_devices (self);
 	for (iter = devices; iter; iter = g_slist_next (iter)) {
 		NMDevice *device = NM_DEVICE (iter->data);
 
-		if (nm_device_check_connection_available (device, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL))
+		if (nm_device_check_connection_available (device, connection, flags, NULL))
 			return device;
 	}
 
@@ -2566,7 +2585,7 @@ autoconnect_slaves (NMManager *manager,
 			nm_manager_activate_connection (manager,
 			                                slave_connection,
 			                                NULL,
-			                                nm_manager_get_best_device_for_connection (manager, slave_connection),
+			                                nm_manager_get_best_device_for_connection (manager, slave_connection, FALSE),
 			                                subject,
 			                                &local_err);
 			if (local_err) {
@@ -3077,7 +3096,7 @@ validate_activation_request (NMManager *self,
 			goto error;
 		}
 	} else
-		device = nm_manager_get_best_device_for_connection (self, connection);
+		device = nm_manager_get_best_device_for_connection (self, connection, TRUE);
 
 	if (!device) {
 		gboolean is_software = nm_connection_is_virtual (connection);
@@ -5100,7 +5119,16 @@ dispose (GObject *object)
 		g_clear_object (&priv->policy);
 	}
 
-	g_clear_object (&priv->settings);
+	if (priv->settings) {
+		g_signal_handlers_disconnect_by_func (priv->settings, settings_startup_complete_changed, manager);
+		g_signal_handlers_disconnect_by_func (priv->settings, system_unmanaged_devices_changed_cb, manager);
+		g_signal_handlers_disconnect_by_func (priv->settings, system_hostname_changed_cb, manager);
+		g_signal_handlers_disconnect_by_func (priv->settings, connection_added, manager);
+		g_signal_handlers_disconnect_by_func (priv->settings, connection_changed, manager);
+		g_signal_handlers_disconnect_by_func (priv->settings, connection_removed, manager);
+		g_clear_object (&priv->settings);
+	}
+
 	g_free (priv->state_file);
 	g_clear_object (&priv->vpn_manager);
 
@@ -5128,6 +5156,11 @@ dispose (GObject *object)
 		g_clear_object (&priv->fw_monitor);
 	}
 
+	if (priv->rfkill_mgr) {
+		g_signal_handlers_disconnect_by_func (priv->rfkill_mgr, rfkill_manager_rfkill_changed_cb, manager);
+		g_clear_object (&priv->rfkill_mgr);
+	}
+
 	nm_device_factory_manager_for_each_factory (_deinit_device_factory, manager);
 	
 	if (priv->timestamp_update_id) {
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 8a573c8b..1be5c4a3 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -754,17 +754,21 @@ process_secondaries (NMPolicy *policy,
                      gboolean connected)
 {
 	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
-	GSList *iter, *iter2;
+	GSList *iter, *iter2, *next, *next2;
 
 	/* Loop through devices waiting for secondary connections to activate */
-	for (iter = priv->pending_secondaries; iter; iter = g_slist_next (iter)) {
+	for (iter = priv->pending_secondaries; iter; iter = next) {
 		PendingSecondaryData *secondary_data = (PendingSecondaryData *) iter->data;
 		NMDevice *item_device = secondary_data->device;
 
+		next = g_slist_next (iter);
+
 		/* Look for 'active' in each device's secondary connections list */
-		for (iter2 = secondary_data->secondaries; iter2; iter2 = g_slist_next (iter2)) {
+		for (iter2 = secondary_data->secondaries; iter2; iter2 = next2) {
 			NMActiveConnection *secondary_active = NM_ACTIVE_CONNECTION (iter2->data);
 
+			next2 = g_slist_next (iter2);
+
 			if (active != secondary_active)
 				continue;
 
diff --git a/src/nm-ppp-manager-glue.h b/src/nm-ppp-manager-glue.h
index c3ba2ee4..5aea527e 100644
--- a/src/nm-ppp-manager-glue.h
+++ b/src/nm-ppp-manager-glue.h
@@ -78,9 +78,9 @@ dbus_glib_marshal_nm_ppp_manager_BOOLEAN__UINT_POINTER (GClosure     *closure,
                                                           guint        arg_1,
                                                           gpointer     arg_2,
                                                           gpointer     data2);
-  register GMarshalFunc_BOOLEAN__UINT_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_BOOLEAN__UINT_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
@@ -125,9 +125,9 @@ dbus_glib_marshal_nm_ppp_manager_BOOLEAN__BOXED_POINTER (GClosure     *closure,
                                                            gpointer     arg_1,
                                                            gpointer     arg_2,
                                                            gpointer     data2);
-  register GMarshalFunc_BOOLEAN__BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_BOOLEAN__BOXED_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index b392fc17..bb21384e 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -465,13 +465,13 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
 	ASSERT_route_index_valid (vtable, known_routes, known_routes_idx, FALSE);
 
 	_LOGD (vtable->vt->addr_family, "%3d: sync %u IPv%c routes", ifindex, known_routes_idx->len, vtable->vt->is_ip4 ? '4' : '6');
-	if (_LOGT_ENABLED (vtable->vt->addr_family)) {
+	if (_LOGt_ENABLED (vtable->vt->addr_family)) {
 		for (i = 0; i < known_routes_idx->len; i++) {
-			_LOGT (vtable->vt->addr_family, "%3d: sync new route #%u: %s",
+			_LOGt (vtable->vt->addr_family, "%3d: sync new route #%u: %s",
 			       ifindex, i, vtable->vt->route_to_string (VTABLE_ROUTE_INDEX (vtable, known_routes, i)));
 		}
 		for (i = 0; i < ipx_routes->index->len; i++)
-			_LOGT (vtable->vt->addr_family, "%3d: STATE: has     #%u - %s (%lld)",
+			_LOGt (vtable->vt->addr_family, "%3d: STATE: has     #%u - %s (%lld)",
 			       ifindex, i,
 			       vtable->vt->route_to_string (ipx_routes->index->entries[i]),
 			       (long long) g_array_index (ipx_routes->effective_metrics, gint64, i));
@@ -513,7 +513,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
 				cur_ipx_route->rx.ifindex = ifindex;
 				cur_ipx_route->rx.metric = vtable->vt->metric_normalize (cur_ipx_route->rx.metric);
 				ipx_routes_changed = TRUE;
-				_LOGT (vtable->vt->addr_family, "%3d: STATE: update  #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route));
+				_LOGt (vtable->vt->addr_family, "%3d: STATE: update  #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route));
 			}
 		} else if (cur_known_route) {
 			g_assert (!cur_ipx_route || route_id_cmp_result > 0);
@@ -571,7 +571,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
 			    && cur_plat_route->rx.metric == *p_effective_metric) {
 				/* we are about to delete cur_ipx_route and we have a matching route
 				 * in platform. Delete it. */
-				_LOGT (vtable->vt->addr_family, "%3d: platform rt-rm #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route));
+				_LOGt (vtable->vt->addr_family, "%3d: platform rt-rm #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route));
 				vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route);
 			}
 		}
@@ -583,7 +583,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
 			for (i = 0; i < to_delete_indexes->len; i++) {
 				guint idx = g_array_index (to_delete_indexes, guint, i);
 
-				_LOGT (vtable->vt->addr_family, "%3d: STATE: delete  #%u - %s", ifindex, idx, vtable->vt->route_to_string (ipx_routes->index->entries[idx]));
+				_LOGt (vtable->vt->addr_family, "%3d: STATE: delete  #%u - %s", ifindex, idx, vtable->vt->route_to_string (ipx_routes->index->entries[idx]));
 				g_array_index (to_delete_indexes, guint, i) = _route_index_reverse_idx (vtable, ipx_routes->index, idx, ipx_routes->entries);
 			}
 			g_array_sort (to_delete_indexes, (GCompareFunc) _sort_indexes_cmp);
@@ -607,7 +607,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
 
 				g_array_index (ipx_routes->effective_metrics_reverse, gint64, j++) = -1;
 
-				_LOGT (vtable->vt->addr_family, "%3d: STATE: added   #%u - %s", ifindex, ipx_routes->entries->len - 1, vtable->vt->route_to_string (ipx_route));
+				_LOGt (vtable->vt->addr_family, "%3d: STATE: added   #%u - %s", ifindex, ipx_routes->entries->len - 1, vtable->vt->route_to_string (ipx_route));
 			}
 			g_ptr_array_unref (to_add_routes);
 		}
@@ -692,7 +692,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
 				break;
 			}
 next:
-			_LOGT (vtable->vt->addr_family, "%3d: new metric     #%u - %s (%lld)",
+			_LOGt (vtable->vt->addr_family, "%3d: new metric     #%u - %s (%lld)",
 			       ifindex, i_ipx_routes,
 			       vtable->vt->route_to_string (cur_ipx_route),
 			       (long long) *p_effective_metric);
@@ -717,7 +717,7 @@ next:
 
 			g_assert (cur_plat_route->rx.ifindex == ifindex);
 
-			_LOGT (vtable->vt->addr_family, "%3d: platform rt    #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route));
+			_LOGt (vtable->vt->addr_family, "%3d: platform rt    #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route));
 
 			/* skip over @cur_ipx_route that are ordered before @cur_plat_route */
 			while (   cur_ipx_route
@@ -987,7 +987,7 @@ _ip4_device_routes_idle_cb (IP4DeviceRoutePurgeEntry *entry)
 		return G_SOURCE_REMOVE;
 	}
 
-	_LOGT (vtable_v4.vt->addr_family, "device-route: delete %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+	_LOGt (vtable_v4.vt->addr_family, "device-route: delete %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
 
 	nm_platform_ip4_route_delete (priv->platform,
 	                              entry->obj->ip4_route.ifindex,
@@ -1030,14 +1030,14 @@ _ip4_device_routes_ip4_route_changed (NMPlatform *platform,
 		return;
 
 	if (_ip4_device_routes_entry_expired (entry, nm_utils_get_monotonic_timestamp_ns ())) {
-		_LOGT (vtable_v4.vt->addr_family, "device-route: cleanup-ch %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+		_LOGt (vtable_v4.vt->addr_family, "device-route: cleanup-ch %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
 		g_hash_table_remove (priv->ip4_device_routes.entries, entry->obj);
 		_ip4_device_routes_cancel (self);
 		return;
 	}
 
 	if (entry->idle_id == 0) {
-		_LOGT (vtable_v4.vt->addr_family, "device-route: schedule %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+		_LOGt (vtable_v4.vt->addr_family, "device-route: schedule %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
 		entry->idle_id = g_idle_add ((GSourceFunc) _ip4_device_routes_idle_cb, entry);
 	}
 }
@@ -1050,7 +1050,7 @@ _ip4_device_routes_cancel (NMRouteManager *self)
 	if (priv->ip4_device_routes.gc_id) {
 		if (g_hash_table_size (priv->ip4_device_routes.entries) > 0)
 			return G_SOURCE_CONTINUE;
-		_LOGT (vtable_v4.vt->addr_family, "device-route: cancel");
+		_LOGt (vtable_v4.vt->addr_family, "device-route: cancel");
 		if (priv->platform)
 			g_signal_handlers_disconnect_by_func (priv->platform, G_CALLBACK (_ip4_device_routes_ip4_route_changed), self);
 		nm_clear_g_source (&priv->ip4_device_routes.gc_id);
@@ -1071,7 +1071,7 @@ _ip4_device_routes_gc (NMRouteManager *self)
 	g_hash_table_iter_init (&iter, priv->ip4_device_routes.entries);
 	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &entry)) {
 		if (_ip4_device_routes_entry_expired (entry, now)) {
-			_LOGT (vtable_v4.vt->addr_family, "device-route: cleanup-gc %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+			_LOGt (vtable_v4.vt->addr_family, "device-route: cleanup-gc %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
 			g_hash_table_iter_remove (&iter);
 		}
 	}
@@ -1104,7 +1104,7 @@ nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *sel
 		IP4DeviceRoutePurgeEntry *entry;
 
 		entry = _ip4_device_routes_purge_entry_create (self, &g_array_index (device_route_purge_list, NMPlatformIP4Route, i), now_ns);
-		_LOGT (vtable_v4.vt->addr_family, "device-route: watch (%s) %s",
+		_LOGt (vtable_v4.vt->addr_family, "device-route: watch (%s) %s",
 		                                  g_hash_table_contains (priv->ip4_device_routes.entries, entry->obj)
 		                                      ? "update" : "new",
 		                                  nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
diff --git a/src/nm-settings-connection-glue.h b/src/nm-settings-connection-glue.h
index 23797562..22f096c6 100644
--- a/src/nm-settings-connection-glue.h
+++ b/src/nm-settings-connection-glue.h
@@ -78,9 +78,9 @@ dbus_glib_marshal_nm_settings_connection_VOID__STRING_POINTER (GClosure     *clo
                                                      gpointer     arg_1,
                                                      gpointer     arg_2,
                                                      gpointer     data2);
-  register GMarshalFunc_VOID__STRING_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__STRING_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
@@ -122,9 +122,9 @@ dbus_glib_marshal_nm_settings_connection_VOID__BOXED_POINTER (GClosure     *clos
                                                     gpointer     arg_1,
                                                     gpointer     arg_2,
                                                     gpointer     data2);
-  register GMarshalFunc_VOID__BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__BOXED_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
diff --git a/src/nm-settings-glue.h b/src/nm-settings-glue.h
index 631f4530..d03c4545 100644
--- a/src/nm-settings-glue.h
+++ b/src/nm-settings-glue.h
@@ -78,9 +78,9 @@ dbus_glib_marshal_nm_settings_BOOLEAN__POINTER_POINTER (GClosure     *closure,
                                                              gpointer     arg_1,
                                                              gpointer     arg_2,
                                                              gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
@@ -125,9 +125,9 @@ dbus_glib_marshal_nm_settings_VOID__STRING_POINTER (GClosure     *closure,
                                                      gpointer     arg_1,
                                                      gpointer     arg_2,
                                                      gpointer     data2);
-  register GMarshalFunc_VOID__STRING_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__STRING_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
@@ -169,9 +169,9 @@ dbus_glib_marshal_nm_settings_VOID__BOXED_POINTER (GClosure     *closure,
                                                     gpointer     arg_1,
                                                     gpointer     arg_2,
                                                     gpointer     data2);
-  register GMarshalFunc_VOID__BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
+  GMarshalFunc_VOID__BOXED_POINTER callback;
+  GCClosure *cc = (GCClosure*) closure;
+  gpointer data1, data2;
 
   g_return_if_fail (n_param_values == 3);
 
diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf
index afbcc720..10c6184e 100644
--- a/src/org.freedesktop.NetworkManager.conf
+++ b/src/org.freedesktop.NetworkManager.conf
@@ -27,6 +27,8 @@
                 <allow send_destination="org.freedesktop.NetworkManager.iodine"/>
                 <allow send_destination="org.freedesktop.NetworkManager.l2tp"/>
                 <allow send_destination="org.freedesktop.NetworkManager.libreswan"/>
+                <allow send_destination="org.freedesktop.NetworkManager.fortisslvpn"/>
+                <allow send_destination="org.freedesktop.NetworkManager.strongswan"/>
         </policy>
         <policy context="default">
                 <deny own="org.freedesktop.NetworkManager"/>
diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in
index 0616c88b..e8b73294 100644
--- a/src/platform/Makefile.in
+++ b/src/platform/Makefile.in
@@ -313,6 +313,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index cd0a4e07..2dd0b512 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -169,6 +169,9 @@ _nl_get_vtable (void)
 			vtable.f_nl_has_capability = &_nl_f_nl_has_capability;
 
 		trace ("libnl: rtnl_link_get_link_netnsid() %s", vtable.f_rtnl_link_get_link_netnsid ? "supported" : "not supported");
+
+		g_return_val_if_fail (vtable.handle, &vtable);
+		g_return_val_if_fail (vtable.handle_route, &vtable);
 	}
 
 	return &vtable;
@@ -463,7 +466,7 @@ _nl_sock_request_link (NMPlatform *platform, struct nl_sock *sk, int ifindex, co
 
 	g_return_val_if_fail (ifindex > 0 || name, -NLE_INVAL);
 
-	_LOGT ("sock: request-link %d%s%s%s", ifindex, name ? ", \"" : "", name ? name : "", name ? "\"" : "");
+	_LOGt ("sock: request-link %d%s%s%s", ifindex, name ? ", \"" : "", name ? name : "", name ? "\"" : "");
 
 	if ((err = rtnl_link_build_get_request (ifindex, name, &msg)) < 0)
 		return err;
@@ -488,7 +491,7 @@ _nl_sock_request_all (NMPlatform *platform, struct nl_sock *sk, NMPObjectType ob
 
 	klass = nmp_class_from_type (obj_type);
 
-	_LOGT ("sock: request-all-%s", klass->obj_type_name);
+	_LOGt ("sock: request-all-%s", klass->obj_type_name);
 
 	/* reimplement
 	 *   nl_rtgen_request (sk, klass->rtm_gettype, klass->addr_family, NLM_F_DUMP);
@@ -898,7 +901,7 @@ link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink, gboolean *c
 		obj = _lookup_link_cached (platform, rtnl_link_get_ifindex (rtnllink), completed_from_cache, link_cached);
 		if (obj && obj->link.kind) {
 			rtnl_type = obj->link.kind;
-			_LOGT ("link_extract_type(): complete kind from cache: ifindex=%d, kind=%s", rtnl_link_get_ifindex (rtnllink), rtnl_type);
+			_LOGt ("link_extract_type(): complete kind from cache: ifindex=%d, kind=%s", rtnl_link_get_ifindex (rtnllink), rtnl_type);
 		}
 	}
 	if (out_kind)
@@ -944,18 +947,18 @@ link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink, gboolean *c
 		gs_free char *anycast_mask = NULL;
 		gs_free char *devtype = NULL;
 
-		if (arptype == 256) {
-			/* Some s390 CTC-type devices report 256 for the encapsulation type
-			 * for some reason, but we need to call them Ethernet.
-			 */
-			if (!g_strcmp0 (driver, "ctcm"))
-				return NM_LINK_TYPE_ETHERNET;
-		}
-
 		/* Fallback OVS detection for kernel <= 3.16 */
 		if (nmp_utils_ethtool_get_driver_info (ifname, &driver, NULL, NULL)) {
 			if (!g_strcmp0 (driver, "openvswitch"))
 				return NM_LINK_TYPE_OPENVSWITCH;
+
+			if (arptype == 256) {
+				/* Some s390 CTC-type devices report 256 for the encapsulation type
+				 * for some reason, but we need to call them Ethernet.
+				 */
+				if (!g_strcmp0 (driver, "ctcm"))
+					return NM_LINK_TYPE_ETHERNET;
+			}
 		}
 
 		sysfs_path = g_strdup_printf ("/sys/class/net/%s", ifname);
@@ -1009,8 +1012,8 @@ _nmp_vt_cmd_plobj_init_from_nl_link (NMPlatform *platform, NMPlatformObject *_ob
 
 	nm_assert (memcmp (obj, ((char [sizeof (NMPObjectLink)]) { 0 }), sizeof (NMPObjectLink)) == 0);
 
-	if (_LOGT_ENABLED () && !NM_IN_SET (rtnl_link_get_family (nlo), AF_UNSPEC, AF_BRIDGE))
-		_LOGT ("netlink object for ifindex %d has unusual family %d", rtnl_link_get_ifindex (nlo), rtnl_link_get_family (nlo));
+	if (_LOGt_ENABLED () && !NM_IN_SET (rtnl_link_get_family (nlo), AF_UNSPEC, AF_BRIDGE))
+		_LOGt ("netlink object for ifindex %d has unusual family %d", rtnl_link_get_ifindex (nlo), rtnl_link_get_family (nlo));
 
 	obj->ifindex = rtnl_link_get_ifindex (nlo);
 
@@ -1132,6 +1135,7 @@ _rtnl_addr_last_update_time_to_nm (const struct rtnl_addr *rtnladdr, gint32 *out
 	guint32 last_update_time = rtnl_addr_get_last_update_time ((struct rtnl_addr *) rtnladdr);
 	struct timespec tp;
 	gint64 now_nl, now_nm, result;
+	int err;
 
 	/* timestamp is unset. Default to 1. */
 	if (!last_update_time) {
@@ -1142,7 +1146,8 @@ _rtnl_addr_last_update_time_to_nm (const struct rtnl_addr *rtnladdr, gint32 *out
 
 	/* do all the calculations in milliseconds scale */
 
-	clock_gettime (CLOCK_MONOTONIC, &tp);
+	err = clock_gettime (CLOCK_MONOTONIC, &tp);
+	g_assert (err == 0);
 	now_nm = nm_utils_get_monotonic_timestamp_ms ();
 	now_nl = (((gint64) tp.tv_sec) * ((gint64) 1000)) +
 	         (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
@@ -1466,7 +1471,7 @@ do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cach
 
 	klass = NMP_OBJECT_GET_CLASS (obj);
 
-	_LOGT ("emit signal %s %s: %s (%ld)",
+	_LOGt ("emit signal %s %s: %s (%ld)",
 	       klass->signal_type,
 	       nm_platform_signal_change_type_to_string ((NMPlatformSignalChangeType) cache_op),
 	       nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0),
@@ -1523,8 +1528,8 @@ delayed_action_to_string (DelayedActionType action_type)
 	}
 }
 
-#define _LOGT_delayed_action(action_type, arg, operation) \
-    _LOGT ("delayed-action: %s %s (%d) [%p / %d]", ""operation, delayed_action_to_string (action_type), (int) action_type, arg, GPOINTER_TO_INT (arg))
+#define _LOGt_delayed_action(action_type, arg, operation) \
+    _LOGt ("delayed-action: %s %s (%d) [%p / %d]", ""operation, delayed_action_to_string (action_type), (int) action_type, arg, GPOINTER_TO_INT (arg))
 
 static void
 delayed_action_handle_MASTER_CONNECTED (NMPlatform *platform, int master_ifindex)
@@ -1579,7 +1584,7 @@ delayed_action_handle_one (NMPlatform *platform)
 			priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_MASTER_CONNECTED;
 		nm_assert (_nm_utils_ptrarray_find_first (priv->delayed_action.list_master_connected->pdata, priv->delayed_action.list_master_connected->len, user_data) < 0);
 
-		_LOGT_delayed_action (DELAYED_ACTION_TYPE_MASTER_CONNECTED, user_data, "handle");
+		_LOGt_delayed_action (DELAYED_ACTION_TYPE_MASTER_CONNECTED, user_data, "handle");
 		delayed_action_handle_MASTER_CONNECTED (platform, GPOINTER_TO_INT (user_data));
 		return TRUE;
 	}
@@ -1588,7 +1593,7 @@ delayed_action_handle_one (NMPlatform *platform)
 	/* Next we prefer read-netlink, because the buffer size is limited and we want to process events
 	 * from netlink early. */
 	if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_READ_NETLINK)) {
-		_LOGT_delayed_action (DELAYED_ACTION_TYPE_READ_NETLINK, NULL, "handle");
+		_LOGt_delayed_action (DELAYED_ACTION_TYPE_READ_NETLINK, NULL, "handle");
 		priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_READ_NETLINK;
 		delayed_action_handle_READ_NETLINK (platform);
 		return TRUE;
@@ -1601,10 +1606,10 @@ delayed_action_handle_one (NMPlatform *platform)
 
 		priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL;
 
-		if (_LOGT_ENABLED ()) {
+		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");
+					_LOGt_delayed_action (iflags, NULL, "handle");
 			}
 		}
 
@@ -1617,11 +1622,11 @@ delayed_action_handle_one (NMPlatform *platform)
 
 	user_data = priv->delayed_action.list_refresh_link->pdata[0];
 	g_ptr_array_remove_index_fast (priv->delayed_action.list_refresh_link, 0);
-	if (priv->delayed_action.list_master_connected->len == 0)
+	if (priv->delayed_action.list_refresh_link->len == 0)
 		priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK;
 	nm_assert (_nm_utils_ptrarray_find_first (priv->delayed_action.list_refresh_link->pdata, priv->delayed_action.list_refresh_link->len, user_data) < 0);
 
-	_LOGT_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "handle");
+	_LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "handle");
 
 	delayed_action_handle_REFRESH_LINK (platform, GPOINTER_TO_INT (user_data));
 
@@ -1653,6 +1658,33 @@ delayed_action_handle_idle (gpointer user_data)
 }
 
 static void
+delayed_action_clear_REFRESH_LINK (NMPlatform *platform, int ifindex)
+{
+	NMLinuxPlatformPrivate *priv;
+	gssize idx;
+	gpointer user_data;
+
+	if (ifindex <= 0)
+		return;
+
+	priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+	if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK))
+		return;
+
+	user_data = GINT_TO_POINTER (ifindex);
+
+	idx = _nm_utils_ptrarray_find_first (priv->delayed_action.list_refresh_link->pdata, priv->delayed_action.list_refresh_link->len, user_data);
+	if (idx < 0)
+		return;
+
+	_LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "clear");
+
+	g_ptr_array_remove_index_fast (priv->delayed_action.list_refresh_link, idx);
+	if (priv->delayed_action.list_refresh_link->len == 0)
+		priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK;
+}
+
+static void
 delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gpointer user_data)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
@@ -1673,10 +1705,10 @@ delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gp
 
 	priv->delayed_action.flags |= action_type;
 
-	if (_LOGT_ENABLED ()) {
+	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");
+				_LOGt_delayed_action (iflags, user_data, "schedule");
 		}
 	}
 
@@ -1694,7 +1726,7 @@ cache_prune_candidates_record_all (NMPlatform *platform, NMPObjectType obj_type)
 	priv->prune_candidates = nmp_cache_lookup_all_to_hash (priv->cache,
 	                                                       nmp_cache_id_init_object_type (NMP_CACHE_ID_STATIC, obj_type, FALSE),
 	                                                       priv->prune_candidates);
-	_LOGT ("cache-prune: record %s (now %u candidates)", nmp_class_from_type (obj_type)->obj_type_name,
+	_LOGt ("cache-prune: record %s (now %u candidates)", nmp_class_from_type (obj_type)->obj_type_name,
 	       priv->prune_candidates ? g_hash_table_size (priv->prune_candidates) : 0);
 }
 
@@ -1711,8 +1743,8 @@ cache_prune_candidates_record_one (NMPlatform *platform, NMPObject *obj)
 	if (!priv->prune_candidates)
 		priv->prune_candidates = g_hash_table_new_full (NULL, NULL, (GDestroyNotify) nmp_object_unref, NULL);
 
-	if (_LOGT_ENABLED () && !g_hash_table_contains (priv->prune_candidates, obj))
-		_LOGT ("cache-prune: record-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
+	if (_LOGt_ENABLED () && !g_hash_table_contains (priv->prune_candidates, obj))
+		_LOGt ("cache-prune: record-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
 	g_hash_table_add (priv->prune_candidates, nmp_object_ref (obj));
 }
 
@@ -1726,8 +1758,8 @@ cache_prune_candidates_drop (NMPlatform *platform, const NMPObject *obj)
 
 	priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	if (priv->prune_candidates) {
-		if (_LOGT_ENABLED () && g_hash_table_contains (priv->prune_candidates, obj))
-			_LOGT ("cache-prune: drop-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
+		if (_LOGt_ENABLED () && g_hash_table_contains (priv->prune_candidates, obj))
+			_LOGt ("cache-prune: drop-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
 		g_hash_table_remove (priv->prune_candidates, obj);
 	}
 }
@@ -1752,7 +1784,7 @@ cache_prune_candidates_prune (NMPlatform *platform)
 	while (g_hash_table_iter_next (&iter, (gpointer *)&obj, NULL)) {
 		auto_nmp_obj NMPObject *obj_cache = NULL;
 
-		_LOGT ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
+		_LOGt ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
 		cache_op = nmp_cache_remove (priv->cache, obj, TRUE, &obj_cache, &was_visible, cache_pre_hook, platform);
 		do_emit_signal (platform, obj_cache, cache_op, was_visible, NM_PLATFORM_REASON_INTERNAL);
 	}
@@ -1786,7 +1818,7 @@ cache_delayed_deletion_prune (NMPlatform *platform)
 	if (prune_list) {
 		for (i = 0; i < prune_list->len; i++) {
 			obj = prune_list->pdata[i];
-			_LOGT ("delayed-deletion: delete %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
+			_LOGt ("delayed-deletion: delete %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
 			cache_remove_netlink (platform, obj, NULL, NULL, NM_PLATFORM_REASON_EXTERNAL);
 		}
 		g_ptr_array_unref (prune_list);
@@ -1813,7 +1845,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 
 	nm_assert (klass == (new ? NMP_OBJECT_GET_CLASS (new) : NMP_OBJECT_GET_CLASS (old)));
 
-	_LOGT ("update-cache-%s: %s: %s%s%s",
+	_LOGt ("update-cache-%s: %s: %s%s%s",
 	       klass->obj_type_name,
 	       (ops_type == NMP_CACHE_OPS_UPDATED
 	           ? "UPDATE"
@@ -1869,6 +1901,37 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
 			}
 		}
 		{
+			int ifindex = -1;
+
+			/* removal of a link could be caused by moving the link to another netns.
+			 * In this case, we potentially have to update other links that have this link as parent.
+			 * Currently, kernel misses to sent us a notification in this case (rh #1262908). */
+
+			if (   ops_type == NMP_CACHE_OPS_REMOVED
+			    && old /* <-- nonsensical, make coverity happy */
+			    && old->_link.netlink.is_in_netlink)
+				ifindex = old->link.ifindex;
+			else if (   ops_type == NMP_CACHE_OPS_UPDATED
+			         && old && new /* <-- nonsensical, make coverity happy */
+			         && old->_link.netlink.is_in_netlink
+			         && !new->_link.netlink.is_in_netlink)
+				ifindex = new->link.ifindex;
+
+			if (ifindex > 0) {
+				const NMPlatformLink *const *links;
+
+				links = cache_lookup_all_objects (NMPlatformLink, platform, NMP_OBJECT_TYPE_LINK, FALSE);
+				if (links) {
+					for (; *links; links++) {
+						const NMPlatformLink *l = (*links);
+
+						if (l->parent == ifindex)
+							delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (l->ifindex));
+					}
+				}
+			}
+		}
+		{
 			/* if a link goes down, we must refresh routes */
 			if (   ops_type == NMP_CACHE_OPS_UPDATED
 			    && old && new /* <-- nonsensical, make coverity happy */
@@ -1974,7 +2037,7 @@ _new_sequence_number (NMPlatform *platform, guint32 seq)
 {
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 
-	_LOGT ("_new_sequence_number(): new sequence number %u", seq);
+	_LOGt ("_new_sequence_number(): new sequence number %u", seq);
 
 	priv->nlh_seq_expect = seq;
 }
@@ -1985,7 +2048,7 @@ do_request_link (NMPlatform *platform, int ifindex, const char *name, gboolean h
 	NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
 	guint32 seq;
 
-	_LOGT ("do_request_link (%d,%s)", ifindex, name ? name : "");
+	_LOGt ("do_request_link (%d,%s)", ifindex, name ? name : "");
 
 	if (ifindex > 0) {
 		NMPObject *obj;
@@ -1993,7 +2056,7 @@ do_request_link (NMPlatform *platform, int ifindex, const char *name, gboolean h
 		cache_prune_candidates_record_one (platform,
 		                                   (NMPObject *) nmp_cache_lookup_link (priv->cache, ifindex));
 		obj = nmp_object_new_link (ifindex);
-		_LOGT ("delayed-deletion: protect object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
+		_LOGt ("delayed-deletion: protect object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
 		g_hash_table_insert (priv->delayed_deletion, obj, NULL);
 	}
 
@@ -2038,9 +2101,11 @@ do_request_all (NMPlatform *platform, DelayedActionType action_type, gboolean ha
 
 			/* 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)");
 			}
 
 			event_handler_read_netlink_all (platform, FALSE);
@@ -2081,7 +2146,7 @@ kernel_add_object (NMPlatform *platform, NMPObjectType obj_type, const struct nl
 		g_return_val_if_reached (-NLE_INVAL);
 	}
 
-	_LOGT ("kernel-add-%s: returned %s (%d)",
+	_LOGt ("kernel-add-%s: returned %s (%d)",
 	       nmp_class_from_type (obj_type)->obj_type_name, nl_geterror (nle), -nle);
 
 	switch (nle) {
@@ -2125,20 +2190,20 @@ kernel_delete_object (NMPlatform *platform, NMPObjectType object_type, const str
 	case -NLE_SUCCESS:
 		return NLE_SUCCESS;
 	case -NLE_OBJ_NOTFOUND:
-		_LOGT ("kernel-delete-%s: failed with \"%s\" (%d), meaning the object was already removed",
+		_LOGt ("kernel-delete-%s: failed with \"%s\" (%d), meaning the object was already removed",
 		       nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle);
 		return -NLE_SUCCESS;
 	case -NLE_FAILURE:
 		if (object_type == NMP_OBJECT_TYPE_IP6_ADDRESS) {
 			/* On RHEL7 kernel, deleting a non existing address fails with ENXIO (which libnl maps to NLE_FAILURE) */
-			_LOGT ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed",
+			_LOGt ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed",
 			       nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle);
 			return NLE_SUCCESS;
 		}
 		break;
 	case -NLE_NOADDR:
 		if (object_type == NMP_OBJECT_TYPE_IP4_ADDRESS || object_type == NMP_OBJECT_TYPE_IP6_ADDRESS) {
-			_LOGT ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed",
+			_LOGt ("kernel-delete-%s: deleting address failed with \"%s\" (%d), meaning the address was already removed",
 			       nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle);
 			return -NLE_SUCCESS;
 		}
@@ -2146,7 +2211,7 @@ kernel_delete_object (NMPlatform *platform, NMPObjectType object_type, const str
 	default:
 		break;
 	}
-	_LOGT ("kernel-delete-%s: failed with %s (%d)",
+	_LOGt ("kernel-delete-%s: failed with %s (%d)",
 	       nmp_class_from_type (object_type)->obj_type_name, nl_geterror (nle), -nle);
 	return nle;
 }
@@ -2183,7 +2248,7 @@ kernel_change_link (NMPlatform *platform, struct rtnl_link *nlo, gboolean *compl
 
 		obj_cache = nmp_cache_lookup_link (priv->cache, ifindex);
 		if (!obj_cache || !obj_cache->_link.netlink.is_in_netlink) {
-			_LOGT ("kernel-change-link: failure changing link %d: cannot complete link", ifindex);
+			_LOGt ("kernel-change-link: failure changing link %d: cannot complete link", ifindex);
 			*complete_from_cache = FALSE;
 			return -NLE_INVAL;
 		}
@@ -2204,7 +2269,7 @@ kernel_change_link (NMPlatform *platform, struct rtnl_link *nlo, gboolean *compl
 
 	nle = rtnl_link_build_add_request (nlo, nlflags, &msg);
 	if (nle < 0) {
-		_LOGT ("kernel-change-link: failure changing link %d: cannot construct message (%s, %d)",
+		_LOGt ("kernel-change-link: failure changing link %d: cannot construct message (%s, %d)",
 		       ifindex, nl_geterror (nle), -nle);
 		return nle;
 	}
@@ -2234,18 +2299,18 @@ errout:
 	 */
 	switch (nle) {
 	case -NLE_SUCCESS:
-		_LOGT ("kernel-change-link: success changing link %d", ifindex);
+		_LOGt ("kernel-change-link: success changing link %d", ifindex);
 		break;
 	case -NLE_EXIST:
-		_LOGT ("kernel-change-link: success changing link %d: %s (%d)",
+		_LOGt ("kernel-change-link: success changing link %d: %s (%d)",
 		       ifindex, nl_geterror (nle), -nle);
 		break;
 	case -NLE_OBJ_NOTFOUND:
-		_LOGT ("kernel-change-link: failure changing link %d: firmware not found (%s, %d)",
+		_LOGt ("kernel-change-link: failure changing link %d: firmware not found (%s, %d)",
 		       ifindex, nl_geterror (nle), -nle);
 		break;
 	default:
-		_LOGT ("kernel-change-link: failure changing link %d: netlink error (%s, %d)",
+		_LOGt ("kernel-change-link: failure changing link %d: netlink error (%s, %d)",
 		       ifindex, nl_geterror (nle), -nle);
 		break;
 	}
@@ -2277,13 +2342,13 @@ event_seq_check (struct nl_msg *msg, gpointer user_data)
 	priv->nlh_seq_last = hdr->nlmsg_seq;
 
 	if (priv->nlh_seq_expect == 0)
-		_LOGT ("event_seq_check(): seq %u received (not waited)", hdr->nlmsg_seq);
+		_LOGt ("event_seq_check(): seq %u received (not waited)", hdr->nlmsg_seq);
 	else if (hdr->nlmsg_seq == priv->nlh_seq_expect) {
-		_LOGT ("event_seq_check(): seq %u received", hdr->nlmsg_seq);
+		_LOGt ("event_seq_check(): seq %u received", hdr->nlmsg_seq);
 
 		priv->nlh_seq_expect = 0;
 	} else
-		_LOGT ("event_seq_check(): seq %u received (wait for %u)", hdr->nlmsg_seq, priv->nlh_seq_last);
+		_LOGt ("event_seq_check(): seq %u received (wait for %u)", hdr->nlmsg_seq, priv->nlh_seq_last);
 
 	return NL_OK;
 }
@@ -2291,7 +2356,7 @@ event_seq_check (struct nl_msg *msg, gpointer user_data)
 static int
 event_err (struct sockaddr_nl *nla, struct nlmsgerr *nlerr, gpointer platform)
 {
-	_LOGT ("event_err(): error from kernel: %s (%d) for request %d",
+	_LOGt ("event_err(): error from kernel: %s (%d) for request %d",
 	       strerror (nlerr ? -nlerr->error : 0),
 	       nlerr ? -nlerr->error : 0,
 	       NM_LINUX_PLATFORM_GET_PRIVATE (platform)->nlh_seq_last);
@@ -2333,13 +2398,13 @@ event_notification (struct nl_msg *msg, gpointer user_data)
 		/* The event notifies about a deleted object. We don't need to initialize all the
 		 * fields of the nmp-object. Shortcut nmp_object_from_nl(). */
 		obj = nmp_object_from_nl (platform, nlo, TRUE, TRUE);
-		_LOGD ("event-notification: %s, seq %u: %s",
+		_LOGT ("event-notification: %s, seq %u: %s",
 		       _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)),
 		       msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
 		break;
 	default:
 		obj = nmp_object_from_nl (platform, nlo, FALSE, TRUE);
-		_LOGD ("event-notification: %s, seq %u: %s",
+		_LOGT ("event-notification: %s, seq %u: %s",
 		       _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)),
 		       msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
 		break;
@@ -2351,12 +2416,14 @@ event_notification (struct nl_msg *msg, gpointer user_data)
 		switch (msghdr->nlmsg_type) {
 
 		case RTM_NEWLINK:
-			if (   NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LINK
-			    && g_hash_table_lookup (priv->delayed_deletion, obj) != NULL) {
-				/* the object is scheduled for delayed deletion. Replace that object
-				 * by clearing the value from priv->delayed_deletion. */
-				_LOGT ("delayed-deletion: clear delayed deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
-				g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), NULL);
+			if (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LINK) {
+				if (g_hash_table_lookup (priv->delayed_deletion, obj) != NULL) {
+					/* the object is scheduled for delayed deletion. Replace that object
+					 * by clearing the value from priv->delayed_deletion. */
+					_LOGt ("delayed-deletion: clear delayed deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
+					g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), NULL);
+				}
+				delayed_action_clear_REFRESH_LINK (platform, obj->link.ifindex);
 			}
 			/* fall-through */
 		case RTM_NEWADDR:
@@ -2369,7 +2436,7 @@ event_notification (struct nl_msg *msg, gpointer user_data)
 			    && g_hash_table_contains (priv->delayed_deletion, obj)) {
 				/* We sometimes receive spurious RTM_DELLINK events. In this case, we want to delay
 				 * the deletion of the object until later. */
-				_LOGT ("delayed-deletion: delay deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
+				_LOGt ("delayed-deletion: delay deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
 				g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), nmp_object_ref (obj));
 				break;
 			}
@@ -2681,7 +2748,7 @@ do_add_link (NMPlatform *platform, const char *name, const struct rtnl_link *nlo
 	 * link so that it is in the cache. A better solution would be to do everything
 	 * via one netlink socket. */
 	if (!nmp_cache_lookup_link_full (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, 0, obj_needle.link.name, FALSE, NM_LINK_TYPE_NONE, NULL, NULL)) {
-		_LOGT ("do-add-link: reload: the added link is not yet ready. Request %s", obj_needle.link.name);
+		_LOGt ("do-add-link: reload: the added link is not yet ready. Request %s", obj_needle.link.name);
 		do_request_link (platform, 0, obj_needle.link.name, TRUE);
 	}
 
@@ -2733,7 +2800,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, const struct nl
 	/* FIXME: instead of re-requesting the added object, add it via nlh_event
 	 * so that the events are in sync. */
 	if (!nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, obj_id)) {
-		_LOGT ("do-add-%s: reload: the added object is not yet ready. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0));
+		_LOGt ("do-add-%s: reload: the added object is not yet ready. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0));
 		do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id), TRUE);
 	}
 
@@ -2771,12 +2838,12 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, const struct nl
 
 		obj = nmp_cache_lookup_link_full (priv->cache, obj_id->link.ifindex, obj_id->link.ifindex <= 0 && obj_id->link.name[0] ? obj_id->link.name : NULL, FALSE, NM_LINK_TYPE_NONE, NULL, NULL);
 		if (obj && obj->_link.netlink.is_in_netlink) {
-			_LOGT ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0));
+			_LOGt ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0));
 			do_request_link (platform, obj_id->link.ifindex, obj_id->link.name, TRUE);
 		}
 	} else {
 		if (nmp_cache_lookup_obj (priv->cache, obj_id)) {
-			_LOGT ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0));
+			_LOGt ("do-delete-%s: reload: the deleted object is not yet removed. Request %s", NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name, nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0));
 			do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id), TRUE);
 		}
 	}
@@ -4621,7 +4688,7 @@ event_handler_read_netlink_all (NMPlatform *platform, gboolean wait_for_acks)
 
 		if (!wait_for_acks || priv->nlh_seq_expect == 0) {
 			if (wait_for_seq)
-				_LOGT ("read-netlink-all: ACK for sequence number %u received", priv->nlh_seq_expect);
+				_LOGt ("read-netlink-all: ACK for sequence number %u received", priv->nlh_seq_expect);
 			return any;
 		}
 
@@ -4629,7 +4696,7 @@ event_handler_read_netlink_all (NMPlatform *platform, gboolean wait_for_acks)
 		if (wait_for_seq != priv->nlh_seq_expect) {
 			/* We are waiting for a new sequence number (or we will wait for the first time).
 			 * Reset/start counting the overall wait time. */
-			_LOGT ("read-netlink-all: wait for ACK for sequence number %u...", priv->nlh_seq_expect);
+			_LOGt ("read-netlink-all: wait for ACK for sequence number %u...", priv->nlh_seq_expect);
 			wait_for_seq = priv->nlh_seq_expect;
 			timestamp = now;
 			timeout = TIMEOUT;
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index b7f0947e..e9b8d4be 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -139,21 +139,31 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
                                          guint8 *buf,
                                          size_t *length)
 {
-	gs_free struct ethtool_perm_addr *epaddr = NULL;
+	struct {
+		struct ethtool_perm_addr e;
+		guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1];
+	} edata;
+	guint zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
 
 	if (!ifname)
 		return FALSE;
 
-	epaddr = g_malloc0 (sizeof (*epaddr) + NM_UTILS_HWADDR_LEN_MAX);
-	epaddr->cmd = ETHTOOL_GPERMADDR;
-	epaddr->size = NM_UTILS_HWADDR_LEN_MAX;
+	memset (&edata, 0, sizeof (edata));
+	edata.e.cmd = ETHTOOL_GPERMADDR;
+	edata.e.size = NM_UTILS_HWADDR_LEN_MAX;
 
-	if (!ethtool_get (ifname, epaddr))
+	if (!ethtool_get (ifname, &edata.e))
 		return FALSE;
 
-	g_assert (epaddr->size <= NM_UTILS_HWADDR_LEN_MAX);
-	memcpy (buf, epaddr->data, epaddr->size);
-	*length = epaddr->size;
+	g_assert (edata.e.size <= NM_UTILS_HWADDR_LEN_MAX);
+
+	/* Some drivers might return a permanent address of all zeros.
+	 * Reject that (rh#1264024) */
+	if (memcmp (edata.e.data, zeros, edata.e.size) == 0)
+		return FALSE;
+
+	memcpy (buf, edata.e.data, edata.e.size);
+	*length = edata.e.size;
 	return TRUE;
 }
 
@@ -269,6 +279,9 @@ nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
 {
 	struct ethtool_wolinfo wol_info = { };
 
+	if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE)
+		return TRUE;
+
 	nm_log_dbg (LOGD_PLATFORM, "setting Wake-on-LAN options 0x%x, password '%s'",
 	            (unsigned int) wol, wol_password);
 
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index fcb5b061..9948ac8b 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -427,7 +427,7 @@ nm_platform_link_get_all (NMPlatform *self)
 	for (i = 0; i < links->len; i++) {
 		item = &g_array_index (links, NMPlatformLink, i);
 
-		_LOGT ("link-get: %3d: %s", i, nm_platform_link_to_string (item));
+		_LOGt ("link-get: %3d: %s", i, nm_platform_link_to_string (item));
 
 		nm_assert (item->ifindex > 0 && !g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex)));
 
@@ -483,7 +483,7 @@ nm_platform_link_get_all (NMPlatform *self)
 			if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent)))
 				continue;
 
-			_LOGT ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item));
+			_LOGt ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item));
 
 			g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex));
 			g_array_index (result, NMPlatformLink, j++) = *item;
@@ -496,7 +496,7 @@ nm_platform_link_get_all (NMPlatform *self)
 			 * This can happen for veth pairs where each peer is parent of the other end. */
 			item = &g_array_index (links, NMPlatformLink, first_idx);
 
-			_LOGT ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item));
+			_LOGt ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item));
 
 			g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex));
 			g_array_index (result, NMPlatformLink, j++) = *item;
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 7fe2d7d3..eb6bfc3a 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -178,7 +178,7 @@ nmp_object_ref (NMPObject *obj)
 	g_return_val_if_fail (obj->_ref_count != NMP_REF_COUNT_STACKINIT, NULL);
 	obj->_ref_count++;
 
-	_LOGT (obj, "ref: %d", obj->_ref_count);
+	_LOGt (obj, "ref: %d", obj->_ref_count);
 
 	return obj;
 }
@@ -189,7 +189,7 @@ nmp_object_unref (NMPObject *obj)
 	if (obj) {
 		g_return_if_fail (obj->_ref_count > 0);
 		g_return_if_fail (obj->_ref_count != NMP_REF_COUNT_STACKINIT);
-		_LOGT (obj, "%s: %d",
+		_LOGt (obj, "%s: %d",
 		       obj->_ref_count <= 1 ? "destroy" : "unref",
 		       obj->_ref_count - 1);
 		if (--obj->_ref_count <= 0) {
@@ -221,7 +221,7 @@ _nmp_object_new_from_class (const NMPClass *klass)
 	obj = g_slice_alloc0 (klass->sizeof_data + G_STRUCT_OFFSET (NMPObject, object));
 	obj->_class = klass;
 	obj->_ref_count = 1;
-	_LOGT (obj, "new");
+	_LOGt (obj, "new");
 	return obj;
 }
 
diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am
index 54844ec1..35aa098a 100644
--- a/src/platform/tests/Makefile.am
+++ b/src/platform/tests/Makefile.am
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I${top_srcdir} \
 	-I${top_srcdir}/include \
+	-I${top_builddir}/include \
 	-I${top_srcdir}/src \
 	-I${top_builddir}/src \
 	-I${top_srcdir}/libnm-core \
diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in
index a9333539..f45f3a9c 100644
--- a/src/platform/tests/Makefile.in
+++ b/src/platform/tests/Makefile.in
@@ -616,6 +616,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -757,9 +758,10 @@ with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include \
-	-I${top_srcdir}/src -I${top_builddir}/src \
-	-I${top_srcdir}/libnm-core -I${top_builddir}/libnm-core \
-	-I${srcdir}/.. -DG_LOG_DOMAIN=\""NetworkManager"\" \
+	-I${top_builddir}/include -I${top_srcdir}/src \
+	-I${top_builddir}/src -I${top_srcdir}/libnm-core \
+	-I${top_builddir}/libnm-core -I${srcdir}/.. \
+	-DG_LOG_DOMAIN=\""NetworkManager"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \
 	$(GUDEV_CFLAGS) $(LIBNL_CFLAGS) $(am__append_1)
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index ce371b75..f9645d85 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -118,6 +118,41 @@ software_add (NMLinkType link_type, const char *name)
 }
 
 static void
+test_link_changed_signal_cb (NMPlatform *platform,
+                             NMPObjectType obj_type,
+                             int ifindex,
+                             const NMPlatformIP4Route *route,
+                             NMPlatformSignalChangeType change_type,
+                             NMPlatformReason reason,
+                             gboolean *p_test_link_changed_signal_arg)
+{
+	/* test invocation of platform signals with multiple listeners
+	 * connected to the signal. Platform signals have enum-typed
+	 * arguments and there seem to be an issue with invoking such
+	 * signals on s390x and ppc64 archs.
+	 * https://bugzilla.redhat.com/show_bug.cgi?id=1260577
+	 *
+	 * As the test shows, the failure is not reproducible for
+	 * platform signals.
+	 */
+	g_assert (NM_IS_PLATFORM (platform));
+	g_assert (platform == NM_PLATFORM_GET);
+
+	g_assert (ifindex > 0);
+	g_assert (route);
+
+	g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_LINK);
+
+	g_assert_cmpint ((gint64) change_type, !=, (gint64) 0);
+	g_assert_cmpint (change_type, !=, NM_PLATFORM_SIGNAL_NONE);
+
+	g_assert_cmpint ((gint64) reason, !=, (gint64) 0);
+	g_assert_cmpint (reason, !=, NM_PLATFORM_REASON_NONE);
+
+	*p_test_link_changed_signal_arg = TRUE;
+}
+
+static void
 test_slave (int master, int type, SignalData *master_changed)
 {
 	int ifindex;
@@ -125,6 +160,8 @@ test_slave (int master, int type, SignalData *master_changed)
 	SignalData *link_changed, *link_removed;
 	char *value;
 	NMLinkType link_type = nm_platform_link_get_type (NM_PLATFORM_GET, master);
+	gboolean test_link_changed_signal_arg1;
+	gboolean test_link_changed_signal_arg2;
 
 	g_assert (NM_IN_SET (link_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE));
 
@@ -158,11 +195,21 @@ test_slave (int master, int type, SignalData *master_changed)
 	else
 		g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
 
+	test_link_changed_signal_arg1 = FALSE;
+	test_link_changed_signal_arg2 = FALSE;
+	g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg1);
+	g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg2);
+
 	/* Set master up */
 	g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, master, NULL));
 	g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, master));
 	accept_signals (master_changed, 1, 2);
 
+	g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg1);
+	g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (test_link_changed_signal_cb), &test_link_changed_signal_arg2);
+	g_assert (test_link_changed_signal_arg1);
+	g_assert (test_link_changed_signal_arg2);
+
 	/* Master with a disconnected slave is disconnected
 	 *
 	 * For some reason, bonding and teaming slaves are automatically set up. We
diff --git a/src/ppp-manager/Makefile.am b/src/ppp-manager/Makefile.am
index fd2fe76b..5b1edc29 100644
--- a/src/ppp-manager/Makefile.am
+++ b/src/ppp-manager/Makefile.am
@@ -2,6 +2,7 @@ if WITH_PPP
 
 AM_CPPFLAGS = \
 	-I${top_srcdir}/include \
+	-I${top_builddir}/include \
 	-I${top_srcdir}/libnm-core \
 	-I${top_builddir}/libnm-core \
 	-DG_LOG_DOMAIN=\""nm-pppd-plugin"\" \
diff --git a/src/ppp-manager/Makefile.in b/src/ppp-manager/Makefile.in
index 26698e16..338dcff7 100644
--- a/src/ppp-manager/Makefile.in
+++ b/src/ppp-manager/Makefile.in
@@ -339,6 +339,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -481,6 +482,7 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 @WITH_PPP_TRUE@AM_CPPFLAGS = \
 @WITH_PPP_TRUE@	-I${top_srcdir}/include \
+@WITH_PPP_TRUE@	-I${top_builddir}/include \
 @WITH_PPP_TRUE@	-I${top_srcdir}/libnm-core \
 @WITH_PPP_TRUE@	-I${top_builddir}/libnm-core \
 @WITH_PPP_TRUE@	-DG_LOG_DOMAIN=\""nm-pppd-plugin"\" \
diff --git a/src/rdisc/Makefile.in b/src/rdisc/Makefile.in
index 4713fa9b..0df08e30 100644
--- a/src/rdisc/Makefile.in
+++ b/src/rdisc/Makefile.in
@@ -313,6 +313,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
diff --git a/src/rdisc/tests/Makefile.am b/src/rdisc/tests/Makefile.am
index 5d6f8b5b..995f68bd 100644
--- a/src/rdisc/tests/Makefile.am
+++ b/src/rdisc/tests/Makefile.am
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
 	-I${top_srcdir} \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I${top_srcdir}/src \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/libnm-core \
diff --git a/src/rdisc/tests/Makefile.in b/src/rdisc/tests/Makefile.in
index 8fedb770..1a5c70e2 100644
--- a/src/rdisc/tests/Makefile.in
+++ b/src/rdisc/tests/Makefile.in
@@ -514,6 +514,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -657,6 +658,7 @@ with_valgrind = @with_valgrind@
 AM_CPPFLAGS = \
 	-I${top_srcdir} \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I${top_srcdir}/src \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/libnm-core \
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index 8dcda06d..c694ad6f 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -421,6 +421,8 @@ struct _Request {
 	 */
 	GSList *asked;
 
+	NMAuthChain *chain;
+
 	guint32 idle_id;
 
 	RequestAddAgentFunc add_agent_callback;
@@ -475,6 +477,9 @@ request_free (Request *req)
 	if (!req->completed && req->cancel_callback)
 		req->cancel_callback (req);
 
+	if (req->chain)
+		nm_auth_chain_unref (req->chain);
+
 	g_object_unref (req->subject);
 
 	g_free (req->detail);
@@ -640,6 +645,13 @@ request_remove_agent (Request *req, NMSecretAgent *agent, GSList **pending_reqs)
 	if (agent == req->current) {
 		nm_log_dbg (LOGD_AGENTS, "(%s) current agent removed from secrets request %p/%s",
 		            nm_secret_agent_get_description (agent), req, req->detail);
+
+		if (req->chain) {
+			/* This cancels the pending authorization requests. */
+			nm_auth_chain_unref (req->chain);
+			req->chain = NULL;
+		}
+
 		*pending_reqs = g_slist_prepend (*pending_reqs, req);
 	} else {
 		nm_log_dbg (LOGD_AGENTS, "(%s) agent removed from secrets request %p/%s",
@@ -675,8 +687,6 @@ typedef struct {
 	gpointer other_data2;
 	gpointer other_data3;
 
-	NMAuthChain *chain;
-
 	/* Whether the agent currently being asked for secrets
 	 * has the system.modify privilege.
 	 */
@@ -693,8 +703,6 @@ connection_request_free (gpointer data)
 	g_strfreev (req->hints);
 	if (req->existing_secrets)
 		g_hash_table_unref (req->existing_secrets);
-	if (req->chain)
-		nm_auth_chain_unref (req->chain);
 }
 
 static gboolean
@@ -816,6 +824,11 @@ get_done_cb (NMSecretAgent *agent,
 			req_complete_error (parent, error);
 			g_error_free (error);
 		} else {
+			if (parent->current_call_id) {
+				/* Tell the failed agent we're no longer interested. */
+				nm_secret_agent_cancel_secrets (parent->current, parent->current_call_id);
+			}
+
 			/* Try the next agent */
 			request_next_agent (parent);
 		}
@@ -941,7 +954,7 @@ get_agent_modify_auth_cb (NMAuthChain *chain,
 	ConnectionRequest *req = user_data;
 	const char *perm;
 
-	req->chain = NULL;
+	parent->chain = NULL;
 
 	if (error) {
 		nm_log_dbg (LOGD_AGENTS, "(%s) agent %p/%s/%s MODIFY check error: (%d) %s",
@@ -1036,11 +1049,11 @@ get_next_cb (Request *parent)
 		nm_log_dbg (LOGD_AGENTS, "(%p/%s/%s) request has system secrets; checking agent %s for MODIFY",
 		            req, parent->detail, req->setting_name, agent_dbus_owner);
 
-		req->chain = nm_auth_chain_new_subject (nm_secret_agent_get_subject (parent->current),
-		                                        NULL,
-		                                        get_agent_modify_auth_cb,
-		                                        req);
-		g_assert (req->chain);
+		parent->chain = nm_auth_chain_new_subject (nm_secret_agent_get_subject (parent->current),
+		                                           NULL,
+		                                           get_agent_modify_auth_cb,
+		                                           req);
+		g_assert (parent->chain);
 
 		/* If the caller is the only user in the connection's permissions, then
 		 * we use the 'modify.own' permission instead of 'modify.system'.  If the
@@ -1052,9 +1065,9 @@ get_next_cb (Request *parent)
 			perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
 		else
 			perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
-		nm_auth_chain_set_data (req->chain, "perm", (gpointer) perm, NULL);
+		nm_auth_chain_set_data (parent->chain, "perm", (gpointer) perm, NULL);
 
-		nm_auth_chain_add_call (req->chain, perm, TRUE);
+		nm_auth_chain_add_call (parent->chain, perm, TRUE);
 	} else {
 		nm_log_dbg (LOGD_AGENTS, "(%p/%s/%s) requesting user-owned secrets from agent %s",
 		            req, parent->detail, req->setting_name, agent_dbus_owner);
diff --git a/src/settings/plugins/Makefile.in b/src/settings/plugins/Makefile.in
index d7b7ab14..c706214b 100644
--- a/src/settings/plugins/Makefile.in
+++ b/src/settings/plugins/Makefile.in
@@ -318,6 +318,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
diff --git a/src/settings/plugins/example/Makefile.am b/src/settings/plugins/example/Makefile.am
index b98f66ef..7ce8eaea 100644
--- a/src/settings/plugins/example/Makefile.am
+++ b/src/settings/plugins/example/Makefile.am
@@ -2,6 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-example"\" \
diff --git a/src/settings/plugins/example/Makefile.in b/src/settings/plugins/example/Makefile.in
index 3b7a1551..5f16d186 100644
--- a/src/settings/plugins/example/Makefile.in
+++ b/src/settings/plugins/example/Makefile.in
@@ -309,6 +309,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -453,6 +454,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-example"\" \
diff --git a/src/settings/plugins/ibft/Makefile.am b/src/settings/plugins/ibft/Makefile.am
index 00a5d175..6bc9d05d 100644
--- a/src/settings/plugins/ibft/Makefile.am
+++ b/src/settings/plugins/ibft/Makefile.am
@@ -15,6 +15,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DNETWORKMANAGER_COMPILATION \
diff --git a/src/settings/plugins/ibft/Makefile.in b/src/settings/plugins/ibft/Makefile.in
index de9be286..1f5b8eb4 100644
--- a/src/settings/plugins/ibft/Makefile.in
+++ b/src/settings/plugins/ibft/Makefile.in
@@ -384,6 +384,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -536,6 +537,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DNETWORKMANAGER_COMPILATION \
diff --git a/src/settings/plugins/ibft/tests/Makefile.am b/src/settings/plugins/ibft/tests/Makefile.am
index 3c7c94ac..9901119e 100644
--- a/src/settings/plugins/ibft/tests/Makefile.am
+++ b/src/settings/plugins/ibft/tests/Makefile.am
@@ -6,6 +6,7 @@ AM_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(CODE_COVERAGE_CFLAGS) \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src/ \
diff --git a/src/settings/plugins/ibft/tests/Makefile.in b/src/settings/plugins/ibft/tests/Makefile.in
index 266497b6..30bd78df 100644
--- a/src/settings/plugins/ibft/tests/Makefile.in
+++ b/src/settings/plugins/ibft/tests/Makefile.in
@@ -512,6 +512,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -656,6 +657,7 @@ with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS) \
 @ENABLE_TESTS_TRUE@	$(CODE_COVERAGE_CFLAGS) \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/ \
diff --git a/src/settings/plugins/ifcfg-rh/Makefile.am b/src/settings/plugins/ifcfg-rh/Makefile.am
index 4989f4ba..08ffa0ec 100644
--- a/src/settings/plugins/ifcfg-rh/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/Makefile.am
@@ -28,6 +28,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DNETWORKMANAGER_COMPILATION \
diff --git a/src/settings/plugins/ifcfg-rh/Makefile.in b/src/settings/plugins/ifcfg-rh/Makefile.in
index 0cd26960..eaa456bb 100644
--- a/src/settings/plugins/ifcfg-rh/Makefile.in
+++ b/src/settings/plugins/ifcfg-rh/Makefile.in
@@ -387,6 +387,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -549,6 +550,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DNETWORKMANAGER_COMPILATION \
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index 72123e66..271b7bb1 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -346,7 +346,6 @@ is_any_ip4_address_defined (shvarFile *ifcfg, int *idx)
 /* Returns TRUE on missing address or valid address */
 static gboolean
 read_full_ip4_address (shvarFile *ifcfg,
-                       const char *network_file,
                        gint32 which,
                        NMIPAddress *base_addr,
                        NMIPAddress **out_address,
@@ -362,7 +361,6 @@ read_full_ip4_address (shvarFile *ifcfg,
 
 	g_return_val_if_fail (which >= -1, FALSE);
 	g_return_val_if_fail (ifcfg != NULL, FALSE);
-	g_return_val_if_fail (network_file != NULL, FALSE);
 	g_return_val_if_fail (out_address != NULL, FALSE);
 	g_return_val_if_fail (*out_address == NULL, FALSE);
 	if (error)
@@ -452,7 +450,6 @@ done:
 /* Returns TRUE on missing route or valid route */
 static gboolean
 read_one_ip4_route (shvarFile *ifcfg,
-                    const char *network_file,
                     guint32 which,
                     NMIPRoute **out_route,
                     GError **error)
@@ -463,7 +460,6 @@ read_one_ip4_route (shvarFile *ifcfg,
 	gboolean success = FALSE;
 
 	g_return_val_if_fail (ifcfg != NULL, FALSE);
-	g_return_val_if_fail (network_file != NULL, FALSE);
 	g_return_val_if_fail (out_route != NULL, FALSE);
 	g_return_val_if_fail (*out_route == NULL, FALSE);
 	if (error)
@@ -684,7 +680,6 @@ error:
 
 static gboolean
 parse_full_ip6_address (shvarFile *ifcfg,
-                        const char *network_file,
                         const char *addr_str,
                         int i,
                         NMIPAddress **out_address,
@@ -942,7 +937,10 @@ make_ip4_setting (shvarFile *ifcfg,
 	} else if (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp")) {
 		method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
 	} else if (!g_ascii_strcasecmp (value, "static")) {
-		method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+		if (is_any_ip4_address_defined (ifcfg, NULL))
+			method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+		else
+			method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
 	} else if (!g_ascii_strcasecmp (value, "autoip")) {
 		g_free (value);
 		g_object_set (s_ip4,
@@ -962,7 +960,7 @@ make_ip4_setting (shvarFile *ifcfg,
 		if (is_any_ip4_address_defined (ifcfg, &idx)) {
 			NMIPAddress *addr = NULL;
 
-			if (!read_full_ip4_address (ifcfg, network_file, idx, NULL, &addr, NULL, error))
+			if (!read_full_ip4_address (ifcfg, idx, NULL, &addr, NULL, error))
 				goto done;
 			if (!read_ip4_address (ifcfg, "GATEWAY", &gateway, error))
 				goto done;
@@ -1020,7 +1018,7 @@ make_ip4_setting (shvarFile *ifcfg,
 
 		/* gateway will only be set if still unset. Hence, we don't leak gateway
 		 * here by calling read_full_ip4_address() repeatedly */
-		if (!read_full_ip4_address (ifcfg, network_file, i, NULL, &addr, &gateway, error))
+		if (!read_full_ip4_address (ifcfg, i, NULL, &addr, &gateway, error))
 			goto done;
 
 		if (!addr) {
@@ -1046,6 +1044,13 @@ make_ip4_setting (shvarFile *ifcfg,
 			svCloseFile (network_ifcfg);
 			if (!read_success)
 				goto done;
+
+			if (gateway && nm_setting_ip_config_get_num_addresses (s_ip4) == 0) {
+				gs_free char *f = g_path_get_basename (ifcfg->fileName);
+				PARSE_WARNING ("ignoring GATEWAY (/etc/sysconfig/network) for %s "
+				               "because the connection has no static addresses", f);
+				g_clear_pointer (&gateway, g_free);
+			}
 		}
 	}
 	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL);
@@ -1108,7 +1113,7 @@ make_ip4_setting (shvarFile *ifcfg,
 			for (i = 0; i < 256; i++) {
 				NMIPRoute *route = NULL;
 
-				if (!read_one_ip4_route (route_ifcfg, network_file, i, &route, error)) {
+				if (!read_one_ip4_route (route_ifcfg, i, &route, error)) {
 					svCloseFile (route_ifcfg);
 					goto done;
 				}
@@ -1158,7 +1163,7 @@ done:
 }
 
 static void
-read_aliases (NMSettingIPConfig *s_ip4, const char *filename, const char *network_file)
+read_aliases (NMSettingIPConfig *s_ip4, const char *filename)
 {
 	GDir *dir;
 	char *dirname, *base;
@@ -1230,7 +1235,7 @@ read_aliases (NMSettingIPConfig *s_ip4, const char *filename, const char *networ
 			}
 
 			addr = NULL;
-			ok = read_full_ip4_address (parsed, network_file, -1, base_addr, &addr, NULL, &err);
+			ok = read_full_ip4_address (parsed, -1, base_addr, &addr, NULL, &err);
 			svCloseFile (parsed);
 			if (ok) {
 				nm_ip_address_set_attribute (addr, "label", g_variant_new_string (device));
@@ -1417,7 +1422,7 @@ make_ip6_setting (shvarFile *ifcfg,
 	for (iter = list, i = 0; iter && *iter; iter++, i++) {
 		NMIPAddress *addr = NULL;
 
-		if (!parse_full_ip6_address (ifcfg, network_file, *iter, i, &addr, error)) {
+		if (!parse_full_ip6_address (ifcfg, *iter, i, &addr, error)) {
 			g_strfreev (list);
 			goto error;
 		}
@@ -3502,21 +3507,46 @@ wireless_connection_from_ifcfg (const char *file,
 }
 
 static void
-parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, char *value)
+parse_ethtool_option (const char *value, NMSettingWiredWakeOnLan *out_flags, char **out_password)
 {
-	NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
-	gboolean use_password = FALSE;
-	char **words, **iter, *flag;
+	gs_strfreev char **words = NULL;
+	const char **iter = NULL, *flag;
 
 	if (!value || !value[0])
 		return;
 
-	words = g_strsplit_set (value, " ", 0);
-	iter = words;
+	words = g_strsplit_set (value, "\t ", 0);
+	iter = (const char **) words;
 
 	while (iter[0]) {
-		if (g_str_equal (iter[0], "wol") && iter[1] && *iter[1]) {
-			for (flag = iter[1]; *flag; flag++) {
+		gboolean is_wol;
+
+		if (g_str_equal (iter[0], "wol"))
+			is_wol = TRUE;
+		else if (g_str_equal (iter[0], "sopass"))
+			is_wol = FALSE;
+		else {
+			/* Silently skip unknown options */
+			iter++;
+			continue;
+		}
+
+		iter++;
+
+		/* g_strsplit_set() returns empty tokens, meaning that we must skip over repeated
+		 * space characters like to parse "wol     d". */
+		while (iter[0] && !*iter[0])
+			iter++;
+
+		if (is_wol) {
+			NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
+
+			if (!iter[0]) {
+				PARSE_WARNING ("Wake-on-LAN options missing");
+				break;
+			}
+
+			for (flag = iter[0]; *flag; flag++) {
 				switch (*flag) {
 				case 'p':
 					wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY;
@@ -3537,42 +3567,62 @@ parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, char *value)
 					wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC;
 					break;
 				case 's':
-					use_password = TRUE;
 					break;
 				case 'd':
 					wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
-					use_password = FALSE;
 					break;
 				default:
 					PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *flag);
 				}
 			}
 
-			if (!NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC))
-				use_password = FALSE;
+			*out_flags = wol_flags;
+		} else {
+			if (!iter[0]) {
+				PARSE_WARNING ("Wake-on-LAN password missing");
+				break;
+			}
 
-			g_object_set (s_wired, NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, NULL);
-			iter += 2;
-			continue;
+			g_clear_pointer (out_password, g_free);
+			if (nm_utils_hwaddr_valid (iter[0], ETH_ALEN))
+				*out_password = g_strdup (iter[0]);
+			else
+				PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", iter[0]);
 		}
+		iter++;
+	}
+}
 
-		if (g_str_equal (iter[0], "sopass") && iter[1] && *iter[1]) {
-			if (use_password) {
-				if (nm_utils_hwaddr_valid (iter[1], ETH_ALEN))
-					g_object_set (s_wired, NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, iter[1], NULL);
-				else
-					PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", iter[1]);
-			} else
-				PARSE_WARNING ("Wake-on-LAN password not expected");
-			iter += 2;
-			continue;
-		}
+static void
+parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, const char *value)
+{
+	NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT;
+	gs_free char *wol_password = NULL;
+	gboolean ignore_wol_password = FALSE;
 
-		/* Silently skip unknown options */
-		iter++;
+	if (value) {
+		gs_strfreev char **opts = NULL;
+		const char **iter;
+
+		wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE;
+
+		opts = g_strsplit_set (value, ";", 0);
+		for (iter = (const char **) opts; iter[0]; iter++) {
+			/* in case of repeated wol_passwords, parse_ethtool_option()
+			 * will do the right thing and clear wol_password before resetting. */
+			parse_ethtool_option (iter[0], &wol_flags, &wol_password);
+		}
 	}
 
-	g_strfreev (words);
+	if (   wol_password
+	    && !NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) {
+		PARSE_WARNING ("Wake-on-LAN password not expected");
+		ignore_wol_password = TRUE;
+	}
+	g_object_set (s_wired,
+	              NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags,
+	              NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, ignore_wol_password ? NULL : wol_password,
+	              NULL);
 }
 
 static NMSetting *
@@ -3710,7 +3760,7 @@ make_wired_setting (shvarFile *ifcfg,
 		g_free (value);
 	}
 
-	value = svGetValue (ifcfg, "ETHTOOL_OPTS", FALSE);
+	value = svGetValueFull (ifcfg, "ETHTOOL_OPTS", FALSE);
 	parse_ethtool_options (ifcfg, s_wired, value);
 	g_free (value);
 
@@ -4884,7 +4934,7 @@ connection_from_file_full (const char *filename,
 		connection = NULL;
 		goto done;
 	} else {
-		read_aliases (NM_SETTING_IP_CONFIG (s_ip4), filename, network_file);
+		read_aliases (NM_SETTING_IP_CONFIG (s_ip4), filename);
 		nm_connection_add_setting (connection, s_ip4);
 	}
 
diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c
index 283aa826..5fd7755f 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.c
+++ b/src/settings/plugins/ifcfg-rh/shvar.c
@@ -299,8 +299,8 @@ svGetValueFull (shvarFile *s, const char *key, gboolean verbatim)
 	return value;
 }
 
-/* return TRUE if <key> resolves to any truth value (e.g. "yes", "y", "true")
- * return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false")
+/* return TRUE if <key> resolves to any truth value (e.g. "yes", "true", "y", "t", "1")
+ * return FALSE if <key> resolves to any non-truth value (e.g. "no", "false", "n", "f", "0")
  * return <default> otherwise
  */
 gint
@@ -316,12 +316,14 @@ svTrueValue (shvarFile *s, const char *key, gint def)
 	if (   !g_ascii_strcasecmp ("yes", tmp)
 	    || !g_ascii_strcasecmp ("true", tmp)
 	    || !g_ascii_strcasecmp ("t", tmp)
-	    || !g_ascii_strcasecmp ("y", tmp))
+	    || !g_ascii_strcasecmp ("y", tmp)
+	    || !g_ascii_strcasecmp ("1", tmp))
 		returnValue = TRUE;
 	else if (   !g_ascii_strcasecmp ("no", tmp)
 	         || !g_ascii_strcasecmp ("false", tmp)
 	         || !g_ascii_strcasecmp ("f", tmp)
-	         || !g_ascii_strcasecmp ("n", tmp))
+	         || !g_ascii_strcasecmp ("n", tmp)
+	         || !g_ascii_strcasecmp ("0", tmp))
 		returnValue = FALSE;
 
 	g_free (tmp);
diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/Makefile.am
index a3f6a052..73f3b5d8 100644
--- a/src/settings/plugins/ifcfg-rh/tests/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.am
@@ -8,6 +8,7 @@ AM_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(CODE_COVERAGE_CFLAGS) \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src/ \
diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/Makefile.in
index d0832e47..da25c8b9 100644
--- a/src/settings/plugins/ifcfg-rh/tests/Makefile.in
+++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.in
@@ -566,6 +566,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -711,6 +712,7 @@ with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS) \
 @ENABLE_TESTS_TRUE@	$(CODE_COVERAGE_CFLAGS) \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/ \
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
index 7b5aaf17..c3fde548 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
@@ -14,6 +14,8 @@ EXTRA_DIST = \
 	ifcfg-test-wired-dhcp6-only \
 	ifcfg-test-wired-global-gateway \
 	network-test-wired-global-gateway \
+	ifcfg-test-wired-global-gateway-ignore \
+	network-test-wired-global-gateway-ignore \
 	ifcfg-test-wired-obsolete-gateway-n \
 	ifcfg-test-wired-never-default \
 	network-test-wired-never-default \
@@ -99,6 +101,7 @@ EXTRA_DIST = \
 	ifcfg-test-vlan-only-vlanid \
 	ifcfg-test-vlan-only-device \
 	ifcfg-test-vlan-physdev \
+	ifcfg-test-vlan-reorder-hdr-1 \
 	ifcfg-test-wifi-wep-no-keys \
 	ifcfg-test-permissions \
 	ifcfg-test-wifi-wep-agent-keys \
@@ -124,7 +127,8 @@ EXTRA_DIST = \
 	ifcfg-test-team-port \
 	ifcfg-test-team-port-empty-config \
 	ifcfg-test-vlan-trailing-spaces \
-	ifcfg-test-wired-wake-on-lan
+	ifcfg-test-wired-wake-on-lan \
+	ifcfg-test-wired-ipv6-only-1
 
 # make target dependencies can't have colons in their names, which ends up
 # meaning that we can't add the alias files to EXTRA_DIST
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
index 2435434d..4add27b7 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
@@ -253,6 +253,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -409,6 +410,8 @@ EXTRA_DIST = \
 	ifcfg-test-wired-dhcp6-only \
 	ifcfg-test-wired-global-gateway \
 	network-test-wired-global-gateway \
+	ifcfg-test-wired-global-gateway-ignore \
+	network-test-wired-global-gateway-ignore \
 	ifcfg-test-wired-obsolete-gateway-n \
 	ifcfg-test-wired-never-default \
 	network-test-wired-never-default \
@@ -494,6 +497,7 @@ EXTRA_DIST = \
 	ifcfg-test-vlan-only-vlanid \
 	ifcfg-test-vlan-only-device \
 	ifcfg-test-vlan-physdev \
+	ifcfg-test-vlan-reorder-hdr-1 \
 	ifcfg-test-wifi-wep-no-keys \
 	ifcfg-test-permissions \
 	ifcfg-test-wifi-wep-agent-keys \
@@ -519,7 +523,8 @@ EXTRA_DIST = \
 	ifcfg-test-team-port \
 	ifcfg-test-team-port-empty-config \
 	ifcfg-test-vlan-trailing-spaces \
-	ifcfg-test-wired-wake-on-lan
+	ifcfg-test-wired-wake-on-lan \
+	ifcfg-test-wired-ipv6-only-1
 
 
 # make target dependencies can't have colons in their names, which ends up
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1
new file mode 100644
index 00000000..ca38f839
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1
@@ -0,0 +1,7 @@
+VLAN=yes
+TYPE=Vlan
+DEVICE=vlan0.3
+PHYSDEV=eth0
+VLAN_ID=3
+REORDER_HDR=1
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore
new file mode 100644
index 00000000..bb81399e
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore
@@ -0,0 +1,8 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=dhcp
+ONBOOT=yes
+USERCTL=yes
+IPV6INIT=no
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1
new file mode 100644
index 00000000..95f8a8ed
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1
@@ -0,0 +1,16 @@
+IPADDR=
+GATEWAY=
+NETMASK=
+BOOTPROTO=static
+TYPE=Ethernet
+DEVICE=eth2
+HWADDR=00:11:22:33:44:ee
+ONBOOT=yes
+USERCTL=yes
+NM_CONTROLLED=yes
+PEERDNS=yes
+DNS1=1:2:3:4::a
+DOMAIN="lorem.com ipsum.org dolor.edu"
+IPV6INIT=yes
+IPV6_AUTOCONF=no
+IPV6ADDR="1001:abba::1234/56"
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore b/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore
new file mode 100644
index 00000000..7987d105
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore
@@ -0,0 +1 @@
+GATEWAY=192.168.1.2
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index f2f85d3c..cd2d0417 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -868,6 +868,48 @@ test_read_wired_global_gateway (void)
 	g_object_unref (connection);
 }
 
+/* Ignore GATEWAY from /etc/sysconfig/network for automatic connections */
+static void
+test_read_wired_global_gateway_ignore (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	NMSettingIPConfig *s_ip4;
+	GError *error = NULL;
+	char *unmanaged = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*ignoring GATEWAY (/etc/sysconfig/network) for * because the connection has no static addresses");
+	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway-ignore",
+	                                        TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway-ignore",
+	                                        TYPE_ETHERNET, &unmanaged, &error);
+	nmtst_assert_connection_verifies_without_normalization (connection);
+	g_assert (unmanaged == NULL);
+
+	/* ===== CONNECTION SETTING ===== */
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System test-wired-global-gateway-ignore");
+
+	/* ===== WIRED SETTING ===== */
+	s_wired = nm_connection_get_setting_wired (connection);
+	g_assert (s_wired);
+
+	/* ===== IPv4 SETTING ===== */
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+
+	/* Addresses */
+	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
+
+	/* Gateway */
+	g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, NULL);
+
+	g_object_unref (connection);
+}
+
 static void
 test_read_wired_obsolete_gateway_n (void)
 {
@@ -1633,9 +1675,10 @@ test_read_wired_ipv6_manual (void)
 }
 
 #define TEST_IFCFG_WIRED_IPV6_ONLY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only"
+#define TEST_IFCFG_WIRED_IPV6_ONLY_1 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only-1"
 
 static void
-test_read_wired_ipv6_only (void)
+test_read_wired_ipv6_only (const char *file, const char *expected_id)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
@@ -1645,17 +1688,16 @@ test_read_wired_ipv6_only (void)
 	char *unmanaged = NULL;
 	GError *error = NULL;
 	const char *tmp;
-	const char *expected_id = "System test-wired-ipv6-only";
 	NMIPAddress *ip6_addr;
 	const char *method;
 
-	connection = connection_from_file_test (TEST_IFCFG_WIRED_IPV6_ONLY,
+	connection = connection_from_file_test (file,
 	                                        NULL,
 	                                        TYPE_ETHERNET,
 	                                        &unmanaged,
 	                                        &error);
 	ASSERT (connection != NULL,
-	        "wired-ipv6-only-read", "failed to read %s: %s", TEST_IFCFG_WIRED_IPV6_ONLY, error->message);
+	        "wired-ipv6-only-read", "failed to read %s: %s", file, error->message);
 
 	ASSERT (nm_connection_verify (connection, &error),
 	        "wired-ipv6-only-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_IPV6_ONLY, error->message);
@@ -6080,8 +6122,7 @@ test_write_wired_static (void)
 	g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip4), ==, 204);
 	g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip6), ==, 206);
 
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-	        "wired-static-write", "written and re-read connection weren't the same.");
+	nmtst_assert_connection_equals (connection, FALSE, reread, FALSE);
 
 	route6file = utils_get_route6_path (testfile);
 	unlink (route6file);
@@ -10847,6 +10888,8 @@ test_read_vlan_only_vlan_id (void)
 
 	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth9");
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 43);
+	/* Ensure that flags are 0 if both REORDER_HDR and VLAN_FLAGS are missing */
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 0);
 
 	g_object_unref (connection);
 }
@@ -10906,6 +10949,33 @@ test_read_vlan_physdev (void)
 }
 
 static void
+test_read_vlan_reorder_hdr_1 (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+	NMSettingVlan *s_vlan;
+
+	connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-reorder-hdr-1",
+	                                        NULL, TYPE_ETHERNET, NULL,
+	                                        &error);
+	g_assert_no_error (error);
+	g_assert (connection);
+	g_assert (nm_connection_verify (connection, &error));
+
+	g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "vlan0.3");
+
+	s_vlan = nm_connection_get_setting_vlan (connection);
+	g_assert (s_vlan);
+
+	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth0");
+	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 3);
+	/* Check correct read of REORDER_HDR=1 */
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 1);
+
+	g_object_unref (connection);
+}
+
+static void
 test_write_vlan (void)
 {
 	NMConnection *connection;
@@ -10981,6 +11051,77 @@ test_write_vlan_only_vlanid (void)
 }
 
 static void
+test_write_vlan_reorder_hdr (void)
+{
+	NMConnection *connection, *reread;
+	NMSettingConnection *s_con;
+	NMSettingVlan *s_vlan;
+	NMSettingWired *s_wired;
+	char *uuid;
+	GError *error = NULL;
+	gboolean success;
+	char *testfile = NULL;
+
+	connection = nm_simple_connection_new ();
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Write VLAN reorder_hdr",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_VLAN_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wired setting */
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	/* VLAN setting */
+	s_vlan = (NMSettingVlan *) nm_setting_vlan_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_vlan));
+
+	g_object_set (s_vlan,
+	              NM_SETTING_VLAN_PARENT, "eth0",
+	              NM_SETTING_VLAN_ID, 444,
+	              NM_SETTING_VLAN_FLAGS, 1,
+	              NULL);
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_connection_normalize (connection, NULL, NULL, NULL);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file_test (testfile,
+	                                    NULL,
+	                                    TYPE_ETHERNET,
+	                                    NULL,
+	                                    &error);
+	unlink (testfile);
+
+	g_assert_no_error (error);
+	g_assert (reread);
+	g_assert (nm_connection_verify (reread, &error));
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+
+	g_object_unref (connection);
+	g_object_unref (reread);
+	g_free (testfile);
+}
+
+static void
 test_write_ethernet_missing_ipv6 (void)
 {
 	NMConnection *connection;
@@ -12604,12 +12745,13 @@ int main (int argc, char **argv)
 	test_read_wired_static (TEST_IFCFG_WIRED_STATIC, "System test-wired-static", TRUE);
 	test_read_wired_static (TEST_IFCFG_WIRED_STATIC_BOOTPROTO, "System test-wired-static-bootproto", FALSE);
 	test_read_wired_dhcp ();
-	g_test_add_func (TPATH "dhcp-plus-ip", test_read_wired_dhcp_plus_ip);
-	g_test_add_func (TPATH "shared-plus-ip", test_read_wired_shared_plus_ip);
-	g_test_add_func (TPATH "dhcp-send-hostname", test_read_write_wired_dhcp_send_hostname);
-	g_test_add_func (TPATH "global-gateway", test_read_wired_global_gateway);
-	g_test_add_func (TPATH "obsolete-gateway-n", test_read_wired_obsolete_gateway_n);
-	g_test_add_func (TPATH "never-default", test_read_wired_never_default);
+	g_test_add_func (TPATH "read-dhcp-plus-ip", test_read_wired_dhcp_plus_ip);
+	g_test_add_func (TPATH "read-shared-plus-ip", test_read_wired_shared_plus_ip);
+	g_test_add_func (TPATH "read-dhcp-send-hostname", test_read_write_wired_dhcp_send_hostname);
+	g_test_add_func (TPATH "read-global-gateway", test_read_wired_global_gateway);
+	g_test_add_func (TPATH "read-global-gateway-ignore", test_read_wired_global_gateway_ignore);
+	g_test_add_func (TPATH "read-obsolete-gateway-n", test_read_wired_obsolete_gateway_n);
+	g_test_add_func (TPATH "read-never-default", test_read_wired_never_default);
 	test_read_wired_defroute_no ();
 	test_read_wired_defroute_no_gatewaydev_yes ();
 	g_test_add_func (TPATH "routes/read-static", test_read_wired_static_routes);
@@ -12619,7 +12761,8 @@ int main (int argc, char **argv)
 	test_read_wired_ipv4_manual (TEST_IFCFG_WIRED_IPV4_MANUAL_3, "System test-wired-ipv4-manual-3");
 	test_read_wired_ipv4_manual (TEST_IFCFG_WIRED_IPV4_MANUAL_4, "System test-wired-ipv4-manual-4");
 	test_read_wired_ipv6_manual ();
-	test_read_wired_ipv6_only ();
+	test_read_wired_ipv6_only (TEST_IFCFG_WIRED_IPV6_ONLY, "System test-wired-ipv6-only");
+	test_read_wired_ipv6_only (TEST_IFCFG_WIRED_IPV6_ONLY_1, "System test-wired-ipv6-only-1");
 	test_read_wired_dhcp6_only ();
 	test_read_onboot_no ();
 	test_read_noip ();
@@ -12672,6 +12815,7 @@ int main (int argc, char **argv)
 	test_read_vlan_only_vlan_id ();
 	test_read_vlan_only_device ();
 	g_test_add_func (TPATH "vlan/physdev", test_read_vlan_physdev);
+	g_test_add_func (TPATH "vlan/reorder-hdr-1", test_read_vlan_reorder_hdr_1);
 	g_test_add_func (TPATH "wired/read-wake-on-lan", test_read_wired_wake_on_lan);
 
 	test_write_wired_static ();
@@ -12679,7 +12823,7 @@ int main (int argc, char **argv)
 	test_write_wired_static_routes ();
 	test_read_write_static_routes_legacy ();
 	test_write_wired_dhcp ();
-	g_test_add_func (TPATH "dhcp-plus-ip", test_write_wired_dhcp_plus_ip);
+	g_test_add_func (TPATH "wired/write-dhcp-plus-ip", test_write_wired_dhcp_plus_ip);
 	test_write_wired_dhcp_8021x_peap_mschapv2 ();
 	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
 	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_NOT_SAVED);
@@ -12751,6 +12895,7 @@ int main (int argc, char **argv)
 	test_write_infiniband ();
 	test_write_vlan ();
 	test_write_vlan_only_vlanid ();
+	g_test_add_func (TPATH "vlan/write-vlan-reorder-hdr", test_write_vlan_reorder_hdr);
 	test_write_ethernet_missing_ipv6 ();
 
 	/* iSCSI / ibft */
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index 69b7d64a..3640a104 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -714,15 +714,19 @@ write_wireless_security_setting (NMConnection *connection,
 						ascii_key = g_strdup_printf ("s:%s", key);
 						key = ascii_key;
 					}
-				} else
-					key = NULL;
-
-				set_secret (ifcfg,
-				            tmp,
-				            key,
-				            "WEP_KEY_FLAGS",
-				            nm_setting_wireless_security_get_wep_key_flags (s_wsec),
-				            FALSE);
+				} else {
+					nm_log_warn (LOGD_SETTINGS, "    invalid WEP key '%s'", key);
+					tmp = NULL;
+				}
+
+				if (tmp) {
+					set_secret (ifcfg,
+					            tmp,
+					            key,
+					            "WEP_KEY_FLAGS",
+					            nm_setting_wireless_security_get_wep_key_flags (s_wsec),
+					            FALSE);
+				}
 				g_free (tmp);
 				g_free (ascii_key);
 			}
@@ -1137,7 +1141,9 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 
 	wol = nm_setting_wired_get_wake_on_lan (s_wired);
 	wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired);
-	if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)
+	if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE)
+		svSetValueFull (ifcfg, "ETHTOOL_OPTS", "", FALSE);
+	else if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)
 		svSetValue (ifcfg, "ETHTOOL_OPTS", NULL, FALSE);
 	else {
 		str = g_string_sized_new (30);
@@ -1258,9 +1264,9 @@ write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired,
 
 	vlan_flags = nm_setting_vlan_get_flags (s_vlan);
 	if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS)
-		svSetValue (ifcfg, "REORDER_HDR", "1", FALSE);
+		svSetValue (ifcfg, "REORDER_HDR", "yes", FALSE);
 	else
-		svSetValue (ifcfg, "REORDER_HDR", "0", FALSE);
+		svSetValue (ifcfg, "REORDER_HDR", "no", FALSE);
 
 	svSetValue (ifcfg, "VLAN_FLAGS", NULL, FALSE);
 	if (vlan_flags & NM_VLAN_FLAG_GVRP) {
diff --git a/src/settings/plugins/ifcfg-suse/Makefile.am b/src/settings/plugins/ifcfg-suse/Makefile.am
index 46204d7d..55494536 100644
--- a/src/settings/plugins/ifcfg-suse/Makefile.am
+++ b/src/settings/plugins/ifcfg-suse/Makefile.am
@@ -3,6 +3,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src \
 	-I${top_srcdir}/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-ifcfg-suse"\" \
diff --git a/src/settings/plugins/ifcfg-suse/Makefile.in b/src/settings/plugins/ifcfg-suse/Makefile.in
index 3d7df19e..fa51b0aa 100644
--- a/src/settings/plugins/ifcfg-suse/Makefile.in
+++ b/src/settings/plugins/ifcfg-suse/Makefile.in
@@ -337,6 +337,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -482,6 +483,7 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src \
 	-I${top_srcdir}/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-ifcfg-suse"\" \
diff --git a/src/settings/plugins/ifnet/Makefile.am b/src/settings/plugins/ifnet/Makefile.am
index b0cfd9a1..84e2e697 100644
--- a/src/settings/plugins/ifnet/Makefile.am
+++ b/src/settings/plugins/ifnet/Makefile.am
@@ -7,6 +7,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-ifnet"\" \
diff --git a/src/settings/plugins/ifnet/Makefile.in b/src/settings/plugins/ifnet/Makefile.in
index 4832249a..589f1f22 100644
--- a/src/settings/plugins/ifnet/Makefile.in
+++ b/src/settings/plugins/ifnet/Makefile.in
@@ -385,6 +385,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -531,6 +532,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-ifnet"\" \
diff --git a/src/settings/plugins/ifnet/tests/Makefile.am b/src/settings/plugins/ifnet/tests/Makefile.am
index 66409a54..754bb182 100644
--- a/src/settings/plugins/ifnet/tests/Makefile.am
+++ b/src/settings/plugins/ifnet/tests/Makefile.am
@@ -5,6 +5,7 @@ if ENABLE_TESTS
 AM_CPPFLAGS= \
 	-I$(srcdir)/../ \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src \
diff --git a/src/settings/plugins/ifnet/tests/Makefile.in b/src/settings/plugins/ifnet/tests/Makefile.in
index b94a46fc..d331ecee 100644
--- a/src/settings/plugins/ifnet/tests/Makefile.in
+++ b/src/settings/plugins/ifnet/tests/Makefile.in
@@ -313,6 +313,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -456,6 +457,7 @@ with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
 @ENABLE_TESTS_TRUE@	-I$(srcdir)/../ \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src \
diff --git a/src/settings/plugins/ifupdown/Makefile.am b/src/settings/plugins/ifupdown/Makefile.am
index 0ca543e3..e1f2b339 100644
--- a/src/settings/plugins/ifupdown/Makefile.am
+++ b/src/settings/plugins/ifupdown/Makefile.am
@@ -6,6 +6,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-ifupdown"\" \
diff --git a/src/settings/plugins/ifupdown/Makefile.in b/src/settings/plugins/ifupdown/Makefile.in
index 7cd1ef4e..3bd19afc 100644
--- a/src/settings/plugins/ifupdown/Makefile.in
+++ b/src/settings/plugins/ifupdown/Makefile.in
@@ -384,6 +384,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -529,6 +530,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-ifupdown"\" \
diff --git a/src/settings/plugins/ifupdown/tests/Makefile.am b/src/settings/plugins/ifupdown/tests/Makefile.am
index 2e927db9..4ae44a0b 100644
--- a/src/settings/plugins/ifupdown/tests/Makefile.am
+++ b/src/settings/plugins/ifupdown/tests/Makefile.am
@@ -2,6 +2,7 @@ if ENABLE_TESTS
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src \
diff --git a/src/settings/plugins/ifupdown/tests/Makefile.in b/src/settings/plugins/ifupdown/tests/Makefile.in
index a1c029c3..2387a257 100644
--- a/src/settings/plugins/ifupdown/tests/Makefile.in
+++ b/src/settings/plugins/ifupdown/tests/Makefile.in
@@ -513,6 +513,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -655,6 +656,7 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src \
diff --git a/src/settings/plugins/keyfile/Makefile.am b/src/settings/plugins/keyfile/Makefile.am
index 079c45c3..919b0805 100644
--- a/src/settings/plugins/keyfile/Makefile.am
+++ b/src/settings/plugins/keyfile/Makefile.am
@@ -6,6 +6,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-keyfile"\" \
diff --git a/src/settings/plugins/keyfile/Makefile.in b/src/settings/plugins/keyfile/Makefile.in
index c409d481..1514768b 100644
--- a/src/settings/plugins/keyfile/Makefile.in
+++ b/src/settings/plugins/keyfile/Makefile.in
@@ -353,6 +353,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -498,6 +499,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-keyfile"\" \
diff --git a/src/settings/plugins/keyfile/tests/Makefile.am b/src/settings/plugins/keyfile/tests/Makefile.am
index a79e20b5..cbe3f73b 100644
--- a/src/settings/plugins/keyfile/tests/Makefile.am
+++ b/src/settings/plugins/keyfile/tests/Makefile.am
@@ -6,6 +6,7 @@ SUBDIRS=keyfiles
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src \
diff --git a/src/settings/plugins/keyfile/tests/Makefile.in b/src/settings/plugins/keyfile/tests/Makefile.in
index a65110f6..6dfaf110 100644
--- a/src/settings/plugins/keyfile/tests/Makefile.in
+++ b/src/settings/plugins/keyfile/tests/Makefile.in
@@ -557,6 +557,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -700,6 +701,7 @@ with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@SUBDIRS = keyfiles
 @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src \
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
index 4ca4c3fa..be431067 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
@@ -28,6 +28,7 @@ KEYFILES = \
 	Test_minimal_slave_3 \
 	Test_minimal_slave_4 \
 	Test_Missing_Vlan_Setting \
+	Test_Missing_Vlan_Flags \
 	Test_Missing_ID_UUID \
 	Test_Enum_Property \
 	Test_Flags_Property
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
index de7af82b..33d0e0c5 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
@@ -253,6 +253,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -423,6 +424,7 @@ KEYFILES = \
 	Test_minimal_slave_3 \
 	Test_minimal_slave_4 \
 	Test_Missing_Vlan_Setting \
+	Test_Missing_Vlan_Flags \
 	Test_Missing_ID_UUID \
 	Test_Enum_Property \
 	Test_Flags_Property
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags b/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags
new file mode 100644
index 00000000..330adda0
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags
@@ -0,0 +1,15 @@
+# VLAN setting with missing 'flags' key
+# vlan.flags will be set to 0 (even if the default 'flags' property value is 1)
+
+[connection]
+id=Test Missing Vlan Flags
+uuid=803ebe47-8c31-401d-b47b-03fc0d34eb11
+type=vlan
+autoconnect=true
+
+[802-3-ethernet]
+mac-address=00:11:22:33:44:55
+
+[vlan]
+id=444
+parent=em1
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c
index 4fc44c7b..785ad4cb 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile.c
@@ -3292,6 +3292,35 @@ test_read_missing_vlan_setting (void)
 	s_vlan = nm_connection_get_setting_vlan (connection);
 	g_assert (s_vlan);
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 0);
+	/* Ensure the VLAN flags are not set (0) */
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 0);
+
+	g_object_unref (connection);
+}
+
+static void
+test_read_missing_vlan_flags (void)
+{
+	NMConnection *connection;
+	NMSettingVlan *s_vlan;
+	GError *error = NULL;
+	gboolean success;
+
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Flags", &error);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* Ensure the VLAN setting exists */
+	s_vlan = nm_connection_get_setting_vlan (connection);
+	g_assert (s_vlan);
+
+	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 444);
+	g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "em1");
+	/* Ensure the VLAN flags are not set (0) */
+	g_assert_cmpint (nm_setting_vlan_get_flags (s_vlan), ==, 0);
 
 	g_object_unref (connection);
 }
@@ -3688,6 +3717,7 @@ int main (int argc, char **argv)
 	g_test_add_func ("/keyfile/test_write_new_wireless_group_names ", test_write_new_wireless_group_names);
 
 	g_test_add_func ("/keyfile/test_read_missing_vlan_setting ", test_read_missing_vlan_setting);
+	g_test_add_func ("/keyfile/test_read_missing_vlan_flags ", test_read_missing_vlan_flags);
 	g_test_add_func ("/keyfile/test_read_missing_id_uuid ", test_read_missing_id_uuid);
 
 	g_test_add_func ("/keyfile/test_read_minimal", test_read_minimal);
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index c4c725c1..692efef3 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -612,7 +612,8 @@ gboolean
 nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
                                                     NMSettingWirelessSecurity *setting,
                                                     NMSetting8021x *setting_8021x,
-                                                    const char *con_uuid)
+                                                    const char *con_uuid,
+                                                    guint32 mtu)
 {
 	gboolean success = FALSE;
 	const char *key_mgmt, *auth_alg;
@@ -729,7 +730,7 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
 		if (!strcmp (key_mgmt, "ieee8021x") || !strcmp (key_mgmt, "wpa-eap")) {
 		    if (!setting_8021x)
 		    	return FALSE;
-			if (!nm_supplicant_config_add_setting_8021x (self, setting_8021x, con_uuid, FALSE))
+			if (!nm_supplicant_config_add_setting_8021x (self, setting_8021x, con_uuid, mtu, FALSE))
 				return FALSE;
 		}
 
@@ -756,6 +757,7 @@ gboolean
 nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
                                         NMSetting8021x *setting,
                                         const char *con_uuid,
+                                        guint32 mtu,
                                         gboolean wired)
 {
 	NMSupplicantConfigPrivate *priv;
@@ -768,6 +770,8 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 	guint32 i, num_eap;
 	gboolean fast_provisoning_allowed = FALSE;
 	const char *ca_path_override = NULL, *ca_cert_override = NULL;
+	guint32 frag, hdrs;
+	char *frag_str = NULL;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
 	g_return_val_if_fail (setting != NULL, FALSE);
@@ -819,9 +823,19 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 		}
 	}
 
-	/* Drop the fragment size a bit for better compatibility */
-	if (!nm_supplicant_config_add_option (self, "fragment_size", "1300", -1, FALSE))
+	/* Adjust the fragment size according to MTU, but do not set it higher than 1280-14
+	 * for better compatibility */
+	hdrs = 14; /* EAPOL + EAP-TLS */
+	frag = 1280 - hdrs;
+	if (mtu > hdrs)
+		frag = CLAMP (mtu - hdrs, 100, frag);
+	frag_str = g_strdup_printf ("%u", frag);
+
+	if (!nm_supplicant_config_add_option (self, "fragment_size", frag_str, -1, FALSE)) {
+		g_free (frag_str);
 		return FALSE;
+	}
+	g_free (frag_str);
 
 	phase1 = g_string_new (NULL);
 	peapver = nm_setting_802_1x_get_phase1_peapver (setting);
diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h
index 3324f637..9708a6d3 100644
--- a/src/supplicant-manager/nm-supplicant-config.h
+++ b/src/supplicant-manager/nm-supplicant-config.h
@@ -70,13 +70,15 @@ gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self,
 gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
                                                              NMSettingWirelessSecurity *setting,
                                                              NMSetting8021x *setting_8021x,
-                                                             const char *con_uuid);
+                                                             const char *con_uuid,
+                                                             guint32 mtu);
 
 gboolean nm_supplicant_config_add_no_security (NMSupplicantConfig *self);
 
 gboolean nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
                                                  NMSetting8021x *setting,
                                                  const char *con_uuid,
+                                                 guint32 mtu,
                                                  gboolean wired);
 
 G_END_DECLS
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
index 66bab2e3..30be23ae 100644
--- a/src/supplicant-manager/nm-supplicant-interface.c
+++ b/src/supplicant-manager/nm-supplicant-interface.c
@@ -128,16 +128,36 @@ bss_props_changed_cb (GDBusProxy *proxy,
 	               changed_properties);
 }
 
+static GVariant *
+_get_bss_proxy_properties (NMSupplicantInterface *self, GDBusProxy *proxy)
+{
+	gs_strfreev char **properties = NULL;
+	GVariantBuilder builder;
+	char **iter;
+
+	iter = properties = g_dbus_proxy_get_cached_property_names (proxy);
+	if (!iter)
+		return NULL;
+
+	g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+	while (*iter) {
+		GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter);
+
+		g_variant_builder_add (&builder, "{sv}", *iter++, copy);
+		g_variant_unref (copy);
+	}
+
+	return g_variant_builder_end (&builder);
+}
+
+#define BSS_PROXY_INITED "bss-proxy-inited"
+
 static void
 on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
 	NMSupplicantInterface *self;
-	NMSupplicantInterfacePrivate *priv;
 	gs_free_error GError *error = NULL;
-	gs_strfreev char **properties = NULL;
 	gs_unref_variant GVariant *props = NULL;
-	GVariantBuilder builder;
-	char **iter;
 
 	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
@@ -149,19 +169,12 @@ on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_da
 	}
 
 	self = NM_SUPPLICANT_INTERFACE (user_data);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
-
-	iter = properties = g_dbus_proxy_get_cached_property_names (proxy);
-	while (*iter) {
-		GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter);
+	props = _get_bss_proxy_properties (self, proxy);
+	if (!props)
+		return;
 
-		g_variant_builder_add (&builder, "{sv}", *iter++, copy);
-		g_variant_unref (copy);
-	}
+	g_object_set_data (G_OBJECT (proxy), BSS_PROXY_INITED, GUINT_TO_POINTER (TRUE));
 
-	props = g_variant_builder_end (&builder);
 	g_signal_emit (self, signals[NEW_BSS], 0,
 	               g_dbus_proxy_get_object_path (proxy),
 	               g_variant_ref_sink (props));
@@ -508,11 +521,30 @@ signal_cb (GDBusProxy  *proxy,
 	gboolean success;
 
 	if (MATCH_SIGNAL (signal, "ScanDone", args, G_VARIANT_TYPE ("(b)"))) {
+		GVariant *props;
+		GHashTableIter iter;
+		char *bss_path;
+		GDBusProxy *bss_proxy;
+
 		/* Cache last scan completed time */
 		priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
 
 		g_variant_get (args, "(b)", &success);
 		g_signal_emit (self, signals[SCAN_DONE], 0, success);
+
+		/* Emit NEW_BSS so that wifi device has the APs (in case it removed them) */
+		g_hash_table_iter_init (&iter, priv->bss_proxies);
+		while (g_hash_table_iter_next (&iter, (gpointer) &bss_path, (gpointer) &bss_proxy)) {
+			if (g_object_get_data (G_OBJECT (bss_proxy), BSS_PROXY_INITED)) {
+				props = _get_bss_proxy_properties (self, bss_proxy);
+				if (props) {
+					g_signal_emit (self, signals[NEW_BSS], 0,
+					               bss_path,
+					               g_variant_ref_sink (props));
+					g_variant_unref (props);
+				}
+			}
+		}
 	} else if (MATCH_SIGNAL (signal, "BSSAdded", args, G_VARIANT_TYPE ("(oa{sv})"))) {
 		if (priv->scanning)
 			priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
@@ -556,7 +588,7 @@ props_changed_cb (GDBusProxy *proxy,
 		set_state_from_string (self, s);
 	}
 
-	if (g_variant_lookup (changed_properties, "BSSs", "^a&s", &array)) {
+	if (g_variant_lookup (changed_properties, "BSSs", "^a&o", &array)) {
 		iter = array;
 		while (*iter)
 			handle_new_bss (self, *iter++);
diff --git a/src/supplicant-manager/tests/Makefile.am b/src/supplicant-manager/tests/Makefile.am
index 85268dcf..517f57b7 100644
--- a/src/supplicant-manager/tests/Makefile.am
+++ b/src/supplicant-manager/tests/Makefile.am
@@ -1,5 +1,8 @@
+SUBDIRS=certs
+
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src \
@@ -7,6 +10,7 @@ AM_CPPFLAGS = \
 	-DG_LOG_DOMAIN=\""NetworkManager"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+	-DTEST_CERT_DIR=\"$(srcdir)/certs/\" \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS)
 
diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in
index ef5233b2..e36c4c00 100644
--- a/src/supplicant-manager/tests/Makefile.in
+++ b/src/supplicant-manager/tests/Makefile.in
@@ -157,11 +157,27 @@ am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = $(test_supplicant_config_SOURCES)
 DIST_SOURCES = $(test_supplicant_config_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+	ctags-recursive dvi-recursive html-recursive info-recursive \
+	install-data-recursive install-dvi-recursive \
+	install-exec-recursive install-html-recursive \
+	install-info-recursive install-pdf-recursive \
+	install-ps-recursive install-recursive installcheck-recursive \
+	installdirs-recursive pdf-recursive ps-recursive \
+	tags-recursive uninstall-recursive
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+	check recheck distdir
 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
 # Read a list of newline-separated strings from the standard input,
 # and print each of them once, without duplicates.  Input order is
@@ -364,7 +380,6 @@ am__set_TESTS_bases = \
   bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
   bases=`echo $$bases`
 RECHECK_LOGS = $(TEST_LOGS)
-AM_RECURSIVE_TARGETS = check recheck
 TEST_SUITE_LOG = test-suite.log
 TEST_EXTENSIONS = @EXEEXT@ .test
 LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
@@ -384,10 +399,36 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log)
 TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
 TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
 	$(TEST_LOG_FLAGS)
+DIST_SUBDIRS = $(SUBDIRS)
 am__DIST_COMMON = $(srcdir)/Makefile.in \
 	$(top_srcdir)/build-aux/depcomp \
 	$(top_srcdir)/build-aux/test-driver
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
 ACLOCAL = @ACLOCAL@
 ALL_LINGUAS = @ALL_LINGUAS@
 AMTAR = @AMTAR@
@@ -510,6 +551,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -650,8 +692,10 @@ with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
+SUBDIRS = certs
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src \
@@ -659,6 +703,7 @@ AM_CPPFLAGS = \
 	-DG_LOG_DOMAIN=\""NetworkManager"\" \
 	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+	-DTEST_CERT_DIR=\"$(srcdir)/certs/\" \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS)
 
@@ -668,7 +713,7 @@ test_supplicant_config_SOURCES = \
 test_supplicant_config_LDADD = \
 	$(top_builddir)/src/libNetworkManager.la
 
-all: all-am
+all: all-recursive
 
 .SUFFIXES:
 .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
@@ -750,14 +795,61 @@ mostlyclean-libtool:
 clean-libtool:
 	-rm -rf .libs _libs
 
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+	@fail=; \
+	if $(am__make_keepgoing); then \
+	  failcom='fail=yes'; \
+	else \
+	  failcom='exit 1'; \
+	fi; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
 ID: $(am__tagged_files)
 	$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
+tags: tags-recursive
 TAGS: tags
 
 tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
 	set x; \
 	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
 	$(am__define_uniq_tagged_files); \
 	shift; \
 	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
@@ -770,7 +862,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
 	      $$unique; \
 	  fi; \
 	fi
-ctags: ctags-am
+ctags: ctags-recursive
 
 CTAGS: ctags
 ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
@@ -783,7 +875,7 @@ GTAGS:
 	here=`$(am__cd) $(top_builddir) && pwd` \
 	  && $(am__cd) $(top_srcdir) \
 	  && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
+cscopelist: cscopelist-recursive
 
 cscopelist-am: $(am__tagged_files)
 	list='$(am__tagged_files)'; \
@@ -995,20 +1087,46 @@ distdir: $(DISTFILES)
 	    || exit 1; \
 	  fi; \
 	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    $(am__make_dryrun) \
+	      || test -d "$(distdir)/$$subdir" \
+	      || $(MKDIR_P) "$(distdir)/$$subdir" \
+	      || exit 1; \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
 check-am: all-am
 	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
-check: check-am
+check: check-recursive
 all-am: Makefile $(PROGRAMS)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
 
 install-am: all-am
 	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
 
-installcheck: installcheck-am
+installcheck: installcheck-recursive
 install-strip:
 	if test -z '$(STRIP)'; then \
 	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
@@ -1033,92 +1151,93 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
+clean: clean-recursive
 
 clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
 	mostlyclean-am
 
-distclean: distclean-am
+distclean: distclean-recursive
 	-rm -rf ./$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-tags
 
-dvi: dvi-am
+dvi: dvi-recursive
 
 dvi-am:
 
-html: html-am
+html: html-recursive
 
 html-am:
 
-info: info-am
+info: info-recursive
 
 info-am:
 
 install-data-am:
 
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
 
 install-dvi-am:
 
 install-exec-am:
 
-install-html: install-html-am
+install-html: install-html-recursive
 
 install-html-am:
 
-install-info: install-info-am
+install-info: install-info-recursive
 
 install-info-am:
 
 install-man:
 
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
 
 install-pdf-am:
 
-install-ps: install-ps-am
+install-ps: install-ps-recursive
 
 install-ps-am:
 
 installcheck-am:
 
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
 	-rm -rf ./$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
 
 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
 	mostlyclean-libtool
 
-pdf: pdf-am
+pdf: pdf-recursive
 
 pdf-am:
 
-ps: ps-am
+ps: ps-recursive
 
 ps-am:
 
 uninstall-am:
 
-.MAKE: check-am install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
-	clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \
-	ctags ctags-am distclean distclean-compile distclean-generic \
-	distclean-libtool distclean-tags distdir dvi dvi-am html \
-	html-am info info-am install install-am install-data \
-	install-data-am install-dvi install-dvi-am install-exec \
-	install-exec-am install-html install-html-am install-info \
-	install-info-am install-man install-pdf install-pdf-am \
-	install-ps install-ps-am install-strip installcheck \
-	installcheck-am installdirs maintainer-clean \
-	maintainer-clean-generic mostlyclean mostlyclean-compile \
-	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-	recheck tags tags-am uninstall uninstall-am
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+	check-TESTS check-am clean clean-generic clean-libtool \
+	clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \
+	uninstall uninstall-am
 
 .PRECIOUS: Makefile
 
diff --git a/src/supplicant-manager/tests/certs/Makefile.am b/src/supplicant-manager/tests/certs/Makefile.am
new file mode 100644
index 00000000..f2e889f7
--- /dev/null
+++ b/src/supplicant-manager/tests/certs/Makefile.am
@@ -0,0 +1,6 @@
+CERTS = \
+	test-ca-cert.pem \
+	test-cert.p12
+
+EXTRA_DIST = $(CERTS)
+
diff --git a/src/supplicant-manager/tests/certs/Makefile.in b/src/supplicant-manager/tests/certs/Makefile.in
new file mode 100644
index 00000000..fcfdd689
--- /dev/null
+++ b/src/supplicant-manager/tests/certs/Makefile.in
@@ -0,0 +1,596 @@
+# Makefile.in generated by automake 1.15 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2014 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/supplicant-manager/tests/certs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_warnings.m4 \
+	$(top_srcdir)/m4/gettext.m4 \
+	$(top_srcdir)/m4/gnome-code-coverage.m4 \
+	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
+	$(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \
+	$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AM_TESTS_FD_REDIRECT = @AM_TESTS_FD_REDIRECT@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CKDB_PATH = @CKDB_PATH@
+CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
+DLLTOOL = @DLLTOOL@
+DNSMASQ_PATH = @DNSMASQ_PATH@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MAKEFILE = @GLIB_MAKEFILE@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+IPTABLES_PATH = @IPTABLES_PATH@
+IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
+IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
+LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOG_DRIVER = @LOG_DRIVER@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@
+MM_GLIB_LIBS = @MM_GLIB_LIBS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@
+NM_VERSION = @NM_VERSION@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
+QT_CFLAGS = @QT_CFLAGS@
+QT_LIBS = @QT_LIBS@
+RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
+SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
+SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
+SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
+SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
+SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_DIR = @UDEV_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
+VAPIGEN = @VAPIGEN@
+VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
+VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nmbinary = @nmbinary@
+nmconfdir = @nmconfdir@
+nmdatadir = @nmdatadir@
+nmrundir = @nmrundir@
+nmstatedir = @nmstatedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+with_dhclient = @with_dhclient@
+with_dhcpcd = @with_dhcpcd@
+with_netconfig = @with_netconfig@
+with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
+CERTS = \
+	test-ca-cert.pem \
+	test-cert.p12
+
+EXTRA_DIST = $(CERTS)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/supplicant-manager/tests/certs/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/supplicant-manager/tests/certs/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	cscopelist-am ctags-am distclean distclean-generic \
+	distclean-libtool distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/supplicant-manager/tests/certs/test-ca-cert.pem b/src/supplicant-manager/tests/certs/test-ca-cert.pem
new file mode 100644
index 00000000..ef1be20d
--- /dev/null
+++ b/src/supplicant-manager/tests/certs/test-ca-cert.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEjzCCA3egAwIBAgIJAOvnZPt59yIZMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD
+VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw
+FQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UE
+AxMEdGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAzMTAx
+NTEyMTRaFw0xOTAzMDgxNTEyMTRaMIGLMQswCQYDVQQGEwJVUzESMBAGA1UECBMJ
+QmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55
+IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3
+DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKot9j+/+CX1/gZLgJHIXCRgCItKLGnf7qGbgqB9T2ACBqR0jllKWwDKrcWU
+xjXNIc+GF9Wnv+lX6G0Okn4Zt3/uRNobL+2b/yOF7M3Td3/9W873zdkQQX930YZc
+Rr8uxdRPP5bxiCgtcw632y21sSEbG9mjccAUnV/0jdvfmMNj0i8gN6E0fMBiJ9S3
+FkxX/KFvt9JWE9CtoyL7ki7UIDq+6vj7Gd5N0B3dOa1y+rRHZzKlJPcSXQSEYUS4
+HmKDwiKSVahft8c4tDn7KPi0vex91hlgZVd3usL2E/Vq7o5D9FAZ5kZY0AdFXwdm
+J4lO4Mj7ac7GE4vNERNcXVIX59sCAwEAAaOB8zCB8DAdBgNVHQ4EFgQUuDU3Mr7P
+T3n1e3Sy8hBauoDFahAwgcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDF
+ahChgZGkgY4wgYsxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO
+BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQL
+EwdUZXN0aW5nMQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRl
+c3QuY29tggkA6+dk+3n3IhkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
+AQEAVRG4aALIvCXCiKfe7K+iJxjBVRDFPEf7JWA9LGgbFOn6pNvbxonrR+0BETdc
+JV1ET4ct2xsE7QNFIkp9GKRC+6J32zCo8qtLCD5+v436r8TUG2/t2JRMkb9I2XVT
+p7RJoot6M0Ltf8KNQUPYh756xmKZ4USfQUwc58MOSDGY8VWEXJOYij9Pf0e0c52t
+qiCEjXH7uXiS8Pgq9TYm7AkWSOrglYhSa83x0f8mtT8Q15nBESIHZ6o8FAS2bBgn
+B0BkrKRjtBUkuJG3vTox+bYINh2Gxi1JZHWSV1tN5z3hd4VFcKqanW5OgQwToBqp
+3nniskIjbH0xjgZf/nVMyLnjxg==
+-----END CERTIFICATE-----
diff --git a/src/supplicant-manager/tests/certs/test-cert.p12 b/src/supplicant-manager/tests/certs/test-cert.p12
new file mode 100644
index 00000000..ae4a6830
--- /dev/null
+++ b/src/supplicant-manager/tests/certs/test-cert.p12
Binary files differdiff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c
index 937757b2..15be2ba8 100644
--- a/src/supplicant-manager/tests/test-supplicant-config.c
+++ b/src/supplicant-manager/tests/test-supplicant-config.c
@@ -269,7 +269,8 @@ test_wifi_wep_key (const char *detail,
 	g_assert (nm_supplicant_config_add_setting_wireless_security (config,
 	                                                              s_wsec,
 	                                                              NULL,
-	                                                              "376aced7-b28c-46be-9a62-fcdf072571da"));
+	                                                              "376aced7-b28c-46be-9a62-fcdf072571da",
+	                                                              1500));
 	g_test_assert_expected_messages ();
 
 	config_dict = nm_supplicant_config_to_variant (config);
@@ -409,7 +410,8 @@ test_wifi_wpa_psk (const char *detail,
 	g_assert (nm_supplicant_config_add_setting_wireless_security (config,
 	                                                              s_wsec,
 	                                                              NULL,
-	                                                              "376aced7-b28c-46be-9a62-fcdf072571da"));
+	                                                              "376aced7-b28c-46be-9a62-fcdf072571da",
+	                                                              1500));
 	g_test_assert_expected_messages ();
 
 	config_dict = nm_supplicant_config_to_variant (config);
@@ -439,6 +441,142 @@ test_wifi_wpa_psk_types (void)
 	test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2, (gconstpointer) key2, strlen (key2));
 }
 
+static void
+test_wifi_eap (void)
+{
+	gs_unref_object NMConnection *connection = NULL;
+	gs_unref_object NMSupplicantConfig *config = NULL;
+	gs_unref_variant GVariant *config_dict = NULL;
+	NMSettingConnection *s_con;
+	NMSettingWireless *s_wifi;
+	NMSettingWirelessSecurity *s_wsec;
+	NMSetting8021x *s_8021x;
+	NMSettingIPConfig *s_ip4;
+	char *uuid;
+	gboolean success;
+	GError *error = NULL;
+	GBytes *ssid;
+	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
+	const char *bssid_str = "11:22:33:44:55:66";
+	guint32 mtu = 1100;
+
+	connection = nm_simple_connection_new ();
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Wifi EAP-TLS",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wifi setting */
+	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	ssid = g_bytes_new (ssid_data, sizeof (ssid_data));
+
+	g_object_set (s_wifi,
+	              NM_SETTING_WIRELESS_SSID, ssid,
+	              NM_SETTING_WIRELESS_BSSID, bssid_str,
+	              NM_SETTING_WIRELESS_MODE, "infrastructure",
+	              NM_SETTING_WIRELESS_BAND, "bg",
+	              NULL);
+
+	g_bytes_unref (ssid);
+
+	/* Wifi Security setting */
+	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+	g_object_set (s_wsec,
+	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap",
+	              NULL);
+
+	nm_setting_wireless_security_add_proto (s_wsec, "wpa");
+	nm_setting_wireless_security_add_proto (s_wsec, "rsn");
+	nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
+	nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp");
+	nm_setting_wireless_security_add_group (s_wsec, "tkip");
+	nm_setting_wireless_security_add_group (s_wsec, "ccmp");
+
+	/* 802-1X setting */
+	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+	nm_setting_802_1x_add_eap_method (s_8021x, "tls");
+	nm_setting_802_1x_set_client_cert (s_8021x, TEST_CERT_DIR "test-cert.p12", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL);
+	nm_setting_802_1x_set_ca_cert (s_8021x, TEST_CERT_DIR "test-ca-cert.pem", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL);
+	nm_setting_802_1x_set_private_key (s_8021x, TEST_CERT_DIR "test-cert.p12", NULL, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL);
+
+	/* IP4 setting */
+	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	config = nm_supplicant_config_new ();
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'ssid' value 'Test SSID'*");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'scan_ssid' value '1'*");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'bssid' value '11:22:33:44:55:66'*");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'freq_list' value *");
+	g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'key_mgmt' value 'WPA-EAP'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'proto' value 'WPA RSN'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'pairwise' value 'TKIP CCMP'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*added 'group' value 'TKIP CCMP'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*Config: added 'eap' value 'TLS'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*Config: added 'fragment_size' value '1086'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "* Config: added 'ca_cert' value '*/test-ca-cert.pem'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "* Config: added 'private_key' value '*/test-cert.p12'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*Config: added 'bgscan' value 'simple:30:-65:300'");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+	                       "*Config: added 'proactive_key_caching' value '1'");
+	g_assert (nm_supplicant_config_add_setting_wireless_security (config,
+	                                                              s_wsec,
+	                                                              s_8021x,
+	                                                              "d5b488af-9cab-41ed-bad4-97709c58430f",
+	                                                              mtu));
+	g_test_assert_expected_messages ();
+
+	config_dict = nm_supplicant_config_to_variant (config);
+	g_assert (config_dict);
+
+	validate_opt ("wifi-eap", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
+	validate_opt ("wifi-eap", config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
+	validate_opt ("wifi-eap", config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1);
+	validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-EAP", -1);
+	validate_opt ("wifi-eap", config_dict, "eap", TYPE_KEYWORD, "TLS", -1);
+	validate_opt ("wifi-eap", config_dict, "proto", TYPE_KEYWORD, "WPA RSN", -1);
+	validate_opt ("wifi-eap", config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1);
+	validate_opt ("wifi-eap", config_dict, "group", TYPE_KEYWORD, "TKIP CCMP", -1);
+	validate_opt ("wifi-eap", config_dict, "fragment_size", TYPE_INT, GINT_TO_POINTER(mtu-14), -1);
+}
+
 NMTST_DEFINE ();
 
 int main (int argc, char **argv)
@@ -448,6 +586,7 @@ int main (int argc, char **argv)
 	g_test_add_func ("/supplicant-config/wifi-open", test_wifi_open);
 	g_test_add_func ("/supplicant-config/wifi-wep", test_wifi_wep);
 	g_test_add_func ("/supplicant-config/wifi-wpa-psk-types", test_wifi_wpa_psk_types);
+	g_test_add_func ("/supplicant-config/wifi-eap", test_wifi_eap);
 
 	return g_test_run ();
 }
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 83632bd1..eebdb248 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -2,6 +2,7 @@ SUBDIRS = config
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src/platform \
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
index f84c5536..a4527284 100644
--- a/src/tests/Makefile.in
+++ b/src/tests/Makefile.in
@@ -609,6 +609,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -752,6 +753,7 @@ with_valgrind = @with_valgrind@
 SUBDIRS = config
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src/platform \
diff --git a/src/tests/config/Makefile.am b/src/tests/config/Makefile.am
index 42c6b9a1..a5e068e4 100644
--- a/src/tests/config/Makefile.am
+++ b/src/tests/config/Makefile.am
@@ -1,5 +1,6 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src/ \
diff --git a/src/tests/config/Makefile.in b/src/tests/config/Makefile.in
index 6d1dd4bc..20bbe60a 100644
--- a/src/tests/config/Makefile.in
+++ b/src/tests/config/Makefile.in
@@ -510,6 +510,7 @@ LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
@@ -652,6 +653,7 @@ with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src/ \
diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c
index 8b8028e6..6dad8216 100644
--- a/src/tests/config/test-config.c
+++ b/src/tests/config/test-config.c
@@ -380,7 +380,7 @@ test_config_confdir (void)
 	g_assert_cmpstr (value, ==, "VAL5");
 	g_free (value);
 
-	nm_config_data_log (nm_config_get_data_orig (config), ">>> TEST: ");
+	nm_config_data_log (nm_config_get_data_orig (config), ">>> TEST: ", " ", NULL);
 
 	g_object_unref (config);
 }
@@ -396,6 +396,89 @@ test_config_confdir_parse_error (void)
 	g_clear_error (&error);
 }
 
+/*****************************************************************************/
+
+static void
+_test_signal_config_changed_cb (NMConfig *config,
+                                NMConfigData *config_data,
+                                NMConfigChangeFlags changes,
+                                NMConfigData *old_data,
+                                gpointer user_data)
+{
+	const NMConfigChangeFlags *expected = user_data;
+
+	g_assert (changes);
+	g_assert_cmpint (changes, ==, *expected);
+	g_assert (NM_IS_CONFIG (config));
+	g_assert (NM_IS_CONFIG_DATA (config_data));
+
+	g_assert (config_data == old_data);
+	g_assert (config_data == nm_config_get_data (config));
+}
+
+static void
+_test_signal_config_changed_cb2 (NMConfig *config,
+                                 NMConfigData *config_data,
+                                 NMConfigChangeFlags changes,
+                                 NMConfigData *old_data,
+                                 gpointer user_data)
+{
+	const NMConfigChangeFlags *expected = user_data;
+
+	g_assert (changes);
+	g_assert_cmpint (changes, ==, *expected);
+}
+
+static void
+test_config_signal (void)
+{
+	gs_unref_object NMConfig *config = NULL;
+	NMConfigChangeFlags expected;
+	gs_unref_object NMConfigData *config_data_orig = NULL;
+
+	config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "/no/such/dir", NULL);
+
+	config_data_orig = g_object_ref (nm_config_get_data_orig (config));
+
+	g_signal_connect (G_OBJECT (config),
+	                  NM_CONFIG_SIGNAL_CONFIG_CHANGED,
+	                  G_CALLBACK (_test_signal_config_changed_cb),
+	                  &expected);
+
+	expected = NM_CONFIG_CHANGE_SIGUSR1;
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGUSR1");
+	nm_config_reload (config, SIGUSR1);
+
+	expected = NM_CONFIG_CHANGE_SIGUSR2;
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGUSR2");
+	nm_config_reload (config, SIGUSR2);
+
+	expected = NM_CONFIG_CHANGE_SIGHUP;
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGHUP (no changes from disk)*");
+	nm_config_reload (config, SIGHUP);
+
+
+	/* test with subscribing two signals...
+	 *
+	 * This test exposes glib bug https://bugzilla.redhat.com/show_bug.cgi?id=1260577
+	 * for which we however have a workaround in 'nm-config.c' */
+	g_signal_connect (G_OBJECT (config),
+	                  NM_CONFIG_SIGNAL_CONFIG_CHANGED,
+	                  G_CALLBACK (_test_signal_config_changed_cb2),
+	                  &expected);
+	expected = NM_CONFIG_CHANGE_SIGUSR2;
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, "*config: signal SIGUSR2");
+	nm_config_reload (config, SIGUSR2);
+	g_signal_handlers_disconnect_by_func (config, _test_signal_config_changed_cb2, &expected);
+
+
+	g_signal_handlers_disconnect_by_func (config, _test_signal_config_changed_cb, &expected);
+
+	g_assert (config_data_orig == nm_config_get_data (config));
+}
+
+/*****************************************************************************/
+
 NMTST_DEFINE ();
 
 int
@@ -419,6 +502,8 @@ main (int argc, char **argv)
 	g_test_add_func ("/config/confdir", test_config_confdir);
 	g_test_add_func ("/config/confdir-parse-error", test_config_confdir_parse_error);
 
+	g_test_add_func ("/config/signal", test_config_signal);
+
 	/* This one has to come last, because it leaves its values in
 	 * nm-config.c's global variables, and there's no way to reset
 	 * those to NULL.
diff --git a/src/tests/test-general-with-expect.c b/src/tests/test-general-with-expect.c
index fe76e3fa..21fb0681 100644
--- a/src/tests/test-general-with-expect.c
+++ b/src/tests/test-general-with-expect.c
@@ -23,6 +23,7 @@
 #include <glib.h>
 #include <string.h>
 #include <errno.h>
+#include <time.h>
 #include <netinet/ether.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -33,6 +34,10 @@
 
 #include "nm-test-utils.h"
 
+#ifndef CLOCK_BOOTTIME
+#define CLOCK_BOOTTIME 7
+#endif
+
 /*******************************************/
 
 static void
@@ -284,9 +289,9 @@ test_nm_utils_kill_child (void)
 
 	fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
 
-	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-1-1' (*): waiting up to 500 milliseconds for process to terminate normally after sending SIGTERM (15)...");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-1-1' (*): waiting up to 3000 milliseconds for process to terminate normally after sending SIGTERM (15)...");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-1-1' (*): after sending SIGTERM (15), process * exited by signal 15 (* usec elapsed)");
-	test_nm_utils_kill_child_sync_do ("test-s-1-1", pid1s_1, SIGTERM, 1000 / 2, TRUE,  &expected_signal_TERM);
+	test_nm_utils_kill_child_sync_do ("test-s-1-1", pid1s_1, SIGTERM, 3000, TRUE,  &expected_signal_TERM);
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-1-2' (*): waiting for process to terminate after sending SIGKILL (9)...");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-1-2' (*): after sending SIGKILL (9), process * exited by signal 9 (* usec elapsed)");
@@ -298,16 +303,16 @@ test_nm_utils_kill_child (void)
 	test_nm_utils_kill_child_sync_do ("test-s-1-3", pid1s_3, 0, 1, TRUE,  &expected_signal_KILL);
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-2' (*): process * already terminated normally with status 47");
-	test_nm_utils_kill_child_sync_do ("test-s-2", pid2s, SIGTERM, 1000 / 2, TRUE,  &expected_exit_47);
+	test_nm_utils_kill_child_sync_do ("test-s-2", pid2s, SIGTERM, 3000, TRUE,  &expected_exit_47);
 
 	/* send invalid signal. */
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*kill child process 'test-s-3-0' (*): failed to send Unexpected signal: Invalid argument (22)");
 	test_nm_utils_kill_child_sync_do ("test-s-3-0", pid3s, -1, 0, FALSE, NULL);
 
 	/* really kill pid3s */
-	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-3-1' (*): waiting up to 500 milliseconds for process to terminate normally after sending SIGTERM (15)...");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-3-1' (*): waiting up to 3000 milliseconds for process to terminate normally after sending SIGTERM (15)...");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-s-3-1' (*): after sending SIGTERM (15), process * exited normally with status 47 (* usec elapsed)");
-	test_nm_utils_kill_child_sync_do ("test-s-3-1", pid3s, SIGTERM, 1000 / 2, TRUE,  &expected_exit_47);
+	test_nm_utils_kill_child_sync_do ("test-s-3-1", pid3s, SIGTERM, 3000, TRUE,  &expected_exit_47);
 
 	/* pid3s should not be a valid process, hence the call should fail. Note, that there
 	 * is a race here. */
@@ -320,9 +325,9 @@ test_nm_utils_kill_child (void)
 	test_nm_utils_kill_child_sync_do ("test-s-4", pid4s, SIGTERM, 1, TRUE, &expected_signal_KILL);
 
 
-	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-1-1' (*): wait for process to terminate after sending SIGTERM (15) (send SIGKILL in 500 milliseconds)...");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-1-1' (*): wait for process to terminate after sending SIGTERM (15) (send SIGKILL in 3000 milliseconds)...");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-1-1' (*): terminated by signal 15 (* usec elapsed)");
-	test_nm_utils_kill_child_async_do ("test-a-1-1", pid1a_1, SIGTERM, 1000 / 2, TRUE, &expected_signal_TERM);
+	test_nm_utils_kill_child_async_do ("test-a-1-1", pid1a_1, SIGTERM, 3000, TRUE, &expected_signal_TERM);
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-1-2' (*): wait for process to terminate after sending SIGKILL (9)...");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-1-2' (*): terminated by signal 9 (* usec elapsed)");
@@ -335,16 +340,16 @@ test_nm_utils_kill_child (void)
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-2' (*): process * already terminated normally with status 47");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-2' (*): invoke callback: terminated normally with status 47");
-	test_nm_utils_kill_child_async_do ("test-a-2", pid2a, SIGTERM, 1000 / 2, TRUE, &expected_exit_47);
+	test_nm_utils_kill_child_async_do ("test-a-2", pid2a, SIGTERM, 3000, TRUE, &expected_exit_47);
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*kill child process 'test-a-3-0' (*): unexpected error sending Unexpected signal: Invalid argument (22)");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-3-0' (*): invoke callback: killing child failed");
 	/* coverity[negative_returns] */
 	test_nm_utils_kill_child_async_do ("test-a-3-0", pid3a, -1, 1000 / 2, FALSE, NULL);
 
-	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-3-1' (*): wait for process to terminate after sending SIGTERM (15) (send SIGKILL in 500 milliseconds)...");
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-3-1' (*): wait for process to terminate after sending SIGTERM (15) (send SIGKILL in 3000 milliseconds)...");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_DEBUG, "*kill child process 'test-a-3-1' (*): terminated normally with status 47 (* usec elapsed)");
-	test_nm_utils_kill_child_async_do ("test-a-3-1", pid3a, SIGTERM, 1000 / 2, TRUE, &expected_exit_47);
+	test_nm_utils_kill_child_async_do ("test-a-3-1", pid3a, SIGTERM, 3000, TRUE, &expected_exit_47);
 
 	/* pid3a should not be a valid process, hence the call should fail. Note, that there
 	 * is a race here. */
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
index de65d50f..094a4a65 100644
--- a/src/tests/test-general.c
+++ b/src/tests/test-general.c
@@ -440,6 +440,82 @@ test_connection_match_wired (void)
 }
 
 static void
+test_connection_match_wired2 (void)
+{
+	NMConnection *orig, *copy, *matched;
+	GSList *connections = NULL;
+	NMSettingWired *s_wired;
+	const char *mac = "52:54:00:ab:db:23";
+
+	orig = _match_connection_new ();
+	s_wired = nm_connection_get_setting_wired (orig);
+	g_assert (s_wired);
+	g_object_set (G_OBJECT (s_wired),
+	              NM_SETTING_WIRED_PORT, "tp",           /* port is not compared */
+	              NM_SETTING_WIRED_MAC_ADDRESS, mac,     /* we allow MAC address just in one connection */
+	              NULL);
+
+	copy = nm_simple_connection_new_clone (orig);
+	connections = g_slist_append (connections, copy);
+
+	/* Check that if the generated connection do not have wired setting
+	 * and s390 properties in the existing connection's setting are default,
+	 * the connections match. It can happen if assuming VLAN devices. */
+	nm_connection_remove_setting (orig, NM_TYPE_SETTING_WIRED);
+
+	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	g_assert (matched == copy);
+
+	g_slist_free (connections);
+	g_object_unref (orig);
+	g_object_unref (copy);
+}
+
+static void
+test_connection_match_cloned_mac (void)
+{
+	NMConnection *orig, *exact, *fuzzy, *matched;
+	GSList *connections = NULL;
+	NMSettingWired *s_wired;
+
+	orig = _match_connection_new ();
+
+	fuzzy = nm_simple_connection_new_clone (orig);
+	connections = g_slist_append (connections, fuzzy);
+	s_wired = nm_connection_get_setting_wired (orig);
+	g_assert (s_wired);
+	g_object_set (G_OBJECT (s_wired),
+	              NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:23",
+	              NULL);
+
+	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	g_assert (matched == fuzzy);
+
+	exact = nm_simple_connection_new_clone (orig);
+	connections = g_slist_append (connections, exact);
+	s_wired = nm_connection_get_setting_wired (exact);
+	g_assert (s_wired);
+	g_object_set (G_OBJECT (s_wired),
+	              NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:23",
+	              NULL);
+
+	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	g_assert (matched == exact);
+
+	g_object_set (G_OBJECT (s_wired),
+	              NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "52:54:00:ab:db:24",
+	              NULL);
+
+	matched = nm_utils_match_connection (connections, orig, TRUE, NULL, NULL);
+	g_assert (matched == fuzzy);
+
+	g_slist_free (connections);
+	g_object_unref (orig);
+	g_object_unref (fuzzy);
+	g_object_unref (exact);
+}
+
+static void
 test_connection_no_match_ip4_addr (void)
 {
 	NMConnection *orig, *copy, *matched;
@@ -747,6 +823,8 @@ main (int argc, char **argv)
 	g_test_add_func ("/general/connection-match/ip4-method", test_connection_match_ip4_method);
 	g_test_add_func ("/general/connection-match/con-interface-name", test_connection_match_interface_name);
 	g_test_add_func ("/general/connection-match/wired", test_connection_match_wired);
+	g_test_add_func ("/general/connection-match/wired2", test_connection_match_wired2);
+	g_test_add_func ("/general/connection-match/cloned_mac", test_connection_match_cloned_mac);
 	g_test_add_func ("/general/connection-match/no-match-ip4-addr", test_connection_no_match_ip4_addr);
 
 	g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index c34155ef..e2d3103b 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -933,7 +933,7 @@ apply_parent_device_config (NMVpnConnection *connection)
 		 * default route. */
 		if (vpn4_parent_config) {
 			nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
-			nm_ip4_config_set_gateway (vpn4_parent_config, 0);
+			nm_ip4_config_unset_gateway (vpn4_parent_config);
 		}
 		if (vpn6_parent_config) {
 			nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_DEFAULT);
@@ -980,6 +980,9 @@ nm_vpn_connection_apply_config (NMVpnConnection *connection)
 			                           TRUE))
 				return FALSE;
 		}
+
+		if (priv->mtu && priv->mtu != nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ip_ifindex))
+			nm_platform_link_set_mtu (NM_PLATFORM_GET, priv->ip_ifindex, priv->mtu);
 	}
 
 	apply_parent_device_config (connection);
@@ -1149,10 +1152,6 @@ process_generic_config (NMVpnConnection *connection,
 		}
 	}
 
-	/* MTU; this is a per-connection value, though NM's API treats it
-	 * like it's IP4-specific. So we store it for now and retrieve it
-	 * later in ip4_config_get.
-	 */
 	priv->mtu = 0;
 	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_MTU);
 	if (val) {
@@ -1328,9 +1327,6 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
 	if (val)
 		nm_ip4_config_set_mss (config, g_value_get_uint (val));
 
-	if (priv->mtu)
-		nm_ip4_config_set_mtu (config, priv->mtu, NM_IP_CONFIG_SOURCE_VPN);
-
 	val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN);
 	if (val)
 		nm_ip4_config_add_domain (config, g_value_get_string (val));