summary refs log tree commit diff
path: root/src/supplicant-manager/nm-supplicant-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/supplicant-manager/nm-supplicant-manager.c')
-rw-r--r--src/supplicant-manager/nm-supplicant-manager.c263
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 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));
 }