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