summary refs log tree commit diff
path: root/src/supplicant-manager/nm-supplicant-interface.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2017-01-17 20:25:09 +0100
committerMichael Biebl <biebl@debian.org>2017-01-17 20:25:09 +0100
commit58f8be580039b0575b197b9573a1c92745d96d30 (patch)
tree2c226233f623a0dcb529be0eb8cdf97e4a2ae0c0 /src/supplicant-manager/nm-supplicant-interface.c
parent45cb5bb3c0e6edb887cf69b417fcaf7053814a9b (diff)
New upstream version 1.5.90 upstream/1.5.90
Diffstat (limited to 'src/supplicant-manager/nm-supplicant-interface.c')
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c1663
1 files changed, 0 insertions, 1663 deletions
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
deleted file mode 100644
index 05d9aa67..00000000
--- a/src/supplicant-manager/nm-supplicant-interface.c
+++ /dev/null
@@ -1,1663 +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) 2006 - 2012 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include "nm-default.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "NetworkManagerUtils.h"
-#include "nm-supplicant-interface.h"
-#include "nm-supplicant-config.h"
-#include "nm-core-internal.h"
-#include "nm-dbus-compat.h"
-
-#define WPAS_DBUS_IFACE_INTERFACE   WPAS_DBUS_INTERFACE ".Interface"
-#define WPAS_DBUS_IFACE_BSS         WPAS_DBUS_INTERFACE ".BSS"
-#define WPAS_DBUS_IFACE_NETWORK	    WPAS_DBUS_INTERFACE ".Network"
-#define WPAS_ERROR_INVALID_IFACE    WPAS_DBUS_INTERFACE ".InvalidInterface"
-#define WPAS_ERROR_EXISTS_ERROR     WPAS_DBUS_INTERFACE ".InterfaceExists"
-
-G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT)
-
-#define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
-                                                 NM_TYPE_SUPPLICANT_INTERFACE, \
-                                                 NMSupplicantInterfacePrivate))
-
-/* Signals */
-enum {
-	STATE,               /* change in the interface's state */
-	REMOVED,             /* interface was removed by the supplicant */
-	NEW_BSS,             /* interface saw a new access point from a scan */
-	BSS_UPDATED,         /* a BSS property changed */
-	BSS_REMOVED,         /* supplicant removed BSS from its scan list */
-	SCAN_DONE,           /* wifi scan is complete */
-	CONNECTION_ERROR,    /* an error occurred during a connection request */
-	CREDENTIALS_REQUEST, /* 802.1x identity or password requested */
-	LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0 };
-
-
-/* Properties */
-NM_GOBJECT_PROPERTIES_DEFINE (NMSupplicantInterface,
-	PROP_IFACE,
-	PROP_SCANNING,
-	PROP_CURRENT_BSS,
-	PROP_IS_WIRELESS,
-	PROP_FAST_SUPPORTED,
-	PROP_AP_SUPPORT,
-);
-
-typedef struct {
-	char *         dev;
-	bool           is_wireless;
-	bool           fast_supported;
-	gboolean       has_credreq;  /* Whether querying 802.1x credentials is supported */
-	NMSupplicantFeature ap_support;   /* Lightweight AP mode support */
-	NMSupplicantFeature mac_randomization_support;
-	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;
-	char *         current_bss;
-
-	gint32         last_scan; /* timestamp as returned by nm_utils_get_monotonic_timestamp_s() */
-
-	NMSupplicantConfig *cfg;
-} NMSupplicantInterfacePrivate;
-
-/*********************************************************************************************/
-
-#define _NMLOG_DOMAIN           LOGD_SUPPLICANT
-#define _NMLOG_PREFIX_NAME      "sup-iface"
-#define _NMLOG(level, ...) \
-    G_STMT_START { \
-         char _sbuf[64]; \
-         \
-         nm_log ((level), _NMLOG_DOMAIN, \
-                 "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
-                 _NMLOG_PREFIX_NAME, \
-                 ((self) \
-                      ? nm_sprintf_buf (_sbuf, \
-                                        "[%p,%s]", \
-                                        (self), \
-                                        NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev) \
-                      : "") \
-                 _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
-    } G_STMT_END
-
-/*********************************************************************************************/
-
-static void
-emit_error_helper (NMSupplicantInterface *self, GError *error)
-{
-	char *name = NULL;
-
-	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_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);
-
-	if (priv->scanning)
-		priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
-
-	g_signal_emit (self, signals[BSS_UPDATED], 0,
-	               g_dbus_proxy_get_object_path (proxy),
-	               changed_properties);
-}
-
-static GVariant *
-_get_bss_proxy_properties (NMSupplicantInterface *self, GDBusProxy *proxy)
-{
-	gs_strfreev char **properties = NULL;
-	GVariantBuilder builder;
-	char **iter;
-
-	iter = properties = g_dbus_proxy_get_cached_property_names (proxy);
-	if (!iter)
-		return NULL;
-
-	g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
-	while (*iter) {
-		GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter);
-
-		g_variant_builder_add (&builder, "{sv}", *iter++, copy);
-		g_variant_unref (copy);
-	}
-
-	return g_variant_builder_end (&builder);
-}
-
-#define BSS_PROXY_INITED "bss-proxy-inited"
-
-static void
-on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	gs_free_error GError *error = NULL;
-	gs_unref_variant GVariant *props = NULL;
-
-	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
-		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			self = NM_SUPPLICANT_INTERFACE (user_data);
-			_LOGD ("failed to acquire BSS proxy: (%s)", error->message);
-			g_hash_table_remove (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->bss_proxies,
-			                     g_dbus_proxy_get_object_path (proxy));
-		}
-		return;
-	}
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-	props = _get_bss_proxy_properties (self, proxy);
-	if (!props)
-		return;
-
-	g_object_set_data (G_OBJECT (proxy), BSS_PROXY_INITED, GUINT_TO_POINTER (TRUE));
-
-	g_signal_emit (self, signals[NEW_BSS], 0,
-	               g_dbus_proxy_get_object_path (proxy),
-	               g_variant_ref_sink (props));
-}
-
-static void
-handle_new_bss (NMSupplicantInterface *self, const char *object_path)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GDBusProxy *bss_proxy;
-
-	g_return_if_fail (object_path != NULL);
-
-	if (g_hash_table_lookup (priv->bss_proxies, object_path))
-		return;
-
-	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
-set_state (NMSupplicantInterface *self, guint32 new_state)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	guint32 old_state = priv->state;
-
-	g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST);
-
-	if (new_state == priv->state)
-		return;
-
-	/* DOWN is a terminal state */
-	g_return_if_fail (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DOWN);
-
-	/* Cannot regress to READY, STARTING, or INIT from higher states */
-	if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY)
-		g_return_if_fail (new_state > NM_SUPPLICANT_INTERFACE_STATE_READY);
-
-	if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
-		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->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;
-
-	if (   priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING
-	    || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
-		priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
-
-	/* Disconnect reason is no longer relevant when not in the DISCONNECTED state */
-	if (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED)
-		priv->disconnect_reason = 0;
-
-	g_signal_emit (self, signals[STATE], 0,
-	               priv->state,
-	               old_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;
-
-	return -1;
-}
-
-static void
-set_state_from_string (NMSupplicantInterface *self, const char *new_state)
-{
-	int state;
-
-	state = wpas_state_string_to_enum (new_state);
-	if (state == -1) {
-		_LOGW ("unknown supplicant state '%s'", new_state);
-		return;
-	}
-	set_state (self, (guint32) state);
-}
-
-static void
-set_scanning (NMSupplicantInterface *self, gboolean new_scanning)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	if (priv->scanning != new_scanning) {
-		priv->scanning = new_scanning;
-
-		/* Cache time of last scan completion */
-		if (priv->scanning == FALSE)
-			priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
-
-		_notify (self, PROP_SCANNING);
-	}
-}
-
-gboolean
-nm_supplicant_interface_get_scanning (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv;
-
-	g_return_val_if_fail (self != NULL, FALSE);
-
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	if (priv->scanning)
-		return TRUE;
-	if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
-		return TRUE;
-	return FALSE;
-}
-
-const char *
-nm_supplicant_interface_get_current_bss (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv;
-
-	g_return_val_if_fail (self != NULL, FALSE);
-
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	return priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY ? priv->current_bss : NULL;
-}
-
-gint32
-nm_supplicant_interface_get_last_scan_time (NMSupplicantInterface *self)
-{
-	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->last_scan;
-}
-
-#define MATCH_PROPERTY(p, n, v, t) (!strcmp (p, n) && g_variant_is_of_type (v, t))
-
-static void
-parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	gboolean have_active = FALSE, have_ssid = FALSE;
-	gint32 max_scan_ssids = -1;
-	const char **array;
-
-	g_return_if_fail (capabilities && g_variant_is_of_type (capabilities, G_VARIANT_TYPE_VARDICT));
-
-	if (   g_variant_lookup (capabilities, "Scan", "^a&s", &array)
-	    && array) {
-		if (g_strv_contains (array, "active"))
-			have_active = TRUE;
-		if (g_strv_contains (array, "ssid"))
-			have_ssid = TRUE;
-		g_free (array);
-	}
-
-	if (g_variant_lookup (capabilities, "MaxScanSSID", "i", &max_scan_ssids)) {
-		/* We need active scan and SSID probe capabilities to care about MaxScanSSIDs */
-		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 (max_scan_ssids, 0, 5);
-			_LOGI ("supports %d scan SSIDs", priv->max_scan_ssids);
-		}
-	}
-}
-
-static void
-iface_check_ready (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	if (priv->ready_count && priv->state < NM_SUPPLICANT_INTERFACE_STATE_READY) {
-		priv->ready_count--;
-		if (priv->ready_count == 0)
-			set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY);
-	}
-}
-
-gboolean
-nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
-                                           const char *field,
-                                           const char *value,
-                                           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);
-	g_return_val_if_fail (value != NULL, FALSE);
-
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	g_return_val_if_fail (priv->has_credreq == TRUE, FALSE);
-
-	/* Need a network block object path */
-	g_return_val_if_fail (priv->net_path, FALSE);
-	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);
-	if (error && *error)
-		g_dbus_error_strip_remote_error (*error);
-
-	return !!reply;
-}
-
-static void
-iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	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.
-	 */
-
-	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 || _nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs"))
-		priv->has_credreq = TRUE;
-
-	_LOGD ("supplicant %s network credentials requests",
-	       priv->has_credreq ? "supports" : "does not support");
-
-	iface_check_ready (self);
-}
-
-NMSupplicantFeature
-nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self)
-{
-	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ap_support;
-}
-
-void
-nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
-                                        NMSupplicantFeature ap_support)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	/* Use the best indicator of support between the supplicant global
-	 * Capabilities property and the interface's introspection data.
-	 */
-	if (ap_support > priv->ap_support)
-		priv->ap_support = ap_support;
-}
-
-static void
-set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	gs_unref_variant GVariant *variant = NULL;
-	gs_free_error GError *error = NULL;
-
-	variant = _nm_dbus_proxy_call_finish (proxy, result,
-	                                      G_VARIANT_TYPE ("()"),
-	                                      &error);
-	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-		return;
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-	if (error)
-		_LOGW ("failed to enable scan MAC address randomization (%s)", error->message);
-	iface_check_ready (self);
-}
-
-static void
-iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	NMSupplicantInterfacePrivate *priv;
-	gs_unref_variant GVariant *variant = NULL;
-	gs_free_error GError *error = NULL;
-	const char *data;
-
-	variant = _nm_dbus_proxy_call_finish (proxy, result,
-	                                      G_VARIANT_TYPE ("(s)"),
-	                                      &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_get (variant, "(&s)", &data);
-
-		/* The ProbeRequest method only exists if AP mode has been enabled */
-		if (strstr (data, "ProbeRequest"))
-			priv->ap_support = NM_SUPPLICANT_FEATURE_YES;
-
-		if (strstr (data, "PreassocMacAddr")) {
-			priv->mac_randomization_support = NM_SUPPLICANT_FEATURE_YES;
-
-			/* Turn on MAC randomization during scans by default */
-			priv->ready_count++;
-			g_dbus_proxy_call (priv->iface_proxy,
-			                   DBUS_INTERFACE_PROPERTIES ".Set",
-			                   g_variant_new ("(ssv)",
-			                                  WPAS_DBUS_IFACE_INTERFACE,
-			                                  "PreassocMacAddr",
-			                                  g_variant_new_string ("0")),
-			                   G_DBUS_CALL_FLAGS_NONE,
-			                   -1,
-			                   priv->init_cancellable,
-			                   (GAsyncReadyCallback) set_preassoc_scan_mac_cb,
-			                   self);
-		}
-	}
-
-	iface_check_ready (self);
-}
-
-static void
-wpas_iface_scan_done (GDBusProxy *proxy,
-                      gboolean success,
-                      gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-	GVariant *props;
-	GHashTableIter iter;
-	char *bss_path;
-	GDBusProxy *bss_proxy;
-
-	/* Cache last scan completed time */
-	priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
-
-	g_signal_emit (self, signals[SCAN_DONE], 0, success);
-
-	/* Emit NEW_BSS so that wifi device has the APs (in case it removed them) */
-	g_hash_table_iter_init (&iter, priv->bss_proxies);
-	while (g_hash_table_iter_next (&iter, (gpointer) &bss_path, (gpointer) &bss_proxy)) {
-		if (g_object_get_data (G_OBJECT (bss_proxy), BSS_PROXY_INITED)) {
-			props = _get_bss_proxy_properties (self, bss_proxy);
-			if (props) {
-				g_signal_emit (self, signals[NEW_BSS], 0,
-				               bss_path,
-				               g_variant_ref_sink (props));
-				g_variant_unref (props);
-			}
-		}
-	}
-}
-
-static void
-wpas_iface_bss_added (GDBusProxy *proxy,
-                      const char *path,
-                      GVariant *props,
-                      gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	if (priv->scanning)
-		priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
-
-	handle_new_bss (self, path);
-}
-
-static void
-wpas_iface_bss_removed (GDBusProxy *proxy,
-                        const char *path,
-                        gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	g_signal_emit (self, signals[BSS_REMOVED], 0, path);
-	g_hash_table_remove (priv->bss_proxies, path);
-}
-
-static void
-wpas_iface_network_request (GDBusProxy *proxy,
-                            const char *path,
-                            const char *field,
-                            const char *message,
-                            gpointer user_data)
-{
-	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	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
-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;
-
-	g_object_freeze_notify (G_OBJECT (self));
-
-	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);
-	}
-
-	if (g_variant_lookup (changed_properties, "BSSs", "^a&o", &array)) {
-		iter = array;
-		while (*iter)
-			handle_new_bss (self, *iter++);
-		g_free (array);
-	}
-
-	if (g_variant_lookup (changed_properties, "CurrentBSS", "&o", &s)) {
-		if (strcmp (s, "/") == 0)
-			s = NULL;
-		if (g_strcmp0 (s, priv->current_bss) != 0) {
-			g_free (priv->current_bss);
-			priv->current_bss = g_strdup (s);
-			_notify (self, PROP_CURRENT_BSS);
-		}
-	}
-
-	v = g_variant_lookup_value (changed_properties, "Capabilities", G_VARIANT_TYPE_VARDICT);
-	if (v) {
-		parse_capabilities (self, v);
-		g_variant_unref (v);
-	}
-
-	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)
-			_LOGW ("connection disconnected (reason %d)", priv->disconnect_reason);
-	}
-
-	g_object_thaw_notify (G_OBJECT (self));
-}
-
-static void
-on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	NMSupplicantInterfacePrivate *priv;
-	gs_free_error GError *error = NULL;
-
-	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
-		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			self = NM_SUPPLICANT_INTERFACE (user_data);
-			_LOGW ("failed to acquire wpa_supplicant interface proxy: (%s)", error->message);
-			set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
-		}
-		return;
-	}
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	_nm_dbus_signal_connect (priv->iface_proxy, "ScanDone", G_VARIANT_TYPE ("(b)"),
-	                         G_CALLBACK (wpas_iface_scan_done), self);
-	_nm_dbus_signal_connect (priv->iface_proxy, "BSSAdded", G_VARIANT_TYPE ("(oa{sv})"),
-	                         G_CALLBACK (wpas_iface_bss_added), self);
-	_nm_dbus_signal_connect (priv->iface_proxy, "BSSRemoved", G_VARIANT_TYPE ("(o)"),
-	                         G_CALLBACK (wpas_iface_bss_removed), self);
-	_nm_dbus_signal_connect (priv->iface_proxy, "NetworkRequest", G_VARIANT_TYPE ("(oss)"),
-	                         G_CALLBACK (wpas_iface_network_request), self);
-
-	/* Scan result aging parameters */
-	g_dbus_proxy_call (priv->iface_proxy,
-	                   "org.freedesktop.DBus.Properties.Set",
-	                   g_variant_new ("(ssv)",
-	                                  WPAS_DBUS_IFACE_INTERFACE,
-	                                  "BSSExpireAge",
-	                                  g_variant_new_uint32 (250)),
-	                   G_DBUS_CALL_FLAGS_NONE,
-	                   -1,
-	                   priv->init_cancellable,
-	                   NULL,
-	                   NULL);
-	g_dbus_proxy_call (priv->iface_proxy,
-	                   "org.freedesktop.DBus.Properties.Set",
-	                   g_variant_new ("(ssv)",
-	                                  WPAS_DBUS_IFACE_INTERFACE,
-	                                  "BSSExpireCount",
-	                                  g_variant_new_uint32 (2)),
-	                   G_DBUS_CALL_FLAGS_NONE,
-	                   -1,
-	                   priv->init_cancellable,
-	                   NULL,
-	                   NULL);
-
-	/* 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 == NM_SUPPLICANT_FEATURE_UNKNOWN ||
-	    priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_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,
-		                   DBUS_INTERFACE_INTROSPECTABLE ".Introspect",
-		                   NULL,
-		                   G_DBUS_CALL_FLAGS_NONE,
-		                   -1,
-		                   priv->init_cancellable,
-		                   (GAsyncReadyCallback) iface_introspect_cb,
-		                   self);
-	}
-}
-
-static void
-interface_add_done (NMSupplicantInterface *self, const char *path)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	_LOGD ("interface added to supplicant");
-
-	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_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	NMSupplicantInterfacePrivate *priv;
-	gs_unref_variant GVariant *variant = NULL;
-	gs_free_error GError *error = NULL;
-	const char *path;
-
-	variant = _nm_dbus_proxy_call_finish (proxy, result,
-	                                      G_VARIANT_TYPE ("(o)"),
-	                                      &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_get (variant, "(&o)", &path);
-		interface_add_done (self, path);
-	} else {
-		g_dbus_error_strip_remote_error (error);
-		_LOGE ("error getting interface: %s", 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;
-	const char *path;
-
-	variant = _nm_dbus_proxy_call_finish (proxy, result,
-	                                      G_VARIANT_TYPE ("(o)"),
-	                                      &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_get (variant, "(&o)", &path);
-		interface_add_done (self, path);
-	} else if (_nm_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.
-		 */
-		g_dbus_error_strip_remote_error (error);
-		_LOGD ("failed to activate supplicant: %s", error->message);
-		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_INIT);
-	} else {
-		g_dbus_error_strip_remote_error (error);
-		_LOGE ("error adding interface: %s", error->message);
-		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
-	}
-}
-
-#if HAVE_WEXT
-#define DEFAULT_WIFI_DRIVER "nl80211,wext"
-#else
-#define DEFAULT_WIFI_DRIVER "nl80211"
-#endif
-
-static void
-on_wpas_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	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)) {
-			self = NM_SUPPLICANT_INTERFACE (user_data);
-			_LOGW ("failed to acquire wpa_supplicant proxy: (%s)", error->message);
-			set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
-		}
-		return;
-	}
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	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.
-	 */
-
-	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);
-}
-
-static void
-interface_add (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	/* Can only start the interface from INIT state */
-	g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT);
-
-	_LOGD ("adding interface to supplicant");
-
-	/* Move to starting to prevent double-calls of interface_add() */
-	set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING);
-
-	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);
-}
-
-void
-nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
-                                                  gboolean available)
-{
-	NMSupplicantInterfacePrivate *priv;
-
-	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
-
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	if (available) {
-		/* This can happen if the supplicant couldn't be activated but
-		 * for some reason was started after the activation failure.
-		 */
-		if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT)
-			interface_add (self);
-	} else {
-		/* The supplicant stopped; so we must tear down the interface */
-		set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
-	}
-}
-
-static void
-log_result_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	gs_unref_variant GVariant *reply = NULL;
-	gs_free_error GError *error = NULL;
-
-	reply = g_dbus_proxy_call_finish (proxy, result, &error);
-	if (   !reply
-	    && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
-	    && !strstr (error->message, "fi.w1.wpa_supplicant1.NotConnected")) {
-		g_dbus_error_strip_remote_error (error);
-		nm_log_warn (_NMLOG_DOMAIN, "%s: failed to %s: %s",
-		             _NMLOG_PREFIX_NAME, (const char *) user_data, error->message);
-	}
-}
-
-void
-nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
-{
-	NMSupplicantInterfacePrivate *priv;
-
-	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
-
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	/* 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)
-		return;
-
-	/* Disconnect from the current AP */
-	if (   (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
-	    && (priv->state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)) {
-		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) {
-		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 (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	gs_unref_variant GVariant *reply = NULL;
-	gs_free_error GError *error = NULL;
-
-	reply = g_dbus_proxy_call_finish (proxy, result, &error);
-	if (   !reply
-	    && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-		self = NM_SUPPLICANT_INTERFACE (user_data);
-		g_dbus_error_strip_remote_error (error);
-		_LOGW ("couldn't select network config: %s", error->message);
-		emit_error_helper (self, error);
-	}
-}
-
-static void
-call_select_network (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	/* We only select the network after all blobs (if any) have been set */
-	if (priv->blobs_left == 0) {
-		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 (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	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;
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	priv->blobs_left--;
-	if (reply)
-		call_select_network (self);
-	else {
-		g_dbus_error_strip_remote_error (error);
-		_LOGW ("couldn't set network certificates: %s", error->message);
-		emit_error_helper (self, error);
-	}
-}
-
-static void
-add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	NMSupplicantInterfacePrivate *priv;
-	gs_unref_variant GVariant *reply = NULL;
-	gs_free_error GError *error = NULL;
-	GHashTable *blobs;
-	GHashTableIter iter;
-	const char *blob_name;
-	GByteArray *blob_data;
-
-	reply = _nm_dbus_proxy_call_finish (proxy, result,
-	                                    G_VARIANT_TYPE ("(o)"),
-	                                    &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);
-
-	g_free (priv->net_path);
-	priv->net_path = NULL;
-
-	if (error) {
-		g_dbus_error_strip_remote_error (error);
-		_LOGW ("adding network to supplicant failed: %s", error->message);
-		emit_error_helper (self, error);
-		return;
-	}
-
-	g_variant_get (reply, "(o)", &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, (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
-add_network (NMSupplicantInterface *self)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	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);
-}
-
-static void
-set_mac_randomization_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	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;
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	if (!reply) {
-		g_dbus_error_strip_remote_error (error);
-		_LOGW ("couldn't send MAC randomization mode to the supplicant interface: %s",
-		       error->message);
-		emit_error_helper (self, error);
-		return;
-	}
-
-	_LOGT ("config: set MAC randomization to 0");
-	add_network (self);
-}
-
-static void
-set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	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;
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	if (!reply) {
-		g_dbus_error_strip_remote_error (error);
-		_LOGW ("couldn't send AP scan mode to the supplicant interface: %s",
-		       error->message);
-		emit_error_helper (self, error);
-		return;
-	}
-
-	_LOGI ("config: set interface ap_scan to %d",
-	       nm_supplicant_config_get_ap_scan (priv->cfg));
-
-	if (priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) {
-		/* Enable/disable association MAC address randomization */
-		g_dbus_proxy_call (priv->iface_proxy,
-		                   DBUS_INTERFACE_PROPERTIES ".Set",
-		                   g_variant_new ("(ssv)",
-		                                  WPAS_DBUS_IFACE_INTERFACE,
-		                                  "MacAddr",
-		                                  g_variant_new_string ("0")),
-		                   G_DBUS_CALL_FLAGS_NONE,
-		                   -1,
-		                   priv->assoc_cancellable,
-		                   (GAsyncReadyCallback) set_mac_randomization_cb,
-		                   self);
-	} else
-		add_network (self);
-}
-
-gboolean
-nm_supplicant_interface_set_config (NMSupplicantInterface *self,
-                                    NMSupplicantConfig *cfg,
-                                    GError **error)
-{
-	NMSupplicantInterfacePrivate *priv;
-
-	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
-
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	nm_supplicant_interface_disconnect (self);
-
-	/* Make sure the supplicant supports EAP-FAST before trying to send
-	 * it an EAP-FAST configuration.
-	 */
-	if (nm_supplicant_config_fast_required (cfg) && !priv->fast_supported) {
-		g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG,
-		             "EAP-FAST is not supported by the supplicant");
-		return FALSE;
-	}
-
-	g_clear_object (&priv->cfg);
-	if (cfg) {
-		priv->assoc_cancellable = g_cancellable_new ();
-		priv->cfg = g_object_ref (cfg);
-		g_dbus_proxy_call (priv->iface_proxy,
-		                   DBUS_INTERFACE_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
-scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
-{
-	NMSupplicantInterface *self;
-	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;
-
-	self = NM_SUPPLICANT_INTERFACE (user_data);
-
-	if (error) {
-		if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError"))
-			_LOGD ("could not get scan request result: %s", error->message);
-		else {
-			g_dbus_error_strip_remote_error (error);
-			_LOGW ("could not get scan request result: %s", error->message);
-		}
-	}
-	g_signal_emit (self, signals[SCAN_DONE], 0, error ? FALSE : TRUE);
-}
-
-gboolean
-nm_supplicant_interface_request_scan (NMSupplicantInterface *self, const GPtrArray *ssids)
-{
-	NMSupplicantInterfacePrivate *priv;
-	GVariantBuilder builder;
-	guint i;
-
-	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
-
-	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	/* Scan parameters */
-	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));
-	}
-
-	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
-nm_supplicant_interface_get_state (NMSupplicantInterface * self)
-{
-	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NM_SUPPLICANT_INTERFACE_STATE_DOWN);
-
-	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state;
-}
-
-const char *
-nm_supplicant_interface_state_to_string (guint32 state)
-{
-	switch (state) {
-	case NM_SUPPLICANT_INTERFACE_STATE_INIT:
-		return "init";
-	case NM_SUPPLICANT_INTERFACE_STATE_STARTING:
-		return "starting";
-	case NM_SUPPLICANT_INTERFACE_STATE_READY:
-		return "ready";
-	case NM_SUPPLICANT_INTERFACE_STATE_DISABLED:
-		return "disabled";
-	case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED:
-		return "disconnected";
-	case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE:
-		return "inactive";
-	case NM_SUPPLICANT_INTERFACE_STATE_SCANNING:
-		return "scanning";
-	case NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING:
-		return "authenticating";
-	case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING:
-		return "associating";
-	case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED:
-		return "associated";
-	case NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE:
-		return "4-way handshake";
-	case NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE:
-		return "group handshake";
-	case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
-		return "completed";
-	case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
-		return "down";
-	default:
-		break;
-	}
-	return "unknown";
-}
-
-const char *
-nm_supplicant_interface_get_object_path (NMSupplicantInterface *self)
-{
-	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL);
-
-	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->object_path;
-}
-
-const char *
-nm_supplicant_interface_get_ifname (NMSupplicantInterface *self)
-{
-	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL);
-
-	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev;
-}
-
-guint
-nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self)
-{
-	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), 0);
-
-	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->max_scan_ssids;
-}
-
-/*******************************************************************/
-
-NMSupplicantInterface *
-nm_supplicant_interface_new (const char *ifname,
-                             gboolean is_wireless,
-                             gboolean fast_supported,
-                             NMSupplicantFeature ap_support)
-{
-	g_return_val_if_fail (ifname != NULL, NULL);
-
-	return g_object_new (NM_TYPE_SUPPLICANT_INTERFACE,
-	                     NM_SUPPLICANT_INTERFACE_IFACE, ifname,
-	                     NM_SUPPLICANT_INTERFACE_IS_WIRELESS, is_wireless,
-	                     NM_SUPPLICANT_INTERFACE_FAST_SUPPORTED, fast_supported,
-	                     NM_SUPPLICANT_INTERFACE_AP_SUPPORT, (int) ap_support,
-	                     NULL);
-}
-
-static void
-nm_supplicant_interface_init (NMSupplicantInterface * self)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
-
-	priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT;
-	priv->bss_proxies = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
-}
-
-static void
-set_property (GObject *object,
-              guint prop_id,
-              const GValue *value,
-              GParamSpec *pspec)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
-
-	switch (prop_id) {
-	case PROP_IFACE:
-		/* construct-only */
-		priv->dev = g_value_dup_string (value);
-		g_return_if_fail (priv->dev);
-		break;
-	case PROP_IS_WIRELESS:
-		/* construct-only */
-		priv->is_wireless = g_value_get_boolean (value);
-		break;
-	case PROP_FAST_SUPPORTED:
-		/* construct-only */
-		priv->fast_supported = g_value_get_boolean (value);
-		break;
-	case PROP_AP_SUPPORT:
-		/* construct-only */
-		priv->ap_support = g_value_get_int (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-get_property (GObject *object,
-              guint prop_id,
-              GValue *value,
-              GParamSpec *pspec)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
-
-	switch (prop_id) {
-	case PROP_SCANNING:
-		g_value_set_boolean (value, priv->scanning);
-		break;
-	case PROP_CURRENT_BSS:
-		g_value_set_string (value, priv->current_bss);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-dispose (GObject *object)
-{
-	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
-
-	if (priv->iface_proxy)
-		g_signal_handlers_disconnect_by_data (priv->iface_proxy, NM_SUPPLICANT_INTERFACE (object));
-	g_clear_object (&priv->iface_proxy);
-
-	nm_clear_g_cancellable (&priv->init_cancellable);
-	nm_clear_g_cancellable (&priv->other_cancellable);
-	nm_clear_g_cancellable (&priv->assoc_cancellable);
-
-	g_clear_object (&priv->wpas_proxy);
-	g_clear_pointer (&priv->bss_proxies, (GDestroyNotify) g_hash_table_destroy);
-
-	g_clear_pointer (&priv->net_path, g_free);
-	g_clear_pointer (&priv->dev, g_free);
-	g_clear_pointer (&priv->object_path, g_free);
-	g_clear_pointer (&priv->current_bss, g_free);
-
-	g_clear_object (&priv->cfg);
-
-	/* Chain up to the parent class */
-	G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object);
-}
-
-static void
-nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate));
-
-	object_class->dispose = dispose;
-	object_class->set_property = set_property;
-	object_class->get_property = get_property;
-
-	/* Properties */
-	obj_properties[PROP_SCANNING] =
-	    g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_SCANNING, "", "",
-	                          FALSE,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_CURRENT_BSS] =
-	    g_param_spec_string (NM_SUPPLICANT_INTERFACE_CURRENT_BSS, "", "",
-	                         NULL,
-	                         G_PARAM_READABLE |
-	                         G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_IFACE] =
-	    g_param_spec_string (NM_SUPPLICANT_INTERFACE_IFACE, "", "",
-	                         NULL,
-	                         G_PARAM_WRITABLE |
-	                         G_PARAM_CONSTRUCT_ONLY |
-	                         G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_IS_WIRELESS] =
-	    g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_IS_WIRELESS, "", "",
-	                          TRUE,
-	                          G_PARAM_WRITABLE |
-	                          G_PARAM_CONSTRUCT_ONLY |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_FAST_SUPPORTED] =
-	    g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_FAST_SUPPORTED, "", "",
-	                          TRUE,
-	                          G_PARAM_WRITABLE |
-	                          G_PARAM_CONSTRUCT_ONLY |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_AP_SUPPORT] =
-	    g_param_spec_int (NM_SUPPLICANT_INTERFACE_AP_SUPPORT, "", "",
-	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
-	                      NM_SUPPLICANT_FEATURE_YES,
-	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
-	                      G_PARAM_WRITABLE |
-	                      G_PARAM_CONSTRUCT_ONLY |
-	                      G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-
-	/* Signals */
-	signals[STATE] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_STATE,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INT);
-
-	signals[REMOVED] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_REMOVED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, removed),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 0);
-
-	signals[NEW_BSS] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_NEW_BSS,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, new_bss),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
-
-	signals[BSS_UPDATED] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_UPDATED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, bss_updated),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
-
-	signals[BSS_REMOVED] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_REMOVED,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, bss_removed),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 1, G_TYPE_STRING);
-
-	signals[SCAN_DONE] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_SCAN_DONE,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_done),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
-	signals[CONNECTION_ERROR] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
-
-	signals[CREDENTIALS_REQUEST] =
-		g_signal_new (NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST,
-		              G_OBJECT_CLASS_TYPE (object_class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, credentials_request),
-		              NULL, NULL, NULL,
-		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
-}
-