diff options
-rw-r--r-- | src/core/devices/nm-device.c | 2 | ||||
-rw-r--r-- | src/core/devices/nm-device.h | 1 | ||||
-rw-r--r-- | src/core/nm-manager.c | 139 | ||||
-rw-r--r-- | src/core/nm-manager.h | 5 | ||||
-rw-r--r-- | src/core/settings/nm-settings-connection.c | 2 | ||||
-rw-r--r-- | src/core/settings/nm-settings-connection.h | 1 | ||||
-rw-r--r-- | src/core/settings/nm-settings.c | 2 |
7 files changed, 152 insertions, 0 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 6f8b416440..c0cdd733d9 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -17729,6 +17729,7 @@ nm_device_init(NMDevice *self) c_list_init(&priv->concheck_lst_head); c_list_init(&self->devices_lst); + c_list_init(&self->devcon_dev_lst_head); c_list_init(&priv->slaves); priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE; @@ -17849,6 +17850,7 @@ dispose(GObject *object) _LOGD(LOGD_DEVICE, "disposing"); nm_assert(c_list_is_empty(&self->devices_lst)); + nm_assert(c_list_is_empty(&self->devcon_dev_lst_head)); while ((con_handle = c_list_first_entry(&priv->concheck_lst_head, NMDeviceConnectivityHandle, diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index d6d559e6a0..435a6f82aa 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -144,6 +144,7 @@ struct _NMDevice { NMDBusObject parent; struct _NMDevicePrivate *_priv; CList devices_lst; + CList devcon_dev_lst_head; }; /* The flags have an relaxing meaning, that means, specifying more flags, can make diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 9d444e45f3..07a11150fa 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -69,6 +69,13 @@ typedef struct { bool os_owner : 1; } RfkillRadioState; +typedef struct { + NMDevice *device; + NMSettingsConnection *sett_conn; + CList dev_lst; + CList con_lst; +} DevConData; + typedef enum { ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL, ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER, @@ -173,6 +180,8 @@ typedef struct { } prop_filter; NMRfkillManager *rfkill_mgr; + GHashTable *devcon_data_dict; + CList link_cb_lst; NMCheckpointManager *checkpoint_mgr; @@ -415,6 +424,11 @@ static void _activation_auth_done(NMManager *self, static void _rfkill_update(NMManager *self, NMRfkillType rtype); +static DevConData *_devcon_lookup_data(NMManager *self, + NMDevice *device, + NMSettingsConnection *sett_conn, + gboolean create); + /*****************************************************************************/ static NM_CACHED_QUARK_FCN("autoconnect-root", autoconnect_root_quark); @@ -1212,6 +1226,125 @@ active_connection_get_by_path(NMManager *self, const char *path) /*****************************************************************************/ +static guint +_devcon_data_hash(gconstpointer ptr) +{ + const DevConData *data = ptr; + + nm_assert(NM_IS_DEVICE(data->device)); + nm_assert(NM_IS_SETTINGS_CONNECTION(data->sett_conn)); + + return nm_hash_vals(1832112199u, data->device, data->sett_conn); +} + +static gboolean +_devcon_data_equal(gconstpointer ptr_a, gconstpointer ptr_b) +{ + const DevConData *data_a = ptr_a; + const DevConData *data_b = ptr_b; + + nm_assert(NM_IS_DEVICE(data_a->device)); + nm_assert(NM_IS_SETTINGS_CONNECTION(data_a->sett_conn)); + nm_assert(NM_IS_DEVICE(data_b->device)); + nm_assert(NM_IS_SETTINGS_CONNECTION(data_b->sett_conn)); + + return data_a->device == data_b->device && data_a->sett_conn == data_b->sett_conn; +} + +static DevConData * +_devcon_lookup_data(NMManager *self, + NMDevice *device, + NMSettingsConnection *sett_conn, + gboolean create) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + DevConData *data; + DevConData needle; + + nm_assert(NM_IS_DEVICE(device)); + nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn)); + nm_assert(self == nm_device_get_manager(device)); + nm_assert(self == nm_settings_connection_get_manager(sett_conn)); + + needle.device = device; + needle.sett_conn = sett_conn; + + data = g_hash_table_lookup(priv->devcon_data_dict, &needle); + + if (data) + return data; + if (!create) + return NULL; + + data = g_slice_new(DevConData); + *data = (DevConData){ + .device = device, + .sett_conn = sett_conn, + }; + c_list_link_tail(&device->devcon_dev_lst_head, &data->dev_lst); + c_list_link_tail(&sett_conn->devcon_con_lst_head, &data->con_lst); + + g_hash_table_add(priv->devcon_data_dict, data); + + return data; +} + +static void +_devcon_remove_data(NMManager *self, DevConData *data) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + + nm_assert(data); + nm_assert(NM_IS_DEVICE(data->device)); + nm_assert(NM_IS_SETTINGS_CONNECTION(data->sett_conn)); + nm_assert(data == _devcon_lookup_data(self, data->device, data->sett_conn, FALSE)); + + c_list_unlink_stale(&data->dev_lst); + c_list_unlink_stale(&data->con_lst); + g_hash_table_remove(priv->devcon_data_dict, data); + nm_g_slice_free(data); +} + +static gboolean +_devcon_remove_device_all(NMManager *self, NMDevice *device) +{ + DevConData *data; + gboolean changed; + + nm_assert(NM_IS_DEVICE(device)); + + while ((data = c_list_first_entry(&device->devcon_dev_lst_head, DevConData, dev_lst))) { + changed = TRUE; + _devcon_remove_data(self, data); + } + + return changed; +} + +static gboolean +_devcon_remove_sett_conn_all(NMManager *self, NMSettingsConnection *sett_conn) +{ + DevConData *data; + gboolean changed; + + nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn)); + + while ((data = c_list_first_entry(&sett_conn->devcon_con_lst_head, DevConData, con_lst))) { + changed = TRUE; + _devcon_remove_data(self, data); + } + + return changed; +} + +void +nm_manager_notify_delete_settings_connections(NMManager *self, NMSettingsConnection *sett_conn) +{ + _devcon_remove_sett_conn_all(self, sett_conn); +} + +/*****************************************************************************/ + static void _config_changed_cb(NMConfig *config, NMConfigData *config_data, @@ -1814,6 +1947,8 @@ remove_device(NMManager *self, NMDevice *device, gboolean quitting) nm_settings_device_removed(priv->settings, device, quitting); + _devcon_remove_device_all(self, device); + c_list_unlink(&device->devices_lst); _parent_notify_changed(self, device, TRUE); @@ -8114,6 +8249,8 @@ nm_manager_init(NMManager *self) priv->state = NM_STATE_DISCONNECTED; priv->startup = TRUE; + priv->devcon_data_dict = g_hash_table_new(_devcon_data_hash, _devcon_data_equal); + /* sleep/wake handling */ priv->sleep_monitor = nm_sleep_monitor_new(); g_signal_connect(priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, G_CALLBACK(sleeping_cb), self); @@ -8447,6 +8584,8 @@ dispose(GObject *object) nm_clear_pointer(&priv->device_route_metrics, g_hash_table_destroy); + nm_clear_pointer(&priv->devcon_data_dict, g_hash_table_destroy); + G_OBJECT_CLASS(nm_manager_parent_class)->dispose(object); } diff --git a/src/core/nm-manager.h b/src/core/nm-manager.h index 0cbbcbf0ae..851b9b5388 100644 --- a/src/core/nm-manager.h +++ b/src/core/nm-manager.h @@ -207,6 +207,11 @@ struct _NMDnsManager *nm_manager_get_dns_manager(NMManager *self); /*****************************************************************************/ +void nm_manager_notify_delete_settings_connections(NMManager *self, + NMSettingsConnection *sett_conn); + +/*****************************************************************************/ + void nm_manager_device_auth_request(NMManager *self, NMDevice *device, GDBusMethodInvocation *context, diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c index 87a20bca1c..a77628ca6d 100644 --- a/src/core/settings/nm-settings-connection.c +++ b/src/core/settings/nm-settings-connection.c @@ -2756,6 +2756,7 @@ nm_settings_connection_init(NMSettingsConnection *self) self->_priv = priv; c_list_init(&self->_connections_lst); + c_list_init(&self->devcon_con_lst_head); c_list_init(&priv->seen_bssids_lst_head); c_list_init(&priv->call_ids_lst_head); c_list_init(&priv->auth_lst_head); @@ -2784,6 +2785,7 @@ dispose(GObject *object) nm_assert(!priv->default_wired_device); nm_assert(c_list_is_empty(&self->_connections_lst)); + nm_assert(c_list_is_empty(&self->devcon_con_lst_head)); nm_assert(c_list_is_empty(&priv->auth_lst_head)); /* Cancel in-progress secrets requests */ diff --git a/src/core/settings/nm-settings-connection.h b/src/core/settings/nm-settings-connection.h index 33a999ee8a..f8007a9a12 100644 --- a/src/core/settings/nm-settings-connection.h +++ b/src/core/settings/nm-settings-connection.h @@ -210,6 +210,7 @@ struct _NMSettingsConnectionPrivate; struct _NMSettingsConnection { NMDBusObject parent; CList _connections_lst; + CList devcon_con_lst_head; struct _NMSettingsConnectionPrivate *_priv; }; diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c index 27adba4db2..36a3d7b764 100644 --- a/src/core/settings/nm-settings.c +++ b/src/core/settings/nm-settings.c @@ -1247,6 +1247,8 @@ _connection_changed_delete(NMSettings *self, | NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, FALSE); + nm_manager_notify_delete_settings_connections(priv->manager, sett_conn); + _emit_connection_removed(self, sett_conn); _nm_settings_connection_cleanup_after_remove(sett_conn); |