diff options
| author | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
| commit | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch) | |
| tree | 3469f17ea9af91f7ff169b890633bda68b0cf76e /src/core/settings/nm-settings.c | |
| parent | bfe522304da217296e2a61040f58e35ec5d6f3f2 (diff) | |
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'src/core/settings/nm-settings.c')
| -rw-r--r-- | src/core/settings/nm-settings.c | 250 |
1 files changed, 191 insertions, 59 deletions
diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c index 3d31fb8b..f9f98de7 100644 --- a/src/core/settings/nm-settings.c +++ b/src/core/settings/nm-settings.c @@ -20,9 +20,10 @@ #include <selinux/selinux.h> #endif -#include "nm-libnm-core-intern/nm-common-macros.h" -#include "nm-glib-aux/nm-keyfile-aux.h" -#include "nm-keyfile-internal.h" +#include "libnm-core-aux-intern/nm-common-macros.h" +#include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-keyfile-aux.h" +#include "libnm-core-intern/nm-keyfile-internal.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-setting-8021x.h" @@ -44,17 +45,17 @@ #include "nm-setting-proxy.h" #include "nm-setting-bond.h" #include "nm-utils.h" -#include "nm-core-internal.h" +#include "libnm-core-intern/nm-core-internal.h" -#include "nm-std-aux/c-list-util.h" -#include "nm-glib-aux/nm-c-list.h" +#include "libnm-std-aux/c-list-util.h" +#include "libnm-glib-aux/nm-c-list.h" #include "nm-dbus-object.h" #include "devices/nm-device-ethernet.h" #include "nm-settings-connection.h" #include "nm-settings-plugin.h" #include "nm-dbus-manager.h" #include "nm-auth-utils.h" -#include "nm-libnm-core-intern/nm-auth-subject.h" +#include "libnm-core-aux-intern/nm-auth-subject.h" #include "nm-session-monitor.h" #include "plugins/keyfile/nms-keyfile-plugin.h" #include "plugins/keyfile/nms-keyfile-storage.h" @@ -139,7 +140,7 @@ nm_assert_storage_data_lst(CList *head) u = nm_settings_storage_get_uuid(sd->storage); if (!uuid) { uuid = u; - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); } else nm_assert(nm_streq0(uuid, u)); } @@ -182,7 +183,7 @@ _sett_conn_entry_new(const char *uuid) SettConnEntry *sett_conn_entry; gsize l_p_1; - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); l_p_1 = strlen(uuid) + 1; @@ -370,6 +371,7 @@ typedef struct { CList connections_lst_head; NMSettingsConnection **connections_cached_list; + NMSettingsConnection **connections_cached_list_sorted_by_autoconnect_priority; GSList *unmanaged_specs; GSList *unrecognized_specs; @@ -386,8 +388,17 @@ typedef struct { guint kf_db_flush_idle_id_timestamps; guint kf_db_flush_idle_id_seen_bssids; + bool kf_db_pruned_timestamps; + bool kf_db_pruned_seen_bssid; + bool started : 1; + /* Whether NMSettingsConnections changed in a way that affects the comparison + * with nm_settings_connection_cmp_autoconnect_priority_with_data(). In that case, + * we may need to re-sort the connections_cached_list_sorted_by_autoconnect_priority + * list. */ + bool sorted_by_autoconnect_priority_maybe_changed : 1; + } NMSettingsPrivate; struct _NMSettings { @@ -487,6 +498,8 @@ _startup_complete_check_is_ready(NMSettings * self, conn = nm_settings_connection_get_connection(sett_conn); nm_manager_for_each_device (priv->manager, device, tmp_lst) { + gs_free_error GError *error = NULL; + if (!nm_device_is_real(device)) continue; @@ -497,7 +510,13 @@ _startup_complete_check_is_ready(NMSettings * self, continue; } - if (!nm_device_check_connection_compatible(device, conn, NULL)) + /* Check that device is compatible with the device. We are also happy + * with a device compatible but for which the connection is disallowed + * by NM configuration. */ + if (!nm_device_check_connection_compatible(device, conn, &error) + && !g_error_matches(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_DISALLOWED)) continue; return TRUE; @@ -1433,7 +1452,8 @@ _plugin_connections_reload(NMSettings *self) NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, TRUE, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS - | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS); + | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET); for (iter = priv->plugins; iter; iter = iter->next) nm_settings_plugin_load_connections_done(iter->data); @@ -1460,7 +1480,7 @@ _add_connection_to_first_plugin(NMSettings * self, uuid = nm_connection_get_uuid(new_connection); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); for (iter = priv->plugins; iter; iter = iter->next) { NMSettingsPlugin *plugin = NM_SETTINGS_PLUGIN(iter->data); @@ -1541,9 +1561,7 @@ _add_connection_to_first_plugin(NMSettings * self, } agent_owned_secrets = - nm_connection_to_dbus(new_connection, - NM_CONNECTION_SERIALIZE_ONLY_SECRETS - | NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); + nm_connection_to_dbus(new_connection, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); connection_to_add_real = _connection_changed_normalize_connection(storage, connection_to_add, @@ -1912,7 +1930,8 @@ again_delete_tombstone: _NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK, FALSE, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS - | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET | (NM_FLAGS_HAS(add_reason, NM_SETTINGS_CONNECTION_ADD_REASON_BLOCK_AUTOCONNECT) ? NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT : NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE)); @@ -2218,9 +2237,7 @@ nm_settings_update_connection(NMSettings * self, nm_assert(nm_streq(uuid, nm_settings_storage_get_uuid(new_storage))); agent_owned_secrets = - nm_connection_to_dbus(connection, - NM_CONNECTION_SERIALIZE_ONLY_SECRETS - | NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); + nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED); new_connection_real = _connection_changed_normalize_connection(new_storage, new_connection, agent_owned_secrets, @@ -2297,7 +2314,7 @@ nm_settings_delete_connection(NMSettings * self, nm_assert(NM_IS_SETTINGS_STORAGE(cur_storage)); uuid = nm_settings_storage_get_uuid(cur_storage); - nm_assert(nm_utils_is_uuid(uuid)); + nm_assert(nm_uuid_is_normalized(uuid)); sett_conn_entry = _sett_conn_entries_get(self, uuid); @@ -2691,9 +2708,9 @@ impl_settings_add_connection2(NMDBusObject * obj, g_variant_get(parameters, "(@a{sa{sv}}u@a{sv})", &settings, &flags_u, &args); if (NM_FLAGS_ANY(flags_u, - ~((guint32)(NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK - | NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY - | NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT)))) { + ~((guint32) (NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK + | NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY + | NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT)))) { g_dbus_method_invocation_take_error(invocation, g_error_new_literal(NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_ARGUMENTS, @@ -2814,7 +2831,8 @@ impl_settings_load_connections(NMDBusObject * obj, NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, TRUE, NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS - | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS); + | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS + | NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET); for (iter = priv->plugins; iter; iter = iter->next) nm_settings_plugin_load_connections_done(iter->data); @@ -2832,7 +2850,7 @@ impl_settings_load_connections(NMDBusObject * obj, g_dbus_method_invocation_return_value(invocation, g_variant_new("(b^as)", - (gboolean)(!failures), + (gboolean) (!failures), failures ? (const char **) failures->pdata : NM_PTRARRAY_EMPTY(const char *))); @@ -2870,25 +2888,48 @@ impl_settings_reload_connections(NMDBusObject * obj, /*****************************************************************************/ +void +_nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(NMSettings *self) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self); + + priv->sorted_by_autoconnect_priority_maybe_changed = TRUE; +} + static void _clear_connections_cached_list(NMSettingsPrivate *priv) { - if (!priv->connections_cached_list) - return; + if (priv->connections_cached_list) { + nm_assert(priv->connections_len == NM_PTRARRAY_LEN(priv->connections_cached_list)); + +#if NM_MORE_ASSERTS + /* set the pointer to a bogus value. This makes it more apparent + * if somebody has a reference to the cached list and still uses + * it. That is a bug, this code just tries to make it blow up + * more eagerly. */ + memset(priv->connections_cached_list, + 0x43, + sizeof(NMSettingsConnection *) * (priv->connections_len + 1)); +#endif - nm_assert(priv->connections_len == NM_PTRARRAY_LEN(priv->connections_cached_list)); + nm_clear_g_free(&priv->connections_cached_list); + } + if (priv->connections_cached_list_sorted_by_autoconnect_priority) { + nm_assert(priv->connections_len + == NM_PTRARRAY_LEN(priv->connections_cached_list_sorted_by_autoconnect_priority)); #if NM_MORE_ASSERTS - /* set the pointer to a bogus value. This makes it more apparent - * if somebody has a reference to the cached list and still uses - * it. That is a bug, this code just tries to make it blow up - * more eagerly. */ - memset(priv->connections_cached_list, - 0x43, - sizeof(NMSettingsConnection *) * (priv->connections_len + 1)); + /* set the pointer to a bogus value. This makes it more apparent + * if somebody has a reference to the cached list and still uses + * it. That is a bug, this code just tries to make it blow up + * more eagerly. */ + memset(priv->connections_cached_list_sorted_by_autoconnect_priority, + 0x42, + sizeof(NMSettingsConnection *) * (priv->connections_len + 1)); #endif - nm_clear_g_free(&priv->connections_cached_list); + nm_clear_g_free(&priv->connections_cached_list_sorted_by_autoconnect_priority); + } } static void @@ -3027,6 +3068,65 @@ nm_settings_get_connections(NMSettings *self, guint *out_len) return priv->connections_cached_list; } +NMSettingsConnection *const * +nm_settings_get_connections_sorted_by_autoconnect_priority(NMSettings *self, guint *out_len) +{ + NMSettingsPrivate *priv; + gboolean needs_sort = FALSE; + + g_return_val_if_fail(NM_IS_SETTINGS(self), NULL); + + priv = NM_SETTINGS_GET_PRIVATE(self); + + nm_assert(priv->connections_len == c_list_length(&priv->connections_lst_head)); + nm_assert( + !priv->connections_cached_list_sorted_by_autoconnect_priority + || (priv->connections_len + == NM_PTRARRAY_LEN(priv->connections_cached_list_sorted_by_autoconnect_priority))); + + if (!priv->connections_cached_list_sorted_by_autoconnect_priority) { + NMSettingsConnection *const *list_cached; + guint len; + + list_cached = nm_settings_get_connections(self, &len); + priv->connections_cached_list_sorted_by_autoconnect_priority = + nm_memdup(list_cached, sizeof(NMSettingsConnection *) * (len + 1)); + needs_sort = (len > 1); + } else if (priv->sorted_by_autoconnect_priority_maybe_changed) { + if (!nm_utils_ptrarray_is_sorted( + (gconstpointer *) priv->connections_cached_list_sorted_by_autoconnect_priority, + priv->connections_len, + FALSE, + nm_settings_connection_cmp_autoconnect_priority_with_data, + NULL)) { + /* We cache the sorted list, but we don't monitor all entries whether they + * get modified to invalidate the sort order. So every time we have to check + * whether the sort order is still correct. The vast majority of the time it + * is, and this check is faster than sorting anew. */ + needs_sort = TRUE; + } + } else { + nm_assert(nm_utils_ptrarray_is_sorted( + (gconstpointer *) priv->connections_cached_list_sorted_by_autoconnect_priority, + priv->connections_len, + TRUE, + nm_settings_connection_cmp_autoconnect_priority_with_data, + NULL)); + } + + priv->sorted_by_autoconnect_priority_maybe_changed = FALSE; + if (needs_sort) { + g_qsort_with_data(priv->connections_cached_list_sorted_by_autoconnect_priority, + priv->connections_len, + sizeof(NMSettingsConnection *), + nm_settings_connection_cmp_autoconnect_priority_p_with_data, + NULL); + } + + NM_SET_OUT(out_len, priv->connections_len); + return priv->connections_cached_list_sorted_by_autoconnect_priority; +} + /** * nm_settings_get_connections_clone: * @self: the #NMSetting @@ -3058,9 +3158,13 @@ nm_settings_get_connections_clone(NMSettings * self, g_return_val_if_fail(NM_IS_SETTINGS(self), NULL); - list_cached = nm_settings_get_connections(self, &len); + if (sort_compare_func == nm_settings_connection_cmp_autoconnect_priority_p_with_data) { + list_cached = nm_settings_get_connections_sorted_by_autoconnect_priority(self, &len); + sort_compare_func = NULL; + } else + list_cached = nm_settings_get_connections(self, &len); -#if NM_MORE_ASSERTS +#if NM_MORE_ASSERTS > 10 nm_assert(list_cached); for (i = 0; i < len; i++) nm_assert(NM_IS_SETTINGS_CONNECTION(list_cached[i])); @@ -3204,7 +3308,7 @@ add_plugin_load_file(NMSettings *self, const char *pname, GError **error) /* errors after this point are fatal, because we loaded the shared library already. */ - if (!g_module_symbol(module, "nm_settings_plugin_factory", (gpointer)(&factory_func))) { + if (!g_module_symbol(module, "nm_settings_plugin_factory", (gpointer) (&factory_func))) { g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, @@ -3591,6 +3695,41 @@ again: /*****************************************************************************/ +static gboolean +_kf_db_prune_predicate(const char *uuid, gpointer user_data) +{ + return !!nm_settings_get_connection_by_uuid(user_data, uuid); +} + +static void +_kf_db_to_file(NMSettings *self, gboolean is_timestamps, gboolean force_write) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self); + NMKeyFileDB * kf_db; + bool * p_kf_db_pruned; + + if (is_timestamps) { + kf_db = priv->kf_db_timestamps; + p_kf_db_pruned = &priv->kf_db_pruned_timestamps; + } else { + kf_db = priv->kf_db_seen_bssids; + p_kf_db_pruned = &priv->kf_db_pruned_seen_bssid; + } + + if (!*p_kf_db_pruned) { + /* we only prune the DB once, because afterwards every + * add/remove of an connection will lead to a direct update. */ + *p_kf_db_pruned = TRUE; + nm_key_file_db_prune(kf_db, _kf_db_prune_predicate, self); + + /* once we also go over the directory, and see whether we + * have any left over temporary files to delete. */ + nm_key_file_db_prune_tmp_files(kf_db); + } + + nm_key_file_db_to_file(kf_db, force_write); +} + G_GNUC_PRINTF(4, 5) static void _kf_db_log_fcn(NMKeyFileDB *kf_db, int syslog_level, gpointer user_data, const char *fmt, ...) @@ -3639,7 +3778,7 @@ _kf_db_got_dirty_flush(NMSettings *self, gboolean is_timestamps) } if (nm_key_file_db_is_dirty(kf_db)) - nm_key_file_db_to_file(kf_db, FALSE); + _kf_db_to_file(self, is_timestamps, FALSE); else { _LOGT("[%s-keyfile]: skip saving changes to \"%s\"", prefix, @@ -3692,15 +3831,10 @@ _kf_db_got_dirty_fcn(NMKeyFileDB *kf_db, gpointer user_data) void nm_settings_kf_db_write(NMSettings *self) { - NMSettingsPrivate *priv; - g_return_if_fail(NM_IS_SETTINGS(self)); - priv = NM_SETTINGS_GET_PRIVATE(self); - if (priv->kf_db_timestamps) - nm_key_file_db_to_file(priv->kf_db_timestamps, TRUE); - if (priv->kf_db_seen_bssids) - nm_key_file_db_to_file(priv->kf_db_seen_bssids, TRUE); + _kf_db_to_file(self, TRUE, TRUE); + _kf_db_to_file(self, FALSE, TRUE); } /*****************************************************************************/ @@ -3938,8 +4072,8 @@ finalize(GObject *object) nm_clear_g_source(&priv->kf_db_flush_idle_id_timestamps); nm_clear_g_source(&priv->kf_db_flush_idle_id_seen_bssids); - nm_key_file_db_to_file(priv->kf_db_timestamps, FALSE); - nm_key_file_db_to_file(priv->kf_db_seen_bssids, FALSE); + _kf_db_to_file(self, TRUE, FALSE); + _kf_db_to_file(self, FALSE, FALSE); nm_key_file_db_destroy(priv->kf_db_timestamps); nm_key_file_db_destroy(priv->kf_db_seen_bssids); @@ -4027,18 +4161,16 @@ static const NMDBusInterfaceInfoExtended interface_info_settings = { .in_args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("hostname", "s"), ), ), .handle = impl_settings_save_hostname, ), ), - .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, - &signal_info_new_connection, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&signal_info_new_connection, &signal_info_connection_removed, ), .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Connections", - "ao", - NM_SETTINGS_CONNECTIONS), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Hostname", "s", NM_SETTINGS_HOSTNAME), - NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("CanModify", - "b", - NM_SETTINGS_CAN_MODIFY), ), ), - .legacy_property_changed = TRUE, + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Connections", + "ao", + NM_SETTINGS_CONNECTIONS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Hostname", "s", NM_SETTINGS_HOSTNAME), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("CanModify", + "b", + NM_SETTINGS_CAN_MODIFY), ), ), }; static void |