diff options
| author | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
| commit | 80ec1decc49c72efec2a8b87c06245c92c0ab807 (patch) | |
| tree | e3b229aa94e8dcf0590f2317664176e7b8f7607b /src/nm-config-data.c | |
| parent | 65f86e8f56267192d42f2b629fc6b0c99fb9cd0c (diff) | |
New upstream version 1.29.90 upstream/1.29.90
Diffstat (limited to 'src/nm-config-data.c')
| -rw-r--r-- | src/nm-config-data.c | 2087 |
1 files changed, 0 insertions, 2087 deletions
diff --git a/src/nm-config-data.c b/src/nm-config-data.c deleted file mode 100644 index 4320e26b..00000000 --- a/src/nm-config-data.c +++ /dev/null @@ -1,2087 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2011 Red Hat, Inc. - * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de> - */ - -#include "nm-default.h" - -#include "nm-config-data.h" - -#include "nm-config.h" -#include "devices/nm-device.h" -#include "nm-core-internal.h" -#include "nm-keyfile/nm-keyfile-internal.h" -#include "nm-keyfile/nm-keyfile-utils.h" - -/*****************************************************************************/ - -typedef struct { - char * group_name; - gboolean stop_match; - struct { - /* have a separate boolean field @has, because a @spec with - * value %NULL does not necessarily mean, that the property - * "match-device" was unspecified. */ - gboolean has; - GSList * spec; - } match_device; -} MatchSectionInfo; - -struct _NMGlobalDnsDomain { - char * name; - char **servers; - char **options; -}; - -struct _NMGlobalDnsConfig { - char ** searches; - char ** options; - GHashTable * domains; - const char **domain_list; - gboolean internal; -}; - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CONFIG_MAIN_FILE, - PROP_CONFIG_DESCRIPTION, - PROP_KEYFILE_USER, - PROP_KEYFILE_INTERN, - PROP_CONNECTIVITY_ENABLED, - PROP_CONNECTIVITY_URI, - PROP_CONNECTIVITY_INTERVAL, - PROP_CONNECTIVITY_RESPONSE, - PROP_NO_AUTO_DEFAULT, ); - -typedef struct { - char *config_main_file; - char *config_description; - - GKeyFile *keyfile; - GKeyFile *keyfile_user; - GKeyFile *keyfile_intern; - - /* A zero-terminated list of pre-processed information from the - * [connection] sections. This is to speed up lookup. */ - MatchSectionInfo *connection_infos; - - /* A zero-terminated list of pre-processed information from the - * [device] sections. This is to speed up lookup. */ - MatchSectionInfo *device_infos; - - struct { - gboolean enabled; - char * uri; - char * response; - guint interval; - } connectivity; - - int autoconnect_retries_default; - - struct { - /* from /var/lib/NetworkManager/no-auto-default.state */ - char ** arr; - GSList *specs; - - /* from main.no-auto-default setting in NetworkManager.conf. */ - GSList *specs_config; - } no_auto_default; - - GSList *ignore_carrier; - GSList *assume_ipv6ll_only; - - char *dns_mode; - char *rc_manager; - - NMGlobalDnsConfig *global_dns; - - bool systemd_resolved : 1; -} NMConfigDataPrivate; - -struct _NMConfigData { - GObject parent; - NMConfigDataPrivate _priv; -}; - -struct _NMConfigDataClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE(NMConfigData, nm_config_data, G_TYPE_OBJECT) - -#define NM_CONFIG_DATA_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMConfigData, NM_IS_CONFIG_DATA) - -/*****************************************************************************/ - -const char * -nm_config_data_get_config_main_file(const NMConfigData *self) -{ - g_return_val_if_fail(self, NULL); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->config_main_file; -} - -const char * -nm_config_data_get_config_description(const NMConfigData *self) -{ - g_return_val_if_fail(self, NULL); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->config_description; -} - -gboolean -nm_config_data_has_group(const NMConfigData *self, const char *group) -{ - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); - g_return_val_if_fail(group && *group, FALSE); - - return g_key_file_has_group(NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile, group); -} - -char * -nm_config_data_get_value(const NMConfigData * self, - const char * group, - const char * key, - NMConfigGetValueFlags flags) -{ - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), NULL); - g_return_val_if_fail(group && *group, NULL); - g_return_val_if_fail(key && *key, NULL); - - return nm_config_keyfile_get_value(NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile, - group, - key, - flags); -} - -gboolean -nm_config_data_has_value(const NMConfigData * self, - const char * group, - const char * key, - NMConfigGetValueFlags flags) -{ - gs_free char *value = NULL; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); - g_return_val_if_fail(group && *group, FALSE); - g_return_val_if_fail(key && *key, FALSE); - - value = - nm_config_keyfile_get_value(NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile, group, key, flags); - return !!value; -} - -int -nm_config_data_get_value_boolean(const NMConfigData *self, - const char * group, - const char * key, - int default_value) -{ - char *str; - int value = default_value; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), default_value); - g_return_val_if_fail(group && *group, default_value); - g_return_val_if_fail(key && *key, default_value); - - /* when parsing the boolean, base it on the raw value from g_key_file_get_value(). */ - str = nm_config_keyfile_get_value(NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile, - group, - key, - NM_CONFIG_GET_VALUE_RAW); - if (str) { - value = nm_config_parse_boolean(str, default_value); - g_free(str); - } - return value; -} - -gint64 -nm_config_data_get_value_int64(const NMConfigData *self, - const char * group, - const char * key, - guint base, - gint64 min, - gint64 max, - gint64 fallback) -{ - int errsv; - gint64 val; - char * str; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), fallback); - g_return_val_if_fail(group && *group, fallback); - g_return_val_if_fail(key && *key, fallback); - - str = nm_config_keyfile_get_value(NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile, - group, - key, - NM_CONFIG_GET_VALUE_NONE); - val = _nm_utils_ascii_str_to_int64(str, base, min, max, fallback); - if (str) { - errsv = errno; - g_free(str); - errno = errsv; - } - return val; -} - -char ** -nm_config_data_get_plugins(const NMConfigData *self, gboolean allow_default) -{ - gs_free_error GError * error = NULL; - const NMConfigDataPrivate *priv; - char ** list; - - g_return_val_if_fail(self, NULL); - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - - list = g_key_file_get_string_list(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - "plugins", - NULL, - &error); - if (nm_keyfile_error_is_not_found(error) && allow_default) { - nm_auto_unref_keyfile GKeyFile *kf = nm_config_create_keyfile(); - - /* let keyfile split the default string according to its own escaping rules. */ - g_key_file_set_value(kf, - NM_CONFIG_KEYFILE_GROUP_MAIN, - "plugins", - NM_CONFIG_DEFAULT_MAIN_PLUGINS); - list = g_key_file_get_string_list(kf, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", NULL, NULL); - } - return _nm_utils_strv_cleanup(list, TRUE, TRUE, TRUE); -} - -gboolean -nm_config_data_get_connectivity_enabled(const NMConfigData *self) -{ - g_return_val_if_fail(self, FALSE); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.enabled; -} - -const char * -nm_config_data_get_connectivity_uri(const NMConfigData *self) -{ - g_return_val_if_fail(self, NULL); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.uri; -} - -guint -nm_config_data_get_connectivity_interval(const NMConfigData *self) -{ - g_return_val_if_fail(self, 0); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.interval; -} - -const char * -nm_config_data_get_connectivity_response(const NMConfigData *self) -{ - g_return_val_if_fail(self != NULL, NULL); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.response; -} - -int -nm_config_data_get_autoconnect_retries_default(const NMConfigData *self) -{ - g_return_val_if_fail(self, FALSE); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->autoconnect_retries_default; -} - -const char *const * -nm_config_data_get_no_auto_default(const NMConfigData *self) -{ - g_return_val_if_fail(self, FALSE); - - return (const char *const *) NM_CONFIG_DATA_GET_PRIVATE(self)->no_auto_default.arr; -} - -gboolean -nm_config_data_get_no_auto_default_for_device(const NMConfigData *self, NMDevice *device) -{ - const NMConfigDataPrivate *priv; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); - g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - return nm_device_spec_match_list(device, priv->no_auto_default.specs) - || nm_device_spec_match_list(device, priv->no_auto_default.specs_config); -} - -const char * -nm_config_data_get_dns_mode(const NMConfigData *self) -{ - g_return_val_if_fail(self, NULL); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->dns_mode; -} - -const char * -nm_config_data_get_rc_manager(const NMConfigData *self) -{ - g_return_val_if_fail(self, NULL); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->rc_manager; -} - -gboolean -nm_config_data_get_systemd_resolved(const NMConfigData *self) -{ - g_return_val_if_fail(self, FALSE); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->systemd_resolved; -} - -gboolean -nm_config_data_get_ignore_carrier(const NMConfigData *self, NMDevice *device) -{ - gs_free char *value = NULL; - gboolean has_match; - int m; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); - g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); - - value = nm_config_data_get_device_config(self, - NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER, - device, - &has_match); - if (has_match) - m = nm_config_parse_boolean(value, -1); - else - m = nm_device_spec_match_list_full(device, - NM_CONFIG_DATA_GET_PRIVATE(self)->ignore_carrier, - -1); - - if (NM_IN_SET(m, TRUE, FALSE)) - return m; - - /* if ignore-carrier is not explicitly configed, then it depends on the device (type). */ - return nm_device_ignore_carrier_by_default(device); -} - -gboolean -nm_config_data_get_assume_ipv6ll_only(const NMConfigData *self, NMDevice *device) -{ - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); - g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); - - return nm_device_spec_match_list(device, NM_CONFIG_DATA_GET_PRIVATE(self)->assume_ipv6ll_only); -} - -GKeyFile * -nm_config_data_clone_keyfile_intern(const NMConfigData *self) -{ - const NMConfigDataPrivate *priv; - GKeyFile * keyfile; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - - keyfile = nm_config_create_keyfile(); - if (priv->keyfile_intern) - _nm_keyfile_copy(keyfile, priv->keyfile_intern); - return keyfile; -} - -GKeyFile * -_nm_config_data_get_keyfile(const NMConfigData *self) -{ - return NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile; -} - -GKeyFile * -_nm_config_data_get_keyfile_intern(const NMConfigData *self) -{ - return NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile_intern; -} - -GKeyFile * -_nm_config_data_get_keyfile_user(const NMConfigData *self) -{ - return NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile_user; -} - -/*****************************************************************************/ - -static NMAuthPolkitMode -nm_auth_polkit_mode_from_string(const char *str) -{ - int as_bool; - - if (!str) - return NM_AUTH_POLKIT_MODE_UNKNOWN; - - if (nm_streq(str, "root-only")) - return NM_AUTH_POLKIT_MODE_ROOT_ONLY; - - as_bool = _nm_utils_ascii_str_to_bool(str, -1); - if (as_bool != -1) { - return as_bool ? NM_AUTH_POLKIT_MODE_USE_POLKIT : NM_AUTH_POLKIT_MODE_ALLOW_ALL; - } - - return NM_AUTH_POLKIT_MODE_UNKNOWN; -} - -static NMAuthPolkitMode -_config_data_get_main_auth_polkit(const NMConfigData *self, gboolean *out_invalid_config) -{ - NMAuthPolkitMode auth_polkit_mode; - const char * str; - - str = nm_config_data_get_value(self, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT, - NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); - auth_polkit_mode = nm_auth_polkit_mode_from_string(str); - if (auth_polkit_mode == NM_AUTH_POLKIT_MODE_UNKNOWN) { - NM_SET_OUT(out_invalid_config, (str != NULL)); - auth_polkit_mode = nm_auth_polkit_mode_from_string(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT); - if (auth_polkit_mode == NM_AUTH_POLKIT_MODE_UNKNOWN) { - nm_assert_not_reached(); - auth_polkit_mode = NM_AUTH_POLKIT_MODE_ROOT_ONLY; - } - } else - NM_SET_OUT(out_invalid_config, FALSE); - - return auth_polkit_mode; -} - -NMAuthPolkitMode -nm_config_data_get_main_auth_polkit(const NMConfigData *self) -{ - return _config_data_get_main_auth_polkit(self, NULL); -} - -/*****************************************************************************/ - -/** - * nm_config_data_get_groups: - * @self: the #NMConfigData instance - * - * Returns: (transfer full): the list of groups in the configuration. The order - * of the section is undefined, as the configuration gets merged from multiple - * sources. - */ -char ** -nm_config_data_get_groups(const NMConfigData *self) -{ - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), NULL); - - return g_key_file_get_groups(NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile, NULL); -} - -char ** -nm_config_data_get_keys(const NMConfigData *self, const char *group) -{ - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), NULL); - g_return_val_if_fail(group && *group, NULL); - - return g_key_file_get_keys(NM_CONFIG_DATA_GET_PRIVATE(self)->keyfile, group, NULL, NULL); -} - -/** - * nm_config_data_is_intern_atomic_group: - * @self: - * @group: name of the group to check. - * - * whether a configuration group @group exists and is entirely overwritten - * by internal configuration, i.e. whether it is an atomic group that is - * overwritten. - * - * It doesn't say, that there actually is a user setting that was overwritten. That - * means there could be no corresponding section defined in user configuration - * that required overwriting. - * - * Returns: %TRUE if @group exists and is an atomic group set via internal configuration. - */ -gboolean -nm_config_data_is_intern_atomic_group(const NMConfigData *self, const char *group) -{ - const NMConfigDataPrivate *priv; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), FALSE); - g_return_val_if_fail(group && *group, FALSE); - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - - if (!priv->keyfile_intern - || !g_key_file_has_key(priv->keyfile_intern, - group, - NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, - NULL)) - return FALSE; - - /* we have a .was entry for the section. That means that the section would be overwritten - * from user configuration. But it doesn't mean that the merged configuration contains this - * groups, because the internal setting could hide the user section. - * Only return TRUE, if we actually have such a group in the merged configuration.*/ - return g_key_file_has_group(priv->keyfile, group); -} - -/*****************************************************************************/ - -static GKeyFile * -_merge_keyfiles(GKeyFile *keyfile_user, GKeyFile *keyfile_intern) -{ - gs_strfreev char **groups = NULL; - guint g, k; - GKeyFile * keyfile; - gsize ngroups; - - keyfile = nm_config_create_keyfile(); - if (keyfile_user) - _nm_keyfile_copy(keyfile, keyfile_user); - if (!keyfile_intern) - return keyfile; - - groups = g_key_file_get_groups(keyfile_intern, &ngroups); - if (!groups) - return keyfile; - - /* we must reverse the order of the connection settings so that we - * have lowest priority last. */ - _nm_config_sort_groups(groups, ngroups); - for (g = 0; groups[g]; g++) { - const char * group = groups[g]; - gs_strfreev char **keys = NULL; - gboolean is_intern, is_atomic = FALSE; - - keys = g_key_file_get_keys(keyfile_intern, group, NULL, NULL); - if (!keys) - continue; - - is_intern = g_str_has_prefix(group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); - if (!is_intern - && g_key_file_has_key(keyfile_intern, - group, - NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, - NULL)) { - /* the entire section is atomically overwritten by @keyfile_intern. */ - g_key_file_remove_group(keyfile, group, NULL); - is_atomic = TRUE; - } - - for (k = 0; keys[k]; k++) { - const char * key = keys[k]; - gs_free char *value = NULL; - - if (is_atomic && strcmp(key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS) == 0) - continue; - - if (!is_intern && !is_atomic - && NM_STR_HAS_PREFIX_WITH_MORE(key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) { - const char *key_base = &key[NM_STRLEN(NM_CONFIG_KEYFILE_KEYPREFIX_WAS)]; - - if (!g_key_file_has_key(keyfile_intern, group, key_base, NULL)) - g_key_file_remove_key(keyfile, group, key_base, NULL); - continue; - } - if (!is_intern && !is_atomic - && NM_STR_HAS_PREFIX_WITH_MORE(key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) - continue; - - value = g_key_file_get_value(keyfile_intern, group, key, NULL); - g_key_file_set_value(keyfile, group, key, value); - } - } - return keyfile; -} - -/*****************************************************************************/ - -static int -_nm_config_data_log_sort(const char **pa, const char **pb, gpointer dummy) -{ - gboolean a_is_connection, b_is_connection; - gboolean a_is_device, b_is_device; - gboolean a_is_intern, b_is_intern; - gboolean a_is_main, b_is_main; - const char *a = *pa; - const char *b = *pb; - - /* we sort intern groups to the end. */ - a_is_intern = g_str_has_prefix(a, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); - b_is_intern = g_str_has_prefix(b, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); - - if (a_is_intern && b_is_intern) - return 0; - if (a_is_intern) - return 1; - if (b_is_intern) - return -1; - - /* we sort connection groups before intern groups (to the end). */ - a_is_connection = a && g_str_has_prefix(a, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); - b_is_connection = b && g_str_has_prefix(b, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); - - if (a_is_connection && b_is_connection) { - /* if both are connection groups, we want the explicit [connection] group first. */ - a_is_connection = a[NM_STRLEN(NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0'; - b_is_connection = b[NM_STRLEN(NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0'; - - if (a_is_connection != b_is_connection) { - if (a_is_connection) - return -1; - return 1; - } - /* the sections are ordered lowest-priority first. Reverse their order. */ - return pa < pb ? 1 : -1; - } - if (a_is_connection && !b_is_connection) - return 1; - if (b_is_connection && !a_is_connection) - return -1; - - /* we sort device groups before connection groups (to the end). */ - a_is_device = a && g_str_has_prefix(a, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); - b_is_device = b && g_str_has_prefix(b, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); - - if (a_is_device && b_is_device) { - /* if both are device groups, we want the explicit [device] group first. */ - a_is_device = a[NM_STRLEN(NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE)] == '\0'; - b_is_device = b[NM_STRLEN(NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE)] == '\0'; - - if (a_is_device != b_is_device) { - if (a_is_device) - return -1; - return 1; - } - /* the sections are ordered lowest-priority first. Reverse their order. */ - return pa < pb ? 1 : -1; - } - if (a_is_device && !b_is_device) - return 1; - if (b_is_device && !a_is_device) - return -1; - - a_is_main = nm_streq0(a, "main"); - b_is_main = nm_streq0(b, "main"); - if (a_is_main != b_is_main) - return a_is_main ? -1 : 1; - - return g_strcmp0(a, b); -} - -static const struct { - const char *group; - const char *key; - const char *value; -} default_values[] = { - {NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", NM_CONFIG_DEFAULT_MAIN_PLUGINS}, - {NM_CONFIG_KEYFILE_GROUP_MAIN, "rc-manager", NM_CONFIG_DEFAULT_MAIN_RC_MANAGER}, - {NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT, - NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT}, - {NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_DHCP, NM_CONFIG_DEFAULT_MAIN_DHCP}, - {NM_CONFIG_KEYFILE_GROUP_LOGGING, "backend", NM_CONFIG_DEFAULT_LOGGING_BACKEND}, - {NM_CONFIG_KEYFILE_GROUP_LOGGING, "audit", NM_CONFIG_DEFAULT_LOGGING_AUDIT}, -}; - -void -nm_config_data_log(const NMConfigData * self, - const char * prefix, - const char * key_prefix, - const char * no_auto_default_file, - /* FILE* */ gpointer print_stream) -{ - const NMConfigDataPrivate *priv; - gs_strfreev char ** groups = NULL; - gsize ngroups; - guint g, k, i; - FILE * stream = print_stream; - gs_unref_ptrarray GPtrArray *groups_full = NULL; - gboolean print_default = !!stream; - - g_return_if_fail(NM_IS_CONFIG_DATA(self)); - - if (!stream && !nm_logging_enabled(LOGL_DEBUG, LOGD_CORE)) - return; - - if (!prefix) - prefix = ""; - if (!key_prefix) - key_prefix = ""; - -#define _LOG(stream, prefix, ...) \ - G_STMT_START \ - { \ - if (!stream) \ - _nm_log(LOGL_DEBUG, \ - LOGD_CORE, \ - 0, \ - NULL, \ - NULL, \ - "%s"_NM_UTILS_MACRO_FIRST(__VA_ARGS__) "%s", \ - prefix _NM_UTILS_MACRO_REST(__VA_ARGS__), \ - ""); \ - else \ - fprintf(stream, \ - "%s"_NM_UTILS_MACRO_FIRST(__VA_ARGS__) "%s", \ - prefix _NM_UTILS_MACRO_REST(__VA_ARGS__), \ - "\n"); \ - } \ - G_STMT_END - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - - groups = g_key_file_get_groups(priv->keyfile, &ngroups); - if (!groups) - ngroups = 0; - - groups_full = g_ptr_array_sized_new(ngroups + 5); - - if (ngroups) { - g_ptr_array_set_size(groups_full, ngroups); - memcpy(groups_full->pdata, groups, sizeof(groups[0]) * ngroups); - g_ptr_array_sort_with_data(groups_full, (GCompareDataFunc) _nm_config_data_log_sort, NULL); - } - - if (print_default) { - for (g = 0; g < G_N_ELEMENTS(default_values); g++) { - const char *group = default_values[g].group; - gssize idx; - - idx = nm_utils_array_find_binary_search((gconstpointer *) groups_full->pdata, - sizeof(char *), - groups_full->len, - &group, - (GCompareDataFunc) _nm_config_data_log_sort, - NULL); - if (idx < 0) - g_ptr_array_insert(groups_full, (~idx), (gpointer) group); - } - } - - if (!stream) - _LOG(stream, prefix, "config-data[%p]: %u groups", self, groups_full->len); - - for (g = 0; g < groups_full->len; g++) { - const char * group = groups_full->pdata[g]; - gs_strfreev char **keys = NULL; - gboolean is_atomic; - - is_atomic = nm_config_data_is_intern_atomic_group(self, group); - - _LOG(stream, prefix, ""); - _LOG(stream, prefix, "[%s]%s", group, is_atomic && !stream ? " # atomic section" : ""); - - /* Print default values as comments */ - if (print_default) { - for (i = 0; i < G_N_ELEMENTS(default_values); i++) { - if (nm_streq(default_values[i].group, group) - && !g_key_file_has_key(priv->keyfile, group, default_values[i].key, NULL)) { - _LOG(stream, - prefix, - "%s# %s=%s", - key_prefix, - default_values[i].key, - default_values[i].value); - } - } - } - - keys = g_key_file_get_keys(priv->keyfile, group, NULL, NULL); - for (k = 0; keys && keys[k]; k++) { - const char * key = keys[k]; - gs_free char *value = NULL; - - value = g_key_file_get_value(priv->keyfile, group, key, NULL); - _LOG(stream, prefix, "%s%s=%s", key_prefix, key, value); - } - } - - _LOG(stream, prefix, ""); - _LOG(stream, prefix, "# no-auto-default file \"%s\"", no_auto_default_file); - { - gs_free char *msg = NULL; - - msg = nm_utils_g_slist_strlist_join(priv->no_auto_default.specs, ","); - if (msg) - _LOG(stream, prefix, "# no-auto-default specs \"%s\"", msg); - } - -#undef _LOG -} - -/*****************************************************************************/ - -const char *const * -nm_global_dns_config_get_searches(const NMGlobalDnsConfig *dns_config) -{ - g_return_val_if_fail(dns_config, NULL); - - return (const char *const *) dns_config->searches; -} - -const char *const * -nm_global_dns_config_get_options(const NMGlobalDnsConfig *dns_config) -{ - g_return_val_if_fail(dns_config, NULL); - - return (const char *const *) dns_config->options; -} - -guint -nm_global_dns_config_get_num_domains(const NMGlobalDnsConfig *dns_config) -{ - g_return_val_if_fail(dns_config, 0); - - return dns_config->domains ? g_hash_table_size(dns_config->domains) : 0; -} - -NMGlobalDnsDomain * -nm_global_dns_config_get_domain(const NMGlobalDnsConfig *dns_config, guint i) -{ - NMGlobalDnsDomain *domain; - - g_return_val_if_fail(dns_config, NULL); - g_return_val_if_fail(dns_config->domains, NULL); - g_return_val_if_fail(i < g_hash_table_size(dns_config->domains), NULL); - - nm_assert(NM_PTRARRAY_LEN(dns_config->domain_list) == g_hash_table_size(dns_config->domains)); - - domain = g_hash_table_lookup(dns_config->domains, dns_config->domain_list[i]); - - nm_assert(domain); - return domain; -} - -NMGlobalDnsDomain * -nm_global_dns_config_lookup_domain(const NMGlobalDnsConfig *dns_config, const char *name) -{ - g_return_val_if_fail(dns_config, NULL); - g_return_val_if_fail(name, NULL); - - return dns_config->domains ? g_hash_table_lookup(dns_config->domains, name) : NULL; -} - -const char * -nm_global_dns_domain_get_name(const NMGlobalDnsDomain *domain) -{ - g_return_val_if_fail(domain, NULL); - - return (const char *) domain->name; -} - -const char *const * -nm_global_dns_domain_get_servers(const NMGlobalDnsDomain *domain) -{ - g_return_val_if_fail(domain, NULL); - - return (const char *const *) domain->servers; -} - -const char *const * -nm_global_dns_domain_get_options(const NMGlobalDnsDomain *domain) -{ - g_return_val_if_fail(domain, NULL); - - return (const char *const *) domain->options; -} - -gboolean -nm_global_dns_config_is_internal(const NMGlobalDnsConfig *dns_config) -{ - return dns_config->internal; -} - -gboolean -nm_global_dns_config_is_empty(const NMGlobalDnsConfig *dns_config) -{ - g_return_val_if_fail(dns_config, TRUE); - - return !dns_config->searches && !dns_config->options && !dns_config->domain_list; -} - -void -nm_global_dns_config_update_checksum(const NMGlobalDnsConfig *dns_config, GChecksum *sum) -{ - NMGlobalDnsDomain *domain; - guint i, j; - guint8 v8; - - g_return_if_fail(dns_config); - g_return_if_fail(sum); - - v8 = NM_HASH_COMBINE_BOOLS(guint8, - !dns_config->searches, - !dns_config->options, - !dns_config->domain_list); - g_checksum_update(sum, (guchar *) &v8, 1); - - if (dns_config->searches) { - for (i = 0; dns_config->searches[i]; i++) - g_checksum_update(sum, - (guchar *) dns_config->searches[i], - strlen(dns_config->searches[i]) + 1); - } - if (dns_config->options) { - for (i = 0; dns_config->options[i]; i++) - g_checksum_update(sum, - (guchar *) dns_config->options[i], - strlen(dns_config->options[i]) + 1); - } - - if (dns_config->domain_list) { - for (i = 0; dns_config->domain_list[i]; i++) { - domain = g_hash_table_lookup(dns_config->domains, dns_config->domain_list[i]); - nm_assert(domain); - - v8 = NM_HASH_COMBINE_BOOLS(guint8, !domain->servers, !domain->options); - g_checksum_update(sum, (guchar *) &v8, 1); - - g_checksum_update(sum, (guchar *) domain->name, strlen(domain->name) + 1); - - if (domain->servers) { - for (j = 0; domain->servers[j]; j++) - g_checksum_update(sum, - (guchar *) domain->servers[j], - strlen(domain->servers[j]) + 1); - } - if (domain->options) { - for (j = 0; domain->options[j]; j++) - g_checksum_update(sum, - (guchar *) domain->options[j], - strlen(domain->options[j]) + 1); - } - } - } -} - -static void -global_dns_domain_free(NMGlobalDnsDomain *domain) -{ - if (domain) { - g_free(domain->name); - g_strfreev(domain->servers); - g_strfreev(domain->options); - g_free(domain); - } -} - -void -nm_global_dns_config_free(NMGlobalDnsConfig *dns_config) -{ - if (dns_config) { - g_strfreev(dns_config->searches); - g_strfreev(dns_config->options); - g_free(dns_config->domain_list); - if (dns_config->domains) - g_hash_table_unref(dns_config->domains); - g_free(dns_config); - } -} - -NMGlobalDnsConfig * -nm_config_data_get_global_dns_config(const NMConfigData *self) -{ - g_return_val_if_fail(NM_IS_CONFIG_DATA(self), NULL); - - return NM_CONFIG_DATA_GET_PRIVATE(self)->global_dns; -} - -static void -global_dns_config_seal_domains(NMGlobalDnsConfig *dns_config) -{ - nm_assert(dns_config); - nm_assert(dns_config->domains); - nm_assert(!dns_config->domain_list); - - if (g_hash_table_size(dns_config->domains) == 0) - nm_clear_pointer(&dns_config->domains, g_hash_table_unref); - else - dns_config->domain_list = nm_utils_strdict_get_keys(dns_config->domains, TRUE, NULL); -} - -static NMGlobalDnsConfig * -load_global_dns(GKeyFile *keyfile, gboolean internal) -{ - NMGlobalDnsConfig *dns_config; - char * group, *domain_prefix; - gs_strfreev char **groups = NULL; - int g, i, j, domain_prefix_len; - gboolean default_found = FALSE; - char ** strv; - - group = - internal ? NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS : NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS; - domain_prefix = internal ? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN - : NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN; - domain_prefix_len = strlen(domain_prefix); - - if (!nm_config_keyfile_has_global_dns_config(keyfile, internal)) - return NULL; - - dns_config = g_malloc0(sizeof(NMGlobalDnsConfig)); - dns_config->domains = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) global_dns_domain_free); - - strv = g_key_file_get_string_list(keyfile, - group, - NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_SEARCHES, - NULL, - NULL); - if (strv) { - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - if (!strv[0]) - g_free(strv); - else - dns_config->searches = strv; - } - - strv = g_key_file_get_string_list(keyfile, - group, - NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_OPTIONS, - NULL, - NULL); - if (strv) { - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - for (i = 0, j = 0; strv[i]; i++) { - if (_nm_utils_dns_option_validate(strv[i], NULL, NULL, TRUE, NULL)) - strv[j++] = strv[i]; - else - g_free(strv[i]); - } - if (j == 0) - g_free(strv); - else { - strv[j] = NULL; - dns_config->options = strv; - } - } - - groups = g_key_file_get_groups(keyfile, NULL); - for (g = 0; groups[g]; g++) { - char * name; - char ** servers = NULL, **options = NULL; - NMGlobalDnsDomain *domain; - - if (!g_str_has_prefix(groups[g], domain_prefix) || !groups[g][domain_prefix_len]) - continue; - - strv = g_key_file_get_string_list(keyfile, - groups[g], - NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_DOMAIN_SERVERS, - NULL, - NULL); - if (strv) { - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - for (i = 0, j = 0; strv[i]; i++) { - if (nm_utils_ipaddr_is_valid(AF_INET, strv[i]) - || nm_utils_ipaddr_is_valid(AF_INET6, strv[i])) - strv[j++] = strv[i]; - else - g_free(strv[i]); - } - if (j == 0) - g_free(strv); - else { - strv[j] = NULL; - servers = strv; - } - } - - if (!servers) - continue; - - strv = g_key_file_get_string_list(keyfile, - groups[g], - NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_DOMAIN_OPTIONS, - NULL, - NULL); - if (strv) { - options = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - if (!options[0]) - nm_clear_g_free(&options); - } - - name = strdup(&groups[g][domain_prefix_len]); - domain = g_malloc0(sizeof(NMGlobalDnsDomain)); - domain->name = name; - domain->servers = servers; - domain->options = options; - - g_hash_table_insert(dns_config->domains, strdup(name), domain); - - if (!strcmp(name, "*")) - default_found = TRUE; - } - - if (!default_found) { - nm_log_dbg(LOGD_CORE, - "%s global DNS configuration is missing default domain, ignore it", - internal ? "internal" : "user"); - nm_global_dns_config_free(dns_config); - return NULL; - } - - dns_config->internal = internal; - global_dns_config_seal_domains(dns_config); - return dns_config; -} - -void -nm_global_dns_config_to_dbus(const NMGlobalDnsConfig *dns_config, GValue *value) -{ - GVariantBuilder conf_builder, domains_builder, domain_builder; - guint i; - - g_variant_builder_init(&conf_builder, G_VARIANT_TYPE("a{sv}")); - if (!dns_config) - goto out; - - if (dns_config->searches) { - g_variant_builder_add(&conf_builder, - "{sv}", - "searches", - g_variant_new_strv((const char *const *) dns_config->searches, -1)); - } - - if (dns_config->options) { - g_variant_builder_add(&conf_builder, - "{sv}", - "options", - g_variant_new_strv((const char *const *) dns_config->options, -1)); - } - - g_variant_builder_init(&domains_builder, G_VARIANT_TYPE("a{sv}")); - if (dns_config->domain_list) { - for (i = 0; dns_config->domain_list[i]; i++) { - NMGlobalDnsDomain *domain; - - domain = g_hash_table_lookup(dns_config->domains, dns_config->domain_list[i]); - - g_variant_builder_init(&domain_builder, G_VARIANT_TYPE("a{sv}")); - - if (domain->servers) { - g_variant_builder_add( - &domain_builder, - "{sv}", - "servers", - g_variant_new_strv((const char *const *) domain->servers, -1)); - } - if (domain->options) { - g_variant_builder_add( - &domain_builder, - "{sv}", - "options", - g_variant_new_strv((const char *const *) domain->options, -1)); - } - - g_variant_builder_add(&domains_builder, - "{sv}", - domain->name, - g_variant_builder_end(&domain_builder)); - } - } - g_variant_builder_add(&conf_builder, - "{sv}", - "domains", - g_variant_builder_end(&domains_builder)); - -out: - g_value_take_variant(value, g_variant_builder_end(&conf_builder)); -} - -static NMGlobalDnsDomain * -global_dns_domain_from_dbus(char *name, GVariant *variant) -{ - NMGlobalDnsDomain *domain; - GVariantIter iter; - char ** strv, *key; - GVariant * val; - int i, j; - - if (!g_variant_is_of_type(variant, G_VARIANT_TYPE("a{sv}"))) - return NULL; - - domain = g_malloc0(sizeof(NMGlobalDnsDomain)); - domain->name = g_strdup(name); - - g_variant_iter_init(&iter, variant); - while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) { - if (!g_strcmp0(key, "servers") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { - strv = g_variant_dup_strv(val, NULL); - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - for (i = 0, j = 0; strv && strv[i]; i++) { - if (nm_utils_ipaddr_is_valid(AF_INET, strv[i]) - || nm_utils_ipaddr_is_valid(AF_INET6, strv[i])) - strv[j++] = strv[i]; - else - g_free(strv[i]); - } - if (j == 0) - g_free(strv); - else { - strv[j] = NULL; - g_strfreev(domain->servers); - domain->servers = strv; - } - } else if (!g_strcmp0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { - strv = g_variant_dup_strv(val, NULL); - g_strfreev(domain->options); - domain->options = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - if (!domain->options[0]) - nm_clear_g_free(&domain->options); - } - - g_variant_unref(val); - } - - /* At least one server is required */ - if (!domain->servers) { - global_dns_domain_free(domain); - return NULL; - } - - return domain; -} - -NMGlobalDnsConfig * -nm_global_dns_config_from_dbus(const GValue *value, GError **error) -{ - NMGlobalDnsConfig *dns_config; - GVariant * variant, *val; - GVariantIter iter; - char ** strv, *key; - int i, j; - - if (!G_VALUE_HOLDS_VARIANT(value)) { - g_set_error(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "invalid value type"); - return NULL; - } - - variant = g_value_get_variant(value); - if (!g_variant_is_of_type(variant, G_VARIANT_TYPE("a{sv}"))) { - g_set_error(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "invalid variant type"); - return NULL; - } - - dns_config = g_malloc0(sizeof(NMGlobalDnsConfig)); - dns_config->domains = g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) global_dns_domain_free); - - g_variant_iter_init(&iter, variant); - while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) { - if (!g_strcmp0(key, "searches") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { - strv = g_variant_dup_strv(val, NULL); - dns_config->searches = _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - } else if (!g_strcmp0(key, "options") && g_variant_is_of_type(val, G_VARIANT_TYPE("as"))) { - strv = g_variant_dup_strv(val, NULL); - _nm_utils_strv_cleanup(strv, TRUE, TRUE, TRUE); - - for (i = 0, j = 0; strv && strv[i]; i++) { - if (_nm_utils_dns_option_validate(strv[i], NULL, NULL, TRUE, NULL)) - strv[j++] = strv[i]; - else - g_free(strv[i]); - } - if (j == 0) - g_free(strv); - else { - strv[j] = NULL; - dns_config->options = strv; - } - } else if (!g_strcmp0(key, "domains") - && g_variant_is_of_type(val, G_VARIANT_TYPE("a{sv}"))) { - NMGlobalDnsDomain *domain; - GVariantIter domain_iter; - GVariant * v; - char * k; - - g_variant_iter_init(&domain_iter, val); - while (g_variant_iter_next(&domain_iter, "{&sv}", &k, &v)) { - if (k) { - domain = global_dns_domain_from_dbus(k, v); - if (domain) - g_hash_table_insert(dns_config->domains, strdup(k), domain); - } - g_variant_unref(v); - } - } - g_variant_unref(val); - } - - /* An empty value is valid and clears the internal configuration */ - if (!nm_global_dns_config_is_empty(dns_config) - && !nm_global_dns_config_lookup_domain(dns_config, "*")) { - g_set_error_literal(error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_FAILED, - "Global DNS configuration is missing the default domain"); - nm_global_dns_config_free(dns_config); - return NULL; - } - - global_dns_config_seal_domains(dns_config); - return dns_config; -} - -static gboolean -global_dns_equal(NMGlobalDnsConfig *old, NMGlobalDnsConfig *new) -{ - NMGlobalDnsDomain *domain_old, *domain_new; - gpointer key, value_old, value_new; - GHashTableIter iter; - - if (old == new) - return TRUE; - - if (!old || !new) - return FALSE; - - if (!_nm_utils_strv_equal(old->options, new->options) - || !_nm_utils_strv_equal(old->searches, new->searches)) - return FALSE; - - if ((!old->domains || !new->domains) && old->domains != new->domains) - return FALSE; - - if (g_hash_table_size(old->domains) != g_hash_table_size(new->domains)) - return FALSE; - - g_hash_table_iter_init(&iter, old->domains); - while (g_hash_table_iter_next(&iter, &key, &value_old)) { - value_new = g_hash_table_lookup(new->domains, key); - if (!value_new) - return FALSE; - - domain_old = value_old; - domain_new = value_new; - - if (!_nm_utils_strv_equal(domain_old->options, domain_new->options) - || !_nm_utils_strv_equal(domain_old->servers, domain_new->servers)) - return FALSE; - } - - return TRUE; -} - -/*****************************************************************************/ - -static const MatchSectionInfo * -_match_section_infos_lookup(const MatchSectionInfo *match_section_infos, - GKeyFile * keyfile, - const char * property, - NMDevice * device, - const NMPlatformLink * pllink, - const char * match_device_type, - char ** out_value) -{ - const char *match_dhcp_plugin; - - if (!match_section_infos) - return NULL; - - match_dhcp_plugin = nm_dhcp_manager_get_config(nm_dhcp_manager_get()); - - for (; match_section_infos->group_name; match_section_infos++) { - char * value = NULL; - gboolean match; - - /* FIXME: Here we use g_key_file_get_string(). This should be in sync with what keyfile-reader - * does. - * - * Unfortunately that is currently not possible because keyfile-reader does the two steps - * string_to_value(keyfile_to_string(keyfile)) in one. Optimally, keyfile library would - * expose both functions, and we would return here keyfile_to_string(keyfile). - * The caller then could convert the string to the proper value via string_to_value(value). */ - value = g_key_file_get_string(keyfile, match_section_infos->group_name, property, NULL); - if (!value && !match_section_infos->stop_match) - continue; - - if (match_section_infos->match_device.has) { - if (device) - match = nm_device_spec_match_list(device, match_section_infos->match_device.spec); - else if (pllink) - match = nm_match_spec_device_by_pllink(pllink, - match_device_type, - match_dhcp_plugin, - match_section_infos->match_device.spec, - FALSE); - else - match = FALSE; - } else - match = TRUE; - - if (match) { - *out_value = value; - return match_section_infos; - } - g_free(value); - } - return NULL; -} - -char * -nm_config_data_get_device_config(const NMConfigData *self, - const char * property, - NMDevice * device, - gboolean * has_match) -{ - const NMConfigDataPrivate *priv; - const MatchSectionInfo * connection_info; - char * value = NULL; - - NM_SET_OUT(has_match, FALSE); - - g_return_val_if_fail(self, NULL); - g_return_val_if_fail(property && *property, NULL); - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - - connection_info = _match_section_infos_lookup(&priv->device_infos[0], - priv->keyfile, - property, - device, - NULL, - NULL, - &value); - NM_SET_OUT(has_match, !!connection_info); - return value; -} - -char * -nm_config_data_get_device_config_by_pllink(const NMConfigData * self, - const char * property, - const NMPlatformLink *pllink, - const char * match_device_type, - gboolean * has_match) -{ - const NMConfigDataPrivate *priv; - const MatchSectionInfo * connection_info; - char * value = NULL; - - g_return_val_if_fail(self, NULL); - g_return_val_if_fail(property && *property, NULL); - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - - connection_info = _match_section_infos_lookup(&priv->device_infos[0], - priv->keyfile, - property, - NULL, - pllink, - match_device_type, - &value); - NM_SET_OUT(has_match, !!connection_info); - return value; -} - -gboolean -nm_config_data_get_device_config_boolean(const NMConfigData *self, - const char * property, - NMDevice * device, - int val_no_match, - int val_invalid) -{ - gs_free char *value = NULL; - gboolean has_match; - - value = nm_config_data_get_device_config(self, property, device, &has_match); - if (!has_match) - return val_no_match; - return nm_config_parse_boolean(value, val_invalid); -} - -char * -nm_config_data_get_connection_default(const NMConfigData *self, - const char * property, - NMDevice * device) -{ - const NMConfigDataPrivate *priv; - char * value = NULL; - - g_return_val_if_fail(self, NULL); - g_return_val_if_fail(property && *property, NULL); - g_return_val_if_fail(strchr(property, '.'), NULL); - - priv = NM_CONFIG_DATA_GET_PRIVATE(self); - -#if NM_MORE_ASSERTS > 10 - { - const char **ptr; - - for (ptr = __start_connection_defaults; ptr < __stop_connection_defaults; ptr++) { - if (nm_streq(property, *ptr)) - break; - } - - nm_assert(ptr < __stop_connection_defaults); - } -#endif - - _match_section_infos_lookup(&priv->connection_infos[0], - priv->keyfile, - property, - device, - NULL, - NULL, - &value); - return value; -} - -gint64 -nm_config_data_get_connection_default_int64(const NMConfigData *self, - const char * property, - NMDevice * device, - gint64 min, - gint64 max, - gint64 fallback) -{ - gs_free char *value = NULL; - - value = nm_config_data_get_connection_default(self, property, device); - return _nm_utils_ascii_str_to_int64(value, 10, min, max, fallback); -} - -static void -_get_connection_info_init(MatchSectionInfo *connection_info, GKeyFile *keyfile, char *group) -{ - /* pass ownership of @group on... */ - connection_info->group_name = group; - - connection_info->match_device.spec = - nm_config_get_match_spec(keyfile, - group, - NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE, - &connection_info->match_device.has); - connection_info->stop_match = - nm_config_keyfile_get_boolean(keyfile, group, NM_CONFIG_KEYFILE_KEY_STOP_MATCH, FALSE); -} - -static void -_match_section_infos_free(MatchSectionInfo *match_section_infos) -{ - guint i; - - if (!match_section_infos) - return; - for (i = 0; match_section_infos[i].group_name; i++) { - g_free(match_section_infos[i].group_name); - g_slist_free_full(match_section_infos[i].match_device.spec, g_free); - } - g_free(match_section_infos); -} - -static MatchSectionInfo * -_match_section_infos_construct(GKeyFile *keyfile, const char *prefix) -{ - char ** groups; - gsize i, j, ngroups; - char * connection_tag = NULL; - MatchSectionInfo *match_section_infos = NULL; - - /* get the list of existing [connection.\+]/[device.\+] sections. - * - * We expect the sections in their right order, with lowest priority - * first. Only exception is the (literal) [connection] section, which - * we will always reorder to the end. */ - groups = g_key_file_get_groups(keyfile, &ngroups); - if (!groups) - return NULL; - - if (ngroups > 0) { - gsize l = strlen(prefix); - - for (i = 0, j = 0; i < ngroups; i++) { - if (g_str_has_prefix(groups[i], prefix)) { - if (groups[i][l] == '\0') - connection_tag = groups[i]; - else - groups[j++] = groups[i]; - } else - g_free(groups[i]); - } - ngroups = j; - } - - if (ngroups == 0 && !connection_tag) { - g_free(groups); - return NULL; - } - - match_section_infos = g_new0(MatchSectionInfo, ngroups + 1 + (connection_tag ? 1 : 0)); - for (i = 0; i < ngroups; i++) { - /* pass ownership of @group on... */ - _get_connection_info_init(&match_section_infos[i], keyfile, groups[ngroups - i - 1]); - } - if (connection_tag) { - /* pass ownership of @connection_tag on... */ - _get_connection_info_init(&match_section_infos[i], keyfile, connection_tag); - } - g_free(groups); - - return match_section_infos; -} - -/*****************************************************************************/ - -NMConfigChangeFlags -nm_config_data_diff(NMConfigData *old_data, NMConfigData *new_data) -{ - NMConfigChangeFlags changes = NM_CONFIG_CHANGE_NONE; - NMConfigDataPrivate *priv_old, *priv_new; - - g_return_val_if_fail(NM_IS_CONFIG_DATA(old_data), NM_CONFIG_CHANGE_NONE); - g_return_val_if_fail(NM_IS_CONFIG_DATA(new_data), NM_CONFIG_CHANGE_NONE); - - priv_old = NM_CONFIG_DATA_GET_PRIVATE(old_data); - priv_new = NM_CONFIG_DATA_GET_PRIVATE(new_data); - - if (!_nm_keyfile_equals(priv_old->keyfile_user, priv_new->keyfile_user, TRUE)) - changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_USER; - - if (!_nm_keyfile_equals(priv_old->keyfile_intern, priv_new->keyfile_intern, TRUE)) - changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN; - - if (g_strcmp0(nm_config_data_get_config_main_file(old_data), - nm_config_data_get_config_main_file(new_data)) - != 0 - || g_strcmp0(nm_config_data_get_config_description(old_data), - nm_config_data_get_config_description(new_data)) - != 0) - changes |= NM_CONFIG_CHANGE_CONFIG_FILES; - - if (nm_config_data_get_connectivity_enabled(old_data) - != nm_config_data_get_connectivity_enabled(new_data) - || nm_config_data_get_connectivity_interval(old_data) - != nm_config_data_get_connectivity_interval(new_data) - || g_strcmp0(nm_config_data_get_connectivity_uri(old_data), - nm_config_data_get_connectivity_uri(new_data)) - || g_strcmp0(nm_config_data_get_connectivity_response(old_data), - nm_config_data_get_connectivity_response(new_data))) - changes |= NM_CONFIG_CHANGE_CONNECTIVITY; - - if (nm_utils_g_slist_strlist_cmp(priv_old->no_auto_default.specs, - priv_new->no_auto_default.specs) - != 0 - || nm_utils_g_slist_strlist_cmp(priv_old->no_auto_default.specs_config, - priv_new->no_auto_default.specs_config) - != 0) - changes |= NM_CONFIG_CHANGE_NO_AUTO_DEFAULT; - - if (g_strcmp0(nm_config_data_get_dns_mode(old_data), nm_config_data_get_dns_mode(new_data))) - changes |= NM_CONFIG_CHANGE_DNS_MODE; - - if (g_strcmp0(nm_config_data_get_rc_manager(old_data), nm_config_data_get_rc_manager(new_data))) - changes |= NM_CONFIG_CHANGE_RC_MANAGER; - - if (!global_dns_equal(priv_old->global_dns, priv_new->global_dns)) - changes |= NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG; - - nm_assert(!NM_FLAGS_ANY(changes, NM_CONFIG_CHANGE_CAUSES)); - - return changes; -} - -/*****************************************************************************/ - -void -nm_config_data_get_warnings(const NMConfigData *self, GPtrArray *warnings) -{ - gboolean invalid; - - nm_assert(NM_IS_CONFIG_DATA(self)); - nm_assert(warnings); - - _config_data_get_main_auth_polkit(self, &invalid); - if (invalid) { - g_ptr_array_add( - warnings, - g_strdup_printf( - "invalid setting for %s.%s (should be one of \"true\", \"false\", \"root-only\")", - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT)); - } -} - -/*****************************************************************************/ - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMConfigData *self = NM_CONFIG_DATA(object); - - switch (prop_id) { - case PROP_CONFIG_MAIN_FILE: - g_value_set_string(value, nm_config_data_get_config_main_file(self)); - break; - case PROP_CONFIG_DESCRIPTION: - g_value_set_string(value, nm_config_data_get_config_description(self)); - break; - case PROP_CONNECTIVITY_ENABLED: - g_value_set_boolean(value, nm_config_data_get_connectivity_enabled(self)); - break; - case PROP_CONNECTIVITY_URI: - g_value_set_string(value, nm_config_data_get_connectivity_uri(self)); - break; - case PROP_CONNECTIVITY_INTERVAL: - g_value_set_uint(value, nm_config_data_get_connectivity_interval(self)); - break; - case PROP_CONNECTIVITY_RESPONSE: - g_value_set_string(value, nm_config_data_get_connectivity_response(self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMConfigData * self = NM_CONFIG_DATA(object); - NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE(self); - - switch (prop_id) { - case PROP_CONFIG_MAIN_FILE: - /* construct-only */ - priv->config_main_file = g_value_dup_string(value); - break; - case PROP_CONFIG_DESCRIPTION: - /* construct-only */ - priv->config_description = g_value_dup_string(value); - break; - case PROP_KEYFILE_USER: - /* construct-only */ - priv->keyfile_user = g_value_dup_boxed(value); - if (priv->keyfile_user && !_nm_keyfile_has_values(priv->keyfile_user)) { - g_key_file_unref(priv->keyfile_user); - priv->keyfile_user = NULL; - } - break; - case PROP_KEYFILE_INTERN: - /* construct-only */ - priv->keyfile_intern = g_value_dup_boxed(value); - if (priv->keyfile_intern && !_nm_keyfile_has_values(priv->keyfile_intern)) { - g_key_file_unref(priv->keyfile_intern); - priv->keyfile_intern = NULL; - } - break; - case PROP_NO_AUTO_DEFAULT: - /* construct-only */ - { - const char *const * value_arr_orig = g_value_get_boxed(value); - gs_free const char **value_arr = NULL; - GSList * specs = NULL; - gsize i, j; - gsize len; - - len = NM_PTRARRAY_LEN(value_arr_orig); - - /* sort entries, remove duplicates and empty words. */ - value_arr = - len == 0 ? NULL : nm_memdup(value_arr_orig, sizeof(const char *) * (len + 1)); - nm_utils_strv_sort(value_arr, len); - _nm_utils_strv_cleanup((char **) value_arr, FALSE, TRUE, TRUE); - - len = NM_PTRARRAY_LEN(value_arr); - j = 0; - for (i = 0; i < len; i++) { - const char *s = value_arr[i]; - gboolean is_mac; - char * spec; - - if (NM_STR_HAS_PREFIX(s, NM_MATCH_SPEC_INTERFACE_NAME_TAG "=")) - is_mac = FALSE; - else if (nm_utils_hwaddr_valid(s, -1)) - is_mac = TRUE; - else { - /* we drop all lines that we don't understand. */ - continue; - } - - value_arr[j++] = s; - - spec = is_mac ? g_strdup_printf(NM_MATCH_SPEC_MAC_TAG "%s", s) : g_strdup(s); - specs = g_slist_prepend(specs, spec); - } - - priv->no_auto_default.arr = nm_utils_strv_dup(value_arr, j, TRUE); - priv->no_auto_default.specs = g_slist_reverse(specs); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/*****************************************************************************/ - -static void -nm_config_data_init(NMConfigData *self) -{} - -static void -constructed(GObject *object) -{ - NMConfigData * self = NM_CONFIG_DATA(object); - NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE(self); - char * str; - - priv->keyfile = _merge_keyfiles(priv->keyfile_user, priv->keyfile_intern); - - priv->connection_infos = - _match_section_infos_construct(priv->keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); - priv->device_infos = - _match_section_infos_construct(priv->keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); - - priv->connectivity.enabled = - nm_config_keyfile_get_boolean(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, - NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_ENABLED, - TRUE); - priv->connectivity.uri = - nm_strstrip(g_key_file_get_string(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, - NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_URI, - NULL)); - priv->connectivity.response = g_key_file_get_string(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, - NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_RESPONSE, - NULL); - str = nm_config_keyfile_get_value(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_AUTOCONNECT_RETRIES_DEFAULT, - NM_CONFIG_GET_VALUE_NONE); - priv->autoconnect_retries_default = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXINT32, 4); - g_free(str); - - /* On missing config value, fallback to 300. On invalid value, disable connectivity checking by setting - * the interval to zero. */ - str = g_key_file_get_string(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, - NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_INTERVAL, - NULL); - priv->connectivity.interval = - _nm_utils_ascii_str_to_int64(str, - 10, - 0, - G_MAXUINT, - NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL); - g_free(str); - - priv->dns_mode = nm_strstrip(g_key_file_get_string(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_DNS, - NULL)); - priv->rc_manager = nm_strstrip(g_key_file_get_string(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_RC_MANAGER, - NULL)); - priv->systemd_resolved = - nm_config_keyfile_get_boolean(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_SYSTEMD_RESOLVED, - TRUE); - priv->ignore_carrier = nm_config_get_match_spec(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_IGNORE_CARRIER, - NULL); - priv->assume_ipv6ll_only = - nm_config_get_match_spec(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_ASSUME_IPV6LL_ONLY, - NULL); - priv->no_auto_default.specs_config = - nm_config_get_match_spec(priv->keyfile, - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_NO_AUTO_DEFAULT, - NULL); - - priv->global_dns = load_global_dns(priv->keyfile_user, FALSE); - if (!priv->global_dns) - priv->global_dns = load_global_dns(priv->keyfile_intern, TRUE); - - G_OBJECT_CLASS(nm_config_data_parent_class)->constructed(object); -} - -NMConfigData * -nm_config_data_new(const char * config_main_file, - const char * config_description, - const char *const *no_auto_default, - GKeyFile * keyfile_user, - GKeyFile * keyfile_intern) -{ - return g_object_new(NM_TYPE_CONFIG_DATA, - NM_CONFIG_DATA_CONFIG_MAIN_FILE, - config_main_file, - NM_CONFIG_DATA_CONFIG_DESCRIPTION, - config_description, - NM_CONFIG_DATA_KEYFILE_USER, - keyfile_user, - NM_CONFIG_DATA_KEYFILE_INTERN, - keyfile_intern, - NM_CONFIG_DATA_NO_AUTO_DEFAULT, - no_auto_default, - NULL); -} - -NMConfigData * -nm_config_data_new_update_keyfile_intern(const NMConfigData *base, GKeyFile *keyfile_intern) -{ - const NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE(base); - - return g_object_new(NM_TYPE_CONFIG_DATA, - NM_CONFIG_DATA_CONFIG_MAIN_FILE, - priv->config_main_file, - NM_CONFIG_DATA_CONFIG_DESCRIPTION, - priv->config_description, - NM_CONFIG_DATA_KEYFILE_USER, - priv->keyfile_user, /* the keyfile is unchanged. It's safe to share it. */ - NM_CONFIG_DATA_KEYFILE_INTERN, - keyfile_intern, - NM_CONFIG_DATA_NO_AUTO_DEFAULT, - priv->no_auto_default.arr, - NULL); -} - -NMConfigData * -nm_config_data_new_update_no_auto_default(const NMConfigData *base, - const char *const * no_auto_default) -{ - const NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE(base); - - return g_object_new(NM_TYPE_CONFIG_DATA, - NM_CONFIG_DATA_CONFIG_MAIN_FILE, - priv->config_main_file, - NM_CONFIG_DATA_CONFIG_DESCRIPTION, - priv->config_description, - NM_CONFIG_DATA_KEYFILE_USER, - priv->keyfile_user, /* the keyfile is unchanged. It's safe to share it. */ - NM_CONFIG_DATA_KEYFILE_INTERN, - priv->keyfile_intern, - NM_CONFIG_DATA_NO_AUTO_DEFAULT, - no_auto_default, - NULL); -} - -static void -finalize(GObject *gobject) -{ - NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE(gobject); - - g_free(priv->config_main_file); - g_free(priv->config_description); - - g_free(priv->connectivity.uri); - g_free(priv->connectivity.response); - - g_slist_free_full(priv->no_auto_default.specs, g_free); - g_slist_free_full(priv->no_auto_default.specs_config, g_free); - g_strfreev(priv->no_auto_default.arr); - - g_free(priv->dns_mode); - g_free(priv->rc_manager); - - g_slist_free_full(priv->ignore_carrier, g_free); - g_slist_free_full(priv->assume_ipv6ll_only, g_free); - - nm_global_dns_config_free(priv->global_dns); - - _match_section_infos_free(priv->connection_infos); - _match_section_infos_free(priv->device_infos); - - g_key_file_unref(priv->keyfile); - if (priv->keyfile_user) - g_key_file_unref(priv->keyfile_user); - if (priv->keyfile_intern) - g_key_file_unref(priv->keyfile_intern); - - G_OBJECT_CLASS(nm_config_data_parent_class)->finalize(gobject); -} - -static void -nm_config_data_class_init(NMConfigDataClass *config_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(config_class); - - object_class->constructed = constructed; - object_class->finalize = finalize; - object_class->get_property = get_property; - object_class->set_property = set_property; - - obj_properties[PROP_CONFIG_MAIN_FILE] = - g_param_spec_string(NM_CONFIG_DATA_CONFIG_MAIN_FILE, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONFIG_DESCRIPTION] = - g_param_spec_string(NM_CONFIG_DATA_CONFIG_DESCRIPTION, - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_KEYFILE_USER] = - g_param_spec_boxed(NM_CONFIG_DATA_KEYFILE_USER, - "", - "", - G_TYPE_KEY_FILE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_KEYFILE_INTERN] = - g_param_spec_boxed(NM_CONFIG_DATA_KEYFILE_INTERN, - "", - "", - G_TYPE_KEY_FILE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY_ENABLED] = - g_param_spec_string(NM_CONFIG_DATA_CONNECTIVITY_ENABLED, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY_URI] = - g_param_spec_string(NM_CONFIG_DATA_CONNECTIVITY_URI, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY_INTERVAL] = - g_param_spec_uint(NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, - "", - "", - 0, - G_MAXUINT, - 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_CONNECTIVITY_RESPONSE] = - g_param_spec_string(NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, - "", - "", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_NO_AUTO_DEFAULT] = - g_param_spec_boxed(NM_CONFIG_DATA_NO_AUTO_DEFAULT, - "", - "", - G_TYPE_STRV, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} |