summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/devices/nm-device.c2
-rw-r--r--src/core/devices/nm-device.h1
-rw-r--r--src/core/nm-manager.c139
-rw-r--r--src/core/nm-manager.h5
-rw-r--r--src/core/settings/nm-settings-connection.c2
-rw-r--r--src/core/settings/nm-settings-connection.h1
-rw-r--r--src/core/settings/nm-settings.c2
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);