summaryrefslogtreecommitdiff
path: root/src/devices/wifi/nm-iwd-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/wifi/nm-iwd-manager.c')
-rw-r--r--src/devices/wifi/nm-iwd-manager.c90
1 files changed, 77 insertions, 13 deletions
diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c
index 1ba8587299..713b431be2 100644
--- a/src/devices/wifi/nm-iwd-manager.c
+++ b/src/devices/wifi/nm-iwd-manager.c
@@ -48,6 +48,7 @@ typedef struct {
typedef struct {
NMManager *manager;
+ NMSettings *settings;
GCancellable *cancellable;
gboolean running;
GDBusObjectManager *object_manager;
@@ -363,17 +364,18 @@ 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.
+/* Look up an existing NMSettingsConnection for a WPA2-Enterprise network
+ * that has been preprovisioned with an IWD config file, or create a new
+ * in-memory connection object so that NM autoconnect mechanism and the
+ * clients know this networks needs no additional EAP configuration from
+ * the user.
*/
static NMSettingsConnection *
mirror_8021x_connection (NMIwdManager *self,
- const char *name)
+ const char *name,
+ gboolean create_new)
{
- NMSettings *settings = NM_SETTINGS_GET;
+ NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
NMSettingsConnection *const*iter;
gs_unref_object NMConnection *connection = NULL;
NMSettingsConnection *settings_connection = NULL;
@@ -382,7 +384,7 @@ mirror_8021x_connection (NMIwdManager *self,
GError *error = NULL;
gs_unref_bytes GBytes *new_ssid = NULL;
- for (iter = nm_settings_get_connections (settings, NULL); *iter; iter++) {
+ for (iter = nm_settings_get_connections (priv->settings, NULL); *iter; iter++) {
NMSettingsConnection *sett_conn = *iter;
NMConnection *conn = nm_settings_connection_get_connection (sett_conn);
NMIwdNetworkSecurity security;
@@ -418,11 +420,12 @@ mirror_8021x_connection (NMIwdManager *self,
settings_connection = sett_conn;
}
- /* We already have an NMSettingsConnection matching this
+ /* If 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.
+ * potentially created by ourselves then we have nothing left to
+ * do here.
*/
- if (settings_connection)
+ if (settings_connection || !create_new)
return settings_connection;
connection = nm_simple_connection_new ();
@@ -464,7 +467,7 @@ mirror_8021x_connection (NMIwdManager *self,
if (!nm_connection_normalize (connection, NULL, NULL, NULL))
return NULL;
- settings_connection = nm_settings_add_connection (settings, connection,
+ settings_connection = nm_settings_add_connection (priv->settings, connection,
FALSE, &error);
if (!settings_connection) {
_LOGW ("failed to add a mirror NMConnection for IWD's Known Network '%s': %s",
@@ -556,7 +559,7 @@ interface_added (GDBusObjectManager *object_manager, GDBusObject *object,
}
if (security == NM_IWD_NETWORK_SECURITY_8021X) {
- sett_conn = mirror_8021x_connection (self, name);
+ sett_conn = mirror_8021x_connection (self, name, TRUE);
if ( sett_conn
&& sett_conn != data->mirror_connection) {
@@ -614,6 +617,55 @@ interface_removed (GDBusObjectManager *object_manager, GDBusObject *object,
}
}
+static void
+connection_removed (NMSettings *settings,
+ NMSettingsConnection *sett_conn,
+ gpointer user_data)
+{
+ NMIwdManager *self = user_data;
+ NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
+ NMConnection *conn = nm_settings_connection_get_connection (sett_conn);
+ NMSettingWireless *s_wireless;
+ gboolean mapped;
+ KnownNetworkData *data;
+ KnownNetworkId id;
+
+ id.security = nm_wifi_connection_get_iwd_security (conn, &mapped);
+ if (!mapped)
+ return;
+
+ s_wireless = nm_connection_get_setting_wireless (conn);
+ id.name = _nm_utils_ssid_to_utf8 (nm_setting_wireless_get_ssid (s_wireless));
+ data = g_hash_table_lookup (priv->known_networks, &id);
+ g_free ((char *) id.name);
+ if (!data)
+ return;
+
+ if (id.security == NM_IWD_NETWORK_SECURITY_8021X) {
+ NMSettingsConnection *new_mirror_conn;
+
+ if (data->mirror_connection != sett_conn)
+ return;
+
+ g_clear_object (&data->mirror_connection);
+
+ /* Don't call Forget for an 8021x network until there's no
+ * longer *any* matching NMSettingsConnection (debatable)
+ */
+ new_mirror_conn = mirror_8021x_connection (self, id.name, FALSE);
+ if (new_mirror_conn) {
+ data->mirror_connection = g_object_ref (new_mirror_conn);
+ return;
+ }
+ }
+
+ if (!priv->running)
+ return;
+
+ g_dbus_proxy_call (data->known_network, "Forget",
+ NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+}
+
static gboolean
_om_has_name_owner (GDBusObjectManager *object_manager)
{
@@ -845,6 +897,10 @@ nm_iwd_manager_init (NMIwdManager *self)
g_signal_connect (priv->manager, NM_MANAGER_DEVICE_ADDED,
G_CALLBACK (device_added), self);
+ priv->settings = g_object_ref (nm_settings_get ());
+ g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
+ G_CALLBACK (connection_removed), self);
+
priv->cancellable = g_cancellable_new ();
priv->known_networks = g_hash_table_new_full ((GHashFunc) known_network_id_hash,
@@ -865,6 +921,14 @@ dispose (GObject *object)
nm_clear_g_cancellable (&priv->cancellable);
+ if (priv->settings) {
+ g_signal_handlers_disconnect_by_data (priv->settings, self);
+ g_clear_object (&priv->settings);
+ }
+
+ /* This may trigger mirror connection removals so it happens
+ * after the g_signal_handlers_disconnect_by_data above.
+ */
nm_clear_pointer (&priv->known_networks, g_hash_table_destroy);
if (priv->manager) {