summary refs log tree commit diff
path: root/src/devices/wifi
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/wifi')
-rw-r--r--src/devices/wifi/Makefile.am37
-rw-r--r--src/devices/wifi/Makefile.in80
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh-glue.h73
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c90
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.h4
-rw-r--r--src/devices/wifi/nm-device-wifi-glue.h167
-rw-r--r--src/devices/wifi/nm-device-wifi.c1379
-rw-r--r--src/devices/wifi/nm-device-wifi.h4
-rw-r--r--src/devices/wifi/nm-wifi-ap-utils.c3
-rw-r--r--src/devices/wifi/nm-wifi-ap.c1202
-rw-r--r--src/devices/wifi/nm-wifi-ap.h112
-rw-r--r--src/devices/wifi/nm-wifi-enum-types.c14
-rw-r--r--src/devices/wifi/nm-wifi-enum-types.h17
-rw-r--r--src/devices/wifi/nm-wifi-factory.c33
-rw-r--r--src/devices/wifi/tests/Makefile.am10
-rw-r--r--src/devices/wifi/tests/Makefile.in28
-rw-r--r--src/devices/wifi/tests/test-wifi-ap-utils.c13
17 files changed, 1198 insertions, 2068 deletions
diff --git a/src/devices/wifi/Makefile.am b/src/devices/wifi/Makefile.am
index 4ac59e3d..b0919ef7 100644
--- a/src/devices/wifi/Makefile.am
+++ b/src/devices/wifi/Makefile.am
@@ -2,7 +2,9 @@ include $(GLIB_MAKEFILE)
 
 @GNOME_CODE_COVERAGE_RULES@
 
+if ENABLE_TESTS
 SUBDIRS=. tests
+endif
 
 AM_CPPFLAGS = \
 	-I${top_srcdir}/src \
@@ -11,31 +13,15 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/settings \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/src/supplicant-manager \
-	-I${top_srcdir}/include \
-	-I$(top_builddir)/include \
+	-I${top_builddir}/introspection \
+	-I${top_srcdir}/shared \
+	-I$(top_builddir)/shared \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
-	$(DBUS_CFLAGS)
-
-GLIB_GENERATED = nm-wifi-enum-types.h nm-wifi-enum-types.c
-GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
-GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
-nm_wifi_enum_types_sources = \
-	$(srcdir)/nm-device-wifi.h \
-	$(srcdir)/nm-wifi-ap.h \
-	$(srcdir)/nm-device-olpc-mesh.h
-
-glue_sources = \
-	nm-device-wifi-glue.h \
-	nm-device-olpc-mesh-glue.h
-
-%-glue.h: $(top_srcdir)/introspection/%.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $<
-
-BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources)
+	$(GLIB_CFLAGS)
 
 pkglib_LTLIBRARIES = libnm-device-plugin-wifi.la
 
@@ -48,9 +34,7 @@ libnm_device_plugin_wifi_la_SOURCES = \
 	nm-wifi-ap-utils.c \
 	nm-wifi-ap-utils.h \
 	nm-device-olpc-mesh.c \
-	nm-device-olpc-mesh.h \
-	\
-	$(BUILT_SOURCES)
+	nm-device-olpc-mesh.h
 
 SYMBOL_VIS_FILE=$(srcdir)/exports.ver
 
@@ -59,11 +43,10 @@ libnm_device_plugin_wifi_la_LDFLAGS = \
 	 -Wl,--version-script=$(SYMBOL_VIS_FILE)
 
 libnm_device_plugin_wifi_la_LIBADD = \
-	$(DBUS_LIBS) \
+	$(top_builddir)/introspection/libnmdbus.la \
+	$(GLIB_LIBS) \
 	$(GUDEV_LIBS)
 
-CLEANFILES = $(BUILT_SOURCES)
-
 EXTRA_DIST = $(SYMBOL_VIS_FILE)
 
 if ENABLE_TESTS
diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in
index 82ebad74..1286a480 100644
--- a/src/devices/wifi/Makefile.in
+++ b/src/devices/wifi/Makefile.in
@@ -140,14 +140,12 @@ am__uninstall_files_from_dir = { \
 am__installdirs = "$(DESTDIR)$(pkglibdir)"
 LTLIBRARIES = $(pkglib_LTLIBRARIES)
 am__DEPENDENCIES_1 =
-libnm_device_plugin_wifi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
-am__objects_1 = nm-wifi-enum-types.lo
-am__objects_2 =
-am__objects_3 = $(am__objects_1) $(am__objects_2)
+libnm_device_plugin_wifi_la_DEPENDENCIES =  \
+	$(top_builddir)/introspection/libnmdbus.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am_libnm_device_plugin_wifi_la_OBJECTS = nm-wifi-factory.lo \
 	nm-device-wifi.lo nm-wifi-ap.lo nm-wifi-ap-utils.lo \
-	nm-device-olpc-mesh.lo $(am__objects_3)
+	nm-device-olpc-mesh.lo
 libnm_device_plugin_wifi_la_OBJECTS =  \
 	$(am_libnm_device_plugin_wifi_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
@@ -234,7 +232,7 @@ am__define_uniq_tagged_files = \
   done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
-DIST_SUBDIRS = $(SUBDIRS)
+DIST_SUBDIRS = . tests
 am__DIST_COMMON = $(srcdir)/Makefile.in \
 	$(top_srcdir)/build-aux/depcomp
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -278,7 +276,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CKDB_PATH = @CKDB_PATH@
 CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
 CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
 CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
@@ -290,8 +287,6 @@ CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
-DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
@@ -301,6 +296,7 @@ DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
+DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
@@ -355,16 +351,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
-IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
-IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
+LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
 LIBDL = @LIBDL@
-LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
-LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
-LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -401,6 +394,8 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
+NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -429,7 +424,6 @@ POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
 PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
-PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
@@ -444,6 +438,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
 SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
 SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
 SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@
+SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
@@ -504,6 +500,7 @@ mkdir_p = @mkdir_p@
 nmbinary = @nmbinary@
 nmconfdir = @nmconfdir@
 nmdatadir = @nmdatadir@
+nmlibdir = @nmlibdir@
 nmrundir = @nmrundir@
 nmstatedir = @nmstatedir@
 oldincludedir = @oldincludedir@
@@ -511,6 +508,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -526,7 +524,7 @@ with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
-SUBDIRS = . tests
+@ENABLE_TESTS_TRUE@SUBDIRS = . tests
 AM_CPPFLAGS = \
 	-I${top_srcdir}/src \
 	-I${top_builddir}/src \
@@ -534,28 +532,16 @@ AM_CPPFLAGS = \
 	-I${top_srcdir}/src/settings \
 	-I${top_srcdir}/src/platform \
 	-I${top_srcdir}/src/supplicant-manager \
-	-I${top_srcdir}/include \
-	-I$(top_builddir)/include \
+	-I${top_builddir}/introspection \
+	-I${top_srcdir}/shared \
+	-I$(top_builddir)/shared \
 	-I${top_builddir}/libnm-core \
 	-I${top_srcdir}/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
-	$(DBUS_CFLAGS)
+	$(GLIB_CFLAGS)
 
-GLIB_GENERATED = nm-wifi-enum-types.h nm-wifi-enum-types.c
-GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
-GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
-nm_wifi_enum_types_sources = \
-	$(srcdir)/nm-device-wifi.h \
-	$(srcdir)/nm-wifi-ap.h \
-	$(srcdir)/nm-device-olpc-mesh.h
-
-glue_sources = \
-	nm-device-wifi-glue.h \
-	nm-device-olpc-mesh-glue.h
-
-BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources)
 pkglib_LTLIBRARIES = libnm-device-plugin-wifi.la
 libnm_device_plugin_wifi_la_SOURCES = \
 	nm-wifi-factory.c \
@@ -566,9 +552,7 @@ libnm_device_plugin_wifi_la_SOURCES = \
 	nm-wifi-ap-utils.c \
 	nm-wifi-ap-utils.h \
 	nm-device-olpc-mesh.c \
-	nm-device-olpc-mesh.h \
-	\
-	$(BUILT_SOURCES)
+	nm-device-olpc-mesh.h
 
 SYMBOL_VIS_FILE = $(srcdir)/exports.ver
 libnm_device_plugin_wifi_la_LDFLAGS = \
@@ -576,13 +560,12 @@ libnm_device_plugin_wifi_la_LDFLAGS = \
 	 -Wl,--version-script=$(SYMBOL_VIS_FILE)
 
 libnm_device_plugin_wifi_la_LIBADD = \
-	$(DBUS_LIBS) \
+	$(top_builddir)/introspection/libnmdbus.la \
+	$(GLIB_LIBS) \
 	$(GUDEV_LIBS)
 
-CLEANFILES = $(BUILT_SOURCES)
 EXTRA_DIST = $(SYMBOL_VIS_FILE)
-all: $(BUILT_SOURCES)
-	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+all: all-recursive
 
 .SUFFIXES:
 .SUFFIXES: .c .lo .o .obj
@@ -664,7 +647,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-wifi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap-utils.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-enum-types.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-factory.Plo@am__quote@
 
 .c.o:
@@ -851,16 +833,14 @@ distdir: $(DISTFILES)
 @ENABLE_TESTS_FALSE@check-local:
 check-am: all-am
 	$(MAKE) $(AM_MAKEFLAGS) check-local
-check: $(BUILT_SOURCES)
-	$(MAKE) $(AM_MAKEFLAGS) check-recursive
+check: check-recursive
 all-am: Makefile $(LTLIBRARIES)
 installdirs: installdirs-recursive
 installdirs-am:
 	for dir in "$(DESTDIR)$(pkglibdir)"; do \
 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
 	done
-install: $(BUILT_SOURCES)
-	$(MAKE) $(AM_MAKEFLAGS) install-recursive
+install: install-recursive
 install-exec: install-exec-recursive
 install-data: install-data-recursive
 uninstall: uninstall-recursive
@@ -882,7 +862,6 @@ install-strip:
 mostlyclean-generic:
 
 clean-generic:
-	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
 distclean-generic:
 	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -891,7 +870,6 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
-	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
 clean: clean-recursive
 
 clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \
@@ -963,8 +941,7 @@ ps-am:
 
 uninstall-am: uninstall-pkglibLTLIBRARIES
 
-.MAKE: $(am__recursive_targets) all check check-am install install-am \
-	install-strip
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
 
 .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
 	check-am check-local clean clean-generic clean-libtool \
@@ -988,9 +965,6 @@ include $(GLIB_MAKEFILE)
 
 @GNOME_CODE_COVERAGE_RULES@
 
-%-glue.h: $(top_srcdir)/introspection/%.xml
-	$(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $<
-
 @ENABLE_TESTS_TRUE@check-local:
 @ENABLE_TESTS_TRUE@	$(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE)
 
diff --git a/src/devices/wifi/nm-device-olpc-mesh-glue.h b/src/devices/wifi/nm-device-olpc-mesh-glue.h
deleted file mode 100644
index 04b5e83f..00000000
--- a/src/devices/wifi/nm-device-olpc-mesh-glue.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Generated by dbus-binding-tool; do not edit! */
-
-
-#ifndef __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__
-#define __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-G_END_DECLS
-
-#endif /* __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__ */
-
-#include <dbus/dbus-glib.h>
-static const DBusGMethodInfo dbus_glib_nm_device_olpc_mesh_methods[] = {
-};
-
-const DBusGObjectInfo dbus_glib_nm_device_olpc_mesh_object_info = {  1,
-  dbus_glib_nm_device_olpc_mesh_methods,
-  0,
-"\0",
-"org.freedesktop.NetworkManager.Device.OlpcMesh\0PropertiesChanged\0\0",
-"org.freedesktop.NetworkManager.Device.OlpcMesh\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.OlpcMesh\0Companion\0companion\0read\0org.freedesktop.NetworkManager.Device.OlpcMesh\0ActiveChannel\0active_channel\0read\0\0"
-};
-
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index e67d1a20..23ebd9c8 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -26,9 +26,6 @@
 
 #include "config.h"
 
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <dbus/dbus.h>
 #include <netinet/in.h>
 #include <string.h>
 #include <sys/stat.h>
@@ -38,27 +35,24 @@
 #include <sys/ioctl.h>
 #include <errno.h>
 
+#include "nm-default.h"
 #include "nm-device.h"
 #include "nm-device-wifi.h"
 #include "nm-device-olpc-mesh.h"
 #include "nm-device-private.h"
 #include "nm-utils.h"
-#include "nm-logging.h"
 #include "NetworkManagerUtils.h"
 #include "nm-activation-request.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-olpc-mesh.h"
 #include "nm-manager.h"
 #include "nm-enum-types.h"
-#include "nm-dbus-manager.h"
 #include "nm-platform.h"
-#include "nm-wifi-enum-types.h"
 
 /* This is a bug; but we can't really change API now... */
 #include "nm-vpn-dbus-interface.h"
 
-
-#include "nm-device-olpc-mesh-glue.h"
+#include "nmdbus-device-olpc-mesh.h"
 
 #include "nm-device-logging.h"
 _LOG_DECLARE_SELF(NMDeviceOlpcMesh);
@@ -77,6 +71,7 @@ enum {
 
 struct _NMDeviceOlpcMeshPrivate {
 	NMDevice *companion;
+	NMManager *manager;
 	gboolean  stage1_waiting;
 };
 
@@ -213,7 +208,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	GBytes *ssid;
 	const char *anycast_addr;
 
-	connection = nm_device_get_connection (device);
+	connection = nm_device_get_applied_connection (device);
 	g_assert (connection);
 
 	s_mesh = nm_connection_get_setting_olpc_mesh (connection);
@@ -345,7 +340,7 @@ check_companion (NMDeviceOlpcMesh *self, NMDevice *other)
 	_LOGI (LOGD_OLPC, "found companion WiFi device %s",
 	       nm_device_get_iface (other));
 
-	g_signal_connect (G_OBJECT (other), "state-changed",
+	g_signal_connect (G_OBJECT (other), NM_DEVICE_STATE_CHANGED,
 	                  G_CALLBACK (companion_state_changed_cb), self);
 
 	g_signal_connect (G_OBJECT (other), "notify::scanning",
@@ -397,7 +392,7 @@ find_companion (NMDeviceOlpcMesh *self)
 	nm_device_add_pending_action (NM_DEVICE (self), "waiting for companion", TRUE);
 
 	/* Try to find the companion if it's already known to the NMManager */
-	for (list = nm_manager_get_devices (nm_manager_get ()); list ; list = g_slist_next (list)) {
+	for (list = nm_manager_get_devices (priv->manager); list ; list = g_slist_next (list)) {
 		if (check_companion (self, NM_DEVICE (list->data))) {
 			nm_device_queue_recheck_available (NM_DEVICE (self),
 			                                   NM_DEVICE_STATE_REASON_NONE,
@@ -421,14 +416,13 @@ state_changed (NMDevice *device,
 /*******************************************************************/
 
 NMDevice *
-nm_device_olpc_mesh_new (NMPlatformLink *platform_device)
+nm_device_olpc_mesh_new (const char *iface)
 {
-	g_return_val_if_fail (platform_device != NULL, NULL);
-
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_OLPC_MESH,
-	                                  NM_DEVICE_PLATFORM_DEVICE, platform_device,
+	                                  NM_DEVICE_IFACE, iface,
 	                                  NM_DEVICE_TYPE_DESC, "802.11 OLPC Mesh",
 	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH,
+	                                  NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_OLPC_MESH,
 	                                  NULL);
 }
 
@@ -437,35 +431,21 @@ nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self)
 {
 }
 
-static GObject*
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
-	GObjectClass *klass;
-	NMDeviceOlpcMesh *self;
-	NMDeviceWifiCapabilities caps;
-
-	klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class);
-	object = klass->constructor (type, n_construct_params, construct_params);
-	if (!object)
-		return NULL;
-
-	self = NM_DEVICE_OLPC_MESH (object);
-
-	if (!nm_platform_wifi_get_capabilities (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), &caps)) {
-		_LOGW (LOGD_HW | LOGD_OLPC, "failed to initialize WiFi driver");
-		g_object_unref (object);
-		return NULL;
-	}
+	NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object);
+	NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
 
-	g_signal_connect (nm_manager_get (), "device-added", G_CALLBACK (device_added_cb), self);
-	g_signal_connect (nm_manager_get (), "device-removed", G_CALLBACK (device_removed_cb), self);
+	G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->constructed (object);
+
+	priv->manager = g_object_ref (nm_manager_get ());
+
+	g_signal_connect (priv->manager, "device-added", G_CALLBACK (device_added_cb), self);
+	g_signal_connect (priv->manager, "device-removed", G_CALLBACK (device_removed_cb), self);
 
 	/* shorter timeout for mesh connectivity */
 	nm_device_set_dhcp_timeout (NM_DEVICE (self), 20);
-	return object;
 }
 
 static void
@@ -477,10 +457,7 @@ get_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_COMPANION:
-		if (priv->companion)
-			g_value_set_boxed (value, nm_device_get_path (priv->companion));
-		else
-			g_value_set_boxed (value, "/");
+		nm_utils_g_value_set_object_path (value, priv->companion);
 		break;
 	case PROP_ACTIVE_CHANNEL:
 		g_value_set_uint (value, nm_platform_mesh_get_channel (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (device))));
@@ -506,10 +483,15 @@ static void
 dispose (GObject *object)
 {
 	NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object);
+	NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
 
 	companion_cleanup (self);
-	g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_added_cb), self);
-	g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_removed_cb), self);
+
+	if (priv->manager) {
+		g_signal_handlers_disconnect_by_func (priv->manager, G_CALLBACK (device_added_cb), self);
+		g_signal_handlers_disconnect_by_func (priv->manager, G_CALLBACK (device_removed_cb), self);
+		g_clear_object (&priv->manager);
+	}
 
 	G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object);
 }
@@ -522,7 +504,9 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
 
 	g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate));
 
-	object_class->constructor = constructor;
+	NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_OLPC_MESH_SETTING_NAME, NM_LINK_TYPE_OLPC_MESH)
+
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 	object_class->dispose = dispose;
@@ -540,10 +524,10 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
 	/* Properties */
 	g_object_class_install_property
 		(object_class, PROP_COMPANION,
-		 g_param_spec_boxed (NM_DEVICE_OLPC_MESH_COMPANION, "", "",
-		                     DBUS_TYPE_G_OBJECT_PATH,
-		                     G_PARAM_READABLE |
-		                     G_PARAM_STATIC_STRINGS));
+		 g_param_spec_string (NM_DEVICE_OLPC_MESH_COMPANION, "", "",
+		                      NULL,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	g_object_class_install_property
 		(object_class, PROP_ACTIVE_CHANNEL,
@@ -552,8 +536,8 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
 		                    G_PARAM_READABLE |
 		                    G_PARAM_STATIC_STRINGS));
 
-	nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
-	                                        G_TYPE_FROM_CLASS (klass),
-	                                        &dbus_glib_nm_device_olpc_mesh_object_info);
+	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
+	                                        NMDBUS_TYPE_DEVICE_OLPC_MESH_SKELETON,
+	                                        NULL);
 }
 
diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h
index 67d83fb0..63895a88 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.h
+++ b/src/devices/wifi/nm-device-olpc-mesh.h
@@ -28,8 +28,6 @@
 #ifndef __NETWORKMANAGER_DEVICE_OLPC_MESH_H__
 #define __NETWORKMANAGER_DEVICE_OLPC_MESH_H__
 
-#include <glib-object.h>
-
 #include "nm-device.h"
 
 G_BEGIN_DECLS
@@ -67,7 +65,7 @@ struct _NMDeviceOlpcMeshClass
 
 GType nm_device_olpc_mesh_get_type (void);
 
-NMDevice *nm_device_olpc_mesh_new (NMPlatformLink *platform_device);
+NMDevice *nm_device_olpc_mesh_new (const char *iface);
 
 G_END_DECLS
 
diff --git a/src/devices/wifi/nm-device-wifi-glue.h b/src/devices/wifi/nm-device-wifi-glue.h
deleted file mode 100644
index 8f8da2af..00000000
--- a/src/devices/wifi/nm-device-wifi-glue.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Generated by dbus-binding-tool; do not edit! */
-
-
-#ifndef __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__
-#define __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* BOOLEAN:POINTER,POINTER */
-extern void dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER (GClosure     *closure,
-                                                                       GValue       *return_value,
-                                                                       guint         n_param_values,
-                                                                       const GValue *param_values,
-                                                                       gpointer      invocation_hint,
-                                                                       gpointer      marshal_data);
-void
-dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER (GClosure     *closure,
-                                                           GValue       *return_value G_GNUC_UNUSED,
-                                                           guint         n_param_values,
-                                                           const GValue *param_values,
-                                                           gpointer      invocation_hint G_GNUC_UNUSED,
-                                                           gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer     data1,
-                                                             gpointer     arg_1,
-                                                             gpointer     arg_2,
-                                                             gpointer     data2);
-  GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
-  GCClosure *cc = (GCClosure*) closure;
-  gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_pointer (param_values + 1),
-                       g_marshal_value_peek_pointer (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* NONE:BOXED,POINTER */
-extern void dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER (GClosure     *closure,
-                                                                  GValue       *return_value,
-                                                                  guint         n_param_values,
-                                                                  const GValue *param_values,
-                                                                  gpointer      invocation_hint,
-                                                                  gpointer      marshal_data);
-void
-dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER (GClosure     *closure,
-                                                      GValue       *return_value G_GNUC_UNUSED,
-                                                      guint         n_param_values,
-                                                      const GValue *param_values,
-                                                      gpointer      invocation_hint G_GNUC_UNUSED,
-                                                      gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer     data1,
-                                                    gpointer     arg_1,
-                                                    gpointer     arg_2,
-                                                    gpointer     data2);
-  GMarshalFunc_VOID__BOXED_POINTER callback;
-  GCClosure *cc = (GCClosure*) closure;
-  gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_boxed (param_values + 1),
-            g_marshal_value_peek_pointer (param_values + 2),
-            data2);
-}
-#define dbus_glib_marshal_nm_device_wifi_NONE__BOXED_POINTER	dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER
-
-G_END_DECLS
-
-#endif /* __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__ */
-
-#include <dbus/dbus-glib.h>
-static const DBusGMethodInfo dbus_glib_nm_device_wifi_methods[] = {
-  { (GCallback) impl_device_get_access_points, dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER, 0 },
-  { (GCallback) impl_device_get_all_access_points, dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER, 89 },
-  { (GCallback) impl_device_request_scan, dbus_glib_marshal_nm_device_wifi_NONE__BOXED_POINTER, 181 },
-};
-
-const DBusGObjectInfo dbus_glib_nm_device_wifi_object_info = {  1,
-  dbus_glib_nm_device_wifi_methods,
-  3,
-"org.freedesktop.NetworkManager.Device.Wireless\0GetAccessPoints\0S\0access_points\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager.Device.Wireless\0GetAllAccessPoints\0S\0access_points\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager.Device.Wireless\0RequestScan\0A\0options\0I\0a{sv}\0\0\0",
-"org.freedesktop.NetworkManager.Device.Wireless\0PropertiesChanged\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPointAdded\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPointRemoved\0\0",
-"org.freedesktop.NetworkManager.Device.Wireless\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Wireless\0PermHwAddress\0perm_hw_address\0read\0org.freedesktop.NetworkManager.Device.Wireless\0Mode\0mode\0read\0org.freedesktop.NetworkManager.Device.Wireless\0Bitrate\0bitrate\0read\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPoints\0access_points\0read\0org.freedesktop.NetworkManager.Device.Wireless\0ActiveAccessPoint\0active_access_point\0read\0org.freedesktop.NetworkManager.Device.Wireless\0WirelessCapabilities\0wireless_capabilities\0read\0\0"
-};
-
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 1bf64bcc..64da03e1 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -21,21 +21,16 @@
 
 #include "config.h"
 
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <dbus/dbus.h>
 #include <netinet/in.h>
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
 
-#include "nm-glib-compat.h"
-#include "nm-dbus-manager.h"
+#include "nm-default.h"
 #include "nm-device.h"
 #include "nm-device-wifi.h"
 #include "nm-device-private.h"
 #include "nm-utils.h"
-#include "nm-logging.h"
 #include "NetworkManagerUtils.h"
 #include "nm-activation-request.h"
 #include "nm-supplicant-manager.h"
@@ -52,25 +47,11 @@
 #include "nm-auth-utils.h"
 #include "nm-settings-connection.h"
 #include "nm-enum-types.h"
-#include "nm-dbus-glib-types.h"
-#include "nm-wifi-enum-types.h"
 #include "nm-connection-provider.h"
-#include "gsystem-local-alloc.h"
+#include "nm-core-internal.h"
+#include "nm-config.h"
 
-
-static gboolean impl_device_get_access_points (NMDeviceWifi *device,
-                                               GPtrArray **aps,
-                                               GError **err);
-
-static gboolean impl_device_get_all_access_points (NMDeviceWifi *device,
-                                                   GPtrArray **aps,
-                                                   GError **err);
-
-static void impl_device_request_scan (NMDeviceWifi *device,
-                                      GHashTable *options,
-                                      DBusGMethodInvocation *context);
-
-#include "nm-device-wifi-glue.h"
+#include "nmdbus-device-wifi.h"
 
 #include "nm-device-logging.h"
 _LOG_DECLARE_SELF(NMDeviceWifi);
@@ -111,29 +92,27 @@ enum {
 static guint signals[LAST_SIGNAL] = { 0 };
 
 struct _NMDeviceWifiPrivate {
-	gboolean disposed;
-
 	gint8             invalid_strength_counter;
 
-	GSList *          ap_list;
+	GHashTable *      aps;
 	NMAccessPoint *   current_ap;
 	guint32           rate;
 	gboolean          enabled; /* rfkilled or not */
 
+	gint32            last_scan;
 	gint32            scheduled_scan_time;
 	guint8            scan_interval; /* seconds */
 	guint             pending_scan_id;
-	guint             scanlist_cull_id;
-	gboolean          requested_scan;
+	guint             ap_dump_id;
+	bool              requested_scan;
 
 	NMSupplicantManager   *sup_mgr;
 	NMSupplicantInterface *sup_iface;
 	guint                  sup_timeout_id; /* supplicant association timeout */
 
-	gboolean          ssid_found;
+	bool              ssid_found;
 	NM80211Mode       mode;
 
-	guint32           failed_link_count;
 	guint             periodic_source_id;
 	guint             link_timeout_id;
 	guint32           failed_iface_count;
@@ -164,7 +143,7 @@ static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface,
 
 static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
                                              const char *object_path,
-                                             GHashTable *properties,
+                                             GVariant *properties,
                                              NMDeviceWifi *self);
 
 static void supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
@@ -179,49 +158,34 @@ static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface,
                                                  GParamSpec * pspec,
                                                  NMDeviceWifi * self);
 
-static void schedule_scanlist_cull (NMDeviceWifi *self);
+static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
+                                                 GParamSpec *pspec,
+                                                 NMDeviceWifi *self);
 
-static void request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options);
+static void request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options);
 
-static void remove_access_point (NMDeviceWifi *device, NMAccessPoint *ap);
+static void ap_add_remove (NMDeviceWifi *self,
+                           guint signum,
+                           NMAccessPoint *ap,
+                           gboolean recheck_available_connections);
 
 static void remove_supplicant_interface_error_handler (NMDeviceWifi *self);
 
 /*****************************************************************/
 
-static GObject*
-constructor (GType type,
-             guint n_construct_params,
-             GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
 {
-	GObject *object;
-	GObjectClass *klass;
-	NMDeviceWifi *self;
-	NMDeviceWifiPrivate *priv;
+	NMDeviceWifi *self = NM_DEVICE_WIFI (object);
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
-	klass = G_OBJECT_CLASS (nm_device_wifi_parent_class);
-	object = klass->constructor (type, n_construct_params, construct_params);
-	if (!object)
-		return NULL;
-
-	self = NM_DEVICE_WIFI (object);
-	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-
-	if (!nm_platform_wifi_get_capabilities (NM_PLATFORM_GET,
-	                                        nm_device_get_ifindex (NM_DEVICE (self)),
-	                                        &priv->capabilities)) {
-		_LOGW (LOGD_HW | LOGD_WIFI, "failed to initialize WiFi driver");
-		g_object_unref (object);
-		return NULL;
-	}
+	G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object);
 
 	if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP)
 		_LOGI (LOGD_HW | LOGD_WIFI, "driver supports Access Point (AP) mode");
 
 	/* Connect to the supplicant manager */
 	priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ());
-
-	return object;
 }
 
 static gboolean
@@ -268,6 +232,10 @@ supplicant_interface_acquire (NMDeviceWifi *self)
 	                  "notify::scanning",
 	                  G_CALLBACK (supplicant_iface_notify_scanning_cb),
 	                  self);
+	g_signal_connect (priv->sup_iface,
+	                  "notify::" NM_SUPPLICANT_INTERFACE_CURRENT_BSS,
+	                  G_CALLBACK (supplicant_iface_notify_current_bss),
+	                  self);
 
 	return TRUE;
 }
@@ -288,10 +256,7 @@ supplicant_interface_release (NMDeviceWifi *self)
 	_LOGD (LOGD_WIFI_SCAN, "reset scanning interval to %d seconds",
 	       priv->scan_interval);
 
-	if (priv->scanlist_cull_id) {
-		g_source_remove (priv->scanlist_cull_id);
-		priv->scanlist_cull_id = 0;
-	}
+	nm_clear_g_source (&priv->ap_dump_id);
 
 	if (priv->sup_iface) {
 		remove_supplicant_interface_error_handler (self);
@@ -310,177 +275,30 @@ supplicant_interface_release (NMDeviceWifi *self)
 static NMAccessPoint *
 get_ap_by_path (NMDeviceWifi *self, const char *path)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	GSList *iter;
+	g_return_val_if_fail (path != NULL, NULL);
+	return g_hash_table_lookup (NM_DEVICE_WIFI_GET_PRIVATE (self)->aps, path);
 
-	if (!path)
-		return NULL;
-
-	for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
-		if (g_strcmp0 (path, nm_ap_get_dbus_path (NM_AP (iter->data))) == 0)
-			return NM_AP (iter->data);
-	}
-	return NULL;
 }
 
 static NMAccessPoint *
 get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	GSList *iter;
+	GHashTableIter iter;
+	NMAccessPoint *ap;
 
-	if (!path)
-		return NULL;
+	g_return_val_if_fail (path != NULL, NULL);
 
-	for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
-		if (g_strcmp0 (path, nm_ap_get_supplicant_path (NM_AP (iter->data))) == 0)
-			return NM_AP (iter->data);
+	g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
+		if (g_strcmp0 (path, nm_ap_get_supplicant_path (ap)) == 0)
+			return ap;
 	}
 	return NULL;
 }
 
-static NMAccessPoint *
-find_active_ap (NMDeviceWifi *self,
-                NMAccessPoint *ignore_ap,
-                gboolean match_hidden)
-{
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	int ifindex = nm_device_get_ifindex (NM_DEVICE (self));
-	guint8 bssid[ETH_ALEN];
-	GByteArray *ssid;
-	GSList *iter;
-	int i = 0;
-	NMAccessPoint *match_nofreq = NULL, *active_ap = NULL;
-	gboolean found_a_band = FALSE;
-	gboolean found_bg_band = FALSE;
-	NM80211Mode devmode;
-	guint32 devfreq;
-
-	nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid);
-	_LOGD (LOGD_WIFI, "active BSSID: %02x:%02x:%02x:%02x:%02x:%02x",
-	       bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
-
-	if (!nm_ethernet_address_is_valid (bssid, ETH_ALEN))
-		return NULL;
-
-	ssid = nm_platform_wifi_get_ssid (NM_PLATFORM_GET, ifindex);
-	_LOGD (LOGD_WIFI, "active SSID: %s%s%s",
-	       ssid ? "'" : "",
-	       ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
-	       ssid ? "'" : "");
-
-	devmode = nm_platform_wifi_get_mode (NM_PLATFORM_GET, ifindex);
-	devfreq = nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex);
-
-	/* When matching hidden APs, do a second pass that ignores the SSID check,
-	 * because NM might not yet know the SSID of the hidden AP in the scan list
-	 * and therefore it won't get matched the first time around.
-	 */
-	while (i++ < (match_hidden ? 2 : 1)) {
-		_LOGD (LOGD_WIFI, "  Pass #%d %s", i, i > 1 ? "(ignoring SSID)" : "");
-
-		/* Find this SSID + BSSID in the device's AP list */
-		for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
-			NMAccessPoint *ap = NM_AP (iter->data);
-			const char *ap_bssid = nm_ap_get_address (ap);
-			const GByteArray *ap_ssid = nm_ap_get_ssid (ap);
-			NM80211Mode apmode;
-			guint32 apfreq;
-
-			_LOGD (LOGD_WIFI, "    AP: %s%s%s  %s",
-			       ap_ssid ? "'" : "",
-			       ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)",
-			       ap_ssid ? "'" : "",
-			       str_if_set (ap_bssid, "(none)"));
-
-			if (ap == ignore_ap) {
-				_LOGD (LOGD_WIFI, "      ignored");
-				continue;
-			}
-
-			if (!nm_utils_hwaddr_matches (bssid, ETH_ALEN, ap_bssid, -1)) {
-				_LOGD (LOGD_WIFI, "      BSSID mismatch");
-				continue;
-			}
-
-			if (i == 0) {
-				if (   (ssid && !ap_ssid)
-				    || (ap_ssid && !ssid)
-				    || (ssid && ap_ssid && !nm_utils_same_ssid (ssid->data, ssid->len,
-				                                                ap_ssid->data, ap_ssid->len,
-				                                                TRUE))) {
-					_LOGD (LOGD_WIFI, "      SSID mismatch");
-					continue;
-				}
-			}
-
-			apmode = nm_ap_get_mode (ap);
-			if (devmode != apmode) {
-				_LOGD (LOGD_WIFI, "      mode mismatch (device %d, ap %d)",
-				       devmode, apmode);
-				continue;
-			}
-
-			apfreq = nm_ap_get_freq (ap);
-			if (devfreq != apfreq) {
-				_LOGD (LOGD_WIFI, "      frequency mismatch (device %u, ap %u)",
-				       devfreq, apfreq);
-
-				if (match_nofreq == NULL)
-					match_nofreq = ap;
-
-				if (apfreq > 4000)
-					found_a_band = TRUE;
-				else if (apfreq > 2000)
-					found_bg_band = TRUE;
-				continue;
-			}
-
-			// FIXME: handle security settings here too
-			_LOGD (LOGD_WIFI, "      matched");
-			active_ap = ap;
-			goto done;
-		}
-	}
-
-	/* Some proprietary drivers (wl.o) report tuned frequency (like when
-	 * scanning) instead of the associated AP's frequency.  This is a great
-	 * example of how WEXT is underspecified.  We use frequency to find the
-	 * active AP in the scan list because some configurations use the same
-	 * SSID/BSSID on the 2GHz and 5GHz bands simultaneously, and we need to
-	 * make sure we get the right AP in the right band.  This configuration
-	 * is uncommon though, and the frequency check penalizes closed drivers we
-	 * can't fix.  Because we're not total dicks, ignore the frequency condition
-	 * if the associated BSSID/SSID exists only in one band since that's most
-	 * likely the AP we want.  Sometimes wl.o returns a frequency of 0, so if
-	 * we can't match the AP based on frequency at all, just give up.
-	 */
-	if (match_nofreq && ((found_a_band != found_bg_band) || (devfreq == 0))) {
-		const GByteArray *ap_ssid = nm_ap_get_ssid (match_nofreq);
-
-		_LOGD (LOGD_WIFI, "    matched %s%s%s  %s",
-		       ap_ssid ? "'" : "",
-		       ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)",
-		       ap_ssid ? "'" : "",
-		       str_if_set (nm_ap_get_address (match_nofreq), "(none)"));
-
-		active_ap = match_nofreq;
-		goto done;
-	}
-
-	_LOGD (LOGD_WIFI, "  No matching AP found.");
-
-done:
-	if (ssid)
-		g_byte_array_free (ssid, TRUE);
-	return active_ap;
-}
-
 static void
 update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap)
 {
-	NMConnection *connection;
-
 	g_return_if_fail (NM_IS_DEVICE_WIFI (self));
 
 	if (ap == NULL)
@@ -490,12 +308,10 @@ update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap)
 	if (nm_ap_get_mode (ap) != NM_802_11_MODE_INFRA)
 		return;
 
-	if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED) {
-		connection = nm_device_get_connection (NM_DEVICE (self));
-		if (connection) {
-			nm_settings_connection_add_seen_bssid (NM_SETTINGS_CONNECTION (connection),
-			                                       nm_ap_get_address (ap));
-		}
+	if (   nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED
+	    && nm_device_has_unmodified_applied_connection (NM_DEVICE (self), NM_SETTING_COMPARE_FLAG_NONE)) {
+		nm_settings_connection_add_seen_bssid (nm_device_get_settings_connection (NM_DEVICE (self)),
+		                                       nm_ap_get_address (ap));
 	}
 }
 
@@ -516,13 +332,6 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai
 	if (new_ap) {
 		priv->current_ap = g_object_ref (new_ap);
 
-		/* Move the current AP to the front of the scan list.  Since we
-		 * do a lot of searches looking for the current AP, it saves
-		 * time to have it in front.
-		 */
-		priv->ap_list = g_slist_remove (priv->ap_list, new_ap);
-		priv->ap_list = g_slist_prepend (priv->ap_list, new_ap);
-
 		/* Update seen BSSIDs cache */
 		update_seen_bssids_cache (self, priv->current_ap);
 	} else
@@ -531,11 +340,9 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai
 	if (old_ap) {
 		NM80211Mode mode = nm_ap_get_mode (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));
-		}
+		/* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */
+		if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap))
+			ap_add_remove (self, ACCESS_POINT_REMOVED, old_ap, recheck_available_connections);
 		g_object_unref (old_ap);
 	}
 
@@ -543,11 +350,10 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai
 }
 
 static void
-periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap)
+periodic_update (NMDeviceWifi *self)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	int ifindex = nm_device_get_ifindex (NM_DEVICE (self));
-	NMAccessPoint *new_ap;
 	guint32 new_rate;
 	int percent;
 	NMDeviceState state;
@@ -574,65 +380,15 @@ periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap)
 	if (priv->mode == NM_802_11_MODE_AP)
 		return;
 
-	/* In IBSS mode, most newer firmware/drivers do "BSS coalescing" where
-	 * multiple IBSS stations using the same SSID will eventually switch to
-	 * using the same BSSID to avoid network segmentation.  When this happens,
-	 * the card's reported BSSID will change, but the new BSS may not
-	 * be in the scan list, since scanning isn't done in ad-hoc mode for
-	 * various reasons.  So pull the BSSID from the card and update the
-	 * current AP with it, if the current AP is adhoc.
-	 */
-	if (priv->current_ap && (nm_ap_get_mode (priv->current_ap) == NM_802_11_MODE_ADHOC)) {
-		guint8 bssid[ETH_ALEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
-
-		nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid);
-		/* 0x02 means "locally administered" and should be OR-ed into
-		 * the first byte of IBSS BSSIDs.
-		 */
-		if ((bssid[0] & 0x02) && nm_ethernet_address_is_valid (bssid, ETH_ALEN)) {
-			char *bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN);
-			nm_ap_set_address (priv->current_ap, bssid_str);
-			g_free (bssid_str);
-		}
-	}
-
-	new_ap = find_active_ap (self, ignore_ap, FALSE);
-	if (new_ap) {
-		/* Try to smooth out the strength.  Atmel cards, for example, will give no strength
-		 * one second and normal strength the next.
-		 */
+	if (priv->current_ap) {
+		/* Smooth out the strength to work around crappy drivers */
 		percent = nm_platform_wifi_get_quality (NM_PLATFORM_GET, ifindex);
 		if (percent >= 0 || ++priv->invalid_strength_counter > 3) {
-			nm_ap_set_strength (new_ap, (gint8) percent);
+			nm_ap_set_strength (priv->current_ap, (gint8) percent);
 			priv->invalid_strength_counter = 0;
 		}
 	}
 
-	if (new_ap != priv->current_ap) {
-		const char *new_bssid = NULL;
-		const GByteArray *new_ssid = NULL;
-		const char *old_bssid = NULL;
-		const GByteArray *old_ssid = NULL;
-
-		if (new_ap) {
-			new_bssid = nm_ap_get_address (new_ap);
-			new_ssid = nm_ap_get_ssid (new_ap);
-		}
-
-		if (priv->current_ap) {
-			old_bssid = nm_ap_get_address (priv->current_ap);
-			old_ssid = nm_ap_get_ssid (priv->current_ap);
-		}
-
-		_LOGI (LOGD_WIFI, "roamed from BSSID %s (%s) to %s (%s)",
-		       old_bssid ? old_bssid : "(none)",
-		       old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)",
-		       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);
-	}
-
 	new_rate = nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex);
 	if (new_rate != priv->rate) {
 		priv->rate = new_rate;
@@ -643,10 +399,18 @@ periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap)
 static gboolean
 periodic_update_cb (gpointer user_data)
 {
-	periodic_update (NM_DEVICE_WIFI (user_data), NULL);
+	periodic_update (NM_DEVICE_WIFI (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)
 {
@@ -657,47 +421,55 @@ bring_up (NMDevice *device, gboolean *no_firmware)
 }
 
 static void
-emit_ap_added_removed (NMDeviceWifi *self,
-                       guint signum,
-                       NMAccessPoint *ap,
-                       gboolean recheck_available_connections)
+ap_add_remove (NMDeviceWifi *self,
+               guint signum,
+               NMAccessPoint *ap,
+               gboolean recheck_available_connections)
 {
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	nm_assert (NM_IN_SET (signum, ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED));
+
+	if (signum == ACCESS_POINT_ADDED) {
+		g_hash_table_insert (priv->aps,
+		                     (gpointer) nm_exported_object_export ((NMExportedObject *) ap),
+		                     g_object_ref (ap));
+	}
+
 	g_signal_emit (self, signals[signum], 0, ap);
 	g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACCESS_POINTS);
+
+	if (signum == ACCESS_POINT_REMOVED) {
+		g_hash_table_remove (priv->aps, nm_exported_object_get_path ((NMExportedObject *) ap));
+		nm_exported_object_unexport ((NMExportedObject *) ap);
+		g_object_unref (ap);
+	}
+
 	nm_device_emit_recheck_auto_activate (NM_DEVICE (self));
 	if (recheck_available_connections)
 		nm_device_recheck_available_connections (NM_DEVICE (self));
 }
 
 static void
-remove_access_point (NMDeviceWifi *device,
-                     NMAccessPoint *ap)
-{
-	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-
-	g_return_if_fail (ap);
-	g_return_if_fail (ap != priv->current_ap);
-	g_return_if_fail (g_slist_find (priv->ap_list, ap));
-
-	priv->ap_list = g_slist_remove (priv->ap_list, ap);
-	emit_ap_added_removed (self, ACCESS_POINT_REMOVED, ap, FALSE);
-	g_object_unref (ap);
-}
-
-static void
 remove_all_aps (NMDeviceWifi *self)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	GHashTableIter iter;
+	NMAccessPoint *ap;
 
-	if (priv->ap_list) {
-		set_current_ap (self, NULL, FALSE);
+	if (!g_hash_table_size (priv->aps))
+		return;
 
-		while (priv->ap_list)
-			remove_access_point (self, NM_AP (priv->ap_list->data));
+	set_current_ap (self, NULL, FALSE);
 
-		nm_device_recheck_available_connections (NM_DEVICE (self));
+again:
+	g_hash_table_iter_init (&iter, priv->aps);
+	if (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
+		ap_add_remove (self, ACCESS_POINT_REMOVED, ap, FALSE);
+		goto again;
 	}
+
+	nm_device_recheck_available_connections (NM_DEVICE (self));
 }
 
 static void
@@ -706,29 +478,14 @@ deactivate (NMDevice *device)
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	int ifindex = nm_device_get_ifindex (device);
-	NMConnection *connection;
 	NM80211Mode old_mode = priv->mode;
 
-	connection = nm_device_get_connection (device);
-	if (connection) {
-		/* Clear wireless secrets tries when deactivating */
-		g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL);
-	}
-
-	if (priv->periodic_source_id) {
-		g_source_remove (priv->periodic_source_id);
-		priv->periodic_source_id = 0;
-	}
+	nm_clear_g_source (&priv->periodic_source_id);
 
 	cleanup_association_attempt (self, TRUE);
 
 	priv->rate = 0;
 
-	/* If the AP is 'fake', i.e. it wasn't actually found from
-	 * a scan but the user tried to connect to it manually (maybe it
-	 * 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);
 
 	/* Clear any critical protocol notification in the Wi-Fi stack */
@@ -738,6 +495,8 @@ deactivate (NMDevice *device)
 	if (nm_device_get_initial_hw_address (device))
 		nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_WIFI);
 
+	nm_platform_wifi_set_powersave (NM_PLATFORM_GET, ifindex, 0);
+
 	/* Ensure we're in infrastructure mode after deactivation; some devices
 	 * (usually older ones) don't scan well in adhoc mode.
 	 */
@@ -848,7 +607,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 			return FALSE;
 
 		if (priv->sup_iface) {
-			if (nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_NO)
+			if (nm_supplicant_interface_get_ap_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_NO)
 				return FALSE;
 		}
 	}
@@ -860,6 +619,28 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 	return TRUE;
 }
 
+static NMAccessPoint *
+find_first_compatible_ap (NMDeviceWifi *self,
+                          NMConnection *connection,
+                          gboolean allow_unstable_order)
+{
+	GHashTableIter iter;
+	NMAccessPoint *ap;
+	NMAccessPoint *cand_ap = NULL;
+
+	g_return_val_if_fail (connection != NULL, NULL);
+
+	g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) {
+		if (!nm_ap_check_compatible (ap, connection))
+			continue;
+		if (allow_unstable_order)
+			return ap;
+		if (!cand_ap || (nm_ap_get_id (cand_ap) < nm_ap_get_id (ap)))
+			cand_ap = ap;
+	}
+	return cand_ap;
+}
 
 static gboolean
 check_connection_available (NMDevice *device,
@@ -867,10 +648,8 @@ check_connection_available (NMDevice *device,
                             NMDeviceCheckConAvailableFlags flags,
                             const char *specific_object)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
 	NMSettingWireless *s_wifi;
 	const char *mode;
-	GSList *ap_iter = NULL;
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_return_val_if_fail (s_wifi, FALSE);
@@ -904,13 +683,8 @@ check_connection_available (NMDevice *device,
 	if (nm_setting_wireless_get_hidden (s_wifi) || NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
 		return TRUE;
 
-	/* check if its visible */
-	for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) {
-		if (nm_ap_check_compatible (NM_AP (ap_iter->data), connection))
-			return TRUE;
-	}
-
-	return FALSE;
+	/* check at least one AP is compatible with this connection */
+	return !!find_first_compatible_ap (NM_DEVICE_WIFI (device), connection, TRUE);
 }
 
 /*
@@ -957,7 +731,6 @@ complete_connection (NMDevice *device,
                      GError **error)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	NMSettingWireless *s_wifi;
 	const char *setting_mac;
 	char *str_ssid = NULL;
@@ -965,7 +738,6 @@ complete_connection (NMDevice *device,
 	const GByteArray *ssid = NULL;
 	GByteArray *tmp_ssid = NULL;
 	GBytes *setting_ssid = NULL;
-	GSList *iter;
 	gboolean hidden = FALSE;
 	const char *perm_hw_addr;
 
@@ -991,12 +763,7 @@ complete_connection (NMDevice *device,
 		}
 
 		/* Find a compatible AP in the scan list */
-		for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
-			if (nm_ap_check_compatible (NM_AP (iter->data), connection)) {
-				ap = NM_AP (iter->data);
-				break;
-			}
-		}
+		ap = find_first_compatible_ap (self, connection, FALSE);
 
 		/* If we still don't have an AP, then the WiFI settings needs to be
 		 * fully specified by the client.  Might not be able to find an AP
@@ -1159,8 +926,7 @@ can_auto_connect (NMDevice *device,
                   char **specific_object)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	GSList *ap_iter;
+	NMAccessPoint *ap;
 	const char *method = NULL;
 	guint64 timestamp = 0;
 
@@ -1181,130 +947,141 @@ can_auto_connect (NMDevice *device,
 	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
 		return TRUE;
 
-	for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) {
-		NMAccessPoint *ap = NM_AP (ap_iter->data);
-
-		if (nm_ap_check_compatible (ap, connection)) {
-			/* All good; connection is usable */
-			*specific_object = (char *) nm_ap_get_dbus_path (ap);
-			return TRUE;
-		}
+	ap = find_first_compatible_ap (self, connection, FALSE);
+	if (ap) {
+		/* All good; connection is usable */
+		*specific_object = (char *) nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap));
+		return TRUE;
 	}
 
 	return FALSE;
 }
 
-static void
-ap_list_dump (NMDeviceWifi *self)
+static gint
+ap_id_compare (NMAccessPoint *a, NMAccessPoint *b)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	GSList * elt;
-	int i = 0;
+	guint32 a_id = nm_ap_get_id (a);
+	guint32 b_id = nm_ap_get_id (b);
 
-	g_return_if_fail (NM_IS_DEVICE_WIFI (self));
+	return a_id < b_id ? -1 : (a_id == b_id ? 0 : 1);
+}
 
-	_LOGD (LOGD_WIFI_SCAN, "Current AP list:");
-	for (elt = priv->ap_list; elt; elt = g_slist_next (elt), i++) {
-		NMAccessPoint * ap = NM_AP (elt->data);
-		nm_ap_dump (ap, "List AP: ");
-	}
-	_LOGD (LOGD_WIFI_SCAN, "Current AP list: done");
+static GSList *
+get_sorted_ap_list (NMDeviceWifi *self)
+{
+	GSList *sorted = NULL;
+	GHashTableIter iter;
+	NMAccessPoint *ap;
+
+	g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap))
+		sorted = g_slist_prepend (sorted, ap);
+	return g_slist_sort (sorted, (GCompareFunc) ap_id_compare);
 }
 
-static gboolean
-impl_device_get_access_points (NMDeviceWifi *self,
-                               GPtrArray **aps,
-                               GError **err)
+static void
+impl_device_wifi_get_access_points (NMDeviceWifi *self,
+                                    GDBusMethodInvocation *context)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	GSList *elt;
+	GSList *sorted, *iter;
+	GPtrArray *paths;
 
-	*aps = g_ptr_array_new ();
-	for (elt = priv->ap_list; elt; elt = g_slist_next (elt)) {
-		NMAccessPoint *ap = NM_AP (elt->data);
+	paths = g_ptr_array_new ();
+	sorted = get_sorted_ap_list (self);
+	for (iter = sorted; iter; iter = iter->next) {
+		NMAccessPoint *ap = NM_AP (iter->data);
 
 		if (nm_ap_get_ssid (ap))
-			g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (ap)));
+			g_ptr_array_add (paths, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap))));
 	}
-	return TRUE;
+	g_ptr_array_add (paths, NULL);
+	g_slist_free (sorted);
+
+	g_dbus_method_invocation_return_value (context, g_variant_new ("(^ao)", (char **) paths->pdata));
+	g_ptr_array_unref (paths);
 }
 
-static gboolean
-impl_device_get_all_access_points (NMDeviceWifi *self,
-                                   GPtrArray **aps,
-                                   GError **err)
+static void
+impl_device_wifi_get_all_access_points (NMDeviceWifi *self,
+                                        GDBusMethodInvocation *context)
 {
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	GSList *elt;
+	GSList *sorted, *iter;
+	GPtrArray *paths;
 
-	*aps = g_ptr_array_new ();
-	for (elt = priv->ap_list; elt; elt = g_slist_next (elt))
-		g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (NM_AP (elt->data))));
-	return TRUE;
+	paths = g_ptr_array_new ();
+	sorted = get_sorted_ap_list (self);
+	for (iter = sorted; iter; iter = iter->next)
+		g_ptr_array_add (paths, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data))));
+	g_ptr_array_add (paths, NULL);
+	g_slist_free (sorted);
+
+	g_dbus_method_invocation_return_value (context, g_variant_new ("(^ao)", (char **) paths->pdata));
+	g_ptr_array_unref (paths);
 }
 
 static void
 request_scan_cb (NMDevice *device,
-                 DBusGMethodInvocation *context,
+                 GDBusMethodInvocation *context,
+                 NMAuthSubject *subject,
                  GError *error,
                  gpointer user_data)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
-	GError *local = NULL;
-	gs_unref_hashtable GHashTable *new_scan_options = user_data;
+	gs_unref_variant GVariant *new_scan_options = user_data;
 
 	if (error) {
-		dbus_g_method_return_error (context, error);
+		g_dbus_method_invocation_return_gerror (context, error);
 		return;
 	}
 
 	if (!check_scanning_allowed (self)) {
-		local = g_error_new_literal (NM_DEVICE_ERROR,
-		                             NM_DEVICE_ERROR_NOT_ALLOWED,
-		                             "Scanning not allowed at this time");
-		dbus_g_method_return_error (context, local);
-		g_error_free (local);
+		g_dbus_method_invocation_return_error_literal (context,
+		                                               NM_DEVICE_ERROR,
+		                                               NM_DEVICE_ERROR_NOT_ALLOWED,
+		                                               "Scanning not allowed at this time");
 		return;
 	}
 
 	cancel_pending_scan (self);
 	request_wireless_scan (self, new_scan_options);
-	dbus_g_method_return (context);
+	g_dbus_method_invocation_return_value (context, NULL);
 }
 
 static void
-impl_device_request_scan (NMDeviceWifi *self,
-                          GHashTable *options,
-                          DBusGMethodInvocation *context)
+impl_device_wifi_request_scan (NMDeviceWifi *self,
+                               GDBusMethodInvocation *context,
+                               GVariant *options)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	NMDevice *device = NM_DEVICE (self);
 	gint32 last_scan;
-	GError *error;
 
 	if (   !priv->enabled
 	    || !priv->sup_iface
 	    || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED
 	    || nm_device_is_activating (device)) {
-		error = g_error_new_literal (NM_DEVICE_ERROR,
-		                             NM_DEVICE_ERROR_NOT_ALLOWED,
-		                             "Scanning not allowed while unavailable or activating");
-		goto error;
+		g_dbus_method_invocation_return_error_literal (context,
+		                                               NM_DEVICE_ERROR,
+		                                               NM_DEVICE_ERROR_NOT_ALLOWED,
+		                                               "Scanning not allowed while unavailable or activating");
+		return;
 	}
 
 	if (nm_supplicant_interface_get_scanning (priv->sup_iface)) {
-		error = g_error_new_literal (NM_DEVICE_ERROR,
-		                             NM_DEVICE_ERROR_NOT_ALLOWED,
-		                             "Scanning not allowed while already scanning");
-		goto error;
+		g_dbus_method_invocation_return_error_literal (context,
+		                                               NM_DEVICE_ERROR,
+		                                               NM_DEVICE_ERROR_NOT_ALLOWED,
+		                                               "Scanning not allowed while already scanning");
+		return;
 	}
 
 	last_scan = nm_supplicant_interface_get_last_scan_time (priv->sup_iface);
 	if (last_scan && (nm_utils_get_monotonic_timestamp_s () - last_scan) < 10) {
-		error = g_error_new_literal (NM_DEVICE_ERROR,
-		                             NM_DEVICE_ERROR_NOT_ALLOWED,
-		                             "Scanning not allowed immediately following previous scan");
-		goto error;
+		g_dbus_method_invocation_return_error_literal (context,
+		                                               NM_DEVICE_ERROR,
+		                                               NM_DEVICE_ERROR_NOT_ALLOWED,
+		                                               "Scanning not allowed immediately following previous scan");
+		return;
 	}
 
 	/* Ask the manager to authenticate this request for us */
@@ -1315,12 +1092,7 @@ impl_device_request_scan (NMDeviceWifi *self,
 	                       NM_AUTH_PERMISSION_NETWORK_CONTROL,
 	                       TRUE,
 	                       request_scan_cb,
-	                       options ? g_hash_table_ref (options) : NULL);
-	return;
-
-error:
-	dbus_g_method_return_error (context, error);
-	g_error_free (error);
+	                       options ? g_variant_ref (options) : NULL);
 }
 
 static gboolean
@@ -1367,7 +1139,7 @@ scanning_allowed (NMDeviceWifi *self)
 	    || nm_supplicant_interface_get_scanning (priv->sup_iface))
 		return FALSE;
 
-	connection = nm_device_get_connection (NM_DEVICE (self));
+	connection = nm_device_get_applied_connection (NM_DEVICE (self));
 	if (connection) {
 		NMSettingWireless *s_wifi;
 		const char *ip4_method = NULL;
@@ -1481,8 +1253,32 @@ build_hidden_probe_list (NMDeviceWifi *self)
 	return ssids;
 }
 
+static GPtrArray *
+ssids_options_to_ptrarray (GVariant *value)
+{
+	GPtrArray *ssids = NULL;
+	GByteArray *ssid_array;
+	GVariant *v;
+	const guint8 *bytes;
+	gsize len;
+	int num_ssids, i;
+
+	num_ssids = g_variant_n_children (value);
+	if (num_ssids) {
+		ssids = g_ptr_array_new_full (num_ssids, (GDestroyNotify) g_byte_array_unref);
+		for (i = 0; i < num_ssids; i++) {
+			v = g_variant_get_child_value (value, i);
+			bytes = g_variant_get_fixed_array (v, &len, sizeof (guint8));
+			ssid_array = g_byte_array_new ();
+			g_byte_array_append (ssid_array, bytes, len);
+			g_ptr_array_add (ssids, ssid_array);
+		}
+	}
+	return ssids;
+}
+
 static void
-request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options)
+request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	gboolean backoff = FALSE;
@@ -1496,13 +1292,16 @@ request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options)
 	if (check_scanning_allowed (self)) {
 		_LOGD (LOGD_WIFI_SCAN, "scanning requested");
 
-		if (scan_options && g_hash_table_size (scan_options)) {
-			GValue *val = g_hash_table_lookup (scan_options, "ssids");
+		if (scan_options) {
+			GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL);
 
-			if (val && G_VALUE_HOLDS (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR))
-				ssids = g_ptr_array_ref (g_value_get_boxed (val));
-			else
-				_LOGD (LOGD_WIFI_SCAN, "ignoring invalid scan options");
+			if (val) {
+				if (g_variant_is_of_type (val, G_VARIANT_TYPE ("aay")))
+					ssids = ssids_options_to_ptrarray (val);
+				else
+					_LOGD (LOGD_WIFI_SCAN, "ignoring invalid 'ssids' scan option");
+				g_variant_unref (val);
+			}
 		}
 		if (!ssids)
 			ssids = build_hidden_probe_list (self);
@@ -1606,10 +1405,7 @@ cancel_pending_scan (NMDeviceWifi *self)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
-	if (priv->pending_scan_id) {
-		g_source_remove (priv->pending_scan_id);
-		priv->pending_scan_id = 0;
-	}
+	nm_clear_g_source (&priv->pending_scan_id);
 }
 
 static void
@@ -1621,13 +1417,9 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface,
 
 	_LOGD (LOGD_WIFI_SCAN, "scan %s", success ? "successful" : "failed");
 
+	priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
 	schedule_scan (self, success);
 
-	/* Ensure that old APs get removed, which otherwise only
-	 * happens when there are new BSSes.
-	 */
-	schedule_scanlist_cull (self);
-
 	if (priv->requested_scan) {
 		priv->requested_scan = FALSE;
 		nm_device_remove_pending_action (NM_DEVICE (self), "scan", TRUE);
@@ -1639,7 +1431,35 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface,
  *
  */
 
-#define WPAS_REMOVED_TAG "supplicant-removed"
+static gboolean
+ap_list_dump (gpointer user_data)
+{
+	NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	GSList *sorted, *iter;
+
+	priv->ap_dump_id = 0;
+	_LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%u next:%u]",
+	       nm_utils_get_monotonic_timestamp_s (),
+	       priv->last_scan,
+	       priv->scheduled_scan_time);
+	sorted = get_sorted_ap_list (self);
+	for (iter = sorted; iter; iter = iter->next)
+		nm_ap_dump (NM_AP (iter->data), "dump    ", nm_device_get_iface (NM_DEVICE (self)));
+	g_slist_free (sorted);
+	return G_SOURCE_REMOVE;
+}
+
+static void
+schedule_ap_list_dump (NMDeviceWifi *self)
+{
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	if (!nm_logging_enabled (LOGL_DEBUG, LOGD_WIFI_SCAN))
+		return;
+	nm_clear_g_source (&priv->ap_dump_id);
+	priv->ap_dump_id = g_timeout_add_seconds (1, ap_list_dump, self);
+}
 
 static void
 try_fill_ssid_for_hidden_ap (NMAccessPoint *ap)
@@ -1673,213 +1493,77 @@ try_fill_ssid_for_hidden_ap (NMAccessPoint *ap)
 	}
 }
 
-/*
- * merge_scanned_ap
- *
- * If there is already an entry that matches the BSSID and ESSID of the
- * AP to merge, replace that entry with the scanned AP.  Otherwise, add
- * the scanned AP to the list.
- *
- * TODO: possibly need to differentiate entries based on security too; i.e. if
- * there are two scan results with the same BSSID and SSID but different
- * security options?
- *
- */
 static void
-merge_scanned_ap (NMDeviceWifi *self,
-                  NMAccessPoint *merge_ap)
+supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
+                             const char *object_path,
+                             GVariant *properties,
+                             NMDeviceWifi *self)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	NMDeviceState state;
+	NMAccessPoint *ap;
 	NMAccessPoint *found_ap = NULL;
 	const GByteArray *ssid;
-	gboolean strict_match = TRUE;
+
+	g_return_if_fail (self != NULL);
+	g_return_if_fail (properties != NULL);
+	g_return_if_fail (iface != NULL);
+
+	/* Ignore new APs when unavailable, unmanaged, or in AP mode */
+	state = nm_device_get_state (NM_DEVICE (self));
+	if (state <= NM_DEVICE_STATE_UNAVAILABLE)
+		return;
+	if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP)
+		return;
+
+	ap = nm_ap_new_from_properties (object_path, properties);
+	if (!ap) {
+		_LOGD (LOGD_WIFI_SCAN, "invalid AP properties received for %s", object_path);
+		return;
+	}
 
 	/* Let the manager try to fill in the SSID from seen-bssids lists */
-	ssid = nm_ap_get_ssid (merge_ap);
+	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 (merge_ap);
+		try_fill_ssid_for_hidden_ap (ap);
 
-		ssid = nm_ap_get_ssid (merge_ap);
+		ssid = nm_ap_get_ssid (ap);
 		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'",
-			       nm_ap_get_address (merge_ap), nm_utils_escape_ssid (ssid->data, ssid->len));
-			nm_ap_set_broadcast (merge_ap, FALSE);
+			       nm_ap_get_address (ap), nm_utils_escape_ssid (ssid->data, ssid->len));
 		} else {
 			/* Didn't have an entry for this AP in the database */
 			_LOGD (LOGD_WIFI_SCAN, "failed to match hidden AP %s",
-			       nm_ap_get_address (merge_ap));
+			       nm_ap_get_address (ap));
 		}
 	}
 
-	/* If the incoming scan result matches the hidden AP that NM is currently
-	 * connected to but hasn't been seen in the scan list yet, don't use
-	 * strict matching.  Because the capabilities of the fake AP have to be
-	 * constructed from the NMConnection of the activation request, they won't
-	 * always be the same as the capabilities of the real AP from the scan.
-	 */
-	if (priv->current_ap && nm_ap_get_fake (priv->current_ap))
-		strict_match = FALSE;
-
-	found_ap = get_ap_by_supplicant_path (self, nm_ap_get_supplicant_path (merge_ap));
-	if (!found_ap)
-		found_ap = nm_ap_match_in_list (merge_ap, priv->ap_list, strict_match);
+	found_ap = get_ap_by_supplicant_path (self, object_path);
 	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)",
-		            nm_ap_get_address (merge_ap),
-		            merge_ap,
-		            found_ap);
-
-		nm_ap_set_supplicant_path (found_ap, nm_ap_get_supplicant_path (merge_ap));
-		nm_ap_set_flags (found_ap, nm_ap_get_flags (merge_ap));
-		nm_ap_set_wpa_flags (found_ap, nm_ap_get_wpa_flags (merge_ap));
-		nm_ap_set_rsn_flags (found_ap, nm_ap_get_rsn_flags (merge_ap));
-		nm_ap_set_strength (found_ap, nm_ap_get_strength (merge_ap));
-		nm_ap_set_last_seen (found_ap, nm_ap_get_last_seen (merge_ap));
-		nm_ap_set_broadcast (found_ap, nm_ap_get_broadcast (merge_ap));
-		nm_ap_set_freq (found_ap, nm_ap_get_freq (merge_ap));
-		nm_ap_set_max_bitrate (found_ap, nm_ap_get_max_bitrate (merge_ap));
-
-		/* If the AP is noticed in a scan, it's automatically no longer
-		 * fake, since it clearly exists somewhere.
-		 */
-		nm_ap_set_fake (found_ap, FALSE);
-		g_object_set_data (G_OBJECT (found_ap), WPAS_REMOVED_TAG, NULL);
+		nm_ap_dump (ap, "updated ", nm_device_get_iface (NM_DEVICE (self)));
+		nm_ap_update_from_properties (found_ap, object_path, properties);
 	} else {
-		/* 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)",
-		       nm_ap_get_address (merge_ap), merge_ap);
-
-		g_object_ref (merge_ap);
-		priv->ap_list = g_slist_prepend (priv->ap_list, merge_ap);
-		nm_ap_export_to_dbus (merge_ap);
-		emit_ap_added_removed (self, ACCESS_POINT_ADDED, merge_ap, TRUE);
+		nm_ap_dump (ap, "added   ", nm_device_get_iface (NM_DEVICE (self)));
+		ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE);
 	}
-}
 
-static gboolean
-cull_scan_list (NMDeviceWifi *self)
-{
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	gint32 now = nm_utils_get_monotonic_timestamp_s ();
-	GSList *outdated_list = NULL;
-	GSList *elt;
-	guint32 removed = 0, total = 0;
-
-	priv->scanlist_cull_id = 0;
-
-	_LOGD (LOGD_WIFI_SCAN, "checking scan list for outdated APs");
+	g_object_unref (ap);
 
-	/* Walk the access point list and remove any access points older than
-	 * three times the inactive scan interval.
+	/* Update the current AP if the supplicant notified a current BSS change
+	 * before it sent the current BSS's scan result.
 	 */
-	for (elt = priv->ap_list; elt; elt = g_slist_next (elt), total++) {
-		NMAccessPoint *ap = elt->data;
-		const guint prune_interval_s = SCAN_INTERVAL_MAX * 3;
-		gint32 last_seen;
-
-		/* Don't cull the associated AP or manually created APs */
-		if (ap == priv->current_ap)
-			continue;
-		g_assert (!nm_ap_get_fake (ap)); /* only the current_ap can be fake */
-
-		/* Don't cull APs still known to the supplicant.  Since the supplicant
-		 * doesn't yet emit property updates for "last seen" we have to rely
-		 * on changing signal strength for updating "last seen".  But if the
-		 * AP's strength doesn't change we won't get any updates for the AP,
-		 * and we'll end up here even if the AP was still found by the
-		 * supplicant in the last scan.
-		 */
-		if (   nm_ap_get_supplicant_path (ap)
-		    && g_object_get_data (G_OBJECT (ap), WPAS_REMOVED_TAG) == NULL)
-			continue;
-
-		last_seen = nm_ap_get_last_seen (ap);
-		if (!last_seen || last_seen + prune_interval_s < now)
-			outdated_list = g_slist_prepend (outdated_list, ap);
-	}
-
-	/* Remove outdated APs */
-	for (elt = outdated_list; elt; elt = g_slist_next (elt)) {
-		NMAccessPoint *outdated_ap = NM_AP (elt->data);
-		const GByteArray *ssid;
-
-		ssid = nm_ap_get_ssid (outdated_ap);
-		_LOGD (LOGD_WIFI_SCAN,
-		       "   removing %s (%s%s%s)",
-		       str_if_set (nm_ap_get_address (outdated_ap), "(none)"),
-		       ssid ? "'" : "",
-		       ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
-		       ssid ? "'" : "");
-
-		remove_access_point (self, outdated_ap);
-		removed++;
-	}
-	g_slist_free (outdated_list);
-
-	_LOGD (LOGD_WIFI_SCAN, "removed %d APs (of %d)",
-	       removed, total);
-
-	ap_list_dump (self);
-
-	if(removed > 0)
-	    nm_device_recheck_available_connections (NM_DEVICE (self));
-
-	return FALSE;
-}
+	if (g_strcmp0 (nm_supplicant_interface_get_current_bss (iface), object_path) == 0)
+		supplicant_iface_notify_current_bss (priv->sup_iface, NULL, self);
 
-static void
-schedule_scanlist_cull (NMDeviceWifi *self)
-{
-	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-
-	/* Cull the scan list after the last request for it has come in */
-	if (priv->scanlist_cull_id)
-		g_source_remove (priv->scanlist_cull_id);
-	priv->scanlist_cull_id = g_timeout_add_seconds (4, (GSourceFunc) cull_scan_list, self);
-}
-
-static void
-supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
-                             const char *object_path,
-                             GVariant *properties,
-                             NMDeviceWifi *self)
-{
-	NMDeviceState state;
-	NMAccessPoint *ap;
-
-	g_return_if_fail (self != NULL);
-	g_return_if_fail (properties != NULL);
-	g_return_if_fail (iface != NULL);
-
-	/* Ignore new APs when unavailable, unmanaged, or in AP mode */
-	state = nm_device_get_state (NM_DEVICE (self));
-	if (state <= NM_DEVICE_STATE_UNAVAILABLE)
-		return;
-	if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP)
-		return;
-
-	ap = nm_ap_new_from_properties (object_path, properties);
-	if (ap) {
-		nm_ap_dump (ap, "New AP: ");
-
-		/* Add the AP to the device's AP list */
-		merge_scanned_ap (self, ap);
-		g_object_unref (ap);
-	} else
-		_LOGD (LOGD_WIFI_SCAN, "invalid AP properties received for %s", object_path);
-
-	/* Remove outdated access points */
-	schedule_scanlist_cull (self);
+	schedule_ap_list_dump (self);
 }
 
 static void
 supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
                                  const char *object_path,
-                                 GHashTable *properties,
+                                 GVariant *properties,
                                  NMDeviceWifi *self)
 {
 	NMDeviceState state;
@@ -1889,18 +1573,17 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
 	g_return_if_fail (object_path != NULL);
 	g_return_if_fail (properties != NULL);
 
-	/* Ignore new APs when unavailable or unamnaged */
+	/* Ignore new APs when unavailable or unmanaged */
 	state = nm_device_get_state (NM_DEVICE (self));
 	if (state <= NM_DEVICE_STATE_UNAVAILABLE)
 		return;
 
-	/* Update the AP's last-seen property */
 	ap = get_ap_by_supplicant_path (self, object_path);
-	if (ap)
-		nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ());
-
-	/* Remove outdated access points */
-	schedule_scanlist_cull (self);
+	if (ap) {
+		nm_ap_dump (ap, "updated ", nm_device_get_iface (NM_DEVICE (self)));
+		nm_ap_update_from_properties (ap, object_path, properties);
+		schedule_ap_list_dump (self);
+	}
 }
 
 static void
@@ -1908,28 +1591,28 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
                                  const char *object_path,
                                  NMDeviceWifi *self)
 {
+	NMDeviceWifiPrivate *priv;
 	NMAccessPoint *ap;
 
 	g_return_if_fail (self != NULL);
 	g_return_if_fail (object_path != NULL);
 
+	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	ap = get_ap_by_supplicant_path (self, object_path);
 	if (ap) {
-		gint32 now = nm_utils_get_monotonic_timestamp_s ();
-		gint32 last_seen = nm_ap_get_last_seen (ap);
-
-		/* We don't know when the supplicant last saw the AP's beacons,
-		 * it could be two minutes or it could be 2 seconds.  Because the
-		 * supplicant doesn't send property change notifications if the
-		 * AP's other properties don't change, our last-seen time may be
-		 * much older the supplicant's, and the AP would be immediately
-		 * removed from the list on the next cleanup.  So update the
-		 * last-seen time to ensure the AP sticks around for at least
-		 * one more periodic scan.
-		 */
-		nm_ap_set_last_seen (ap, MAX (last_seen, now - SCAN_INTERVAL_MAX));
-		g_object_set_data (G_OBJECT (ap), WPAS_REMOVED_TAG, GUINT_TO_POINTER (TRUE));
-}
+		if (ap == priv->current_ap) {
+			/* The current AP cannot be removed (to prevent NM indicating that
+			 * it is connected, but to nothing), but it must be removed later
+			 * when the current AP is changed or cleared.  Set 'fake' to
+			 * indicate that this AP is now unknown to the supplicant.
+			 */
+			nm_ap_set_fake (ap, TRUE);
+		} else {
+			nm_ap_dump (ap, "removed ", nm_device_get_iface (NM_DEVICE (self)));
+			ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE);
+			schedule_ap_list_dump (self);
+		}
+	}
 }
 
 static void
@@ -1937,15 +1620,8 @@ remove_supplicant_timeouts (NMDeviceWifi *self)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
-	if (priv->sup_timeout_id) {
-		g_source_remove (priv->sup_timeout_id);
-		priv->sup_timeout_id = 0;
-	}
-
-	if (priv->link_timeout_id) {
-		g_source_remove (priv->link_timeout_id);
-		priv->link_timeout_id = 0;
-	}
+	nm_clear_g_source (&priv->sup_timeout_id);
+	nm_clear_g_source (&priv->link_timeout_id);
 }
 
 static void
@@ -1970,17 +1646,19 @@ cleanup_supplicant_failures (NMDeviceWifi *self)
 
 static void
 wifi_secrets_cb (NMActRequest *req,
-                 guint32 call_id,
-                 NMConnection *connection,
+                 NMActRequestGetSecretsCallId call_id,
+                 NMSettingsConnection *connection,
                  GError *error,
                  gpointer user_data)
 {
 	NMDevice *device = NM_DEVICE (user_data);
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
 
-	g_return_if_fail (req == nm_device_get_act_request (device));
+	if (req != nm_device_get_act_request (device))
+		return;
+
 	g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
-	g_return_if_fail (nm_act_request_get_connection (req) == connection);
+	g_return_if_fail (nm_act_request_get_settings_connection (req) == connection);
 
 	if (error) {
 		_LOGW (LOGD_WIFI, "%s", error->message);
@@ -2015,23 +1693,7 @@ link_timeout_cb (gpointer user_data)
 	if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED)
 		return FALSE;
 
-	/* 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.
-	 */
-	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);
-	}
+	set_current_ap (self, NULL, TRUE);
 
 	nm_device_state_changed (device,
 	                         NM_DEVICE_STATE_FAILED,
@@ -2052,7 +1714,7 @@ need_new_8021x_secrets (NMDeviceWifi *self,
 
 	g_assert (setting_name != NULL);
 
-	connection = nm_device_get_connection (NM_DEVICE (self));
+	connection = nm_device_get_applied_connection (NM_DEVICE (self));
 	g_return_val_if_fail (connection != NULL, FALSE);
 
 	/* 802.1x stuff only happens in the supplicant's ASSOCIATED state when it's
@@ -2105,7 +1767,7 @@ need_new_wpa_psk (NMDeviceWifi *self,
 
 	g_assert (setting_name != NULL);
 
-	connection = nm_device_get_connection (NM_DEVICE (self));
+	connection = nm_device_get_applied_connection (NM_DEVICE (self));
 	g_return_val_if_fail (connection != NULL, FALSE);
 
 	/* A bad PSK will cause the supplicant to disconnect during the 4-way handshake */
@@ -2133,7 +1795,6 @@ handle_8021x_or_psk_auth_fail (NMDeviceWifi *self,
 {
 	NMDevice *device = NM_DEVICE (self);
 	NMActRequest *req;
-	NMConnection *connection;
 	const char *setting_name = NULL;
 	gboolean handled = FALSE;
 
@@ -2142,13 +1803,10 @@ handle_8021x_or_psk_auth_fail (NMDeviceWifi *self,
 	req = nm_device_get_act_request (NM_DEVICE (self));
 	g_return_val_if_fail (req != NULL, FALSE);
 
-	connection = nm_act_request_get_connection (req);
-	g_assert (connection);
-
 	if (   need_new_8021x_secrets (self, old_state, &setting_name)
 	    || need_new_wpa_psk (self, old_state, &setting_name)) {
 
-		nm_connection_clear_secrets (connection);
+		nm_act_request_clear_secrets (req);
 
 		_LOGI (LOGD_DEVICE | LOGD_WIFI,
 		       "Activation: (wifi) disconnected during association, asking for new key");
@@ -2236,7 +1894,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
 			NMSettingWireless *s_wifi;
 			GBytes *ssid;
 
-			connection = nm_device_get_connection (NM_DEVICE (self));
+			connection = nm_device_get_applied_connection (NM_DEVICE (self));
 			g_return_if_fail (connection);
 
 			s_wifi = nm_connection_get_setting_wireless (connection);
@@ -2253,7 +1911,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
 			                                    g_bytes_get_size (ssid)) : "(none)");
 			nm_device_activate_schedule_stage3_ip_config_start (device);
 		} else if (devstate == NM_DEVICE_STATE_ACTIVATED)
-			periodic_update (self, NULL);
+			periodic_update (self);
 		break;
 	case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED:
 		if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
@@ -2359,7 +2017,53 @@ supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface,
 	/* Run a quick update of current AP when coming out of a scan */
 	state = nm_device_get_state (NM_DEVICE (self));
 	if (!scanning && state == NM_DEVICE_STATE_ACTIVATED)
-		periodic_update (self, NULL);
+		periodic_update (self);
+}
+
+static void
+supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
+                                     GParamSpec *pspec,
+                                     NMDeviceWifi *self)
+{
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	const char *current_bss;
+	NMAccessPoint *new_ap = NULL;
+
+	current_bss = nm_supplicant_interface_get_current_bss (iface);
+	if (current_bss)
+		new_ap = get_ap_by_supplicant_path (self, current_bss);
+
+	if (new_ap != priv->current_ap) {
+		const char *new_bssid = NULL;
+		const GByteArray *new_ssid = NULL;
+		const char *old_bssid = NULL;
+		const GByteArray *old_ssid = NULL;
+
+		/* Don't ever replace a "fake" current AP if we don't know about the
+		 * supplicant's current BSS yet.  It'll get replaced when we receive
+		 * the current BSS's scan result.
+		 */
+		if (new_ap == NULL && nm_ap_get_fake (priv->current_ap))
+			return;
+
+		if (new_ap) {
+			new_bssid = nm_ap_get_address (new_ap);
+			new_ssid = nm_ap_get_ssid (new_ap);
+		}
+
+		if (priv->current_ap) {
+			old_bssid = nm_ap_get_address (priv->current_ap);
+			old_ssid = nm_ap_get_ssid (priv->current_ap);
+		}
+
+		_LOGD (LOGD_WIFI, "roamed from BSSID %s (%s) to %s (%s)",
+		       old_bssid ? old_bssid : "(none)",
+		       old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)",
+		       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);
+	}
 }
 
 static NMActStageReturn
@@ -2369,7 +2073,7 @@ handle_auth_or_fail (NMDeviceWifi *self,
 {
 	const char *setting_name;
 	guint32 tries;
-	NMConnection *connection;
+	NMConnection *applied_connection;
 	NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
 
 	g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE);
@@ -2379,17 +2083,16 @@ handle_auth_or_fail (NMDeviceWifi *self,
 		g_assert (req);
 	}
 
-	connection = nm_act_request_get_connection (req);
-	g_assert (connection);
+	applied_connection = nm_act_request_get_applied_connection (req);
 
-	tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES));
+	tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES));
 	if (tries > 3)
 		return NM_ACT_STAGE_RETURN_FAILURE;
 
 	nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
 
-	nm_connection_clear_secrets (connection);
-	setting_name = nm_connection_need_secrets (connection, NULL);
+	nm_act_request_clear_secrets (req);
+	setting_name = nm_connection_need_secrets (applied_connection, NULL);
 	if (setting_name) {
 		NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION;
 
@@ -2397,7 +2100,7 @@ handle_auth_or_fail (NMDeviceWifi *self,
 			flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW;
 		nm_act_request_get_secrets (req, setting_name, flags, NULL, wifi_secrets_cb, self);
 
-		g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries));
+		g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries));
 		ret = NM_ACT_STAGE_RETURN_POSTPONE;
 	} else
 		_LOGW (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets.");
@@ -2434,7 +2137,7 @@ supplicant_connection_timeout_cb (gpointer user_data)
 	req = nm_device_get_act_request (device);
 	g_assert (req);
 
-	connection = nm_act_request_get_connection (req);
+	connection = nm_act_request_get_applied_connection (req);
 	g_assert (connection);
 
 	if (   priv->mode == NM_802_11_MODE_ADHOC
@@ -2468,7 +2171,7 @@ supplicant_connection_timeout_cb (gpointer user_data)
 		 * dialogs, just retry or fail, and if we never connect the user can
 		 * fix the password somewhere else.
 		 */
-		if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), &timestamp))
+		if (nm_settings_connection_get_timestamp (nm_act_request_get_settings_connection (req), &timestamp))
 			new_secrets = !timestamp;
 
 		if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE)
@@ -2491,12 +2194,16 @@ supplicant_connection_timeout_cb (gpointer user_data)
 static NMSupplicantConfig *
 build_supplicant_config (NMDeviceWifi *self,
                          NMConnection *connection,
-                         guint32 fixed_freq)
+                         guint32 fixed_freq,
+                         GError **error)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (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 (self != NULL, NULL);
 
@@ -2504,19 +2211,29 @@ build_supplicant_config (NMDeviceWifi *self,
 	g_return_val_if_fail (s_wireless != NULL, NULL);
 
 	config = nm_supplicant_config_new ();
-	if (!config)
-		return NULL;
 
 	/* Warn if AP mode may not be supported */
 	if (   g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0
-	    && nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_UNKNOWN) {
+	    && nm_supplicant_interface_get_ap_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_UNKNOWN) {
 		_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)) {
-		_LOGE (LOGD_WIFI, "Couldn't add 802-11-wireless setting to supplicant config.");
+	                                                fixed_freq,
+	                                                mac_randomization_support,
+	                                                mac_randomization_fallback,
+	                                                error)) {
+		g_prefix_error (error, "802-11-wireless: ");
 		goto error;
 	}
 
@@ -2533,13 +2250,14 @@ build_supplicant_config (NMDeviceWifi *self,
 		                                                         s_wireless_sec,
 		                                                         s_8021x,
 		                                                         con_uuid,
-		                                                         mtu)) {
-			_LOGE (LOGD_WIFI, "Couldn't add 802-11-wireless-security setting to supplicant config.");
+		                                                         mtu,
+		                                                         error)) {
+			g_prefix_error (error, "802-11-wireless-security: ");
 			goto error;
 		}
 	} else {
-		if (!nm_supplicant_config_add_no_security (config)) {
-			_LOGE (LOGD_WIFI, "Couldn't add unsecured option to supplicant config.");
+		if (!nm_supplicant_config_add_no_security (config, error)) {
+			g_prefix_error (error, "unsecured-option: ");
 			goto error;
 		}
 	}
@@ -2564,7 +2282,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	NMConnection *connection;
 	NMSettingWireless *s_wireless;
 	const char *cloned_mac;
-	GSList *iter;
 	const char *mode;
 	const char *ap_path;
 
@@ -2575,7 +2292,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	req = nm_device_get_act_request (NM_DEVICE (self));
 	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
-	connection = nm_act_request_get_connection (req);
+	connection = nm_act_request_get_applied_connection (req);
 	g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
@@ -2611,25 +2328,17 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 
 	/* AP mode never uses a specific object or existing scanned AP */
 	if (priv->mode != NM_802_11_MODE_AP) {
-
 		ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req));
 		ap = ap_path ? get_ap_by_path (self, ap_path) : NULL;
 		if (ap)
 			goto done;
 
-		/* Find a compatible AP in the scan list */
-		for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
-			NMAccessPoint *candidate = NM_AP (iter->data);
-
-			if (nm_ap_check_compatible (candidate, connection)) {
-				ap = candidate;
-				break;
-			}
-		}
+		ap = find_first_compatible_ap (self, connection, FALSE);
 	}
 
 	if (ap) {
-		nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap));
+		nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
+		                                          nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)));
 		goto done;
 	}
 
@@ -2642,18 +2351,15 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 	ap = nm_ap_new_fake_from_connection (connection);
 	g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
-	if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA)
-		nm_ap_set_broadcast (ap, FALSE);
-	else if (nm_ap_is_hotspot (ap))
+	if (nm_ap_is_hotspot (ap))
 		nm_ap_set_address (ap, nm_device_get_hw_address (device));
 
-	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);
-	emit_ap_added_removed (self, ACCESS_POINT_ADDED, ap, TRUE);
+	ap_add_remove (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));
+	set_current_ap (self, ap, FALSE);
+	nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
+	                                          nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)));
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 
 done:
@@ -2699,6 +2405,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	NMConnection *connection;
 	const char *setting_name;
 	NMSettingWireless *s_wireless;
+	GError *error = NULL;
 
 	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
 
@@ -2713,7 +2420,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 		goto out;
 	}
 
-	connection = nm_act_request_get_connection (req);
+	connection = nm_act_request_get_applied_connection (req);
 	g_assert (connection);
 
 	s_wireless = nm_connection_get_setting_wireless (connection);
@@ -2752,11 +2459,19 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap))
 		ensure_hotspot_frequency (self, s_wireless, ap);
 
+	if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) {
+		nm_platform_wifi_set_powersave (NM_PLATFORM_GET,
+		                                nm_device_get_ifindex (device),
+		                                nm_setting_wireless_get_powersave (s_wireless));
+	}
+
 	/* Build up the supplicant configuration */
-	config = build_supplicant_config (self, connection, nm_ap_get_freq (ap));
+	config = build_supplicant_config (self, connection, nm_ap_get_freq (ap), &error);
 	if (config == NULL) {
 		_LOGE (LOGD_DEVICE | LOGD_WIFI,
-		       "Activation: (wifi) couldn't build wireless configuration.");
+		       "Activation: (wifi) couldn't build wireless configuration: %s",
+		       error ? error->message : "<BUG>");
+		g_clear_error (&error);
 		*reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED;
 		goto out;
 	}
@@ -2767,9 +2482,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 	                  G_CALLBACK (supplicant_iface_connection_error_cb),
 	                  self);
 
-	if (!nm_supplicant_interface_set_config (priv->sup_iface, config)) {
+	if (!nm_supplicant_interface_set_config (priv->sup_iface, config, &error)) {
 		_LOGE (LOGD_DEVICE | LOGD_WIFI,
-		       "Activation: (wifi) couldn't send wireless configuration to the supplicant.");
+		       "Activation: (wifi) couldn't send wireless configuration to the supplicant: %s",
+		       error ? error->message : "<BUG>");
+		g_clear_error (&error);
 		*reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED;
 		goto out;
 	}
@@ -2805,7 +2522,7 @@ act_stage3_ip4_config_start (NMDevice *device,
 	NMSettingIPConfig *s_ip4;
 	const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
 
-	connection = nm_device_get_connection (device);
+	connection = nm_device_get_applied_connection (device);
 	g_assert (connection);
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
 	if (s_ip4)
@@ -2827,7 +2544,7 @@ act_stage3_ip6_config_start (NMDevice *device,
 	NMSettingIPConfig *s_ip6;
 	const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
 
-	connection = nm_device_get_connection (device);
+	connection = nm_device_get_applied_connection (device);
 	g_assert (connection);
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
 	if (s_ip6)
@@ -2848,7 +2565,7 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config)
 	NMSettingWireless *s_wifi;
 	guint32 mtu;
 
-	connection = nm_device_get_connection (device);
+	connection = nm_device_get_applied_connection (device);
 	g_assert (connection);
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
@@ -2935,7 +2652,7 @@ act_stage4_ip4_config_timeout (NMDevice *device, NMDeviceStateReason *reason)
 	gboolean may_fail = FALSE, chain_up = FALSE;
 	NMActStageReturn ret;
 
-	connection = nm_device_get_connection (device);
+	connection = nm_device_get_applied_connection (device);
 	g_assert (connection);
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -2956,7 +2673,7 @@ act_stage4_ip6_config_timeout (NMDevice *device, NMDeviceStateReason *reason)
 	gboolean may_fail = FALSE, chain_up = FALSE;
 	NMActStageReturn ret;
 
-	connection = nm_device_get_connection (device);
+	connection = nm_device_get_applied_connection (device);
 	g_assert (connection);
 
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
@@ -2975,78 +2692,53 @@ activation_success_handler (NMDevice *device)
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 	int ifindex = nm_device_get_ifindex (device);
-	NMAccessPoint *ap;
-	guint8 bssid[ETH_ALEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
-	NMAccessPoint *tmp_ap = NULL;
 	NMActRequest *req;
-	NMConnection *connection;
+	NMConnection *applied_connection;
 
 	req = nm_device_get_act_request (device);
 	g_assert (req);
 
-	connection = nm_act_request_get_connection (req);
-	g_assert (connection);
+	applied_connection = nm_act_request_get_applied_connection (req);
 
 	/* Clear any critical protocol notification in the wifi stack */
 	nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE);
 
 	/* Clear wireless secrets tries on success */
-	g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL);
-
-	ap = priv->current_ap;
-
-	/* If the AP isn't fake, it was found in the scan list and all its
-	 * details are known.
-	 */
-	if (!ap || !nm_ap_get_fake (ap)){
-		ap = NULL;
-		goto done;
-	}
+	g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, NULL);
 
-	/* If the activate AP was fake, it probably won't have a BSSID at all.
-	 * But if activation was successful, the card will know the BSSID.  Grab
-	 * the BSSID off the card and fill in the BSSID of the activation AP.
+	/* There should always be a current AP, either a fake one because we haven't
+	 * seen a scan result for the activated AP yet, or a real one from the
+	 * supplicant's scan list.
 	 */
-	nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid);
-	if (!nm_ap_get_address (ap)) {
-		char *bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN);
-		nm_ap_set_address (ap, bssid_str);
-		g_free (bssid_str);
-	}
-	if (!nm_ap_get_freq (ap))
-		nm_ap_set_freq (ap, nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex));
-	if (!nm_ap_get_max_bitrate (ap))
-		nm_ap_set_max_bitrate (ap, nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex));
-
-	tmp_ap = find_active_ap (self, ap, TRUE);
-	if (tmp_ap) {
-		const GByteArray *ssid = nm_ap_get_ssid (tmp_ap);
-
-		/* Found a better match in the scan list than the fake AP.  Use it
-		 * instead.
-		 */
-
-		/* If the better match was a hidden AP, update its SSID */
-		if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) {
-			ssid = nm_ap_get_ssid (ap);
-			nm_ap_set_ssid (tmp_ap, ssid->data, ssid->len);
+	g_warn_if_fail (priv->current_ap);
+	if (priv->current_ap) {
+		if (nm_ap_get_fake (priv->current_ap)) {
+			/* If the activation AP hasn't been seen by the supplicant in a scan
+			 * yet, it will be "fake".  This usually happens for Ad-Hoc and
+			 * AP-mode connections.  Fill in the details from the device itself
+			 * until the supplicant sends the scan result.
+			 */
+			if (!nm_ap_get_address (priv->current_ap)) {
+				guint8 bssid[ETH_ALEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+				gs_free char *bssid_str = NULL;
+
+				if (   nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid)
+				    && nm_ethernet_address_is_valid (bssid, ETH_ALEN)) {
+					bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN);
+					nm_ap_set_address (priv->current_ap, bssid_str);
+				}
+			}
+			if (!nm_ap_get_freq (priv->current_ap))
+				nm_ap_set_freq (priv->current_ap, nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex));
+			if (!nm_ap_get_max_bitrate (priv->current_ap))
+				nm_ap_set_max_bitrate (priv->current_ap, nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex));
 		}
 
 		nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
-		                                          nm_ap_get_dbus_path (tmp_ap));
+		                                          nm_exported_object_get_path (NM_EXPORTED_OBJECT (priv->current_ap)));
 	}
 
-done:
-	periodic_update (self, ap);
-
-	/* ap might be already unrefed, because it was a fake_ap. But we don't touch it... */
-	if (tmp_ap && ap == priv->current_ap) {
-		/* Strange, we would expect periodic_update() to find a better AP
-		 * 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);
-	}
+	periodic_update (self);
 
 	update_seen_bssids_cache (self, priv->current_ap);
 
@@ -3057,13 +2749,13 @@ done:
 static void
 activation_failure_handler (NMDevice *device)
 {
-	NMConnection *connection;
+	NMConnection *applied_connection;
 
-	connection = nm_device_get_connection (device);
-	g_assert (connection);
+	applied_connection = nm_device_get_applied_connection (device);
+	g_assert (applied_connection);
 
 	/* Clear wireless secrets tries on failure */
-	g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL);
+	g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, NULL);
 
 	/* Clear any critical protocol notification in the wifi stack */
 	nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, nm_device_get_ifindex (device), FALSE);
@@ -3086,10 +2778,7 @@ device_state_changed (NMDevice *device,
 		if (priv->sup_iface)
 			supplicant_interface_release (self);
 
-		if (priv->periodic_source_id) {
-			g_source_remove (priv->periodic_source_id);
-			priv->periodic_source_id = 0;
-		}
+		nm_clear_g_source (&priv->periodic_source_id);
 
 		cleanup_association_attempt (self, TRUE);
 		cleanup_supplicant_failures (self);
@@ -3196,22 +2885,25 @@ set_enabled (NMDevice *device, gboolean enabled)
 /********************************************************************/
 
 NMDevice *
-nm_device_wifi_new (NMPlatformLink *platform_device)
+nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities)
 {
-	g_return_val_if_fail (platform_device != NULL, NULL);
-
-	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIFI,
-	                                  NM_DEVICE_PLATFORM_DEVICE, platform_device,
-	                                  NM_DEVICE_TYPE_DESC, "802.11 WiFi",
-	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI,
-	                                  NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN,
-	                                  NULL);
+	return g_object_new (NM_TYPE_DEVICE_WIFI,
+	                     NM_DEVICE_IFACE, iface,
+	                     NM_DEVICE_TYPE_DESC, "802.11 WiFi",
+	                     NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI,
+	                     NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI,
+	                     NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN,
+	                     NM_DEVICE_WIFI_CAPABILITIES, (guint) capabilities,
+	                     NULL);
 }
 
 static void
 nm_device_wifi_init (NMDeviceWifi *self)
 {
-	NM_DEVICE_WIFI_GET_PRIVATE (self)->mode = NM_802_11_MODE_INFRA;
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	priv->mode = NM_802_11_MODE_INFRA;
+	priv->aps = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
 static void
@@ -3220,17 +2912,7 @@ dispose (GObject *object)
 	NMDeviceWifi *self = NM_DEVICE_WIFI (object);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	if (priv->periodic_source_id) {
-		g_source_remove (priv->periodic_source_id);
-		priv->periodic_source_id = 0;
-	}
+	nm_clear_g_source (&priv->periodic_source_id);
 
 	cleanup_association_attempt (self, TRUE);
 	supplicant_interface_release (self);
@@ -3246,6 +2928,13 @@ dispose (GObject *object)
 static void
 finalize (GObject *object)
 {
+	NMDeviceWifi *self = NM_DEVICE_WIFI (object);
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	nm_assert (g_hash_table_size (priv->aps) == 0);
+
+	g_hash_table_unref (priv->aps);
+
 	G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object);
 }
 
@@ -3255,8 +2944,9 @@ get_property (GObject *object, guint prop_id,
 {
 	NMDeviceWifi *device = NM_DEVICE_WIFI (object);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
+	GHashTableIter iter;
+	const char *dbus_path;
 	GPtrArray *array;
-	GSList *iter;
 
 	switch (prop_id) {
 	case PROP_PERM_HW_ADDRESS:
@@ -3272,16 +2962,15 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_uint (value, priv->capabilities);
 		break;
 	case PROP_ACCESS_POINTS:
-		array = g_ptr_array_sized_new (4);
-		for (iter = priv->ap_list; iter; iter = g_slist_next (iter))
-			g_ptr_array_add (array, g_strdup (nm_ap_get_dbus_path (NM_AP (iter->data))));
-		g_value_take_boxed (value, array);
+		array = g_ptr_array_sized_new (g_hash_table_size (priv->aps) + 1);
+		g_hash_table_iter_init (&iter, priv->aps);
+		while (g_hash_table_iter_next (&iter, (gpointer) &dbus_path, NULL))
+			g_ptr_array_add (array, g_strdup (dbus_path));
+		g_ptr_array_add (array, NULL);
+		g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE));
 		break;
 	case PROP_ACTIVE_ACCESS_POINT:
-		if (priv->current_ap)
-			g_value_set_boxed (value, nm_ap_get_dbus_path (priv->current_ap));
-		else
-			g_value_set_boxed (value, "/");
+		nm_utils_g_value_set_object_path (value, priv->current_ap);
 		break;
 	case PROP_SCANNING:
 		g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->sup_iface));
@@ -3296,7 +2985,14 @@ static void
 set_property (GObject *object, guint prop_id,
               const GValue *value, GParamSpec *pspec)
 {
+	NMDeviceWifi *device = NM_DEVICE_WIFI (object);
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
+
 	switch (prop_id) {
+	case PROP_CAPABILITIES:
+		/* construct-only */
+		priv->capabilities = g_value_get_uint (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -3312,12 +3008,15 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 
 	g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate));
 
-	object_class->constructor = constructor;
+	NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI)
+
+	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 	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;
@@ -3366,22 +3065,23 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 	g_object_class_install_property
 		(object_class, PROP_ACCESS_POINTS,
 		 g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "",
-		                     DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
+		                     G_TYPE_STRV,
 		                     G_PARAM_READABLE |
 		                     G_PARAM_STATIC_STRINGS));
 
 	g_object_class_install_property
 		(object_class, PROP_ACTIVE_ACCESS_POINT,
-		 g_param_spec_boxed (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "",
-		                     DBUS_TYPE_G_OBJECT_PATH,
-		                     G_PARAM_READABLE |
-		                     G_PARAM_STATIC_STRINGS));
+		 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_READABLE |
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT_ONLY |
 		                    G_PARAM_STATIC_STRINGS));
 
 	g_object_class_install_property
@@ -3399,7 +3099,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 		              G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added),
 		              NULL, NULL, NULL,
 		              G_TYPE_NONE, 1,
-		              G_TYPE_OBJECT);
+		              NM_TYPE_AP);
 
 	signals[ACCESS_POINT_REMOVED] =
 		g_signal_new ("access-point-removed",
@@ -3408,7 +3108,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 		              0,
 		              NULL, NULL, NULL,
 		              G_TYPE_NONE, 1,
-		              G_TYPE_OBJECT);
+		              NM_TYPE_AP);
 
 	signals[SCANNING_ALLOWED] =
 		g_signal_new ("scanning-allowed",
@@ -3418,9 +3118,12 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 		              scanning_allowed_accumulator, NULL, NULL,
 		              G_TYPE_BOOLEAN, 0);
 
-	nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
-	                                        G_TYPE_FROM_CLASS (klass),
-	                                        &dbus_glib_nm_device_wifi_object_info);
+	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
+	                                        NMDBUS_TYPE_DEVICE_WIFI_SKELETON,
+	                                        "GetAccessPoints", impl_device_wifi_get_access_points,
+	                                        "GetAllAccessPoints", impl_device_wifi_get_all_access_points,
+	                                        "RequestScan", impl_device_wifi_request_scan,
+	                                        NULL);
 }
 
 
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
index bcba91da..7e0d06f5 100644
--- a/src/devices/wifi/nm-device-wifi.h
+++ b/src/devices/wifi/nm-device-wifi.h
@@ -22,8 +22,6 @@
 #ifndef __NETWORKMANAGER_DEVICE_WIFI_H__
 #define __NETWORKMANAGER_DEVICE_WIFI_H__
 
-#include <glib-object.h>
-
 #include "nm-device.h"
 #include "nm-wifi-ap.h"
 
@@ -75,7 +73,7 @@ struct _NMDeviceWifiClass
 
 GType nm_device_wifi_get_type (void);
 
-NMDevice *nm_device_wifi_new (NMPlatformLink *platform_device);
+NMDevice * nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities);
 
 G_END_DECLS
 
diff --git a/src/devices/wifi/nm-wifi-ap-utils.c b/src/devices/wifi/nm-wifi-ap-utils.c
index 1a772fb7..d7916aa0 100644
--- a/src/devices/wifi/nm-wifi-ap-utils.c
+++ b/src/devices/wifi/nm-wifi-ap-utils.c
@@ -23,8 +23,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include <glib/gi18n.h>
-
+#include "nm-default.h"
 #include "nm-wifi-ap-utils.h"
 #include "nm-utils.h"
 
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index 72430021..771d6704 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -24,32 +24,29 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "nm-default.h"
 #include "nm-wifi-ap.h"
 #include "nm-wifi-ap-utils.h"
 #include "NetworkManagerUtils.h"
 #include "nm-utils.h"
-#include "nm-logging.h"
-#include "nm-dbus-manager.h"
 #include "nm-core-internal.h"
 
 #include "nm-setting-wireless.h"
-#include "nm-glib-compat.h"
 
-#include "nm-access-point-glue.h"
+#include "nmdbus-access-point.h"
 
 /*
  * Encapsulates Access Point information
  */
 typedef struct
 {
-	char *dbus_path;
 	char *supplicant_path;   /* D-Bus object path of this AP from wpa_supplicant */
 
 	/* Scanned or cached values */
 	GByteArray *	ssid;
 	char *          address;
 	NM80211Mode		mode;
-	gint8			strength;
+	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) */
 
@@ -60,13 +57,12 @@ typedef struct
 	/* 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 */
-	gboolean			broadcast;	/* Whether or not the AP is broadcasting (hidden) */
 	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))
 
-G_DEFINE_TYPE (NMAccessPoint, nm_ap, G_TYPE_OBJECT)
+G_DEFINE_TYPE (NMAccessPoint, nm_ap, NM_TYPE_EXPORTED_OBJECT)
 
 enum {
 	PROP_0,
@@ -83,267 +79,267 @@ enum {
 	LAST_PROP
 };
 
-static void
-nm_ap_init (NMAccessPoint *ap)
+/*****************************************************************/
+
+const char *
+nm_ap_get_supplicant_path (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap);
+	g_return_val_if_fail (NM_IS_AP (ap), NULL);
 
-	priv->dbus_path = NULL;
-	priv->mode = NM_802_11_MODE_INFRA;
-	priv->flags = NM_802_11_AP_FLAGS_NONE;
-	priv->wpa_flags = NM_802_11_AP_SEC_NONE;
-	priv->rsn_flags = NM_802_11_AP_SEC_NONE;
-	priv->broadcast = TRUE;
+	return NM_AP_GET_PRIVATE (ap)->supplicant_path;
 }
 
-static void
-finalize (GObject *object)
+guint32
+nm_ap_get_id (NMAccessPoint *ap)
 {
-	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object);
+	g_return_val_if_fail (NM_IS_AP (ap), 0);
+	g_return_val_if_fail (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (ap)), 0);
 
-	g_free (priv->dbus_path);
-	g_free (priv->supplicant_path);
-	if (priv->ssid)
+	return atoi (strrchr (nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)), '/') + 1);
+}
+
+const GByteArray * nm_ap_get_ssid (const NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), NULL);
+
+	return NM_AP_GET_PRIVATE (ap)->ssid;
+}
+
+void
+nm_ap_set_ssid (NMAccessPoint *ap, const guint8 *ssid, gsize len)
+{
+	NMAccessPointPrivate *priv;
+
+	g_return_if_fail (NM_IS_AP (ap));
+	g_return_if_fail (ssid == NULL || len > 0);
+
+	priv = NM_AP_GET_PRIVATE (ap);
+
+	/* same SSID */
+	if ((ssid && priv->ssid) && (len == priv->ssid->len)) {
+		if (!memcmp (ssid, priv->ssid->data, len))
+			return;
+	}
+
+	if (priv->ssid) {
 		g_byte_array_free (priv->ssid, TRUE);
-	g_free (priv->address);
+		priv->ssid = NULL;
+	}
 
-	G_OBJECT_CLASS (nm_ap_parent_class)->finalize (object);
+	if (ssid) {
+		priv->ssid = g_byte_array_new ();
+		g_byte_array_append (priv->ssid, ssid, len);
+	}
+
+	g_object_notify (G_OBJECT (ap), NM_AP_SSID);
 }
 
 static void
-set_property (GObject *object, guint prop_id,
-		    const GValue *value, GParamSpec *pspec)
+nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags)
 {
-	NMAccessPoint *ap = NM_AP (object);
-	GByteArray *ssid;
+	NMAccessPointPrivate *priv;
 
-	switch (prop_id) {
-	case PROP_FLAGS:
-		nm_ap_set_flags (ap, g_value_get_uint (value));
-		break;
-	case PROP_WPA_FLAGS:
-		nm_ap_set_wpa_flags (ap, g_value_get_uint (value));
-		break;
-	case PROP_RSN_FLAGS:
-		nm_ap_set_rsn_flags (ap, g_value_get_uint (value));
-		break;
-	case PROP_SSID:
-		ssid = g_value_get_boxed (value);
-		if (ssid)
-			nm_ap_set_ssid (ap, ssid->data, ssid->len);
-		else
-			nm_ap_set_ssid (ap, NULL, 0);
-		break;
-	case PROP_FREQUENCY:
-		nm_ap_set_freq (ap, g_value_get_uint (value));
-		break;
-	case PROP_MODE:
-		nm_ap_set_mode (ap, g_value_get_uint (value));
-		break;
-	case PROP_MAX_BITRATE:
-		nm_ap_set_max_bitrate (ap, g_value_get_uint (value));
-		break;
-	case PROP_STRENGTH:
-		nm_ap_set_strength (ap, g_value_get_schar (value));
-		break;
-	case PROP_HW_ADDRESS:
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
+	g_return_if_fail (NM_IS_AP (ap));
+
+	priv = NM_AP_GET_PRIVATE (ap);
+
+	if (priv->flags != flags) {
+		priv->flags = flags;
+		g_object_notify (G_OBJECT (ap), NM_AP_FLAGS);
 	}
 }
 
 static void
-get_property (GObject *object, guint prop_id,
-			  GValue *value, GParamSpec *pspec)
+nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags)
 {
-	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object);
-	GArray * ssid;
-	int len;
-	int i;
+	NMAccessPointPrivate *priv;
 
-	switch (prop_id) {
-	case PROP_FLAGS:
-		g_value_set_uint (value, priv->flags);
-		break;
-	case PROP_WPA_FLAGS:
-		g_value_set_uint (value, priv->wpa_flags);
-		break;
-	case PROP_RSN_FLAGS:
-		g_value_set_uint (value, priv->rsn_flags);
-		break;
-	case PROP_SSID:
-		len = priv->ssid ? priv->ssid->len : 0;
-		ssid = g_array_sized_new (FALSE, TRUE, sizeof (unsigned char), len);
-		for (i = 0; i < len; i++)
-			g_array_append_val (ssid, priv->ssid->data[i]);
-		g_value_set_boxed (value, ssid);
-		g_array_free (ssid, TRUE);
-		break;
-	case PROP_FREQUENCY:
-		g_value_set_uint (value, priv->freq);
-		break;
-	case PROP_HW_ADDRESS:
-		g_value_set_string (value, priv->address);
-		break;
-	case PROP_MODE:
-		g_value_set_uint (value, priv->mode);
-		break;
-	case PROP_MAX_BITRATE:
-		g_value_set_uint (value, priv->max_bitrate);
-		break;
-	case PROP_STRENGTH:
-		g_value_set_schar (value, priv->strength);
-		break;
-	case PROP_LAST_SEEN:
-		g_value_set_int (value,
-		                 priv->last_seen > 0
-		                     ? (gint) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND)
-		                     : -1);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
+	g_return_if_fail (NM_IS_AP (ap));
+
+	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);
 	}
 }
 
 static void
-nm_ap_class_init (NMAccessPointClass *ap_class)
+nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (ap_class);
-	const NM80211ApSecurityFlags all_sec_flags =   NM_802_11_AP_SEC_NONE
-	                                             | NM_802_11_AP_SEC_PAIR_WEP40
-	                                             | NM_802_11_AP_SEC_PAIR_WEP104
-	                                             | NM_802_11_AP_SEC_PAIR_TKIP
-	                                             | NM_802_11_AP_SEC_PAIR_CCMP
-	                                             | NM_802_11_AP_SEC_GROUP_WEP40
-	                                             | NM_802_11_AP_SEC_GROUP_WEP104
-	                                             | NM_802_11_AP_SEC_GROUP_TKIP
-	                                             | NM_802_11_AP_SEC_GROUP_CCMP
-	                                             | NM_802_11_AP_SEC_KEY_MGMT_PSK
-	                                             | NM_802_11_AP_SEC_KEY_MGMT_802_1X;
+	NMAccessPointPrivate *priv;
 
-	g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate));
+	g_return_if_fail (NM_IS_AP (ap));
 
-	/* virtual methods */
-	object_class->set_property = set_property;
-	object_class->get_property = get_property;
-	object_class->finalize = finalize;
+	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);
+	}
+}
 
-	/* 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_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
+const char *
+nm_ap_get_address (const NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), NULL);
 
-	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_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
+	return NM_AP_GET_PRIVATE (ap)->address;
+}
 
-	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_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
+void
+nm_ap_set_address (NMAccessPoint *ap, const char *addr)
+{
+	NMAccessPointPrivate *priv;
 
-	g_object_class_install_property
-		(object_class, PROP_SSID,
-	     g_param_spec_boxed (NM_AP_SSID, "", "",
-	                         DBUS_TYPE_G_UCHAR_ARRAY,
-	                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-	                         G_PARAM_STATIC_STRINGS));
+	g_return_if_fail (NM_IS_AP (ap));
+	g_return_if_fail (addr != NULL);
+	g_return_if_fail (nm_utils_hwaddr_valid (addr, ETH_ALEN));
 
-	g_object_class_install_property
-		(object_class, PROP_FREQUENCY,
-		 g_param_spec_uint (NM_AP_FREQUENCY, "", "",
-		                    0, 10000, 0,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
+	priv = NM_AP_GET_PRIVATE (ap);
 
-	g_object_class_install_property
-		(object_class, PROP_HW_ADDRESS,
-		 g_param_spec_string (NM_AP_HW_ADDRESS, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                      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_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
+	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);
+	}
+}
 
-	g_object_class_install_property
-		(object_class, PROP_MAX_BITRATE,
-		 g_param_spec_uint (NM_AP_MAX_BITRATE, "", "",
-		                    0, G_MAXUINT16, 0,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
+NM80211Mode
+nm_ap_get_mode (NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_MODE_UNKNOWN);
 
-	g_object_class_install_property
-		(object_class, PROP_STRENGTH,
-		 g_param_spec_char (NM_AP_STRENGTH, "", "",
-		                    G_MININT8, G_MAXINT8, 0,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-		                    G_PARAM_STATIC_STRINGS));
+	return NM_AP_GET_PRIVATE (ap)->mode;
+}
 
-	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));
-
-	nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
-	                                        G_TYPE_FROM_CLASS (ap_class),
-	                                        &dbus_glib_nm_access_point_object_info);
+static void
+nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode)
+{
+	NMAccessPointPrivate *priv;
+
+	g_return_if_fail (NM_IS_AP (ap));
+	g_return_if_fail (   mode == NM_802_11_MODE_ADHOC
+	                  || mode == NM_802_11_MODE_INFRA);
+
+	priv = NM_AP_GET_PRIVATE (ap);
+
+	if (priv->mode != mode) {
+		priv->mode = mode;
+		g_object_notify (G_OBJECT (ap), NM_AP_MODE);
+	}
+}
+
+gboolean
+nm_ap_is_hotspot (NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), FALSE);
+
+	return NM_AP_GET_PRIVATE (ap)->hotspot;
+}
+
+gint8
+nm_ap_get_strength (NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), 0);
+
+	return NM_AP_GET_PRIVATE (ap)->strength;
 }
 
 void
-nm_ap_export_to_dbus (NMAccessPoint *ap)
+nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength)
 {
 	NMAccessPointPrivate *priv;
-	static guint32 counter = 0;
 
 	g_return_if_fail (NM_IS_AP (ap));
 
 	priv = NM_AP_GET_PRIVATE (ap);
 
-	if (priv->dbus_path) {
-		nm_log_err (LOGD_CORE, "Tried to export AP %s twice.", priv->dbus_path);
-		return;
+	if (priv->strength != strength) {
+		priv->strength = strength;
+		g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH);
 	}
+}
+
+guint32
+nm_ap_get_freq (NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), 0);
 
-	priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_ACCESS_POINT "/%d", counter++);
-	nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->dbus_path, ap);
+	return NM_AP_GET_PRIVATE (ap)->freq;
 }
 
-/*
- * nm_ap_new
- *
- * Create a new, blank user access point info structure
- *
- */
-static NMAccessPoint *
-nm_ap_new (void)
+void
+nm_ap_set_freq (NMAccessPoint *ap,
+                const guint32 freq)
+{
+	NMAccessPointPrivate *priv;
+
+	g_return_if_fail (NM_IS_AP (ap));
+
+	priv = NM_AP_GET_PRIVATE (ap);
+
+	if (priv->freq != freq) {
+		priv->freq = freq;
+		g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY);
+	}
+}
+
+guint32
+nm_ap_get_max_bitrate (NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), 0);
+	g_return_val_if_fail (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (ap)), 0);
+
+	return NM_AP_GET_PRIVATE (ap)->max_bitrate;
+}
+
+void
+nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate)
+{
+	NMAccessPointPrivate *priv;
+
+	g_return_if_fail (NM_IS_AP (ap));
+
+	priv = NM_AP_GET_PRIVATE (ap);
+
+	if (priv->max_bitrate != bitrate) {
+		priv->max_bitrate = bitrate;
+		g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE);
+	}
+}
+
+gboolean
+nm_ap_get_fake (const NMAccessPoint *ap)
+{
+	g_return_val_if_fail (NM_IS_AP (ap), FALSE);
+
+	return NM_AP_GET_PRIVATE (ap)->fake;
+}
+
+void
+nm_ap_set_fake (NMAccessPoint *ap, gboolean fake)
 {
-	return (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL);
+	g_return_if_fail (NM_IS_AP (ap));
+
+	NM_AP_GET_PRIVATE (ap)->fake = fake;
 }
 
+static void
+nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen)
+{
+	NMAccessPointPrivate *priv;
+
+	g_return_if_fail (NM_IS_AP (ap));
+
+	priv = NM_AP_GET_PRIVATE (ap);
+
+	if (priv->last_seen != last_seen) {
+		priv->last_seen = last_seen;
+		g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN);
+	}
+}
+
+/*****************************************************************/
+
 static NM80211ApSecurityFlags
 security_from_vardict (GVariant *security)
 {
@@ -382,14 +378,14 @@ security_from_vardict (GVariant *security)
 	return flags;
 }
 
-NMAccessPoint *
-nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
+void
+nm_ap_update_from_properties (NMAccessPoint *ap,
+                              const char *supplicant_path,
+                              GVariant *properties)
 {
-	const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-	const char *addr;
+	NMAccessPointPrivate *priv;
+	char *addr;
 	const guint8 *bytes;
-	NMAccessPoint *ap;
 	GVariant *v;
 	gsize len;
 	gboolean b = FALSE;
@@ -397,14 +393,14 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
 	gint16 i16;
 	guint16 u16;
 
-	g_return_val_if_fail (properties != NULL, NULL);
-
-	ap = nm_ap_new ();
+	g_return_if_fail (ap != NULL);
+	g_return_if_fail (properties != NULL);
+	priv = NM_AP_GET_PRIVATE (ap);
 
 	g_object_freeze_notify (G_OBJECT (ap));
 
 	if (g_variant_lookup (properties, "Privacy", "b", &b) && b)
-		nm_ap_set_flags (ap, nm_ap_get_flags (ap) | NM_802_11_AP_FLAGS_PRIVACY);
+		nm_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY);
 
 	if (g_variant_lookup (properties, "Mode", "&s", &s)) {
 		if (!g_strcmp0 (s, "infrastructure"))
@@ -437,11 +433,9 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
 	if (v) {
 		bytes = g_variant_get_fixed_array (v, &len, 1);
 		if (len == ETH_ALEN) {
-			char *a;
-
-			a = nm_utils_hwaddr_ntoa (bytes, len);
-			nm_ap_set_address (ap, a);
-			g_free (a);
+			addr = nm_utils_hwaddr_ntoa (bytes, len);
+			nm_ap_set_address (ap, addr);
+			g_free (addr);
 		}
 		g_variant_unref (v);
 	}
@@ -464,17 +458,38 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
 
 	v = g_variant_lookup_value (properties, "WPA", G_VARIANT_TYPE_VARDICT);
 	if (v) {
-		nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | security_from_vardict (v));
+		nm_ap_set_wpa_flags (ap, priv->wpa_flags | security_from_vardict (v));
 		g_variant_unref (v);
 	}
 
 	v = g_variant_lookup_value (properties, "RSN", G_VARIANT_TYPE_VARDICT);
 	if (v) {
-		nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | security_from_vardict (v));
+		nm_ap_set_rsn_flags (ap, priv->rsn_flags | security_from_vardict (v));
 		g_variant_unref (v);
 	}
 
-	nm_ap_set_supplicant_path (ap, supplicant_path);
+	if (!priv->supplicant_path)
+		priv->supplicant_path = g_strdup (supplicant_path);
+
+	nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ());
+	priv->fake = FALSE;
+
+	g_object_thaw_notify (G_OBJECT (ap));
+}
+
+NMAccessPoint *
+nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
+{
+	const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	NMAccessPoint *ap;
+	const char *addr;
+
+	g_return_val_if_fail (supplicant_path != NULL, NULL);
+	g_return_val_if_fail (properties != NULL, NULL);
+
+	ap = (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL);
+	nm_ap_update_from_properties (ap, supplicant_path, properties);
 
 	/* ignore APs with invalid or missing BSSIDs */
 	addr = nm_ap_get_address (ap);
@@ -485,13 +500,6 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties)
 		return NULL;
 	}
 
-	nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ());
-
-	if (!nm_ap_get_ssid (ap))
-		nm_ap_set_broadcast (ap, FALSE);
-
-	g_object_thaw_notify (G_OBJECT (ap));
-
 	return ap;
 }
 
@@ -517,6 +525,7 @@ has_proto (NMSettingWirelessSecurity *sec, const char *proto)
 static void
 add_pair_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec)
 {
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap);
 	guint32 num = nm_setting_wireless_security_get_num_pairwise (sec);
 	NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE;
 	guint32 i;
@@ -536,14 +545,15 @@ add_pair_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec)
 	}
 
 	if (has_proto (sec, PROTO_WPA))
-		nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags);
+		nm_ap_set_wpa_flags (ap, priv->wpa_flags | flags);
 	if (has_proto (sec, PROTO_RSN))
-		nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags);
+		nm_ap_set_rsn_flags (ap, priv->rsn_flags | flags);
 }
 
 static void
 add_group_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec)
 {
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap);
 	guint32 num = nm_setting_wireless_security_get_num_groups (sec);
 	NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE;
 	guint32 i;
@@ -567,15 +577,16 @@ add_group_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec)
 	}
 
 	if (has_proto (sec, PROTO_WPA))
-		nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags);
+		nm_ap_set_wpa_flags (ap, priv->wpa_flags | flags);
 	if (has_proto (sec, PROTO_RSN))
-		nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags);
+		nm_ap_set_rsn_flags (ap, priv->rsn_flags | flags);
 }
 
 NMAccessPoint *
 nm_ap_new_fake_from_connection (NMConnection *connection)
 {
 	NMAccessPoint *ap;
+	NMAccessPointPrivate *priv;
 	NMSettingWireless *s_wireless;
 	NMSettingWirelessSecurity *s_wireless_sec;
 	GBytes *ssid;
@@ -593,8 +604,9 @@ nm_ap_new_fake_from_connection (NMConnection *connection)
 	g_return_val_if_fail (ssid != NULL, NULL);
 	g_return_val_if_fail (g_bytes_get_size (ssid) > 0, NULL);
 
-	ap = nm_ap_new ();
-	nm_ap_set_fake (ap, TRUE);
+	ap = (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL);
+	priv = NM_AP_GET_PRIVATE (ap);
+	priv->fake = TRUE;
 	nm_ap_set_ssid (ap, g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
 
 	// FIXME: bssid too?
@@ -634,7 +646,7 @@ nm_ap_new_fake_from_connection (NMConnection *connection)
 	key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
 
 	/* Everything below here uses encryption */
-	nm_ap_set_flags (ap, nm_ap_get_flags (ap) | NM_802_11_AP_FLAGS_PRIVACY);
+	nm_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY);
 
 	/* Static & Dynamic WEP */
 	if (!strcmp (key_mgmt, "none") || !strcmp (key_mgmt, "ieee8021x"))
@@ -644,13 +656,11 @@ nm_ap_new_fake_from_connection (NMConnection *connection)
 	eap = !strcmp (key_mgmt, "wpa-eap");
 	if (psk || eap) {
 		if (has_proto (s_wireless_sec, PROTO_WPA)) {
-			flags = nm_ap_get_wpa_flags (ap);
-			flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK;
+			flags = priv->wpa_flags | (eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK);
 			nm_ap_set_wpa_flags (ap, flags);
 		}
 		if (has_proto (s_wireless_sec, PROTO_RSN)) {
-			flags = nm_ap_get_rsn_flags (ap);
-			flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK;
+			flags = priv->rsn_flags | (eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK);
 			nm_ap_set_rsn_flags (ap, flags);
 		}
 
@@ -663,8 +673,7 @@ nm_ap_new_fake_from_connection (NMConnection *connection)
 		 * group=TKIP/CCMP (but not both).
 		 */
 
-		flags = nm_ap_get_wpa_flags (ap);
-		flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK;
+		flags = priv->wpa_flags | NM_802_11_AP_SEC_KEY_MGMT_PSK;
 
 		/* Clear ciphers; pairwise must be unset anyway, and group gets set below */
 		flags &= ~(  NM_802_11_AP_SEC_PAIR_WEP40
@@ -701,394 +710,60 @@ error:
 	return NULL;
 }
 
-void
-nm_ap_dump (NMAccessPoint *ap, const char *prefix)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	nm_log_dbg (LOGD_WIFI_SCAN, "%s'%s' (%p)",
-	            prefix,
-	            priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)",
-	            ap);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    BSSID     %s", str_if_set (priv->address, "(none)"));
-	nm_log_dbg (LOGD_WIFI_SCAN, "    mode      %d", priv->mode);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    flags     0x%X", priv->flags);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    wpa flags 0x%X", priv->wpa_flags);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    rsn flags 0x%X", priv->rsn_flags);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    quality   %d", priv->strength);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    frequency %d", priv->freq);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    max rate  %d", priv->max_bitrate);
-	nm_log_dbg (LOGD_WIFI_SCAN, "    last-seen %d", (int) priv->last_seen);
-}
-
-const char *
-nm_ap_get_dbus_path (NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), NULL);
-
-	return NM_AP_GET_PRIVATE (ap)->dbus_path;
-}
-
-const char *
-nm_ap_get_supplicant_path (NMAccessPoint *ap)
+static char
+mode_to_char (NMAccessPoint *self)
 {
-	g_return_val_if_fail (NM_IS_AP (ap), NULL);
-
-	return NM_AP_GET_PRIVATE (ap)->supplicant_path;
-}
-
-void
-nm_ap_set_supplicant_path (NMAccessPoint *ap, const char *path)
-{
-	g_return_if_fail (NM_IS_AP (ap));
-	g_return_if_fail (path != NULL);
-
-	g_free (NM_AP_GET_PRIVATE (ap)->supplicant_path);
-	NM_AP_GET_PRIVATE (ap)->supplicant_path = g_strdup (path);
-}
-
-/*
- * Get/set functions for ssid
- *
- */
-const GByteArray * nm_ap_get_ssid (const NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), NULL);
-
-	return NM_AP_GET_PRIVATE (ap)->ssid;
-}
-
-void
-nm_ap_set_ssid (NMAccessPoint *ap, const guint8 *ssid, gsize len)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-	g_return_if_fail (ssid == NULL || len > 0);
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	/* same SSID */
-	if ((ssid && priv->ssid) && (len == priv->ssid->len)) {
-		if (!memcmp (ssid, priv->ssid->data, len))
-			return;
-	}
-
-	if (priv->ssid) {
-		g_byte_array_free (priv->ssid, TRUE);
-		priv->ssid = NULL;
-	}
-
-	if (ssid) {
-		priv->ssid = g_byte_array_new ();
-		g_byte_array_append (priv->ssid, ssid, len);
-	}
-
-	g_object_notify (G_OBJECT (ap), NM_AP_SSID);
-}
-
-
-NM80211ApFlags
-nm_ap_get_flags (NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_FLAGS_NONE);
-
-	return NM_AP_GET_PRIVATE (ap)->flags;
-}
-
-
-void
-nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	if (priv->flags != flags) {
-		priv->flags = flags;
-		g_object_notify (G_OBJECT (ap), NM_AP_FLAGS);
-	}
-}
-
-NM80211ApSecurityFlags
-nm_ap_get_wpa_flags (NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE);
-
-	return NM_AP_GET_PRIVATE (ap)->wpa_flags;
-}
-
-
-void
-nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-
-	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);
-	}
-}
-
-NM80211ApSecurityFlags
-nm_ap_get_rsn_flags (NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE);
-
-	return NM_AP_GET_PRIVATE (ap)->rsn_flags;
-}
-
-
-void
-nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-
-	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);
-	}
-}
-
-/*
- * Get/set functions for address
- *
- */
-const char *
-nm_ap_get_address (const NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), NULL);
-
-	return NM_AP_GET_PRIVATE (ap)->address;
-}
-
-void
-nm_ap_set_address (NMAccessPoint *ap, const char *addr)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-	g_return_if_fail (addr != NULL);
-	g_return_if_fail (nm_utils_hwaddr_valid (addr, ETH_ALEN));
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	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);
-	}
-}
-
-
-/*
- * Get/set functions for mode (ie Ad-Hoc, Infrastructure, etc)
- *
- */
-NM80211Mode nm_ap_get_mode (NMAccessPoint *ap)
-{
-	NM80211Mode mode;
-
-	g_return_val_if_fail (NM_IS_AP (ap), -1);
-
-	g_object_get (ap, NM_AP_MODE, &mode, NULL);
-
-	return mode;
-}
-
-void nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-	g_return_if_fail (   mode == NM_802_11_MODE_ADHOC
-	                  || mode == NM_802_11_MODE_INFRA);
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	if (priv->mode != mode) {
-		priv->mode = mode;
-		g_object_notify (G_OBJECT (ap), NM_AP_MODE);
-	}
-}
-
-gboolean
-nm_ap_is_hotspot (NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), FALSE);
-
-	return NM_AP_GET_PRIVATE (ap)->hotspot;
-}
-
-/*
- * Get/set functions for strength
- *
- */
-gint8 nm_ap_get_strength (NMAccessPoint *ap)
-{
-	gint8 strength;
-
-	g_return_val_if_fail (NM_IS_AP (ap), 0);
-
-	g_object_get (ap, NM_AP_STRENGTH, &strength, NULL);
-
-	return strength;
-}
-
-void nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	if (priv->strength != strength) {
-		priv->strength = strength;
-		g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH);
-	}
-}
-
-
-/*
- * Get/set functions for frequency
- *
- */
-guint32
-nm_ap_get_freq (NMAccessPoint *ap)
-{
-	guint32 freq;
-
-	g_return_val_if_fail (NM_IS_AP (ap), 0);
-
-	g_object_get (ap, NM_AP_FREQUENCY, &freq, NULL);
-
-	return freq;
-}
-
-void
-nm_ap_set_freq (NMAccessPoint *ap,
-                const guint32 freq)
-{
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	if (priv->freq != freq) {
-		priv->freq = freq;
-		g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY);
-	}
-}
-
-
-/*
- * Get/set functions for max bitrate (in kbit/s)
- *
- */
-guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap)
-{
-	guint32 rate;
-
-	g_return_val_if_fail (NM_IS_AP (ap), 0);
-
-	g_object_get (ap, NM_AP_MAX_BITRATE, &rate, NULL);
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (self);
 
-	return rate;
+	if (priv->mode == NM_802_11_MODE_ADHOC)
+		return '*';
+	if (priv->hotspot)
+		return '#';
+	if (priv->fake)
+		return '-';
+	return ' ';
 }
 
 void
-nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate)
+nm_ap_dump (NMAccessPoint *self,
+            const char *prefix,
+            const char *ifname)
 {
 	NMAccessPointPrivate *priv;
+	const char *supplicant_id = "-";
+	guint32 chan;
 
-	g_return_if_fail (NM_IS_AP (ap));
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	if (priv->max_bitrate != bitrate) {
-		priv->max_bitrate = bitrate;
-		g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE);
-	}
-}
-
-/*
- * Get/Set functions to indicate that an access point is 'fake', ie whether
- * or not it was created from scan results
- */
-gboolean nm_ap_get_fake (const NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), FALSE);
-
-	return NM_AP_GET_PRIVATE (ap)->fake;
-}
-
-void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake)
-{
-	g_return_if_fail (NM_IS_AP (ap));
-
-	NM_AP_GET_PRIVATE (ap)->fake = fake;
-}
-
-
-/*
- * Get/Set functions to indicate whether an AP broadcasts its SSID.
- */
-gboolean nm_ap_get_broadcast (NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), TRUE);
-
-	return NM_AP_GET_PRIVATE (ap)->broadcast;
-}
-
-
-void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast)
-{
-	g_return_if_fail (NM_IS_AP (ap));
-
-	NM_AP_GET_PRIVATE (ap)->broadcast = broadcast;
-}
-
+	g_return_if_fail (NM_IS_AP (self));
 
-/*
- * Get/Set functions for how long ago the AP was last seen in a scan.
- * APs older than a certain date are dropped from the list.
- *
- */
-gint32
-nm_ap_get_last_seen (const NMAccessPoint *ap)
-{
-	g_return_val_if_fail (NM_IS_AP (ap), 0);
+	priv = NM_AP_GET_PRIVATE (self);
+	chan = nm_utils_wifi_freq_to_channel (priv->freq);
+	if (priv->supplicant_path)
+		supplicant_id = strrchr (priv->supplicant_path, '/');
 
-	return NM_AP_GET_PRIVATE (ap)->last_seen;
+	nm_log_dbg (LOGD_WIFI_SCAN, "%s[%s%c] %-32s[%s%u %3u%% %c W:%04X R:%04X] [%3u] %s%s",
+	            prefix,
+	            str_if_set (priv->address, "(none)"),
+	            mode_to_char (self),
+	            priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)",
+	            chan > 99 ? "" : (chan > 9 ? " " : "  "),
+	            chan,
+	            priv->strength,
+	            priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : ' ',
+	            priv->wpa_flags & 0xFFFF,
+	            priv->rsn_flags & 0xFFFF,
+	            priv->last_seen > 0 ? (nm_utils_get_monotonic_timestamp_s () - priv->last_seen) : -1,
+	            ifname,
+	            supplicant_id);
 }
 
-void
-nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen)
+static guint
+freq_to_band (guint32 freq)
 {
-	NMAccessPointPrivate *priv;
-
-	g_return_if_fail (NM_IS_AP (ap));
-
-	priv = NM_AP_GET_PRIVATE (ap);
-
-	if (priv->last_seen != last_seen) {
-		priv->last_seen = last_seen;
-		g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN);
-	}
+	if (freq >= 4915 && freq <= 5825)
+		return 5;
+	else if (freq >= 2412 && freq <= 2484)
+		return 2;
+	return 0;
 }
 
 gboolean
@@ -1141,13 +816,12 @@ nm_ap_check_compatible (NMAccessPoint *self,
 
 	band = nm_setting_wireless_get_band (s_wireless);
 	if (band) {
-		if (!strcmp (band, "a")) {
-			if (priv->freq < 4915 || priv->freq > 5825)
-				return FALSE;
-		} else if (!strcmp (band, "bg")) {
-			if (priv->freq < 2412 || priv->freq > 2484)
-				return FALSE;
-		}
+		guint ap_band = freq_to_band (priv->freq);
+
+		if (!strcmp (band, "a") && ap_band != 5)
+			return FALSE;
+		else if (!strcmp (band, "bg") && ap_band != 2)
+			return FALSE;
 	}
 
 	channel = nm_setting_wireless_get_channel (s_wireless);
@@ -1162,10 +836,10 @@ nm_ap_check_compatible (NMAccessPoint *self,
 
 	return nm_setting_wireless_ap_security_compatible (s_wireless,
 	                                                   s_wireless_sec,
-	                                                   nm_ap_get_flags (self),
-	                                                   nm_ap_get_wpa_flags (self),
-	                                                   nm_ap_get_rsn_flags (self),
-	                                                   nm_ap_get_mode (self));
+	                                                   priv->flags,
+	                                                   priv->wpa_flags,
+	                                                   priv->rsn_flags,
+	                                                   priv->mode);
 }
 
 gboolean
@@ -1189,96 +863,188 @@ nm_ap_complete_connection (NMAccessPoint *self,
 	                                        error);
 }
 
-static gboolean
-capabilities_compatible (NM80211ApSecurityFlags a_flags, NM80211ApSecurityFlags b_flags)
+/*****************************************************************/
+
+static void
+nm_ap_init (NMAccessPoint *ap)
 {
-	if (a_flags == b_flags)
-		return TRUE;
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap);
 
-	/* Make sure there's a common key management method */
-	if (!((a_flags & 0x300) & (b_flags & 0x300)))
-		return FALSE;
+	priv->mode = NM_802_11_MODE_INFRA;
+	priv->flags = NM_802_11_AP_FLAGS_NONE;
+	priv->wpa_flags = NM_802_11_AP_SEC_NONE;
+	priv->rsn_flags = NM_802_11_AP_SEC_NONE;
+	priv->last_seen = -1;
+}
 
-	/* Ensure common pairwise ciphers */
-	if (!((a_flags & 0xF) & (b_flags & 0xF)))
-		return FALSE;
+static void
+finalize (GObject *object)
+{
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object);
 
-	/* Ensure common group ciphers */
-	if (!((a_flags & 0xF0) & (b_flags & 0xF0)))
-		return FALSE;
+	g_free (priv->supplicant_path);
+	if (priv->ssid)
+		g_byte_array_free (priv->ssid, TRUE);
+	g_free (priv->address);
 
-	return TRUE;
+	G_OBJECT_CLASS (nm_ap_parent_class)->finalize (object);
 }
 
-NMAccessPoint *
-nm_ap_match_in_list (NMAccessPoint *find_ap,
-                     GSList *ap_list,
-                     gboolean strict_match)
+static void
+set_property (GObject *object, guint prop_id,
+		    const GValue *value, GParamSpec *pspec)
 {
-	GSList *iter;
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
 
-	g_return_val_if_fail (find_ap != NULL, NULL);
+static void
+get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object);
+	GVariant *ssid;
 
-	for (iter = ap_list; iter; iter = g_slist_next (iter)) {
-		NMAccessPoint * list_ap = NM_AP (iter->data);
-		const GByteArray * list_ssid = nm_ap_get_ssid (list_ap);
-		const char * list_addr = nm_ap_get_address (list_ap);
+	switch (prop_id) {
+	case PROP_FLAGS:
+		g_value_set_uint (value, priv->flags);
+		break;
+	case PROP_WPA_FLAGS:
+		g_value_set_uint (value, priv->wpa_flags);
+		break;
+	case PROP_RSN_FLAGS:
+		g_value_set_uint (value, priv->rsn_flags);
+		break;
+	case PROP_SSID:
+		if (priv->ssid) {
+			ssid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+			                                  priv->ssid->data, priv->ssid->len, 1);
+		} else
+			ssid = g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0);
+		g_value_take_variant (value, ssid);
+		break;
+	case PROP_FREQUENCY:
+		g_value_set_uint (value, priv->freq);
+		break;
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, priv->address);
+		break;
+	case PROP_MODE:
+		g_value_set_uint (value, priv->mode);
+		break;
+	case PROP_MAX_BITRATE:
+		g_value_set_uint (value, priv->max_bitrate);
+		break;
+	case PROP_STRENGTH:
+		g_value_set_uchar (value, priv->strength);
+		break;
+	case PROP_LAST_SEEN:
+		g_value_set_int (value,
+		                 priv->last_seen > 0
+		                     ? (gint) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND)
+		                     : -1);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
 
-		const GByteArray * find_ssid = nm_ap_get_ssid (find_ap);
-		const char * find_addr = nm_ap_get_address (find_ap);
+static void
+nm_ap_class_init (NMAccessPointClass *ap_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (ap_class);
+	NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (ap_class);
+	const NM80211ApSecurityFlags all_sec_flags =   NM_802_11_AP_SEC_NONE
+	                                             | NM_802_11_AP_SEC_PAIR_WEP40
+	                                             | NM_802_11_AP_SEC_PAIR_WEP104
+	                                             | NM_802_11_AP_SEC_PAIR_TKIP
+	                                             | NM_802_11_AP_SEC_PAIR_CCMP
+	                                             | NM_802_11_AP_SEC_GROUP_WEP40
+	                                             | NM_802_11_AP_SEC_GROUP_WEP104
+	                                             | NM_802_11_AP_SEC_GROUP_TKIP
+	                                             | NM_802_11_AP_SEC_GROUP_CCMP
+	                                             | NM_802_11_AP_SEC_KEY_MGMT_PSK
+	                                             | NM_802_11_AP_SEC_KEY_MGMT_802_1X;
 
-		/* SSID match; if both APs are hiding their SSIDs,
-		 * let matching continue on BSSID and other properties
-		 */
-		if (   (!list_ssid && find_ssid)
-		    || (list_ssid && !find_ssid))
-			continue;
-		if (   list_ssid
-		    && find_ssid
-		    && !nm_utils_same_ssid (list_ssid->data, list_ssid->len,
-		                            find_ssid->data, find_ssid->len,
-		                            TRUE))
-			continue;
-
-		/* BSSID match */
-		if (   (strict_match || nm_ethernet_address_is_valid (find_addr, -1))
-		    && nm_ethernet_address_is_valid (list_addr, -1)
-		    && !nm_utils_hwaddr_matches (list_addr, -1, find_addr, -1))
-			continue;
-
-		/* mode match */
-		if (nm_ap_get_mode (list_ap) != nm_ap_get_mode (find_ap))
-			continue;
-
-		/* Frequency match */
-		if (nm_ap_get_freq (list_ap) != nm_ap_get_freq (find_ap))
-			continue;
-
-		/* AP flags */
-		if (nm_ap_get_flags (list_ap) != nm_ap_get_flags (find_ap))
-			continue;
-
-		if (strict_match) {
-			if (nm_ap_get_wpa_flags (list_ap) != nm_ap_get_wpa_flags (find_ap))
-				continue;
-
-			if (nm_ap_get_rsn_flags (list_ap) != nm_ap_get_rsn_flags (find_ap))
-				continue;
-		} else {
-			NM80211ApSecurityFlags list_wpa_flags = nm_ap_get_wpa_flags (list_ap);
-			NM80211ApSecurityFlags find_wpa_flags = nm_ap_get_wpa_flags (find_ap);
-			NM80211ApSecurityFlags list_rsn_flags = nm_ap_get_rsn_flags (list_ap);
-			NM80211ApSecurityFlags find_rsn_flags = nm_ap_get_rsn_flags (find_ap);
-
-			/* Just ensure that there is overlap in the capabilities */
-			if (   !capabilities_compatible (list_wpa_flags, find_wpa_flags)
-			    && !capabilities_compatible (list_rsn_flags, find_rsn_flags))
-				continue;
-		}
+	g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate));
 
-		return list_ap;
-	}
+	exported_object_class->export_path = NM_DBUS_PATH_ACCESS_POINT "/%u";
 
-	return NULL;
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	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, "", "",
+	                          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));
+
+	nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ap_class),
+	                                        NMDBUS_TYPE_ACCESS_POINT_SKELETON,
+	                                        NULL);
 }
 
diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h
index 67d30769..84aff983 100644
--- a/src/devices/wifi/nm-wifi-ap.h
+++ b/src/devices/wifi/nm-wifi-ap.h
@@ -22,8 +22,7 @@
 #ifndef __NETWORKMANAGER_ACCESS_POINT_H__
 #define __NETWORKMANAGER_ACCESS_POINT_H__
 
-#include <glib.h>
-#include <glib-object.h>
+#include "nm-exported-object.h"
 #include "nm-dbus-interface.h"
 #include "nm-connection.h"
 
@@ -46,77 +45,58 @@
 #define NM_AP_LAST_SEEN "last-seen"
 
 typedef struct {
-	GObject parent;
+	NMExportedObject parent;
 } NMAccessPoint;
 
 typedef struct {
-	GObjectClass parent;
+	NMExportedObjectClass parent;
 
 } NMAccessPointClass;
 
 GType nm_ap_get_type (void);
 
-NMAccessPoint * nm_ap_new_from_properties (const char *supplicant_path,
-                                           GVariant *properties);
-NMAccessPoint * nm_ap_new_fake_from_connection (NMConnection *connection);
-void            nm_ap_export_to_dbus    (NMAccessPoint *ap);
-
-const char *nm_ap_get_dbus_path (NMAccessPoint *ap);
-
-const char *nm_ap_get_supplicant_path (NMAccessPoint *ap);
-void        nm_ap_set_supplicant_path (NMAccessPoint *ap,
-                                       const char *path);
-
-const GByteArray *nm_ap_get_ssid (const NMAccessPoint * ap);
-void              nm_ap_set_ssid (NMAccessPoint * ap, const guint8 * ssid, gsize len);
-
-NM80211ApFlags nm_ap_get_flags (NMAccessPoint *ap);
-void           nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags);
-
-NM80211ApSecurityFlags nm_ap_get_wpa_flags (NMAccessPoint *ap);
-void                   nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags);
-
-NM80211ApSecurityFlags nm_ap_get_rsn_flags (NMAccessPoint *ap);
-void                   nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags);
-
-const char *nm_ap_get_address (const NMAccessPoint *ap);
-void        nm_ap_set_address (NMAccessPoint *ap, const char *addr);
-
-NM80211Mode nm_ap_get_mode (NMAccessPoint *ap);
-void        nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode);
-
-gboolean nm_ap_is_hotspot (NMAccessPoint *ap);
-
-gint8 nm_ap_get_strength (NMAccessPoint *ap);
-void  nm_ap_set_strength (NMAccessPoint *ap, gint8 strength);
-
-guint32 nm_ap_get_freq (NMAccessPoint *ap);
-void    nm_ap_set_freq (NMAccessPoint *ap, guint32 freq);
-
-guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap);
-void    nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate);
-
-gboolean nm_ap_get_fake (const NMAccessPoint *ap);
-void     nm_ap_set_fake (NMAccessPoint *ap, gboolean fake);
-
-gboolean nm_ap_get_broadcast (NMAccessPoint *ap);
-void     nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast);
-
-gint32   nm_ap_get_last_seen (const NMAccessPoint *ap);
-void     nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen);
-
-gboolean nm_ap_check_compatible (NMAccessPoint *self,
-                                 NMConnection *connection);
-
-gboolean nm_ap_complete_connection (NMAccessPoint *self,
-                                    NMConnection *connection,
-                                    gboolean lock_bssid,
-                                    GError **error);
-
-NMAccessPoint *     nm_ap_match_in_list (NMAccessPoint *find_ap,
-                                         GSList *ap_list,
-                                         gboolean strict_match);
-
-void                nm_ap_dump (NMAccessPoint *ap, const char *prefix);
+NMAccessPoint *   nm_ap_new_from_properties      (const char *supplicant_path,
+                                                  GVariant *properties);
+NMAccessPoint *   nm_ap_new_fake_from_connection (NMConnection *connection);
+
+void              nm_ap_update_from_properties   (NMAccessPoint *ap,
+                                                  const char *supplicant_path,
+                                                  GVariant *properties);
+
+gboolean          nm_ap_check_compatible         (NMAccessPoint *self,
+                                                  NMConnection *connection);
+
+gboolean          nm_ap_complete_connection      (NMAccessPoint *self,
+                                                  NMConnection *connection,
+                                                  gboolean lock_bssid,
+                                                  GError **error);
+
+const char *      nm_ap_get_supplicant_path      (NMAccessPoint *ap);
+guint32           nm_ap_get_id                   (NMAccessPoint *ap);
+const GByteArray *nm_ap_get_ssid                 (const NMAccessPoint *ap);
+void              nm_ap_set_ssid                 (NMAccessPoint *ap,
+                                                  const guint8 *ssid,
+                                                  gsize len);
+const char *      nm_ap_get_address              (const NMAccessPoint *ap);
+void              nm_ap_set_address              (NMAccessPoint *ap,
+                                                  const char *addr);
+NM80211Mode       nm_ap_get_mode                 (NMAccessPoint *ap);
+gboolean          nm_ap_is_hotspot               (NMAccessPoint *ap);
+gint8             nm_ap_get_strength             (NMAccessPoint *ap);
+void              nm_ap_set_strength             (NMAccessPoint *ap,
+                                                  gint8 strength);
+guint32           nm_ap_get_freq                 (NMAccessPoint *ap);
+void              nm_ap_set_freq                 (NMAccessPoint *ap,
+                                                  guint32 freq);
+guint32           nm_ap_get_max_bitrate          (NMAccessPoint *ap);
+void              nm_ap_set_max_bitrate          (NMAccessPoint *ap,
+                                                  guint32 bitrate);
+gboolean          nm_ap_get_fake                 (const NMAccessPoint *ap);
+void              nm_ap_set_fake                 (NMAccessPoint *ap,
+                                                  gboolean fake);
+
+void              nm_ap_dump                     (NMAccessPoint *self,
+                                                  const char *prefix,
+                                                  const char *ifname);
 
 #endif /* __NETWORKMANAGER_ACCESS_POINT_H__ */
diff --git a/src/devices/wifi/nm-wifi-enum-types.c b/src/devices/wifi/nm-wifi-enum-types.c
deleted file mode 100644
index 7cce51cd..00000000
--- a/src/devices/wifi/nm-wifi-enum-types.c
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-/* Generated by glib-mkenums. Do not edit */
-
-#include "nm-wifi-enum-types.h"
-
-#include "nm-device-wifi.h" 
-#include "nm-wifi-ap.h" 
-#include "nm-device-olpc-mesh.h"
-
-
-
-
diff --git a/src/devices/wifi/nm-wifi-enum-types.h b/src/devices/wifi/nm-wifi-enum-types.h
deleted file mode 100644
index 7fc64cd1..00000000
--- a/src/devices/wifi/nm-wifi-enum-types.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-/* Generated by glib-mkenums. Do not edit */
-
-#ifndef __NM_WIFI_ENUM_TYPES_H__
-#define __NM_WIFI_ENUM_TYPES_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-G_END_DECLS
-
-#endif /* __NM_WIFI_ENUM_TYPES_H__ */
-
-
-
diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c
index c4b4042e..7f56dc74 100644
--- a/src/devices/wifi/nm-wifi-factory.c
+++ b/src/devices/wifi/nm-wifi-factory.c
@@ -43,7 +43,7 @@ typedef struct {
 
 static GType nm_wifi_factory_get_type (void);
 
-static void device_factory_interface_init (NMDeviceFactory *factory_iface);
+static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface);
 
 G_DEFINE_TYPE_EXTENDED (NMWifiFactory, nm_wifi_factory, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init))
@@ -59,13 +59,30 @@ nm_device_factory_create (GError **error)
 /**************************************************************************/
 
 static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+               const char *iface,
+               const NMPlatformLink *plink,
+               NMConnection *connection,
+               gboolean *out_ignore)
 {
+	NMDeviceWifiCapabilities capabilities;
+
+	g_return_val_if_fail (iface != NULL, NULL);
+	g_return_val_if_fail (plink != NULL, NULL);
+	g_return_val_if_fail (g_strcmp0 (iface, plink->name) == 0, NULL);
+	g_return_val_if_fail (NM_IN_SET (plink->type, NM_LINK_TYPE_WIFI, NM_LINK_TYPE_OLPC_MESH), NULL);
+
+	if (!nm_platform_wifi_get_capabilities (NM_PLATFORM_GET,
+	                                        plink->ifindex,
+	                                        &capabilities)) {
+		nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s) failed to initialize Wi-Fi driver for ifindex %d", iface, plink->ifindex);
+		return NULL;
+	}
+
 	if (plink->type == NM_LINK_TYPE_WIFI)
-		return nm_device_wifi_new (plink);
-	else if (plink->type == NM_LINK_TYPE_OLPC_MESH)
-		return nm_device_olpc_mesh_new (plink);
-	g_assert_not_reached ();
+		return nm_device_wifi_new (iface, capabilities);
+	else
+		return nm_device_olpc_mesh_new (iface);
 }
 
 NM_DEVICE_FACTORY_DECLARE_TYPES (
@@ -74,9 +91,9 @@ NM_DEVICE_FACTORY_DECLARE_TYPES (
 )
 
 static void
-device_factory_interface_init (NMDeviceFactory *factory_iface)
+device_factory_interface_init (NMDeviceFactoryInterface *factory_iface)
 {
-	factory_iface->new_link = new_link;
+	factory_iface->create_device = create_device;
 	factory_iface->get_supported_types = get_supported_types;
 }
 
diff --git a/src/devices/wifi/tests/Makefile.am b/src/devices/wifi/tests/Makefile.am
index f76bdbf5..dee8e799 100644
--- a/src/devices/wifi/tests/Makefile.am
+++ b/src/devices/wifi/tests/Makefile.am
@@ -1,6 +1,7 @@
 AM_CPPFLAGS = \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir)/include \
+	-I$(top_builddir)/introspection \
+	-I$(top_srcdir)/shared \
+	-I$(top_builddir)/shared \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I${top_srcdir}/src/platform \
@@ -8,10 +9,9 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/devices/wifi \
 	-I$(top_builddir)/src \
 	-DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
-	$(GLIB_CFLAGS) \
-	$(DBUS_CFLAGS)
+	$(GLIB_CFLAGS)
 
 noinst_PROGRAMS = test-wifi-ap-utils
 
diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in
index f2488c7d..90900f00 100644
--- a/src/devices/wifi/tests/Makefile.in
+++ b/src/devices/wifi/tests/Makefile.in
@@ -404,7 +404,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CKDB_PATH = @CKDB_PATH@
 CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
 CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
 CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
@@ -416,8 +415,6 @@ CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
-DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
@@ -427,6 +424,7 @@ DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
+DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
@@ -481,16 +479,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
-IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
-IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
+LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
 LIBDL = @LIBDL@
-LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
-LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
-LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -527,6 +522,8 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
+NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -555,7 +552,6 @@ POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
 PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
-PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
@@ -570,6 +566,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
 SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
 SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
 SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@
+SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
@@ -630,6 +628,7 @@ mkdir_p = @mkdir_p@
 nmbinary = @nmbinary@
 nmconfdir = @nmconfdir@
 nmdatadir = @nmdatadir@
+nmlibdir = @nmlibdir@
 nmrundir = @nmrundir@
 nmstatedir = @nmstatedir@
 oldincludedir = @oldincludedir@
@@ -637,6 +636,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -653,8 +653,9 @@ with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 AM_CPPFLAGS = \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir)/include \
+	-I$(top_builddir)/introspection \
+	-I$(top_srcdir)/shared \
+	-I$(top_builddir)/shared \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-I${top_srcdir}/src/platform \
@@ -662,10 +663,9 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/devices/wifi \
 	-I$(top_builddir)/src \
 	-DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
-	$(GLIB_CFLAGS) \
-	$(DBUS_CFLAGS)
+	$(GLIB_CFLAGS)
 
 test_wifi_ap_utils_SOURCES = \
 	test-wifi-ap-utils.c \
diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c
index 26e130c4..b5642fe2 100644
--- a/src/devices/wifi/tests/test-wifi-ap-utils.c
+++ b/src/devices/wifi/tests/test-wifi-ap-utils.c
@@ -20,14 +20,15 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <string.h>
 
+#include "nm-default.h"
 #include "nm-wifi-ap-utils.h"
-#include "nm-dbus-glib-types.h"
 
 #include "nm-core-internal.h"
 
+#include "nm-test-utils.h"
+
 #define DEBUG 1
 
 /*******************************************/
@@ -1336,16 +1337,14 @@ test_strength_wext (void)
 
 /*******************************************/
 
+NMTST_DEFINE ();
+
 int
 main (int argc, char **argv)
 {
 	gsize i;
 
-#if !GLIB_CHECK_VERSION (2, 35, 0)
-	g_type_init ();
-#endif
-
-	g_test_init (&argc, &argv, NULL);
+	nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
 
 	g_test_add_func ("/wifi/lock_bssid",
 	                 test_lock_bssid);