diff options
Diffstat (limited to 'src/supplicant-manager/nm-supplicant-manager.c')
-rw-r--r-- | src/supplicant-manager/nm-supplicant-manager.c | 263 |
1 files changed, 115 insertions, 148 deletions
diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index 01e35929d..6358c1809 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)); } |