summary refs log tree commit diff
path: root/src/devices/wifi
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2016-08-26 02:18:32 +0200
committerMichael Biebl <biebl@debian.org>2016-08-26 02:18:32 +0200
commit7514efc2f38c9ace4557d4e69d68e7d380389030 (patch)
tree7fb00fda86cfcc2ca377f191633a7cfdbfea7ca3 /src/devices/wifi
parentd6201f5d8daada3d64a0a3e0038e14eebec683ce (diff)
Imported Upstream version 1.4.0 upstream/1.4.0
Diffstat (limited to 'src/devices/wifi')
-rw-r--r--src/devices/wifi/Makefile.am1
-rw-r--r--src/devices/wifi/Makefile.in15
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.h6
-rw-r--r--src/devices/wifi/nm-device-wifi.c451
-rw-r--r--src/devices/wifi/nm-device-wifi.h47
-rw-r--r--src/devices/wifi/nm-wifi-ap.c210
-rw-r--r--src/devices/wifi/nm-wifi-ap.h10
-rw-r--r--src/devices/wifi/tests/Makefile.in14
-rw-r--r--src/devices/wifi/tests/test-wifi-ap-utils.c2
9 files changed, 418 insertions, 338 deletions
diff --git a/src/devices/wifi/Makefile.am b/src/devices/wifi/Makefile.am
index e35a84b4..add0a007 100644
--- a/src/devices/wifi/Makefile.am
+++ b/src/devices/wifi/Makefile.am
@@ -52,6 +52,7 @@ if ENABLE_TESTS
 
 check-local:
 	$(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE)
+	LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-wifi.so $(top_builddir)/src/NetworkManager --version >/dev/null
 
 endif
 
diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in
index 34aa4b97..134c4012 100644
--- a/src/devices/wifi/Makefile.in
+++ b/src/devices/wifi/Makefile.in
@@ -90,8 +90,9 @@ build_triplet = @build@
 host_triplet = @host@
 subdir = src/devices/wifi
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
-	$(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \
+	$(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_options.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -295,6 +296,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
@@ -351,13 +353,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
+JANSSON_CFLAGS = @JANSSON_CFLAGS@
+JANSSON_LIBS = @JANSSON_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
 LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
-LIBDL = @LIBDL@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -369,6 +372,8 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
 LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
 LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
@@ -429,6 +434,8 @@ QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
 READLINE_LIBS = @READLINE_LIBS@
+SANITIZERS = @SANITIZERS@
+SANITIZER_ENV = @SANITIZER_ENV@
 SED = @SED@
 SELINUX_CFLAGS = @SELINUX_CFLAGS@
 SELINUX_LIBS = @SELINUX_LIBS@
@@ -464,6 +471,7 @@ ac_ct_AR = @ac_ct_AR@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_RANLIB = @ac_ct_RANLIB@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
@@ -967,6 +975,7 @@ include $(GLIB_MAKEFILE)
 
 @ENABLE_TESTS_TRUE@check-local:
 @ENABLE_TESTS_TRUE@	$(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE)
+@ENABLE_TESTS_TRUE@	LD_BIND_NOW=1 LD_PRELOAD=$(builddir)/.libs/libnm-device-plugin-wifi.so $(top_builddir)/src/NetworkManager --version >/dev/null
 
 # 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.
diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h
index 63895a88..135226d5 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.h
+++ b/src/devices/wifi/nm-device-olpc-mesh.h
@@ -30,8 +30,6 @@
 
 #include "nm-device.h"
 
-G_BEGIN_DECLS
-
 #define NM_TYPE_DEVICE_OLPC_MESH            (nm_device_olpc_mesh_get_type ())
 #define NM_DEVICE_OLPC_MESH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh))
 #define NM_DEVICE_OLPC_MESH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass))
@@ -67,6 +65,4 @@ GType nm_device_olpc_mesh_get_type (void);
 
 NMDevice *nm_device_olpc_mesh_new (const char *iface);
 
-G_END_DECLS
-
-#endif  /* NM_DEVICE_OLPC_MESH_H */
+#endif /* __NETWORKMANAGER_DEVICE_OLPC_MESH_H__ */
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 82b12a11..49c380af 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -21,6 +21,8 @@
 
 #include "nm-default.h"
 
+#include "nm-device-wifi.h"
+
 #include <netinet/in.h>
 #include <string.h>
 #include <unistd.h>
@@ -28,7 +30,6 @@
 
 #include "nm-common-macros.h"
 #include "nm-device.h"
-#include "nm-device-wifi.h"
 #include "nm-device-private.h"
 #include "nm-utils.h"
 #include "NetworkManagerUtils.h"
@@ -46,8 +47,8 @@
 #include "nm-platform.h"
 #include "nm-auth-utils.h"
 #include "nm-settings-connection.h"
+#include "nm-settings.h"
 #include "nm-enum-types.h"
-#include "nm-connection-provider.h"
 #include "nm-core-internal.h"
 #include "nm-config.h"
 
@@ -61,25 +62,20 @@ _LOG_DECLARE_SELF(NMDeviceWifi);
 #define SCAN_INTERVAL_STEP 20
 #define SCAN_INTERVAL_MAX 120
 
-#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries"
+#define SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN 5
 
-G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
-
-#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate))
+#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries"
 
+/*****************************************************************************/
 
-enum {
-	PROP_0,
-	PROP_PERM_HW_ADDRESS,
+NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi,
 	PROP_MODE,
 	PROP_BITRATE,
 	PROP_ACCESS_POINTS,
 	PROP_ACTIVE_ACCESS_POINT,
 	PROP_CAPABILITIES,
 	PROP_SCANNING,
-
-	LAST_PROP
-};
+);
 
 enum {
 	ACCESS_POINT_ADDED,
@@ -91,26 +87,26 @@ enum {
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
-struct _NMDeviceWifiPrivate {
+typedef struct {
 	gint8             invalid_strength_counter;
 
 	GHashTable *      aps;
 	NMAccessPoint *   current_ap;
 	guint32           rate;
-	gboolean          enabled; /* rfkilled or not */
+	bool              enabled:1; /* rfkilled or not */
+	bool              requested_scan:1;
+	bool              ssid_found:1;
 
 	gint32            last_scan;
 	gint32            scheduled_scan_time;
 	guint8            scan_interval; /* seconds */
 	guint             pending_scan_id;
 	guint             ap_dump_id;
-	bool              requested_scan;
 
 	NMSupplicantManager   *sup_mgr;
 	NMSupplicantInterface *sup_iface;
 	guint                  sup_timeout_id; /* supplicant association timeout */
 
-	bool              ssid_found;
 	NM80211Mode       mode;
 
 	guint             periodic_source_id;
@@ -119,8 +115,44 @@ struct _NMDeviceWifiPrivate {
 	guint             reacquire_iface_id;
 
 	NMDeviceWifiCapabilities capabilities;
+
+	gint32 hw_addr_scan_expire;
+	char *hw_addr_scan;
+} NMDeviceWifiPrivate;
+
+struct _NMDeviceWifi
+{
+	NMDevice parent;
+	NMDeviceWifiPrivate _priv;
 };
 
+struct _NMDeviceWifiClass
+{
+	NMDeviceClass parent;
+
+	/* Signals */
+	gboolean (*scanning_allowed) (NMDeviceWifi *device);
+};
+
+/*****************************************************************************/
+
+G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_WIFI_GET_PRIVATE(self) \
+	({ \
+		/* preserve the const-ness of self. Unfortunately, that
+		 * way, @self cannot be a void pointer */ \
+		typeof (self) _self = (self); \
+		\
+		/* Get compiler error if variable is of wrong type */ \
+		_nm_unused const NMDeviceWifi *_self2 = (_self); \
+		\
+		nm_assert (NM_IS_DEVICE_WIFI (_self)); \
+		&_self->_priv; \
+	})
+
+/*****************************************************************************/
+
 static gboolean check_scanning_allowed (NMDeviceWifi *self);
 
 static void schedule_scan (NMDeviceWifi *self, gboolean backoff);
@@ -169,7 +201,9 @@ static void ap_add_remove (NMDeviceWifi *self,
 
 static void remove_supplicant_interface_error_handler (NMDeviceWifi *self);
 
-/*****************************************************************/
+static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset);
+
+/*****************************************************************************/
 
 static void
 constructed (GObject *object)
@@ -187,6 +221,18 @@ constructed (GObject *object)
 }
 
 static gboolean
+unmanaged_on_quit (NMDevice *self)
+{
+	/* Wi-Fi devices cannot be assumed and are always taken down.
+	 * However, also when being disconnected, we scan and thus
+	 * set the MAC address to a random value.
+	 *
+	 * We must restore the original MAC address when quitting, thus
+	 * signal to unmanage the device. */
+	return TRUE;
+}
+
+static gboolean
 supplicant_interface_acquire (NMDeviceWifi *self)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
@@ -238,6 +284,24 @@ supplicant_interface_acquire (NMDeviceWifi *self)
 }
 
 static void
+_requested_scan_set (NMDeviceWifi *self, gboolean value)
+{
+	NMDeviceWifiPrivate *priv;
+
+	value = !!value;
+
+	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	if (priv->requested_scan == value)
+		return;
+
+	priv->requested_scan = value;
+	if (value)
+		nm_device_add_pending_action ((NMDevice *) self, "scan", TRUE);
+	else
+		nm_device_remove_pending_action ((NMDevice *) self, "scan", TRUE);
+}
+
+static void
 supplicant_interface_release (NMDeviceWifi *self)
 {
 	NMDeviceWifiPrivate *priv;
@@ -246,6 +310,8 @@ supplicant_interface_release (NMDeviceWifi *self)
 
 	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
+	_requested_scan_set (self, FALSE);
+
 	nm_clear_g_source (&priv->pending_scan_id);
 
 	/* Reset the scan interval to be pretty frequent when disconnected */
@@ -340,7 +406,7 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai
 		g_object_unref (old_ap);
 	}
 
-	g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
+	_notify (self, PROP_ACTIVE_ACCESS_POINT);
 }
 
 static void
@@ -386,7 +452,7 @@ periodic_update (NMDeviceWifi *self)
 	new_rate = nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex);
 	if (new_rate != priv->rate) {
 		priv->rate = new_rate;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_BITRATE);
+		_notify (self, PROP_BITRATE);
 	}
 }
 
@@ -397,18 +463,10 @@ periodic_update_cb (gpointer user_data)
 	return TRUE;
 }
 
-static void
-realize_start_notify (NMDevice *device, const NMPlatformLink *plink)
-{
-	NM_DEVICE_CLASS (nm_device_wifi_parent_class)->realize_start_notify (device, plink);
-
-	g_object_notify (G_OBJECT (device), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
-}
-
 static gboolean
 bring_up (NMDevice *device, gboolean *no_firmware)
 {
-	if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled)
+	if (!NM_DEVICE_WIFI_GET_PRIVATE ((NMDeviceWifi *) device)->enabled)
 		return FALSE;
 
 	return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->bring_up (device, no_firmware);
@@ -431,7 +489,7 @@ ap_add_remove (NMDeviceWifi *self,
 	}
 
 	g_signal_emit (self, signals[signum], 0, ap);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACCESS_POINTS);
+	_notify (self, PROP_ACCESS_POINTS);
 
 	if (signum == ACCESS_POINT_REMOVED) {
 		g_hash_table_remove (priv->aps, nm_exported_object_get_path ((NMExportedObject *) ap));
@@ -485,10 +543,6 @@ deactivate (NMDevice *device)
 	/* Clear any critical protocol notification in the Wi-Fi stack */
 	nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE);
 
-	/* Reset MAC address back to initial address */
-	if (nm_device_get_initial_hw_address (device))
-		nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_WIFI);
-
 	/* Ensure we're in infrastructure mode after deactivation; some devices
 	 * (usually older ones) don't scan well in adhoc mode.
 	 */
@@ -500,7 +554,7 @@ deactivate (NMDevice *device)
 
 	if (priv->mode != NM_802_11_MODE_INFRA) {
 		priv->mode = NM_802_11_MODE_INFRA;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE);
+		_notify (self, PROP_MODE);
 	}
 
 	/* Ensure we trigger a scan after deactivating a Hotspot */
@@ -510,6 +564,12 @@ deactivate (NMDevice *device)
 	}
 }
 
+static void
+deactivate_reset_hw_addr (NMDevice *device)
+{
+	_hw_addr_set_scanning ((NMDeviceWifi *) device, TRUE);
+}
+
 static gboolean
 is_adhoc_wpa (NMConnection *connection)
 {
@@ -566,7 +626,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 	if (!s_wireless)
 		return FALSE;
 
-	perm_hw_addr = nm_device_get_permanent_hw_address (device);
+	perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
 	mac = nm_setting_wireless_get_mac_address (s_wireless);
 	if (perm_hw_addr) {
 		if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
@@ -679,35 +739,31 @@ check_connection_available (NMDevice *device,
 	return !!find_first_compatible_ap (NM_DEVICE_WIFI (device), connection, TRUE);
 }
 
-/*
- * List of manufacturer default SSIDs that are often unchanged by users.
- *
- * NOTE: this list should *not* contain networks that you would like to
- * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot".
- */
-static const char *
-manf_defaults[] = {
-	"linksys",
-	"linksys-a",
-	"linksys-g",
-	"default",
-	"belkin54g",
-	"NETGEAR",
-	"o2DSL",
-	"WLAN",
-	"ALICE-WLAN",
-	"Speedport W 501V",
-	"TURBONETT",
-};
-
-#define ARRAY_SIZE(a)  (sizeof (a) / sizeof (a[0]))
-
 static gboolean
 is_manf_default_ssid (const GByteArray *ssid)
 {
 	int i;
-
-	for (i = 0; i < ARRAY_SIZE (manf_defaults); i++) {
+	/*
+	 * List of manufacturer default SSIDs that are often unchanged by users.
+	 *
+	 * NOTE: this list should *not* contain networks that you would like to
+	 * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot".
+	 */
+	static const char *manf_defaults[] = {
+		"linksys",
+		"linksys-a",
+		"linksys-g",
+		"default",
+		"belkin54g",
+		"NETGEAR",
+		"o2DSL",
+		"WLAN",
+		"ALICE-WLAN",
+		"Speedport W 501V",
+		"TURBONETT",
+	};
+
+	for (i = 0; i < G_N_ELEMENTS (manf_defaults); i++) {
 		if (ssid->len == strlen (manf_defaults[i])) {
 			if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0)
 				return TRUE;
@@ -862,7 +918,7 @@ complete_connection (NMDevice *device,
 	if (hidden)
 		g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL);
 
-	perm_hw_addr = nm_device_get_permanent_hw_address (device);
+	perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
 	if (perm_hw_addr) {
 		setting_mac = nm_setting_wireless_get_mac_address (s_wifi);
 		if (setting_mac) {
@@ -1022,6 +1078,60 @@ impl_device_wifi_get_all_access_points (NMDeviceWifi *self,
 }
 
 static void
+_hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset)
+{
+	NMDevice *device = (NMDevice *) self;
+	NMDeviceWifiPrivate *priv;
+	guint32 now;
+	gboolean randomize;
+
+	g_return_if_fail (NM_IS_DEVICE_WIFI (self));
+
+	if (   nm_device_is_activating (device)
+	    || nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
+		return;
+
+	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	randomize = nm_config_data_get_device_config_boolean (NM_CONFIG_GET_DATA,
+	                                                      "wifi.scan-rand-mac-address",
+	                                                      device,
+	                                                      TRUE, TRUE);
+
+	if (!randomize) {
+		g_clear_pointer (&priv->hw_addr_scan, g_free);
+		if (do_reset)
+			nm_device_hw_addr_reset (device, "scanning");
+		return;
+	}
+
+	now = nm_utils_get_monotonic_timestamp_s ();
+
+	if (   !priv->hw_addr_scan
+	    || now >= priv->hw_addr_scan_expire) {
+		gs_free char *generate_mac_address_mask = NULL;
+
+		/* the random MAC address for scanning expires after a while.
+		 *
+		 * We don't bother with to update the MAC address exactly when
+		 * it expires, instead on the next scan request, we will generate
+		 * a new one.*/
+		priv->hw_addr_scan_expire = now + (SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN * 60);
+
+		generate_mac_address_mask = nm_config_data_get_device_config (NM_CONFIG_GET_DATA,
+		                                                              "wifi.scan-generate-mac-address-mask",
+		                                                              device,
+		                                                              NULL);
+
+		g_free (priv->hw_addr_scan);
+		priv->hw_addr_scan = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (device),
+		                                                      generate_mac_address_mask);
+	}
+
+	nm_device_hw_addr_set (device, priv->hw_addr_scan, "scanning");
+}
+
+static void
 request_scan_cb (NMDevice *device,
                  GDBusMethodInvocation *context,
                  NMAuthSubject *subject,
@@ -1199,7 +1309,7 @@ check_scanning_allowed (NMDeviceWifi *self)
 }
 
 static gboolean
-hidden_filter_func (NMConnectionProvider *provider,
+hidden_filter_func (NMSettings *settings,
                     NMConnection *connection,
                     gpointer user_data)
 {
@@ -1226,12 +1336,12 @@ build_hidden_probe_list (NMDeviceWifi *self)
 	if (G_UNLIKELY (nullssid == NULL))
 		nullssid = g_byte_array_new ();
 
-	connections = nm_connection_provider_get_best_connections (nm_connection_provider_get (),
-	                                                           max_scan_ssids - 1,
-	                                                           NM_SETTING_WIRELESS_SETTING_NAME,
-	                                                           NULL,
-	                                                           hidden_filter_func,
-	                                                           NULL);
+	connections = nm_settings_get_best_connections (nm_device_get_settings ((NMDevice *) self),
+	                                                max_scan_ssids - 1,
+	                                                NM_SETTING_WIRELESS_SETTING_NAME,
+	                                                NULL,
+	                                                hidden_filter_func,
+	                                                NULL);
 	if (connections && connections->data) {
 		ssids = g_ptr_array_new_full (max_scan_ssids - 1, (GDestroyNotify) g_byte_array_unref);
 		g_ptr_array_add (ssids, g_byte_array_ref (nullssid));  /* Add wildcard SSID */
@@ -1330,11 +1440,12 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
 				_LOGD (LOGD_WIFI_SCAN, "no SSIDs to probe scan");
 		}
 
+		_hw_addr_set_scanning (self, FALSE);
+
 		if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) {
 			/* success */
 			backoff = TRUE;
-			priv->requested_scan = TRUE;
-			nm_device_add_pending_action (NM_DEVICE (self), "scan", TRUE);
+			_requested_scan_set (self, TRUE);
 		}
 
 		if (ssids)
@@ -1349,10 +1460,11 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
 static gboolean
 request_wireless_scan_periodic (gpointer user_data)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (user_data);
+	NMDeviceWifi *self = user_data;
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
 	priv->pending_scan_id = 0;
-	request_wireless_scan (user_data, NULL);
+	request_wireless_scan (self, NULL);
 	return FALSE;
 }
 
@@ -1416,10 +1528,7 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface,
 	priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
 	schedule_scan (self, success);
 
-	if (priv->requested_scan) {
-		priv->requested_scan = FALSE;
-		nm_device_remove_pending_action (NM_DEVICE (self), "scan", TRUE);
-	}
+	_requested_scan_set (self, FALSE);
 }
 
 /****************************************************************************
@@ -1458,10 +1567,12 @@ schedule_ap_list_dump (NMDeviceWifi *self)
 }
 
 static void
-try_fill_ssid_for_hidden_ap (NMAccessPoint *ap)
+try_fill_ssid_for_hidden_ap (NMDeviceWifi *self,
+                             NMAccessPoint *ap)
 {
 	const char *bssid;
-	const GSList *connections, *iter;
+	NMSettingsConnection *const*connections;
+	guint i;
 
 	g_return_if_fail (nm_ap_get_ssid (ap) == NULL);
 
@@ -1470,9 +1581,9 @@ try_fill_ssid_for_hidden_ap (NMAccessPoint *ap)
 
 	/* Look for this AP's BSSID in the seen-bssids list of a connection,
 	 * and if a match is found, copy over the SSID */
-	connections = nm_connection_provider_get_connections (nm_connection_provider_get ());
-	for (iter = connections; iter; iter = g_slist_next (iter)) {
-		NMConnection *connection = NM_CONNECTION (iter->data);
+	connections = nm_settings_get_connections (nm_device_get_settings ((NMDevice *) self), NULL);
+	for (i = 0; connections[i]; i++) {
+		NMConnection *connection = (NMConnection *) connections[i];
 		NMSettingWireless *s_wifi;
 
 		s_wifi = nm_connection_get_setting_wireless (connection);
@@ -1522,7 +1633,7 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
 	ssid = nm_ap_get_ssid (ap);
 	if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) {
 		/* Try to fill the SSID from the AP database */
-		try_fill_ssid_for_hidden_ap (ap);
+		try_fill_ssid_for_hidden_ap (self, ap);
 
 		ssid = nm_ap_get_ssid (ap);
 		if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) {
@@ -1951,6 +2062,11 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
 		else
 			_LOGI (LOGD_DEVICE | LOGD_WIFI, "supplicant interface keeps failing, giving up");
 		break;
+	case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE:
+		_requested_scan_set (self, FALSE);
+		nm_clear_g_source (&priv->pending_scan_id);
+		request_wireless_scan (self, NULL);
+		break;
 	default:
 		break;
 	}
@@ -1964,7 +2080,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
 	/* Signal scanning state changes */
 	if (   new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING
 	    || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
-		g_object_notify (G_OBJECT (self), "scanning");
+		_notify (self, PROP_SCANNING);
 }
 
 static void
@@ -2008,7 +2124,7 @@ supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface,
 	scanning = nm_supplicant_interface_get_scanning (iface);
 	_LOGD (LOGD_WIFI_SCAN, "now %s", scanning ? "scanning" : "idle");
 
-	g_object_notify (G_OBJECT (self), "scanning");
+	_notify (self, PROP_SCANNING);
 
 	/* Run a quick update of current AP when coming out of a scan */
 	state = nm_device_get_state (NM_DEVICE (self));
@@ -2197,9 +2313,6 @@ build_supplicant_config (NMDeviceWifi *self,
 	NMSupplicantConfig *config = NULL;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wireless_sec;
-	NMSupplicantFeature mac_randomization_support;
-	NMSettingMacRandomization mac_randomization_fallback;
-	gs_free char *svalue = NULL;
 
 	g_return_val_if_fail (priv->sup_iface, NULL);
 
@@ -2214,20 +2327,9 @@ build_supplicant_config (NMDeviceWifi *self,
 		_LOGW (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out.");
 	}
 
-	mac_randomization_support = nm_supplicant_interface_get_mac_randomization_support (priv->sup_iface);
-	svalue = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
-	                                                "wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION,
-	                                                NM_DEVICE (self));
-	mac_randomization_fallback = _nm_utils_ascii_str_to_int64 (svalue, 10,
-	                                                           NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
-	                                                           NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
-	                                                           NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
-
 	if (!nm_supplicant_config_add_setting_wireless (config,
 	                                                s_wireless,
 	                                                fixed_freq,
-	                                                mac_randomization_support,
-	                                                mac_randomization_fallback,
 	                                                error)) {
 		g_prefix_error (error, "802-11-wireless: ");
 		goto error;
@@ -2277,7 +2379,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	NMActRequest *req;
 	NMConnection *connection;
 	NMSettingWireless *s_wireless;
-	const char *cloned_mac;
 	const char *mode;
 	const char *ap_path;
 
@@ -2305,7 +2406,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 		/* Scanning not done in AP mode; clear the scan list */
 		remove_all_aps (self);
 	}
-	g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE);
+	_notify (self, PROP_MODE);
 
 	/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
 	 * and turns them into open networks.  It's been this way since at least
@@ -2317,9 +2418,12 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 		return NM_ACT_STAGE_RETURN_FAILURE;
 	}
 
+	/* forget the temporary MAC address used during scanning */
+	g_clear_pointer (&priv->hw_addr_scan, g_free);
+
 	/* Set spoof MAC to the interface */
-	cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
-	nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_WIFI);
+	if (!nm_device_hw_addr_set_cloned (device, connection, TRUE))
+		return NM_ACT_STAGE_RETURN_FAILURE;
 
 	/* AP mode never uses a specific object or existing scanned AP */
 	if (priv->mode != NM_802_11_MODE_AP) {
@@ -2859,6 +2963,8 @@ set_enabled (NMDevice *device, gboolean enabled)
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	NMDeviceState state;
 
+	enabled = !!enabled;
+
 	if (priv->enabled == enabled)
 		return;
 
@@ -2959,6 +3065,8 @@ finalize (GObject *object)
 
 	g_hash_table_unref (priv->aps);
 
+	g_free (priv->hw_addr_scan);
+
 	G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object);
 }
 
@@ -2973,9 +3081,6 @@ get_property (GObject *object, guint prop_id,
 	GPtrArray *array;
 
 	switch (prop_id) {
-	case PROP_PERM_HW_ADDRESS:
-		g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (device)));
-		break;
 	case PROP_MODE:
 		g_value_set_uint (value, priv->mode);
 		break;
@@ -3030,8 +3135,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
 
-	g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate));
-
 	NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI)
 
 	object_class->constructed = constructed;
@@ -3040,7 +3143,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 
-	parent_class->realize_start_notify = realize_start_notify;
 	parent_class->bring_up = bring_up;
 	parent_class->can_auto_connect = can_auto_connect;
 	parent_class->is_available = is_available;
@@ -3057,90 +3159,81 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 	parent_class->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
 	parent_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
 	parent_class->deactivate = deactivate;
+	parent_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
+	parent_class->unmanaged_on_quit = unmanaged_on_quit;
 
 	parent_class->state_changed = device_state_changed;
 
 	klass->scanning_allowed = scanning_allowed;
 
 	/* Properties */
-	g_object_class_install_property
-		(object_class, PROP_PERM_HW_ADDRESS,
-		 g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, "", "",
-		                      NULL,
-		                      G_PARAM_READABLE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_MODE,
-		 g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "",
-		                    NM_802_11_MODE_UNKNOWN,
-		                    NM_802_11_MODE_AP,
-		                    NM_802_11_MODE_INFRA,
-		                    G_PARAM_READABLE |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_BITRATE,
-		 g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, "", "",
-		                    0, G_MAXUINT32, 0,
-		                    G_PARAM_READABLE |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_ACCESS_POINTS,
-		 g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "",
-		                     G_TYPE_STRV,
-		                     G_PARAM_READABLE |
-		                     G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_ACTIVE_ACCESS_POINT,
-		 g_param_spec_string (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "",
-		                      NULL,
-		                      G_PARAM_READABLE |
-		                      G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_CAPABILITIES,
-		 g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, "", "",
-		                    0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE,
-		                    G_PARAM_READWRITE |
-		                    G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-		(object_class, PROP_SCANNING,
-		 g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, "", "",
-		                       FALSE,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_MODE] =
+	    g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "",
+	                       NM_802_11_MODE_UNKNOWN,
+	                       NM_802_11_MODE_AP,
+	                       NM_802_11_MODE_INFRA,
+	                       G_PARAM_READABLE |
+	                       G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_BITRATE] =
+	    g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, "", "",
+	                       0, G_MAXUINT32, 0,
+	                       G_PARAM_READABLE |
+	                       G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_ACCESS_POINTS] =
+	    g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "",
+	                        G_TYPE_STRV,
+	                        G_PARAM_READABLE |
+	                        G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_ACTIVE_ACCESS_POINT] =
+	    g_param_spec_string (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_CAPABILITIES] =
+	    g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, "", "",
+	                       0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE,
+	                       G_PARAM_READWRITE |
+	                       G_PARAM_CONSTRUCT_ONLY |
+	                       G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_SCANNING] =
+	    g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, "", "",
+	                          FALSE,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
 	/* Signals */
 	signals[ACCESS_POINT_ADDED] =
-		g_signal_new ("access-point-added",
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 1,
-		              NM_TYPE_AP);
+	    g_signal_new ("access-point-added",
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0,
+	                  NULL, NULL, NULL,
+	                  G_TYPE_NONE, 1,
+	                  NM_TYPE_AP);
 
 	signals[ACCESS_POINT_REMOVED] =
-		g_signal_new ("access-point-removed",
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_FIRST,
-		              0,
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 1,
-		              NM_TYPE_AP);
+	    g_signal_new ("access-point-removed",
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_FIRST,
+	                  0,
+	                  NULL, NULL, NULL,
+	                  G_TYPE_NONE, 1,
+	                  NM_TYPE_AP);
 
 	signals[SCANNING_ALLOWED] =
-		g_signal_new ("scanning-allowed",
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed),
-		              scanning_allowed_accumulator, NULL, NULL,
-		              G_TYPE_BOOLEAN, 0);
+	    g_signal_new ("scanning-allowed",
+	                  G_OBJECT_CLASS_TYPE (object_class),
+	                  G_SIGNAL_RUN_LAST,
+	                  G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed),
+	                  scanning_allowed_accumulator, NULL, NULL,
+	                  G_TYPE_BOOLEAN, 0);
 
 	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
 	                                        NMDBUS_TYPE_DEVICE_WIFI_SKELETON,
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
index 7e0d06f5..ba9d60e2 100644
--- a/src/devices/wifi/nm-device-wifi.h
+++ b/src/devices/wifi/nm-device-wifi.h
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2005 - 2010 Red Hat, Inc.
+ * Copyright (C) 2005 - 2016 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
 
@@ -25,18 +25,13 @@
 #include "nm-device.h"
 #include "nm-wifi-ap.h"
 
-struct NMAccessPointList;
+#define NM_TYPE_DEVICE_WIFI             (nm_device_wifi_get_type ())
+#define NM_DEVICE_WIFI(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi))
+#define NM_DEVICE_WIFI_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
+#define NM_IS_DEVICE_WIFI(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI))
+#define NM_IS_DEVICE_WIFI_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_DEVICE_WIFI))
+#define NM_DEVICE_WIFI_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
 
-G_BEGIN_DECLS
-
-#define NM_TYPE_DEVICE_WIFI			(nm_device_wifi_get_type ())
-#define NM_DEVICE_WIFI(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi))
-#define NM_DEVICE_WIFI_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
-#define NM_IS_DEVICE_WIFI(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI))
-#define NM_IS_DEVICE_WIFI_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_DEVICE_WIFI))
-#define NM_DEVICE_WIFI_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
-
-#define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address"
 #define NM_DEVICE_WIFI_MODE                "mode"
 #define NM_DEVICE_WIFI_BITRATE             "bitrate"
 #define NM_DEVICE_WIFI_ACCESS_POINTS       "access-points"
@@ -44,37 +39,11 @@ G_BEGIN_DECLS
 #define NM_DEVICE_WIFI_CAPABILITIES        "wireless-capabilities"
 #define NM_DEVICE_WIFI_SCANNING            "scanning"
 
-#ifndef NM_DEVICE_WIFI_DEFINED
-#define NM_DEVICE_WIFI_DEFINED
 typedef struct _NMDeviceWifi NMDeviceWifi;
-#endif
-
 typedef struct _NMDeviceWifiClass NMDeviceWifiClass;
-typedef struct _NMDeviceWifiPrivate NMDeviceWifiPrivate;
-
-struct _NMDeviceWifi
-{
-	NMDevice parent;
-
-	/*< private >*/
-	NMDeviceWifiPrivate *priv;
-};
-
-struct _NMDeviceWifiClass
-{
-	NMDeviceClass parent;
-
-	/* Signals */
-	void (*access_point_added)   (NMDeviceWifi *device, NMAccessPoint *ap);
-	void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap);
-	gboolean (*scanning_allowed) (NMDeviceWifi *device);
-};
-
 
 GType nm_device_wifi_get_type (void);
 
 NMDevice * nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities);
 
-G_END_DECLS
-
-#endif	/* NM_DEVICE_WIFI_H */
+#endif /* __NETWORKMANAGER_DEVICE_WIFI_H__ */
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index a0c25709..e1beb85b 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -42,29 +42,48 @@ typedef struct
 	char *supplicant_path;   /* D-Bus object path of this AP from wpa_supplicant */
 
 	/* Scanned or cached values */
-	GByteArray *	ssid;
-	char *          address;
-	NM80211Mode		mode;
-	guint8			strength;
-	guint32			freq;		/* Frequency in MHz; ie 2412 (== 2.412 GHz) */
-	guint32			max_bitrate;/* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */
+	GByteArray *       ssid;
+	char *             address;
+	NM80211Mode        mode;
+	guint8             strength;
+	guint32            freq;        /* Frequency in MHz; ie 2412 (== 2.412 GHz) */
+	guint32            max_bitrate; /* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */
 
 	NM80211ApFlags         flags;      /* General flags */
 	NM80211ApSecurityFlags wpa_flags;  /* WPA-related flags */
 	NM80211ApSecurityFlags rsn_flags;  /* RSN (WPA2) -related flags */
 
 	/* Non-scanned attributes */
-	gboolean			fake;	/* Whether or not the AP is from a scan */
-	gboolean            hotspot;    /* Whether the AP is a local device's hotspot network */
+	bool                fake;       /* Whether or not the AP is from a scan */
+	bool                hotspot;    /* Whether the AP is a local device's hotspot network */
 	gint32              last_seen;  /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */
 } NMAccessPointPrivate;
 
-#define NM_AP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP, NMAccessPointPrivate))
+struct _NMAccessPoint {
+	NMExportedObject parent;
+	NMAccessPointPrivate _priv;
+};
+
+struct _NMAccessPointClass{
+	NMExportedObjectClass parent;
+};
+
+#define NM_AP_GET_PRIVATE(self) \
+	({ \
+		/* preserve the const-ness of self. Unfortunately, that
+		 * way, @self cannot be a void pointer */ \
+		typeof (self) _self = (self); \
+		\
+		/* Get compiler error if variable is of wrong type */ \
+		_nm_unused const NMAccessPoint *_self2 = (_self); \
+		\
+		nm_assert (NM_IS_AP (_self)); \
+		&_self->_priv; \
+	})
 
 G_DEFINE_TYPE (NMAccessPoint, nm_ap, NM_TYPE_EXPORTED_OBJECT)
 
-enum {
-	PROP_0,
+NM_GOBJECT_PROPERTIES_DEFINE (NMAccessPoint,
 	PROP_FLAGS,
 	PROP_WPA_FLAGS,
 	PROP_RSN_FLAGS,
@@ -75,8 +94,7 @@ enum {
 	PROP_MAX_BITRATE,
 	PROP_STRENGTH,
 	PROP_LAST_SEEN,
-	LAST_PROP
-};
+);
 
 /*****************************************************************/
 
@@ -130,7 +148,7 @@ nm_ap_set_ssid (NMAccessPoint *ap, const guint8 *ssid, gsize len)
 		g_byte_array_append (priv->ssid, ssid, len);
 	}
 
-	g_object_notify (G_OBJECT (ap), NM_AP_SSID);
+	_notify (ap, PROP_SSID);
 }
 
 static void
@@ -144,7 +162,7 @@ nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags)
 
 	if (priv->flags != flags) {
 		priv->flags = flags;
-		g_object_notify (G_OBJECT (ap), NM_AP_FLAGS);
+		_notify (ap, PROP_FLAGS);
 	}
 }
 
@@ -158,7 +176,7 @@ nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags)
 	priv = NM_AP_GET_PRIVATE (ap);
 	if (priv->wpa_flags != flags) {
 		priv->wpa_flags = flags;
-		g_object_notify (G_OBJECT (ap), NM_AP_WPA_FLAGS);
+		_notify (ap, PROP_WPA_FLAGS);
 	}
 }
 
@@ -172,7 +190,7 @@ nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags)
 	priv = NM_AP_GET_PRIVATE (ap);
 	if (priv->rsn_flags != flags) {
 		priv->rsn_flags = flags;
-		g_object_notify (G_OBJECT (ap), NM_AP_RSN_FLAGS);
+		_notify (ap, PROP_RSN_FLAGS);
 	}
 }
 
@@ -198,7 +216,7 @@ nm_ap_set_address (NMAccessPoint *ap, const char *addr)
 	if (!priv->address || !nm_utils_hwaddr_matches (addr, -1, priv->address, -1)) {
 		g_free (priv->address);
 		priv->address = g_strdup (addr);
-		g_object_notify (G_OBJECT (ap), NM_AP_HW_ADDRESS);
+		_notify (ap, PROP_HW_ADDRESS);
 	}
 }
 
@@ -223,7 +241,7 @@ nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode)
 
 	if (priv->mode != mode) {
 		priv->mode = mode;
-		g_object_notify (G_OBJECT (ap), NM_AP_MODE);
+		_notify (ap, PROP_MODE);
 	}
 }
 
@@ -254,7 +272,7 @@ nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength)
 
 	if (priv->strength != strength) {
 		priv->strength = strength;
-		g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH);
+		_notify (ap, PROP_STRENGTH);
 	}
 }
 
@@ -278,7 +296,7 @@ nm_ap_set_freq (NMAccessPoint *ap,
 
 	if (priv->freq != freq) {
 		priv->freq = freq;
-		g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY);
+		_notify (ap, PROP_FREQUENCY);
 	}
 }
 
@@ -302,7 +320,7 @@ nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate)
 
 	if (priv->max_bitrate != bitrate) {
 		priv->max_bitrate = bitrate;
-		g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE);
+		_notify (ap, PROP_MAX_BITRATE);
 	}
 }
 
@@ -333,7 +351,7 @@ nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen)
 
 	if (priv->last_seen != last_seen) {
 		priv->last_seen = last_seen;
-		g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN);
+		_notify (ap, PROP_LAST_SEEN);
 	}
 }
 
@@ -347,18 +365,20 @@ security_from_vardict (GVariant *security)
 
 	g_return_val_if_fail (g_variant_is_of_type (security, G_VARIANT_TYPE_VARDICT), NM_802_11_AP_SEC_NONE);
 
-	if (g_variant_lookup (security, "KeyMgmt", "^a&s", &array)) {
-		if (_nm_utils_string_in_list ("wpa-psk", array))
+	if (   g_variant_lookup (security, "KeyMgmt", "^a&s", &array)
+	    && array) {
+		if (g_strv_contains (array, "wpa-psk"))
 			flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK;
-		if (_nm_utils_string_in_list ("wpa-eap", array))
+		if (g_strv_contains (array, "wpa-eap"))
 			flags |= NM_802_11_AP_SEC_KEY_MGMT_802_1X;
 		g_free (array);
 	}
 
-	if (g_variant_lookup (security, "Pairwise", "^a&s", &array)) {
-		if (_nm_utils_string_in_list ("tkip", array))
+	if (   g_variant_lookup (security, "Pairwise", "^a&s", &array)
+	    && array) {
+		if (g_strv_contains (array, "tkip"))
 			flags |= NM_802_11_AP_SEC_PAIR_TKIP;
-		if (_nm_utils_string_in_list ("ccmp", array))
+		if (g_strv_contains (array, "ccmp"))
 			flags |= NM_802_11_AP_SEC_PAIR_CCMP;
 		g_free (array);
 	}
@@ -879,7 +899,7 @@ nm_ap_init (NMAccessPoint *ap)
 static void
 finalize (GObject *object)
 {
-	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object);
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE ((NMAccessPoint *) object);
 
 	g_free (priv->supplicant_path);
 	if (priv->ssid)
@@ -891,16 +911,16 @@ finalize (GObject *object)
 
 static void
 set_property (GObject *object, guint prop_id,
-		    const GValue *value, GParamSpec *pspec)
+              const GValue *value, GParamSpec *pspec)
 {
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 }
 
 static void
 get_property (GObject *object, guint prop_id,
-			  GValue *value, GParamSpec *pspec)
+              GValue *value, GParamSpec *pspec)
 {
-	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object);
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE ((NMAccessPoint *) object);
 	GVariant *ssid;
 
 	switch (prop_id) {
@@ -965,8 +985,6 @@ nm_ap_class_init (NMAccessPointClass *ap_class)
 	                                             | NM_802_11_AP_SEC_KEY_MGMT_PSK
 	                                             | NM_802_11_AP_SEC_KEY_MGMT_802_1X;
 
-	g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate));
-
 	exported_object_class->export_path = NM_DBUS_PATH_ACCESS_POINT "/%u";
 
 	/* virtual methods */
@@ -975,72 +993,64 @@ nm_ap_class_init (NMAccessPointClass *ap_class)
 	object_class->finalize = finalize;
 
 	/* properties */
-	g_object_class_install_property
-	    (object_class, PROP_FLAGS,
-	     g_param_spec_uint (NM_AP_FLAGS, "", "",
-	                        NM_802_11_AP_FLAGS_NONE,
-	                        NM_802_11_AP_FLAGS_PRIVACY,
-	                        NM_802_11_AP_FLAGS_NONE,
-	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_WPA_FLAGS,
-	     g_param_spec_uint (NM_AP_WPA_FLAGS, "", "",
-	                        NM_802_11_AP_SEC_NONE,
-	                        all_sec_flags,
-	                        NM_802_11_AP_SEC_NONE,
-	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_RSN_FLAGS,
-	     g_param_spec_uint (NM_AP_RSN_FLAGS, "", "",
-	                        NM_802_11_AP_SEC_NONE,
-	                        all_sec_flags,
-	                        NM_802_11_AP_SEC_NONE,
-	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_SSID,
-	     g_param_spec_variant (NM_AP_SSID, "", "",
-	                           G_VARIANT_TYPE ("ay"),
-	                           NULL,
-	                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_FREQUENCY,
-	     g_param_spec_uint (NM_AP_FREQUENCY, "", "",
-	                        0, 10000, 0,
-	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_HW_ADDRESS,
-	     g_param_spec_string (NM_AP_HW_ADDRESS, "", "",
+	obj_properties[PROP_FLAGS] =
+	    g_param_spec_uint (NM_AP_FLAGS, "", "",
+	                       NM_802_11_AP_FLAGS_NONE,
+	                       NM_802_11_AP_FLAGS_PRIVACY,
+	                       NM_802_11_AP_FLAGS_NONE,
+	                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_WPA_FLAGS] =
+	    g_param_spec_uint (NM_AP_WPA_FLAGS, "", "",
+	                       NM_802_11_AP_SEC_NONE,
+	                       all_sec_flags,
+	                       NM_802_11_AP_SEC_NONE,
+	                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_RSN_FLAGS] =
+	    g_param_spec_uint (NM_AP_RSN_FLAGS, "", "",
+	                       NM_802_11_AP_SEC_NONE,
+	                       all_sec_flags,
+	                       NM_802_11_AP_SEC_NONE,
+	                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_SSID] =
+	    g_param_spec_variant (NM_AP_SSID, "", "",
+	                          G_VARIANT_TYPE ("ay"),
 	                          NULL,
-	                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_MODE,
-	     g_param_spec_uint (NM_AP_MODE, "", "",
-	                        NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA,
-	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_MAX_BITRATE,
-	     g_param_spec_uint (NM_AP_MAX_BITRATE, "", "",
-	                        0, G_MAXUINT16, 0,
-	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_STRENGTH,
-	     g_param_spec_uchar (NM_AP_STRENGTH, "", "",
-	                         0, G_MAXINT8, 0,
-	                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-	g_object_class_install_property
-	    (object_class, PROP_LAST_SEEN,
-	     g_param_spec_int (NM_AP_LAST_SEEN, "", "",
-	                       -1, G_MAXINT, -1,
-	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+	                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_FREQUENCY] =
+	    g_param_spec_uint (NM_AP_FREQUENCY, "", "",
+	                       0, 10000, 0,
+	                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_HW_ADDRESS] =
+	    g_param_spec_string (NM_AP_HW_ADDRESS, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_MODE] =
+	    g_param_spec_uint (NM_AP_MODE, "", "",
+	                       NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA,
+	                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_MAX_BITRATE] =
+	    g_param_spec_uint (NM_AP_MAX_BITRATE, "", "",
+	                       0, G_MAXUINT16, 0,
+	                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_STRENGTH] =
+	    g_param_spec_uchar (NM_AP_STRENGTH, "", "",
+	                        0, G_MAXINT8, 0,
+	                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	obj_properties[PROP_LAST_SEEN] =
+	    g_param_spec_int (NM_AP_LAST_SEEN, "", "",
+	                      -1, G_MAXINT, -1,
+	                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
 	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ap_class),
 	                                        NMDBUS_TYPE_ACCESS_POINT_SKELETON,
diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h
index 84aff983..035d1b5e 100644
--- a/src/devices/wifi/nm-wifi-ap.h
+++ b/src/devices/wifi/nm-wifi-ap.h
@@ -44,14 +44,8 @@
 #define NM_AP_STRENGTH "strength"
 #define NM_AP_LAST_SEEN "last-seen"
 
-typedef struct {
-	NMExportedObject parent;
-} NMAccessPoint;
-
-typedef struct {
-	NMExportedObjectClass parent;
-
-} NMAccessPointClass;
+typedef struct _NMAccessPoint NMAccessPoint;
+typedef struct _NMAccessPointClass NMAccessPointClass;
 
 GType nm_ap_get_type (void);
 
diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in
index 956730f8..64113a21 100644
--- a/src/devices/wifi/tests/Makefile.in
+++ b/src/devices/wifi/tests/Makefile.in
@@ -92,8 +92,9 @@ noinst_PROGRAMS = test-wifi-ap-utils$(EXEEXT)
 TESTS = test-wifi-ap-utils$(EXEEXT)
 subdir = src/devices/wifi/tests
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
-	$(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/attributes.m4 \
+	$(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_options.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -423,6 +424,7 @@ DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
@@ -479,13 +481,14 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
+JANSSON_CFLAGS = @JANSSON_CFLAGS@
+JANSSON_LIBS = @JANSSON_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
 LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
 LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
-LIBDL = @LIBDL@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -497,6 +500,8 @@ LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
 LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
 LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
@@ -557,6 +562,8 @@ QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
 READLINE_LIBS = @READLINE_LIBS@
+SANITIZERS = @SANITIZERS@
+SANITIZER_ENV = @SANITIZER_ENV@
 SED = @SED@
 SELINUX_CFLAGS = @SELINUX_CFLAGS@
 SELINUX_LIBS = @SELINUX_LIBS@
@@ -592,6 +599,7 @@ ac_ct_AR = @ac_ct_AR@
 ac_ct_CC = @ac_ct_CC@
 ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_RANLIB = @ac_ct_RANLIB@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
 am__quote = @am__quote@
diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c
index 838368c4..dbe185b3 100644
--- a/src/devices/wifi/tests/test-wifi-ap-utils.c
+++ b/src/devices/wifi/tests/test-wifi-ap-utils.c
@@ -26,7 +26,7 @@
 
 #include "nm-core-internal.h"
 
-#include "nm-test-utils.h"
+#include "nm-test-utils-core.h"
 
 #define DEBUG 1