From 142d83b01973b843ea2eba38d0c19eee2c8dfbb6 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Mon, 13 Aug 2018 19:25:37 +0200 Subject: [PATCH] wifi/iwd: Track known networks using interface-added/-removed signals The known networks hash table is indexed by the (ssid, security) tuple for fast lookups both on DBus signals related to an IWD known network and local NMConnection signals such as on removal. --- src/devices/wifi/nm-iwd-manager.c | 117 ++++++++++++++++++++++++------ src/devices/wifi/nm-iwd-manager.h | 2 +- 2 files changed, 96 insertions(+), 23 deletions(-) diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index 512d9a0368..d9d539114e 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -278,6 +278,20 @@ register_agent (NMIwdManager *self) /*****************************************************************************/ +static KnownNetworkId * +known_network_id_new (const char *name, NMIwdNetworkSecurity security) +{ + KnownNetworkId *id; + size_t strsize = strlen (name) + 1; + + id = g_malloc (sizeof (KnownNetworkId) + strsize); + id->name = id->buf; + id->security = security; + memcpy (id->buf, name, strsize); + + return id; +} + static guint known_network_id_hash (KnownNetworkId *id) { @@ -303,26 +317,14 @@ known_network_data_free (KnownNetworkData *network) /*****************************************************************************/ static void -set_device_dbus_object (NMIwdManager *self, GDBusInterface *interface, +set_device_dbus_object (NMIwdManager *self, GDBusProxy *proxy, GDBusObject *object) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - GDBusProxy *proxy; const char *ifname; int ifindex; NMDevice *device; - if (!priv->running) - return; - - g_return_if_fail (G_IS_DBUS_PROXY (interface)); - - proxy = G_DBUS_PROXY (interface); - - if (strcmp (g_dbus_proxy_get_interface_name (proxy), - NM_IWD_DEVICE_INTERFACE)) - return; - ifname = get_property_string_or_null (proxy, "Name"); if (!ifname) { _LOGE ("Name not cached for Device at %s", @@ -352,8 +354,50 @@ interface_added (GDBusObjectManager *object_manager, GDBusObject *object, GDBusInterface *interface, gpointer user_data) { NMIwdManager *self = user_data; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + GDBusProxy *proxy; + const char *iface_name; - set_device_dbus_object (self, interface, object); + if (!priv->running) + return; + + g_return_if_fail (G_IS_DBUS_PROXY (interface)); + + proxy = G_DBUS_PROXY (interface); + iface_name = g_dbus_proxy_get_interface_name (proxy); + + if (nm_streq (iface_name, NM_IWD_DEVICE_INTERFACE)) { + set_device_dbus_object (self, proxy, object); + return; + } + + if (nm_streq (iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) { + KnownNetworkId *id; + KnownNetworkData *data; + NMIwdNetworkSecurity security; + const char *type_str, *name; + + type_str = get_property_string_or_null (proxy, "Type"); + name = get_property_string_or_null (proxy, "Name"); + if (!type_str || !name) + return; + + if (nm_streq (type_str, "open")) + security = NM_IWD_NETWORK_SECURITY_NONE; + else if (nm_streq (type_str, "psk")) + security = NM_IWD_NETWORK_SECURITY_PSK; + else if (nm_streq (type_str, "8021x")) + security = NM_IWD_NETWORK_SECURITY_8021X; + else + return; + + id = known_network_id_new (name, security); + + data = g_slice_new (KnownNetworkData); + data->known_network = (GDBusProxy *) g_object_ref (proxy); + g_hash_table_insert (priv->known_networks, id, data); + return; + } } static void @@ -361,15 +405,41 @@ interface_removed (GDBusObjectManager *object_manager, GDBusObject *object, GDBusInterface *interface, gpointer user_data) { NMIwdManager *self = user_data; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + GDBusProxy *proxy; + const char *iface_name; - /* - * TODO: we may need to save the GDBusInterface or GDBusObject - * pointer in the hash table because we may be no longer able to - * access the Name property or map the name to ifindex with - * if_nametoindex at this point. - */ + g_return_if_fail (G_IS_DBUS_PROXY (interface)); - set_device_dbus_object (self, interface, NULL); + proxy = G_DBUS_PROXY (interface); + iface_name = g_dbus_proxy_get_interface_name (proxy); + + if (nm_streq (iface_name, NM_IWD_DEVICE_INTERFACE)) { + set_device_dbus_object (self, proxy, NULL); + return; + } + + if (nm_streq (iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) { + KnownNetworkId id; + const char *type_str; + + type_str = get_property_string_or_null (proxy, "Type"); + id.name = get_property_string_or_null (proxy, "Name"); + if (!type_str || !id.name) + return; + + if (nm_streq (type_str, "open")) + id.security = NM_IWD_NETWORK_SECURITY_NONE; + else if (nm_streq (type_str, "psk")) + id.security = NM_IWD_NETWORK_SECURITY_PSK; + else if (nm_streq (type_str, "8021x")) + id.security = NM_IWD_NETWORK_SECURITY_8021X; + else + return; + + g_hash_table_remove (priv->known_networks, &id); + return; + } } static gboolean @@ -389,10 +459,11 @@ object_added (NMIwdManager *self, GDBusObject *object) GList *interfaces, *iter; interfaces = g_dbus_object_get_interfaces (object); + for (iter = interfaces; iter; iter = iter->next) { GDBusInterface *interface = G_DBUS_INTERFACE (iter->data); - set_device_dbus_object (self, interface, object); + interface_added (NULL, object, interface, self); } g_list_free_full (interfaces, g_object_unref); @@ -508,6 +579,8 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data) g_signal_connect (priv->object_manager, "interface-removed", G_CALLBACK (interface_removed), self); + g_hash_table_remove_all (priv->known_networks); + objects = g_dbus_object_manager_get_objects (object_manager); for (iter = objects; iter; iter = iter->next) object_added (self, G_DBUS_OBJECT (iter->data)); diff --git a/src/devices/wifi/nm-iwd-manager.h b/src/devices/wifi/nm-iwd-manager.h index 1c867edb64..13622919c9 100644 --- a/src/devices/wifi/nm-iwd-manager.h +++ b/src/devices/wifi/nm-iwd-manager.h @@ -33,7 +33,7 @@ #define NM_IWD_AGENT_INTERFACE "net.connman.iwd.Agent" #define NM_IWD_WSC_INTERFACE \ "net.connman.iwd.WiFiSimpleConfiguration" -#define NM_IWD_KNOWN_NETWORKS_INTERFACE "net.connman.iwd.KnownNetworks" +#define NM_IWD_KNOWN_NETWORK_INTERFACE "net.connman.iwd.KnownNetwork" #define NM_IWD_SIGNAL_AGENT_INTERFACE "net.connman.iwd.SignalLevelAgent" typedef enum {