summary refs log tree commit diff
path: root/src/devices
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices')
-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
29 files changed, 390 insertions, 268 deletions
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 */