about summary refs log tree commit diff
path: root/src/devices/wifi/nm-device-iwd.c
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2021-02-25 11:35:01 +0100
committerSebastien Bacher <seb128@ubuntu.com>2021-02-25 11:49:48 +0100
commit77dea84aa6e816f66dc622cec8ae2668eba3c068 (patch)
tree755536a0ed1fb36c2899e9bff9e092c4008a25c4 /src/devices/wifi/nm-device-iwd.c
parent47f08826b44eed651b44dc8bacb5b46bc4c52067 (diff)
parentfd80297a396cc4dd7da4da20208fb360aa369aa7 (diff)
Merge branch 'debian/master' into ubuntu/master
Diffstat (limited to 'src/devices/wifi/nm-device-iwd.c')
-rw-r--r--src/devices/wifi/nm-device-iwd.c2702
1 files changed, 0 insertions, 2702 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
deleted file mode 100644
index 64ac3de7..00000000
--- a/src/devices/wifi/nm-device-iwd.c
+++ /dev/null
@@ -1,2702 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2017 Intel Corporation
- */
-
-#include "nm-default.h"
-
-#include "nm-device-iwd.h"
-
-#include "devices/nm-device-private.h"
-#include "devices/nm-device.h"
-#include "nm-act-request.h"
-#include "nm-config.h"
-#include "nm-core-internal.h"
-#include "nm-dbus-manager.h"
-#include "nm-glib-aux/nm-ref-string.h"
-#include "nm-iwd-manager.h"
-#include "nm-libnm-core-intern/nm-common-macros.h"
-#include "nm-setting-8021x.h"
-#include "nm-setting-connection.h"
-#include "nm-setting-wireless-security.h"
-#include "nm-setting-wireless.h"
-#include "nm-std-aux/nm-dbus-compat.h"
-#include "nm-utils.h"
-#include "nm-wifi-common.h"
-#include "nm-wifi-utils.h"
-#include "settings/nm-settings-connection.h"
-#include "settings/nm-settings.h"
-#include "supplicant/nm-supplicant-types.h"
-
-#include "devices/nm-device-logging.h"
-_LOG_DECLARE_SELF(NMDeviceIwd);
-
-/*****************************************************************************/
-
-NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceIwd,
-                             PROP_MODE,
-                             PROP_BITRATE,
-                             PROP_ACCESS_POINTS,
-                             PROP_ACTIVE_ACCESS_POINT,
-                             PROP_CAPABILITIES,
-                             PROP_SCANNING,
-                             PROP_LAST_SCAN, );
-
-typedef struct {
-    GDBusObject *                 dbus_obj;
-    GDBusProxy *                  dbus_device_proxy;
-    GDBusProxy *                  dbus_station_proxy;
-    GDBusProxy *                  dbus_ap_proxy;
-    GDBusProxy *                  dbus_adhoc_proxy;
-    CList                         aps_lst_head;
-    NMWifiAP *                    current_ap;
-    GCancellable *                cancellable;
-    NMDeviceWifiCapabilities      capabilities;
-    NMActRequestGetSecretsCallId *wifi_secrets_id;
-    guint                         periodic_scan_id;
-    bool                          enabled : 1;
-    bool                          can_scan : 1;
-    bool                          can_connect : 1;
-    bool                          scanning : 1;
-    bool                          scan_requested : 1;
-    bool                          act_mode_switch : 1;
-    gint64                        last_scan;
-} NMDeviceIwdPrivate;
-
-struct _NMDeviceIwd {
-    NMDevice           parent;
-    NMDeviceIwdPrivate _priv;
-};
-
-struct _NMDeviceIwdClass {
-    NMDeviceClass parent;
-};
-
-/*****************************************************************************/
-
-G_DEFINE_TYPE(NMDeviceIwd, nm_device_iwd, NM_TYPE_DEVICE)
-
-#define NM_DEVICE_IWD_GET_PRIVATE(self) \
-    _NM_GET_PRIVATE(self, NMDeviceIwd, NM_IS_DEVICE_IWD, NMDevice)
-
-/*****************************************************************************/
-
-static void schedule_periodic_scan(NMDeviceIwd *self, gboolean initial_scan);
-
-static gboolean check_scanning_prohibited(NMDeviceIwd *self, gboolean periodic);
-
-/*****************************************************************************/
-
-static void
-_ap_dump(NMDeviceIwd *self, NMLogLevel log_level, const NMWifiAP *ap, const char *prefix)
-{
-    char buf[1024];
-
-    buf[0] = '\0';
-    _NMLOG(log_level,
-           LOGD_WIFI_SCAN,
-           "wifi-ap: %-7s %s",
-           prefix,
-           nm_wifi_ap_to_string(ap, buf, sizeof(buf), 0));
-}
-
-/* Callers ensure we're not removing current_ap */
-static void
-ap_add_remove(NMDeviceIwd *self,
-              gboolean     is_adding, /* or else is removing */
-              NMWifiAP *   ap,
-              gboolean     recheck_available_connections)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    if (is_adding) {
-        g_object_ref(ap);
-        ap->wifi_device = NM_DEVICE(self);
-        c_list_link_tail(&priv->aps_lst_head, &ap->aps_lst);
-        nm_dbus_object_export(NM_DBUS_OBJECT(ap));
-        _ap_dump(self, LOGL_DEBUG, ap, "added");
-        nm_device_wifi_emit_signal_access_point(NM_DEVICE(self), ap, TRUE);
-    } else {
-        ap->wifi_device = NULL;
-        c_list_unlink(&ap->aps_lst);
-        _ap_dump(self, LOGL_DEBUG, ap, "removed");
-    }
-
-    _notify(self, PROP_ACCESS_POINTS);
-
-    if (!is_adding) {
-        nm_device_wifi_emit_signal_access_point(NM_DEVICE(self), ap, FALSE);
-        nm_dbus_object_clear_and_unexport(&ap);
-    }
-
-    nm_device_emit_recheck_auto_activate(NM_DEVICE(self));
-    if (recheck_available_connections)
-        nm_device_recheck_available_connections(NM_DEVICE(self));
-}
-
-static void
-set_current_ap(NMDeviceIwd *self, NMWifiAP *new_ap, gboolean recheck_available_connections)
-{
-    NMDeviceIwdPrivate *priv;
-    NMWifiAP *          old_ap;
-
-    g_return_if_fail(NM_IS_DEVICE_IWD(self));
-
-    priv   = NM_DEVICE_IWD_GET_PRIVATE(self);
-    old_ap = priv->current_ap;
-
-    if (old_ap == new_ap)
-        return;
-
-    if (new_ap)
-        priv->current_ap = g_object_ref(new_ap);
-    else
-        priv->current_ap = NULL;
-
-    if (old_ap) {
-        if (nm_wifi_ap_get_fake(old_ap))
-            ap_add_remove(self, FALSE, old_ap, recheck_available_connections);
-        g_object_unref(old_ap);
-    }
-
-    _notify(self, PROP_ACTIVE_ACCESS_POINT);
-    _notify(self, PROP_MODE);
-}
-
-static void
-remove_all_aps(NMDeviceIwd *self)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMWifiAP *          ap, *ap_safe;
-
-    if (c_list_is_empty(&priv->aps_lst_head))
-        return;
-
-    set_current_ap(self, NULL, FALSE);
-
-    c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst)
-        ap_add_remove(self, FALSE, ap, FALSE);
-
-    nm_device_emit_recheck_auto_activate(NM_DEVICE(self));
-    nm_device_recheck_available_connections(NM_DEVICE(self));
-}
-
-static NM80211ApSecurityFlags
-ap_security_flags_from_network_type(const char *type)
-{
-    NM80211ApSecurityFlags flags;
-
-    if (nm_streq(type, "psk"))
-        flags = NM_802_11_AP_SEC_KEY_MGMT_PSK;
-    else if (nm_streq(type, "8021x"))
-        flags = NM_802_11_AP_SEC_KEY_MGMT_802_1X;
-    else
-        return NM_802_11_AP_SEC_NONE;
-
-    flags |= NM_802_11_AP_SEC_PAIR_CCMP;
-    flags |= NM_802_11_AP_SEC_GROUP_CCMP;
-    return flags;
-}
-
-static void
-insert_ap_from_network(NMDeviceIwd *self,
-                       GHashTable * aps,
-                       const char * path,
-                       gint64       last_seen_msec,
-                       int16_t      signal,
-                       uint32_t     ap_id)
-{
-    gs_unref_object GDBusProxy *network_proxy = NULL;
-    gs_unref_variant GVariant *name_value     = NULL;
-    gs_unref_variant GVariant *type_value     = NULL;
-    nm_auto_ref_string NMRefString *bss_path  = NULL;
-    const char *                    name;
-    const char *                    type;
-    NMSupplicantBssInfo             bss_info;
-    uint8_t                         bssid[6];
-    NMWifiAP *                      ap;
-    gs_unref_bytes GBytes *ssid = NULL;
-
-    bss_path = nm_ref_string_new(path);
-
-    if (g_hash_table_lookup(aps, path)) {
-        _LOGD(LOGD_WIFI, "Duplicate network at %s", path);
-        return;
-    }
-
-    network_proxy =
-        nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(), path, NM_IWD_NETWORK_INTERFACE);
-    if (!network_proxy)
-        return;
-
-    name_value = g_dbus_proxy_get_cached_property(network_proxy, "Name");
-    type_value = g_dbus_proxy_get_cached_property(network_proxy, "Type");
-    if (!name_value || !g_variant_is_of_type(name_value, G_VARIANT_TYPE_STRING) || !type_value
-        || !g_variant_is_of_type(type_value, G_VARIANT_TYPE_STRING))
-        return;
-
-    name = g_variant_get_string(name_value, NULL);
-    type = g_variant_get_string(type_value, NULL);
-
-    if (nm_streq(type, "wep")) {
-        /* WEP not supported */
-        return;
-    }
-
-    /* What we get from IWD are networks, or ESSs, that may contain
-     * multiple APs, or BSSs, each.  We don't get information about any
-     * specific BSSs within an ESS but we can safely present each ESS
-     * as an individual BSS to NM, which will be seen as ESSs comprising
-     * a single BSS each.  NM won't be able to handle roaming but IWD
-     * already does that.  We fake the BSSIDs as they don't play any
-     * role either.
-     */
-    bssid[0] = 0x00;
-    bssid[1] = 0x01;
-    bssid[2] = 0x02;
-    bssid[3] = ap_id >> 16;
-    bssid[4] = ap_id >> 8;
-    bssid[5] = ap_id;
-
-    ssid = g_bytes_new(name, NM_MIN(32u, strlen(name)));
-
-    bss_info = (NMSupplicantBssInfo){
-        .bss_path       = bss_path,
-        .last_seen_msec = last_seen_msec,
-        .bssid_valid    = TRUE,
-        .mode           = NM_802_11_MODE_INFRA,
-        .rsn_flags      = ap_security_flags_from_network_type(type),
-        .ssid           = ssid,
-        .signal_percent = nm_wifi_utils_level_to_quality(signal / 100),
-        .frequency      = 2417,
-        .max_rate       = 65000,
-    };
-    memcpy(bss_info.bssid, bssid, sizeof(bssid));
-
-    ap = nm_wifi_ap_new_from_properties(&bss_info);
-
-    nm_assert(bss_path == nm_wifi_ap_get_supplicant_path(ap));
-
-    g_hash_table_insert(aps, bss_path, ap);
-}
-
-static void
-get_ordered_networks_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-    NMDeviceIwd *       self = user_data;
-    NMDeviceIwdPrivate *priv;
-    gs_free_error GError *error        = NULL;
-    gs_unref_variant GVariant *variant = NULL;
-    GVariantIter *             networks;
-    const char *               path, *name, *type;
-    int16_t                    signal;
-    NMWifiAP *                 ap, *ap_safe, *new_ap;
-    gboolean                   changed = FALSE;
-    GHashTableIter             ap_iter;
-    gs_unref_hashtable GHashTable *new_aps = NULL;
-    gboolean                       compat;
-    const char *                   return_sig;
-    static uint32_t                ap_id = 0;
-    gint64                         last_seen_msec;
-
-    variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
-    if (!variant) {
-        _LOGE(LOGD_WIFI, "Station.GetOrderedNetworks failed: %s", error->message);
-        return;
-    }
-
-    priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    /* Depending on whether we're using the Station interface or the Device
-     * interface for compatibility with IWD <= 0.7, the return signature of
-     * GetOrderedNetworks will be different.
-     */
-    compat     = priv->dbus_station_proxy == priv->dbus_device_proxy;
-    return_sig = compat ? "(a(osns))" : "(a(on))";
-
-    if (!g_variant_is_of_type(variant, G_VARIANT_TYPE(return_sig))) {
-        _LOGE(LOGD_WIFI,
-              "Station.GetOrderedNetworks returned type %s instead of %s",
-              g_variant_get_type_string(variant),
-              return_sig);
-        return;
-    }
-
-    new_aps = g_hash_table_new_full(nm_direct_hash, NULL, NULL, g_object_unref);
-
-    g_variant_get(variant, return_sig, &networks);
-
-    last_seen_msec = nm_utils_get_monotonic_timestamp_msec();
-    if (compat) {
-        while (g_variant_iter_next(networks, "(&o&sn&s)", &path, &name, &signal, &type))
-            insert_ap_from_network(self, new_aps, path, last_seen_msec, signal, ap_id++);
-    } else {
-        while (g_variant_iter_next(networks, "(&on)", &path, &signal))
-            insert_ap_from_network(self, new_aps, path, last_seen_msec, signal, ap_id++);
-    }
-
-    g_variant_iter_free(networks);
-
-    c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst) {
-        new_ap = g_hash_table_lookup(new_aps, nm_wifi_ap_get_supplicant_path(ap));
-        if (new_ap) {
-            if (nm_wifi_ap_set_strength(ap, nm_wifi_ap_get_strength(new_ap))) {
-                _ap_dump(self, LOGL_TRACE, ap, "updated");
-                changed = TRUE;
-            }
-            g_hash_table_remove(new_aps, nm_wifi_ap_get_supplicant_path(ap));
-            continue;
-        }
-
-        if (ap == priv->current_ap) {
-            /* Normally IWD will prevent the current AP from being
-             * removed from the list and set a low signal strength,
-             * but just making sure.
-             */
-            continue;
-        }
-
-        ap_add_remove(self, FALSE, ap, FALSE);
-        changed = TRUE;
-    }
-
-    g_hash_table_iter_init(&ap_iter, new_aps);
-    while (g_hash_table_iter_next(&ap_iter, NULL, (gpointer) &ap)) {
-        ap_add_remove(self, TRUE, ap, FALSE);
-        g_hash_table_iter_remove(&ap_iter);
-        changed = TRUE;
-    }
-
-    if (changed) {
-        nm_device_emit_recheck_auto_activate(NM_DEVICE(self));
-        nm_device_recheck_available_connections(NM_DEVICE(self));
-    }
-}
-
-static void
-update_aps(NMDeviceIwd *self)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    if (!priv->cancellable)
-        priv->cancellable = g_cancellable_new();
-
-    g_dbus_proxy_call(priv->dbus_station_proxy,
-                      "GetOrderedNetworks",
-                      NULL,
-                      G_DBUS_CALL_FLAGS_NONE,
-                      2000,
-                      priv->cancellable,
-                      get_ordered_networks_cb,
-                      self);
-}
-
-static void
-send_disconnect(NMDeviceIwd *self)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    g_dbus_proxy_call(priv->dbus_station_proxy,
-                      "Disconnect",
-                      NULL,
-                      G_DBUS_CALL_FLAGS_NONE,
-                      -1,
-                      NULL,
-                      NULL,
-                      NULL);
-}
-
-static void
-wifi_secrets_cancel(NMDeviceIwd *self)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    if (priv->wifi_secrets_id)
-        nm_act_request_cancel_secrets(NULL, priv->wifi_secrets_id);
-    nm_assert(!priv->wifi_secrets_id);
-}
-
-static void
-cleanup_association_attempt(NMDeviceIwd *self, gboolean disconnect)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    wifi_secrets_cancel(self);
-
-    set_current_ap(self, NULL, TRUE);
-
-    if (disconnect && priv->dbus_station_proxy)
-        send_disconnect(self);
-}
-
-static void
-reset_mode(NMDeviceIwd *       self,
-           GCancellable *      cancellable,
-           GAsyncReadyCallback callback,
-           gpointer            user_data)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    g_dbus_proxy_call(
-        priv->dbus_device_proxy,
-        DBUS_INTERFACE_PROPERTIES ".Set",
-        g_variant_new("(ssv)", NM_IWD_DEVICE_INTERFACE, "Mode", g_variant_new_string("station")),
-        G_DBUS_CALL_FLAGS_NONE,
-        2000,
-        cancellable,
-        callback,
-        user_data);
-}
-
-static void
-deactivate(NMDevice *device)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    if (!priv->dbus_obj)
-        return;
-
-    cleanup_association_attempt(self, TRUE);
-    priv->act_mode_switch = FALSE;
-
-    if (!priv->dbus_station_proxy)
-        reset_mode(self, NULL, NULL, NULL);
-}
-
-static void
-disconnect_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-    gs_unref_object NMDeviceIwd *self = NULL;
-    NMDeviceDeactivateCallback   callback;
-    gpointer                     callback_user_data;
-    gs_unref_variant GVariant *variant = NULL;
-    gs_free_error GError *error        = NULL;
-
-    nm_utils_user_data_unpack(user_data, &self, &callback, &callback_user_data);
-
-    variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
-    callback(NM_DEVICE(self), error, callback_user_data);
-}
-
-static void
-disconnect_cb_on_idle(gpointer user_data, GCancellable *cancellable)
-{
-    gs_unref_object NMDeviceIwd *self = NULL;
-    NMDeviceDeactivateCallback   callback;
-    gpointer                     callback_user_data;
-    gs_free_error GError *cancelled_error = NULL;
-
-    nm_utils_user_data_unpack(user_data, &self, &callback, &callback_user_data);
-
-    g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error);
-    callback(NM_DEVICE(self), cancelled_error, callback_user_data);
-}
-
-static void
-deactivate_async(NMDevice *                 device,
-                 GCancellable *             cancellable,
-                 NMDeviceDeactivateCallback callback,
-                 gpointer                   callback_user_data)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    gpointer            user_data;
-
-    nm_assert(G_IS_CANCELLABLE(cancellable));
-    nm_assert(callback);
-
-    user_data = nm_utils_user_data_pack(g_object_ref(self), callback, callback_user_data);
-
-    if (!priv->dbus_obj) {
-        nm_utils_invoke_on_idle(cancellable, disconnect_cb_on_idle, user_data);
-        return;
-    }
-
-    cleanup_association_attempt(self, FALSE);
-    priv->act_mode_switch = FALSE;
-
-    if (priv->dbus_station_proxy) {
-        g_dbus_proxy_call(priv->dbus_station_proxy,
-                          "Disconnect",
-                          NULL,
-                          G_DBUS_CALL_FLAGS_NONE,
-                          -1,
-                          cancellable,
-                          disconnect_cb,
-                          user_data);
-    } else
-        reset_mode(self, cancellable, disconnect_cb, user_data);
-}
-
-static gboolean
-is_connection_known_network(NMConnection *connection)
-{
-    NMSettingWireless *  s_wireless;
-    NMIwdNetworkSecurity security;
-    gboolean             security_ok;
-    GBytes *             ssid;
-    gs_free char *       ssid_utf8 = NULL;
-
-    s_wireless = nm_connection_get_setting_wireless(connection);
-    if (!s_wireless)
-        return FALSE;
-
-    ssid = nm_setting_wireless_get_ssid(s_wireless);
-    if (!ssid)
-        return FALSE;
-
-    ssid_utf8 = _nm_utils_ssid_to_utf8(ssid);
-
-    security = nm_wifi_connection_get_iwd_security(connection, &security_ok);
-    if (!security_ok)
-        return FALSE;
-
-    return nm_iwd_manager_is_known_network(nm_iwd_manager_get(), ssid_utf8, security);
-}
-
-static gboolean
-is_ap_known_network(NMWifiAP *ap)
-{
-    gs_unref_object GDBusProxy *network_proxy = NULL;
-    gs_unref_variant GVariant *known_network  = NULL;
-
-    network_proxy =
-        nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(),
-                                          nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)),
-                                          NM_IWD_NETWORK_INTERFACE);
-    if (!network_proxy)
-        return FALSE;
-
-    known_network = g_dbus_proxy_get_cached_property(network_proxy, "KnownNetwork");
-    return nm_g_variant_is_of_type(known_network, G_VARIANT_TYPE_OBJECT_PATH);
-}
-
-static gboolean
-check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
-{
-    NMDeviceIwd *        self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMSettingWireless *  s_wireless;
-    const char *         mac;
-    const char *const *  mac_blacklist;
-    int                  i;
-    const char *         perm_hw_addr;
-    const char *         mode;
-    NMIwdNetworkSecurity security;
-    gboolean             mapped;
-
-    if (!NM_DEVICE_CLASS(nm_device_iwd_parent_class)
-             ->check_connection_compatible(device, connection, error))
-        return FALSE;
-
-    s_wireless = nm_connection_get_setting_wireless(connection);
-
-    perm_hw_addr = nm_device_get_permanent_hw_address(device);
-    mac          = nm_setting_wireless_get_mac_address(s_wireless);
-    if (perm_hw_addr) {
-        if (mac && !nm_utils_hwaddr_matches(mac, -1, perm_hw_addr, -1)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "device MAC address does not match the profile");
-            return FALSE;
-        }
-
-        /* Check for MAC address blacklist */
-        mac_blacklist = nm_setting_wireless_get_mac_address_blacklist(s_wireless);
-        for (i = 0; mac_blacklist[i]; i++) {
-            nm_assert(nm_utils_hwaddr_valid(mac_blacklist[i], ETH_ALEN));
-
-            if (nm_utils_hwaddr_matches(mac_blacklist[i], -1, perm_hw_addr, -1)) {
-                nm_utils_error_set_literal(error,
-                                           NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                           "MAC address blacklisted");
-                return FALSE;
-            }
-        }
-    } else if (mac) {
-        nm_utils_error_set_literal(error,
-                                   NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                   "device has no valid MAC address as required by profile");
-        return FALSE;
-    }
-
-    security = nm_wifi_connection_get_iwd_security(connection, &mapped);
-    if (!mapped) {
-        nm_utils_error_set_literal(error,
-                                   NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                   "connection authentication type not supported by IWD backend");
-        return FALSE;
-    }
-
-    mode = nm_setting_wireless_get_mode(s_wireless);
-
-    /* Hidden SSIDs only supported in client mode */
-    if (nm_setting_wireless_get_hidden(s_wireless)
-        && !NM_IN_STRSET(mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) {
-        nm_utils_error_set_literal(
-            error,
-            NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-            "non-infrastructure hidden networks not supported by the IWD backend");
-        return FALSE;
-    }
-
-    if (NM_IN_STRSET(mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) {
-        /* 8021x networks can only be used if they've been provisioned on the IWD side and
-         * thus are Known Networks.
-         */
-        if (security == NM_IWD_NETWORK_SECURITY_8021X) {
-            if (!is_connection_known_network(connection)) {
-                nm_utils_error_set_literal(error,
-                                           NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                           "802.1x connections must have IWD provisioning files");
-                return FALSE;
-            }
-        } else if (!NM_IN_SET(security,
-                              NM_IWD_NETWORK_SECURITY_NONE,
-                              NM_IWD_NETWORK_SECURITY_PSK)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "IWD backend only supports Open, PSK and 802.1x network "
-                                       "authentication in Infrastructure mode");
-            return FALSE;
-        }
-    } else if (nm_streq(mode, NM_SETTING_WIRELESS_MODE_AP)) {
-        if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "device does not support Access Point mode");
-            return FALSE;
-        }
-
-        if (!NM_IN_SET(security, NM_IWD_NETWORK_SECURITY_PSK)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "IWD backend only supports PSK authentication in AP mode");
-            return FALSE;
-        }
-    } else if (nm_streq(mode, NM_SETTING_WIRELESS_MODE_ADHOC)) {
-        if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "device does not support Ad-Hoc mode");
-            return FALSE;
-        }
-
-        if (!NM_IN_SET(security, NM_IWD_NETWORK_SECURITY_NONE, NM_IWD_NETWORK_SECURITY_PSK)) {
-            nm_utils_error_set_literal(
-                error,
-                NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                "IWD backend only supports Open and PSK authentication in Ad-Hoc mode");
-            return FALSE;
-        }
-    } else {
-        nm_utils_error_set_literal(error,
-                                   NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                   "%s type profiles not supported by IWD backend");
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static gboolean
-check_connection_available(NMDevice *                     device,
-                           NMConnection *                 connection,
-                           NMDeviceCheckConAvailableFlags flags,
-                           const char *                   specific_object,
-                           GError **                      error)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMSettingWireless * s_wifi;
-    const char *        mode;
-    NMWifiAP *          ap = NULL;
-
-    s_wifi = nm_connection_get_setting_wireless(connection);
-    g_return_val_if_fail(s_wifi, FALSE);
-
-    /* a connection that is available for a certain @specific_object, MUST
-     * also be available in general (without @specific_object). */
-
-    if (specific_object) {
-        ap = nm_wifi_ap_lookup_for_device(NM_DEVICE(self), specific_object);
-        if (!ap) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "requested access point not found");
-            return FALSE;
-        }
-        if (!nm_wifi_ap_check_compatible(ap, connection)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "requested access point is not compatible with profile");
-            return FALSE;
-        }
-    }
-
-    /* AP and Ad-Hoc connections can be activated independent of the scan list */
-    mode = nm_setting_wireless_get_mode(s_wifi);
-    if (NM_IN_STRSET(mode, NM_SETTING_WIRELESS_MODE_AP, NM_SETTING_WIRELESS_MODE_ADHOC))
-        return TRUE;
-
-    if (NM_FLAGS_HAS(flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
-        return TRUE;
-
-    if (!ap)
-        ap = nm_wifi_aps_find_first_compatible(&priv->aps_lst_head, connection);
-
-    if (!ap) {
-        nm_utils_error_set_literal(error,
-                                   NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                   "no compatible access point found");
-        return FALSE;
-    }
-
-    /* 8021x networks can only be used if they've been provisioned on the IWD side and
-     * thus are Known Networks.
-     */
-    if (nm_wifi_connection_get_iwd_security(connection, NULL) == NM_IWD_NETWORK_SECURITY_8021X) {
-        if (!is_ap_known_network(ap)) {
-            nm_utils_error_set_literal(
-                error,
-                NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                "802.1x network is not an IWD Known Network (missing provisioning file?)");
-            return FALSE;
-        }
-    }
-
-    return TRUE;
-}
-
-static gboolean
-complete_connection(NMDevice *           device,
-                    NMConnection *       connection,
-                    const char *         specific_object,
-                    NMConnection *const *existing_connections,
-                    GError **            error)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMSettingWireless * s_wifi;
-    gs_free char *      ssid_utf8 = NULL;
-    NMWifiAP *          ap;
-    GBytes *            ssid;
-    GBytes *            setting_ssid = NULL;
-    gboolean            hidden       = FALSE;
-    const char *        mode;
-
-    s_wifi = nm_connection_get_setting_wireless(connection);
-
-    mode = s_wifi ? nm_setting_wireless_get_mode(s_wifi) : NULL;
-
-    if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP)) {
-        if (!nm_setting_verify(NM_SETTING(s_wifi), connection, error))
-            return FALSE;
-        ap = NULL;
-    } else if (!specific_object) {
-        /* If not given a specific object, we need at minimum an SSID */
-        if (!s_wifi) {
-            g_set_error_literal(error,
-                                NM_DEVICE_ERROR,
-                                NM_DEVICE_ERROR_INVALID_CONNECTION,
-                                "A 'wireless' setting is required if no AP path was given.");
-            return FALSE;
-        }
-
-        setting_ssid = nm_setting_wireless_get_ssid(s_wifi);
-        if (!setting_ssid || g_bytes_get_size(setting_ssid) == 0) {
-            g_set_error_literal(
-                error,
-                NM_DEVICE_ERROR,
-                NM_DEVICE_ERROR_INVALID_CONNECTION,
-                "A 'wireless' setting with a valid SSID is required if no AP path was given.");
-            return FALSE;
-        }
-
-        /* Find a compatible AP in the scan list */
-        ap = nm_wifi_aps_find_first_compatible(&priv->aps_lst_head, connection);
-        if (!ap) {
-            /* If we still don't have an AP, then the WiFI settings needs to be
-             * fully specified by the client.  Might not be able to find an AP
-             * if the network isn't broadcasting the SSID for example.
-             */
-            if (!nm_setting_verify(NM_SETTING(s_wifi), connection, error))
-                return FALSE;
-
-            hidden = TRUE;
-        }
-    } else {
-        ap = nm_wifi_ap_lookup_for_device(NM_DEVICE(self), specific_object);
-        if (!ap) {
-            g_set_error(error,
-                        NM_DEVICE_ERROR,
-                        NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND,
-                        "The access point %s was not in the scan list.",
-                        specific_object);
-            return FALSE;
-        }
-    }
-
-    /* Add a wifi setting if one doesn't exist yet */
-    if (!s_wifi) {
-        s_wifi = (NMSettingWireless *) nm_setting_wireless_new();
-        nm_connection_add_setting(connection, NM_SETTING(s_wifi));
-    }
-
-    ssid = nm_setting_wireless_get_ssid(s_wifi);
-    if (!ssid && ap)
-        ssid = nm_wifi_ap_get_ssid(ap);
-
-    if (!ssid) {
-        g_set_error_literal(error,
-                            NM_DEVICE_ERROR,
-                            NM_DEVICE_ERROR_INVALID_CONNECTION,
-                            "A 'wireless' setting with a valid SSID is required.");
-        return FALSE;
-    }
-
-    if (ap) {
-        if (!nm_wifi_ap_complete_connection(ap,
-                                            connection,
-                                            nm_wifi_utils_is_manf_default_ssid(ssid),
-                                            error))
-            return FALSE;
-    }
-
-    ssid_utf8 = _nm_utils_ssid_to_utf8(ssid);
-    nm_utils_complete_generic(
-        nm_device_get_platform(device),
-        connection,
-        NM_SETTING_WIRELESS_SETTING_NAME,
-        existing_connections,
-        ssid_utf8,
-        ssid_utf8,
-        NULL,
-        nm_setting_wireless_get_mac_address(s_wifi) ? NULL : nm_device_get_iface(device),
-        TRUE);
-
-    if (hidden)
-        g_object_set(s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL);
-
-    return TRUE;
-}
-
-static gboolean
-get_variant_boolean(GVariant *v, const char *property)
-{
-    if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) {
-        nm_log_warn(LOGD_DEVICE | LOGD_WIFI,
-                    "Property %s not cached or not boolean type",
-                    property);
-
-        return FALSE;
-    }
-
-    return g_variant_get_boolean(v);
-}
-
-static const char *
-get_variant_state(GVariant *v)
-{
-    if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_STRING)) {
-        nm_log_warn(LOGD_DEVICE | LOGD_WIFI, "State property not cached or not a string");
-
-        return "unknown";
-    }
-
-    return g_variant_get_string(v, NULL);
-}
-
-static gboolean
-is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
-{
-    NMDeviceIwd *       self  = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv  = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDeviceState       state = nm_device_get_state(device);
-
-    /* Available if either the device is UP and in station mode
-     * or in AP/Ad-Hoc modes while activating or activated.  Device
-     * may be temporarily DOWN while activating or deactivating and
-     * we don't want it to be marked unavailable because of this.
-     *
-     * For reference:
-     * We call nm_device_queue_recheck_available whenever
-     * priv->enabled changes or priv->dbus_station_proxy changes.
-     */
-    return priv->dbus_obj && priv->enabled
-           && (priv->dbus_station_proxy
-               || (state >= NM_DEVICE_STATE_CONFIG && state <= NM_DEVICE_STATE_DEACTIVATING));
-}
-
-static gboolean
-get_autoconnect_allowed(NMDevice *device)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(NM_DEVICE_IWD(device));
-
-    return priv->can_connect;
-}
-
-static gboolean
-can_auto_connect(NMDevice *device, NMSettingsConnection *sett_conn, char **specific_object)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMConnection *      connection;
-    NMSettingWireless * s_wifi;
-    NMWifiAP *          ap;
-    const char *        mode;
-    guint64             timestamp = 0;
-
-    nm_assert(!specific_object || !*specific_object);
-
-    if (!NM_DEVICE_CLASS(nm_device_iwd_parent_class)->can_auto_connect(device, sett_conn, NULL))
-        return FALSE;
-
-    connection = nm_settings_connection_get_connection(sett_conn);
-
-    s_wifi = nm_connection_get_setting_wireless(connection);
-    g_return_val_if_fail(s_wifi, FALSE);
-
-    /* Don't auto-activate AP or Ad-Hoc connections.
-     * Note the wpa_supplicant backend has the opposite policy.
-     */
-    mode = nm_setting_wireless_get_mode(s_wifi);
-    if (mode && g_strcmp0(mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0)
-        return FALSE;
-
-    /* Don't autoconnect to networks that have been tried at least once
-     * but haven't been successful, since these are often accidental choices
-     * from the menu and the user may not know the password.
-     */
-    if (nm_settings_connection_get_timestamp(sett_conn, &timestamp)) {
-        if (timestamp == 0)
-            return FALSE;
-    }
-
-    ap = nm_wifi_aps_find_first_compatible(&priv->aps_lst_head, connection);
-    if (ap) {
-        /* All good; connection is usable */
-        NM_SET_OUT(specific_object, g_strdup(nm_dbus_object_get_path(NM_DBUS_OBJECT(ap))));
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-const CList *
-_nm_device_iwd_get_aps(NMDeviceIwd *self)
-{
-    return &NM_DEVICE_IWD_GET_PRIVATE(self)->aps_lst_head;
-}
-
-static void
-scan_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-    NMDeviceIwd *       self = user_data;
-    NMDeviceIwdPrivate *priv;
-    gs_unref_variant GVariant *variant = NULL;
-    gs_free_error GError *error        = NULL;
-
-    variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
-    if (!variant && nm_utils_error_is_cancelled(error))
-        return;
-
-    priv                 = NM_DEVICE_IWD_GET_PRIVATE(self);
-    priv->scan_requested = FALSE;
-    priv->last_scan      = nm_utils_get_monotonic_timestamp_msec();
-    _notify(self, PROP_LAST_SCAN);
-
-    /* On success, priv->scanning becomes true right before or right
-     * after this callback, so the next automatic scan will be
-     * scheduled when priv->scanning goes back to false.  On error,
-     * schedule a retry now.
-     */
-    if (error && !priv->scanning)
-        schedule_periodic_scan(self, FALSE);
-}
-
-static void
-dbus_request_scan_cb(NMDevice *             device,
-                     GDBusMethodInvocation *context,
-                     NMAuthSubject *        subject,
-                     GError *               error,
-                     gpointer               user_data)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv;
-    gs_unref_variant GVariant *scan_options = user_data;
-
-    if (error) {
-        g_dbus_method_invocation_return_gerror(context, error);
-        return;
-    }
-
-    if (check_scanning_prohibited(self, FALSE)) {
-        g_dbus_method_invocation_return_error_literal(context,
-                                                      NM_DEVICE_ERROR,
-                                                      NM_DEVICE_ERROR_NOT_ALLOWED,
-                                                      "Scanning not allowed at this time");
-        return;
-    }
-
-    priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    if (!priv->can_scan) {
-        g_dbus_method_invocation_return_error_literal(context,
-                                                      NM_DEVICE_ERROR,
-                                                      NM_DEVICE_ERROR_NOT_ALLOWED,
-                                                      "Scanning not allowed while unavailable");
-        return;
-    }
-
-    if (scan_options) {
-        gs_unref_variant GVariant *val = g_variant_lookup_value(scan_options, "ssids", NULL);
-
-        if (val) {
-            g_dbus_method_invocation_return_error_literal(context,
-                                                          NM_DEVICE_ERROR,
-                                                          NM_DEVICE_ERROR_NOT_ALLOWED,
-                                                          "'ssid' scan option not supported");
-            return;
-        }
-    }
-
-    if (!priv->scanning && !priv->scan_requested) {
-        g_dbus_proxy_call(priv->dbus_station_proxy,
-                          "Scan",
-                          NULL,
-                          G_DBUS_CALL_FLAGS_NONE,
-                          -1,
-                          priv->cancellable,
-                          scan_cb,
-                          self);
-        priv->scan_requested = TRUE;
-    }
-
-    g_dbus_method_invocation_return_value(context, NULL);
-}
-
-void
-_nm_device_iwd_request_scan(NMDeviceIwd *self, GVariant *options, GDBusMethodInvocation *invocation)
-{
-    NMDeviceIwdPrivate *priv   = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDevice *          device = NM_DEVICE(self);
-
-    if (!priv->can_scan) {
-        g_dbus_method_invocation_return_error_literal(invocation,
-                                                      NM_DEVICE_ERROR,
-                                                      NM_DEVICE_ERROR_NOT_ALLOWED,
-                                                      "Scanning not allowed while unavailable");
-        return;
-    }
-
-    nm_device_auth_request(device,
-                           invocation,
-                           NULL,
-                           NM_AUTH_PERMISSION_WIFI_SCAN,
-                           TRUE,
-                           NULL,
-                           dbus_request_scan_cb,
-                           nm_g_variant_ref(options));
-}
-
-static gboolean
-check_scanning_prohibited(NMDeviceIwd *self, gboolean periodic)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    g_return_val_if_fail(priv->dbus_obj != NULL, TRUE);
-
-    switch (nm_device_get_state(NM_DEVICE(self))) {
-    case NM_DEVICE_STATE_UNKNOWN:
-    case NM_DEVICE_STATE_UNMANAGED:
-    case NM_DEVICE_STATE_UNAVAILABLE:
-    case NM_DEVICE_STATE_PREPARE:
-    case NM_DEVICE_STATE_CONFIG:
-    case NM_DEVICE_STATE_NEED_AUTH:
-    case NM_DEVICE_STATE_IP_CONFIG:
-    case NM_DEVICE_STATE_IP_CHECK:
-    case NM_DEVICE_STATE_SECONDARIES:
-    case NM_DEVICE_STATE_DEACTIVATING:
-        /* Prohibit scans when unusable or activating */
-        return TRUE;
-    case NM_DEVICE_STATE_DISCONNECTED:
-    case NM_DEVICE_STATE_FAILED:
-    case NM_DEVICE_STATE_ACTIVATED:
-        break;
-    }
-
-    /* Prohibit scans if IWD is busy */
-    return !priv->can_scan;
-}
-
-/*
- * try_reply_agent_request
- *
- * Check if the connection settings already have the secrets corresponding
- * to the IWD agent method that was invoked.  If they do, send the method reply
- * with the appropriate secrets.  Otherwise, return the missing secret's setting
- * name and key so the caller can send a NM secrets request with this data.
- * Return TRUE in either case, return FALSE if an error is detected.
- */
-static gboolean
-try_reply_agent_request(NMDeviceIwd *          self,
-                        NMConnection *         connection,
-                        GDBusMethodInvocation *invocation,
-                        const char **          setting_name,
-                        const char **          setting_key,
-                        gboolean *             replied)
-{
-    const char *               method_name = g_dbus_method_invocation_get_method_name(invocation);
-    NMSettingWirelessSecurity *s_wireless_sec;
-    NMSetting8021x *           s_8021x;
-
-    s_wireless_sec = nm_connection_get_setting_wireless_security(connection);
-    s_8021x        = nm_connection_get_setting_802_1x(connection);
-
-    *replied = FALSE;
-
-    if (nm_streq(method_name, "RequestPassphrase")) {
-        const char *psk;
-
-        if (!s_wireless_sec)
-            return FALSE;
-
-        psk = nm_setting_wireless_security_get_psk(s_wireless_sec);
-        if (psk) {
-            _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the PSK to the IWD Agent");
-
-            g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", psk));
-            *replied = TRUE;
-            return TRUE;
-        }
-
-        *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
-        *setting_key  = NM_SETTING_WIRELESS_SECURITY_PSK;
-        return TRUE;
-    } else if (nm_streq(method_name, "RequestPrivateKeyPassphrase")) {
-        const char *password;
-
-        if (!s_8021x)
-            return FALSE;
-
-        password = nm_setting_802_1x_get_private_key_password(s_8021x);
-        if (password) {
-            _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the private key password to the IWD Agent");
-
-            g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", password));
-            *replied = TRUE;
-            return TRUE;
-        }
-
-        *setting_name = NM_SETTING_802_1X_SETTING_NAME;
-        *setting_key  = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
-        return TRUE;
-    } else if (nm_streq(method_name, "RequestUserNameAndPassword")) {
-        const char *identity, *password;
-
-        if (!s_8021x)
-            return FALSE;
-
-        identity = nm_setting_802_1x_get_identity(s_8021x);
-        password = nm_setting_802_1x_get_password(s_8021x);
-        if (identity && password) {
-            _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the username and password to the IWD Agent");
-
-            g_dbus_method_invocation_return_value(invocation,
-                                                  g_variant_new("(ss)", identity, password));
-            *replied = TRUE;
-            return TRUE;
-        }
-
-        *setting_name = NM_SETTING_802_1X_SETTING_NAME;
-        if (!identity)
-            *setting_key = NM_SETTING_802_1X_IDENTITY;
-        else
-            *setting_key = NM_SETTING_802_1X_PASSWORD;
-        return TRUE;
-    } else if (nm_streq(method_name, "RequestUserPassword")) {
-        const char *password;
-
-        if (!s_8021x)
-            return FALSE;
-
-        password = nm_setting_802_1x_get_password(s_8021x);
-        if (password) {
-            _LOGD(LOGD_DEVICE | LOGD_WIFI, "Returning the user password to the IWD Agent");
-
-            g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", password));
-            *replied = TRUE;
-            return TRUE;
-        }
-
-        *setting_name = NM_SETTING_802_1X_SETTING_NAME;
-        *setting_key  = NM_SETTING_802_1X_PASSWORD;
-        return TRUE;
-    } else
-        return FALSE;
-}
-
-static void wifi_secrets_get_one(NMDeviceIwd *                self,
-                                 const char *                 setting_name,
-                                 NMSecretAgentGetSecretsFlags flags,
-                                 const char *                 setting_key,
-                                 GDBusMethodInvocation *      invocation);
-
-static void
-wifi_secrets_cb(NMActRequest *                req,
-                NMActRequestGetSecretsCallId *call_id,
-                NMSettingsConnection *        s_connection,
-                GError *                      error,
-                gpointer                      user_data)
-{
-    NMDeviceIwd *                self;
-    NMDeviceIwdPrivate *         priv;
-    NMDevice *                   device;
-    GDBusMethodInvocation *      invocation;
-    const char *                 setting_name;
-    const char *                 setting_key;
-    gboolean                     replied;
-    NMSecretAgentGetSecretsFlags get_secret_flags =
-        NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION;
-
-    nm_utils_user_data_unpack(user_data, &self, &invocation);
-
-    g_return_if_fail(NM_IS_DEVICE_IWD(self));
-
-    priv   = NM_DEVICE_IWD_GET_PRIVATE(self);
-    device = NM_DEVICE(self);
-
-    g_return_if_fail(priv->wifi_secrets_id == call_id);
-
-    priv->wifi_secrets_id = NULL;
-
-    if (nm_utils_error_is_cancelled(error)) {
-        g_dbus_method_invocation_return_error_literal(invocation,
-                                                      NM_DEVICE_ERROR,
-                                                      NM_DEVICE_ERROR_INVALID_CONNECTION,
-                                                      "NM secrets request cancelled");
-        return;
-    }
-
-    g_return_if_fail(req == nm_device_get_act_request(device));
-    g_return_if_fail(nm_act_request_get_settings_connection(req) == s_connection);
-
-    if (nm_device_get_state(device) != NM_DEVICE_STATE_NEED_AUTH)
-        goto secrets_error;
-
-    if (error) {
-        _LOGW(LOGD_WIFI, "%s", error->message);
-        goto secrets_error;
-    }
-
-    if (!try_reply_agent_request(self,
-                                 nm_act_request_get_applied_connection(req),
-                                 invocation,
-                                 &setting_name,
-                                 &setting_key,
-                                 &replied))
-        goto secrets_error;
-
-    if (replied) {
-        /* Change state back to what it was before NEED_AUTH */
-        nm_device_state_changed(device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
-        return;
-    }
-
-    if (nm_settings_connection_get_timestamp(nm_act_request_get_settings_connection(req), NULL))
-        get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW;
-
-    /* Request further secrets if we still need something */
-    wifi_secrets_get_one(self, setting_name, get_secret_flags, setting_key, invocation);
-    return;
-
-secrets_error:
-    g_dbus_method_invocation_return_error_literal(invocation,
-                                                  NM_DEVICE_ERROR,
-                                                  NM_DEVICE_ERROR_INVALID_CONNECTION,
-                                                  "NM secrets request failed");
-    /* Now wait for the Connect callback to update device state */
-}
-
-static void
-wifi_secrets_get_one(NMDeviceIwd *                self,
-                     const char *                 setting_name,
-                     NMSecretAgentGetSecretsFlags flags,
-                     const char *                 setting_key,
-                     GDBusMethodInvocation *      invocation)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMActRequest *      req;
-
-    wifi_secrets_cancel(self);
-
-    req = nm_device_get_act_request(NM_DEVICE(self));
-    g_return_if_fail(NM_IS_ACT_REQUEST(req));
-
-    priv->wifi_secrets_id = nm_act_request_get_secrets(req,
-                                                       TRUE,
-                                                       setting_name,
-                                                       flags,
-                                                       NM_MAKE_STRV(setting_key),
-                                                       wifi_secrets_cb,
-                                                       nm_utils_user_data_pack(self, invocation));
-}
-
-static void
-network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-    NMDeviceIwd *       self           = user_data;
-    NMDevice *          device         = NM_DEVICE(self);
-    NMDeviceIwdPrivate *priv           = NM_DEVICE_IWD_GET_PRIVATE(self);
-    gs_unref_variant GVariant *variant = NULL;
-    gs_free_error GError *error        = NULL;
-    NMConnection *        connection;
-    NMSettingWireless *   s_wifi;
-    GBytes *              ssid;
-    gs_free char *        ssid_utf8 = NULL;
-    NMDeviceStateReason   reason    = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED;
-    GVariant *            value;
-
-    variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
-    if (!variant) {
-        gs_free char *dbus_error = NULL;
-
-        /* Connection failed; radio problems or if the network wasn't
-         * open, the passwords or certificates may be wrong.
-         */
-
-        _LOGE(LOGD_DEVICE | LOGD_WIFI,
-              "Activation: (wifi) Network.Connect failed: %s",
-              error->message);
-
-        if (nm_utils_error_is_cancelled(error))
-            return;
-
-        if (!NM_IN_SET(nm_device_get_state(device),
-                       NM_DEVICE_STATE_CONFIG,
-                       NM_DEVICE_STATE_NEED_AUTH))
-            return;
-
-        connection = nm_device_get_applied_connection(device);
-        if (!connection)
-            goto failed;
-
-        if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR))
-            dbus_error = g_dbus_error_get_remote_error(error);
-
-        if (nm_streq0(dbus_error, "net.connman.iwd.Failed")) {
-            nm_connection_clear_secrets(connection);
-
-            /* If secrets were wrong, we'd be getting a net.connman.iwd.Failed */
-            reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
-        } else if (nm_streq0(dbus_error, "net.connman.iwd.Aborted")) {
-            /* If agent call was cancelled we'd be getting a net.connman.iwd.Aborted */
-            reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
-        }
-
-        goto failed;
-    }
-
-    nm_assert(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG);
-
-    connection = nm_device_get_applied_connection(device);
-    if (!connection)
-        goto failed;
-
-    s_wifi = nm_connection_get_setting_wireless(connection);
-    if (!s_wifi)
-        goto failed;
-
-    ssid = nm_setting_wireless_get_ssid(s_wifi);
-    if (!ssid)
-        goto failed;
-
-    ssid_utf8 = _nm_utils_ssid_to_utf8(ssid);
-
-    _LOGI(LOGD_DEVICE | LOGD_WIFI,
-          "Activation: (wifi) Stage 2 of 5 (Device Configure) successful.  Connected to '%s'.",
-          ssid_utf8);
-    nm_device_activate_schedule_stage3_ip_config_start(device);
-
-    return;
-
-failed:
-    /* Call Disconnect to make sure IWD's autoconnect is disabled */
-    cleanup_association_attempt(self, TRUE);
-
-    nm_device_queue_state(device, NM_DEVICE_STATE_FAILED, reason);
-
-    value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State");
-    if (!priv->can_connect && nm_streq0(get_variant_state(value), "disconnected")) {
-        priv->can_connect = true;
-        nm_device_emit_recheck_auto_activate(device);
-    }
-    g_variant_unref(value);
-}
-
-static void
-act_failed_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-    NMDeviceIwd *    self              = user_data;
-    NMDevice *       device            = NM_DEVICE(self);
-    gs_unref_variant GVariant *variant = NULL;
-    gs_free_error GError *error        = NULL;
-
-    variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
-    if (!variant && nm_utils_error_is_cancelled(error))
-        return;
-
-    /* Change state to FAILED unless already done by state_changed
-     * which may have been triggered by the station interface
-     * appearing on DBus.
-     */
-    if (nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG)
-        nm_device_queue_state(device,
-                              NM_DEVICE_STATE_FAILED,
-                              NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-}
-
-static void
-act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-    NMDeviceIwd *       self           = user_data;
-    NMDeviceIwdPrivate *priv           = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDevice *          device         = NM_DEVICE(self);
-    gs_unref_variant GVariant *variant = NULL;
-    gs_free_error GError *error        = NULL;
-    NMSettingWireless *   s_wireless;
-    GBytes *              ssid;
-    gs_free char *        ssid_utf8 = NULL;
-
-    variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
-    if (!variant) {
-        _LOGE(LOGD_DEVICE | LOGD_WIFI,
-              "Activation: (wifi) Network.Connect failed: %s",
-              error->message);
-
-        if (nm_utils_error_is_cancelled(error))
-            return;
-
-        if (!NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG))
-            return;
-
-        goto error;
-    }
-
-    nm_assert(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG);
-
-    s_wireless = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS);
-    if (!s_wireless)
-        goto error;
-
-    ssid = nm_setting_wireless_get_ssid(s_wireless);
-    if (!ssid)
-        goto error;
-
-    ssid_utf8 = _nm_utils_ssid_to_utf8(ssid);
-
-    _LOGI(LOGD_DEVICE | LOGD_WIFI,
-          "Activation: (wifi) Stage 2 of 5 (Device Configure) successful.  Started '%s'.",
-          ssid_utf8);
-
-    nm_device_activate_schedule_stage3_ip_config_start(device);
-    return;
-
-error:
-    reset_mode(self, priv->cancellable, act_failed_cb, self);
-}
-
-/* Check if we're activating an AP/AdHoc connection and if the target
- * DBus interface has appeared already.  If so proceed to call Start or
- * StartOpen on that interface.
- */
-static void
-act_check_interface(NMDeviceIwd *self)
-{
-    NMDeviceIwdPrivate *       priv   = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDevice *                 device = NM_DEVICE(self);
-    NMSettingWireless *        s_wireless;
-    NMSettingWirelessSecurity *s_wireless_sec;
-    GDBusProxy *               proxy = NULL;
-    GBytes *                   ssid;
-    gs_free char *             ssid_utf8 = NULL;
-    const char *               mode;
-
-    if (!priv->act_mode_switch)
-        return;
-
-    s_wireless =
-        (NMSettingWireless *) nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS);
-
-    mode = nm_setting_wireless_get_mode(s_wireless);
-    if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP))
-        proxy = priv->dbus_ap_proxy;
-    else if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_ADHOC))
-        proxy = priv->dbus_adhoc_proxy;
-
-    if (!proxy)
-        return;
-
-    priv->act_mode_switch = FALSE;
-
-    if (!NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG))
-        return;
-
-    ssid = nm_setting_wireless_get_ssid(s_wireless);
-    if (!ssid)
-        goto failed;
-
-    ssid_utf8 = _nm_utils_ssid_to_utf8(ssid);
-
-    s_wireless_sec = (NMSettingWirelessSecurity *) nm_device_get_applied_setting(
-        device,
-        NM_TYPE_SETTING_WIRELESS_SECURITY);
-
-    if (!s_wireless_sec) {
-        g_dbus_proxy_call(proxy,
-                          "StartOpen",
-                          g_variant_new("(s)", ssid_utf8),
-                          G_DBUS_CALL_FLAGS_NONE,
-                          G_MAXINT,
-                          priv->cancellable,
-                          act_start_cb,
-                          self);
-    } else {
-        const char *psk = nm_setting_wireless_security_get_psk(s_wireless_sec);
-
-        if (!psk) {
-            _LOGE(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) No PSK for '%s'.", ssid_utf8);
-            goto failed;
-        }
-
-        g_dbus_proxy_call(proxy,
-                          "Start",
-                          g_variant_new("(ss)", ssid_utf8, psk),
-                          G_DBUS_CALL_FLAGS_NONE,
-                          G_MAXINT,
-                          priv->cancellable,
-                          act_start_cb,
-                          self);
-    }
-
-    _LOGD(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Called Start('%s').", ssid_utf8);
-    return;
-
-failed:
-    reset_mode(self, priv->cancellable, act_failed_cb, self);
-}
-
-static void
-act_set_mode_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
-    NMDeviceIwd *       self           = user_data;
-    NMDeviceIwdPrivate *priv           = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDevice *          device         = NM_DEVICE(self);
-    gs_unref_variant GVariant *variant = NULL;
-    gs_free_error GError *error        = NULL;
-
-    variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error);
-    if (!variant) {
-        _LOGE(LOGD_DEVICE | LOGD_WIFI,
-              "Activation: (wifi) Setting Device.Mode failed: %s",
-              error->message);
-
-        if (nm_utils_error_is_cancelled(error))
-            return;
-
-        if (!NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG)
-            || !priv->act_mode_switch)
-            return;
-
-        priv->act_mode_switch = FALSE;
-        nm_device_queue_state(device,
-                              NM_DEVICE_STATE_FAILED,
-                              NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-        return;
-    }
-
-    _LOGD(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) IWD Device.Mode set successfully");
-
-    act_check_interface(self);
-}
-
-static void
-act_set_mode(NMDeviceIwd *self)
-{
-    NMDeviceIwdPrivate *priv   = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDevice *          device = NM_DEVICE(self);
-    const char *        iwd_mode;
-    const char *        mode;
-    NMSettingWireless * s_wireless;
-
-    s_wireless =
-        (NMSettingWireless *) nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS);
-    mode = nm_setting_wireless_get_mode(s_wireless);
-
-    /* We need to first set interface mode (Device.Mode) to ap or ad-hoc.
-     * We can't directly queue a call to the Start/StartOpen method on
-     * the DBus interface that's going to be created after the property
-     * set call returns.
-     */
-    iwd_mode = nm_streq(mode, NM_SETTING_WIRELESS_MODE_AP) ? "ap" : "ad-hoc";
-
-    if (!priv->cancellable)
-        priv->cancellable = g_cancellable_new();
-
-    g_dbus_proxy_call(
-        priv->dbus_device_proxy,
-        DBUS_INTERFACE_PROPERTIES ".Set",
-        g_variant_new("(ssv)", NM_IWD_DEVICE_INTERFACE, "Mode", g_variant_new("s", iwd_mode)),
-        G_DBUS_CALL_FLAGS_NONE,
-        2000,
-        priv->cancellable,
-        act_set_mode_cb,
-        self);
-    priv->act_mode_switch = TRUE;
-}
-
-static void
-act_psk_cb(NMActRequest *                req,
-           NMActRequestGetSecretsCallId *call_id,
-           NMSettingsConnection *        s_connection,
-           GError *                      error,
-           gpointer                      user_data)
-{
-    NMDeviceIwd *       self = user_data;
-    NMDeviceIwdPrivate *priv;
-    NMDevice *          device;
-
-    if (nm_utils_error_is_cancelled(error))
-        return;
-
-    priv   = NM_DEVICE_IWD_GET_PRIVATE(self);
-    device = NM_DEVICE(self);
-
-    g_return_if_fail(priv->wifi_secrets_id == call_id);
-    priv->wifi_secrets_id = NULL;
-
-    g_return_if_fail(req == nm_device_get_act_request(device));
-    g_return_if_fail(nm_act_request_get_settings_connection(req) == s_connection);
-
-    if (nm_device_get_state(device) != NM_DEVICE_STATE_NEED_AUTH)
-        goto secrets_error;
-
-    if (error) {
-        _LOGW(LOGD_WIFI, "%s", error->message);
-        goto secrets_error;
-    }
-
-    _LOGD(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) missing PSK request completed");
-
-    /* Change state back to what it was before NEED_AUTH */
-    nm_device_state_changed(device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
-    act_set_mode(self);
-    return;
-
-secrets_error:
-    nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
-    cleanup_association_attempt(self, FALSE);
-}
-
-static void
-set_powered(NMDeviceIwd *self, gboolean powered)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    g_dbus_proxy_call(
-        priv->dbus_device_proxy,
-        DBUS_INTERFACE_PROPERTIES ".Set",
-        g_variant_new("(ssv)", NM_IWD_DEVICE_INTERFACE, "Powered", g_variant_new("b", powered)),
-        G_DBUS_CALL_FLAGS_NONE,
-        2000,
-        NULL,
-        NULL,
-        NULL);
-}
-
-/*****************************************************************************/
-
-static NMActStageReturn
-act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
-{
-    NMDeviceIwd *       self          = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv          = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMWifiAP *          ap            = NULL;
-    gs_unref_object NMWifiAP *ap_fake = NULL;
-    NMActRequest *            req;
-    NMConnection *            connection;
-    NMSettingWireless *       s_wireless;
-    const char *              mode;
-    const char *              ap_path;
-
-    req = nm_device_get_act_request(device);
-    g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
-
-    connection = nm_act_request_get_applied_connection(req);
-    g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
-
-    s_wireless = nm_connection_get_setting_wireless(connection);
-    g_return_val_if_fail(s_wireless, NM_ACT_STAGE_RETURN_FAILURE);
-
-    /* AP mode never uses a specific object or existing scanned AP */
-    mode = nm_setting_wireless_get_mode(s_wireless);
-    if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP))
-        goto add_new;
-
-    ap_path = nm_active_connection_get_specific_object(NM_ACTIVE_CONNECTION(req));
-    ap      = ap_path ? nm_wifi_ap_lookup_for_device(NM_DEVICE(self), ap_path) : NULL;
-    if (ap) {
-        set_current_ap(self, ap, TRUE);
-        return NM_ACT_STAGE_RETURN_SUCCESS;
-    }
-
-    ap = nm_wifi_aps_find_first_compatible(&priv->aps_lst_head, connection);
-    if (ap) {
-        nm_active_connection_set_specific_object(NM_ACTIVE_CONNECTION(req),
-                                                 nm_dbus_object_get_path(NM_DBUS_OBJECT(ap)));
-        set_current_ap(self, ap, TRUE);
-        return NM_ACT_STAGE_RETURN_SUCCESS;
-    }
-
-    if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_INFRA)) {
-        /* Hidden networks not supported at this time */
-        return NM_ACT_STAGE_RETURN_FAILURE;
-    }
-
-add_new:
-    /* If the user is trying to connect to an AP that NM doesn't yet know about
-     * (hidden network or something) or starting a Hotspot, create an fake AP
-     * from the security settings in the connection.  This "fake" AP gets used
-     * until the real one is found in the scan list (Ad-Hoc or Hidden), or until
-     * the device is deactivated (Ad-Hoc or Hotspot).
-     */
-    ap_fake = nm_wifi_ap_new_fake_from_connection(connection);
-    if (!ap_fake)
-        g_return_val_if_reached(NM_ACT_STAGE_RETURN_FAILURE);
-
-    if (nm_wifi_ap_is_hotspot(ap_fake))
-        nm_wifi_ap_set_address(ap_fake, nm_device_get_hw_address(device));
-
-    g_object_freeze_notify(G_OBJECT(self));
-    ap_add_remove(self, TRUE, ap_fake, FALSE);
-    g_object_thaw_notify(G_OBJECT(self));
-    set_current_ap(self, ap_fake, FALSE);
-    nm_active_connection_set_specific_object(NM_ACTIVE_CONNECTION(req),
-                                             nm_dbus_object_get_path(NM_DBUS_OBJECT(ap_fake)));
-    return NM_ACT_STAGE_RETURN_SUCCESS;
-}
-
-static NMActStageReturn
-act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMActRequest *      req;
-    NMConnection *      connection;
-    NMSettingWireless * s_wireless;
-    const char *        mode;
-
-    req        = nm_device_get_act_request(device);
-    connection = nm_act_request_get_applied_connection(req);
-    s_wireless = nm_connection_get_setting_wireless(connection);
-    g_return_val_if_fail(s_wireless, NM_ACT_STAGE_RETURN_FAILURE);
-
-    mode = nm_setting_wireless_get_mode(s_wireless);
-
-    if (NM_IN_STRSET(mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) {
-        gs_unref_object GDBusProxy *network_proxy = NULL;
-        NMWifiAP *                  ap            = priv->current_ap;
-
-        if (!ap) {
-            NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-            goto out_fail;
-        }
-
-        /* 802.1x networks that are not IWD Known Networks will definitely
-         * fail, for other combinations we will let the Connect call fail
-         * or ask us for any missing secrets through the Agent.
-         */
-        if (nm_connection_get_setting_802_1x(connection) && !is_ap_known_network(ap)) {
-            _LOGI(LOGD_DEVICE | LOGD_WIFI,
-                  "Activation: (wifi) access point '%s' has 802.1x security but is not configured "
-                  "in IWD.",
-                  nm_connection_get_id(connection));
-
-            NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS);
-            goto out_fail;
-        }
-
-        if (!is_connection_known_network(connection)
-            && nm_setting_wireless_get_hidden(s_wireless)) {
-            gs_free char *ssid_str = NULL;
-
-            /* Use Station.ConnectHiddenNetwork method instead of Network proxy. */
-            ssid_str = _nm_utils_ssid_to_utf8(nm_setting_wireless_get_ssid(s_wireless));
-            g_dbus_proxy_call(priv->dbus_station_proxy,
-                              "ConnectHiddenNetwork",
-                              g_variant_new("(s)", ssid_str),
-                              G_DBUS_CALL_FLAGS_NONE,
-                              G_MAXINT,
-                              priv->cancellable,
-                              network_connect_cb,
-                              self);
-            return NM_ACT_STAGE_RETURN_POSTPONE;
-        }
-
-        if (!nm_wifi_ap_get_supplicant_path(ap)) {
-            _LOGW(LOGD_DEVICE | LOGD_WIFI,
-                  "Activation: (wifi) network is provisioned but dbus supplicant path for AP "
-                  "unknown");
-            NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-            goto out_fail;
-        }
-
-        network_proxy = nm_iwd_manager_get_dbus_interface(
-            nm_iwd_manager_get(),
-            nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)),
-            NM_IWD_NETWORK_INTERFACE);
-        if (!network_proxy) {
-            _LOGW(LOGD_DEVICE | LOGD_WIFI,
-                  "Activation: (wifi) could not get Network interface proxy for %s",
-                  nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)));
-            NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-            goto out_fail;
-        }
-
-        if (!priv->cancellable)
-            priv->cancellable = g_cancellable_new();
-
-        /* Call Network.Connect.  No timeout because IWD already handles
-         * timeouts.
-         */
-        g_dbus_proxy_call(network_proxy,
-                          "Connect",
-                          NULL,
-                          G_DBUS_CALL_FLAGS_NONE,
-                          G_MAXINT,
-                          priv->cancellable,
-                          network_connect_cb,
-                          self);
-
-        return NM_ACT_STAGE_RETURN_POSTPONE;
-    }
-
-    if (NM_IN_STRSET(mode, NM_SETTING_WIRELESS_MODE_AP, NM_SETTING_WIRELESS_MODE_ADHOC)) {
-        NMSettingWirelessSecurity *s_wireless_sec;
-
-        s_wireless_sec = nm_connection_get_setting_wireless_security(connection);
-        if (s_wireless_sec && !nm_setting_wireless_security_get_psk(s_wireless_sec)) {
-            /* PSK is missing from the settings, have to request it */
-
-            wifi_secrets_cancel(self);
-
-            priv->wifi_secrets_id =
-                nm_act_request_get_secrets(req,
-                                           TRUE,
-                                           NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-                                           NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION,
-                                           NM_MAKE_STRV(NM_SETTING_WIRELESS_SECURITY_PSK),
-                                           act_psk_cb,
-                                           self);
-            nm_device_state_changed(device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
-        } else
-            act_set_mode(self);
-
-        return NM_ACT_STAGE_RETURN_POSTPONE;
-    }
-
-    _LOGW(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) iwd cannot handle mode %s", mode);
-    NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-
-out_fail:
-    cleanup_association_attempt(self, FALSE);
-    return NM_ACT_STAGE_RETURN_FAILURE;
-}
-
-static guint32
-get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
-{
-    return nm_device_get_configured_mtu_from_connection(device,
-                                                        NM_TYPE_SETTING_WIRELESS,
-                                                        out_source);
-}
-
-static gboolean
-periodic_scan_timeout_cb(gpointer user_data)
-{
-    NMDeviceIwd *       self = user_data;
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    priv->periodic_scan_id = 0;
-
-    if (priv->scanning || priv->scan_requested)
-        return FALSE;
-
-    g_dbus_proxy_call(priv->dbus_station_proxy,
-                      "Scan",
-                      NULL,
-                      G_DBUS_CALL_FLAGS_NONE,
-                      -1,
-                      priv->cancellable,
-                      scan_cb,
-                      self);
-    priv->scan_requested = TRUE;
-
-    return FALSE;
-}
-
-static void
-schedule_periodic_scan(NMDeviceIwd *self, gboolean initial_scan)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    GVariant *          value;
-    gboolean            disconnected = TRUE;
-    guint               interval;
-
-    if (priv->can_scan) {
-        value        = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State");
-        disconnected = nm_streq0(get_variant_state(value), "disconnected");
-        g_variant_unref(value);
-    }
-
-    /* Start scan immediately after a disconnect, mode change or
-     * device UP, otherwise wait 10 seconds.  When connected, update
-     * AP list mainly on UI requests.
-     *
-     * (initial_scan && disconnected) override priv->scanning below
-     * because of an IWD quirk where a device will often be in the
-     * autoconnect state and scanning at the time of our initial_scan,
-     * but our logic will then send it a Disconnect() causing IWD to
-     * exit autoconnect and interrupt the ongoing scan, meaning that
-     * we still want a new scan ASAP.
-     */
-    if (!priv->can_scan || !disconnected || priv->scan_requested || priv->scanning)
-        interval = -1;
-    else if (initial_scan)
-        interval = 0;
-    else if (!priv->periodic_scan_id)
-        interval = 10;
-    else
-        return;
-
-    nm_clear_g_source(&priv->periodic_scan_id);
-
-    if (interval != (guint) -1)
-        priv->periodic_scan_id = g_timeout_add_seconds(interval, periodic_scan_timeout_cb, self);
-}
-
-static void
-set_can_scan(NMDeviceIwd *self, gboolean can_scan)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    if (priv->can_scan == can_scan)
-        return;
-
-    priv->can_scan = can_scan;
-
-    schedule_periodic_scan(self, TRUE);
-}
-
-static void
-device_state_changed(NMDevice *          device,
-                     NMDeviceState       new_state,
-                     NMDeviceState       old_state,
-                     NMDeviceStateReason reason)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    switch (new_state) {
-    case NM_DEVICE_STATE_UNMANAGED:
-        break;
-    case NM_DEVICE_STATE_UNAVAILABLE:
-        /*
-         * If the device is enabled and the IWD manager is ready,
-         * transition to DISCONNECTED because the device is now
-         * ready to use.
-         */
-        if (priv->enabled && priv->dbus_station_proxy) {
-            nm_device_queue_recheck_available(device,
-                                              NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
-                                              NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-        }
-        break;
-    case NM_DEVICE_STATE_NEED_AUTH:
-        break;
-    case NM_DEVICE_STATE_IP_CHECK:
-        break;
-    case NM_DEVICE_STATE_ACTIVATED:
-        break;
-    case NM_DEVICE_STATE_FAILED:
-        break;
-    case NM_DEVICE_STATE_DISCONNECTED:
-        break;
-    default:
-        break;
-    }
-}
-
-static gboolean
-get_enabled(NMDevice *device)
-{
-    return NM_DEVICE_IWD_GET_PRIVATE(device)->enabled;
-}
-
-static void
-set_enabled(NMDevice *device, gboolean enabled)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(device);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDeviceState       state;
-
-    enabled = !!enabled;
-
-    if (priv->enabled == enabled)
-        return;
-
-    priv->enabled = enabled;
-
-    _LOGD(LOGD_WIFI, "device now %s", enabled ? "enabled" : "disabled");
-
-    state = nm_device_get_state(device);
-    if (state < NM_DEVICE_STATE_UNAVAILABLE) {
-        _LOGD(LOGD_WIFI, "(%s): device blocked by UNMANAGED state", enabled ? "enable" : "disable");
-        return;
-    }
-
-    if (priv->dbus_obj)
-        set_powered(self, enabled);
-
-    if (enabled) {
-        if (state != NM_DEVICE_STATE_UNAVAILABLE)
-            _LOGW(LOGD_CORE, "not in expected unavailable state!");
-
-        if (priv->dbus_station_proxy) {
-            nm_device_queue_recheck_available(device,
-                                              NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
-                                              NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-        }
-    } else {
-        nm_device_state_changed(device, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_NONE);
-    }
-}
-
-static gboolean
-can_reapply_change(NMDevice *  device,
-                   const char *setting_name,
-                   NMSetting * s_old,
-                   NMSetting * s_new,
-                   GHashTable *diffs,
-                   GError **   error)
-{
-    NMDeviceClass *device_class;
-
-    /* Only handle wireless setting here, delegate other settings to parent class */
-    if (nm_streq(setting_name, NM_SETTING_WIRELESS_SETTING_NAME)) {
-        return nm_device_hash_check_invalid_keys(
-            diffs,
-            NM_SETTING_WIRELESS_SETTING_NAME,
-            error,
-            NM_SETTING_WIRELESS_SEEN_BSSIDS, /* ignored */
-            NM_SETTING_WIRELESS_MTU);        /* reapplied with IP config */
-    }
-
-    device_class = NM_DEVICE_CLASS(nm_device_iwd_parent_class);
-    return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
-}
-
-/*****************************************************************************/
-
-static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(object);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    const char **       list;
-
-    switch (prop_id) {
-    case PROP_MODE:
-        if (!priv->current_ap)
-            g_value_set_uint(value, NM_802_11_MODE_UNKNOWN);
-        else if (nm_wifi_ap_is_hotspot(priv->current_ap))
-            g_value_set_uint(value, NM_802_11_MODE_AP);
-        else
-            g_value_set_uint(value, nm_wifi_ap_get_mode(priv->current_ap));
-
-        break;
-    case PROP_BITRATE:
-        g_value_set_uint(value, 65000);
-        break;
-    case PROP_CAPABILITIES:
-        g_value_set_uint(value, priv->capabilities);
-        break;
-    case PROP_ACCESS_POINTS:
-        list = nm_wifi_aps_get_paths(&priv->aps_lst_head, TRUE);
-        g_value_take_boxed(value, nm_utils_strv_make_deep_copied(list));
-        break;
-    case PROP_ACTIVE_ACCESS_POINT:
-        nm_dbus_utils_g_value_set_object_path(value, priv->current_ap);
-        break;
-    case PROP_SCANNING:
-        g_value_set_boolean(value, priv->scanning);
-        break;
-    case PROP_LAST_SCAN:
-        g_value_set_int64(
-            value,
-            priv->last_scan > 0
-                ? nm_utils_monotonic_timestamp_as_boottime(priv->last_scan, NM_UTILS_NSEC_PER_MSEC)
-                : (gint64) -1);
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-        break;
-    }
-}
-
-/*****************************************************************************/
-
-static void
-state_changed(NMDeviceIwd *self, const char *new_state)
-{
-    NMDeviceIwdPrivate *priv           = NM_DEVICE_IWD_GET_PRIVATE(self);
-    NMDevice *          device         = NM_DEVICE(self);
-    NMDeviceState       dev_state      = nm_device_get_state(device);
-    gboolean            iwd_connection = FALSE;
-    gboolean            can_connect    = priv->can_connect;
-
-    _LOGI(LOGD_DEVICE | LOGD_WIFI, "new IWD device state is %s", new_state);
-
-    if (dev_state >= NM_DEVICE_STATE_CONFIG && dev_state <= NM_DEVICE_STATE_ACTIVATED)
-        iwd_connection = TRUE;
-
-    /* Don't allow scanning while connecting, disconnecting or roaming */
-    set_can_scan(self, NM_IN_STRSET(new_state, "connected", "disconnected"));
-
-    priv->can_connect = FALSE;
-
-    if (NM_IN_STRSET(new_state, "connecting", "connected", "roaming")) {
-        /* If we were connecting, do nothing, the confirmation of
-         * a connection success is handled in the Device.Connect
-         * method return callback.  Otherwise, IWD must have connected
-         * without Network Manager's will so for simplicity force a
-         * disconnect.
-         */
-        if (iwd_connection)
-            return;
-
-        _LOGW(LOGD_DEVICE | LOGD_WIFI, "Unsolicited connection success, asking IWD to disconnect");
-        send_disconnect(self);
-    } else if (NM_IN_STRSET(new_state, "disconnecting", "disconnected")) {
-        /* Call Disconnect on the IWD device object to make sure it
-         * disables its own autoconnect.
-         */
-        send_disconnect(self);
-
-        /*
-         * If IWD is still handling the Connect call, let our Connect
-         * callback for the dbus method handle the failure.  The main
-         * reason we can't handle the failure here is because the method
-         * callback will have more information on the specific failure
-         * reason.
-         */
-        if (NM_IN_SET(dev_state, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH))
-            return;
-
-        if (iwd_connection)
-            nm_device_state_changed(device,
-                                    NM_DEVICE_STATE_FAILED,
-                                    NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
-    } else if (!nm_streq(new_state, "unknown")) {
-        _LOGE(LOGD_WIFI, "State %s unknown", new_state);
-        return;
-    }
-
-    /* Don't allow new connection until iwd exits disconnecting and no
-     * Connect callback is pending.
-     */
-    if (NM_IN_STRSET(new_state, "disconnected")) {
-        priv->can_connect = TRUE;
-        if (!can_connect)
-            nm_device_emit_recheck_auto_activate(device);
-    }
-}
-
-static void
-scanning_changed(NMDeviceIwd *self, gboolean new_scanning)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    if (new_scanning == priv->scanning)
-        return;
-
-    priv->scanning = new_scanning;
-
-    _notify(self, PROP_SCANNING);
-
-    if (!priv->scanning) {
-        update_aps(self);
-
-        if (!priv->scan_requested)
-            schedule_periodic_scan(self, FALSE);
-    }
-}
-
-static void
-station_properties_changed(GDBusProxy *proxy,
-                           GVariant *  changed_properties,
-                           GStrv       invalidate_properties,
-                           gpointer    user_data)
-{
-    NMDeviceIwd *self = user_data;
-    const char * new_str;
-    gboolean     new_bool;
-
-    if (g_variant_lookup(changed_properties, "State", "&s", &new_str))
-        state_changed(self, new_str);
-
-    if (g_variant_lookup(changed_properties, "Scanning", "b", &new_bool))
-        scanning_changed(self, new_bool);
-}
-
-static void
-ap_adhoc_properties_changed(GDBusProxy *proxy,
-                            GVariant *  changed_properties,
-                            GStrv       invalidate_properties,
-                            gpointer    user_data)
-{
-    NMDeviceIwd *self = user_data;
-    gboolean     new_bool;
-
-    if (g_variant_lookup(changed_properties, "Started", "b", &new_bool))
-        _LOGI(LOGD_DEVICE | LOGD_WIFI,
-              "IWD AP/AdHoc state is now %s",
-              new_bool ? "Started" : "Stopped");
-}
-
-static void
-powered_changed(NMDeviceIwd *self, gboolean new_powered)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    GDBusInterface *    interface;
-    GVariant *          value;
-
-    nm_device_queue_recheck_available(NM_DEVICE(self),
-                                      NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
-                                      NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
-
-    interface =
-        new_powered ? g_dbus_object_get_interface(priv->dbus_obj, NM_IWD_AP_INTERFACE) : NULL;
-
-    if (priv->dbus_ap_proxy) {
-        g_signal_handlers_disconnect_by_func(priv->dbus_ap_proxy,
-                                             ap_adhoc_properties_changed,
-                                             self);
-        g_clear_object(&priv->dbus_ap_proxy);
-    }
-
-    if (interface) {
-        priv->dbus_ap_proxy = G_DBUS_PROXY(interface);
-        g_signal_connect(priv->dbus_ap_proxy,
-                         "g-properties-changed",
-                         G_CALLBACK(ap_adhoc_properties_changed),
-                         self);
-
-        if (priv->act_mode_switch)
-            act_check_interface(self);
-        else
-            reset_mode(self, NULL, NULL, NULL);
-    }
-
-    interface =
-        new_powered ? g_dbus_object_get_interface(priv->dbus_obj, NM_IWD_ADHOC_INTERFACE) : NULL;
-
-    if (priv->dbus_adhoc_proxy) {
-        g_signal_handlers_disconnect_by_func(priv->dbus_adhoc_proxy,
-                                             ap_adhoc_properties_changed,
-                                             self);
-        g_clear_object(&priv->dbus_adhoc_proxy);
-    }
-
-    if (interface) {
-        priv->dbus_adhoc_proxy = G_DBUS_PROXY(interface);
-        g_signal_connect(priv->dbus_adhoc_proxy,
-                         "g-properties-changed",
-                         G_CALLBACK(ap_adhoc_properties_changed),
-                         self);
-
-        if (priv->act_mode_switch)
-            act_check_interface(self);
-        else
-            reset_mode(self, NULL, NULL, NULL);
-    }
-
-    /* We expect one of the three interfaces to always be present when
-     * device is Powered so if AP and AdHoc are not present we should
-     * be in station mode.
-     */
-    if (new_powered && !priv->dbus_ap_proxy && !priv->dbus_adhoc_proxy) {
-        interface = g_dbus_object_get_interface(priv->dbus_obj, NM_IWD_STATION_INTERFACE);
-        if (!interface) {
-            /* No Station interface on the device object.  Check if the
-             * "State" property is present on the Device interface, that
-             * would mean we're dealing with an IWD version from before the
-             * Device/Station split (0.7 or earlier) and we can easily
-             * handle that by making priv->dbus_device_proxy and
-             * priv->dbus_station_proxy both point at the Device interface.
-             */
-            value = g_dbus_proxy_get_cached_property(priv->dbus_device_proxy, "State");
-            if (value) {
-                g_variant_unref(value);
-                interface = g_object_ref(G_DBUS_INTERFACE(priv->dbus_device_proxy));
-            } else {
-                _LOGE(LOGD_WIFI,
-                      "Interface %s not found on obj %s",
-                      NM_IWD_STATION_INTERFACE,
-                      g_dbus_object_get_object_path(priv->dbus_obj));
-                interface = NULL;
-            }
-        }
-    } else
-        interface = NULL;
-
-    if (priv->dbus_station_proxy) {
-        g_signal_handlers_disconnect_by_func(priv->dbus_station_proxy,
-                                             station_properties_changed,
-                                             self);
-        g_clear_object(&priv->dbus_station_proxy);
-    }
-
-    if (interface) {
-        priv->dbus_station_proxy = G_DBUS_PROXY(interface);
-        g_signal_connect(priv->dbus_station_proxy,
-                         "g-properties-changed",
-                         G_CALLBACK(station_properties_changed),
-                         self);
-
-        value          = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "Scanning");
-        priv->scanning = get_variant_boolean(value, "Scanning");
-        g_variant_unref(value);
-
-        value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State");
-        state_changed(self, get_variant_state(value));
-        g_variant_unref(value);
-
-        update_aps(self);
-    } else {
-        set_can_scan(self, FALSE);
-        priv->scanning       = FALSE;
-        priv->scan_requested = FALSE;
-        priv->can_connect    = FALSE;
-        cleanup_association_attempt(self, FALSE);
-        remove_all_aps(self);
-    }
-}
-
-static void
-device_properties_changed(GDBusProxy *proxy,
-                          GVariant *  changed_properties,
-                          GStrv       invalidate_properties,
-                          gpointer    user_data)
-{
-    NMDeviceIwd *self = user_data;
-    gboolean     new_bool;
-
-    if (g_variant_lookup(changed_properties, "Powered", "b", &new_bool))
-        powered_changed(self, new_bool);
-}
-
-void
-nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-    GDBusInterface *    interface;
-    gs_unref_variant GVariant *value          = NULL;
-    gs_unref_object GDBusProxy *adapter_proxy = NULL;
-    GVariantIter *              iter;
-    const char *                mode;
-    gboolean                    powered;
-    NMDeviceWifiCapabilities    capabilities;
-
-    if (!nm_g_object_ref_set(&priv->dbus_obj, object))
-        return;
-
-    if (priv->dbus_device_proxy) {
-        g_signal_handlers_disconnect_by_func(priv->dbus_device_proxy,
-                                             device_properties_changed,
-                                             self);
-        g_clear_object(&priv->dbus_device_proxy);
-
-        powered_changed(self, FALSE);
-
-        priv->act_mode_switch = FALSE;
-    }
-
-    if (!object)
-        return;
-
-    interface = g_dbus_object_get_interface(object, NM_IWD_DEVICE_INTERFACE);
-    if (!interface) {
-        _LOGE(LOGD_WIFI,
-              "Interface %s not found on obj %s",
-              NM_IWD_DEVICE_INTERFACE,
-              g_dbus_object_get_object_path(object));
-        g_clear_object(&priv->dbus_obj);
-        return;
-    }
-
-    priv->dbus_device_proxy = G_DBUS_PROXY(interface);
-
-    g_signal_connect(priv->dbus_device_proxy,
-                     "g-properties-changed",
-                     G_CALLBACK(device_properties_changed),
-                     self);
-
-    /* Parse list of interface modes supported by adapter (wiphy) */
-
-    value = g_dbus_proxy_get_cached_property(priv->dbus_device_proxy, "Adapter");
-    if (!value || !g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH)) {
-        nm_log_warn(LOGD_DEVICE | LOGD_WIFI, "Adapter property not cached or not an object path");
-        goto error;
-    }
-
-    adapter_proxy = nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(),
-                                                      g_variant_get_string(value, NULL),
-                                                      NM_IWD_WIPHY_INTERFACE);
-    if (!adapter_proxy) {
-        nm_log_warn(LOGD_DEVICE | LOGD_WIFI, "Can't get DBus proxy for IWD Adapter for IWD Device");
-        goto error;
-    }
-
-    g_variant_unref(value);
-    value = g_dbus_proxy_get_cached_property(adapter_proxy, "SupportedModes");
-    if (!value || !g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY)) {
-        nm_log_warn(LOGD_DEVICE | LOGD_WIFI,
-                    "SupportedModes property not cached or not a string array");
-        goto error;
-    }
-
-    capabilities = NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN;
-
-    g_variant_get(value, "as", &iter);
-    while (g_variant_iter_next(iter, "&s", &mode)) {
-        if (nm_streq(mode, "ap"))
-            capabilities |= NM_WIFI_DEVICE_CAP_AP;
-        else if (nm_streq(mode, "ad-hoc"))
-            capabilities |= NM_WIFI_DEVICE_CAP_ADHOC;
-    }
-    g_variant_iter_free(iter);
-
-    if (priv->capabilities != capabilities) {
-        priv->capabilities = capabilities;
-        _notify(self, PROP_CAPABILITIES);
-    }
-
-    g_variant_unref(value);
-    value   = g_dbus_proxy_get_cached_property(priv->dbus_device_proxy, "Powered");
-    powered = get_variant_boolean(value, "Powered");
-
-    if (powered != priv->enabled)
-        set_powered(self, priv->enabled);
-    else if (powered)
-        powered_changed(self, TRUE);
-
-    return;
-
-error:
-    g_signal_handlers_disconnect_by_func(priv->dbus_device_proxy, device_properties_changed, self);
-    g_clear_object(&priv->dbus_device_proxy);
-}
-
-gboolean
-nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation)
-{
-    NMActRequest *               req;
-    const char *                 setting_name;
-    const char *                 setting_key;
-    gboolean                     replied;
-    NMSecretAgentGetSecretsFlags get_secret_flags =
-        NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION;
-
-    req = nm_device_get_act_request(NM_DEVICE(self));
-    if (!req)
-        return FALSE;
-
-    if (!try_reply_agent_request(self,
-                                 nm_act_request_get_applied_connection(req),
-                                 invocation,
-                                 &setting_name,
-                                 &setting_key,
-                                 &replied))
-        return FALSE;
-
-    if (replied)
-        return TRUE;
-
-    /* Normally require new secrets every time IWD asks for them.
-     * IWD only queries us if it has not saved the secrets (e.g. by policy)
-     * or a previous attempt has failed with current secrets so it wants
-     * a fresh set.  However if this is a new connection it may include
-     * all of the needed settings already so allow using these, too.
-     * Connection timestamp is set after activation or after first
-     * activation failure (to 0).
-     */
-    if (nm_settings_connection_get_timestamp(nm_act_request_get_settings_connection(req), NULL))
-        get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW;
-
-    nm_device_state_changed(NM_DEVICE(self),
-                            NM_DEVICE_STATE_NEED_AUTH,
-                            NM_DEVICE_STATE_REASON_NO_SECRETS);
-    wifi_secrets_get_one(self, setting_name, get_secret_flags, setting_key, invocation);
-
-    return TRUE;
-}
-
-/*****************************************************************************/
-
-static const char *
-get_type_description(NMDevice *device)
-{
-    nm_assert(NM_IS_DEVICE_IWD(device));
-
-    return "wifi";
-}
-
-/*****************************************************************************/
-
-static void
-nm_device_iwd_init(NMDeviceIwd *self)
-{
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    c_list_init(&priv->aps_lst_head);
-
-    /* Make sure the manager is running */
-    (void) nm_iwd_manager_get();
-}
-
-NMDevice *
-nm_device_iwd_new(const char *iface)
-{
-    return g_object_new(NM_TYPE_DEVICE_IWD,
-                        NM_DEVICE_IFACE,
-                        iface,
-                        NM_DEVICE_TYPE_DESC,
-                        "802.11 Wi-Fi",
-                        NM_DEVICE_DEVICE_TYPE,
-                        NM_DEVICE_TYPE_WIFI,
-                        NM_DEVICE_LINK_TYPE,
-                        NM_LINK_TYPE_WIFI,
-                        NM_DEVICE_RFKILL_TYPE,
-                        RFKILL_TYPE_WLAN,
-                        NULL);
-}
-
-static void
-dispose(GObject *object)
-{
-    NMDeviceIwd *       self = NM_DEVICE_IWD(object);
-    NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self);
-
-    nm_clear_g_cancellable(&priv->cancellable);
-
-    nm_device_iwd_set_dbus_object(self, NULL);
-
-    G_OBJECT_CLASS(nm_device_iwd_parent_class)->dispose(object);
-
-    nm_assert(c_list_is_empty(&priv->aps_lst_head));
-}
-
-static void
-nm_device_iwd_class_init(NMDeviceIwdClass *klass)
-{
-    GObjectClass *     object_class      = G_OBJECT_CLASS(klass);
-    NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
-    NMDeviceClass *    device_class      = NM_DEVICE_CLASS(klass);
-
-    object_class->get_property = get_property;
-    object_class->dispose      = dispose;
-
-    dbus_object_class->interface_infos =
-        NM_DBUS_INTERFACE_INFOS(&nm_interface_info_device_wireless);
-
-    device_class->connection_type_supported        = NM_SETTING_WIRELESS_SETTING_NAME;
-    device_class->connection_type_check_compatible = NM_SETTING_WIRELESS_SETTING_NAME;
-    device_class->link_types                       = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_WIFI);
-
-    device_class->can_auto_connect            = can_auto_connect;
-    device_class->is_available                = is_available;
-    device_class->get_autoconnect_allowed     = get_autoconnect_allowed;
-    device_class->check_connection_compatible = check_connection_compatible;
-    device_class->check_connection_available  = check_connection_available;
-    device_class->complete_connection         = complete_connection;
-    device_class->get_enabled                 = get_enabled;
-    device_class->set_enabled                 = set_enabled;
-    device_class->get_type_description        = get_type_description;
-
-    device_class->act_stage1_prepare = act_stage1_prepare;
-    device_class->act_stage2_config  = act_stage2_config;
-    device_class->get_configured_mtu = get_configured_mtu;
-    device_class->deactivate         = deactivate;
-    device_class->deactivate_async   = deactivate_async;
-    device_class->can_reapply_change = can_reapply_change;
-
-    device_class->state_changed = device_state_changed;
-
-    obj_properties[PROP_MODE] = g_param_spec_uint(NM_DEVICE_IWD_MODE,
-                                                  "",
-                                                  "",
-                                                  NM_802_11_MODE_UNKNOWN,
-                                                  NM_802_11_MODE_AP,
-                                                  NM_802_11_MODE_INFRA,
-                                                  G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_BITRATE] = g_param_spec_uint(NM_DEVICE_IWD_BITRATE,
-                                                     "",
-                                                     "",
-                                                     0,
-                                                     G_MAXUINT32,
-                                                     0,
-                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_ACCESS_POINTS] =
-        g_param_spec_boxed(NM_DEVICE_IWD_ACCESS_POINTS,
-                           "",
-                           "",
-                           G_TYPE_STRV,
-                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_ACTIVE_ACCESS_POINT] =
-        g_param_spec_string(NM_DEVICE_IWD_ACTIVE_ACCESS_POINT,
-                            "",
-                            "",
-                            NULL,
-                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_CAPABILITIES] =
-        g_param_spec_uint(NM_DEVICE_IWD_CAPABILITIES,
-                          "",
-                          "",
-                          0,
-                          G_MAXUINT32,
-                          NM_WIFI_DEVICE_CAP_NONE,
-                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_SCANNING] = g_param_spec_boolean(NM_DEVICE_IWD_SCANNING,
-                                                         "",
-                                                         "",
-                                                         FALSE,
-                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_LAST_SCAN] = g_param_spec_int64(NM_DEVICE_IWD_LAST_SCAN,
-                                                        "",
-                                                        "",
-                                                        -1,
-                                                        G_MAXINT64,
-                                                        -1,
-                                                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-}