device: renew dhcp leases on awake for software devices
[NetworkManager.git] / src / nm-config.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager -- Network link manager
3  *
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.
8  *
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.
13  *
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.
17  *
18  * Copyright (C) 2011 Red Hat, Inc.
19  * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de>
20  */
21
22 #include "nm-default.h"
23
24 #include <string.h>
25 #include <stdio.h>
26
27 #include "nm-config.h"
28 #include "nm-utils.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"
34
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"
41
42 struct NMConfigCmdLineOptions {
43         char *config_main_file;
44         char *intern_config_file;
45         char *config_dir;
46         char *system_config_dir;
47         char *no_auto_default_file;
48         char *plugins;
49         gboolean configure_and_quit;
50         gboolean is_debug;
51         char *connectivity_uri;
52
53         /* We store interval as signed internally to track whether it's
54          * set or not via GOptionEntry
55          */
56         int connectivity_interval;
57         char *connectivity_response;
58 };
59
60 typedef struct {
61         NMConfigCmdLineOptions cli;
62
63         NMConfigData *config_data;
64         NMConfigData *config_data_orig;
65
66         char *config_dir;
67         char *system_config_dir;
68         char *no_auto_default_file;
69         char *intern_config_file;
70
71         char **plugins;
72         gboolean monitor_connection_files;
73         gboolean auth_polkit;
74         char *dhcp_client;
75
76         char *log_level;
77         char *log_domains;
78
79         char *debug;
80
81         gboolean configure_and_quit;
82
83         char **atomic_section_prefixes;
84 } NMConfigPrivate;
85
86 enum {
87         PROP_0,
88         PROP_CMD_LINE_OPTIONS,
89         PROP_ATOMIC_SECTION_PREFIXES,
90         LAST_PROP,
91 };
92
93 enum {
94         SIGNAL_CONFIG_CHANGED,
95
96         LAST_SIGNAL
97 };
98
99 static guint signals[LAST_SIGNAL] = { 0 };
100
101 static void nm_config_initable_iface_init (GInitableIface *iface);
102
103 G_DEFINE_TYPE_WITH_CODE (NMConfig, nm_config, G_TYPE_OBJECT,
104                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_config_initable_iface_init);
105                          )
106
107
108 #define NM_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG, NMConfigPrivate))
109
110 /************************************************************************/
111
112 static void _set_config_data (NMConfig *self, NMConfigData *new_data, int signal);
113
114 /************************************************************************/
115
116 #define _HAS_PREFIX(str, prefix) \
117         ({ \
118                 const char *_str = (str); \
119                 g_str_has_prefix ( _str, ""prefix"") && _str[NM_STRLEN(prefix)] != '\0'; \
120         })
121
122 /************************************************************************/
123
124 gint
125 nm_config_parse_boolean (const char *str,
126                          gint default_value)
127 {
128         return nm_utils_ascii_str_to_bool (str, default_value);
129 }
130
131 gint
132 nm_config_keyfile_get_boolean (GKeyFile *keyfile,
133                                const char *section,
134                                const char *key,
135                                gint default_value)
136 {
137         gs_free char *str = NULL;
138
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);
142
143         str = g_key_file_get_value (keyfile, section, key, NULL);
144         return nm_config_parse_boolean (str, default_value);
145 }
146
147 char *
148 nm_config_keyfile_get_value (GKeyFile *keyfile,
149                              const char *section,
150                              const char *key,
151                              NMConfigGetValueFlags flags)
152 {
153         char *value;
154
155         if (NM_FLAGS_HAS (flags, NM_CONFIG_GET_VALUE_RAW))
156                 value = g_key_file_get_value (keyfile, section, key, NULL);
157         else
158                 value = g_key_file_get_string (keyfile, section, key, NULL);
159
160         if (!value)
161                 return NULL;
162
163         if (NM_FLAGS_HAS (flags, NM_CONFIG_GET_VALUE_STRIP))
164                 g_strstrip (value);
165
166         if (   NM_FLAGS_HAS (flags, NM_CONFIG_GET_VALUE_NO_EMPTY)
167             && !*value) {
168                 g_free (value);
169                 return NULL;
170         }
171
172         return value;
173 }
174
175 void
176 nm_config_keyfile_set_string_list (GKeyFile *keyfile,
177                                    const char *group,
178                                    const char *key,
179                                    const char *const* strv,
180                                    gssize len)
181 {
182         gsize l;
183         char *new_value;
184
185         if (len < 0)
186                 len = strv ? g_strv_length ((char **) strv) : 0;
187
188         g_key_file_set_string_list (keyfile, group, key, strv, len);
189
190         /* g_key_file_set_string_list() appends a trailing separator to the value.
191          * We don't like that, get rid of it. */
192
193         new_value = g_key_file_get_value (keyfile, group, key, NULL);
194         if (!new_value)
195                 return;
196
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);
204         }
205         g_free (new_value);
206 }
207
208 /************************************************************************/
209
210 NMConfigData *
211 nm_config_get_data (NMConfig *config)
212 {
213         g_return_val_if_fail (config != NULL, NULL);
214
215         return NM_CONFIG_GET_PRIVATE (config)->config_data;
216 }
217
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. */
221 NMConfigData *
222 nm_config_get_data_orig (NMConfig *config)
223 {
224         g_return_val_if_fail (config != NULL, NULL);
225
226         return NM_CONFIG_GET_PRIVATE (config)->config_data_orig;
227 }
228
229 const char **
230 nm_config_get_plugins (NMConfig *config)
231 {
232         g_return_val_if_fail (config != NULL, NULL);
233
234         return (const char **) NM_CONFIG_GET_PRIVATE (config)->plugins;
235 }
236
237 gboolean
238 nm_config_get_monitor_connection_files (NMConfig *config)
239 {
240         g_return_val_if_fail (config != NULL, FALSE);
241
242         return NM_CONFIG_GET_PRIVATE (config)->monitor_connection_files;
243 }
244
245 gboolean
246 nm_config_get_auth_polkit (NMConfig *config)
247 {
248         g_return_val_if_fail (NM_IS_CONFIG (config), NM_CONFIG_DEFAULT_AUTH_POLKIT);
249
250         return NM_CONFIG_GET_PRIVATE (config)->auth_polkit;
251 }
252
253 const char *
254 nm_config_get_dhcp_client (NMConfig *config)
255 {
256         g_return_val_if_fail (config != NULL, NULL);
257
258         return NM_CONFIG_GET_PRIVATE (config)->dhcp_client;
259 }
260
261 const char *
262 nm_config_get_log_level (NMConfig *config)
263 {
264         g_return_val_if_fail (config != NULL, NULL);
265
266         return NM_CONFIG_GET_PRIVATE (config)->log_level;
267 }
268
269 const char *
270 nm_config_get_log_domains (NMConfig *config)
271 {
272         g_return_val_if_fail (config != NULL, NULL);
273
274         return NM_CONFIG_GET_PRIVATE (config)->log_domains;
275 }
276
277 const char *
278 nm_config_get_debug (NMConfig *config)
279 {
280         g_return_val_if_fail (config != NULL, NULL);
281
282         return NM_CONFIG_GET_PRIVATE (config)->debug;
283 }
284
285 gboolean
286 nm_config_get_configure_and_quit (NMConfig *config)
287 {
288         return NM_CONFIG_GET_PRIVATE (config)->configure_and_quit;
289 }
290
291 gboolean
292 nm_config_get_is_debug (NMConfig *config)
293 {
294         return NM_CONFIG_GET_PRIVATE (config)->cli.is_debug;
295 }
296
297 /************************************************************************/
298
299 static char **
300 no_auto_default_from_file (const char *no_auto_default_file)
301 {
302         GPtrArray *no_auto_default_new;
303         char **list;
304         guint i;
305         char *data;
306
307         no_auto_default_new = g_ptr_array_new ();
308
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++) {
313                         if (   *list[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]);
317                         else
318                                 g_free (list[i]);
319                 }
320                 g_free (list);
321                 g_free (data);
322         }
323
324         g_ptr_array_add (no_auto_default_new, NULL);
325         return (char **) g_ptr_array_free (no_auto_default_new, FALSE);
326 }
327
328 static gboolean
329 no_auto_default_to_file (const char *no_auto_default_file, const char *const*no_auto_default, GError **error)
330 {
331         GString *data;
332         gboolean success;
333         guint i;
334
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');
339         }
340         success = g_file_set_contents (no_auto_default_file, data->str, data->len, error);
341         g_string_free (data, TRUE);
342         return success;
343 }
344
345 gboolean
346 nm_config_get_no_auto_default_for_device (NMConfig *self, NMDevice *device)
347 {
348         g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
349
350         return nm_config_data_get_no_auto_default_for_device (NM_CONFIG_GET_PRIVATE (self)->config_data, device);
351 }
352
353 void
354 nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device)
355 {
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;
362         guint i;
363
364         g_return_if_fail (NM_IS_CONFIG (self));
365         g_return_if_fail (NM_IS_DEVICE (device));
366
367         priv = NM_CONFIG_GET_PRIVATE (self);
368
369         hw_address = nm_device_get_hw_address (device);
370
371         no_auto_default_current = nm_config_data_get_no_auto_default (priv->config_data);
372
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. */
376                 return;
377         }
378
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);
384
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",
387                              error->message);
388                 g_error_free (error);
389         }
390
391         new_data = nm_config_data_new_update_no_auto_default (priv->config_data, (const char *const*) no_auto_default_new->pdata);
392
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);
395
396         _set_config_data (self, new_data, 0);
397 }
398
399 /************************************************************************/
400
401 static void
402 _nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli)
403 {
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;
415 }
416
417 static void
418 _nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmdLineOptions *dst)
419 {
420         g_return_if_fail (cli);
421         g_return_if_fail (dst);
422         g_return_if_fail (cli != dst);
423
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;
436 }
437
438 NMConfigCmdLineOptions *
439 nm_config_cmd_line_options_new ()
440 {
441         NMConfigCmdLineOptions *cli = g_new0 (NMConfigCmdLineOptions, 1);
442
443         _nm_config_cmd_line_options_clear (cli);
444         return cli;
445 }
446
447 void
448 nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli)
449 {
450         g_return_if_fail (cli);
451
452         _nm_config_cmd_line_options_clear (cli);
453         g_free (cli);
454 }
455
456 void
457 nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli,
458                                            GOptionContext *opt_ctx)
459 {
460         g_return_if_fail (opt_ctx);
461         g_return_if_fail (cli);
462
463         {
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 },
473
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) },
478                         { 0 },
479                 };
480
481                 g_option_context_add_main_entries (opt_ctx, config_options, NULL);
482         }
483 }
484
485 /************************************************************************/
486
487 GKeyFile *
488 nm_config_create_keyfile ()
489 {
490         GKeyFile *keyfile;
491
492         keyfile = g_key_file_new ();
493         g_key_file_set_list_separator (keyfile, NM_CONFIG_KEYFILE_LIST_SEPARATOR);
494         return keyfile;
495 }
496
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;
501
502 static gboolean
503 ignore_config_snippet (GKeyFile *keyfile, gboolean is_base_config)
504 {
505         GSList *specs;
506         gboolean as_bool;
507         NMMatchSpecMatchType match_type;
508
509         if (is_base_config)
510                 return FALSE;
511
512         if (!g_key_file_has_key (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, NULL))
513                 return FALSE;
514
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);
518         if (as_bool != -1)
519                 return !as_bool;
520
521         if (G_UNLIKELY (!_nm_config_match_env)) {
522                 const char *e;
523
524                 e = g_getenv ("NM_CONFIG_ENABLE_TAG");
525                 _nm_config_match_env = g_strdup (e ? e : "");
526         }
527
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);
534
535         return match_type != NM_MATCH_SPEC_MATCH;
536 }
537
538 static int
539 _sort_groups_cmp (const char **pa, const char **pb, gpointer dummy)
540 {
541         const char *a, *b;
542         gboolean a_is_connection, b_is_connection;
543
544         /* basic NULL checking... */
545         if (pa == pb)
546                 return 0;
547         if (!pa)
548                 return -1;
549         if (!pb)
550                 return 1;
551
552         a = *pa;
553         b = *pb;
554
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);
557
558         if (a_is_connection != b_is_connection) {
559                 /* one is a [connection*] entry, the other not. We sort [connection*] entires
560                  * after.  */
561                 if (a_is_connection)
562                         return 1;
563                 return -1;
564         }
565         if (!a_is_connection) {
566                 /* both are non-connection entries. Don't reorder. */
567                 return 0;
568         }
569
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;
575 }
576
577 void
578 _nm_config_sort_groups (char **groups, gsize ngroups)
579 {
580         if (ngroups > 1) {
581                 g_qsort_with_data (groups,
582                                    ngroups,
583                                    sizeof (char *),
584                                    (GCompareDataFunc) _sort_groups_cmp,
585                                    NULL);
586         }
587 }
588
589 static gboolean
590 _setting_is_device_spec (const char *group, const char *key)
591 {
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"));
598 }
599
600 static gboolean
601 _setting_is_string_list (const char *group, const char *key)
602 {
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);
607 #undef _IS
608 }
609
610 static gboolean
611 read_config (GKeyFile *keyfile, gboolean is_base_config, const char *dirname, const char *path, GError **error)
612 {
613         GKeyFile *kf;
614         char **groups, **keys;
615         gsize ngroups, nkeys;
616         int g, k;
617         gs_free char *path_free = NULL;
618
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);
622
623         if (dirname) {
624                 path_free = g_build_filename (dirname, path, NULL);
625                 path = path_free;
626         }
627
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);
630                 return FALSE;
631         }
632
633         nm_log_dbg (LOGD_SETTINGS, "Reading config file '%s'", path);
634
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);
638                 return FALSE;
639         }
640
641         if (ignore_config_snippet (kf, is_base_config)) {
642                 g_key_file_free (kf);
643                 return TRUE;
644         }
645
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);
650
651         /* Override the current settings with the new ones */
652         groups = g_key_file_get_groups (kf, &ngroups);
653         if (!groups)
654                 ngroups = 0;
655
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);
665
666         for (g = 0; groups && groups[g]; g++) {
667                 const char *group = groups[g];
668
669                 if (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN)) {
670                         /* internal groups cannot be set by user configuration. */
671                         continue;
672                 }
673                 keys = g_key_file_get_keys (kf, group, &nkeys, NULL);
674                 if (!keys)
675                         continue;
676                 for (k = 0; keys[k]; k++) {
677                         const char *key;
678                         char *new_value;
679                         char last_char;
680                         gsize key_len;
681
682                         key = keys[k];
683                         g_assert (key && *key);
684
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. */
688                                 continue;
689                         }
690
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. */
693                                 continue;
694                         }
695
696                         key_len = strlen (key);
697                         last_char = key[key_len - 1];
698                         if (   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;
702
703                                 is_string_list = _setting_is_string_list (group, base_key);
704
705                                 if (   is_string_list
706                                     || _setting_is_device_spec (group, base_key)) {
707                                         gs_unref_ptrarray GPtrArray *new = g_ptr_array_new_with_free_func (g_free);
708                                         char **iter_val;
709                                         gs_strfreev  char **old_val = NULL;
710                                         gs_free char **new_val = NULL;
711
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);
715                                         } else {
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);
720
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);
725                                         }
726
727                                         /* merge the string lists, by omiting duplicates. */
728
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));
733                                         }
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);
739                                                 else
740                                                         g_free (*iter_val);
741                                         }
742
743                                         if (new->len > 0) {
744                                                 if (is_string_list)
745                                                         nm_config_keyfile_set_string_list (keyfile, group, base_key, (const char *const*) new->pdata, new->len);
746                                                 else {
747                                                         gs_free_slist GSList *specs = NULL;
748                                                         gs_free char *specs_joined = NULL;
749
750                                                         g_ptr_array_add (new, NULL);
751                                                         specs = _nm_utils_strv_to_slist ((char **) new->pdata, FALSE);
752
753                                                         specs_joined = nm_match_spec_join (specs);
754
755                                                         g_key_file_set_value (keyfile, group, base_key, specs_joined);
756                                                 }
757                                         } else {
758                                                 if (is_string_list)
759                                                         g_key_file_remove_key (keyfile, group, base_key, NULL);
760                                                 else
761                                                         g_key_file_set_value (keyfile, group, base_key, "");
762                                         }
763                                 } else {
764                                         /* For any other settings we don't support extending the option with +/-.
765                                          * Just drop the key. */
766                                 }
767                                 continue;
768                         }
769
770                         new_value = g_key_file_get_value (kf, group, key, NULL);
771                         g_key_file_set_value (keyfile, group, key, new_value);
772                         g_free (new_value);
773                 }
774                 g_strfreev (keys);
775         }
776         g_strfreev (groups);
777         g_key_file_free (kf);
778
779         return TRUE;
780 }
781
782 static gboolean
783 read_base_config (GKeyFile *keyfile,
784                   const char *cli_config_main_file,
785                   char **out_config_main_file,
786                   GError **error)
787 {
788         GError *my_error = NULL;
789
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);
793
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);
799                         return TRUE;
800                 } else
801                         return FALSE;
802         }
803
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.
809          */
810
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);
814                 return TRUE;
815         }
816
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,
820                              my_error->message);
821         }
822         g_clear_error (&my_error);
823
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);
827                 return TRUE;
828         }
829
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,
833                              my_error->message);
834                 g_propagate_error (error, my_error);
835                 return FALSE;
836         }
837         g_clear_error (&my_error);
838
839         /* If for some reason no config file exists, use the default
840          * config file path.
841          */
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);
845         return TRUE;
846 }
847
848 static int
849 sort_asciibetically (gconstpointer a, gconstpointer b)
850 {
851         const char *s1 = *(const char **)a;
852         const char *s2 = *(const char **)b;
853
854         return strcmp (s1, s2);
855 }
856
857 static GPtrArray *
858 _get_config_dir_files (const char *config_dir)
859 {
860         GFile *dir;
861         GFileEnumerator *direnum;
862         GFileInfo *info;
863         GPtrArray *confs;
864         const char *name;
865
866         g_return_val_if_fail (config_dir, NULL);
867
868         confs = g_ptr_array_new_with_free_func (g_free);
869         if (!*config_dir)
870                 return confs;
871
872         dir = g_file_new_for_path (config_dir);
873         direnum = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL);
874         if (direnum) {
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);
880                 }
881                 g_object_unref (direnum);
882         }
883         g_object_unref (dir);
884
885         g_ptr_array_sort (confs, sort_asciibetically);
886         return confs;
887 }
888
889 static GKeyFile *
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,
895                     GError **error)
896 {
897         GKeyFile *keyfile;
898         gs_unref_ptrarray GPtrArray *system_confs = NULL;
899         gs_unref_ptrarray GPtrArray *confs = NULL;
900         guint i;
901         gs_free char *o_config_main_file = NULL;
902         GString *str;
903         char **plugins_default;
904
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);
910
911         /* create a default configuration file. */
912         keyfile = nm_config_create_keyfile ();
913
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);
918
919         system_confs = _get_config_dir_files (system_config_dir);
920         confs = _get_config_dir_files (config_dir);
921
922         for (i = 0; i < system_confs->len; ) {
923                 const char *filename = system_confs->pdata[i];
924
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);
928                         continue;
929                 }
930
931                 if (!read_config (keyfile, FALSE, system_config_dir, filename, error)) {
932                         g_key_file_free (keyfile);
933                         return NULL;
934                 }
935                 i++;
936         }
937
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);
941                 return NULL;
942         }
943
944         g_assert (o_config_main_file);
945
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);
949                         return NULL;
950                 }
951         }
952
953         /* Merge settings from command line. They overwrite everything read from
954          * config files. */
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);
959         }
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);
968
969         str = g_string_new (o_config_main_file);
970         if (system_confs->len > 0) {
971                 for (i = 0; i < system_confs->len; i++) {
972                         if (i == 0)
973                                 g_string_append (str, " (lib: ");
974                         else
975                                 g_string_append (str, ", ");
976                         g_string_append (str, system_confs->pdata[i]);
977                 }
978                 g_string_append (str, ")");
979         }
980         if (confs->len > 0) {
981                 for (i = 0; i < confs->len; i++) {
982                         if (i == 0)
983                                 g_string_append (str, " (etc: ");
984                         else
985                                 g_string_append (str, ", ");
986                         g_string_append (str, confs->pdata[i]);
987                 }
988                 g_string_append (str, ")");
989         }
990
991         if (out_config_main_file)
992                 *out_config_main_file = o_config_main_file;
993         else
994                 g_free (o_config_main_file);
995         if (out_config_description)
996                 *out_config_description = g_string_free (str, FALSE);
997         else
998                 g_string_free (str, TRUE);
999
1000         o_config_main_file = NULL;
1001         return keyfile;
1002 }
1003
1004 static gboolean
1005 _is_atomic_section (const char *const*atomic_section_prefixes, const char *group)
1006 {
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))
1011                                 return TRUE;
1012                 }
1013         }
1014         return FALSE;
1015 }
1016
1017 static void
1018 _string_append_val (GString *str, const char *value)
1019 {
1020         if (!value)
1021                 return;
1022         g_string_append_c (str, '+');
1023         while (TRUE) {
1024                 switch (*value) {
1025                 case '\0':
1026                         return;
1027                 case '\\':
1028                 case '+':
1029                 case '#':
1030                 case ':':
1031                         g_string_append_c (str, '+');
1032                 default:
1033                         g_string_append_c (str, *value);
1034                 }
1035                 value++;
1036         }
1037 }
1038
1039 static char *
1040 _keyfile_serialize_section (GKeyFile *keyfile, const char *group)
1041 {
1042         gs_strfreev char **keys = NULL;
1043         GString *str;
1044         guint k;
1045
1046         if (keyfile)
1047                 keys = g_key_file_get_keys (keyfile, group, NULL, NULL);
1048         if (!keys)
1049                 return g_strdup ("0#");
1050
1051         /* prepend a version. */
1052         str = g_string_new ("1#");
1053
1054         for (k = 0; keys[k]; k++) {
1055                 const char *key = keys[k];
1056                 gs_free char *value = NULL;
1057
1058                 _string_append_val (str, key);
1059                 g_string_append_c (str, ':');
1060
1061                 value = g_key_file_get_value (keyfile, group, key, NULL);
1062                 _string_append_val (str, value);
1063                 g_string_append_c (str, '#');
1064         }
1065         return g_string_free (str, FALSE);
1066 }
1067
1068 gboolean
1069 nm_config_keyfile_has_global_dns_config (GKeyFile *keyfile, gboolean internal)
1070 {
1071         gs_strfreev char **groups = NULL;
1072         guint g;
1073         const char *prefix;
1074
1075         if (!keyfile)
1076                 return FALSE;
1077         if (g_key_file_has_group (keyfile,
1078                                   internal
1079                                       ? NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS
1080                                       : NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS))
1081                 return TRUE;
1082
1083         groups = g_key_file_get_groups (keyfile, NULL);
1084         if (!groups)
1085                 return FALSE;
1086
1087         prefix = internal ? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN : NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN;
1088
1089         for (g = 0; groups[g]; g++) {
1090                 if (g_str_has_prefix (groups[g], prefix))
1091                         return TRUE;
1092         }
1093         return FALSE;
1094 }
1095
1096 /**
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
1102  *   the file.
1103  *
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".
1110  *
1111  * Returns: a #GKeyFile instance with the internal configuration.
1112  */
1113 static GKeyFile *
1114 intern_config_read (const char *filename,
1115                     GKeyFile *keyfile_conf,
1116                     const char *const*atomic_section_prefixes,
1117                     gboolean *out_needs_rewrite)
1118 {
1119         GKeyFile *keyfile_intern;
1120         GKeyFile *keyfile;
1121         gboolean needs_rewrite = FALSE;
1122         gs_strfreev char **groups = NULL;
1123         guint g, k;
1124         gboolean has_intern = FALSE;
1125
1126         g_return_val_if_fail (filename, NULL);
1127
1128         if (!*filename) {
1129                 if (out_needs_rewrite)
1130                         *out_needs_rewrite = FALSE;
1131                 return NULL;
1132         }
1133
1134         keyfile_intern = nm_config_create_keyfile ();
1135
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;
1139                 goto out;
1140         }
1141
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;
1147
1148                 if (!strcmp (group, NM_CONFIG_KEYFILE_GROUP_CONFIG))
1149                         continue;
1150
1151                 keys = g_key_file_get_keys (keyfile, group, NULL, NULL);
1152                 if (!keys)
1153                         continue;
1154
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);
1157
1158                 if (is_atomic) {
1159                         gs_free char *conf_section_was = NULL;
1160                         gs_free char *conf_section_is = NULL;
1161
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);
1164
1165                         if (g_strcmp0 (conf_section_was, conf_section_is) != 0) {
1166                                 /* the section no longer matches. Skip it entirely. */
1167                                 needs_rewrite = TRUE;
1168                                 continue;
1169                         }
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, "");
1174                 }
1175
1176                 for (k = 0; keys[k]; k++) {
1177                         gs_free char *value_set = NULL;
1178                         const char *key = keys[k];
1179
1180                         value_set = g_key_file_get_value (keyfile, group, key, NULL);
1181
1182                         if (is_intern) {
1183                                 has_intern = TRUE;
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)
1187                                         continue;
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);
1194
1195                                 if (keyfile_conf)
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);
1198
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
1203                                          * rewrite it. */
1204                                         needs_rewrite = TRUE;
1205                                         continue;
1206                                 }
1207                                 has_intern = 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;
1214
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. */
1217                                         continue;
1218                                 }
1219
1220                                 if (keyfile_conf)
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);
1223
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;
1230                                         continue;
1231                                 }
1232                                 has_intern = 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
1235                                  * user key. */
1236                                 g_key_file_set_value (keyfile_intern, group, key, "");
1237                         } else
1238                                 needs_rewrite = TRUE;
1239                 }
1240         }
1241
1242 out:
1243         /*
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.
1248          */
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;
1257                         }
1258                 }
1259         }
1260
1261         g_key_file_unref (keyfile);
1262
1263         if (out_needs_rewrite)
1264                 *out_needs_rewrite = needs_rewrite;
1265
1266         nm_log_dbg (LOGD_CORE, "intern config file \"%s\"", filename);
1267
1268         if (!has_intern) {
1269                 g_key_file_unref (keyfile_intern);
1270                 return NULL;
1271         }
1272         return keyfile_intern;
1273 }
1274
1275 static int
1276 _intern_config_write_sort_fcn (const char **a, const char **b, const char *const*atomic_section_prefixes)
1277 {
1278         const char *g_a = (a ? *a : NULL);
1279         const char *g_b = (b ? *b : NULL);
1280         gboolean a_is, b_is;
1281
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);
1284
1285         if (a_is != b_is) {
1286                 if (a_is)
1287                         return 1;
1288                 return -1;
1289         }
1290         if (!a_is) {
1291                 a_is = _is_atomic_section (atomic_section_prefixes, g_a);
1292                 b_is = _is_atomic_section (atomic_section_prefixes, g_b);
1293
1294                 if (a_is != b_is) {
1295                         if (a_is)
1296                                 return 1;
1297                         return -1;
1298                 }
1299         }
1300         return g_strcmp0 (g_a, g_b);
1301 }
1302
1303 static gboolean
1304 intern_config_write (const char *filename,
1305                      GKeyFile *keyfile_intern,
1306                      GKeyFile *keyfile_conf,
1307                      const char *const*atomic_section_prefixes,
1308                      GError **error)
1309 {
1310         GKeyFile *keyfile;
1311         gs_strfreev char **groups = NULL;
1312         guint g, k;
1313         gboolean has_intern = FALSE;
1314         gboolean success = FALSE;
1315         GError *local = NULL;
1316
1317         g_return_val_if_fail (filename, FALSE);
1318
1319         if (!*filename) {
1320                 g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "no filename to write (use --intern-config?)");
1321                 return FALSE;
1322         }
1323
1324         keyfile = nm_config_create_keyfile ();
1325
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),
1331                                            sizeof (char *),
1332                                            (GCompareDataFunc) _intern_config_write_sort_fcn,
1333                                            (gpointer) atomic_section_prefixes);
1334                 }
1335         }
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;
1340
1341                 keys = g_key_file_get_keys (keyfile_intern, group, NULL, NULL);
1342                 if (!keys)
1343                         continue;
1344
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);
1347
1348                 if (is_atomic) {
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#"). */
1354                                 continue;
1355                         } else {
1356                                 gs_free char *conf_section_is = NULL;
1357
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'",
1362                                                         NULL);
1363                         }
1364                 }
1365
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;
1370
1371                         if (   !is_intern
1372                             && strcmp (key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS) == 0) {
1373                                 g_warn_if_fail (is_atomic);
1374                                 continue;
1375                         }
1376
1377                         value_set = g_key_file_get_value (keyfile_intern, group, key, NULL);
1378
1379                         if (is_intern) {
1380                                 has_intern = TRUE;
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);
1384                         else {
1385                                 gs_free char *value_was = NULL;
1386
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)];
1394
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 ();
1398                                                 continue;
1399                                         }
1400
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. */
1404                                                 continue;
1405                                         }
1406
1407                                         if (keyfile_conf) {
1408                                                 value_was = g_key_file_get_value (keyfile_conf, group, key_base, NULL);
1409                                                 if (value_was)
1410                                                         g_key_file_set_value (keyfile, group, key, value_was);
1411                                         }
1412                                 } else {
1413                                         if (keyfile_conf) {
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. */
1418                                                         continue;
1419                                                 }
1420                                                 if (value_was) {
1421                                                         gs_free char *key_was = NULL;
1422
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);
1425                                                 }
1426                                         }
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);
1429                                 }
1430                         }
1431                 }
1432                 if (   is_intern
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'",
1436                                                 NULL);
1437                 }
1438         }
1439
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"
1444                                 "\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"
1452                                 "\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"
1456                                 "\n"
1457                                 " Internal sections of the form [" NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN "*] cannot\n"
1458                                 " be set by user configuration.\n"
1459                                 "\n"
1460                                 " CHANGES TO THIS FILE WILL BE OVERWRITTEN",
1461                                 NULL);
1462
1463         success = g_key_file_save_to_file (keyfile, filename, &local);
1464
1465         nm_log_dbg (LOGD_CORE, "write intern config file \"%s\"%s%s", filename, success ? "" : ": ", success ? "" : local->message);
1466         g_key_file_unref (keyfile);
1467         if (!success)
1468                 g_propagate_error (error, local);
1469         return success;
1470 }
1471
1472 /************************************************************************/
1473
1474 GSList *
1475 nm_config_get_match_spec (const GKeyFile *keyfile, const char *group, const char *key, gboolean *out_has_key)
1476 {
1477         gs_free char *value = NULL;
1478
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);
1483         if (out_has_key)
1484                 *out_has_key = !!value;
1485         return nm_match_spec_split (value);
1486 }
1487
1488 /************************************************************************/
1489
1490 gboolean
1491 nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError **error)
1492 {
1493         NMConfigPrivate *priv;
1494         GKeyFile *keyfile;
1495         char **groups;
1496         const NMGlobalDnsConfig *old_global_dns;
1497         guint i;
1498
1499         g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
1500
1501         priv = NM_CONFIG_GET_PRIVATE (self);
1502         g_return_val_if_fail (priv->config_data, FALSE);
1503
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");
1508                 return FALSE;
1509         }
1510
1511         keyfile = nm_config_data_clone_keyfile_intern (priv->config_data);
1512
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);
1519         }
1520         g_strfreev (groups);
1521
1522         /* An empty configuration removes everything from internal configuration file */
1523         if (nm_global_dns_config_is_empty (global_dns))
1524                 goto done;
1525
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),
1529                                            -1);
1530
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),
1533                                            -1);
1534
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;
1538
1539                 group_name = g_strdup_printf (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN "%s",
1540                                               nm_global_dns_domain_get_name (domain));
1541
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);
1546         }
1547
1548 done:
1549         nm_config_set_values (self, keyfile, TRUE, FALSE);
1550         g_key_file_unref (keyfile);
1551
1552         return TRUE;
1553 }
1554
1555 /**
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
1565  *   no changes.
1566  *
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.
1570  *
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
1574  *      them, that's it.
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.
1585  */
1586 void
1587 nm_config_set_values (NMConfig *self,
1588                       GKeyFile *keyfile_intern_new,
1589                       gboolean allow_write,
1590                       gboolean force_rewrite)
1591 {
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;
1599         gint g;
1600
1601         g_return_if_fail (NM_IS_CONFIG (self));
1602
1603         priv = NM_CONFIG_GET_PRIVATE (self);
1604
1605         keyfile_intern_current = _nm_config_data_get_keyfile_intern (priv->config_data);
1606
1607         keyfile_new = nm_config_create_keyfile ();
1608         if (keyfile_intern_new)
1609                 _nm_keyfile_copy (keyfile_new, keyfile_intern_new);
1610
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, "");
1616         }
1617
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);
1620
1621         nm_log_dbg (LOGD_CORE, "set values(): %s", new_data ? "has changes" : "no changes");
1622
1623         if (allow_write
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);
1638                         }
1639                 } else
1640                         nm_log_dbg (LOGD_CORE, "don't persistate internal configuration (no file set, use --intern-config?)");
1641         }
1642         if (new_data)
1643                 _set_config_data (self, new_data, 0);
1644
1645         g_key_file_unref (keyfile_new);
1646 }
1647
1648 /************************************************************************/
1649
1650 void
1651 nm_config_reload (NMConfig *self, int signal)
1652 {
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;
1661
1662         g_return_if_fail (NM_IS_CONFIG (self));
1663
1664         priv = NM_CONFIG_GET_PRIVATE (self);
1665
1666         if (signal != SIGHUP) {
1667                 _set_config_data (self, NULL, signal);
1668                 return;
1669         }
1670
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.
1674          */
1675         keyfile = read_entire_config (&priv->cli,
1676                                       priv->config_dir,
1677                                       priv->system_config_dir,
1678                                       &config_main_file,
1679                                       &config_description,
1680                                       &error);
1681         if (!keyfile) {
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);
1685                 return;
1686         }
1687
1688         no_auto_default = no_auto_default_from_file (priv->no_auto_default_file);
1689
1690         keyfile_intern = intern_config_read (priv->intern_config_file,
1691                                              keyfile,
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);
1697         }
1698
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);
1703         if (keyfile_intern)
1704                 g_key_file_unref (keyfile_intern);
1705
1706         _set_config_data (self, new_data, signal);
1707 }
1708
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"),
1722 );
1723
1724 static void
1725 _set_config_data (NMConfig *self, NMConfigData *new_data, int signal)
1726 {
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;
1731
1732         switch (signal) {
1733         case SIGHUP:
1734                 changes = NM_CONFIG_CHANGE_SIGHUP;
1735                 break;
1736         case SIGUSR1:
1737                 changes = NM_CONFIG_CHANGE_SIGUSR1;
1738                 break;
1739         case SIGUSR2:
1740                 changes = NM_CONFIG_CHANGE_SIGUSR2;
1741                 break;
1742         default:
1743                 changes = NM_CONFIG_CHANGE_NONE;
1744                 break;
1745         }
1746
1747         if (new_data) {
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);
1751                 else
1752                         changes |= changes_diff;
1753         }
1754
1755         if (changes == NM_CONFIG_CHANGE_NONE)
1756                 return;
1757
1758         if (new_data) {
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));
1765         else
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,
1769                        changes, old_data);
1770         if (new_data)
1771                 g_object_unref (old_data);
1772 }
1773
1774 NM_DEFINE_SINGLETON_REGISTER (NMConfig);
1775
1776 NMConfig *
1777 nm_config_get (void)
1778 {
1779         g_assert (singleton_instance);
1780         return singleton_instance;
1781 }
1782
1783 NMConfig *
1784 nm_config_setup (const NMConfigCmdLineOptions *cli, char **atomic_section_prefixes, GError **error)
1785 {
1786         g_assert (!singleton_instance);
1787
1788         singleton_instance = nm_config_new (cli, atomic_section_prefixes, error);
1789         if (singleton_instance) {
1790                 nm_singleton_instance_register ();
1791
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);
1795         }
1796         return singleton_instance;
1797 }
1798
1799 static gboolean
1800 init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
1801 {
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;
1809
1810         if (priv->config_dir) {
1811                 /* Object is already initialized. */
1812                 if (priv->config_data)
1813                         return TRUE;
1814                 g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "unspecified error");
1815                 return FALSE;
1816         }
1817
1818         if (priv->cli.config_dir)
1819                 priv->config_dir = g_strdup (priv->cli.config_dir);
1820         else
1821                 priv->config_dir = g_strdup (DEFAULT_CONFIG_DIR);
1822
1823         if (priv->cli.system_config_dir)
1824                 priv->system_config_dir = g_strdup (priv->cli.system_config_dir);
1825         else
1826                 priv->system_config_dir = g_strdup (DEFAULT_SYSTEM_CONFIG_DIR);
1827
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 ("");
1833         }
1834
1835         if (priv->cli.intern_config_file)
1836                 priv->intern_config_file = g_strdup (priv->cli.intern_config_file);
1837         else
1838                 priv->intern_config_file = g_strdup (DEFAULT_INTERN_CONFIG_FILE);
1839
1840         keyfile = read_entire_config (&priv->cli,
1841                                       priv->config_dir,
1842                                       priv->system_config_dir,
1843                                       &config_main_file,
1844                                       &config_description,
1845                                       error);
1846         if (!keyfile)
1847                 return FALSE;
1848
1849         /* Initialize read only private members */
1850
1851         if (priv->cli.no_auto_default_file)
1852                 priv->no_auto_default_file = g_strdup (priv->cli.no_auto_default_file);
1853         else
1854                 priv->no_auto_default_file = g_strdup (DEFAULT_NO_AUTO_DEFAULT_FILE);
1855
1856         priv->plugins = _nm_utils_strv_cleanup (g_key_file_get_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", NULL, NULL),
1857                                                 TRUE, TRUE, TRUE);
1858         if (!priv->plugins)
1859                 priv->plugins = g_new0 (char *, 1);
1860
1861         priv->monitor_connection_files = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "monitor-connection-files", FALSE);
1862
1863         priv->auth_polkit = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "auth-polkit", NM_CONFIG_DEFAULT_AUTH_POLKIT);
1864
1865         priv->dhcp_client = nm_strstrip (g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "dhcp", NULL));
1866
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));
1869
1870         priv->debug = g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "debug", NULL);
1871
1872         priv->configure_and_quit = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", FALSE);
1873
1874         no_auto_default = no_auto_default_from_file (priv->no_auto_default_file);
1875
1876         keyfile_intern = intern_config_read (priv->intern_config_file,
1877                                              keyfile,
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);
1883         }
1884
1885         priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile, keyfile_intern);
1886
1887         priv->config_data = g_object_ref (priv->config_data_orig);
1888
1889         g_free (config_main_file);
1890         g_free (config_description);
1891         g_key_file_unref (keyfile);
1892         if (keyfile_intern)
1893                 g_key_file_unref (keyfile_intern);
1894         return TRUE;
1895 }
1896
1897 NMConfig *
1898 nm_config_new (const NMConfigCmdLineOptions *cli, char **atomic_section_prefixes, GError **error)
1899 {
1900         return NM_CONFIG (g_initable_new (NM_TYPE_CONFIG,
1901                                           NULL,
1902                                           error,
1903                                           NM_CONFIG_CMD_LINE_OPTIONS, cli,
1904                                           NM_CONFIG_ATOMIC_SECTION_PREFIXES, atomic_section_prefixes,
1905                                           NULL));
1906 }
1907
1908 static void
1909 nm_config_init (NMConfig *config)
1910 {
1911         NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (config);
1912
1913         priv->auth_polkit = NM_CONFIG_DEFAULT_AUTH_POLKIT;
1914 }
1915
1916 static void
1917 finalize (GObject *gobject)
1918 {
1919         NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject);
1920
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);
1931
1932         _nm_config_cmd_line_options_clear (&priv->cli);
1933
1934         g_clear_object (&priv->config_data);
1935         g_clear_object (&priv->config_data_orig);
1936
1937         G_OBJECT_CLASS (nm_config_parent_class)->finalize (gobject);
1938 }
1939
1940 static void
1941 set_property (GObject *object, guint prop_id,
1942               const GValue *value, GParamSpec *pspec)
1943 {
1944         NMConfig *self = NM_CONFIG (object);
1945         NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
1946         NMConfigCmdLineOptions *cli;
1947
1948         switch (prop_id) {
1949         case PROP_CMD_LINE_OPTIONS:
1950                 /* construct only */
1951                 cli = g_value_get_pointer (value);
1952                 if (!cli)
1953                         _nm_config_cmd_line_options_clear (&priv->cli);
1954                 else
1955                         _nm_config_cmd_line_options_copy (cli, &priv->cli);
1956                 break;
1957         case PROP_ATOMIC_SECTION_PREFIXES:
1958                 /* construct only */
1959                 priv->atomic_section_prefixes = g_strdupv (g_value_get_boxed (value));
1960                 break;
1961         default:
1962                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1963                 break;
1964         }
1965 }
1966
1967 static void
1968 nm_config_class_init (NMConfigClass *config_class)
1969 {
1970         GObjectClass *object_class = G_OBJECT_CLASS (config_class);
1971
1972         g_type_class_add_private (config_class, sizeof (NMConfigPrivate));
1973         object_class->finalize = finalize;
1974         object_class->set_property = set_property;
1975
1976         g_object_class_install_property
1977             (object_class, PROP_CMD_LINE_OPTIONS,
1978              g_param_spec_pointer (NM_CONFIG_CMD_LINE_OPTIONS, "", "",
1979                                    G_PARAM_WRITABLE |
1980                                    G_PARAM_CONSTRUCT_ONLY |
1981                                    G_PARAM_STATIC_STRINGS));
1982
1983         g_object_class_install_property
1984             (object_class, PROP_ATOMIC_SECTION_PREFIXES,
1985              g_param_spec_boxed (NM_CONFIG_ATOMIC_SECTION_PREFIXES, "", "",
1986                                  G_TYPE_STRV,
1987                                  G_PARAM_WRITABLE |
1988                                  G_PARAM_CONSTRUCT_ONLY |
1989                                  G_PARAM_STATIC_STRINGS));
1990
1991         signals[SIGNAL_CONFIG_CHANGED] =
1992             g_signal_new (NM_CONFIG_SIGNAL_CONFIG_CHANGED,
1993                           G_OBJECT_CLASS_TYPE (object_class),
1994                           G_SIGNAL_RUN_FIRST,
1995                           0,
1996                           NULL, NULL, NULL,
1997                           G_TYPE_NONE,
1998                           3,
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, */
2003                           G_TYPE_UINT,
2004                           NM_TYPE_CONFIG_DATA);
2005
2006         G_STATIC_ASSERT_EXPR (sizeof (guint) == sizeof (NMConfigChangeFlags));
2007         G_STATIC_ASSERT_EXPR (((gint64) ((NMConfigChangeFlags) -1)) > ((gint64) 0));
2008 }
2009
2010 static void
2011 nm_config_initable_iface_init (GInitableIface *iface)
2012 {
2013         iface->init = init_sync;
2014 }
2015