1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager -- Network link manager
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Copyright (C) 2011 Red Hat, Inc.
19 * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de>
22 #include "nm-default.h"
27 #include "nm-config.h"
29 #include "nm-device.h"
30 #include "NetworkManagerUtils.h"
31 #include "nm-enum-types.h"
32 #include "nm-core-internal.h"
33 #include "nm-keyfile-internal.h"
35 #define DEFAULT_CONFIG_MAIN_FILE NMCONFDIR "/NetworkManager.conf"
36 #define DEFAULT_CONFIG_DIR NMCONFDIR "/conf.d"
37 #define DEFAULT_CONFIG_MAIN_FILE_OLD NMCONFDIR "/nm-system-settings.conf"
38 #define DEFAULT_SYSTEM_CONFIG_DIR NMLIBDIR "/conf.d"
39 #define DEFAULT_NO_AUTO_DEFAULT_FILE NMSTATEDIR "/no-auto-default.state"
40 #define DEFAULT_INTERN_CONFIG_FILE NMSTATEDIR "/NetworkManager-intern.conf"
42 struct NMConfigCmdLineOptions {
43 char *config_main_file;
44 char *intern_config_file;
46 char *system_config_dir;
47 char *no_auto_default_file;
49 gboolean configure_and_quit;
51 char *connectivity_uri;
53 /* We store interval as signed internally to track whether it's
54 * set or not via GOptionEntry
56 int connectivity_interval;
57 char *connectivity_response;
61 NMConfigCmdLineOptions cli;
63 NMConfigData *config_data;
64 NMConfigData *config_data_orig;
67 char *system_config_dir;
68 char *no_auto_default_file;
69 char *intern_config_file;
72 gboolean monitor_connection_files;
81 gboolean configure_and_quit;
83 char **atomic_section_prefixes;
88 PROP_CMD_LINE_OPTIONS,
89 PROP_ATOMIC_SECTION_PREFIXES,
94 SIGNAL_CONFIG_CHANGED,
99 static guint signals[LAST_SIGNAL] = { 0 };
101 static void nm_config_initable_iface_init (GInitableIface *iface);
103 G_DEFINE_TYPE_WITH_CODE (NMConfig, nm_config, G_TYPE_OBJECT,
104 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_config_initable_iface_init);
108 #define NM_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG, NMConfigPrivate))
110 /************************************************************************/
112 static void _set_config_data (NMConfig *self, NMConfigData *new_data, int signal);
114 /************************************************************************/
116 #define _HAS_PREFIX(str, prefix) \
118 const char *_str = (str); \
119 g_str_has_prefix ( _str, ""prefix"") && _str[NM_STRLEN(prefix)] != '\0'; \
122 /************************************************************************/
125 nm_config_parse_boolean (const char *str,
128 return nm_utils_ascii_str_to_bool (str, default_value);
132 nm_config_keyfile_get_boolean (GKeyFile *keyfile,
137 gs_free char *str = NULL;
139 g_return_val_if_fail (keyfile != NULL, default_value);
140 g_return_val_if_fail (section != NULL, default_value);
141 g_return_val_if_fail (key != NULL, default_value);
143 str = g_key_file_get_value (keyfile, section, key, NULL);
144 return nm_config_parse_boolean (str, default_value);
148 nm_config_keyfile_get_value (GKeyFile *keyfile,
151 NMConfigGetValueFlags flags)
155 if (NM_FLAGS_HAS (flags, NM_CONFIG_GET_VALUE_RAW))
156 value = g_key_file_get_value (keyfile, section, key, NULL);
158 value = g_key_file_get_string (keyfile, section, key, NULL);
163 if (NM_FLAGS_HAS (flags, NM_CONFIG_GET_VALUE_STRIP))
166 if ( NM_FLAGS_HAS (flags, NM_CONFIG_GET_VALUE_NO_EMPTY)
176 nm_config_keyfile_set_string_list (GKeyFile *keyfile,
179 const char *const* strv,
186 len = strv ? g_strv_length ((char **) strv) : 0;
188 g_key_file_set_string_list (keyfile, group, key, strv, len);
190 /* g_key_file_set_string_list() appends a trailing separator to the value.
191 * We don't like that, get rid of it. */
193 new_value = g_key_file_get_value (keyfile, group, key, NULL);
197 l = strlen (new_value);
198 if (l > 0 && new_value[l - 1] == NM_CONFIG_KEYFILE_LIST_SEPARATOR) {
199 /* Maybe we should check that value doesn't end with "\\,", i.e.
200 * with an escaped separator. But the way g_key_file_set_string_list()
201 * is implemented (currently), it always adds a trailing separator. */
202 new_value[l - 1] = '\0';
203 g_key_file_set_value (keyfile, group, key, new_value);
208 /************************************************************************/
211 nm_config_get_data (NMConfig *config)
213 g_return_val_if_fail (config != NULL, NULL);
215 return NM_CONFIG_GET_PRIVATE (config)->config_data;
218 /* The NMConfigData instance is reloadable and will be swapped on reload.
219 * nm_config_get_data_orig() returns the original configuration, when the NMConfig
220 * instance was created. */
222 nm_config_get_data_orig (NMConfig *config)
224 g_return_val_if_fail (config != NULL, NULL);
226 return NM_CONFIG_GET_PRIVATE (config)->config_data_orig;
230 nm_config_get_plugins (NMConfig *config)
232 g_return_val_if_fail (config != NULL, NULL);
234 return (const char **) NM_CONFIG_GET_PRIVATE (config)->plugins;
238 nm_config_get_monitor_connection_files (NMConfig *config)
240 g_return_val_if_fail (config != NULL, FALSE);
242 return NM_CONFIG_GET_PRIVATE (config)->monitor_connection_files;
246 nm_config_get_auth_polkit (NMConfig *config)
248 g_return_val_if_fail (NM_IS_CONFIG (config), NM_CONFIG_DEFAULT_AUTH_POLKIT);
250 return NM_CONFIG_GET_PRIVATE (config)->auth_polkit;
254 nm_config_get_dhcp_client (NMConfig *config)
256 g_return_val_if_fail (config != NULL, NULL);
258 return NM_CONFIG_GET_PRIVATE (config)->dhcp_client;
262 nm_config_get_log_level (NMConfig *config)
264 g_return_val_if_fail (config != NULL, NULL);
266 return NM_CONFIG_GET_PRIVATE (config)->log_level;
270 nm_config_get_log_domains (NMConfig *config)
272 g_return_val_if_fail (config != NULL, NULL);
274 return NM_CONFIG_GET_PRIVATE (config)->log_domains;
278 nm_config_get_debug (NMConfig *config)
280 g_return_val_if_fail (config != NULL, NULL);
282 return NM_CONFIG_GET_PRIVATE (config)->debug;
286 nm_config_get_configure_and_quit (NMConfig *config)
288 return NM_CONFIG_GET_PRIVATE (config)->configure_and_quit;
292 nm_config_get_is_debug (NMConfig *config)
294 return NM_CONFIG_GET_PRIVATE (config)->cli.is_debug;
297 /************************************************************************/
300 no_auto_default_from_file (const char *no_auto_default_file)
302 GPtrArray *no_auto_default_new;
307 no_auto_default_new = g_ptr_array_new ();
309 if ( no_auto_default_file
310 && g_file_get_contents (no_auto_default_file, &data, NULL, NULL)) {
311 list = g_strsplit (data, "\n", -1);
312 for (i = 0; list[i]; i++) {
314 && nm_utils_hwaddr_valid (list[i], -1)
315 && _nm_utils_strv_find_first (list, i, list[i]) < 0)
316 g_ptr_array_add (no_auto_default_new, list[i]);
324 g_ptr_array_add (no_auto_default_new, NULL);
325 return (char **) g_ptr_array_free (no_auto_default_new, FALSE);
329 no_auto_default_to_file (const char *no_auto_default_file, const char *const*no_auto_default, GError **error)
335 data = g_string_new ("");
336 for (i = 0; no_auto_default && no_auto_default[i]; i++) {
337 g_string_append (data, no_auto_default[i]);
338 g_string_append_c (data, '\n');
340 success = g_file_set_contents (no_auto_default_file, data->str, data->len, error);
341 g_string_free (data, TRUE);
346 nm_config_get_no_auto_default_for_device (NMConfig *self, NMDevice *device)
348 g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
350 return nm_config_data_get_no_auto_default_for_device (NM_CONFIG_GET_PRIVATE (self)->config_data, device);
354 nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device)
356 NMConfigPrivate *priv;
357 GError *error = NULL;
358 NMConfigData *new_data = NULL;
359 const char *hw_address;
360 const char *const*no_auto_default_current;
361 GPtrArray *no_auto_default_new = NULL;
364 g_return_if_fail (NM_IS_CONFIG (self));
365 g_return_if_fail (NM_IS_DEVICE (device));
367 priv = NM_CONFIG_GET_PRIVATE (self);
369 hw_address = nm_device_get_hw_address (device);
371 no_auto_default_current = nm_config_data_get_no_auto_default (priv->config_data);
373 if (_nm_utils_strv_find_first ((char **) no_auto_default_current, -1, hw_address) >= 0) {
374 /* @hw_address is already blocked. We don't have to update our in-memory representation.
375 * Maybe we should write to no_auto_default_file anew, but let's save that too. */
379 no_auto_default_new = g_ptr_array_new ();
380 for (i = 0; no_auto_default_current && no_auto_default_current[i]; i++)
381 g_ptr_array_add (no_auto_default_new, (char *) no_auto_default_current[i]);
382 g_ptr_array_add (no_auto_default_new, (char *) hw_address);
383 g_ptr_array_add (no_auto_default_new, NULL);
385 if (!no_auto_default_to_file (priv->no_auto_default_file, (const char *const*) no_auto_default_new->pdata, &error)) {
386 nm_log_warn (LOGD_SETTINGS, "Could not update no-auto-default.state file: %s",
388 g_error_free (error);
391 new_data = nm_config_data_new_update_no_auto_default (priv->config_data, (const char *const*) no_auto_default_new->pdata);
393 /* unref no_auto_default_set here. Note that _set_config_data() probably invalidates the content of the array. */
394 g_ptr_array_unref (no_auto_default_new);
396 _set_config_data (self, new_data, 0);
399 /************************************************************************/
402 _nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli)
404 g_clear_pointer (&cli->config_main_file, g_free);
405 g_clear_pointer (&cli->config_dir, g_free);
406 g_clear_pointer (&cli->system_config_dir, g_free);
407 g_clear_pointer (&cli->no_auto_default_file, g_free);
408 g_clear_pointer (&cli->intern_config_file, g_free);
409 g_clear_pointer (&cli->plugins, g_free);
410 cli->configure_and_quit = FALSE;
411 cli->is_debug = FALSE;
412 g_clear_pointer (&cli->connectivity_uri, g_free);
413 g_clear_pointer (&cli->connectivity_response, g_free);
414 cli->connectivity_interval = -1;
418 _nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmdLineOptions *dst)
420 g_return_if_fail (cli);
421 g_return_if_fail (dst);
422 g_return_if_fail (cli != dst);
424 _nm_config_cmd_line_options_clear (dst);
425 dst->config_dir = g_strdup (cli->config_dir);
426 dst->system_config_dir = g_strdup (cli->system_config_dir);
427 dst->config_main_file = g_strdup (cli->config_main_file);
428 dst->no_auto_default_file = g_strdup (cli->no_auto_default_file);
429 dst->intern_config_file = g_strdup (cli->intern_config_file);
430 dst->plugins = g_strdup (cli->plugins);
431 dst->configure_and_quit = cli->configure_and_quit;
432 dst->is_debug = cli->is_debug;
433 dst->connectivity_uri = g_strdup (cli->connectivity_uri);
434 dst->connectivity_response = g_strdup (cli->connectivity_response);
435 dst->connectivity_interval = cli->connectivity_interval;
438 NMConfigCmdLineOptions *
439 nm_config_cmd_line_options_new ()
441 NMConfigCmdLineOptions *cli = g_new0 (NMConfigCmdLineOptions, 1);
443 _nm_config_cmd_line_options_clear (cli);
448 nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli)
450 g_return_if_fail (cli);
452 _nm_config_cmd_line_options_clear (cli);
457 nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli,
458 GOptionContext *opt_ctx)
460 g_return_if_fail (opt_ctx);
461 g_return_if_fail (cli);
464 GOptionEntry config_options[] = {
465 { "config", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_main_file, N_("Config file location"), N_(DEFAULT_CONFIG_MAIN_FILE) },
466 { "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_dir, N_("Config directory location"), N_(DEFAULT_CONFIG_DIR) },
467 { "system-config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->system_config_dir, N_("System config directory location"), N_(DEFAULT_SYSTEM_CONFIG_DIR) },
468 { "intern-config", 0, 0, G_OPTION_ARG_FILENAME, &cli->intern_config_file, N_("Internal config file location"), N_(DEFAULT_INTERN_CONFIG_FILE) },
469 { "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli->no_auto_default_file, N_("State file for no-auto-default devices"), N_(DEFAULT_NO_AUTO_DEFAULT_FILE) },
470 { "plugins", 0, 0, G_OPTION_ARG_STRING, &cli->plugins, N_("List of plugins separated by ','"), N_(CONFIG_PLUGINS_DEFAULT) },
471 { "configure-and-quit", 0, 0, G_OPTION_ARG_NONE, &cli->configure_and_quit, N_("Quit after initial configuration"), NULL },
472 { "debug", 'd', 0, G_OPTION_ARG_NONE, &cli->is_debug, N_("Don't become a daemon, and log to stderr"), NULL },
474 /* These three are hidden for now, and should eventually just go away. */
475 { "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" },
476 { "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli->connectivity_interval, N_("The interval between connectivity checks (in seconds)"), G_STRINGIFY (NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL) },
477 { "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_response, N_("The expected start of the response"), N_(NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE) },
481 g_option_context_add_main_entries (opt_ctx, config_options, NULL);
485 /************************************************************************/
488 nm_config_create_keyfile ()
492 keyfile = g_key_file_new ();
493 g_key_file_set_list_separator (keyfile, NM_CONFIG_KEYFILE_LIST_SEPARATOR);
497 /* this is an external variable, to make loading testable. Other then that,
498 * no code is supposed to change this. */
499 guint _nm_config_match_nm_version = NM_VERSION_CUR_STABLE;
500 char *_nm_config_match_env = NULL;
503 ignore_config_snippet (GKeyFile *keyfile, gboolean is_base_config)
507 NMMatchSpecMatchType match_type;
512 if (!g_key_file_has_key (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, NULL))
515 /* first, let's try to parse the value as plain boolean. If that is possible, we don't treat
516 * the value as match-spec. */
517 as_bool = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, -1);
521 if (G_UNLIKELY (!_nm_config_match_env)) {
524 e = g_getenv ("NM_CONFIG_ENABLE_TAG");
525 _nm_config_match_env = g_strdup (e ? e : "");
528 /* second, interpret the value as match-spec. */
529 specs = nm_config_get_match_spec (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, NULL);
530 match_type = nm_match_spec_match_config (specs,
531 _nm_config_match_nm_version,
532 _nm_config_match_env);
533 g_slist_free_full (specs, g_free);
535 return match_type != NM_MATCH_SPEC_MATCH;
539 _sort_groups_cmp (const char **pa, const char **pb, gpointer dummy)
542 gboolean a_is_connection, b_is_connection;
544 /* basic NULL checking... */
555 a_is_connection = g_str_has_prefix (a, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION);
556 b_is_connection = g_str_has_prefix (b, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION);
558 if (a_is_connection != b_is_connection) {
559 /* one is a [connection*] entry, the other not. We sort [connection*] entires
565 if (!a_is_connection) {
566 /* both are non-connection entries. Don't reorder. */
570 /* both are [connection.\+] entires. Reverse their order.
571 * One of the sections might be literally [connection]. That section
572 * is special and it's order will be fixed later. It doesn't actually
573 * matter here how it compares with [connection.\+] sections. */
574 return pa > pb ? -1 : 1;
578 _nm_config_sort_groups (char **groups, gsize ngroups)
581 g_qsort_with_data (groups,
584 (GCompareDataFunc) _sort_groups_cmp,
590 _setting_is_device_spec (const char *group, const char *key)
592 #define _IS(group_v, key_v) (strcmp (group, (""group_v)) == 0 && strcmp (key, (""key_v)) == 0)
593 return _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "no-auto-default")
594 || _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "ignore-carrier")
595 || _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "assume-ipv6ll-only")
596 || _IS (NM_CONFIG_KEYFILE_GROUP_KEYFILE, "unmanaged-devices")
597 || (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION) && !strcmp (key, "match-device"));
601 _setting_is_string_list (const char *group, const char *key)
603 return _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins")
604 || _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "debug")
605 || _IS (NM_CONFIG_KEYFILE_GROUP_LOGGING, "domains")
606 || g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST);
611 read_config (GKeyFile *keyfile, gboolean is_base_config, const char *dirname, const char *path, GError **error)
614 char **groups, **keys;
615 gsize ngroups, nkeys;
617 gs_free char *path_free = NULL;
619 g_return_val_if_fail (keyfile, FALSE);
620 g_return_val_if_fail (path, FALSE);
621 g_return_val_if_fail (!error || !*error, FALSE);
624 path_free = g_build_filename (dirname, path, NULL);
628 if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) {
629 g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "file %s not found", path);
633 nm_log_dbg (LOGD_SETTINGS, "Reading config file '%s'", path);
635 kf = nm_config_create_keyfile ();
636 if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) {
637 g_key_file_free (kf);
641 if (ignore_config_snippet (kf, is_base_config)) {
642 g_key_file_free (kf);
646 /* the config-group is internal to every configuration snippets. It doesn't make sense
647 * to merge the into the global configuration, and it doesn't make sense to preserve the
648 * group beyond this point. */
649 g_key_file_remove_group (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NULL);
651 /* Override the current settings with the new ones */
652 groups = g_key_file_get_groups (kf, &ngroups);
656 /* Within one file we reverse the order of the '[connection.\+] sections.
657 * Here we merge the current file (@kf) into @keyfile. As we merge multiple
658 * files, earlier sections (with lower priority) will be added first.
659 * But within one file, we want a top-to-bottom order. This means we
660 * must reverse the order within each file.
661 * At the very end, we will revert the order of all sections again and
662 * get thus the right behavior. This final reversing is done in
663 * NMConfigData:_get_connection_infos(). */
664 _nm_config_sort_groups (groups, ngroups);
666 for (g = 0; groups && groups[g]; g++) {
667 const char *group = groups[g];
669 if (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN)) {
670 /* internal groups cannot be set by user configuration. */
673 keys = g_key_file_get_keys (kf, group, &nkeys, NULL);
676 for (k = 0; keys[k]; k++) {
683 g_assert (key && *key);
685 if ( _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)
686 || _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) {
687 /* these keys are protected. We ignore them if the user sets them. */
691 if (!strcmp (key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS)) {
692 /* the "was" key is protected and it cannot be set by user configuration. */
696 key_len = strlen (key);
697 last_char = key[key_len - 1];
699 && (last_char == '+' || last_char == '-')) {
700 gs_free char *base_key = g_strndup (key, key_len - 1);
701 gboolean is_string_list;
703 is_string_list = _setting_is_string_list (group, base_key);
706 || _setting_is_device_spec (group, base_key)) {
707 gs_unref_ptrarray GPtrArray *new = g_ptr_array_new_with_free_func (g_free);
709 gs_strfreev char **old_val = NULL;
710 gs_free char **new_val = NULL;
712 if (is_string_list) {
713 old_val = g_key_file_get_string_list (keyfile, group, base_key, NULL, NULL);
714 new_val = g_key_file_get_string_list (kf, group, key, NULL, NULL);
716 gs_free char *old_sval = nm_config_keyfile_get_value (keyfile, group, base_key, NM_CONFIG_GET_VALUE_TYPE_SPEC);
717 gs_free char *new_sval = nm_config_keyfile_get_value (kf, group, key, NM_CONFIG_GET_VALUE_TYPE_SPEC);
718 gs_free_slist GSList *old_specs = nm_match_spec_split (old_sval);
719 gs_free_slist GSList *new_specs = nm_match_spec_split (new_sval);
721 /* the key is a device spec. This is a special kind of string-list, that
722 * we must split differently. */
723 old_val = _nm_utils_slist_to_strv (old_specs, FALSE);
724 new_val = _nm_utils_slist_to_strv (new_specs, FALSE);
727 /* merge the string lists, by omiting duplicates. */
729 for (iter_val = old_val; iter_val && *iter_val; iter_val++) {
730 if ( last_char != '-'
731 || _nm_utils_strv_find_first (new_val, -1, *iter_val) < 0)
732 g_ptr_array_add (new, g_strdup (*iter_val));
734 for (iter_val = new_val; iter_val && *iter_val; iter_val++) {
735 /* don't add duplicates. That means an "option=a,b"; "option+=a,c" results in "option=a,b,c" */
736 if ( last_char == '+'
737 && _nm_utils_strv_find_first (old_val, -1, *iter_val) < 0)
738 g_ptr_array_add (new, *iter_val);
745 nm_config_keyfile_set_string_list (keyfile, group, base_key, (const char *const*) new->pdata, new->len);
747 gs_free_slist GSList *specs = NULL;
748 gs_free char *specs_joined = NULL;
750 g_ptr_array_add (new, NULL);
751 specs = _nm_utils_strv_to_slist ((char **) new->pdata, FALSE);
753 specs_joined = nm_match_spec_join (specs);
755 g_key_file_set_value (keyfile, group, base_key, specs_joined);
759 g_key_file_remove_key (keyfile, group, base_key, NULL);
761 g_key_file_set_value (keyfile, group, base_key, "");
764 /* For any other settings we don't support extending the option with +/-.
765 * Just drop the key. */
770 new_value = g_key_file_get_value (kf, group, key, NULL);
771 g_key_file_set_value (keyfile, group, key, new_value);
777 g_key_file_free (kf);
783 read_base_config (GKeyFile *keyfile,
784 const char *cli_config_main_file,
785 char **out_config_main_file,
788 GError *my_error = NULL;
790 g_return_val_if_fail (keyfile, FALSE);
791 g_return_val_if_fail (out_config_main_file && !*out_config_main_file, FALSE);
792 g_return_val_if_fail (!error || !*error, FALSE);
794 /* Try a user-specified config file first */
795 if (cli_config_main_file) {
796 /* Bad user-specific config file path is a hard error */
797 if (read_config (keyfile, TRUE, NULL, cli_config_main_file, error)) {
798 *out_config_main_file = g_strdup (cli_config_main_file);
804 /* Even though we prefer NetworkManager.conf, we need to check the
805 * old nm-system-settings.conf first to preserve compat with older
806 * setups. In package managed systems dropping a NetworkManager.conf
807 * onto the system would make NM use it instead of nm-system-settings.conf,
808 * changing behavior during an upgrade. We don't want that.
811 /* Try deprecated nm-system-settings.conf first */
812 if (read_config (keyfile, TRUE, NULL, DEFAULT_CONFIG_MAIN_FILE_OLD, &my_error)) {
813 *out_config_main_file = g_strdup (DEFAULT_CONFIG_MAIN_FILE_OLD);
817 if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
818 nm_log_warn (LOGD_CORE, "Old default config file %s invalid: %s\n",
819 DEFAULT_CONFIG_MAIN_FILE_OLD,
822 g_clear_error (&my_error);
824 /* Try the standard config file location next */
825 if (read_config (keyfile, TRUE, NULL, DEFAULT_CONFIG_MAIN_FILE, &my_error)) {
826 *out_config_main_file = g_strdup (DEFAULT_CONFIG_MAIN_FILE);
830 if (!g_error_matches (my_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
831 nm_log_warn (LOGD_CORE, "Default config file %s invalid: %s\n",
832 DEFAULT_CONFIG_MAIN_FILE,
834 g_propagate_error (error, my_error);
837 g_clear_error (&my_error);
839 /* If for some reason no config file exists, use the default
842 *out_config_main_file = g_strdup (DEFAULT_CONFIG_MAIN_FILE);
843 nm_log_info (LOGD_CORE, "No config file found or given; using %s\n",
844 DEFAULT_CONFIG_MAIN_FILE);
849 sort_asciibetically (gconstpointer a, gconstpointer b)
851 const char *s1 = *(const char **)a;
852 const char *s2 = *(const char **)b;
854 return strcmp (s1, s2);
858 _get_config_dir_files (const char *config_dir)
861 GFileEnumerator *direnum;
866 g_return_val_if_fail (config_dir, NULL);
868 confs = g_ptr_array_new_with_free_func (g_free);
872 dir = g_file_new_for_path (config_dir);
873 direnum = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL);
875 while ((info = g_file_enumerator_next_file (direnum, NULL, NULL))) {
876 name = g_file_info_get_name (info);
877 if (g_str_has_suffix (name, ".conf"))
878 g_ptr_array_add (confs, g_strdup (name));
879 g_object_unref (info);
881 g_object_unref (direnum);
883 g_object_unref (dir);
885 g_ptr_array_sort (confs, sort_asciibetically);
890 read_entire_config (const NMConfigCmdLineOptions *cli,
891 const char *config_dir,
892 const char *system_config_dir,
893 char **out_config_main_file,
894 char **out_config_description,
898 gs_unref_ptrarray GPtrArray *system_confs = NULL;
899 gs_unref_ptrarray GPtrArray *confs = NULL;
901 gs_free char *o_config_main_file = NULL;
903 char **plugins_default;
905 g_return_val_if_fail (config_dir, NULL);
906 g_return_val_if_fail (system_config_dir, NULL);
907 g_return_val_if_fail (!out_config_main_file || !*out_config_main_file, FALSE);
908 g_return_val_if_fail (!out_config_description || !*out_config_description, NULL);
909 g_return_val_if_fail (!error || !*error, FALSE);
911 /* create a default configuration file. */
912 keyfile = nm_config_create_keyfile ();
914 plugins_default = g_strsplit (CONFIG_PLUGINS_DEFAULT, ",", -1);
915 if (plugins_default && plugins_default[0])
916 nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", (const char *const*) plugins_default, -1);
917 g_strfreev (plugins_default);
919 system_confs = _get_config_dir_files (system_config_dir);
920 confs = _get_config_dir_files (config_dir);
922 for (i = 0; i < system_confs->len; ) {
923 const char *filename = system_confs->pdata[i];
925 /* if a same named file exists in config_dir, skip it. */
926 if (_nm_utils_strv_find_first ((char **) confs->pdata, confs->len, filename) >= 0) {
927 g_ptr_array_remove_index (system_confs, i);
931 if (!read_config (keyfile, FALSE, system_config_dir, filename, error)) {
932 g_key_file_free (keyfile);
938 /* First read the base config file */
939 if (!read_base_config (keyfile, cli ? cli->config_main_file : NULL, &o_config_main_file, error)) {
940 g_key_file_free (keyfile);
944 g_assert (o_config_main_file);
946 for (i = 0; i < confs->len; i++) {
947 if (!read_config (keyfile, FALSE, config_dir, confs->pdata[i], error)) {
948 g_key_file_free (keyfile);
953 /* Merge settings from command line. They overwrite everything read from
955 if (cli && cli->plugins) {
956 /* plugins is a string list. Set the value directly, so the user has to do proper escaping
957 * on the command line. */
958 g_key_file_set_value (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", cli->plugins);
960 if (cli && cli->configure_and_quit)
961 g_key_file_set_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", TRUE);
962 if (cli && cli->connectivity_uri && cli->connectivity_uri[0])
963 g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "uri", cli->connectivity_uri);
964 if (cli && cli->connectivity_interval >= 0)
965 g_key_file_set_integer (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "interval", cli->connectivity_interval);
966 if (cli && cli->connectivity_response && cli->connectivity_response[0])
967 g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "response", cli->connectivity_response);
969 str = g_string_new (o_config_main_file);
970 if (system_confs->len > 0) {
971 for (i = 0; i < system_confs->len; i++) {
973 g_string_append (str, " (lib: ");
975 g_string_append (str, ", ");
976 g_string_append (str, system_confs->pdata[i]);
978 g_string_append (str, ")");
980 if (confs->len > 0) {
981 for (i = 0; i < confs->len; i++) {
983 g_string_append (str, " (etc: ");
985 g_string_append (str, ", ");
986 g_string_append (str, confs->pdata[i]);
988 g_string_append (str, ")");
991 if (out_config_main_file)
992 *out_config_main_file = o_config_main_file;
994 g_free (o_config_main_file);
995 if (out_config_description)
996 *out_config_description = g_string_free (str, FALSE);
998 g_string_free (str, TRUE);
1000 o_config_main_file = NULL;
1005 _is_atomic_section (const char *const*atomic_section_prefixes, const char *group)
1007 if (atomic_section_prefixes) {
1008 for (; *atomic_section_prefixes; atomic_section_prefixes++) {
1009 if ( **atomic_section_prefixes
1010 && g_str_has_prefix (group, *atomic_section_prefixes))
1018 _string_append_val (GString *str, const char *value)
1022 g_string_append_c (str, '+');
1031 g_string_append_c (str, '+');
1033 g_string_append_c (str, *value);
1040 _keyfile_serialize_section (GKeyFile *keyfile, const char *group)
1042 gs_strfreev char **keys = NULL;
1047 keys = g_key_file_get_keys (keyfile, group, NULL, NULL);
1049 return g_strdup ("0#");
1051 /* prepend a version. */
1052 str = g_string_new ("1#");
1054 for (k = 0; keys[k]; k++) {
1055 const char *key = keys[k];
1056 gs_free char *value = NULL;
1058 _string_append_val (str, key);
1059 g_string_append_c (str, ':');
1061 value = g_key_file_get_value (keyfile, group, key, NULL);
1062 _string_append_val (str, value);
1063 g_string_append_c (str, '#');
1065 return g_string_free (str, FALSE);
1069 nm_config_keyfile_has_global_dns_config (GKeyFile *keyfile, gboolean internal)
1071 gs_strfreev char **groups = NULL;
1077 if (g_key_file_has_group (keyfile,
1079 ? NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS
1080 : NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS))
1083 groups = g_key_file_get_groups (keyfile, NULL);
1087 prefix = internal ? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN : NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN;
1089 for (g = 0; groups[g]; g++) {
1090 if (g_str_has_prefix (groups[g], prefix))
1097 * intern_config_read:
1098 * @filename: the filename where to store the internal config
1099 * @keyfile_conf: the merged configuration from user (/etc/NM/NetworkManager.conf).
1100 * @out_needs_rewrite: (allow-none): whether the read keyfile contains inconsistent
1101 * data (compared to @keyfile_conf). If %TRUE, you might want to rewrite
1104 * Does the opposite of intern_config_write(). It reads the internal configuration.
1105 * Note that the actual format of how the configuration is saved in @filename
1106 * is different then what we return here. NMConfig manages what is written internally
1107 * by having it inside a keyfile_intern. But we don't write that to disk as is.
1108 * Especially, we also store parts of @keyfile_conf as ".was" and on read we compare
1109 * what we have, with what ".was".
1111 * Returns: a #GKeyFile instance with the internal configuration.
1114 intern_config_read (const char *filename,
1115 GKeyFile *keyfile_conf,
1116 const char *const*atomic_section_prefixes,
1117 gboolean *out_needs_rewrite)
1119 GKeyFile *keyfile_intern;
1121 gboolean needs_rewrite = FALSE;
1122 gs_strfreev char **groups = NULL;
1124 gboolean has_intern = FALSE;
1126 g_return_val_if_fail (filename, NULL);
1129 if (out_needs_rewrite)
1130 *out_needs_rewrite = FALSE;
1134 keyfile_intern = nm_config_create_keyfile ();
1136 keyfile = nm_config_create_keyfile ();
1137 if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL)) {
1138 needs_rewrite = TRUE;
1142 groups = g_key_file_get_groups (keyfile, NULL);
1143 for (g = 0; groups && groups[g]; g++) {
1144 gs_strfreev char **keys = NULL;
1145 const char *group = groups[g];
1146 gboolean is_intern, is_atomic;
1148 if (!strcmp (group, NM_CONFIG_KEYFILE_GROUP_CONFIG))
1151 keys = g_key_file_get_keys (keyfile, group, NULL, NULL);
1155 is_intern = g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN);
1156 is_atomic = !is_intern && _is_atomic_section (atomic_section_prefixes, group);
1159 gs_free char *conf_section_was = NULL;
1160 gs_free char *conf_section_is = NULL;
1162 conf_section_is = _keyfile_serialize_section (keyfile_conf, group);
1163 conf_section_was = g_key_file_get_string (keyfile, group, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, NULL);
1165 if (g_strcmp0 (conf_section_was, conf_section_is) != 0) {
1166 /* the section no longer matches. Skip it entirely. */
1167 needs_rewrite = TRUE;
1170 /* we must set the "was" marker in our keyfile, so that we know that the section
1171 * from user config is overwritten. The value doesn't matter, it's just a marker
1172 * that this section is present. */
1173 g_key_file_set_value (keyfile_intern, group, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, "");
1176 for (k = 0; keys[k]; k++) {
1177 gs_free char *value_set = NULL;
1178 const char *key = keys[k];
1180 value_set = g_key_file_get_value (keyfile, group, key, NULL);
1184 g_key_file_set_value (keyfile_intern, group, key, value_set);
1185 } else if (is_atomic) {
1186 if (strcmp (key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS) == 0)
1188 g_key_file_set_value (keyfile_intern, group, key, value_set);
1189 } else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) {
1190 const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_SET)];
1191 gs_free char *value_was = NULL;
1192 gs_free char *value_conf = NULL;
1193 gs_free char *key_was = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_WAS"%s", key_base);
1196 value_conf = g_key_file_get_value (keyfile_conf, group, key_base, NULL);
1197 value_was = g_key_file_get_value (keyfile, group, key_was, NULL);
1199 if (g_strcmp0 (value_conf, value_was) != 0) {
1200 /* if value_was is no longer the same as @value_conf, it means the user
1201 * changed the configuration since the last write. In this case, we
1202 * drop the value. It also means our file is out-of-date, and we should
1204 needs_rewrite = TRUE;
1208 g_key_file_set_value (keyfile_intern, group, key_base, value_set);
1209 } else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
1210 const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
1211 gs_free char *key_set = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_SET"%s", key_base);
1212 gs_free char *value_was = NULL;
1213 gs_free char *value_conf = NULL;
1215 if (g_key_file_has_key (keyfile, group, key_set, NULL)) {
1216 /* we have a matching "set" key too. Handle the "was" key there. */
1221 value_conf = g_key_file_get_value (keyfile_conf, group, key_base, NULL);
1222 value_was = g_key_file_get_value (keyfile, group, key, NULL);
1224 if (g_strcmp0 (value_conf, value_was) != 0) {
1225 /* if value_was is no longer the same as @value_conf, it means the user
1226 * changed the configuration since the last write. In this case, we
1227 * don't overwrite the user-provided value. It also means our file is
1228 * out-of-date, and we should rewrite it. */
1229 needs_rewrite = TRUE;
1233 /* signal the absence of the value. That means, we must propagate the
1234 * "was" key to NMConfigData, so that it knows to hide the corresponding
1236 g_key_file_set_value (keyfile_intern, group, key, "");
1238 needs_rewrite = TRUE;
1244 * If user configuration specifies global DNS options, the DNS
1245 * options in internal configuration must be deleted. Otherwise a
1246 * deletion of options from user configuration may cause the
1247 * internal options to appear again.
1249 if (nm_config_keyfile_has_global_dns_config (keyfile_conf, FALSE)) {
1250 if (g_key_file_remove_group (keyfile_intern, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NULL))
1251 needs_rewrite = TRUE;
1252 for (g = 0; groups && groups[g]; g++) {
1253 if ( g_str_has_prefix (groups[g], NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)
1254 && groups[g][NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)]) {
1255 g_key_file_remove_group (keyfile_intern, groups[g], NULL);
1256 needs_rewrite = TRUE;
1261 g_key_file_unref (keyfile);
1263 if (out_needs_rewrite)
1264 *out_needs_rewrite = needs_rewrite;
1266 nm_log_dbg (LOGD_CORE, "intern config file \"%s\"", filename);
1269 g_key_file_unref (keyfile_intern);
1272 return keyfile_intern;
1276 _intern_config_write_sort_fcn (const char **a, const char **b, const char *const*atomic_section_prefixes)
1278 const char *g_a = (a ? *a : NULL);
1279 const char *g_b = (b ? *b : NULL);
1280 gboolean a_is, b_is;
1282 a_is = g_str_has_prefix (g_a, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN);
1283 b_is = g_str_has_prefix (g_b, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN);
1291 a_is = _is_atomic_section (atomic_section_prefixes, g_a);
1292 b_is = _is_atomic_section (atomic_section_prefixes, g_b);
1300 return g_strcmp0 (g_a, g_b);
1304 intern_config_write (const char *filename,
1305 GKeyFile *keyfile_intern,
1306 GKeyFile *keyfile_conf,
1307 const char *const*atomic_section_prefixes,
1311 gs_strfreev char **groups = NULL;
1313 gboolean has_intern = FALSE;
1314 gboolean success = FALSE;
1315 GError *local = NULL;
1317 g_return_val_if_fail (filename, FALSE);
1320 g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "no filename to write (use --intern-config?)");
1324 keyfile = nm_config_create_keyfile ();
1326 if (keyfile_intern) {
1327 groups = g_key_file_get_groups (keyfile_intern, NULL);
1328 if (groups && groups[0]) {
1329 g_qsort_with_data (groups,
1330 g_strv_length (groups),
1332 (GCompareDataFunc) _intern_config_write_sort_fcn,
1333 (gpointer) atomic_section_prefixes);
1336 for (g = 0; groups && groups[g]; g++) {
1337 gs_strfreev char **keys = NULL;
1338 const char *group = groups[g];
1339 gboolean is_intern, is_atomic;
1341 keys = g_key_file_get_keys (keyfile_intern, group, NULL, NULL);
1345 is_intern = g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN);
1346 is_atomic = !is_intern && _is_atomic_section (atomic_section_prefixes, group);
1349 if ( (!keys[0] || (!keys[1] && strcmp (keys[0], NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS) == 0))
1350 && !g_key_file_has_group (keyfile_conf, group)) {
1351 /* we are about to save an atomic section. However, we don't have any additional
1352 * keys on our own and there is no user-provided (overlapping) section either.
1353 * We don't have to write an empty section (i.e. skip the useless ".was=0#"). */
1356 gs_free char *conf_section_is = NULL;
1358 conf_section_is = _keyfile_serialize_section (keyfile_conf, group);
1359 g_key_file_set_string (keyfile, group, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, conf_section_is);
1360 g_key_file_set_comment (keyfile, group, NULL,
1361 " Overwrites entire section from 'NetworkManager.conf'",
1366 for (k = 0; keys[k]; k++) {
1367 const char *key = keys[k];
1368 gs_free char *value_set = NULL;
1369 gs_free char *key_set = NULL;
1372 && strcmp (key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS) == 0) {
1373 g_warn_if_fail (is_atomic);
1377 value_set = g_key_file_get_value (keyfile_intern, group, key, NULL);
1381 g_key_file_set_value (keyfile, group, key, value_set);
1382 } else if (is_atomic)
1383 g_key_file_set_value (keyfile, group, key, value_set);
1385 gs_free char *value_was = NULL;
1387 if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET)) {
1388 /* Setting a key with .set prefix has no meaning, as these keys
1389 * are protected. Just set the value you want to set instead.
1390 * Why did this happen?? */
1391 g_warn_if_reached ();
1392 } else if (_HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
1393 const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
1395 if ( _HAS_PREFIX (key_base, NM_CONFIG_KEYFILE_KEYPREFIX_SET)
1396 || _HAS_PREFIX (key_base, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
1397 g_warn_if_reached ();
1401 if (g_key_file_has_key (keyfile_intern, group, key_base, NULL)) {
1402 /* There is also a matching key_base entry. Skip processing
1403 * the .was. key ad handle the key_base in the other else branch. */
1408 value_was = g_key_file_get_value (keyfile_conf, group, key_base, NULL);
1410 g_key_file_set_value (keyfile, group, key, value_was);
1414 value_was = g_key_file_get_value (keyfile_conf, group, key, NULL);
1415 if (g_strcmp0 (value_set, value_was) == 0) {
1416 /* there is no point in storing the identical value as we have via
1417 * user configuration. Skip it. */
1421 gs_free char *key_was = NULL;
1423 key_was = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_WAS"%s", key);
1424 g_key_file_set_value (keyfile, group, key_was, value_was);
1427 key = key_set = g_strdup_printf (NM_CONFIG_KEYFILE_KEYPREFIX_SET"%s", key);
1428 g_key_file_set_value (keyfile, group, key, value_set);
1433 && g_key_file_has_group (keyfile, group)) {
1434 g_key_file_set_comment (keyfile, group, NULL,
1435 " Internal section. Not overwritable via user configuration in 'NetworkManager.conf'",
1440 g_key_file_set_comment (keyfile, NULL, NULL,
1441 " Internal configuration file. This file is written and read\n"
1442 " by NetworkManager and its configuration values are merged\n"
1443 " with the configuration from 'NetworkManager.conf'.\n"
1445 " Keys with a \""NM_CONFIG_KEYFILE_KEYPREFIX_SET"\" prefix specify the value to set.\n"
1446 " A corresponding key with a \""NM_CONFIG_KEYFILE_KEYPREFIX_WAS"\" prefix records the value\n"
1447 " of the user configuration at the time of storing the file.\n"
1448 " The value from internal configuration is rejected if the corresponding\n"
1449 " \""NM_CONFIG_KEYFILE_KEYPREFIX_WAS"\" key no longer matches the configuration from 'NetworkManager.conf'.\n"
1450 " That means, if you modify a value in 'NetworkManager.conf', the internal\n"
1451 " overwrite no longer matches and is ignored.\n"
1453 " Certain sections can only be overwritten whole, not on a per key basis.\n"
1454 " Such sections are marked with a \""NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS"\" key that records the user configuration\n"
1455 " at the time of writing.\n"
1457 " Internal sections of the form [" NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN "*] cannot\n"
1458 " be set by user configuration.\n"
1460 " CHANGES TO THIS FILE WILL BE OVERWRITTEN",
1463 success = g_key_file_save_to_file (keyfile, filename, &local);
1465 nm_log_dbg (LOGD_CORE, "write intern config file \"%s\"%s%s", filename, success ? "" : ": ", success ? "" : local->message);
1466 g_key_file_unref (keyfile);
1468 g_propagate_error (error, local);
1472 /************************************************************************/
1475 nm_config_get_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key)
1477 gs_free char *value = NULL;
1479 /* nm_match_spec_split() already supports full escaping and is basically
1480 * a modified version of g_key_file_parse_value_as_string(). So we first read
1481 * the raw value (g_key_file_get_value()), and do the parsing ourselves. */
1482 value = g_key_file_get_value ((GKeyFile *) keyfile, group, key, NULL);
1484 *out_has_key = !!value;
1485 return nm_match_spec_split (value);
1488 /************************************************************************/
1491 nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError **error)
1493 NMConfigPrivate *priv;
1496 const NMGlobalDnsConfig *old_global_dns;
1499 g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
1501 priv = NM_CONFIG_GET_PRIVATE (self);
1502 g_return_val_if_fail (priv->config_data, FALSE);
1504 old_global_dns = nm_config_data_get_global_dns_config (priv->config_data);
1505 if (old_global_dns && !nm_global_dns_config_is_internal (old_global_dns)) {
1506 g_set_error_literal (error, 1, 0,
1507 "Global DNS configuration already set via configuration file");
1511 keyfile = nm_config_data_clone_keyfile_intern (priv->config_data);
1513 /* Remove existing groups */
1514 g_key_file_remove_group (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NULL);
1515 groups = g_key_file_get_groups (keyfile, NULL);
1516 for (i = 0; groups[i]; i++) {
1517 if (g_str_has_prefix (groups[i], NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN))
1518 g_key_file_remove_group (keyfile, groups[i], NULL);
1520 g_strfreev (groups);
1522 /* An empty configuration removes everything from internal configuration file */
1523 if (nm_global_dns_config_is_empty (global_dns))
1526 /* Set new values */
1527 nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS,
1528 "searches", nm_global_dns_config_get_searches (global_dns),
1531 nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS,
1532 "options", nm_global_dns_config_get_options (global_dns),
1535 for (i = 0; i < nm_global_dns_config_get_num_domains (global_dns); i++) {
1536 NMGlobalDnsDomain *domain = nm_global_dns_config_get_domain (global_dns, i);
1537 gs_free char *group_name = NULL;
1539 group_name = g_strdup_printf (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN "%s",
1540 nm_global_dns_domain_get_name (domain));
1542 nm_config_keyfile_set_string_list (keyfile, group_name, "servers",
1543 nm_global_dns_domain_get_servers (domain), -1);
1544 nm_config_keyfile_set_string_list (keyfile, group_name, "options",
1545 nm_global_dns_domain_get_options (domain), -1);
1549 nm_config_set_values (self, keyfile, TRUE, FALSE);
1550 g_key_file_unref (keyfile);
1556 * nm_config_set_values:
1557 * @self: the NMConfig instance
1558 * @keyfile_intern_new: (allow-none): the new internal settings to set.
1559 * If %NULL, it is equal to an empty keyfile.
1560 * @allow_write: only if %TRUE, allow writing the changes to file. Otherwise,
1561 * do the changes in-memory only.
1562 * @force_rewrite: if @allow_write is %FALSE, this has no effect. If %FALSE,
1563 * only write the configuration to file, if there are any actual changes.
1564 * If %TRUE, always write the configuration to file, even if tere are seemingly
1567 * This is the most flexible function to set values. It all depends on the
1568 * keys and values you set in @keyfile_intern_new. You basically reset all
1569 * internal configuration values to what is in @keyfile_intern_new.
1571 * There are 3 types of settings:
1572 * - all groups/sections with a prefix [.intern.*] are taken as is. As these
1573 * groups are separate from user configuration, there is no conflict. You set
1575 * - there are atomic sections, i.e. sections whose name start with one of
1576 * NM_CONFIG_ATOMIC_SECTION_PREFIXES. If you put values in these sections,
1577 * it means you completely replace the section from user configuration.
1578 * You can also hide a user provided section by only putting the special
1579 * key NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS into that section.
1580 * - otherwise you can overwrite individual values from user-configuration.
1581 * Just set the value. Keys with a prefix NM_CONFIG_KEYFILE_KEYPREFIX_*
1582 * are protected -- as they are not value user keys.
1583 * You can also hide a certain user setting by putting only a key
1584 * NM_CONFIG_KEYFILE_KEYPREFIX_WAS"keyname" into the keyfile.
1587 nm_config_set_values (NMConfig *self,
1588 GKeyFile *keyfile_intern_new,
1589 gboolean allow_write,
1590 gboolean force_rewrite)
1592 NMConfigPrivate *priv;
1593 GKeyFile *keyfile_intern_current;
1594 GKeyFile *keyfile_user;
1595 GKeyFile *keyfile_new;
1596 GError *local = NULL;
1597 NMConfigData *new_data = NULL;
1598 gs_strfreev char **groups = NULL;
1601 g_return_if_fail (NM_IS_CONFIG (self));
1603 priv = NM_CONFIG_GET_PRIVATE (self);
1605 keyfile_intern_current = _nm_config_data_get_keyfile_intern (priv->config_data);
1607 keyfile_new = nm_config_create_keyfile ();
1608 if (keyfile_intern_new)
1609 _nm_keyfile_copy (keyfile_new, keyfile_intern_new);
1611 /* ensure that every atomic section has a .was entry. */
1612 groups = g_key_file_get_groups (keyfile_new, NULL);
1613 for (g = 0; groups && groups[g]; g++) {
1614 if (_is_atomic_section ((const char *const*) priv->atomic_section_prefixes, groups[g]))
1615 g_key_file_set_value (keyfile_new, groups[g], NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, "");
1618 if (!_nm_keyfile_equals (keyfile_intern_current, keyfile_new, TRUE))
1619 new_data = nm_config_data_new_update_keyfile_intern (priv->config_data, keyfile_new);
1621 nm_log_dbg (LOGD_CORE, "set values(): %s", new_data ? "has changes" : "no changes");
1624 && (new_data || force_rewrite)) {
1625 /* We write the internal config file based on the user configuration from
1626 * the last load/reload. That is correct, because the intern properties might
1627 * be in accordance to what NM thinks is currently configured. Even if the files
1628 * on disk changed in the meantime.
1629 * But if they changed, on the next reload with might throw away our just
1630 * written data. That is correct, because from NM's point of view, those
1631 * changes on disk happened in any case *after* now. */
1632 if (*priv->intern_config_file) {
1633 keyfile_user = _nm_config_data_get_keyfile_user (priv->config_data);
1634 if (!intern_config_write (priv->intern_config_file, keyfile_new, keyfile_user,
1635 (const char *const*) priv->atomic_section_prefixes, &local)) {
1636 nm_log_warn (LOGD_CORE, "error saving internal configuration \"%s\": %s", priv->intern_config_file, local->message);
1637 g_clear_error (&local);
1640 nm_log_dbg (LOGD_CORE, "don't persistate internal configuration (no file set, use --intern-config?)");
1643 _set_config_data (self, new_data, 0);
1645 g_key_file_unref (keyfile_new);
1648 /************************************************************************/
1651 nm_config_reload (NMConfig *self, int signal)
1653 NMConfigPrivate *priv;
1654 GError *error = NULL;
1655 GKeyFile *keyfile, *keyfile_intern;
1656 NMConfigData *new_data = NULL;
1657 char *config_main_file = NULL;
1658 char *config_description = NULL;
1659 gs_strfreev char **no_auto_default = NULL;
1660 gboolean intern_config_needs_rewrite;
1662 g_return_if_fail (NM_IS_CONFIG (self));
1664 priv = NM_CONFIG_GET_PRIVATE (self);
1666 if (signal != SIGHUP) {
1667 _set_config_data (self, NULL, signal);
1671 /* pass on the original command line options. This means, that
1672 * options specified at command line cannot ever be reloaded from
1673 * file. That seems desirable.
1675 keyfile = read_entire_config (&priv->cli,
1677 priv->system_config_dir,
1679 &config_description,
1682 nm_log_err (LOGD_CORE, "Failed to reload the configuration: %s", error->message);
1683 g_clear_error (&error);
1684 _set_config_data (self, NULL, signal);
1688 no_auto_default = no_auto_default_from_file (priv->no_auto_default_file);
1690 keyfile_intern = intern_config_read (priv->intern_config_file,
1692 (const char *const*) priv->atomic_section_prefixes,
1693 &intern_config_needs_rewrite);
1694 if (intern_config_needs_rewrite) {
1695 intern_config_write (priv->intern_config_file, keyfile_intern, keyfile,
1696 (const char *const*) priv->atomic_section_prefixes, NULL);
1699 new_data = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile, keyfile_intern);
1700 g_free (config_main_file);
1701 g_free (config_description);
1702 g_key_file_unref (keyfile);
1704 g_key_file_unref (keyfile_intern);
1706 _set_config_data (self, new_data, signal);
1709 NM_UTILS_FLAGS2STR_DEFINE (nm_config_change_flags_to_string, NMConfigChangeFlags,
1710 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_SIGHUP, "SIGHUP"),
1711 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_SIGUSR1, "SIGUSR1"),
1712 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_SIGUSR2, "SIGUSR2"),
1713 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CONFIG_FILES, "config-files"),
1714 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_VALUES, "values"),
1715 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_VALUES_USER, "values-user"),
1716 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_VALUES_INTERN, "values-intern"),
1717 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_CONNECTIVITY, "connectivity"),
1718 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_NO_AUTO_DEFAULT, "no-auto-default"),
1719 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_DNS_MODE, "dns-mode"),
1720 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_RC_MANAGER, "rc-manager"),
1721 NM_UTILS_FLAGS2STR (NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG, "global-dns-config"),
1725 _set_config_data (NMConfig *self, NMConfigData *new_data, int signal)
1727 NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
1728 NMConfigData *old_data = priv->config_data;
1729 NMConfigChangeFlags changes, changes_diff;
1730 gboolean had_new_data = !!new_data;
1734 changes = NM_CONFIG_CHANGE_SIGHUP;
1737 changes = NM_CONFIG_CHANGE_SIGUSR1;
1740 changes = NM_CONFIG_CHANGE_SIGUSR2;
1743 changes = NM_CONFIG_CHANGE_NONE;
1748 changes_diff = nm_config_data_diff (old_data, new_data);
1749 if (changes_diff == NM_CONFIG_CHANGE_NONE)
1750 g_clear_object (&new_data);
1752 changes |= changes_diff;
1755 if (changes == NM_CONFIG_CHANGE_NONE)
1759 nm_log_info (LOGD_CORE, "config: update %s (%s)", nm_config_data_get_config_description (new_data),
1760 nm_config_change_flags_to_string (changes, NULL, 0));
1761 nm_config_data_log (new_data, "CONFIG: ", " ", NULL);
1762 priv->config_data = new_data;
1763 } else if (had_new_data)
1764 nm_log_info (LOGD_CORE, "config: signal %s (no changes from disk)", nm_config_change_flags_to_string (changes, NULL, 0));
1766 nm_log_info (LOGD_CORE, "config: signal %s", nm_config_change_flags_to_string (changes, NULL, 0));
1767 g_signal_emit (self, signals[SIGNAL_CONFIG_CHANGED], 0,
1768 new_data ? new_data : old_data,
1771 g_object_unref (old_data);
1774 NM_DEFINE_SINGLETON_REGISTER (NMConfig);
1777 nm_config_get (void)
1779 g_assert (singleton_instance);
1780 return singleton_instance;
1784 nm_config_setup (const NMConfigCmdLineOptions *cli, char **atomic_section_prefixes, GError **error)
1786 g_assert (!singleton_instance);
1788 singleton_instance = nm_config_new (cli, atomic_section_prefixes, error);
1789 if (singleton_instance) {
1790 nm_singleton_instance_register ();
1792 /* usually, you would not see this logging line because when creating the
1793 * NMConfig instance, the logging is not yet set up to print debug message. */
1794 nm_log_dbg (LOGD_CORE, "setup %s singleton (%p)", "NMConfig", singleton_instance);
1796 return singleton_instance;
1800 init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
1802 NMConfig *self = NM_CONFIG (initable);
1803 NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
1804 GKeyFile *keyfile, *keyfile_intern;
1805 char *config_main_file = NULL;
1806 char *config_description = NULL;
1807 gs_strfreev char **no_auto_default = NULL;
1808 gboolean intern_config_needs_rewrite;
1810 if (priv->config_dir) {
1811 /* Object is already initialized. */
1812 if (priv->config_data)
1814 g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "unspecified error");
1818 if (priv->cli.config_dir)
1819 priv->config_dir = g_strdup (priv->cli.config_dir);
1821 priv->config_dir = g_strdup (DEFAULT_CONFIG_DIR);
1823 if (priv->cli.system_config_dir)
1824 priv->system_config_dir = g_strdup (priv->cli.system_config_dir);
1826 priv->system_config_dir = g_strdup (DEFAULT_SYSTEM_CONFIG_DIR);
1828 if (strcmp (priv->config_dir, priv->system_config_dir) == 0) {
1829 /* having the same directory twice makes no sense. In that case, clear
1830 * @system_config_dir. */
1831 g_free (priv->system_config_dir);
1832 priv->system_config_dir = g_strdup ("");
1835 if (priv->cli.intern_config_file)
1836 priv->intern_config_file = g_strdup (priv->cli.intern_config_file);
1838 priv->intern_config_file = g_strdup (DEFAULT_INTERN_CONFIG_FILE);
1840 keyfile = read_entire_config (&priv->cli,
1842 priv->system_config_dir,
1844 &config_description,
1849 /* Initialize read only private members */
1851 if (priv->cli.no_auto_default_file)
1852 priv->no_auto_default_file = g_strdup (priv->cli.no_auto_default_file);
1854 priv->no_auto_default_file = g_strdup (DEFAULT_NO_AUTO_DEFAULT_FILE);
1856 priv->plugins = _nm_utils_strv_cleanup (g_key_file_get_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", NULL, NULL),
1859 priv->plugins = g_new0 (char *, 1);
1861 priv->monitor_connection_files = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "monitor-connection-files", FALSE);
1863 priv->auth_polkit = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "auth-polkit", NM_CONFIG_DEFAULT_AUTH_POLKIT);
1865 priv->dhcp_client = nm_strstrip (g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "dhcp", NULL));
1867 priv->log_level = nm_strstrip (g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_LOGGING, "level", NULL));
1868 priv->log_domains = nm_strstrip (g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_LOGGING, "domains", NULL));
1870 priv->debug = g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "debug", NULL);
1872 priv->configure_and_quit = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", FALSE);
1874 no_auto_default = no_auto_default_from_file (priv->no_auto_default_file);
1876 keyfile_intern = intern_config_read (priv->intern_config_file,
1878 (const char *const*) priv->atomic_section_prefixes,
1879 &intern_config_needs_rewrite);
1880 if (intern_config_needs_rewrite) {
1881 intern_config_write (priv->intern_config_file, keyfile_intern, keyfile,
1882 (const char *const*) priv->atomic_section_prefixes, NULL);
1885 priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile, keyfile_intern);
1887 priv->config_data = g_object_ref (priv->config_data_orig);
1889 g_free (config_main_file);
1890 g_free (config_description);
1891 g_key_file_unref (keyfile);
1893 g_key_file_unref (keyfile_intern);
1898 nm_config_new (const NMConfigCmdLineOptions *cli, char **atomic_section_prefixes, GError **error)
1900 return NM_CONFIG (g_initable_new (NM_TYPE_CONFIG,
1903 NM_CONFIG_CMD_LINE_OPTIONS, cli,
1904 NM_CONFIG_ATOMIC_SECTION_PREFIXES, atomic_section_prefixes,
1909 nm_config_init (NMConfig *config)
1911 NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
1913 priv->auth_polkit = NM_CONFIG_DEFAULT_AUTH_POLKIT;
1917 finalize (GObject *gobject)
1919 NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject);
1921 g_free (priv->config_dir);
1922 g_free (priv->system_config_dir);
1923 g_free (priv->no_auto_default_file);
1924 g_free (priv->intern_config_file);
1925 g_strfreev (priv->plugins);
1926 g_free (priv->dhcp_client);
1927 g_free (priv->log_level);
1928 g_free (priv->log_domains);
1929 g_free (priv->debug);
1930 g_strfreev (priv->atomic_section_prefixes);
1932 _nm_config_cmd_line_options_clear (&priv->cli);
1934 g_clear_object (&priv->config_data);
1935 g_clear_object (&priv->config_data_orig);
1937 G_OBJECT_CLASS (nm_config_parent_class)->finalize (gobject);
1941 set_property (GObject *object, guint prop_id,
1942 const GValue *value, GParamSpec *pspec)
1944 NMConfig *self = NM_CONFIG (object);
1945 NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
1946 NMConfigCmdLineOptions *cli;
1949 case PROP_CMD_LINE_OPTIONS:
1950 /* construct only */
1951 cli = g_value_get_pointer (value);
1953 _nm_config_cmd_line_options_clear (&priv->cli);
1955 _nm_config_cmd_line_options_copy (cli, &priv->cli);
1957 case PROP_ATOMIC_SECTION_PREFIXES:
1958 /* construct only */
1959 priv->atomic_section_prefixes = g_strdupv (g_value_get_boxed (value));
1962 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1968 nm_config_class_init (NMConfigClass *config_class)
1970 GObjectClass *object_class = G_OBJECT_CLASS (config_class);
1972 g_type_class_add_private (config_class, sizeof (NMConfigPrivate));
1973 object_class->finalize = finalize;
1974 object_class->set_property = set_property;
1976 g_object_class_install_property
1977 (object_class, PROP_CMD_LINE_OPTIONS,
1978 g_param_spec_pointer (NM_CONFIG_CMD_LINE_OPTIONS, "", "",
1980 G_PARAM_CONSTRUCT_ONLY |
1981 G_PARAM_STATIC_STRINGS));
1983 g_object_class_install_property
1984 (object_class, PROP_ATOMIC_SECTION_PREFIXES,
1985 g_param_spec_boxed (NM_CONFIG_ATOMIC_SECTION_PREFIXES, "", "",
1988 G_PARAM_CONSTRUCT_ONLY |
1989 G_PARAM_STATIC_STRINGS));
1991 signals[SIGNAL_CONFIG_CHANGED] =
1992 g_signal_new (NM_CONFIG_SIGNAL_CONFIG_CHANGED,
1993 G_OBJECT_CLASS_TYPE (object_class),
1999 NM_TYPE_CONFIG_DATA,
2000 /* Use plain guint type for changes argument. This avoids
2001 * glib/ffi bug https://bugzilla.redhat.com/show_bug.cgi?id=1260577 */
2002 /* NM_TYPE_CONFIG_CHANGE_FLAGS, */
2004 NM_TYPE_CONFIG_DATA);
2006 G_STATIC_ASSERT_EXPR (sizeof (guint) == sizeof (NMConfigChangeFlags));
2007 G_STATIC_ASSERT_EXPR (((gint64) ((NMConfigChangeFlags) -1)) > ((gint64) 0));
2011 nm_config_initable_iface_init (GInitableIface *iface)
2013 iface->init = init_sync;