diff options
Diffstat (limited to 'src/supplicant-manager/nm-supplicant-interface.c')
| -rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.c | 1663 |
1 files changed, 0 insertions, 1663 deletions
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c deleted file mode 100644 index 05d9aa67..00000000 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ /dev/null @@ -1,1663 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2006 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include "nm-default.h" - -#include <stdio.h> -#include <string.h> - -#include "NetworkManagerUtils.h" -#include "nm-supplicant-interface.h" -#include "nm-supplicant-config.h" -#include "nm-core-internal.h" -#include "nm-dbus-compat.h" - -#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" -#define WPAS_DBUS_IFACE_BSS WPAS_DBUS_INTERFACE ".BSS" -#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" -#define WPAS_ERROR_INVALID_IFACE WPAS_DBUS_INTERFACE ".InvalidInterface" -#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".InterfaceExists" - -G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) - -#define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_SUPPLICANT_INTERFACE, \ - NMSupplicantInterfacePrivate)) - -/* Signals */ -enum { - STATE, /* change in the interface's state */ - REMOVED, /* interface was removed by the supplicant */ - NEW_BSS, /* interface saw a new access point from a scan */ - BSS_UPDATED, /* a BSS property changed */ - BSS_REMOVED, /* supplicant removed BSS from its scan list */ - SCAN_DONE, /* wifi scan is complete */ - CONNECTION_ERROR, /* an error occurred during a connection request */ - CREDENTIALS_REQUEST, /* 802.1x identity or password requested */ - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - - -/* Properties */ -NM_GOBJECT_PROPERTIES_DEFINE (NMSupplicantInterface, - PROP_IFACE, - PROP_SCANNING, - PROP_CURRENT_BSS, - PROP_IS_WIRELESS, - PROP_FAST_SUPPORTED, - PROP_AP_SUPPORT, -); - -typedef struct { - char * dev; - bool is_wireless; - bool fast_supported; - gboolean has_credreq; /* Whether querying 802.1x credentials is supported */ - NMSupplicantFeature ap_support; /* Lightweight AP mode support */ - NMSupplicantFeature mac_randomization_support; - guint32 max_scan_ssids; - guint32 ready_count; - - char * object_path; - guint32 state; - int disconnect_reason; - - gboolean scanning; - - GDBusProxy * wpas_proxy; - GCancellable * init_cancellable; - GDBusProxy * iface_proxy; - GCancellable * other_cancellable; - GCancellable * assoc_cancellable; - char * net_path; - guint32 blobs_left; - GHashTable * bss_proxies; - char * current_bss; - - gint32 last_scan; /* timestamp as returned by nm_utils_get_monotonic_timestamp_s() */ - - NMSupplicantConfig *cfg; -} NMSupplicantInterfacePrivate; - -/*********************************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_SUPPLICANT -#define _NMLOG_PREFIX_NAME "sup-iface" -#define _NMLOG(level, ...) \ - G_STMT_START { \ - char _sbuf[64]; \ - \ - nm_log ((level), _NMLOG_DOMAIN, \ - "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((self) \ - ? nm_sprintf_buf (_sbuf, \ - "[%p,%s]", \ - (self), \ - NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev) \ - : "") \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } G_STMT_END - -/*********************************************************************************************/ - -static void -emit_error_helper (NMSupplicantInterface *self, GError *error) -{ - char *name = NULL; - - if (g_dbus_error_is_remote_error (error)) - name = g_dbus_error_get_remote_error (error); - - g_signal_emit (self, signals[CONNECTION_ERROR], 0, name, error->message); - g_free (name); -} - -static void -bss_props_changed_cb (GDBusProxy *proxy, - GVariant *changed_properties, - char **invalidated_properties, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (priv->scanning) - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); - - g_signal_emit (self, signals[BSS_UPDATED], 0, - g_dbus_proxy_get_object_path (proxy), - changed_properties); -} - -static GVariant * -_get_bss_proxy_properties (NMSupplicantInterface *self, GDBusProxy *proxy) -{ - gs_strfreev char **properties = NULL; - GVariantBuilder builder; - char **iter; - - iter = properties = g_dbus_proxy_get_cached_property_names (proxy); - if (!iter) - return NULL; - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - while (*iter) { - GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter); - - g_variant_builder_add (&builder, "{sv}", *iter++, copy); - g_variant_unref (copy); - } - - return g_variant_builder_end (&builder); -} - -#define BSS_PROXY_INITED "bss-proxy-inited" - -static void -on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *props = NULL; - - if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - self = NM_SUPPLICANT_INTERFACE (user_data); - _LOGD ("failed to acquire BSS proxy: (%s)", error->message); - g_hash_table_remove (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->bss_proxies, - g_dbus_proxy_get_object_path (proxy)); - } - return; - } - - self = NM_SUPPLICANT_INTERFACE (user_data); - props = _get_bss_proxy_properties (self, proxy); - if (!props) - return; - - g_object_set_data (G_OBJECT (proxy), BSS_PROXY_INITED, GUINT_TO_POINTER (TRUE)); - - g_signal_emit (self, signals[NEW_BSS], 0, - g_dbus_proxy_get_object_path (proxy), - g_variant_ref_sink (props)); -} - -static void -handle_new_bss (NMSupplicantInterface *self, const char *object_path) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - GDBusProxy *bss_proxy; - - g_return_if_fail (object_path != NULL); - - if (g_hash_table_lookup (priv->bss_proxies, object_path)) - return; - - bss_proxy = g_object_new (G_TYPE_DBUS_PROXY, - "g-bus-type", G_BUS_TYPE_SYSTEM, - "g-flags", G_DBUS_PROXY_FLAGS_NONE, - "g-name", WPAS_DBUS_SERVICE, - "g-object-path", object_path, - "g-interface-name", WPAS_DBUS_IFACE_BSS, - NULL); - g_hash_table_insert (priv->bss_proxies, - (char *) g_dbus_proxy_get_object_path (bss_proxy), - bss_proxy); - g_signal_connect (bss_proxy, "g-properties-changed", G_CALLBACK (bss_props_changed_cb), self); - g_async_initable_init_async (G_ASYNC_INITABLE (bss_proxy), - G_PRIORITY_DEFAULT, - priv->other_cancellable, - (GAsyncReadyCallback) on_bss_proxy_acquired, - self); -} - -static void -set_state (NMSupplicantInterface *self, guint32 new_state) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - guint32 old_state = priv->state; - - g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST); - - if (new_state == priv->state) - return; - - /* DOWN is a terminal state */ - g_return_if_fail (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DOWN); - - /* Cannot regress to READY, STARTING, or INIT from higher states */ - if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) - g_return_if_fail (new_state > NM_SUPPLICANT_INTERFACE_STATE_READY); - - if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) { - if (priv->other_cancellable) { - g_warn_if_fail (priv->other_cancellable == NULL); - g_cancellable_cancel (priv->other_cancellable); - g_clear_object (&priv->other_cancellable); - } - priv->other_cancellable = g_cancellable_new (); - } else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { - if (priv->init_cancellable) - g_cancellable_cancel (priv->init_cancellable); - g_clear_object (&priv->init_cancellable); - - if (priv->other_cancellable) - g_cancellable_cancel (priv->other_cancellable); - g_clear_object (&priv->other_cancellable); - - if (priv->iface_proxy) - g_signal_handlers_disconnect_by_data (priv->iface_proxy, self); - } - - priv->state = new_state; - - if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING - || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); - - /* Disconnect reason is no longer relevant when not in the DISCONNECTED state */ - if (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED) - priv->disconnect_reason = 0; - - g_signal_emit (self, signals[STATE], 0, - priv->state, - old_state, - priv->disconnect_reason); -} - -static int -wpas_state_string_to_enum (const char *str_state) -{ - if (!strcmp (str_state, "interface_disabled")) - return NM_SUPPLICANT_INTERFACE_STATE_DISABLED; - else if (!strcmp (str_state, "disconnected")) - return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; - else if (!strcmp (str_state, "inactive")) - return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE; - else if (!strcmp (str_state, "scanning")) - return NM_SUPPLICANT_INTERFACE_STATE_SCANNING; - else if (!strcmp (str_state, "authenticating")) - return NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING; - else if (!strcmp (str_state, "associating")) - return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING; - else if (!strcmp (str_state, "associated")) - return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED; - else if (!strcmp (str_state, "4way_handshake")) - return NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE; - else if (!strcmp (str_state, "group_handshake")) - return NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE; - else if (!strcmp (str_state, "completed")) - return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED; - - return -1; -} - -static void -set_state_from_string (NMSupplicantInterface *self, const char *new_state) -{ - int state; - - state = wpas_state_string_to_enum (new_state); - if (state == -1) { - _LOGW ("unknown supplicant state '%s'", new_state); - return; - } - set_state (self, (guint32) state); -} - -static void -set_scanning (NMSupplicantInterface *self, gboolean new_scanning) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (priv->scanning != new_scanning) { - priv->scanning = new_scanning; - - /* Cache time of last scan completion */ - if (priv->scanning == FALSE) - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); - - _notify (self, PROP_SCANNING); - } -} - -gboolean -nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv; - - g_return_val_if_fail (self != NULL, FALSE); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (priv->scanning) - return TRUE; - if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) - return TRUE; - return FALSE; -} - -const char * -nm_supplicant_interface_get_current_bss (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv; - - g_return_val_if_fail (self != NULL, FALSE); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - return priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY ? priv->current_bss : NULL; -} - -gint32 -nm_supplicant_interface_get_last_scan_time (NMSupplicantInterface *self) -{ - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->last_scan; -} - -#define MATCH_PROPERTY(p, n, v, t) (!strcmp (p, n) && g_variant_is_of_type (v, t)) - -static void -parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - gboolean have_active = FALSE, have_ssid = FALSE; - gint32 max_scan_ssids = -1; - const char **array; - - g_return_if_fail (capabilities && g_variant_is_of_type (capabilities, G_VARIANT_TYPE_VARDICT)); - - if ( g_variant_lookup (capabilities, "Scan", "^a&s", &array) - && array) { - if (g_strv_contains (array, "active")) - have_active = TRUE; - if (g_strv_contains (array, "ssid")) - have_ssid = TRUE; - g_free (array); - } - - if (g_variant_lookup (capabilities, "MaxScanSSID", "i", &max_scan_ssids)) { - /* We need active scan and SSID probe capabilities to care about MaxScanSSIDs */ - if (max_scan_ssids > 0 && have_active && have_ssid) { - /* wpa_supplicant's WPAS_MAX_SCAN_SSIDS value is 16, but for speed - * and to ensure we don't disclose too many SSIDs from the hidden - * list, we'll limit to 5. - */ - priv->max_scan_ssids = CLAMP (max_scan_ssids, 0, 5); - _LOGI ("supports %d scan SSIDs", priv->max_scan_ssids); - } - } -} - -static void -iface_check_ready (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (priv->ready_count && priv->state < NM_SUPPLICANT_INTERFACE_STATE_READY) { - priv->ready_count--; - if (priv->ready_count == 0) - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY); - } -} - -gboolean -nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self, - const char *field, - const char *value, - GError **error) -{ - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *reply = NULL; - - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); - g_return_val_if_fail (field != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - g_return_val_if_fail (priv->has_credreq == TRUE, FALSE); - - /* Need a network block object path */ - g_return_val_if_fail (priv->net_path, FALSE); - reply = g_dbus_proxy_call_sync (priv->iface_proxy, - "NetworkReply", - g_variant_new ("(oss)", - priv->net_path, - field, - value), - G_DBUS_CALL_FLAGS_NONE, - 5000, - NULL, - error); - if (error && *error) - g_dbus_error_strip_remote_error (*error); - - return !!reply; -} - -static void -iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - - /* We know NetworkReply is supported if the NetworkReply method returned - * successfully (which is unexpected since we sent a bogus network - * object path) or if we got an "InvalidArgs" (which indicates NetworkReply - * is supported). We know it's not supported if we get an - * "UnknownMethod" error. - */ - - variant = g_dbus_proxy_call_finish (proxy, result, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (variant || _nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs")) - priv->has_credreq = TRUE; - - _LOGD ("supplicant %s network credentials requests", - priv->has_credreq ? "supports" : "does not support"); - - iface_check_ready (self); -} - -NMSupplicantFeature -nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self) -{ - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ap_support; -} - -void -nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, - NMSupplicantFeature ap_support) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - /* Use the best indicator of support between the supplicant global - * Capabilities property and the interface's introspection data. - */ - if (ap_support > priv->ap_support) - priv->ap_support = ap_support; -} - -static void -set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - - variant = _nm_dbus_proxy_call_finish (proxy, result, - G_VARIANT_TYPE ("()"), - &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - if (error) - _LOGW ("failed to enable scan MAC address randomization (%s)", error->message); - iface_check_ready (self); -} - -static void -iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - const char *data; - - variant = _nm_dbus_proxy_call_finish (proxy, result, - G_VARIANT_TYPE ("(s)"), - &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (variant) { - g_variant_get (variant, "(&s)", &data); - - /* The ProbeRequest method only exists if AP mode has been enabled */ - if (strstr (data, "ProbeRequest")) - priv->ap_support = NM_SUPPLICANT_FEATURE_YES; - - if (strstr (data, "PreassocMacAddr")) { - priv->mac_randomization_support = NM_SUPPLICANT_FEATURE_YES; - - /* Turn on MAC randomization during scans by default */ - priv->ready_count++; - g_dbus_proxy_call (priv->iface_proxy, - DBUS_INTERFACE_PROPERTIES ".Set", - g_variant_new ("(ssv)", - WPAS_DBUS_IFACE_INTERFACE, - "PreassocMacAddr", - g_variant_new_string ("0")), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->init_cancellable, - (GAsyncReadyCallback) set_preassoc_scan_mac_cb, - self); - } - } - - iface_check_ready (self); -} - -static void -wpas_iface_scan_done (GDBusProxy *proxy, - gboolean success, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - GVariant *props; - GHashTableIter iter; - char *bss_path; - GDBusProxy *bss_proxy; - - /* Cache last scan completed time */ - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); - - g_signal_emit (self, signals[SCAN_DONE], 0, success); - - /* Emit NEW_BSS so that wifi device has the APs (in case it removed them) */ - g_hash_table_iter_init (&iter, priv->bss_proxies); - while (g_hash_table_iter_next (&iter, (gpointer) &bss_path, (gpointer) &bss_proxy)) { - if (g_object_get_data (G_OBJECT (bss_proxy), BSS_PROXY_INITED)) { - props = _get_bss_proxy_properties (self, bss_proxy); - if (props) { - g_signal_emit (self, signals[NEW_BSS], 0, - bss_path, - g_variant_ref_sink (props)); - g_variant_unref (props); - } - } - } -} - -static void -wpas_iface_bss_added (GDBusProxy *proxy, - const char *path, - GVariant *props, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (priv->scanning) - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); - - handle_new_bss (self, path); -} - -static void -wpas_iface_bss_removed (GDBusProxy *proxy, - const char *path, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - g_signal_emit (self, signals[BSS_REMOVED], 0, path); - g_hash_table_remove (priv->bss_proxies, path); -} - -static void -wpas_iface_network_request (GDBusProxy *proxy, - const char *path, - const char *field, - const char *message, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path)) - g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message); -} - -static void -props_changed_cb (GDBusProxy *proxy, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - const char *s, **array, **iter; - gboolean b = FALSE; - gint32 i32; - GVariant *v; - - g_object_freeze_notify (G_OBJECT (self)); - - if (g_variant_lookup (changed_properties, "Scanning", "b", &b)) - set_scanning (self, b); - - if ( g_variant_lookup (changed_properties, "State", "&s", &s) - && priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) { - /* Only transition to actual wpa_supplicant interface states (ie, - * anything > READY) after the NMSupplicantInterface has had a - * chance to initialize, which is signalled by entering the READY - * state. - */ - set_state_from_string (self, s); - } - - if (g_variant_lookup (changed_properties, "BSSs", "^a&o", &array)) { - iter = array; - while (*iter) - handle_new_bss (self, *iter++); - g_free (array); - } - - if (g_variant_lookup (changed_properties, "CurrentBSS", "&o", &s)) { - if (strcmp (s, "/") == 0) - s = NULL; - if (g_strcmp0 (s, priv->current_bss) != 0) { - g_free (priv->current_bss); - priv->current_bss = g_strdup (s); - _notify (self, PROP_CURRENT_BSS); - } - } - - v = g_variant_lookup_value (changed_properties, "Capabilities", G_VARIANT_TYPE_VARDICT); - if (v) { - parse_capabilities (self, v); - g_variant_unref (v); - } - - if (g_variant_lookup (changed_properties, "DisconnectReason", "i", &i32)) { - /* Disconnect reason is currently only given for deauthentication events, - * not disassociation; currently they are IEEE 802.11 "reason codes", - * defined by (IEEE 802.11-2007, 7.3.1.7, Table 7-22). Any locally caused - * deauthentication will be negative, while authentications caused by the - * AP will be positive. - */ - priv->disconnect_reason = i32; - if (priv->disconnect_reason != 0) - _LOGW ("connection disconnected (reason %d)", priv->disconnect_reason); - } - - g_object_thaw_notify (G_OBJECT (self)); -} - -static void -on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_free_error GError *error = NULL; - - if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - self = NM_SUPPLICANT_INTERFACE (user_data); - _LOGW ("failed to acquire wpa_supplicant interface proxy: (%s)", error->message); - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); - } - return; - } - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - _nm_dbus_signal_connect (priv->iface_proxy, "ScanDone", G_VARIANT_TYPE ("(b)"), - G_CALLBACK (wpas_iface_scan_done), self); - _nm_dbus_signal_connect (priv->iface_proxy, "BSSAdded", G_VARIANT_TYPE ("(oa{sv})"), - G_CALLBACK (wpas_iface_bss_added), self); - _nm_dbus_signal_connect (priv->iface_proxy, "BSSRemoved", G_VARIANT_TYPE ("(o)"), - G_CALLBACK (wpas_iface_bss_removed), self); - _nm_dbus_signal_connect (priv->iface_proxy, "NetworkRequest", G_VARIANT_TYPE ("(oss)"), - G_CALLBACK (wpas_iface_network_request), self); - - /* Scan result aging parameters */ - g_dbus_proxy_call (priv->iface_proxy, - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", - WPAS_DBUS_IFACE_INTERFACE, - "BSSExpireAge", - g_variant_new_uint32 (250)), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->init_cancellable, - NULL, - NULL); - g_dbus_proxy_call (priv->iface_proxy, - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", - WPAS_DBUS_IFACE_INTERFACE, - "BSSExpireCount", - g_variant_new_uint32 (2)), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->init_cancellable, - NULL, - NULL); - - /* Check whether NetworkReply and AP mode are supported */ - priv->ready_count = 1; - g_dbus_proxy_call (priv->iface_proxy, - "NetworkReply", - g_variant_new ("(oss)", - "/fff", - "foobar", - "foobar"), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->init_cancellable, - (GAsyncReadyCallback) iface_check_netreply_cb, - self); - - if (priv->ap_support == NM_SUPPLICANT_FEATURE_UNKNOWN || - priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_UNKNOWN) { - /* If the global supplicant capabilities property is not present, we can - * fall back to checking whether the ProbeRequest method is supported. If - * neither of these works we have no way of determining if AP mode is - * supported or not. hostap 1.0 and earlier don't support either of these. - */ - priv->ready_count++; - g_dbus_proxy_call (priv->iface_proxy, - DBUS_INTERFACE_INTROSPECTABLE ".Introspect", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->init_cancellable, - (GAsyncReadyCallback) iface_introspect_cb, - self); - } -} - -static void -interface_add_done (NMSupplicantInterface *self, const char *path) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - _LOGD ("interface added to supplicant"); - - priv->object_path = g_strdup (path); - priv->iface_proxy = g_object_new (G_TYPE_DBUS_PROXY, - "g-bus-type", G_BUS_TYPE_SYSTEM, - "g-flags", G_DBUS_PROXY_FLAGS_NONE, - "g-name", WPAS_DBUS_SERVICE, - "g-object-path", priv->object_path, - "g-interface-name", WPAS_DBUS_IFACE_INTERFACE, - NULL); - g_signal_connect (priv->iface_proxy, "g-properties-changed", G_CALLBACK (props_changed_cb), self); - g_async_initable_init_async (G_ASYNC_INITABLE (priv->iface_proxy), - G_PRIORITY_DEFAULT, - priv->init_cancellable, - (GAsyncReadyCallback) on_iface_proxy_acquired, - self); -} - -static void -interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - const char *path; - - variant = _nm_dbus_proxy_call_finish (proxy, result, - G_VARIANT_TYPE ("(o)"), - &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (variant) { - g_variant_get (variant, "(&o)", &path); - interface_add_done (self, path); - } else { - g_dbus_error_strip_remote_error (error); - _LOGE ("error getting interface: %s", error->message); - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); - } -} - -static void -interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *variant = NULL; - const char *path; - - variant = _nm_dbus_proxy_call_finish (proxy, result, - G_VARIANT_TYPE ("(o)"), - &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (variant) { - g_variant_get (variant, "(&o)", &path); - interface_add_done (self, path); - } else if (_nm_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) { - /* Interface already added, just get its object path */ - g_dbus_proxy_call (priv->wpas_proxy, - "GetInterface", - g_variant_new ("(s)", priv->dev), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->init_cancellable, - (GAsyncReadyCallback) interface_get_cb, - self); - } else if ( g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) - || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_EXEC_FAILED) - || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FORK_FAILED) - || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FAILED) - || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMEOUT) - || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NO_REPLY) - || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMED_OUT) - || g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) { - /* Supplicant wasn't running and could not be launched via service - * activation. Wait for it to start by moving back to the INIT - * state. - */ - g_dbus_error_strip_remote_error (error); - _LOGD ("failed to activate supplicant: %s", error->message); - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_INIT); - } else { - g_dbus_error_strip_remote_error (error); - _LOGE ("error adding interface: %s", error->message); - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); - } -} - -#if HAVE_WEXT -#define DEFAULT_WIFI_DRIVER "nl80211,wext" -#else -#define DEFAULT_WIFI_DRIVER "nl80211" -#endif - -static void -on_wpas_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_free_error GError *error = NULL; - GDBusProxy *wpas_proxy; - GVariantBuilder props; - - wpas_proxy = g_dbus_proxy_new_for_bus_finish (result, &error); - if (!wpas_proxy) { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - self = NM_SUPPLICANT_INTERFACE (user_data); - _LOGW ("failed to acquire wpa_supplicant proxy: (%s)", error->message); - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); - } - return; - } - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - priv->wpas_proxy = wpas_proxy; - - /* Try to add the interface to the supplicant. If the supplicant isn't - * running, this will start it via D-Bus activation and return the response - * when the supplicant has started. - */ - - g_variant_builder_init (&props, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&props, "{sv}", - "Driver", - g_variant_new_string (priv->is_wireless ? DEFAULT_WIFI_DRIVER : "wired")); - g_variant_builder_add (&props, "{sv}", - "Ifname", - g_variant_new_string (priv->dev)); - - g_dbus_proxy_call (priv->wpas_proxy, - "CreateInterface", - g_variant_new ("(a{sv})", &props), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->init_cancellable, - (GAsyncReadyCallback) interface_add_cb, - self); -} - -static void -interface_add (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - /* Can only start the interface from INIT state */ - g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT); - - _LOGD ("adding interface to supplicant"); - - /* Move to starting to prevent double-calls of interface_add() */ - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING); - - g_warn_if_fail (priv->init_cancellable == NULL); - g_clear_object (&priv->init_cancellable); - priv->init_cancellable = g_cancellable_new (); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE, - priv->init_cancellable, - (GAsyncReadyCallback) on_wpas_proxy_acquired, - self); -} - -void -nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self, - gboolean available) -{ - NMSupplicantInterfacePrivate *priv; - - g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self)); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (available) { - /* This can happen if the supplicant couldn't be activated but - * for some reason was started after the activation failure. - */ - if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT) - interface_add (self); - } else { - /* The supplicant stopped; so we must tear down the interface */ - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); - } -} - -static void -log_result_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - gs_unref_variant GVariant *reply = NULL; - gs_free_error GError *error = NULL; - - reply = g_dbus_proxy_call_finish (proxy, result, &error); - if ( !reply - && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) - && !strstr (error->message, "fi.w1.wpa_supplicant1.NotConnected")) { - g_dbus_error_strip_remote_error (error); - nm_log_warn (_NMLOG_DOMAIN, "%s: failed to %s: %s", - _NMLOG_PREFIX_NAME, (const char *) user_data, error->message); - } -} - -void -nm_supplicant_interface_disconnect (NMSupplicantInterface * self) -{ - NMSupplicantInterfacePrivate *priv; - - g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self)); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - /* Cancel all pending calls related to a prior connection attempt */ - if (priv->assoc_cancellable) { - g_cancellable_cancel (priv->assoc_cancellable); - g_clear_object (&priv->assoc_cancellable); - } - - /* Don't do anything if there is no connection to the supplicant yet. */ - if (!priv->iface_proxy) - return; - - /* Disconnect from the current AP */ - if ( (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_SCANNING) - && (priv->state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)) { - g_dbus_proxy_call (priv->iface_proxy, - "Disconnect", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) log_result_cb, - "disconnect"); - } - - /* Remove any network that was added by NetworkManager */ - if (priv->net_path) { - g_dbus_proxy_call (priv->iface_proxy, - "RemoveNetwork", - g_variant_new ("(o)", priv->net_path), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->other_cancellable, - (GAsyncReadyCallback) log_result_cb, - "remove network"); - g_free (priv->net_path); - priv->net_path = NULL; - } -} - -static void -select_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - gs_unref_variant GVariant *reply = NULL; - gs_free_error GError *error = NULL; - - reply = g_dbus_proxy_call_finish (proxy, result, &error); - if ( !reply - && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - self = NM_SUPPLICANT_INTERFACE (user_data); - g_dbus_error_strip_remote_error (error); - _LOGW ("couldn't select network config: %s", error->message); - emit_error_helper (self, error); - } -} - -static void -call_select_network (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - /* We only select the network after all blobs (if any) have been set */ - if (priv->blobs_left == 0) { - g_dbus_proxy_call (priv->iface_proxy, - "SelectNetwork", - g_variant_new ("(o)", priv->net_path), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->assoc_cancellable, - (GAsyncReadyCallback) select_network_cb, - self); - } -} - -static void -add_blob_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *reply = NULL; - gs_free_error GError *error = NULL; - - reply = g_dbus_proxy_call_finish (proxy, result, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - priv->blobs_left--; - if (reply) - call_select_network (self); - else { - g_dbus_error_strip_remote_error (error); - _LOGW ("couldn't set network certificates: %s", error->message); - emit_error_helper (self, error); - } -} - -static void -add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *reply = NULL; - gs_free_error GError *error = NULL; - GHashTable *blobs; - GHashTableIter iter; - const char *blob_name; - GByteArray *blob_data; - - reply = _nm_dbus_proxy_call_finish (proxy, result, - G_VARIANT_TYPE ("(o)"), - &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - g_free (priv->net_path); - priv->net_path = NULL; - - if (error) { - g_dbus_error_strip_remote_error (error); - _LOGW ("adding network to supplicant failed: %s", error->message); - emit_error_helper (self, error); - return; - } - - g_variant_get (reply, "(o)", &priv->net_path); - - /* Send blobs first; otherwise jump to selecting the network */ - blobs = nm_supplicant_config_get_blobs (priv->cfg); - priv->blobs_left = g_hash_table_size (blobs); - - g_hash_table_iter_init (&iter, blobs); - while (g_hash_table_iter_next (&iter, (gpointer) &blob_name, (gpointer) &blob_data)) { - g_dbus_proxy_call (priv->iface_proxy, - "AddBlob", - g_variant_new ("(s@ay)", - blob_name, - g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - blob_data->data, blob_data->len, 1)), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->assoc_cancellable, - (GAsyncReadyCallback) add_blob_cb, - self); - } - - call_select_network (self); -} - -static void -add_network (NMSupplicantInterface *self) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - g_dbus_proxy_call (priv->iface_proxy, - "AddNetwork", - g_variant_new ("(@a{sv})", nm_supplicant_config_to_variant (priv->cfg)), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->assoc_cancellable, - (GAsyncReadyCallback) add_network_cb, - self); -} - -static void -set_mac_randomization_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *reply = NULL; - gs_free_error GError *error = NULL; - - reply = g_dbus_proxy_call_finish (proxy, result, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (!reply) { - g_dbus_error_strip_remote_error (error); - _LOGW ("couldn't send MAC randomization mode to the supplicant interface: %s", - error->message); - emit_error_helper (self, error); - return; - } - - _LOGT ("config: set MAC randomization to 0"); - add_network (self); -} - -static void -set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; - gs_unref_variant GVariant *reply = NULL; - gs_free_error GError *error = NULL; - - reply = g_dbus_proxy_call_finish (proxy, result, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - if (!reply) { - g_dbus_error_strip_remote_error (error); - _LOGW ("couldn't send AP scan mode to the supplicant interface: %s", - error->message); - emit_error_helper (self, error); - return; - } - - _LOGI ("config: set interface ap_scan to %d", - nm_supplicant_config_get_ap_scan (priv->cfg)); - - if (priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) { - /* Enable/disable association MAC address randomization */ - g_dbus_proxy_call (priv->iface_proxy, - DBUS_INTERFACE_PROPERTIES ".Set", - g_variant_new ("(ssv)", - WPAS_DBUS_IFACE_INTERFACE, - "MacAddr", - g_variant_new_string ("0")), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->assoc_cancellable, - (GAsyncReadyCallback) set_mac_randomization_cb, - self); - } else - add_network (self); -} - -gboolean -nm_supplicant_interface_set_config (NMSupplicantInterface *self, - NMSupplicantConfig *cfg, - GError **error) -{ - NMSupplicantInterfacePrivate *priv; - - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - nm_supplicant_interface_disconnect (self); - - /* Make sure the supplicant supports EAP-FAST before trying to send - * it an EAP-FAST configuration. - */ - if (nm_supplicant_config_fast_required (cfg) && !priv->fast_supported) { - g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG, - "EAP-FAST is not supported by the supplicant"); - return FALSE; - } - - g_clear_object (&priv->cfg); - if (cfg) { - priv->assoc_cancellable = g_cancellable_new (); - priv->cfg = g_object_ref (cfg); - g_dbus_proxy_call (priv->iface_proxy, - DBUS_INTERFACE_PROPERTIES ".Set", - g_variant_new ("(ssv)", - WPAS_DBUS_IFACE_INTERFACE, - "ApScan", - g_variant_new_uint32 (nm_supplicant_config_get_ap_scan (priv->cfg))), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->assoc_cancellable, - (GAsyncReadyCallback) set_ap_scan_cb, - self); - } - return TRUE; -} - -static void -scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) -{ - NMSupplicantInterface *self; - gs_unref_variant GVariant *reply = NULL; - gs_free_error GError *error = NULL; - - reply = g_dbus_proxy_call_finish (proxy, result, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - self = NM_SUPPLICANT_INTERFACE (user_data); - - if (error) { - if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError")) - _LOGD ("could not get scan request result: %s", error->message); - else { - g_dbus_error_strip_remote_error (error); - _LOGW ("could not get scan request result: %s", error->message); - } - } - g_signal_emit (self, signals[SCAN_DONE], 0, error ? FALSE : TRUE); -} - -gboolean -nm_supplicant_interface_request_scan (NMSupplicantInterface *self, const GPtrArray *ssids) -{ - NMSupplicantInterfacePrivate *priv; - GVariantBuilder builder; - guint i; - - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); - - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - /* Scan parameters */ - g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&builder, "{sv}", "Type", g_variant_new_string ("active")); - if (ssids) { - GVariantBuilder ssids_builder; - - g_variant_builder_init (&ssids_builder, G_VARIANT_TYPE_BYTESTRING_ARRAY); - for (i = 0; i < ssids->len; i++) { - GByteArray *ssid = g_ptr_array_index (ssids, i); - g_variant_builder_add (&ssids_builder, "@ay", - g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - ssid->data, ssid->len, 1)); - } - g_variant_builder_add (&builder, "{sv}", "SSIDs", g_variant_builder_end (&ssids_builder)); - } - - g_dbus_proxy_call (priv->iface_proxy, - "Scan", - g_variant_new ("(a{sv})", &builder), - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->other_cancellable, - (GAsyncReadyCallback) scan_request_cb, - self); - return TRUE; -} - -guint32 -nm_supplicant_interface_get_state (NMSupplicantInterface * self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NM_SUPPLICANT_INTERFACE_STATE_DOWN); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state; -} - -const char * -nm_supplicant_interface_state_to_string (guint32 state) -{ - switch (state) { - case NM_SUPPLICANT_INTERFACE_STATE_INIT: - return "init"; - case NM_SUPPLICANT_INTERFACE_STATE_STARTING: - return "starting"; - case NM_SUPPLICANT_INTERFACE_STATE_READY: - return "ready"; - case NM_SUPPLICANT_INTERFACE_STATE_DISABLED: - return "disabled"; - case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: - return "disconnected"; - case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE: - return "inactive"; - case NM_SUPPLICANT_INTERFACE_STATE_SCANNING: - return "scanning"; - case NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING: - return "authenticating"; - case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING: - return "associating"; - case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED: - return "associated"; - case NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE: - return "4-way handshake"; - case NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE: - return "group handshake"; - case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: - return "completed"; - case NM_SUPPLICANT_INTERFACE_STATE_DOWN: - return "down"; - default: - break; - } - return "unknown"; -} - -const char * -nm_supplicant_interface_get_object_path (NMSupplicantInterface *self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->object_path; -} - -const char * -nm_supplicant_interface_get_ifname (NMSupplicantInterface *self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; -} - -guint -nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), 0); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->max_scan_ssids; -} - -/*******************************************************************/ - -NMSupplicantInterface * -nm_supplicant_interface_new (const char *ifname, - gboolean is_wireless, - gboolean fast_supported, - NMSupplicantFeature ap_support) -{ - g_return_val_if_fail (ifname != NULL, NULL); - - return g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, - NM_SUPPLICANT_INTERFACE_IFACE, ifname, - NM_SUPPLICANT_INTERFACE_IS_WIRELESS, is_wireless, - NM_SUPPLICANT_INTERFACE_FAST_SUPPORTED, fast_supported, - NM_SUPPLICANT_INTERFACE_AP_SUPPORT, (int) ap_support, - NULL); -} - -static void -nm_supplicant_interface_init (NMSupplicantInterface * self) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT; - priv->bss_proxies = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_IFACE: - /* construct-only */ - priv->dev = g_value_dup_string (value); - g_return_if_fail (priv->dev); - break; - case PROP_IS_WIRELESS: - /* construct-only */ - priv->is_wireless = g_value_get_boolean (value); - break; - case PROP_FAST_SUPPORTED: - /* construct-only */ - priv->fast_supported = g_value_get_boolean (value); - break; - case PROP_AP_SUPPORT: - /* construct-only */ - priv->ap_support = g_value_get_int (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_SCANNING: - g_value_set_boolean (value, priv->scanning); - break; - case PROP_CURRENT_BSS: - g_value_set_string (value, priv->current_bss); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - - if (priv->iface_proxy) - g_signal_handlers_disconnect_by_data (priv->iface_proxy, NM_SUPPLICANT_INTERFACE (object)); - g_clear_object (&priv->iface_proxy); - - nm_clear_g_cancellable (&priv->init_cancellable); - nm_clear_g_cancellable (&priv->other_cancellable); - nm_clear_g_cancellable (&priv->assoc_cancellable); - - g_clear_object (&priv->wpas_proxy); - g_clear_pointer (&priv->bss_proxies, (GDestroyNotify) g_hash_table_destroy); - - g_clear_pointer (&priv->net_path, g_free); - g_clear_pointer (&priv->dev, g_free); - g_clear_pointer (&priv->object_path, g_free); - g_clear_pointer (&priv->current_bss, g_free); - - g_clear_object (&priv->cfg); - - /* Chain up to the parent class */ - G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); -} - -static void -nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate)); - - object_class->dispose = dispose; - object_class->set_property = set_property; - object_class->get_property = get_property; - - /* Properties */ - obj_properties[PROP_SCANNING] = - g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_SCANNING, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_CURRENT_BSS] = - g_param_spec_string (NM_SUPPLICANT_INTERFACE_CURRENT_BSS, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_IFACE] = - g_param_spec_string (NM_SUPPLICANT_INTERFACE_IFACE, "", "", - NULL, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_IS_WIRELESS] = - g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_IS_WIRELESS, "", "", - TRUE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_FAST_SUPPORTED] = - g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_FAST_SUPPORTED, "", "", - TRUE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_AP_SUPPORT] = - g_param_spec_int (NM_SUPPLICANT_INTERFACE_AP_SUPPORT, "", "", - NM_SUPPLICANT_FEATURE_UNKNOWN, - NM_SUPPLICANT_FEATURE_YES, - NM_SUPPLICANT_FEATURE_UNKNOWN, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - /* Signals */ - signals[STATE] = - g_signal_new (NM_SUPPLICANT_INTERFACE_STATE, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state), - NULL, NULL, NULL, - G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INT); - - signals[REMOVED] = - g_signal_new (NM_SUPPLICANT_INTERFACE_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, removed), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[NEW_BSS] = - g_signal_new (NM_SUPPLICANT_INTERFACE_NEW_BSS, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, new_bss), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT); - - signals[BSS_UPDATED] = - g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_UPDATED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, bss_updated), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT); - - signals[BSS_REMOVED] = - g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_REMOVED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, bss_removed), - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_STRING); - - signals[SCAN_DONE] = - g_signal_new (NM_SUPPLICANT_INTERFACE_SCAN_DONE, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_done), - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - signals[CONNECTION_ERROR] = - g_signal_new (NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); - - signals[CREDENTIALS_REQUEST] = - g_signal_new (NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, credentials_request), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); -} - |