diff options
Diffstat (limited to 'src/devices/wifi/nm-iwd-manager.c')
| -rw-r--r-- | src/devices/wifi/nm-iwd-manager.c | 540 |
1 files changed, 197 insertions, 343 deletions
diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index 1f28d263..d6511296 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -29,21 +29,13 @@ #include "nm-core-internal.h" #include "nm-manager.h" #include "nm-device-iwd.h" -#include "nm-wifi-utils.h" #include "nm-utils/nm-random-utils.h" -#include "settings/nm-settings.h" /*****************************************************************************/ typedef struct { - const char *name; + gchar *name; NMIwdNetworkSecurity security; - char buf[0]; -} KnownNetworkId; - -typedef struct { - GDBusProxy *known_network; - NMSettingsConnection *mirror_connection; } KnownNetworkData; typedef struct { @@ -52,8 +44,8 @@ typedef struct { gboolean running; GDBusObjectManager *object_manager; guint agent_id; - char *agent_path; - GHashTable *known_networks; + gchar *agent_path; + GSList *known_networks; } NMIwdManagerPrivate; struct _NMIwdManager { @@ -91,49 +83,20 @@ G_DEFINE_TYPE (NMIwdManager, nm_iwd_manager, G_TYPE_OBJECT) /*****************************************************************************/ -static void mirror_8021x_connection_take_and_delete (NMSettingsConnection *sett_conn); - -/*****************************************************************************/ - -static const char * -get_variant_string_or_null (GVariant *v) -{ - if (!v) - return NULL; - - if ( !g_variant_is_of_type (v, G_VARIANT_TYPE_STRING) - && !g_variant_is_of_type (v, G_VARIANT_TYPE_OBJECT_PATH)) - return NULL; - - return g_variant_get_string (v, NULL); -} - -static const char * -get_property_string_or_null (GDBusProxy *proxy, const char *property) -{ - gs_unref_variant GVariant *value = NULL; - - if (!proxy || !property) - return NULL; - - value = g_dbus_proxy_get_cached_property (proxy, property); - - return get_variant_string_or_null (value); -} - static void agent_dbus_method_cb (GDBusConnection *connection, - const char *sender, const char *object_path, - const char *interface_name, const char *method_name, + const gchar *sender, const gchar *object_path, + const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { NMIwdManager *self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - const char *network_path, *device_path, *ifname; + const gchar *network_path, *device_path, *ifname; gs_unref_object GDBusInterface *network = NULL, *device_obj = NULL; - int ifindex; + gs_unref_variant GVariant *value = NULL; + gint ifindex; NMDevice *device; gs_free char *name_owner = NULL; @@ -150,8 +113,9 @@ agent_dbus_method_cb (GDBusConnection *connection, network = g_dbus_object_manager_get_interface (priv->object_manager, network_path, NM_IWD_NETWORK_INTERFACE); + value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (network), "Device"); + device_path = g_variant_get_string (value, NULL); - device_path = get_property_string_or_null (G_DBUS_PROXY (network), "Device"); if (!device_path) { _LOGD ("agent-request: device not cached for network %s in IWD Agent request", network_path); @@ -161,8 +125,10 @@ agent_dbus_method_cb (GDBusConnection *connection, device_obj = g_dbus_object_manager_get_interface (priv->object_manager, device_path, NM_IWD_DEVICE_INTERFACE); + g_variant_unref (value); + value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (device_obj), "Name"); + ifname = g_variant_get_string (value, NULL); - ifname = get_property_string_or_null (G_DBUS_PROXY (device_obj), "Name"); if (!ifname) { _LOGD ("agent-request: name not cached for device %s in IWD Agent request", device_path); @@ -241,12 +207,12 @@ static const GDBusInterfaceInfo iwd_agent_iface_info = NM_DEFINE_GDBUS_INTERFACE static guint iwd_agent_export (GDBusConnection *connection, gpointer user_data, - char **agent_path, GError **error) + gchar **agent_path, GError **error) { static const GDBusInterfaceVTable vtable = { .method_call = agent_dbus_method_cb, }; - char path[50]; + gchar path[50]; unsigned int rnd; guint id; @@ -285,68 +251,38 @@ register_agent (NMIwdManager *self) /*****************************************************************************/ -static KnownNetworkId * -known_network_id_new (const char *name, NMIwdNetworkSecurity security) -{ - KnownNetworkId *id; - gsize 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) -{ - NMHashState h; - - nm_hash_init (&h, 1947951703u); - nm_hash_update_val (&h, id->security); - nm_hash_update_str (&h, id->name); - return nm_hash_complete (&h); -} - -static gboolean -known_network_id_equal (KnownNetworkId *a, KnownNetworkId *b) -{ - return a->security == b->security - && nm_streq (a->name, b->name); -} - -static void -known_network_data_free (KnownNetworkData *network) -{ - if (!network) - return; - - g_object_unref (network->known_network); - mirror_8021x_connection_take_and_delete (network->mirror_connection); - g_slice_free (KnownNetworkData, network); -} - -/*****************************************************************************/ - static void -set_device_dbus_object (NMIwdManager *self, GDBusProxy *proxy, +set_device_dbus_object (NMIwdManager *self, GDBusInterface *interface, GDBusObject *object) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + GDBusProxy *proxy; + GVariant *value; const char *ifname; - int ifindex; + gint ifindex; NMDevice *device; - ifname = get_property_string_or_null (proxy, "Name"); - if (!ifname) { + 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; + + value = g_dbus_proxy_get_cached_property (proxy, "Name"); + if (!value) { _LOGE ("Name not cached for Device at %s", g_dbus_proxy_get_object_path (proxy)); return; } + ifname = g_variant_get_string (value, NULL); ifindex = if_nametoindex (ifname); + g_variant_unref (value); if (!ifindex) { _LOGE ("if_nametoindex failed for Name %s for Device at %s: %i", @@ -363,183 +299,13 @@ set_device_dbus_object (NMIwdManager *self, GDBusProxy *proxy, nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), object); } -/* Create an in-memory NMConnection for a WPA2-Enterprise network that - * has been preprovisioned with an IWD config file so that NM autoconnect - * mechanism and the clients know this networks needs no additional EAP - * configuration from the user. Only do this if no existing connection - * SSID and security type match that network yet. - */ -static NMSettingsConnection * -mirror_8021x_connection (NMIwdManager *self, - const char *name) -{ - NMSettings *settings = NM_SETTINGS_GET; - NMSettingsConnection *const*iter; - gs_unref_object NMConnection *connection = NULL; - NMSettingsConnection *settings_connection; - char uuid[37]; - NMSetting *setting; - GError *error = NULL; - gs_unref_bytes GBytes *new_ssid = NULL; - - for (iter = nm_settings_get_connections (settings, NULL); *iter; iter++) { - NMSettingsConnection *sett_conn = *iter; - NMConnection *conn = nm_settings_connection_get_connection (sett_conn); - NMIwdNetworkSecurity security; - gs_free char *ssid_name = NULL; - NMSettingWireless *s_wifi; - - security = nm_wifi_connection_get_iwd_security (conn, NULL); - if (security != NM_IWD_NETWORK_SECURITY_8021X) - continue; - - s_wifi = nm_connection_get_setting_wireless (conn); - if (!s_wifi) - continue; - - ssid_name = _nm_utils_ssid_to_utf8 (nm_setting_wireless_get_ssid (s_wifi)); - - /* We already have an NMSettingsConnection matching this - * KnownNetwork, whether it's saved or an in-memory connection - * potentially created by ourselves. Nothing to do here. - */ - if (nm_streq (ssid_name, name)) - return NULL; - } - - connection = nm_simple_connection_new (); - - setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_CONNECTION, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_CONNECTION_ID, name, - NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid), - NM_SETTING_CONNECTION_READ_ONLY, TRUE, - NULL)); - nm_connection_add_setting (connection, setting); - - new_ssid = g_bytes_new (name, strlen (name)); - setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS, - NM_SETTING_WIRELESS_SSID, new_ssid, - NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, - NULL)); - nm_connection_add_setting (connection, setting); - - setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS_SECURITY, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", - NULL)); - nm_connection_add_setting (connection, setting); - - setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_802_1X, NULL)); - nm_setting_802_1x_add_eap_method (NM_SETTING_802_1X (setting), "external"); - nm_connection_add_setting (connection, setting); - - if (!nm_connection_normalize (connection, NULL, NULL, NULL)) - return NULL; - - settings_connection = nm_settings_add_connection (settings, connection, - FALSE, &error); - if (!settings_connection) { - _LOGW ("failed to add a mirror NMConnection for IWD's Known Network '%s': %s", - name, error->message); - g_error_free (error); - return NULL; - } - - nm_settings_connection_set_flags (settings_connection, - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED | - NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED, - TRUE); - return settings_connection; -} - -static void -mirror_8021x_connection_take_and_delete (NMSettingsConnection *sett_conn) -{ - NMSettingsConnectionIntFlags flags; - - if (!sett_conn) - return; - - flags = nm_settings_connection_get_flags (sett_conn); - - /* If connection has not been saved since we created it - * in interface_added it too can be removed now. */ - if (NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) - nm_settings_connection_delete (sett_conn, NULL); - - g_object_unref (sett_conn); -} - static void 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; - - 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; - NMSettingsConnection *sett_conn = NULL; - - 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_hash_table_lookup (priv->known_networks, id); - if (data) - g_free (id); - else { - data = g_slice_new0 (KnownNetworkData); - data->known_network = g_object_ref (proxy); - g_hash_table_insert (priv->known_networks, id, data); - } - - if (security == NM_IWD_NETWORK_SECURITY_8021X) { - sett_conn = mirror_8021x_connection (self, name); - - if ( sett_conn - && sett_conn != data->mirror_connection) { - NMSettingsConnection *sett_conn_old = data->mirror_connection; - - data->mirror_connection = nm_g_object_ref (sett_conn); - mirror_8021x_connection_take_and_delete (sett_conn_old); - } - } else - mirror_8021x_connection_take_and_delete (g_steal_pointer (&data->mirror_connection)); - - return; - } + set_device_dbus_object (self, interface, object); } static void @@ -547,41 +313,15 @@ 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; - 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, 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; + /* + * 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_hash_table_remove (priv->known_networks, &id); - return; - } + set_device_dbus_object (self, interface, NULL); } static gboolean @@ -601,42 +341,106 @@ 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); - interface_added (NULL, object, interface, self); + set_device_dbus_object (self, interface, object); } g_list_free_full (interfaces, g_object_unref); } static void -release_object_manager (NMIwdManager *self) +known_network_free (KnownNetworkData *network) { - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + g_free (network->name); + g_free (network); +} - if (!priv->object_manager) +static void +list_known_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMIwdManager *self = user_data; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *variant = NULL; + GVariantIter *networks, *props; + + variant = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, + G_VARIANT_TYPE ("(aa{sv})"), + &error); + if (!variant) { + _LOGE ("ListKnownNetworks() failed: %s", error->message); return; + } - g_signal_handlers_disconnect_by_data (priv->object_manager, self); + g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free); + priv->known_networks = NULL; - if (priv->agent_id) { - GDBusConnection *agent_connection; - GDBusObjectManagerClient *omc = G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager); + g_variant_get (variant, "(aa{sv})", &networks); - agent_connection = g_dbus_object_manager_client_get_connection (omc); + while (g_variant_iter_next (networks, "a{sv}", &props)) { + const gchar *key; + const gchar *name = NULL; + const gchar *type = NULL; + GVariant *val; + KnownNetworkData *network_data; - /* We're is called when we're shutting down (i.e. our DBus connection - * is being closed, and IWD will detect this) or IWD was stopped so - * in either case calling UnregisterAgent will not do anything. - */ - g_dbus_connection_unregister_object (agent_connection, priv->agent_id); - priv->agent_id = 0; - nm_clear_g_free (&priv->agent_path); + while (g_variant_iter_next (props, "{&sv}", &key, &val)) { + if (!strcmp (key, "Name")) + name = g_variant_get_string (val, NULL); + + if (!strcmp (key, "Type")) + type = g_variant_get_string (val, NULL); + + g_variant_unref (val); + } + + if (!name || !type) + goto next; + + network_data = g_new (KnownNetworkData, 1); + network_data->name = g_strdup (name); + if (!strcmp (type, "open")) + network_data->security = NM_IWD_NETWORK_SECURITY_NONE; + else if (!strcmp (type, "psk")) + network_data->security = NM_IWD_NETWORK_SECURITY_PSK; + else if (!strcmp (type, "8021x")) + network_data->security = NM_IWD_NETWORK_SECURITY_8021X; + + priv->known_networks = g_slist_append (priv->known_networks, + network_data); + +next: + g_variant_iter_free (props); } - g_clear_object (&priv->object_manager); + g_variant_iter_free (networks); + + /* For completness we may want to call nm_device_emit_recheck_auto_activate + * and nm_device_recheck_available_connections for all affected devices + * now but the ListKnownNetworks call should have been really fast, + * faster than any scan on any newly created devices could have happened. + */ +} + +static void +update_known_networks (NMIwdManager *self) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + GDBusInterface *known_networks_if; + + known_networks_if = g_dbus_object_manager_get_interface (priv->object_manager, + "/", + NM_IWD_KNOWN_NETWORKS_INTERFACE); + + g_dbus_proxy_call (G_DBUS_PROXY (known_networks_if), + "ListKnownNetworks", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, -1, + priv->cancellable, list_known_networks_cb, self); + + g_object_unref (known_networks_if); } static void prepare_object_manager (NMIwdManager *self); @@ -651,7 +455,8 @@ name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data) nm_assert (object_manager == priv->object_manager); if (_om_has_name_owner (object_manager)) { - release_object_manager (self); + g_signal_handlers_disconnect_by_data (object_manager, self); + g_clear_object (&priv->object_manager); prepare_object_manager (self); } else { const CList *tmp_lst; @@ -687,14 +492,28 @@ device_added (NMManager *manager, NMDevice *device, gpointer user_data) objects = g_dbus_object_manager_get_objects (priv->object_manager); for (iter = objects; iter; iter = iter->next) { GDBusObject *object = G_DBUS_OBJECT (iter->data); - gs_unref_object GDBusInterface *interface = NULL; + GDBusInterface *interface; + GDBusProxy *proxy; + GVariant *value; const char *obj_ifname; interface = g_dbus_object_get_interface (object, NM_IWD_DEVICE_INTERFACE); - obj_ifname = get_property_string_or_null ((GDBusProxy *) interface, "Name"); + if (!interface) + continue; + + proxy = G_DBUS_PROXY (interface); + value = g_dbus_proxy_get_cached_property (proxy, "Name"); + if (!value) { + g_object_unref (interface); + continue; + } - if (!obj_ifname || strcmp (nm_device_get_iface (device), obj_ifname)) + obj_ifname = g_variant_get_string (value, NULL); + g_variant_unref (value); + g_object_unref (interface); + + if (strcmp (nm_device_get_iface (device), obj_ifname)) continue; nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), object); @@ -716,7 +535,7 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data) object_manager = g_dbus_object_manager_client_new_for_bus_finish (result, &error); if (object_manager == NULL) { _LOGE ("failed to acquire IWD Object Manager: Wi-Fi will not be available (%s)", - error->message); + NM_G_ERROR_MSG (error)); g_clear_error (&error); return; } @@ -730,13 +549,11 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data) connection = g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); - priv->agent_id = iwd_agent_export (connection, - self, - &priv->agent_path, - &error); + priv->agent_id = iwd_agent_export (connection, self, + &priv->agent_path, &error); if (!priv->agent_id) { - _LOGE ("failed to export the IWD Agent: PSK/8021x WiFi networks may not work: %s", - error->message); + _LOGE ("failed to export the IWD Agent: PSK/8021x WiFi networks will not work: %s", + NM_G_ERROR_MSG (error)); g_clear_error (&error); } @@ -750,8 +567,6 @@ 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)); @@ -760,6 +575,8 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data) if (priv->agent_id) register_agent (self); + + update_known_networks (self); } } @@ -777,13 +594,36 @@ prepare_object_manager (NMIwdManager *self) } gboolean -nm_iwd_manager_is_known_network (NMIwdManager *self, const char *name, +nm_iwd_manager_is_known_network (NMIwdManager *self, const gchar *name, NMIwdNetworkSecurity security) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - KnownNetworkId kn_id = { name, security }; + const GSList *iter; + + for (iter = priv->known_networks; iter; iter = g_slist_next (iter)) { + const KnownNetworkData *network = iter->data; + + if (!strcmp (network->name, name) && network->security == security) + return true; + } - return g_hash_table_contains (priv->known_networks, &kn_id); + return false; +} + +void +nm_iwd_manager_network_connected (NMIwdManager *self, const gchar *name, + NMIwdNetworkSecurity security) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); + KnownNetworkData *network_data; + + if (nm_iwd_manager_is_known_network (self, name, security)) + return; + + network_data = g_new (KnownNetworkData, 1); + network_data->name = g_strdup (name); + network_data->security = security; + priv->known_networks = g_slist_append (priv->known_networks, network_data); } /*****************************************************************************/ @@ -802,11 +642,6 @@ nm_iwd_manager_init (NMIwdManager *self) priv->cancellable = g_cancellable_new (); - priv->known_networks = g_hash_table_new_full ((GHashFunc) known_network_id_hash, - (GEqualFunc) known_network_id_equal, - g_free, - (GDestroyNotify) known_network_data_free); - prepare_object_manager (self); } @@ -816,11 +651,30 @@ dispose (GObject *object) NMIwdManager *self = (NMIwdManager *) object; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self); - release_object_manager (self); + if (priv->object_manager) { + if (priv->agent_id) { + GDBusConnection *connection; + GDBusObjectManagerClient *omc = G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager); + + /* No need to unregister the agent as IWD will detect + * our DBus connection being closed. + */ + + connection = g_dbus_object_manager_client_get_connection (omc); + + g_dbus_connection_unregister_object (connection, priv->agent_id); + priv->agent_id = 0; + } + + g_clear_object (&priv->object_manager); + } + + nm_clear_g_free (&priv->agent_path); nm_clear_g_cancellable (&priv->cancellable); - nm_clear_pointer (&priv->known_networks, g_hash_table_destroy); + g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free); + priv->known_networks = NULL; if (priv->manager) { g_signal_handlers_disconnect_by_data (priv->manager, self); |