diff options
| author | Michael Biebl <biebl@debian.org> | 2016-01-20 16:26:51 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2016-01-20 16:26:51 +0100 |
| commit | 494f296a3baab08522617b24b1f126d8f9a17502 (patch) | |
| tree | c8ef32fb0dd1c4ff35a0b38e787abb58692de0cd /src/supplicant-manager/nm-supplicant-interface.c | |
| parent | 54f6333410ffd570e62717d9e77c5c987175e397 (diff) | |
Imported Upstream version 1.1.90 upstream/1.1.90
Diffstat (limited to 'src/supplicant-manager/nm-supplicant-interface.c')
| -rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.c | 414 |
1 files changed, 298 insertions, 116 deletions
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 30be23ae..9251af1f 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -23,15 +23,13 @@ #include <stdio.h> #include <string.h> -#include <glib.h> +#include "nm-default.h" #include "NetworkManagerUtils.h" #include "nm-supplicant-interface.h" -#include "nm-logging.h" #include "nm-supplicant-config.h" -#include "nm-glib-compat.h" -#include "gsystem-local-alloc.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" @@ -64,6 +62,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0 = 0, PROP_SCANNING, + PROP_CURRENT_BSS, LAST_PROP }; @@ -72,7 +71,8 @@ typedef struct { char * dev; gboolean is_wireless; gboolean has_credreq; /* Whether querying 802.1x credentials is supported */ - ApSupport ap_support; /* Lightweight AP mode support */ + NMSupplicantFeature ap_support; /* Lightweight AP mode support */ + NMSupplicantFeature mac_randomization_support; gboolean fast_supported; guint32 max_scan_ssids; guint32 ready_count; @@ -91,6 +91,7 @@ typedef struct { 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() */ @@ -333,6 +334,17 @@ nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) 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) { @@ -413,21 +425,10 @@ nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self, 5000, NULL, error); - /* reply will be unrefed when function exits */ - return !!reply; -} - -static gboolean -_dbus_error_has_name (GError *error, const char *dbus_error_name) -{ - gs_free char *error_name = NULL; - gboolean is_error = FALSE; + if (error && *error) + g_dbus_error_strip_remote_error (*error); - if (error && g_dbus_error_is_remote_error (error)) { - error_name = g_dbus_error_get_remote_error (error); - is_error = !g_strcmp0 (error_name, dbus_error_name); - } - return is_error; + return !!reply; } static void @@ -452,7 +453,7 @@ iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - if (variant || _dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs")) + if (variant || _nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs")) priv->has_credreq = TRUE; nm_log_dbg (LOGD_SUPPLICANT, "Supplicant %s network credentials requests", @@ -461,7 +462,7 @@ iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ iface_check_ready (self); } -ApSupport +NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self) { return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ap_support; @@ -469,7 +470,7 @@ nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self) void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, - ApSupport ap_support) + NMSupplicantFeature ap_support) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); @@ -480,8 +481,31 @@ nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self, priv->ap_support = ap_support; } +NMSupplicantFeature +nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *self) +{ + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->mac_randomization_support; +} + +static void +set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + 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; + if (error) + nm_log_warn (LOGD_SUPPLICANT, "Failed to enable scan MAC address randomization"); + + iface_check_ready (NM_SUPPLICANT_INTERFACE (user_data)); +} + static void -iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { NMSupplicantInterface *self; NMSupplicantInterfacePrivate *priv; @@ -489,77 +513,115 @@ iface_check_ap_mode_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_d gs_free_error GError *error = NULL; const char *data; - /* The ProbeRequest method only exists if AP mode has been enabled */ - variant = g_dbus_proxy_call_finish (proxy, result, &error); + 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_is_of_type (variant, G_VARIANT_TYPE ("(s)"))) { + 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 = AP_SUPPORT_YES; + 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 ("1")), + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->init_cancellable, + (GAsyncReadyCallback) set_preassoc_scan_mac_cb, + self); + } } iface_check_ready (self); } -#define MATCH_SIGNAL(s, n, v, t) (!strcmp (s, n) && g_variant_is_of_type (v, t)) - static void -signal_cb (GDBusProxy *proxy, - const gchar *sender, - const gchar *signal, - GVariant *args, - gpointer user_data) +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); - const char *path, *field, *message; - gboolean success; + GVariant *props; + GHashTableIter iter; + char *bss_path; + GDBusProxy *bss_proxy; - if (MATCH_SIGNAL (signal, "ScanDone", args, G_VARIANT_TYPE ("(b)"))) { - 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); - /* Cache last scan completed time */ + if (priv->scanning) priv->last_scan = nm_utils_get_monotonic_timestamp_s (); - g_variant_get (args, "(b)", &success); - 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); - } - } - } - } else if (MATCH_SIGNAL (signal, "BSSAdded", args, G_VARIANT_TYPE ("(oa{sv})"))) { - if (priv->scanning) - priv->last_scan = nm_utils_get_monotonic_timestamp_s (); + handle_new_bss (self, path); +} - g_variant_get (args, "(&oa{sv})", &path, NULL); - handle_new_bss (self, path); - } else if (MATCH_SIGNAL (signal, "BSSRemoved", args, G_VARIANT_TYPE ("(o)"))) { - g_variant_get (args, "(&o)", &path); - g_signal_emit (self, signals[BSS_REMOVED], 0, path); - g_hash_table_remove (priv->bss_proxies, path); - } else if (MATCH_SIGNAL (signal, "NetworkRequest", args, G_VARIANT_TYPE ("(oss)"))) { - g_variant_get (args, "(&o&s&s)", &path, &field, &message); - if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path)) - g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message); - } +static void +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 @@ -575,6 +637,8 @@ props_changed_cb (GDBusProxy *proxy, gint32 i32; GVariant *v; + g_object_freeze_notify (G_OBJECT (self)); + if (g_variant_lookup (changed_properties, "Scanning", "b", &b)) set_scanning (self, b); @@ -595,6 +659,16 @@ props_changed_cb (GDBusProxy *proxy, 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); + g_object_notify (G_OBJECT (self), NM_SUPPLICANT_INTERFACE_CURRENT_BSS); + } + } + v = g_variant_lookup_value (changed_properties, "Capabilities", G_VARIANT_TYPE_VARDICT); if (v) { parse_capabilities (self, v); @@ -614,6 +688,8 @@ props_changed_cb (GDBusProxy *proxy, priv->disconnect_reason); } } + + g_object_thaw_notify (G_OBJECT (self)); } static void @@ -634,7 +710,38 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ self = NM_SUPPLICANT_INTERFACE (user_data); priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - g_signal_connect (priv->iface_proxy, "g-signal", G_CALLBACK (signal_cb), self); + _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; @@ -650,7 +757,8 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ (GAsyncReadyCallback) iface_check_netreply_cb, self); - if (priv->ap_support == AP_SUPPORT_UNKNOWN) { + 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 @@ -658,12 +766,12 @@ on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_ */ priv->ready_count++; g_dbus_proxy_call (priv->iface_proxy, - "org.freedesktop.DBus.Introspectable.Introspect", + DBUS_INTERFACE_INTROSPECTABLE ".Introspect", NULL, G_DBUS_CALL_FLAGS_NONE, -1, priv->init_cancellable, - (GAsyncReadyCallback) iface_check_ap_mode_cb, + (GAsyncReadyCallback) iface_introspect_cb, self); } } @@ -698,20 +806,22 @@ interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) NMSupplicantInterfacePrivate *priv; gs_unref_variant GVariant *variant = NULL; gs_free_error GError *error = NULL; - char *path; + const char *path; - variant = g_dbus_proxy_call_finish (proxy, result, &error); + 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_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) { - g_variant_get (variant, "(o)", &path); + if (variant) { + g_variant_get (variant, "(&o)", &path); interface_add_done (self, path); - g_free (path); } else { + g_dbus_error_strip_remote_error (error); nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", priv->dev, error->message); set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } @@ -724,20 +834,21 @@ interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) NMSupplicantInterfacePrivate *priv; gs_free_error GError *error = NULL; gs_unref_variant GVariant *variant = NULL; - char *path; + const char *path; - variant = g_dbus_proxy_call_finish (proxy, result, &error); + 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_is_of_type (variant, G_VARIANT_TYPE ("(o)"))) { - g_variant_get (variant, "(o)", &path); + if (variant) { + g_variant_get (variant, "(&o)", &path); interface_add_done (self, path); - g_free (path); - } else if (_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) { + } 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", @@ -759,10 +870,12 @@ interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) * activation. Wait for it to start by moving back to the INIT * state. */ + g_dbus_error_strip_remote_error (error); nm_log_dbg (LOGD_SUPPLICANT, "(%s): failed to activate supplicant: %s", priv->dev, error->message); set_state (self, NM_SUPPLICANT_INTERFACE_STATE_INIT); } else { + g_dbus_error_strip_remote_error (error); nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", priv->dev, error->message); set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } @@ -877,8 +990,12 @@ log_result_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) 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)) - nm_log_warn (LOGD_SUPPLICANT, "Failed to %s: %s.", error->message, (char *) user_data); + 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 (LOGD_SUPPLICANT, "Failed to %s: %s.", (char *) user_data, error->message); + } } void @@ -936,6 +1053,7 @@ select_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) reply = g_dbus_proxy_call_finish (proxy, result, &err); if (!reply && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_dbus_error_strip_remote_error (err); nm_log_warn (LOGD_SUPPLICANT, "Couldn't select network config: %s.", err->message); emit_error_helper (NM_SUPPLICANT_INTERFACE (user_data), err); } @@ -978,6 +1096,7 @@ add_blob_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) if (reply) call_select_network (self); else { + g_dbus_error_strip_remote_error (err); nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network certificates: %s.", err->message); emit_error_helper (self, err); } @@ -995,30 +1114,26 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) const char *blob_name; GByteArray *blob_data; - reply = g_dbus_proxy_call_finish (proxy, result, &error); + 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); - if (reply && !g_variant_is_of_type (reply, G_VARIANT_TYPE ("(o)"))) { - error = g_error_new (NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "Unexpected AddNetwork reply type %s", - g_variant_get_type_string (reply)); - } - g_free (priv->net_path); priv->net_path = NULL; if (error) { + g_dbus_error_strip_remote_error (error); nm_log_warn (LOGD_SUPPLICANT, "Adding network to supplicant failed: %s.", error->message); emit_error_helper (self, error); return; } g_variant_get (reply, "(o)", &priv->net_path); - g_assert (priv->net_path); /* Send blobs first; otherwise jump to selecting the network */ blobs = nm_supplicant_config_get_blobs (priv->cfg); @@ -1043,6 +1158,51 @@ add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) } 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); + nm_log_warn (LOGD_SUPPLICANT, "Couldn't send MAC randomization mode to " + "the supplicant interface: %s.", + error->message); + emit_error_helper (self, error); + return; + } + + nm_log_info (LOGD_SUPPLICANT, "Config: set MAC randomization to %s", + nm_supplicant_config_get_mac_randomization (priv->cfg)); + + add_network (self); +} + +static void set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { NMSupplicantInterface *self; @@ -1058,6 +1218,7 @@ set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); if (!reply) { + g_dbus_error_strip_remote_error (error); nm_log_warn (LOGD_SUPPLICANT, "Couldn't send AP scan mode to the supplicant interface: %s.", error->message); emit_error_helper (self, error); @@ -1067,19 +1228,30 @@ set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) nm_log_info (LOGD_SUPPLICANT, "Config: set interface ap_scan to %d", nm_supplicant_config_get_ap_scan (priv->cfg)); - 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); + if (priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) { + const char *mac_randomization = nm_supplicant_config_get_mac_randomization (priv->cfg); + + /* 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 (mac_randomization)), + 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) + NMSupplicantConfig *cfg, + GError **error) { NMSupplicantInterfacePrivate *priv; @@ -1093,7 +1265,8 @@ nm_supplicant_interface_set_config (NMSupplicantInterface *self, * it an EAP-FAST configuration. */ if (nm_supplicant_config_fast_required (cfg) && !priv->fast_supported) { - nm_log_warn (LOGD_SUPPLICANT, "EAP-FAST is not supported by the supplicant"); + g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG, + "EAP-FAST is not supported by the supplicant"); return FALSE; } @@ -1101,7 +1274,7 @@ nm_supplicant_interface_set_config (NMSupplicantInterface *self, if (cfg) { priv->cfg = g_object_ref (cfg); g_dbus_proxy_call (priv->iface_proxy, - "org.freedesktop.DBus.Properties.Set", + DBUS_INTERFACE_PROPERTIES ".Set", g_variant_new ("(ssv)", WPAS_DBUS_IFACE_INTERFACE, "ApScan", @@ -1258,7 +1431,7 @@ NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname, gboolean is_wireless, gboolean fast_supported, - ApSupport ap_support, + NMSupplicantFeature ap_support, gboolean start_now) { NMSupplicantInterface *self; @@ -1295,11 +1468,7 @@ set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } static void @@ -1308,9 +1477,14 @@ get_property (GObject *object, GValue *value, GParamSpec *pspec) { + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); + switch (prop_id) { case PROP_SCANNING: - g_value_set_boolean (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->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); @@ -1341,6 +1515,7 @@ dispose (GObject *object) 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); @@ -1367,6 +1542,13 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_CURRENT_BSS, + g_param_spec_string (NM_SUPPLICANT_INTERFACE_CURRENT_BSS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /* Signals */ signals[STATE] = g_signal_new (NM_SUPPLICANT_INTERFACE_STATE, @@ -1398,7 +1580,7 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMSupplicantInterfaceClass, bss_updated), NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER); + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT); signals[BSS_REMOVED] = g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_REMOVED, |