summary refs log tree commit diff
path: root/src/supplicant-manager
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2015-07-14 19:38:58 +0200
committerMichael Biebl <biebl@debian.org>2015-07-14 19:38:58 +0200
commit50a58f0fabd8a34c1b6108a107e08abe3c1ccd24 (patch)
tree6790165f39daee79e2b6c6617483320613493367 /src/supplicant-manager
parentf408e27bccfacf347605a8d98649975a68f38a17 (diff)
Imported Upstream version 1.0.4 upstream/1.0.4
Diffstat (limited to 'src/supplicant-manager')
-rw-r--r--src/supplicant-manager/nm-call-store.c119
-rw-r--r--src/supplicant-manager/nm-call-store.h41
-rw-r--r--src/supplicant-manager/nm-supplicant-config.c155
-rw-r--r--src/supplicant-manager/nm-supplicant-config.h2
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c1496
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.h6
-rw-r--r--src/supplicant-manager/nm-supplicant-manager.c263
-rw-r--r--src/supplicant-manager/nm-supplicant-manager.h9
-rw-r--r--src/supplicant-manager/nm-supplicant-types.h4
-rw-r--r--src/supplicant-manager/tests/Makefile.in437
-rw-r--r--src/supplicant-manager/tests/test-supplicant-config.c233
11 files changed, 1316 insertions, 1449 deletions
diff --git a/src/supplicant-manager/nm-call-store.c b/src/supplicant-manager/nm-call-store.c
deleted file mode 100644
index 6e910a96..00000000
--- a/src/supplicant-manager/nm-call-store.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Copyright (C) 2007 Novell, Inc.
- * Copyright (C) 2010 Red Hat, Inc.
- */
-
-#include "config.h"
-
-#include "nm-call-store.h"
-#include "nm-logging.h"
-
-NMCallStore *
-nm_call_store_new (void)
-{
-	/* Maps { DBusGProxy :: GHashTable { DBusGProxyCall :: NULL } } */
-	return g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_hash_table_destroy);
-}
-
-static void
-proxy_destroyed_cb (gpointer data, GObject *proxy)
-{
-	g_hash_table_remove ((NMCallStore *) data, proxy);
-}
-
-void
-nm_call_store_add (NMCallStore *store,
-                   DBusGProxy *proxy,
-                   DBusGProxyCall *call)
-{
-	GHashTable *calls;
-
-	g_return_if_fail (store != NULL);
-	g_return_if_fail (proxy != NULL);
-
-	if (!call) {
-		/* Allow calling nm_call_store_add() with NULL @call for convenience.
-		 * This way you can pass the result of dbus_g_proxy_begin_call() directly
-		 * to nm_call_store_add() without checking for NULL. */
-		return;
-	}
-
-	calls = g_hash_table_lookup (store, proxy);
-	if (!calls) {
-		calls = g_hash_table_new (NULL, NULL);
-		g_hash_table_insert (store, proxy, calls);
-		g_object_weak_ref (G_OBJECT (proxy), proxy_destroyed_cb, store);
-	}
-
-	g_hash_table_add (calls, call);
-}
-
-void
-nm_call_store_remove (NMCallStore *store,
-                      DBusGProxy *proxy,
-                      DBusGProxyCall *call)
-{
-	GHashTable *calls;
-
-	g_return_if_fail (store != NULL);
-	g_return_if_fail (proxy != NULL);
-	g_return_if_fail (call != NULL);
-
-	calls = g_hash_table_lookup (store, proxy);
-	if (!calls)
-		return;
-
-	g_hash_table_remove (calls, call);
-	if (g_hash_table_size (calls) == 0) {
-		g_hash_table_remove (store, proxy);
-		g_object_weak_unref (G_OBJECT (proxy), proxy_destroyed_cb, store);
-	}
-}
-
-void
-nm_call_store_clear (NMCallStore *store)
-{
-	DBusGProxy *proxy;
-	GHashTable *calls;
-	GHashTableIter proxies_iter;
-
-	g_return_if_fail (store != NULL);
-
-	g_hash_table_iter_init (&proxies_iter, store);
-	while (g_hash_table_iter_next (&proxies_iter, (gpointer) &proxy, (gpointer) &calls)) {
-		GHashTableIter calls_iter;
-		DBusGProxyCall *call;
-
-		g_hash_table_iter_init (&calls_iter, calls);
-		while (g_hash_table_iter_next (&calls_iter, (gpointer) &call, NULL)) {
-			dbus_g_proxy_cancel_call (proxy, call);
-			g_hash_table_iter_remove (&calls_iter);
-		}
-		g_object_weak_unref (G_OBJECT (proxy), proxy_destroyed_cb, store);
-		g_hash_table_iter_remove (&proxies_iter);
-	}
-	g_assert_cmpint (g_hash_table_size (store), ==, 0);
-}
-
-void
-nm_call_store_destroy (NMCallStore *store)
-{
-	g_return_if_fail (store);
-	g_hash_table_destroy (store);
-}
diff --git a/src/supplicant-manager/nm-call-store.h b/src/supplicant-manager/nm-call-store.h
deleted file mode 100644
index bcee54cf..00000000
--- a/src/supplicant-manager/nm-call-store.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2007 Novell, Inc.
- */
-
-#ifndef __NETWORKMANAGER_CALLBACK_STORE_H__
-#define __NETWORKMANAGER_CALLBACK_STORE_H__
-
-#include <glib-object.h>
-#include <dbus/dbus-glib.h>
-
-typedef GHashTable NMCallStore;
-
-NMCallStore *nm_call_store_new     (void);
-void         nm_call_store_add     (NMCallStore *store,
-									DBusGProxy *proxy,
-									DBusGProxyCall *call);
-
-void         nm_call_store_remove  (NMCallStore *store,
-									DBusGProxy *proxy,
-									DBusGProxyCall *call);
-
-void         nm_call_store_clear   (NMCallStore *store);
-void         nm_call_store_destroy (NMCallStore *store);
-
-#endif /* __NETWORKMANAGER_CALLBACK_STORE_H__ */
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index c60027ad..b78a24d0 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -260,65 +260,44 @@ nm_supplicant_config_fast_required (NMSupplicantConfig *self)
 	return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->fast_required;
 }
 
-static void
-get_hash_cb (gpointer key, gpointer value, gpointer user_data)
-{
-	ConfigOption *opt = (ConfigOption *) value;
-	GValue *variant;
-	GByteArray *array;
-
-	variant = g_slice_new0 (GValue);
-
-	switch (opt->type) {
-	case TYPE_INT:
-		g_value_init (variant, G_TYPE_INT);
-		g_value_set_int (variant, atoi (opt->value));
-		break;
-	case TYPE_BYTES:
-	case TYPE_UTF8:
-		array = g_byte_array_sized_new (opt->len);
-		g_byte_array_append (array, (const guint8 *) opt->value, opt->len);
-		g_value_init (variant, DBUS_TYPE_G_UCHAR_ARRAY);
-		g_value_set_boxed (variant, array);
-		g_byte_array_free (array, TRUE);
-		break;
-	case TYPE_KEYWORD:
-	case TYPE_STRING:
-		g_value_init (variant, G_TYPE_STRING);
-		g_value_set_string (variant, opt->value);
-		break;
-	default:
-		g_slice_free (GValue, variant);
-		return;
-	}
-
-	g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), variant);
-}
-
-static void
-destroy_hash_value (gpointer data)
-{
-	GValue *value = (GValue *) data;
-
-	g_value_unset (value);
-	g_slice_free (GValue, value);
-}
-
-GHashTable *
-nm_supplicant_config_get_hash (NMSupplicantConfig * self)
+GVariant *
+nm_supplicant_config_to_variant (NMSupplicantConfig *self)
 {
 	NMSupplicantConfigPrivate *priv;
-	GHashTable *hash;
+	GVariantBuilder builder;
+	GHashTableIter iter;
+	ConfigOption *option;
+	const char *key;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), NULL);
 
-	hash = g_hash_table_new_full (g_str_hash, g_str_equal,
-	                              (GDestroyNotify) g_free,
-	                              destroy_hash_value);
-
 	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
-	g_hash_table_foreach (priv->config, get_hash_cb, hash);
-	return hash;
+
+	g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+
+	g_hash_table_iter_init (&iter, priv->config);
+	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &option)) {
+		switch (option->type) {
+		case TYPE_INT:
+			g_variant_builder_add (&builder, "{sv}", key, g_variant_new_int32 (atoi (option->value)));
+			break;
+		case TYPE_BYTES:
+		case TYPE_UTF8:
+			g_variant_builder_add (&builder, "{sv}",
+			                       key,
+			                       g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+			                                                  option->value, option->len, 1));
+			break;
+		case TYPE_KEYWORD:
+		case TYPE_STRING:
+			g_variant_builder_add (&builder, "{sv}", key, g_variant_new_string (option->value));
+			break;
+		default:
+			break;
+		}
+	}
+
+	return g_variant_builder_end (&builder);
 }
 
 GHashTable *
@@ -754,6 +733,7 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 	gboolean fast = FALSE;
 	guint32 i, num_eap;
 	gboolean fast_provisoning_allowed = FALSE;
+	const char *ca_path_override = NULL, *ca_cert_override = NULL;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
 	g_return_val_if_fail (setting != NULL, FALSE);
@@ -891,10 +871,18 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 		}
 	}
 
+	/* If user wants to use system CA certs, either populate ca_path (if the path
+	 * is a directory) or ca_cert (the path is a file name) */
+	if (nm_setting_802_1x_get_system_ca_certs (setting)) {
+		if (g_file_test (SYSTEM_CA_PATH, G_FILE_TEST_IS_DIR))
+			ca_path_override = SYSTEM_CA_PATH;
+		else
+			ca_cert_override = SYSTEM_CA_PATH;
+	}
+
 	/* CA path */
 	path = nm_setting_802_1x_get_ca_path (setting);
-	if (nm_setting_802_1x_get_system_ca_certs (setting))
-		path = SYSTEM_CA_PATH;
+	path = ca_path_override ? ca_path_override : path;
 	if (path) {
 		if (!add_string_val (self, path, "ca_path", FALSE, FALSE))
 			return FALSE;
@@ -902,41 +890,50 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
 
 	/* Phase2 CA path */
 	path = nm_setting_802_1x_get_phase2_ca_path (setting);
-	if (nm_setting_802_1x_get_system_ca_certs (setting))
-		path = SYSTEM_CA_PATH;
+	path = ca_path_override ? ca_path_override : path;
 	if (path) {
 		if (!add_string_val (self, path, "ca_path2", FALSE, FALSE))
 			return FALSE;
 	}
 
 	/* CA certificate */
-	switch (nm_setting_802_1x_get_ca_cert_scheme (setting)) {
-	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-		bytes = nm_setting_802_1x_get_ca_cert_blob (setting);
-		ADD_BLOB_VAL (bytes, "ca_cert", con_uuid);
-		break;
-	case NM_SETTING_802_1X_CK_SCHEME_PATH:
-		path = nm_setting_802_1x_get_ca_cert_path (setting);
-		if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
+	if (ca_cert_override) {
+		if (!add_string_val (self, ca_cert_override, "ca_cert", FALSE, FALSE))
 			return FALSE;
-		break;
-	default:
-		break;
+	} else {
+		switch (nm_setting_802_1x_get_ca_cert_scheme (setting)) {
+		case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+			bytes = nm_setting_802_1x_get_ca_cert_blob (setting);
+			ADD_BLOB_VAL (bytes, "ca_cert", con_uuid);
+			break;
+		case NM_SETTING_802_1X_CK_SCHEME_PATH:
+			path = nm_setting_802_1x_get_ca_cert_path (setting);
+			if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
+				return FALSE;
+			break;
+		default:
+			break;
+		}
 	}
 
 	/* Phase 2 CA certificate */
-	switch (nm_setting_802_1x_get_phase2_ca_cert_scheme (setting)) {
-	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-		bytes = nm_setting_802_1x_get_phase2_ca_cert_blob (setting);
-		ADD_BLOB_VAL (bytes, "ca_cert2", con_uuid);
-		break;
-	case NM_SETTING_802_1X_CK_SCHEME_PATH:
-		path = nm_setting_802_1x_get_phase2_ca_cert_path (setting);
-		if (!add_string_val (self, path, "ca_cert2", FALSE, FALSE))
+	if (ca_cert_override) {
+		if (!add_string_val (self, ca_cert_override, "ca_cert2", FALSE, FALSE))
 			return FALSE;
-		break;
-	default:
-		break;
+	} else {
+		switch (nm_setting_802_1x_get_phase2_ca_cert_scheme (setting)) {
+		case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+			bytes = nm_setting_802_1x_get_phase2_ca_cert_blob (setting);
+			ADD_BLOB_VAL (bytes, "ca_cert2", con_uuid);
+			break;
+		case NM_SETTING_802_1X_CK_SCHEME_PATH:
+			path = nm_setting_802_1x_get_phase2_ca_cert_path (setting);
+			if (!add_string_val (self, path, "ca_cert2", FALSE, FALSE))
+				return FALSE;
+			break;
+		default:
+			break;
+		}
 	}
 
 	/* Subject match */
diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h
index 482e3545..3324f637 100644
--- a/src/supplicant-manager/nm-supplicant-config.h
+++ b/src/supplicant-manager/nm-supplicant-config.h
@@ -59,7 +59,7 @@ void nm_supplicant_config_set_ap_scan (NMSupplicantConfig *self,
 
 gboolean nm_supplicant_config_fast_required (NMSupplicantConfig *self);
 
-GHashTable *nm_supplicant_config_get_hash (NMSupplicantConfig *self);
+GVariant *nm_supplicant_config_to_variant (NMSupplicantConfig *self);
 
 GHashTable *nm_supplicant_config_get_blobs (NMSupplicantConfig *self);
 
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
index 02b82b7e..e9775a19 100644
--- a/src/supplicant-manager/nm-supplicant-interface.c
+++ b/src/supplicant-manager/nm-supplicant-interface.c
@@ -27,13 +27,11 @@
 
 #include "NetworkManagerUtils.h"
 #include "nm-supplicant-interface.h"
-#include "nm-supplicant-manager.h"
 #include "nm-logging.h"
 #include "nm-supplicant-config.h"
-#include "nm-dbus-manager.h"
-#include "nm-call-store.h"
-#include "nm-dbus-glib-types.h"
 #include "nm-glib-compat.h"
+#include "gsystem-local-alloc.h"
+#include "nm-core-internal.h"
 
 #define WPAS_DBUS_IFACE_INTERFACE   WPAS_DBUS_INTERFACE ".Interface"
 #define WPAS_DBUS_IFACE_BSS         WPAS_DBUS_INTERFACE ".BSS"
@@ -43,16 +41,6 @@
 
 G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT)
 
-static void wpas_iface_properties_changed (DBusGProxy *proxy,
-                                           GHashTable *props,
-                                           gpointer user_data);
-
-static void wpas_iface_scan_done (DBusGProxy *proxy,
-                                  gboolean success,
-                                  gpointer user_data);
-
-static void wpas_iface_get_props (NMSupplicantInterface *self);
-
 #define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
                                                  NM_TYPE_SUPPLICANT_INTERFACE, \
                                                  NMSupplicantInterfacePrivate))
@@ -81,89 +69,53 @@ enum {
 
 
 typedef struct {
-	NMSupplicantManager * smgr;
-	gulong                smgr_avail_id;
-	NMDBusManager *       dbus_mgr;
-	char *                dev;
-	gboolean              is_wireless;
-	gboolean              has_credreq;  /* Whether querying 802.1x credentials is supported */
-	ApSupport             ap_support;   /* Lightweight AP mode support */
-	gboolean              fast_supported;
-	guint32               max_scan_ssids;
-	guint32               ready_count;
-
-	char *                object_path;
-	guint32               state;
-	int                   disconnect_reason;
-	NMCallStore *         assoc_pcalls;
-	NMCallStore *         other_pcalls;
-
-	gboolean              scanning;
-
-	DBusGProxy *          wpas_proxy;
-	DBusGProxy *          introspect_proxy;
-	DBusGProxy *          iface_proxy;
-	DBusGProxy *          props_proxy;
-	char *                net_path;
-	guint32               blobs_left;
-	GHashTable *          bss_proxies;
-
-	gint32                last_scan; /* timestamp as returned by nm_utils_get_monotonic_timestamp_s() */
-
-	NMSupplicantConfig *  cfg;
-
-	gboolean              disposed;
+	char *         dev;
+	gboolean       is_wireless;
+	gboolean       has_credreq;  /* Whether querying 802.1x credentials is supported */
+	ApSupport      ap_support;   /* Lightweight AP mode support */
+	gboolean       fast_supported;
+	guint32        max_scan_ssids;
+	guint32        ready_count;
+
+	char *         object_path;
+	guint32        state;
+	int            disconnect_reason;
+
+	gboolean       scanning;
+
+	GDBusProxy *   wpas_proxy;
+	GCancellable * init_cancellable;
+	GDBusProxy *   iface_proxy;
+	GCancellable * other_cancellable;
+	GCancellable * assoc_cancellable;
+	char *         net_path;
+	guint32        blobs_left;
+	GHashTable *   bss_proxies;
+
+	gint32         last_scan; /* timestamp as returned by nm_utils_get_monotonic_timestamp_s() */
+
+	NMSupplicantConfig *cfg;
 } NMSupplicantInterfacePrivate;
 
-static void
-emit_error_helper (NMSupplicantInterface *self,
-				   GError *err)
-{
-	const char *name = NULL;
-
-	if (err->domain == DBUS_GERROR && err->code == DBUS_GERROR_REMOTE_EXCEPTION)
-		name = dbus_g_error_get_name (err);
-
-	g_signal_emit (self, signals[CONNECTION_ERROR], 0, name, err->message);
-}
+/***************************************************************/
 
 static void
-signal_new_bss (NMSupplicantInterface *self,
-                const char *object_path,
-                GHashTable *props)
+emit_error_helper (NMSupplicantInterface *self, GError *error)
 {
-	g_signal_emit (self, signals[NEW_BSS], 0, object_path, props);
-}
+	char *name = NULL;
 
-static void
-bssid_properties_cb  (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *error = NULL;
-	GHashTable *props = NULL;
-
-	nm_call_store_remove (priv->other_pcalls, proxy, call_id);
-	if (dbus_g_proxy_end_call (proxy, call_id, &error,
-	                           DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-	                           G_TYPE_INVALID)) {
-		signal_new_bss (self, dbus_g_proxy_get_path (proxy), props);
-		g_hash_table_destroy (props);
-	} else {
-		if (!strstr (error->message, "The BSSID requested was invalid")) {
-			nm_log_warn (LOGD_SUPPLICANT, "Couldn't retrieve BSSID properties: %s.",
-			             error->message);
-		}
-		g_error_free (error);
-	}
+	if (g_dbus_error_is_remote_error (error))
+		name = g_dbus_error_get_remote_error (error);
+
+	g_signal_emit (self, signals[CONNECTION_ERROR], 0, name, error->message);
+	g_free (name);
 }
 
 static void
-bss_properties_changed (DBusGProxy *proxy,
-                        const char *interface,
-                        GHashTable *props,
-                        const char **unused,
-                        gpointer user_data)
+bss_props_changed_cb (GDBusProxy *proxy,
+                      GVariant *changed_properties,
+                      char **invalidated_properties,
+                      gpointer user_data)
 {
 	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
@@ -171,111 +123,77 @@ bss_properties_changed (DBusGProxy *proxy,
 	if (priv->scanning)
 		priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
 
-	if (g_strcmp0 (interface, WPAS_DBUS_IFACE_BSS) == 0)
-		g_signal_emit (self, signals[BSS_UPDATED], 0, dbus_g_proxy_get_path (proxy), props);
+	g_signal_emit (self, signals[BSS_UPDATED], 0,
+	               g_dbus_proxy_get_object_path (proxy),
+	               changed_properties);
 }
 
 static void
-handle_new_bss (NMSupplicantInterface *self,
-                const char *object_path,
-                GHashTable *props)
+on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGProxy *bss_proxy;
-	DBusGProxyCall *call;
-
-	g_return_if_fail (object_path != NULL);
-
-	if (g_hash_table_lookup (priv->bss_proxies, object_path))
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_free_error GError *error = NULL;
+	gs_strfreev char **properties = NULL;
+	gs_unref_variant GVariant *props = NULL;
+	GVariantBuilder builder;
+	char **iter;
+
+	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
+		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+			nm_log_dbg (LOGD_SUPPLICANT, "Failed to acquire BSS proxy: (%s)", error->message);
+			g_hash_table_remove (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data)->bss_proxies,
+			                     g_dbus_proxy_get_object_path (proxy));
+		}
 		return;
+	}
 
-	bss_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
-	                                       WPAS_DBUS_SERVICE,
-	                                       object_path,
-	                                       DBUS_INTERFACE_PROPERTIES);
-	g_hash_table_insert (priv->bss_proxies,
-	                     (gpointer) dbus_g_proxy_get_path (bss_proxy),
-	                     bss_proxy);
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	/* Standard D-Bus PropertiesChanged signal */
-	dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
-	                                   G_TYPE_NONE,
-	                                   G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_STRV,
-	                                   G_TYPE_INVALID);
-	dbus_g_proxy_add_signal (bss_proxy, "PropertiesChanged",
-	                         G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_STRV,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (bss_proxy, "PropertiesChanged",
-	                             G_CALLBACK (bss_properties_changed),
-	                             self, NULL);
-
-	if (props) {
-		signal_new_bss (self, object_path, props);
-	} else {
-		call = dbus_g_proxy_begin_call (bss_proxy, "GetAll",
-		                                bssid_properties_cb,
-		                                self,
-		                                NULL,
-		                                G_TYPE_STRING, WPAS_DBUS_IFACE_BSS,
-		                                G_TYPE_INVALID);
-		nm_call_store_add (priv->other_pcalls, bss_proxy, call);
-	}
-}
+	g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
 
-static void
-wpas_iface_bss_added (DBusGProxy *proxy,
-                      const char *object_path,
-                      GHashTable *props,
-                      gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	iter = properties = g_dbus_proxy_get_cached_property_names (proxy);
+	while (*iter) {
+		GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter);
 
-	if (priv->scanning)
-		priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
+		g_variant_builder_add (&builder, "{sv}", *iter++, copy);
+		g_variant_unref (copy);
+	}
 
-	handle_new_bss (self, object_path, props);
+	props = g_variant_builder_end (&builder);
+	g_signal_emit (self, signals[NEW_BSS], 0,
+	               g_dbus_proxy_get_object_path (proxy),
+	               g_variant_ref_sink (props));
 }
 
 static void
-wpas_iface_bss_removed (DBusGProxy *proxy,
-                        const char *object_path,
-                        gpointer user_data)
+handle_new_bss (NMSupplicantInterface *self, const char *object_path)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	GDBusProxy *bss_proxy;
 
-	g_signal_emit (self, signals[BSS_REMOVED], 0, object_path);
-
-	g_hash_table_remove (priv->bss_proxies, object_path);
-}
+	g_return_if_fail (object_path != NULL);
 
-static int
-wpas_state_string_to_enum (const char *str_state)
-{
-	if (!strcmp (str_state, "interface_disabled"))
-		return NM_SUPPLICANT_INTERFACE_STATE_DISABLED;
-	else if (!strcmp (str_state, "disconnected"))
-		return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED;
-	else if (!strcmp (str_state, "inactive"))
-		return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE;
-	else if (!strcmp (str_state, "scanning"))
-		return NM_SUPPLICANT_INTERFACE_STATE_SCANNING;
-	else if (!strcmp (str_state, "authenticating"))
-		return NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING;
-	else if (!strcmp (str_state, "associating"))
-		return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING;
-	else if (!strcmp (str_state, "associated"))
-		return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED;
-	else if (!strcmp (str_state, "4way_handshake"))
-		return NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE;
-	else if (!strcmp (str_state, "group_handshake"))
-		return NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE;
-	else if (!strcmp (str_state, "completed"))
-		return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED;
+	if (g_hash_table_lookup (priv->bss_proxies, object_path))
+		return;
 
-	nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant state '%s'", str_state);
-	return -1;
+	bss_proxy = g_object_new (G_TYPE_DBUS_PROXY,
+	                          "g-bus-type", G_BUS_TYPE_SYSTEM,
+	                          "g-flags", G_DBUS_PROXY_FLAGS_NONE,
+	                          "g-name", WPAS_DBUS_SERVICE,
+	                          "g-object-path", object_path,
+	                          "g-interface-name", WPAS_DBUS_IFACE_BSS,
+	                          NULL);
+	g_hash_table_insert (priv->bss_proxies,
+	                     (char *) g_dbus_proxy_get_object_path (bss_proxy),
+	                     bss_proxy);
+	g_signal_connect (bss_proxy, "g-properties-changed", G_CALLBACK (bss_props_changed_cb), self);
+	g_async_initable_init_async (G_ASYNC_INITABLE (bss_proxy),
+	                             G_PRIORITY_DEFAULT,
+	                             priv->other_cancellable,
+	                             (GAsyncReadyCallback) on_bss_proxy_acquired,
+	                             self);
 }
 
 static void
@@ -297,39 +215,23 @@ set_state (NMSupplicantInterface *self, guint32 new_state)
 		g_return_if_fail (new_state > NM_SUPPLICANT_INTERFACE_STATE_READY);
 
 	if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
-		/* Get properties again to update to the actual wpa_supplicant
-		 * interface state.
-		 */
-		wpas_iface_get_props (self);
-	} else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
-		/* Cancel all pending calls when going down */
-		nm_call_store_clear (priv->other_pcalls);
-		nm_call_store_clear (priv->assoc_pcalls);
-
-		/* Disconnect supplicant manager state listeners since we're done */
-		if (priv->smgr_avail_id) {
-			g_signal_handler_disconnect (priv->smgr, priv->smgr_avail_id);
-			priv->smgr_avail_id = 0;
+		if (priv->other_cancellable) {
+			g_warn_if_fail (priv->other_cancellable == NULL);
+			g_cancellable_cancel (priv->other_cancellable);
+			g_clear_object (&priv->other_cancellable);
 		}
+		priv->other_cancellable = g_cancellable_new ();
+	} else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
+		if (priv->init_cancellable)
+			g_cancellable_cancel (priv->init_cancellable);
+		g_clear_object (&priv->init_cancellable);
 
-		if (priv->iface_proxy) {
-			dbus_g_proxy_disconnect_signal (priv->iface_proxy,
-			                                "PropertiesChanged",
-			                                G_CALLBACK (wpas_iface_properties_changed),
-			                                self);
-			dbus_g_proxy_disconnect_signal (priv->iface_proxy,
-			                                "ScanDone",
-			                                G_CALLBACK (wpas_iface_scan_done),
-			                                self);
-			dbus_g_proxy_disconnect_signal (priv->iface_proxy,
-			                                "BSSAdded",
-			                                G_CALLBACK (wpas_iface_bss_added),
-			                                self);
-			dbus_g_proxy_disconnect_signal (priv->iface_proxy,
-			                                "BSSRemoved",
-			                                G_CALLBACK (wpas_iface_bss_removed),
-			                                self);
-		}
+		if (priv->other_cancellable)
+			g_cancellable_cancel (priv->other_cancellable);
+		g_clear_object (&priv->other_cancellable);
+
+		if (priv->iface_proxy)
+			g_signal_handlers_disconnect_by_data (priv->iface_proxy, self);
 	}
 
 	priv->state = new_state;
@@ -348,6 +250,34 @@ set_state (NMSupplicantInterface *self, guint32 new_state)
 	               priv->disconnect_reason);
 }
 
+static int
+wpas_state_string_to_enum (const char *str_state)
+{
+	if (!strcmp (str_state, "interface_disabled"))
+		return NM_SUPPLICANT_INTERFACE_STATE_DISABLED;
+	else if (!strcmp (str_state, "disconnected"))
+		return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED;
+	else if (!strcmp (str_state, "inactive"))
+		return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE;
+	else if (!strcmp (str_state, "scanning"))
+		return NM_SUPPLICANT_INTERFACE_STATE_SCANNING;
+	else if (!strcmp (str_state, "authenticating"))
+		return NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING;
+	else if (!strcmp (str_state, "associating"))
+		return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING;
+	else if (!strcmp (str_state, "associated"))
+		return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED;
+	else if (!strcmp (str_state, "4way_handshake"))
+		return NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE;
+	else if (!strcmp (str_state, "group_handshake"))
+		return NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE;
+	else if (!strcmp (str_state, "completed"))
+		return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED;
+
+	nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant state '%s'", str_state);
+	return -1;
+}
+
 static void
 set_state_from_string (NMSupplicantInterface *self, const char *new_state)
 {
@@ -396,107 +326,36 @@ nm_supplicant_interface_get_last_scan_time (NMSupplicantInterface *self)
 	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->last_scan;
 }
 
-static void
-wpas_iface_scan_done (DBusGProxy *proxy,
-                      gboolean success,
-                      gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	/* Cache last scan completed time */
-	priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
-	g_signal_emit (self, signals[SCAN_DONE], 0, success);
-}
+#define MATCH_PROPERTY(p, n, v, t) (!strcmp (p, n) && g_variant_is_of_type (v, t))
 
 static void
-parse_capabilities (NMSupplicantInterface *self, GHashTable *props)
+parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities)
 {
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GValue *value;
 	gboolean have_active = FALSE, have_ssid = FALSE;
+	gint32 max_scan_ssids = -1;
+	const char **array;
 
-	g_return_if_fail (props != NULL);
-
-	value = g_hash_table_lookup (props, "Scan");
-	if (value && G_VALUE_HOLDS (value, G_TYPE_STRV)) {
-		const char **vals = g_value_get_boxed (value);
-		const char **iter = vals;
+	g_return_if_fail (capabilities && g_variant_is_of_type (capabilities, G_VARIANT_TYPE_VARDICT));
 
-		while (iter && *iter && (!have_active || !have_ssid)) {
-			if (g_strcmp0 (*iter, "active") == 0)
-				have_active = TRUE;
-			else if (g_strcmp0 (*iter, "ssid") == 0)
-				have_ssid = TRUE;
-			iter++;
-		}
+	if (g_variant_lookup (capabilities, "Scan", "^a&s", &array)) {
+		if (_nm_utils_string_in_list ("active", array))
+			have_active = TRUE;
+		if (_nm_utils_string_in_list ("ssid", array))
+			have_ssid = TRUE;
+		g_free (array);
 	}
 
-	value = g_hash_table_lookup (props, "MaxScanSSID");
-	if (value && G_VALUE_HOLDS (value, G_TYPE_INT)) {
+	if (g_variant_lookup (capabilities, "MaxScanSSID", "i", &max_scan_ssids)) {
 		/* We need active scan and SSID probe capabilities to care about MaxScanSSIDs */
-		if (have_active && have_ssid) {
+		if (max_scan_ssids > 0 && have_active && have_ssid) {
 			/* wpa_supplicant's WPAS_MAX_SCAN_SSIDS value is 16, but for speed
 			 * and to ensure we don't disclose too many SSIDs from the hidden
 			 * list, we'll limit to 5.
 			 */
-			priv->max_scan_ssids = CLAMP (g_value_get_int (value), 0, 5);
+			priv->max_scan_ssids = CLAMP (max_scan_ssids, 0, 5);
 			nm_log_info (LOGD_SUPPLICANT, "(%s) supports %d scan SSIDs",
-			             priv->dev, priv->max_scan_ssids);
-		}
-	}
-}
-
-static void
-wpas_iface_properties_changed (DBusGProxy *proxy,
-                               GHashTable *props,
-                               gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GValue *value;
-
-	value = g_hash_table_lookup (props, "Scanning");
-	if (value && G_VALUE_HOLDS_BOOLEAN (value))
-		set_scanning (self, g_value_get_boolean (value));
-
-	value = g_hash_table_lookup (props, "State");
-	if (value && G_VALUE_HOLDS_STRING (value)) {
-		if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) {
-			/* Only transition to actual wpa_supplicant interface states (ie,
-			 * anything > READY) after the NMSupplicantInterface has had a
-			 * chance to initialize, which is signalled by entering the READY
-			 * state.
-			 */
-			set_state_from_string (self, g_value_get_string (value));
-		}
-	}
-
-	value = g_hash_table_lookup (props, "BSSs");
-	if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH)) {
-		GPtrArray *paths = g_value_get_boxed (value);
-		int i;
-
-		for (i = 0; paths && (i < paths->len); i++)
-			handle_new_bss (self, g_ptr_array_index (paths, i), NULL);
-	}
-
-	value = g_hash_table_lookup (props, "Capabilities");
-	if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_MAP_OF_VARIANT))
-		parse_capabilities (self, g_value_get_boxed (value));
-
-	/* Disconnect reason is currently only given for deauthentication events,
-	 * not disassociation; currently they are IEEE 802.11 "reason codes",
-	 * defined by (IEEE 802.11-2007, 7.3.1.7, Table 7-22).  Any locally caused
-	 * deauthentication will be negative, while authentications caused by the
-	 * AP will be positive.
-	 */
-	value = g_hash_table_lookup (props, "DisconnectReason");
-	if (value && G_VALUE_HOLDS (value, G_TYPE_INT)) {
-		priv->disconnect_reason = g_value_get_int (value);
-		if (priv->disconnect_reason != 0) {
-			nm_log_warn (LOGD_SUPPLICANT, "Connection disconnected (reason %d)",
-			             priv->disconnect_reason);
+				         priv->dev, priv->max_scan_ssids);
 		}
 	}
 }
@@ -513,43 +372,6 @@ iface_check_ready (NMSupplicantInterface *self)
 	}
 }
 
-static void
-iface_get_props_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GHashTable *props = NULL;
-	GError *error = NULL;
-
-	nm_call_store_remove (priv->other_pcalls, proxy, call_id);
-	if (dbus_g_proxy_end_call (proxy, call_id, &error,
-	                           DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-	                           G_TYPE_INVALID)) {
-		wpas_iface_properties_changed (NULL, props, self);
-		g_hash_table_destroy (props);
-	} else {
-		nm_log_warn (LOGD_SUPPLICANT, "could not get interface properties: %s.",
-		             error && error->message ? error->message : "(unknown)");
-		g_clear_error (&error);
-	}
-	iface_check_ready (self);
-}
-
-static void
-wpas_iface_get_props (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGProxyCall *call;
-
-	call = dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
-	                                iface_get_props_cb,
-	                                self,
-	                                NULL,
-	                                G_TYPE_STRING, WPAS_DBUS_IFACE_INTERFACE,
-	                                G_TYPE_INVALID);
-	nm_call_store_add (priv->other_pcalls, priv->props_proxy, call);
-}
-
 gboolean
 nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
                                            const char *field,
@@ -557,6 +379,7 @@ nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
                                            GError **error)
 {
 	NMSupplicantInterfacePrivate *priv;
+	gs_unref_variant GVariant *reply = NULL;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
 	g_return_val_if_fail (field != NULL, FALSE);
@@ -567,74 +390,62 @@ nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
 
 	/* Need a network block object path */
 	g_return_val_if_fail (priv->net_path, FALSE);
-	return dbus_g_proxy_call_with_timeout (priv->iface_proxy, "NetworkReply",
-	                                       5000,
-	                                       error,
-	                                       DBUS_TYPE_G_OBJECT_PATH, priv->net_path,
-	                                       G_TYPE_STRING, field,
-	                                       G_TYPE_STRING, value,
-	                                       G_TYPE_INVALID);
+	reply = g_dbus_proxy_call_sync (priv->iface_proxy,
+	                                "NetworkReply",
+	                                g_variant_new ("(oss)",
+	                                               priv->net_path,
+	                                               field,
+	                                               value),
+	                                G_DBUS_CALL_FLAGS_NONE,
+	                                5000,
+	                                NULL,
+	                                error);
+	/* reply will be unrefed when function exits */
+	return !!reply;
 }
 
-static void
-wpas_iface_network_request (DBusGProxy *proxy,
-                            const char *object_path,
-                            const char *field,
-                            const char *message,
-                            gpointer user_data)
+static gboolean
+_dbus_error_has_name (GError *error, const char *dbus_error_name)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	g_return_if_fail (priv->has_credreq == TRUE);
-	g_return_if_fail (priv->net_path != NULL);
-	g_return_if_fail (g_strcmp0 (object_path, priv->net_path) == 0);
+	gs_free char *error_name = NULL;
+	gboolean is_error = FALSE;
 
-	g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message);
+	if (error && g_dbus_error_is_remote_error (error)) {
+		error_name = g_dbus_error_get_remote_error (error);
+		is_error = !g_strcmp0 (error_name, dbus_error_name);
+	}
+	return is_error;
 }
 
 static void
-iface_check_netreply_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *error = NULL;
-
-	nm_call_store_remove (priv->other_pcalls, proxy, call_id);
-	if (   dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)
-	    || dbus_g_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs")) {
-		/* We know NetworkReply is supported if the NetworkReply method returned
-		 * successfully (which is unexpected since we sent a bogus network
-		 * object path) or if we got an "InvalidArgs" (which indicates NetworkReply
-		 * is supported).  We know it's not supported if we get an
-		 * "UnknownMethod" error.
-		 */
-		priv->has_credreq = TRUE;
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_unref_variant GVariant *variant = NULL;
+	gs_free_error GError *error = NULL;
+
+	/* We know NetworkReply is supported if the NetworkReply method returned
+	 * successfully (which is unexpected since we sent a bogus network
+	 * object path) or if we got an "InvalidArgs" (which indicates NetworkReply
+	 * is supported).  We know it's not supported if we get an
+	 * "UnknownMethod" error.
+	 */
 
-		nm_log_dbg (LOGD_SUPPLICANT, "Supplicant %s network credentials requests",
-			        priv->has_credreq ? "supports" : "does not support");
-	}
-	g_clear_error (&error);
+	variant = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
 
-	iface_check_ready (self);
-}
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-static void
-wpas_iface_check_network_reply (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGProxyCall *call;
+	if (variant || _dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs"))
+		priv->has_credreq = TRUE;
 
-	priv->ready_count++;
-	call = dbus_g_proxy_begin_call (priv->iface_proxy, "NetworkReply",
-	                                iface_check_netreply_cb,
-	                                self,
-	                                NULL,
-	                                DBUS_TYPE_G_OBJECT_PATH, "/foobaraasdfasdf",
-	                                G_TYPE_STRING, "foobar",
-	                                G_TYPE_STRING, "foobar",
-	                                G_TYPE_INVALID);
-	nm_call_store_add (priv->other_pcalls, priv->iface_proxy, call);
+	nm_log_dbg (LOGD_SUPPLICANT, "Supplicant %s network credentials requests",
+	            priv->has_credreq ? "supports" : "does not support");
+
+	iface_check_ready (self);
 }
 
 ApSupport
@@ -657,207 +468,271 @@ nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
 }
 
 static void
-iface_check_ap_mode_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	char *data;
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_unref_variant GVariant *variant = NULL;
+	gs_free_error GError *error = NULL;
+	const char *data;
 
 	/* The ProbeRequest method only exists if AP mode has been enabled */
-	nm_call_store_remove (priv->other_pcalls, proxy, call_id);
-	if (dbus_g_proxy_end_call (proxy, call_id, NULL,
-	                           G_TYPE_STRING,
-	                           &data,
-	                           G_TYPE_INVALID)) {
-		if (data && strstr (data, "ProbeRequest"))
+	variant = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(s)"))) {
+		g_variant_get (variant, "(&s)", &data);
+		if (strstr (data, "ProbeRequest"))
 			priv->ap_support = AP_SUPPORT_YES;
-		g_free (data);
 	}
 
 	iface_check_ready (self);
 }
 
+#define MATCH_SIGNAL(s, n, v, t) (!strcmp (s, n) && g_variant_is_of_type (v, t))
+
 static void
-wpas_iface_check_ap_mode (NMSupplicantInterface *self)
+signal_cb (GDBusProxy  *proxy,
+           const gchar *sender,
+           const gchar *signal,
+           GVariant    *args,
+           gpointer     user_data)
 {
+	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGProxyCall *call;
+	const char *path, *field, *message;
+	gboolean success;
 
-	priv->ready_count++;
+	if (MATCH_SIGNAL (signal, "ScanDone", args, G_VARIANT_TYPE ("(b)"))) {
+		/* Cache last scan completed time */
+		priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
 
-	/* If the global supplicant capabilities property is not present, we can
-	 * fall back to checking whether the ProbeRequest method is supported.  If
-	 * neither of these works we have no way of determining if AP mode is
-	 * supported or not.  hostap 1.0 and earlier don't support either of these.
-	 */
-	call = dbus_g_proxy_begin_call (priv->introspect_proxy, "Introspect",
-	                                iface_check_ap_mode_cb,
-	                                self,
-	                                NULL,
-	                                G_TYPE_INVALID);
-	nm_call_store_add (priv->other_pcalls, priv->introspect_proxy, call);
+		g_variant_get (args, "(b)", &success);
+		g_signal_emit (self, signals[SCAN_DONE], 0, success);
+	} else if (MATCH_SIGNAL (signal, "BSSAdded", args, G_VARIANT_TYPE ("(oa{sv})"))) {
+		if (priv->scanning)
+			priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
+
+		g_variant_get (args, "(&oa{sv})", &path, NULL);
+		handle_new_bss (self, path);
+	} else if (MATCH_SIGNAL (signal, "BSSRemoved", args, G_VARIANT_TYPE ("(o)"))) {
+		g_variant_get (args, "(&o)", &path);
+		g_signal_emit (self, signals[BSS_REMOVED], 0, path);
+		g_hash_table_remove (priv->bss_proxies, path);
+	} else if (MATCH_SIGNAL (signal, "NetworkRequest", args, G_VARIANT_TYPE ("(oss)"))) {
+		g_variant_get (args, "(&o&s&s)", &path, &field, &message);
+		if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path))
+			g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message);
+	}
 }
 
 static void
-interface_add_done (NMSupplicantInterface *self, char *path)
+props_changed_cb (GDBusProxy *proxy,
+                  GVariant *changed_properties,
+                  GStrv invalidated_properties,
+                  gpointer user_data)
 {
+	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	const char *s, **array, **iter;
+	gboolean b = FALSE;
+	gint32 i32;
+	GVariant *v;
+
+	if (g_variant_lookup (changed_properties, "Scanning", "b", &b))
+		set_scanning (self, b);
+
+	if (   g_variant_lookup (changed_properties, "State", "&s", &s)
+	    && priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) {
+		/* Only transition to actual wpa_supplicant interface states (ie,
+		 * anything > READY) after the NMSupplicantInterface has had a
+		 * chance to initialize, which is signalled by entering the READY
+		 * state.
+		 */
+		set_state_from_string (self, s);
+	}
 
-	nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev);
+	if (g_variant_lookup (changed_properties, "BSSs", "^a&s", &array)) {
+		iter = array;
+		while (*iter)
+			handle_new_bss (self, *iter++);
+		g_free (array);
+	}
 
-	priv->object_path = path;
-
-	priv->iface_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
-	                                               WPAS_DBUS_SERVICE,
-	                                               path,
-	                                               WPAS_DBUS_IFACE_INTERFACE);
-
-	dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED,
-	                                   G_TYPE_NONE,
-	                                   DBUS_TYPE_G_MAP_OF_VARIANT,
-	                                   G_TYPE_INVALID);
-	dbus_g_proxy_add_signal (priv->iface_proxy, "PropertiesChanged",
-	                         DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->iface_proxy, "PropertiesChanged",
-	                             G_CALLBACK (wpas_iface_properties_changed),
-	                             self, NULL);
-
-	dbus_g_proxy_add_signal (priv->iface_proxy, "ScanDone",
-	                         G_TYPE_BOOLEAN, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanDone",
-	                             G_CALLBACK (wpas_iface_scan_done),
-	                             self,
-	                             NULL);
-
-	dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
-	                                   G_TYPE_NONE,
-	                                   DBUS_TYPE_G_OBJECT_PATH, DBUS_TYPE_G_MAP_OF_VARIANT,
-	                                   G_TYPE_INVALID);
-	dbus_g_proxy_add_signal (priv->iface_proxy, "BSSAdded", 
-	                         DBUS_TYPE_G_OBJECT_PATH, DBUS_TYPE_G_MAP_OF_VARIANT,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->iface_proxy, "BSSAdded",
-	                             G_CALLBACK (wpas_iface_bss_added),
-	                             self,
-	                             NULL);
-
-	dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED,
-	                                   G_TYPE_NONE,
-	                                   DBUS_TYPE_G_OBJECT_PATH,
-	                                   G_TYPE_INVALID);
-	dbus_g_proxy_add_signal (priv->iface_proxy, "BSSRemoved",
-	                         DBUS_TYPE_G_OBJECT_PATH,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->iface_proxy, "BSSRemoved",
-	                             G_CALLBACK (wpas_iface_bss_removed),
-	                             self,
-	                             NULL);
-
-	dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
-	                                   G_TYPE_NONE,
-	                                   DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_STRING,
-	                                   G_TYPE_INVALID);
-	dbus_g_proxy_add_signal (priv->iface_proxy, "NetworkRequest",
-	                         DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_STRING,
-	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->iface_proxy, "NetworkRequest",
-	                             G_CALLBACK (wpas_iface_network_request),
-	                             self,
-	                             NULL);
-
-	priv->introspect_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
-	                                                    WPAS_DBUS_SERVICE,
-	                                                    priv->object_path,
-	                                                    DBUS_INTERFACE_INTROSPECTABLE);
-
-	priv->props_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
-	                                               WPAS_DBUS_SERVICE,
-	                                               path,
-	                                               DBUS_INTERFACE_PROPERTIES);
-	/* Get initial properties and check whether NetworkReply is supported */
-	priv->ready_count = 1;
-	wpas_iface_get_props (self);
+	v = g_variant_lookup_value (changed_properties, "Capabilities", G_VARIANT_TYPE_VARDICT);
+	if (v) {
+		parse_capabilities (self, v);
+		g_variant_unref (v);
+	}
 
-	/* These two increment ready_count themselves */
-	wpas_iface_check_network_reply (self);
-	if (priv->ap_support == AP_SUPPORT_UNKNOWN)
-		wpas_iface_check_ap_mode (self);
+	if (g_variant_lookup (changed_properties, "DisconnectReason", "i", &i32)) {
+		/* Disconnect reason is currently only given for deauthentication events,
+		 * not disassociation; currently they are IEEE 802.11 "reason codes",
+		 * defined by (IEEE 802.11-2007, 7.3.1.7, Table 7-22).  Any locally caused
+		 * deauthentication will be negative, while authentications caused by the
+		 * AP will be positive.
+		 */
+		priv->disconnect_reason = i32;
+		if (priv->disconnect_reason != 0) {
+			nm_log_warn (LOGD_SUPPLICANT, "Connection disconnected (reason %d)",
+				         priv->disconnect_reason);
+		}
+	}
 }
 
 static void
-interface_get_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *error = NULL;
-	char *path = NULL;
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_free_error GError *error = NULL;
 
-	nm_call_store_remove (priv->other_pcalls, proxy, call_id);
-	if (dbus_g_proxy_end_call (proxy, call_id, &error,
-	                           DBUS_TYPE_G_OBJECT_PATH, &path,
-	                           G_TYPE_INVALID)) {
-		interface_add_done (self, path);
-	} else {
-		nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s",
-		            priv->dev, error->message);
-		g_clear_error (&error);
-		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
+		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+			nm_log_warn (LOGD_SUPPLICANT, "Failed to acquire wpa_supplicant interface proxy: (%s)", error->message);
+			set_state (NM_SUPPLICANT_INTERFACE (user_data), NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+		}
+		return;
+	}
+
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	g_signal_connect (priv->iface_proxy, "g-signal", G_CALLBACK (signal_cb), self);
+
+	/* Check whether NetworkReply and AP mode are supported */
+	priv->ready_count = 1;
+	g_dbus_proxy_call (priv->iface_proxy,
+	                   "NetworkReply",
+	                   g_variant_new ("(oss)",
+	                                  "/fff",
+	                                  "foobar",
+	                                  "foobar"),
+	                   G_DBUS_CALL_FLAGS_NONE,
+	                   -1,
+	                   priv->init_cancellable,
+	                   (GAsyncReadyCallback) iface_check_netreply_cb,
+	                   self);
+
+	if (priv->ap_support == AP_SUPPORT_UNKNOWN) {
+		/* If the global supplicant capabilities property is not present, we can
+		 * fall back to checking whether the ProbeRequest method is supported.  If
+		 * neither of these works we have no way of determining if AP mode is
+		 * supported or not.  hostap 1.0 and earlier don't support either of these.
+		 */
+		priv->ready_count++;
+		g_dbus_proxy_call (priv->iface_proxy,
+		                   "org.freedesktop.DBus.Introspectable.Introspect",
+		                   NULL,
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1,
+		                   priv->init_cancellable,
+		                   (GAsyncReadyCallback) iface_check_ap_mode_cb,
+		                   self);
 	}
 }
 
 static void
-interface_get (NMSupplicantInterface *self)
+interface_add_done (NMSupplicantInterface *self, const char *path)
 {
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGProxyCall *call;
 
-	call = dbus_g_proxy_begin_call (priv->wpas_proxy, "GetInterface",
-	                                interface_get_cb,
-	                                self,
-	                                NULL,
-	                                G_TYPE_STRING, priv->dev,
-	                                G_TYPE_INVALID);
-	nm_call_store_add (priv->other_pcalls, priv->wpas_proxy, call);
+	nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev);
+
+	priv->object_path = g_strdup (path);
+	priv->iface_proxy = g_object_new (G_TYPE_DBUS_PROXY,
+	                                  "g-bus-type", G_BUS_TYPE_SYSTEM,
+	                                  "g-flags", G_DBUS_PROXY_FLAGS_NONE,
+	                                  "g-name", WPAS_DBUS_SERVICE,
+	                                  "g-object-path", priv->object_path,
+	                                  "g-interface-name", WPAS_DBUS_IFACE_INTERFACE,
+	                                  NULL);
+	g_signal_connect (priv->iface_proxy, "g-properties-changed", G_CALLBACK (props_changed_cb), self);
+	g_async_initable_init_async (G_ASYNC_INITABLE (priv->iface_proxy),
+	                             G_PRIORITY_DEFAULT,
+	                             priv->init_cancellable,
+	                             (GAsyncReadyCallback) on_iface_proxy_acquired,
+	                             self);
 }
 
 static void
-interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *error = NULL;
-	char *path = NULL;
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_unref_variant GVariant *variant = NULL;
+	gs_free_error GError *error = NULL;
+	char *path;
 
-	nm_call_store_remove (priv->other_pcalls, proxy, call_id);
-	if (dbus_g_proxy_end_call (proxy, call_id, &error,
-	                           DBUS_TYPE_G_OBJECT_PATH, &path,
-	                           G_TYPE_INVALID)) {
+	variant = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) {
+		g_variant_get (variant, "(o)", &path);
 		interface_add_done (self, path);
+		g_free (path);
 	} else {
-		if (dbus_g_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) {
-			/* Interface already added, just get its object path */
-			interface_get (self);
-		} else if (   g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)
-		           || g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SPAWN_EXEC_FAILED)
-		           || g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SPAWN_FORK_FAILED)
-		           || g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SPAWN_FAILED)
-		           || g_error_matches (error, DBUS_GERROR, DBUS_GERROR_TIMEOUT)
-		           || g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NO_REPLY)
-		           || g_error_matches (error, DBUS_GERROR, DBUS_GERROR_TIMED_OUT)
-		           || dbus_g_error_has_name (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) {
-			/* Supplicant wasn't running and could not be launched via service
-			 * activation.  Wait for it to start by moving back to the INIT
-			 * state.
-			 */
-			nm_log_dbg (LOGD_SUPPLICANT, "(%s): failed to activate supplicant: %s",
-			            priv->dev, error->message);
-			set_state (self, NM_SUPPLICANT_INTERFACE_STATE_INIT);
-		} else {
-			nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s",
-			            priv->dev, error->message);
-			set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
-		}
-		g_clear_error (&error);
+		nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message);
+		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+	}
+}
+
+static void
+interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
+{
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_free_error GError *error = NULL;
+	gs_unref_variant GVariant *variant = NULL;
+	char *path;
+
+	variant = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) {
+		g_variant_get (variant, "(o)", &path);
+		interface_add_done (self, path);
+		g_free (path);
+	} else if (_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) {
+		/* Interface already added, just get its object path */
+		g_dbus_proxy_call (priv->wpas_proxy,
+		                   "GetInterface",
+		                   g_variant_new ("(s)", priv->dev),
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1,
+		                   priv->init_cancellable,
+		                   (GAsyncReadyCallback) interface_get_cb,
+		                   self);
+	} else if (   g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)
+	           || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_EXEC_FAILED)
+	           || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FORK_FAILED)
+	           || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FAILED)
+	           || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMEOUT)
+	           || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NO_REPLY)
+	           || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMED_OUT)
+	           || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) {
+		/* Supplicant wasn't running and could not be launched via service
+		 * activation.  Wait for it to start by moving back to the INIT
+		 * state.
+		 */
+		nm_log_dbg (LOGD_SUPPLICANT, "(%s): failed to activate supplicant: %s",
+		            priv->dev, error->message);
+		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_INIT);
+	} else {
+		nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", priv->dev, error->message);
+		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
 	}
 }
 
@@ -868,59 +743,90 @@ interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data
 #endif
 
 static void
-interface_add (NMSupplicantInterface *self, gboolean is_wireless)
+on_wpas_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGProxyCall *call;
-	GHashTable *hash;
-	GValue driver = G_VALUE_INIT;
-	GValue ifname = G_VALUE_INIT;
-
-	/* Can only start the interface from INIT state */
-	g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT);
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_free_error GError *error = NULL;
+	GDBusProxy *wpas_proxy;
+	GVariantBuilder props;
+
+	wpas_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
+	if (!wpas_proxy) {
+		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+			nm_log_warn (LOGD_SUPPLICANT, "Failed to acquire wpa_supplicant proxy: (%s)",
+			             error ? error->message : "unknown");
+			set_state (NM_SUPPLICANT_INTERFACE (user_data), NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+		}
+		return;
+	}
 
-	nm_log_dbg (LOGD_SUPPLICANT, "(%s): adding interface to supplicant", priv->dev);
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	/* Move to starting to prevent double-calls of interface_add() */
-	set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING);
+	priv->wpas_proxy = wpas_proxy;
 
 	/* Try to add the interface to the supplicant.  If the supplicant isn't
 	 * running, this will start it via D-Bus activation and return the response
 	 * when the supplicant has started.
 	 */
 
-	hash = g_hash_table_new (g_str_hash, g_str_equal);
+	g_variant_builder_init (&props, G_VARIANT_TYPE_VARDICT);
+	g_variant_builder_add (&props, "{sv}",
+	                       "Driver",
+	                       g_variant_new_string (priv->is_wireless ? DEFAULT_WIFI_DRIVER : "wired"));
+	g_variant_builder_add (&props, "{sv}",
+	                       "Ifname",
+	                       g_variant_new_string (priv->dev));
+
+	g_dbus_proxy_call (priv->wpas_proxy,
+	                   "CreateInterface",
+	                   g_variant_new ("(a{sv})", &props),
+	                   G_DBUS_CALL_FLAGS_NONE,
+	                   -1,
+	                   priv->init_cancellable,
+	                   (GAsyncReadyCallback) interface_add_cb,
+	                   self);
+}
 
-	g_value_init (&driver, G_TYPE_STRING);
-	g_value_set_string (&driver, is_wireless ? DEFAULT_WIFI_DRIVER : "wired");
-	g_hash_table_insert (hash, "Driver", &driver);
+static void
+interface_add (NMSupplicantInterface *self, gboolean is_wireless)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	g_value_init (&ifname, G_TYPE_STRING);
-	g_value_set_string (&ifname, priv->dev);
-	g_hash_table_insert (hash, "Ifname", &ifname);
+	/* Can only start the interface from INIT state */
+	g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT);
 
-	call = dbus_g_proxy_begin_call (priv->wpas_proxy, "CreateInterface",
-	                                interface_add_cb,
-	                                self,
-	                                NULL,
-	                                DBUS_TYPE_G_MAP_OF_VARIANT, hash,
-	                                G_TYPE_INVALID);
-	nm_call_store_add (priv->other_pcalls, priv->wpas_proxy, call);
+	nm_log_dbg (LOGD_SUPPLICANT, "(%s): adding interface to supplicant", priv->dev);
+
+	priv->is_wireless = is_wireless;
+
+	/* Move to starting to prevent double-calls of interface_add() */
+	set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING);
 
-	g_hash_table_destroy (hash);
-	g_value_unset (&driver);
-	g_value_unset (&ifname);
+	g_warn_if_fail (priv->init_cancellable == NULL);
+	g_clear_object (&priv->init_cancellable);
+	priv->init_cancellable = g_cancellable_new ();
+
+	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+	                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+	                            G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+	                          NULL,
+	                          WPAS_DBUS_SERVICE,
+	                          WPAS_DBUS_PATH,
+	                          WPAS_DBUS_INTERFACE,
+	                          priv->init_cancellable,
+	                          (GAsyncReadyCallback) on_wpas_proxy_acquired,
+	                          self);
 }
 
-static void
-smgr_avail_cb (NMSupplicantManager *smgr,
-               GParamSpec *pspec,
-               gpointer user_data)
+void
+nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
+                                                  gboolean available)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data);
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	if (nm_supplicant_manager_available (smgr)) {
+	if (available) {
 		/* This can happen if the supplicant couldn't be activated but
 		 * for some reason was started after the activation failure.
 		 */
@@ -933,27 +839,14 @@ smgr_avail_cb (NMSupplicantManager *smgr,
 }
 
 static void
-remove_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
-{
-	GError *error = NULL;
-
-	if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) {
-		nm_log_dbg (LOGD_SUPPLICANT, "Couldn't remove network from supplicant interface: %s.",
-		             error && error->message ? error->message : "(unknown)");
-		g_clear_error (&error);
-	}
-}
-
-static void
-disconnect_cb  (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+log_result_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	GError *error = NULL;
+	gs_unref_variant GVariant *reply = NULL;
+	gs_free_error GError *error = NULL;
 
-	if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) {
-		nm_log_warn (LOGD_SUPPLICANT, "Couldn't disconnect supplicant interface: %s.",
-		             error && error->message ? error->message : "(unknown)");
-		g_clear_error (&error);
-	}
+	reply = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (!reply && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		nm_log_warn (LOGD_SUPPLICANT, "Failed to %s: %s.", error->message, (char *) user_data);
 }
 
 void
@@ -965,10 +858,11 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
 
 	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	/* Clear and cancel all pending calls related to a prior
-	 * connection attempt.
-	 */
-	nm_call_store_clear (priv->assoc_pcalls);
+	/* Cancel all pending calls related to a prior connection attempt */
+	if (priv->assoc_cancellable) {
+		g_cancellable_cancel (priv->assoc_cancellable);
+		g_clear_object (&priv->assoc_cancellable);
+	}
 
 	/* Don't do anything if there is no connection to the supplicant yet. */
 	if (!priv->iface_proxy)
@@ -977,36 +871,41 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
 	/* Disconnect from the current AP */
 	if (   (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
 	    && (priv->state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)) {
-		dbus_g_proxy_begin_call (priv->iface_proxy, "Disconnect",
-			                     disconnect_cb,
-			                     NULL, NULL,
-			                     G_TYPE_INVALID);
+		g_dbus_proxy_call (priv->iface_proxy,
+		                   "Disconnect",
+		                   NULL,
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1,
+		                   NULL,
+		                   (GAsyncReadyCallback) log_result_cb,
+		                   "disconnect");
 	}
 
 	/* Remove any network that was added by NetworkManager */
 	if (priv->net_path) {
-		dbus_g_proxy_begin_call (priv->iface_proxy, "RemoveNetwork",
-		                         remove_network_cb,
-		                         NULL, NULL,
-		                         DBUS_TYPE_G_OBJECT_PATH, priv->net_path,
-		                         G_TYPE_INVALID);
+		g_dbus_proxy_call (priv->iface_proxy,
+		                   "RemoveNetwork",
+		                   g_variant_new ("(o)", priv->net_path),
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1,
+		                   priv->other_cancellable,
+		                   (GAsyncReadyCallback) log_result_cb,
+		                   "remove network");
 		g_free (priv->net_path);
 		priv->net_path = NULL;
 	}
 }
 
 static void
-select_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+select_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *err = NULL;
+	gs_unref_variant GVariant *reply = NULL;
+	gs_free_error GError *err = NULL;
 
-	nm_call_store_remove (priv->assoc_pcalls, proxy, call_id);
-	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) {
+	reply = g_dbus_proxy_call_finish (proxy, result, &err);
+	if (!reply && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 		nm_log_warn (LOGD_SUPPLICANT, "Couldn't select network config: %s.", err->message);
-		emit_error_helper (self, err);
-		g_error_free (err);
+		emit_error_helper (NM_SUPPLICANT_INTERFACE (user_data), err);
 	}
 }
 
@@ -1014,111 +913,136 @@ static void
 call_select_network (NMSupplicantInterface *self)
 {
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGProxyCall *call;
 
 	/* We only select the network after all blobs (if any) have been set */
 	if (priv->blobs_left == 0) {
-		call = dbus_g_proxy_begin_call (priv->iface_proxy, "SelectNetwork",
-		                                select_network_cb,
-		                                self,
-		                                NULL,
-		                                DBUS_TYPE_G_OBJECT_PATH, priv->net_path,
-		                                G_TYPE_INVALID);
-		nm_call_store_add (priv->assoc_pcalls, priv->iface_proxy, call);
+		g_dbus_proxy_call (priv->iface_proxy,
+		                   "SelectNetwork",
+		                   g_variant_new ("(o)", priv->net_path),
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1,
+		                   priv->assoc_cancellable,
+		                   (GAsyncReadyCallback) select_network_cb,
+		                   self);
 	}
 }
 
 static void
-add_blob_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+add_blob_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *err = NULL;
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_unref_variant GVariant *reply = NULL;
+	gs_free_error GError *err = NULL;
 
-	priv->blobs_left--;
+	reply = g_dbus_proxy_call_finish (proxy, result, &err);
+	if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	nm_call_store_remove (priv->assoc_pcalls, proxy, call_id);
-	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) {
+	priv->blobs_left--;
+	if (reply)
+		call_select_network (self);
+	else {
 		nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network certificates: %s.", err->message);
 		emit_error_helper (self, err);
-		g_error_free (err);
-	} else
-		call_select_network (self);
+	}
 }
 
 static void
-add_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *err = NULL;
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_unref_variant GVariant *reply = NULL;
+	gs_free_error GError *error = NULL;
 	GHashTable *blobs;
 	GHashTableIter iter;
-	gpointer name, data;
-	DBusGProxyCall *call;
+	const char *blob_name;
+	GByteArray *blob_data;
+
+	reply = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
+
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	if (reply && !g_variant_is_of_type (reply, G_VARIANT_TYPE ("(o)"))) {
+		error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
+		                     "Unexpected AddNetwork reply type %s",
+		                     g_variant_get_type_string (reply));
+	}
 
 	g_free (priv->net_path);
 	priv->net_path = NULL;
 
-	nm_call_store_remove (priv->assoc_pcalls, proxy, call_id);
-	if (!dbus_g_proxy_end_call (proxy, call_id, &err,
-	                            DBUS_TYPE_G_OBJECT_PATH, &priv->net_path,
-	                            G_TYPE_INVALID)) {
-		nm_log_warn (LOGD_SUPPLICANT, "Couldn't add a network to the supplicant interface: %s.",
-		             err->message);
-		emit_error_helper (self, err);
-		g_error_free (err);
+	if (error) {
+		nm_log_warn (LOGD_SUPPLICANT, "Adding network to supplicant failed: %s.", error->message);
+		emit_error_helper (self, error);
 		return;
 	}
 
-	/* Send blobs first; otherwise jump to sending the config settings */
+	g_variant_get (reply, "(o)", &priv->net_path);
+	g_assert (priv->net_path);
+
+	/* Send blobs first; otherwise jump to selecting the network */
 	blobs = nm_supplicant_config_get_blobs (priv->cfg);
 	priv->blobs_left = g_hash_table_size (blobs);
+
 	g_hash_table_iter_init (&iter, blobs);
-	while (g_hash_table_iter_next (&iter, &name, &data)) {
-		call = dbus_g_proxy_begin_call (priv->iface_proxy, "AddBlob",
-			                            add_blob_cb,
-			                            self,
-			                            NULL,
-			                            G_TYPE_STRING, name,
-			                            DBUS_TYPE_G_UCHAR_ARRAY, data,
-			                            G_TYPE_INVALID);
-		nm_call_store_add (priv->assoc_pcalls, priv->iface_proxy, call);
+	while (g_hash_table_iter_next (&iter, (gpointer) &blob_name, (gpointer) &blob_data)) {
+		g_dbus_proxy_call (priv->iface_proxy,
+		                   "AddBlob",
+		                   g_variant_new ("(s@ay)",
+		                                  blob_name,
+		                                  g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+		                                                             blob_data->data, blob_data->len, 1)),
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1,
+		                   priv->assoc_cancellable,
+		                   (GAsyncReadyCallback) add_blob_cb,
+		                   self);
 	}
 
 	call_select_network (self);
 }
 
 static void
-set_ap_scan_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *err = NULL;
-	DBusGProxyCall *call;
-	GHashTable *config_hash;
+	NMSupplicantInterface *self;
+	NMSupplicantInterfacePrivate *priv;
+	gs_unref_variant GVariant *reply = NULL;
+	gs_free_error GError *error = NULL;
+
+	reply = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
 
-	nm_call_store_remove (priv->assoc_pcalls, proxy, call_id);
-	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID)) {
+	self = NM_SUPPLICANT_INTERFACE (user_data);
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	if (!reply) {
 		nm_log_warn (LOGD_SUPPLICANT, "Couldn't send AP scan mode to the supplicant interface: %s.",
-		             err->message);
-		emit_error_helper (self, err);
-		g_error_free (err);
+		             error->message);
+		emit_error_helper (self, error);
 		return;
 	}
 
 	nm_log_info (LOGD_SUPPLICANT, "Config: set interface ap_scan to %d",
 	             nm_supplicant_config_get_ap_scan (priv->cfg));
 
-	config_hash = nm_supplicant_config_get_hash (priv->cfg);
-	call = dbus_g_proxy_begin_call (priv->iface_proxy, "AddNetwork",
-	                                add_network_cb,
-	                                self,
-	                                NULL,
-	                                DBUS_TYPE_G_MAP_OF_VARIANT, config_hash,
-	                                G_TYPE_INVALID);
-	g_hash_table_destroy (config_hash);
-	nm_call_store_add (priv->assoc_pcalls, priv->iface_proxy, call);
+	g_dbus_proxy_call (priv->iface_proxy,
+	                   "AddNetwork",
+	                   g_variant_new ("(@a{sv})", nm_supplicant_config_to_variant (priv->cfg)),
+	                   G_DBUS_CALL_FLAGS_NONE,
+	                   -1,
+	                   priv->assoc_cancellable,
+	                   (GAsyncReadyCallback) add_network_cb,
+	                   self);
 }
 
 gboolean
@@ -1126,8 +1050,6 @@ nm_supplicant_interface_set_config (NMSupplicantInterface *self,
                                     NMSupplicantConfig *cfg)
 {
 	NMSupplicantInterfacePrivate *priv;
-	DBusGProxyCall *call;
-	GValue value = G_VALUE_INIT;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
 
@@ -1143,103 +1065,75 @@ nm_supplicant_interface_set_config (NMSupplicantInterface *self,
 		return FALSE;
 	}
 
-	if (priv->cfg)
-		g_object_unref (priv->cfg);
-	priv->cfg = cfg;
-
-	if (cfg == NULL)
-		return TRUE;
-
-	g_object_ref (priv->cfg);
-
-	g_value_init (&value, G_TYPE_UINT);
-	g_value_set_uint (&value, nm_supplicant_config_get_ap_scan (priv->cfg));
-
-	call = dbus_g_proxy_begin_call (priv->props_proxy, "Set",
-	                                set_ap_scan_cb,
-	                                self,
-	                                NULL,
-	                                G_TYPE_STRING, WPAS_DBUS_IFACE_INTERFACE,
-	                                G_TYPE_STRING, "ApScan",
-	                                G_TYPE_VALUE, &value,
-	                                G_TYPE_INVALID);
-	nm_call_store_add (priv->assoc_pcalls, priv->props_proxy, call);
-
-	g_value_unset (&value);
-	return call != NULL;
-}
-
-static void
-scan_request_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GError *err = NULL;
-
-	nm_call_store_remove (priv->other_pcalls, proxy, call_id);
-	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_INVALID))
-		nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", err->message);
-
-	g_signal_emit (self, signals[SCAN_DONE], 0, err ? FALSE : TRUE);
-	g_clear_error (&err);
+	g_clear_object (&priv->cfg);
+	if (cfg) {
+		priv->cfg = g_object_ref (cfg);
+		g_dbus_proxy_call (priv->iface_proxy,
+		                   "org.freedesktop.DBus.Properties.Set",
+		                   g_variant_new ("(ssv)",
+		                                  WPAS_DBUS_IFACE_INTERFACE,
+		                                  "ApScan",
+		                                  g_variant_new_uint32 (nm_supplicant_config_get_ap_scan (priv->cfg))),
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   -1,
+		                   priv->assoc_cancellable,
+		                   (GAsyncReadyCallback) set_ap_scan_cb,
+		                   self);
+	}
+	return TRUE;
 }
 
 static void
-destroy_gvalue (gpointer data)
-{
-	GValue *value = (GValue *) data;
-
-	g_value_unset (value);
-	g_slice_free (GValue, value);
-}
-
-static GValue *
-string_to_gvalue (const char *str)
+scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
-	GValue *val = g_slice_new0 (GValue);
+	gs_unref_variant GVariant *reply = NULL;
+	gs_free_error GError *error = NULL;
 
-	g_value_init (val, G_TYPE_STRING);
-	g_value_set_string (val, str);
-	return val;
-}
-
-static GValue *
-byte_array_array_to_gvalue (const GPtrArray *array)
-{
-	GValue *val = g_slice_new0 (GValue);
+	reply = g_dbus_proxy_call_finish (proxy, result, &error);
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		return;
 
-	g_value_init (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR);
-	g_value_set_boxed (val, array);
-	return val;
+	if (error)
+		nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", error->message);
+	g_signal_emit (NM_SUPPLICANT_INTERFACE (user_data), signals[SCAN_DONE], 0, error ? FALSE : TRUE);
 }
 
 gboolean
 nm_supplicant_interface_request_scan (NMSupplicantInterface *self, const GPtrArray *ssids)
 {
 	NMSupplicantInterfacePrivate *priv;
-	DBusGProxyCall *call;
-	GHashTable *hash;
+	GVariantBuilder builder;
+	guint i;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
 
 	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
 	/* Scan parameters */
-	hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, destroy_gvalue);
-	g_hash_table_insert (hash, "Type", string_to_gvalue ("active"));
-	if (ssids)
-		g_hash_table_insert (hash, "SSIDs", byte_array_array_to_gvalue (ssids));
-
-	call = dbus_g_proxy_begin_call (priv->iface_proxy, "Scan",
-	                                scan_request_cb,
-	                                self,
-	                                NULL,
-	                                DBUS_TYPE_G_MAP_OF_VARIANT, hash,
-	                                G_TYPE_INVALID);
-	g_hash_table_destroy (hash);
-	nm_call_store_add (priv->other_pcalls, priv->iface_proxy, call);
+	g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+	g_variant_builder_add (&builder, "{sv}", "Type", g_variant_new_string ("active"));
+	if (ssids) {
+		GVariantBuilder ssids_builder;
+
+		g_variant_builder_init (&ssids_builder, G_VARIANT_TYPE_BYTESTRING_ARRAY);
+		for (i = 0; i < ssids->len; i++) {
+			GByteArray *ssid = g_ptr_array_index (ssids, i);
+			g_variant_builder_add (&ssids_builder, "@ay",
+			                       g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+			                                                  ssid->data, ssid->len, 1));
+		}
+		g_variant_builder_add (&builder, "{sv}", "SSIDs", g_variant_builder_end (&ssids_builder));
+	}
 
-	return call != NULL;
+	g_dbus_proxy_call (priv->iface_proxy,
+	                   "Scan",
+	                   g_variant_new ("(a{sv})", &builder),
+	                   G_DBUS_CALL_FLAGS_NONE,
+	                   -1,
+	                   priv->other_cancellable,
+	                   (GAsyncReadyCallback) scan_request_cb,
+	                   self);
+	return TRUE;
 }
 
 guint32
@@ -1323,8 +1217,7 @@ nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self)
 /*******************************************************************/
 
 NMSupplicantInterface *
-nm_supplicant_interface_new (NMSupplicantManager *smgr,
-                             const char *ifname,
+nm_supplicant_interface_new (const char *ifname,
                              gboolean is_wireless,
                              gboolean fast_supported,
                              ApSupport ap_support,
@@ -1332,21 +1225,12 @@ nm_supplicant_interface_new (NMSupplicantManager *smgr,
 {
 	NMSupplicantInterface *self;
 	NMSupplicantInterfacePrivate *priv;
-	guint id;
 
-	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (smgr), NULL);
 	g_return_val_if_fail (ifname != NULL, NULL);
 
 	self = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, NULL);
 	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
-	priv->smgr = g_object_ref (smgr);
-	id = g_signal_connect (priv->smgr,
-	                       "notify::" NM_SUPPLICANT_MANAGER_AVAILABLE,
-	                       G_CALLBACK (smgr_avail_cb),
-	                       self);
-	priv->smgr_avail_id = id;
-
 	priv->dev = g_strdup (ifname);
 	priv->is_wireless = is_wireless;
 	priv->fast_supported = fast_supported;
@@ -1362,19 +1246,8 @@ static void
 nm_supplicant_interface_init (NMSupplicantInterface * self)
 {
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	DBusGConnection *bus;
 
 	priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT;
-	priv->assoc_pcalls = nm_call_store_new ();
-	priv->other_pcalls = nm_call_store_new ();
-	priv->dbus_mgr = nm_dbus_manager_get ();
-
-	bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
-	priv->wpas_proxy = dbus_g_proxy_new_for_name (bus,
-	                                              WPAS_DBUS_SERVICE,
-	                                              WPAS_DBUS_PATH,
-	                                              WPAS_DBUS_INTERFACE);
-
 	priv->bss_proxies = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
 }
 
@@ -1412,49 +1285,26 @@ dispose (GObject *object)
 {
 	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object);
-		return;
-	}
-	priv->disposed = TRUE;
-
-	/* Cancel pending calls before unrefing the dbus manager */
-	nm_call_store_clear (priv->other_pcalls);
-	nm_call_store_destroy (priv->other_pcalls);
-
-	nm_call_store_clear (priv->assoc_pcalls);
-	nm_call_store_destroy (priv->assoc_pcalls);
-
-	if (priv->props_proxy)
-		g_object_unref (priv->props_proxy);
-
 	if (priv->iface_proxy)
-		g_object_unref (priv->iface_proxy);
+		g_signal_handlers_disconnect_by_data (priv->iface_proxy, NM_SUPPLICANT_INTERFACE (object));
+	g_clear_object (&priv->iface_proxy);
 
-	g_free (priv->net_path);
+	if (priv->init_cancellable)
+		g_cancellable_cancel (priv->init_cancellable);
+	g_clear_object (&priv->init_cancellable);
 
-	if (priv->introspect_proxy)
-		g_object_unref (priv->introspect_proxy);
+	if (priv->other_cancellable)
+		g_cancellable_cancel (priv->other_cancellable);
+	g_clear_object (&priv->other_cancellable);
 
-	if (priv->wpas_proxy)
-		g_object_unref (priv->wpas_proxy);
+	g_clear_object (&priv->wpas_proxy);
+	g_clear_pointer (&priv->bss_proxies, (GDestroyNotify) g_hash_table_destroy);
 
-	g_hash_table_destroy (priv->bss_proxies);
+	g_clear_pointer (&priv->net_path, g_free);
+	g_clear_pointer (&priv->dev, g_free);
+	g_clear_pointer (&priv->object_path, g_free);
 
-	if (priv->smgr) {
-		if (priv->smgr_avail_id)
-			g_signal_handler_disconnect (priv->smgr, priv->smgr_avail_id);
-		g_object_unref (priv->smgr);
-	}
-
-	g_free (priv->dev);
-
-	priv->dbus_mgr = NULL;
-
-	if (priv->cfg)
-		g_object_unref (priv->cfg);
-
-	g_free (priv->object_path);
+	g_clear_object (&priv->cfg);
 
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object);
@@ -1502,7 +1352,7 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
 		              G_SIGNAL_RUN_LAST,
 		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, new_bss),
 		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER);
+		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
 
 	signals[BSS_UPDATED] =
 		g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_UPDATED,
diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h
index 0112e40e..1b1139d4 100644
--- a/src/supplicant-manager/nm-supplicant-interface.h
+++ b/src/supplicant-manager/nm-supplicant-interface.h
@@ -119,13 +119,15 @@ typedef struct {
 
 GType nm_supplicant_interface_get_type (void);
 
-NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr,
-                                                     const char *ifname,
+NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname,
                                                      gboolean is_wireless,
                                                      gboolean fast_supported,
                                                      ApSupport ap_support,
                                                      gboolean start_now);
 
+void nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
+                                                       gboolean available);
+
 gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface,
                                              NMSupplicantConfig * cfg);
 
diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c
index 01e35929..6358c180 100644
--- a/src/supplicant-manager/nm-supplicant-manager.c
+++ b/src/supplicant-manager/nm-supplicant-manager.c
@@ -25,11 +25,12 @@
 #include <glib.h>
 #include <dbus/dbus.h>
 
+#include "nm-glib-compat.h"
+
 #include "nm-supplicant-manager.h"
 #include "nm-supplicant-interface.h"
-#include "nm-dbus-manager.h"
 #include "nm-logging.h"
-#include "nm-dbus-glib-types.h"
+#include "nm-core-internal.h"
 
 #define NM_SUPPLICANT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
                                               NM_TYPE_SUPPLICANT_MANAGER, \
@@ -37,25 +38,16 @@
 
 G_DEFINE_TYPE (NMSupplicantManager, nm_supplicant_manager, G_TYPE_OBJECT)
 
-/* Properties */
-enum {
-	PROP_0 = 0,
-	PROP_AVAILABLE,
-	LAST_PROP
-};
-
 typedef struct {
-	NMDBusManager * dbus_mgr;
-	guint           name_owner_id;
-	DBusGProxy *    proxy;
-	DBusGProxy *    props_proxy;
-	gboolean        running;
+	GDBusProxy *     proxy;
+	GCancellable *   cancellable;
+	gboolean         running;
+
 	GHashTable *    ifaces;
 	gboolean        fast_supported;
 	ApSupport       ap_support;
 	guint           die_count_reset_id;
 	guint           die_count;
-	gboolean        disposed;
 } NMSupplicantManagerPrivate;
 
 /********************************************************************/
@@ -90,14 +82,16 @@ nm_supplicant_manager_iface_get (NMSupplicantManager * self,
 		start_now = !die_count_exceeded (priv->die_count);
 
 		nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname);
-		iface = nm_supplicant_interface_new (self,
-		                                     ifname,
+		iface = nm_supplicant_interface_new (ifname,
 		                                     is_wireless,
 		                                     priv->fast_supported,
 		                                     priv->ap_support,
 		                                     start_now);
-		if (iface)
-			g_hash_table_insert (priv->ifaces, g_strdup (ifname), iface);
+		if (iface) {
+			g_hash_table_insert (priv->ifaces,
+			                     (char *) nm_supplicant_interface_get_ifname (iface),
+			                     iface);
+		}
 	} else {
 		nm_log_dbg (LOGD_SUPPLICANT, "(%s): returning existing supplicant interface", ifname);
 	}
@@ -125,35 +119,27 @@ nm_supplicant_manager_iface_release (NMSupplicantManager *self,
 	/* Ask wpa_supplicant to remove this interface */
 	op = nm_supplicant_interface_get_object_path (iface);
 	if (priv->running && priv->proxy && op) {
-		dbus_g_proxy_call_no_reply (priv->proxy, "RemoveInterface",
-			                        DBUS_TYPE_G_OBJECT_PATH, op,
-			                        G_TYPE_INVALID);
+		g_dbus_proxy_call (priv->proxy,
+		                   "RemoveInterface",
+		                   g_variant_new ("(o)", op),
+		                   G_DBUS_CALL_FLAGS_NONE,
+		                   3000,
+		                   NULL,
+		                   NULL,
+		                   NULL);
 	}
 
 	g_hash_table_remove (priv->ifaces, ifname);
 }
 
 static void
-get_capabilities_cb  (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+update_capabilities (NMSupplicantManager *self)
 {
-	NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data);
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
 	NMSupplicantInterface *iface;
 	GHashTableIter hash_iter;
-	GError *error = NULL;
-	GHashTable *props = NULL;
-	GValue *value;
-	char **iter;
-
-	if (!dbus_g_proxy_end_call (proxy, call_id, &error,
-	                            DBUS_TYPE_G_MAP_OF_VARIANT, &props,
-	                            G_TYPE_INVALID)) {
-		nm_log_warn (LOGD_CORE, "Unexpected error requesting supplicant properties: (%d) %s",
-		             error ? error->code : -1,
-		             error && error->message ? error->message : "(unknown)");
-		g_clear_error (&error);
-		return;
-	}
+	const char **array;
+	GVariant *value;
 
 	/* The supplicant only advertises global capabilities if the following
 	 * commit has been applied:
@@ -165,13 +151,17 @@ get_capabilities_cb  (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_
 	 * dbus: Add global capabilities property
 	 */
 	priv->ap_support = AP_SUPPORT_UNKNOWN;
-	value = g_hash_table_lookup (props, "Capabilities");
-	if (value && G_VALUE_HOLDS (value, G_TYPE_STRV)) {
-		priv->ap_support = AP_SUPPORT_NO;
-		for (iter = g_value_get_boxed (value); iter && *iter; iter++) {
-			if (strcasecmp (*iter, "ap") == 0)
+
+	value = g_dbus_proxy_get_cached_property (priv->proxy, "Capabilities");
+	if (value) {
+		if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING_ARRAY)) {
+			array = g_variant_get_strv (value, NULL);
+			priv->ap_support = AP_SUPPORT_NO;
+			if (_nm_utils_string_in_list ("ap", array))
 				priv->ap_support = AP_SUPPORT_YES;
+			g_free (array);
 		}
+		g_variant_unref (value);
 	}
 
 	/* Tell all interfaces about results of the AP check */
@@ -185,32 +175,35 @@ get_capabilities_cb  (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_
 
 	/* EAP-FAST */
 	priv->fast_supported = FALSE;
-	value = g_hash_table_lookup (props, "EapMethods");
-	if (value && G_VALUE_HOLDS (value, G_TYPE_STRV)) {
-		for (iter = g_value_get_boxed (value); iter && *iter; iter++) {
-			if (strcasecmp (*iter, "fast") == 0)
+	value = g_dbus_proxy_get_cached_property (priv->proxy, "EapMethods");
+	if (value) {
+		if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING_ARRAY)) {
+			array = g_variant_get_strv (value, NULL);
+			if (_nm_utils_string_in_list ("fast", array))
 				priv->fast_supported = TRUE;
+			g_free (array);
 		}
+		g_variant_unref (value);
 	}
 
 	nm_log_dbg (LOGD_SUPPLICANT, "EAP-FAST is %ssupported", priv->fast_supported ? "" : "not ");
-
-	g_hash_table_unref (props);
 }
 
 static void
-check_capabilities (NMSupplicantManager *self)
+availability_changed (NMSupplicantManager *self, gboolean available)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+	GList *ifaces, *iter;
 
-	dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
-	                         get_capabilities_cb, self, NULL,
-	                         G_TYPE_STRING, WPAS_DBUS_INTERFACE,
-	                         G_TYPE_INVALID);
+	/* priv->ifaces may be modified if availability changes; can't use GHashTableIter */
+	ifaces = g_hash_table_get_values (priv->ifaces);
+	for (iter = ifaces; iter; iter = iter->next)
+		nm_supplicant_interface_set_supplicant_available (NM_SUPPLICANT_INTERFACE (iter->data), available);
+	g_list_free (ifaces);
 }
 
-gboolean
-nm_supplicant_manager_available (NMSupplicantManager *self)
+static gboolean
+is_available (NMSupplicantManager *self)
 {
 	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE);
 
@@ -223,22 +216,26 @@ static void
 set_running (NMSupplicantManager *self, gboolean now_running)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
-	gboolean old_available = nm_supplicant_manager_available (self);
+	gboolean old_available = is_available (self);
+	gboolean new_available;
 
 	priv->running = now_running;
-	if (old_available != nm_supplicant_manager_available (self))
-		g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_AVAILABLE);
+	new_available = is_available (self);
+	if (old_available != new_available)
+		availability_changed (self, new_available);
 }
 
 static void
 set_die_count (NMSupplicantManager *self, guint new_die_count)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
-	gboolean old_available = nm_supplicant_manager_available (self);
+	gboolean old_available = is_available (self);
+	gboolean new_available;
 
 	priv->die_count = new_die_count;
-	if (old_available != nm_supplicant_manager_available (self))
-		g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_AVAILABLE);
+	new_available = is_available (self);
+	if (old_available != new_available)
+		availability_changed (self, new_available);
 }
 
 static gboolean
@@ -255,28 +252,21 @@ wpas_die_count_reset_cb (gpointer user_data)
 }
 
 static void
-name_owner_changed (NMDBusManager *dbus_mgr,
-                    const char *name,
-                    const char *old_owner,
-                    const char *new_owner,
-                    gpointer user_data)
+name_owner_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data)
 {
 	NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data);
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
-	gboolean old_owner_good = (old_owner && strlen (old_owner));
-	gboolean new_owner_good = (new_owner && strlen (new_owner));
+	char *owner;
 
-	/* We only care about the supplicant here */
-	if (strcmp (WPAS_DBUS_SERVICE, name) != 0)
-		return;
+	g_return_if_fail (proxy == priv->proxy);
 
-	if (!old_owner_good && new_owner_good) {
-		nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant started");
-		set_running (self, TRUE);
-		check_capabilities (self);
-	} else if (old_owner_good && !new_owner_good) {
-		nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant stopped");
+	owner = g_dbus_proxy_get_name_owner (proxy);
+	nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant %s", owner ? "running" : "stopped");
 
+	if (owner) {
+		set_running (self, TRUE);
+		update_capabilities (self);
+	} else if (priv->running) {
 		/* Reschedule the die count reset timeout.  Every time the supplicant
 		 * dies we wait 10 seconds before resetting the counter.  If the
 		 * supplicant died more than twice before the timer is reset, then
@@ -297,6 +287,33 @@ name_owner_changed (NMDBusManager *dbus_mgr,
 
 		priv->fast_supported = FALSE;
 	}
+
+	g_free (owner);
+}
+
+static void
+on_proxy_acquired (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	NMSupplicantManager *self;
+	NMSupplicantManagerPrivate *priv;
+	GError *error = NULL;
+	GDBusProxy *proxy;
+
+	proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
+	if (!proxy) {
+		nm_log_warn (LOGD_SUPPLICANT,
+		             "Failed to acquire wpa_supplicant proxy: Wi-Fi and 802.1x will not be available (%s)",
+		             error->message);
+		g_clear_error (&error);
+		return;
+	}
+
+	self = NM_SUPPLICANT_MANAGER (user_data);
+	priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+
+	priv->proxy = proxy;
+	g_signal_connect (priv->proxy, "notify::g-name-owner", G_CALLBACK (name_owner_cb), self);
+	name_owner_cb (priv->proxy, NULL, self);
 }
 
 /*******************************************************************/
@@ -319,50 +336,19 @@ static void
 nm_supplicant_manager_init (NMSupplicantManager *self)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
-	DBusGConnection *bus;
-
-	priv->dbus_mgr = nm_dbus_manager_get ();
-	priv->name_owner_id = g_signal_connect (priv->dbus_mgr,
-	                                        NM_DBUS_MANAGER_NAME_OWNER_CHANGED,
-	                                        G_CALLBACK (name_owner_changed),
-	                                        self);
-	priv->running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, WPAS_DBUS_SERVICE);
-
-	bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
-	priv->proxy = dbus_g_proxy_new_for_name (bus,
-	                                         WPAS_DBUS_SERVICE,
-	                                         WPAS_DBUS_PATH,
-	                                         WPAS_DBUS_INTERFACE);
-
-	priv->props_proxy = dbus_g_proxy_new_for_name (bus,
-	                                               WPAS_DBUS_SERVICE,
-	                                               WPAS_DBUS_PATH,
-	                                               DBUS_INTERFACE_PROPERTIES);
-
-	priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-
-	/* Check generic supplicant capabilities */
-	if (priv->running)
-		check_capabilities (self);
-}
 
-static void
-set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-}
-
-static void
-get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	switch (prop_id) {
-	case PROP_AVAILABLE:
-		g_value_set_boolean (value, nm_supplicant_manager_available (NM_SUPPLICANT_MANAGER (object)));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+	priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+
+	priv->cancellable = g_cancellable_new ();
+	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+	                          G_DBUS_PROXY_FLAGS_NONE,
+	                          NULL,
+	                          WPAS_DBUS_SERVICE,
+	                          WPAS_DBUS_PATH,
+	                          WPAS_DBUS_INTERFACE,
+	                          priv->cancellable,
+	                          (GAsyncReadyCallback) on_proxy_acquired,
+	                          self);
 }
 
 static void
@@ -370,29 +356,19 @@ dispose (GObject *object)
 {
 	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object);
 
-	if (priv->disposed)
-		goto out;
-	priv->disposed = TRUE;
-
-	if (priv->die_count_reset_id)
+	if (priv->die_count_reset_id) {
 		g_source_remove (priv->die_count_reset_id);
-
-	if (priv->dbus_mgr) {
-		if (priv->name_owner_id)
-			g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id);
-		priv->dbus_mgr = NULL;
+		priv->die_count_reset_id = 0;
 	}
 
-	g_hash_table_destroy (priv->ifaces);
-
-	if (priv->proxy)
-		g_object_unref (priv->proxy);
+	if (priv->cancellable) {
+		g_cancellable_cancel (priv->cancellable);
+		g_clear_object (&priv->cancellable);
+	}
 
-	if (priv->props_proxy)
-		g_object_unref (priv->props_proxy);
+	g_clear_pointer (&priv->ifaces, g_hash_table_unref);
+	g_clear_object (&priv->proxy);
 
-out:
-	/* Chain up to the parent class */
 	G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object);
 }
 
@@ -403,15 +379,6 @@ nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass)
 
 	g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate));
 
-	object_class->get_property = get_property;
-	object_class->set_property = set_property;
 	object_class->dispose = dispose;
-
-	g_object_class_install_property
-		(object_class, PROP_AVAILABLE,
-		 g_param_spec_boolean (NM_SUPPLICANT_MANAGER_AVAILABLE, "", "",
-		                       FALSE,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
 }
 
diff --git a/src/supplicant-manager/nm-supplicant-manager.h b/src/supplicant-manager/nm-supplicant-manager.h
index 5e7f1eb5..3b8fddf4 100644
--- a/src/supplicant-manager/nm-supplicant-manager.h
+++ b/src/supplicant-manager/nm-supplicant-manager.h
@@ -26,11 +26,6 @@
 #include "nm-supplicant-types.h"
 #include "nm-device.h"
 
-#define WPAS_DBUS_SERVICE	"fi.w1.wpa_supplicant1"
-#define WPAS_DBUS_PATH		"/fi/w1/wpa_supplicant1"
-#define WPAS_DBUS_INTERFACE	"fi.w1.wpa_supplicant1"
-
-
 G_BEGIN_DECLS
 
 #define NM_TYPE_SUPPLICANT_MANAGER				(nm_supplicant_manager_get_type ())
@@ -40,8 +35,6 @@ G_BEGIN_DECLS
 #define NM_IS_SUPPLICANT_MANAGER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_SUPPLICANT_MANAGER))
 #define NM_SUPPLICANT_MANAGER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass))
 
-#define NM_SUPPLICANT_MANAGER_AVAILABLE "available"
-
 struct _NMSupplicantManager
 {
 	GObject parent;
@@ -63,6 +56,4 @@ NMSupplicantInterface *nm_supplicant_manager_iface_get (NMSupplicantManager *mgr
 void nm_supplicant_manager_iface_release (NMSupplicantManager *mgr,
                                           NMSupplicantInterface *iface);
 
-gboolean nm_supplicant_manager_available (NMSupplicantManager *mgr);
-
 #endif /* __NETWORKMANAGER_SUPPLICANT_MANAGER_H__ */
diff --git a/src/supplicant-manager/nm-supplicant-types.h b/src/supplicant-manager/nm-supplicant-types.h
index 619f0c3e..1c16e494 100644
--- a/src/supplicant-manager/nm-supplicant-types.h
+++ b/src/supplicant-manager/nm-supplicant-types.h
@@ -21,6 +21,10 @@
 #ifndef __NETWORKMANAGER_SUPPLICANT_TYPES_H__
 #define __NETWORKMANAGER_SUPPLICANT_TYPES_H__
 
+#define WPAS_DBUS_SERVICE	"fi.w1.wpa_supplicant1"
+#define WPAS_DBUS_PATH		"/fi/w1/wpa_supplicant1"
+#define WPAS_DBUS_INTERFACE	"fi.w1.wpa_supplicant1"
+
 typedef struct _NMSupplicantManager NMSupplicantManager;
 typedef struct _NMSupplicantInterface NMSupplicantInterface;
 typedef struct _NMSupplicantConfig NMSupplicantConfig;
diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in
index 50981a19..ef5233b2 100644
--- a/src/supplicant-manager/tests/Makefile.in
+++ b/src/supplicant-manager/tests/Makefile.in
@@ -203,13 +203,196 @@ am__tty_colors = { \
     std=''; \
   fi; \
 }
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__recheck_rx = ^[ 	]*:recheck:[ 	]*
+am__global_test_result_rx = ^[ 	]*:global-test-result:[ 	]*
+am__copy_in_global_log_rx = ^[ 	]*:copy-in-global-log:[ 	]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+  recheck = 1; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+        { \
+          if ((getline line2 < ($$0 ".log")) < 0) \
+	    recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+        { \
+          recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+        { \
+          break; \
+        } \
+    }; \
+  if (recheck) \
+    print $$0; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+  print "fatal: making $@: " msg | "cat >&2"; \
+  exit 1; \
+} \
+function rst_section(header) \
+{ \
+  print header; \
+  len = length(header); \
+  for (i = 1; i <= len; i = i + 1) \
+    printf "="; \
+  printf "\n\n"; \
+} \
+{ \
+  copy_in_global_log = 1; \
+  global_test_result = "RUN"; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+         fatal("failed to read from " $$0 ".trs"); \
+      if (line ~ /$(am__global_test_result_rx)/) \
+        { \
+          sub("$(am__global_test_result_rx)", "", line); \
+          sub("[ 	]*$$", "", line); \
+          global_test_result = line; \
+        } \
+      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+        copy_in_global_log = 0; \
+    }; \
+  if (copy_in_global_log) \
+    { \
+      rst_section(global_test_result ": " $$0); \
+      while ((rc = (getline line < ($$0 ".log"))) != 0) \
+      { \
+        if (rc < 0) \
+          fatal("failed to read from " $$0 ".log"); \
+        print line; \
+      }; \
+      printf "\n"; \
+    }; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this.  Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test.  Creates the
+# directory for the log if needed.  Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log.  Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup);					\
+$(am__vpath_adj_setup) $(am__vpath_adj)			\
+$(am__tty_colors);					\
+srcdir=$(srcdir); export srcdir;			\
+case "$@" in						\
+  */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;;	\
+    *) am__odir=.;; 					\
+esac;							\
+test "x$$am__odir" = x"." || test -d "$$am__odir" 	\
+  || $(MKDIR_P) "$$am__odir" || exit $$?;		\
+if test -f "./$$f"; then dir=./;			\
+elif test -f "$$f"; then dir=;				\
+else dir="$(srcdir)/"; fi;				\
+tst=$$dir$$f; log='$@'; 				\
+if test -n '$(DISABLE_HARD_ERRORS)'; then		\
+  am__enable_hard_errors=no; 				\
+else							\
+  am__enable_hard_errors=yes; 				\
+fi; 							\
+case " $(XFAIL_TESTS) " in				\
+  *[\ \	]$$f[\ \	]* | *[\ \	]$$dir$$f[\ \	]*) \
+    am__expect_failure=yes;;				\
+  *)							\
+    am__expect_failure=no;;				\
+esac; 							\
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed).  The result is saved in the shell variable
+# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+	$(TEST_LOG_FLAGS)
 am__DIST_COMMON = $(srcdir)/Makefile.in \
-	$(top_srcdir)/build-aux/depcomp
+	$(top_srcdir)/build-aux/depcomp \
+	$(top_srcdir)/build-aux/test-driver
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 ACLOCAL = @ACLOCAL@
 ALL_LINGUAS = @ALL_LINGUAS@
 AMTAR = @AMTAR@
 AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AM_TESTS_FD_REDIRECT = @AM_TESTS_FD_REDIRECT@
 AR = @AR@
 AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
@@ -323,6 +506,7 @@ LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
+LOG_DRIVER = @LOG_DRIVER@
 LTLIBICONV = @LTLIBICONV@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
@@ -487,7 +671,7 @@ test_supplicant_config_LDADD = \
 all: all-am
 
 .SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
 	@for dep in $?; do \
 	  case '$(am__configure_deps)' in \
@@ -618,98 +802,168 @@ cscopelist-am: $(am__tagged_files)
 distclean-tags:
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
-check-TESTS: $(TESTS)
-	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
-	srcdir=$(srcdir); export srcdir; \
-	list=' $(TESTS) '; \
-	$(am__tty_colors); \
-	if test -n "$$list"; then \
-	  for tst in $$list; do \
-	    if test -f ./$$tst; then dir=./; \
-	    elif test -f $$tst; then dir=; \
-	    else dir="$(srcdir)/"; fi; \
-	    if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *[\ \	]$$tst[\ \	]*) \
-		xpass=`expr $$xpass + 1`; \
-		failed=`expr $$failed + 1`; \
-		col=$$red; res=XPASS; \
-	      ;; \
-	      *) \
-		col=$$grn; res=PASS; \
-	      ;; \
-	      esac; \
-	    elif test $$? -ne 77; then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *[\ \	]$$tst[\ \	]*) \
-		xfail=`expr $$xfail + 1`; \
-		col=$$lgn; res=XFAIL; \
-	      ;; \
-	      *) \
-		failed=`expr $$failed + 1`; \
-		col=$$red; res=FAIL; \
-	      ;; \
-	      esac; \
-	    else \
-	      skip=`expr $$skip + 1`; \
-	      col=$$blu; res=SKIP; \
-	    fi; \
-	    echo "$${col}$$res$${std}: $$tst"; \
-	  done; \
-	  if test "$$all" -eq 1; then \
-	    tests="test"; \
-	    All=""; \
-	  else \
-	    tests="tests"; \
-	    All="All "; \
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+	rm -f $< $@
+	$(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+	@:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+	@$(am__set_TESTS_bases); \
+	am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+	redo_bases=`for i in $$bases; do \
+	              am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+	            done`; \
+	if test -n "$$redo_bases"; then \
+	  redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+	  redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+	  if $(am__make_dryrun); then :; else \
+	    rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
 	  fi; \
-	  if test "$$failed" -eq 0; then \
-	    if test "$$xfail" -eq 0; then \
-	      banner="$$All$$all $$tests passed"; \
-	    else \
-	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
-	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
-	    fi; \
-	  else \
-	    if test "$$xpass" -eq 0; then \
-	      banner="$$failed of $$all $$tests failed"; \
+	fi; \
+	if test -n "$$am__remaking_logs"; then \
+	  echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+	       "recursion detected" >&2; \
+	elif test -n "$$redo_logs"; then \
+	  am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+	fi; \
+	if $(am__make_dryrun); then :; else \
+	  st=0;  \
+	  errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+	  for i in $$redo_bases; do \
+	    test -f $$i.trs && test -r $$i.trs \
+	      || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+	    test -f $$i.log && test -r $$i.log \
+	      || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+	  done; \
+	  test $$st -eq 0 || exit 1; \
+	fi
+	@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+	ws='[ 	]'; \
+	results=`for b in $$bases; do echo $$b.trs; done`; \
+	test -n "$$results" || results=/dev/null; \
+	all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+	pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+	fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+	skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+	xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+	xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+	error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+	if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+	  success=true; \
+	else \
+	  success=false; \
+	fi; \
+	br='==================='; br=$$br$$br$$br$$br; \
+	result_count () \
+	{ \
+	    if test x"$$1" = x"--maybe-color"; then \
+	      maybe_colorize=yes; \
+	    elif test x"$$1" = x"--no-color"; then \
+	      maybe_colorize=no; \
 	    else \
-	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
-	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	      echo "$@: invalid 'result_count' usage" >&2; exit 4; \
 	    fi; \
-	  fi; \
-	  dashes="$$banner"; \
-	  skipped=""; \
-	  if test "$$skip" -ne 0; then \
-	    if test "$$skip" -eq 1; then \
-	      skipped="($$skip test was not run)"; \
+	    shift; \
+	    desc=$$1 count=$$2; \
+	    if test $$maybe_colorize = yes && test $$count -gt 0; then \
+	      color_start=$$3 color_end=$$std; \
 	    else \
-	      skipped="($$skip tests were not run)"; \
+	      color_start= color_end=; \
 	    fi; \
-	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
-	      dashes="$$skipped"; \
-	  fi; \
-	  report=""; \
-	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
-	    report="Please report to $(PACKAGE_BUGREPORT)"; \
-	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
-	      dashes="$$report"; \
-	  fi; \
-	  dashes=`echo "$$dashes" | sed s/./=/g`; \
-	  if test "$$failed" -eq 0; then \
-	    col="$$grn"; \
-	  else \
-	    col="$$red"; \
-	  fi; \
-	  echo "$${col}$$dashes$${std}"; \
-	  echo "$${col}$$banner$${std}"; \
-	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
-	  test -z "$$report" || echo "$${col}$$report$${std}"; \
-	  echo "$${col}$$dashes$${std}"; \
-	  test "$$failed" -eq 0; \
-	else :; fi
+	    echo "$${color_start}# $$desc $$count$${color_end}"; \
+	}; \
+	create_testsuite_report () \
+	{ \
+	  result_count $$1 "TOTAL:" $$all   "$$brg"; \
+	  result_count $$1 "PASS: " $$pass  "$$grn"; \
+	  result_count $$1 "SKIP: " $$skip  "$$blu"; \
+	  result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+	  result_count $$1 "FAIL: " $$fail  "$$red"; \
+	  result_count $$1 "XPASS:" $$xpass "$$red"; \
+	  result_count $$1 "ERROR:" $$error "$$mgn"; \
+	}; \
+	{								\
+	  echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |	\
+	    $(am__rst_title);						\
+	  create_testsuite_report --no-color;				\
+	  echo;								\
+	  echo ".. contents:: :depth: 2";				\
+	  echo;								\
+	  for b in $$bases; do echo $$b; done				\
+	    | $(am__create_global_log);					\
+	} >$(TEST_SUITE_LOG).tmp || exit 1;				\
+	mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);			\
+	if $$success; then						\
+	  col="$$grn";							\
+	 else								\
+	  col="$$red";							\
+	  test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);		\
+	fi;								\
+	echo "$${col}$$br$${std}"; 					\
+	echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}";	\
+	echo "$${col}$$br$${std}"; 					\
+	create_testsuite_report --maybe-color;				\
+	echo "$$col$$br$$std";						\
+	if $$success; then :; else					\
+	  echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";		\
+	  if test -n "$(PACKAGE_BUGREPORT)"; then			\
+	    echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}";	\
+	  fi;								\
+	  echo "$$col$$br$$std";					\
+	fi;								\
+	$$success || exit 1
+
+check-TESTS:
+	@list='$(RECHECK_LOGS)';           test -z "$$list" || rm -f $$list
+	@list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+	@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+	@set +e; $(am__set_TESTS_bases); \
+	log_list=`for i in $$bases; do echo $$i.log; done`; \
+	trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+	log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+	$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+	exit $$?;
+recheck: all 
+	@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+	@set +e; $(am__set_TESTS_bases); \
+	bases=`for i in $$bases; do echo $$i; done \
+	         | $(am__list_recheck_tests)` || exit 1; \
+	log_list=`for i in $$bases; do echo $$i.log; done`; \
+	log_list=`echo $$log_list`; \
+	$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+	        am__force_recheck=am--force-recheck \
+	        TEST_LOGS="$$log_list"; \
+	exit $$?
+test-supplicant-config.log: test-supplicant-config$(EXEEXT)
+	@p='test-supplicant-config$(EXEEXT)'; \
+	b='test-supplicant-config'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+	@p='$<'; \
+	$(am__set_b); \
+	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@	@p='$<'; \
+@am__EXEEXT_TRUE@	$(am__set_b); \
+@am__EXEEXT_TRUE@	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@	--log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@	"$$tst" $(AM_TESTS_FD_REDIRECT)
 
 distdir: $(DISTFILES)
 	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -766,6 +1020,9 @@ install-strip:
 	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
 	fi
 mostlyclean-generic:
+	-test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+	-test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+	-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
 
 clean-generic:
 
@@ -861,7 +1118,7 @@ uninstall-am:
 	installcheck-am installdirs maintainer-clean \
 	maintainer-clean-generic mostlyclean mostlyclean-compile \
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-	tags tags-am uninstall uninstall-am
+	recheck tags tags-am uninstall uninstall-am
 
 .PRECIOUS: Makefile
 
diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c
index 5ffead40..937757b2 100644
--- a/src/supplicant-manager/tests/test-supplicant-config.c
+++ b/src/supplicant-manager/tests/test-supplicant-config.c
@@ -41,78 +41,67 @@
 
 static gboolean
 validate_opt (const char *detail,
-              GHashTable *hash,
+              GVariant *config,
               const char *key,
               OptType val_type,
               gconstpointer expected,
               size_t expected_len)
 {
-	GValue *value;
-	gint int_val;
-	GByteArray *array;
+	char *config_key;
+	GVariant *config_value;
+	gboolean found = FALSE;
+	const guint8 *bytes;
+	gsize len;
 	const char *s;
 	const unsigned char *expected_array = expected;
-	int result;
-
-	ASSERT (hash != NULL, detail, "hash was NULL");
-
-	value = g_hash_table_lookup (hash, key);
-	ASSERT (value != NULL,
-	        detail, "option '%s' expected but not found in config hash.");
-
-	switch (val_type) {
-	case TYPE_INT:
-		ASSERT (G_VALUE_HOLDS_INT (value),
-		        detail, "config hash item '%s' was not TYPE_INT.", key);
-		int_val = g_value_get_int (value);
-		ASSERT (int_val == GPOINTER_TO_INT (expected),
-		        detail, "unexpected config hash item '%s' value %d (expected %d)",
-		        key, int_val, GPOINTER_TO_INT (expected));
-		break;
-	case TYPE_BYTES:
-		ASSERT (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY),
-		        detail, "config hash item '%s' was not TYPE_BYTES.", key);
-		array = g_value_get_boxed (value);
-		ASSERT (array->len == expected_len,
-		        detail, "unexpected config hash item '%s' length %d (expected %d)",
-		        key, array->len, expected_len);
-		result = memcmp (array->data, expected_array, expected_len);
-		ASSERT (result == 0, detail, "unexpected config hash item '%s' value", key);
-		break;
-	case TYPE_KEYWORD:
-	case TYPE_STRING:
-		ASSERT (G_VALUE_HOLDS_STRING (value),
-		        detail, "config hash item '%s' was not TYPE_STRING or TYPE_KEYWORD.", key);
-		if (expected_len == -1)
-			expected_len = strlen ((const char *) expected);
-		s = g_value_get_string (value);
-		ASSERT (s != NULL, detail, "unexpected NULL config hash string item '%s'.", key);
-		ASSERT (strlen (s) == expected_len,
-		        detail, "unexpected config hash string item '%s' length %d (expected %d)",
-		        key, strlen (s), expected_len);
-		result = strcmp (s, (const char *) expected);
-		ASSERT (result == 0,
-		        detail, "unexpected config hash string item '%s' value '%s' (expected '%s')",
-		        key, s, (const char *) expected);
-		break;
-	default:
-		g_warning ("unknown supplicant config hash item '%s' option type %d",
-		           key, val_type);
-		return FALSE;
+	GVariantIter iter;
+
+	g_assert (g_variant_is_of_type (config, G_VARIANT_TYPE_VARDICT));
+
+	g_variant_iter_init (&iter, config);
+	while (g_variant_iter_next (&iter, "{&sv}", (gpointer) &config_key, (gpointer) &config_value)) {
+		if (!strcmp (key, config_key)) {
+			found = TRUE;
+			switch (val_type) {
+			case TYPE_INT:
+				g_assert (g_variant_is_of_type (config_value, G_VARIANT_TYPE_INT32));
+				g_assert_cmpint (g_variant_get_int32 (config_value), ==, GPOINTER_TO_INT (expected));
+				break;
+			case TYPE_BYTES:
+				g_assert (g_variant_is_of_type (config_value, G_VARIANT_TYPE_BYTESTRING));
+				bytes = g_variant_get_fixed_array (config_value, &len, 1);
+				g_assert_cmpint (len, ==, expected_len);
+				g_assert (memcmp (bytes, expected_array, expected_len) == 0);
+				break;
+			case TYPE_KEYWORD:
+			case TYPE_STRING:
+				g_assert (g_variant_is_of_type (config_value, G_VARIANT_TYPE_STRING));
+				if (expected_len == -1)
+					expected_len = strlen ((const char *) expected);
+				s = g_variant_get_string (config_value, NULL);
+				g_assert_cmpint (strlen (s), ==, expected_len);
+				g_assert_cmpstr (s, ==, expected);
+				break;
+			default:
+				g_assert_not_reached ();
+				break;
+			}
+		}
+		g_variant_unref (config_value);
 	}
 
-	return TRUE;
+	return found;
 }
 
 static void
 test_wifi_open (void)
 {
-	NMConnection *connection;
+	gs_unref_object NMConnection *connection = NULL;
+	gs_unref_object NMSupplicantConfig *config = NULL;
+	gs_unref_variant GVariant *config_dict = NULL;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
 	NMSettingIPConfig *s_ip4;
-	gs_unref_object NMSupplicantConfig *config = NULL;
-	GHashTable *hash;
 	char *uuid;
 	gboolean success;
 	GError *error = NULL;
@@ -156,9 +145,9 @@ test_wifi_open (void)
 
 	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        "wifi-open", "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	config = nm_supplicant_config_new ();
 
@@ -170,29 +159,21 @@ test_wifi_open (void)
 	                       "*added 'bssid' value '11:22:33:44:55:66'*");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*added 'freq_list' value *");
-	success = nm_supplicant_config_add_setting_wireless (config, s_wifi, 0);
-	ASSERT (success == TRUE,
-	        "wifi-open", "failed to add wireless setting to supplicant config.");
+	g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
 	g_test_assert_expected_messages ();
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*added 'key_mgmt' value 'NONE'");
-	success = nm_supplicant_config_add_no_security (config);
-	ASSERT (success == TRUE,
-	        "wifi-open", "failed to add wireless security to supplicant config.");
+	g_assert (nm_supplicant_config_add_no_security (config));
 	g_test_assert_expected_messages ();
 
-	hash = nm_supplicant_config_get_hash (config);
-	ASSERT (hash != NULL,
-	        "wifi-open", "failed to hash supplicant config options.");
-
-	validate_opt ("wifi-open", hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
-	validate_opt ("wifi-open", hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
-	validate_opt ("wifi-open", hash, "bssid", TYPE_KEYWORD, bssid_str, -1);
-	validate_opt ("wifi-open", hash, "key_mgmt", TYPE_KEYWORD, "NONE", -1);
+	config_dict = nm_supplicant_config_to_variant (config);
+	g_assert (config_dict);
 
-	g_hash_table_unref (hash);
-	g_object_unref (connection);
+	validate_opt ("wifi-open", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
+	validate_opt ("wifi-open", config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
+	validate_opt ("wifi-open", config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1);
+	validate_opt ("wifi-open", config_dict, "key_mgmt", TYPE_KEYWORD, "NONE", -1);
 }
 
 static void
@@ -202,13 +183,13 @@ test_wifi_wep_key (const char *detail,
                    const unsigned char *expected,
                    size_t expected_size)
 {
-	NMConnection *connection;
+	gs_unref_object NMConnection *connection = NULL;
+	gs_unref_object NMSupplicantConfig *config = NULL;
+	gs_unref_variant GVariant *config_dict = NULL;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
-	gs_unref_object NMSupplicantConfig *config = NULL;
-	GHashTable *hash;
 	char *uuid;
 	gboolean success;
 	GError *error = NULL;
@@ -262,9 +243,9 @@ test_wifi_wep_key (const char *detail,
 
 	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        detail, "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	config = nm_supplicant_config_new ();
 
@@ -276,9 +257,7 @@ test_wifi_wep_key (const char *detail,
 	                       "*added 'bssid' value '11:22:33:44:55:66'*");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*added 'freq_list' value *");
-	success = nm_supplicant_config_add_setting_wireless (config, s_wifi, 0);
-	ASSERT (success == TRUE,
-	        detail, "failed to add wireless setting to supplicant config.");
+	g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
 	g_test_assert_expected_messages ();
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
@@ -287,27 +266,21 @@ test_wifi_wep_key (const char *detail,
 	                       "*added 'wep_key0' value *");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*added 'wep_tx_keyidx' value '0'");
-	success = nm_supplicant_config_add_setting_wireless_security (config,
+	g_assert (nm_supplicant_config_add_setting_wireless_security (config,
 	                                                              s_wsec,
 	                                                              NULL,
-	                                                              "376aced7-b28c-46be-9a62-fcdf072571da");
-	ASSERT (success == TRUE,
-	        detail, "failed to add wireless security to supplicant config.");
+	                                                              "376aced7-b28c-46be-9a62-fcdf072571da"));
 	g_test_assert_expected_messages ();
 
-	hash = nm_supplicant_config_get_hash (config);
-	ASSERT (hash != NULL,
-	        detail, "failed to hash supplicant config options.");
+	config_dict = nm_supplicant_config_to_variant (config);
+	g_assert (config_dict);
 
-	validate_opt (detail, hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
-	validate_opt (detail, hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
-	validate_opt (detail, hash, "bssid", TYPE_KEYWORD, bssid_str, -1);
-	validate_opt (detail, hash, "key_mgmt", TYPE_KEYWORD, "NONE", -1);
-	validate_opt (detail, hash, "wep_tx_keyidx", TYPE_INT, GINT_TO_POINTER (0), -1);
-	validate_opt (detail, hash, "wep_key0", TYPE_BYTES, expected, expected_size);
-
-	g_hash_table_unref (hash);
-	g_object_unref (connection);
+	validate_opt (detail, config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
+	validate_opt (detail, config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
+	validate_opt (detail, config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1);
+	validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "NONE", -1);
+	validate_opt (detail, config_dict, "wep_tx_keyidx", TYPE_INT, GINT_TO_POINTER (0), -1);
+	validate_opt (detail, config_dict, "wep_key0", TYPE_BYTES, expected, expected_size);
 }
 
 static void
@@ -340,13 +313,13 @@ test_wifi_wpa_psk (const char *detail,
                    const unsigned char *expected,
                    size_t expected_size)
 {
-	NMConnection *connection;
+	gs_unref_object NMConnection *connection = NULL;
+	gs_unref_object NMSupplicantConfig *config = NULL;
+	gs_unref_variant GVariant *config_dict = NULL;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIPConfig *s_ip4;
-	gs_unref_object NMSupplicantConfig *config = NULL;
-	GHashTable *hash;
 	char *uuid;
 	gboolean success;
 	GError *error = NULL;
@@ -406,9 +379,9 @@ test_wifi_wpa_psk (const char *detail,
 
 	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 
-	ASSERT (nm_connection_verify (connection, &error) == TRUE,
-	        detail, "failed to verify connection: %s",
-	        (error && error->message) ? error->message : "(unknown)");
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	config = nm_supplicant_config_new ();
 
@@ -420,9 +393,7 @@ test_wifi_wpa_psk (const char *detail,
 	                       "*added 'bssid' value '11:22:33:44:55:66'*");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*added 'freq_list' value *");
-	success = nm_supplicant_config_add_setting_wireless (config, s_wifi, 0);
-	ASSERT (success == TRUE,
-	        detail, "failed to add wireless setting to supplicant config.");
+	g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
 	g_test_assert_expected_messages ();
 
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
@@ -435,29 +406,23 @@ test_wifi_wpa_psk (const char *detail,
 	                       "*added 'pairwise' value 'TKIP CCMP'");
 	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
 	                       "*added 'group' value 'TKIP CCMP'");
-	success = nm_supplicant_config_add_setting_wireless_security (config,
+	g_assert (nm_supplicant_config_add_setting_wireless_security (config,
 	                                                              s_wsec,
 	                                                              NULL,
-	                                                              "376aced7-b28c-46be-9a62-fcdf072571da");
-	ASSERT (success == TRUE,
-	        detail, "failed to add wireless security to supplicant config.");
+	                                                              "376aced7-b28c-46be-9a62-fcdf072571da"));
 	g_test_assert_expected_messages ();
 
-	hash = nm_supplicant_config_get_hash (config);
-	ASSERT (hash != NULL,
-	        detail, "failed to hash supplicant config options.");
-
-	validate_opt (detail, hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
-	validate_opt (detail, hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
-	validate_opt (detail, hash, "bssid", TYPE_KEYWORD, bssid_str, -1);
-	validate_opt (detail, hash, "key_mgmt", TYPE_KEYWORD, "WPA-PSK", -1);
-	validate_opt (detail, hash, "proto", TYPE_KEYWORD, "WPA RSN", -1);
-	validate_opt (detail, hash, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1);
-	validate_opt (detail, hash, "group", TYPE_KEYWORD, "TKIP CCMP", -1);
-	validate_opt (detail, hash, "psk", key_type, expected, expected_size);
-
-	g_hash_table_unref (hash);
-	g_object_unref (connection);
+	config_dict = nm_supplicant_config_to_variant (config);
+	g_assert (config_dict);
+
+	validate_opt (detail, config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
+	validate_opt (detail, config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
+	validate_opt (detail, config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1);
+	validate_opt (detail, config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-PSK", -1);
+	validate_opt (detail, config_dict, "proto", TYPE_KEYWORD, "WPA RSN", -1);
+	validate_opt (detail, config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1);
+	validate_opt (detail, config_dict, "group", TYPE_KEYWORD, "TKIP CCMP", -1);
+	validate_opt (detail, config_dict, "psk", key_type, expected, expected_size);
 }
 
 static void
@@ -478,18 +443,12 @@ NMTST_DEFINE ();
 
 int main (int argc, char **argv)
 {
-	char *base;
-
 	nmtst_init (&argc, &argv, TRUE);
 
-	/* The tests */
-	test_wifi_open ();
-	test_wifi_wep ();
-	test_wifi_wpa_psk_types ();
+	g_test_add_func ("/supplicant-config/wifi-open", test_wifi_open);
+	g_test_add_func ("/supplicant-config/wifi-wep", test_wifi_wep);
+	g_test_add_func ("/supplicant-config/wifi-wpa-psk-types", test_wifi_wpa_psk_types);
 
-	base = g_path_get_basename (argv[0]);
-	fprintf (stdout, "%s: SUCCESS\n", base);
-	g_free (base);
-	return 0;
+	return g_test_run ();
 }