1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager -- Network link manager
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Copyright (C) 2011 Red Hat, Inc.
19 * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de>
22 #include "nm-default.h"
24 #include "nm-config-data.h"
28 #include "nm-config.h"
29 #include "nm-device.h"
30 #include "nm-core-internal.h"
31 #include "nm-keyfile-internal.h"
37 /* have a separate boolean field @has, because a @spec with
38 * value %NULL does not necessarily mean, that the property
39 * "match-device" was unspecified. */
46 char *config_main_file;
47 char *config_description;
50 GKeyFile *keyfile_user;
51 GKeyFile *keyfile_intern;
53 /* A zero-terminated list of pre-processed information from the
54 * [connection] sections. This is to speed up lookup. */
55 ConnectionInfo *connection_infos;
69 GSList *ignore_carrier;
70 GSList *assume_ipv6ll_only;
75 NMGlobalDnsConfig *global_dns;
79 } NMConfigDataPrivate;
81 struct _NMGlobalDnsDomain {
87 struct _NMGlobalDnsConfig {
97 PROP_CONFIG_MAIN_FILE,
98 PROP_CONFIG_DESCRIPTION,
101 PROP_CONNECTIVITY_URI,
102 PROP_CONNECTIVITY_INTERVAL,
103 PROP_CONNECTIVITY_RESPONSE,
104 PROP_NO_AUTO_DEFAULT,
110 G_DEFINE_TYPE (NMConfigData, nm_config_data, G_TYPE_OBJECT)
112 #define NM_CONFIG_DATA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONFIG_DATA, NMConfigDataPrivate))
114 /************************************************************************/
116 #define _HAS_PREFIX(str, prefix) \
118 const char *_str = (str); \
119 g_str_has_prefix ( _str, ""prefix"") && _str[NM_STRLEN(prefix)] != '\0'; \
122 /************************************************************************/
125 nm_config_data_get_config_main_file (const NMConfigData *self)
127 g_return_val_if_fail (self, NULL);
129 return NM_CONFIG_DATA_GET_PRIVATE (self)->config_main_file;
133 nm_config_data_get_config_description (const NMConfigData *self)
135 g_return_val_if_fail (self, NULL);
137 return NM_CONFIG_DATA_GET_PRIVATE (self)->config_description;
141 nm_config_data_has_group (const NMConfigData *self, const char *group)
143 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
144 g_return_val_if_fail (group && *group, FALSE);
146 return g_key_file_has_group (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, group);
150 nm_config_data_get_value (const NMConfigData *self, const char *group, const char *key, NMConfigGetValueFlags flags)
152 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), NULL);
153 g_return_val_if_fail (group && *group, NULL);
154 g_return_val_if_fail (key && *key, NULL);
156 return nm_config_keyfile_get_value (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, group, key, flags);
159 const char *nm_config_data_get_value_cached (const NMConfigData *self, const char *group, const char *key, NMConfigGetValueFlags flags)
161 NMConfigDataPrivate *priv;
163 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), NULL);
164 g_return_val_if_fail (group && *group, NULL);
165 g_return_val_if_fail (key && *key, NULL);
167 priv = NM_CONFIG_DATA_GET_PRIVATE (self);
169 /* we modify @value_cached. In C++ jargon, the field is mutable. */
170 g_free (priv->value_cached);
171 priv->value_cached = nm_config_keyfile_get_value (priv->keyfile, group, key, flags);
172 return priv->value_cached;
176 nm_config_data_has_value (const NMConfigData *self, const char *group, const char *key, NMConfigGetValueFlags flags)
178 gs_free char *value = NULL;
180 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
181 g_return_val_if_fail (group && *group, FALSE);
182 g_return_val_if_fail (key && *key, FALSE);
184 value = nm_config_keyfile_get_value (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, group, key, flags);
189 nm_config_data_get_value_boolean (const NMConfigData *self, const char *group, const char *key, gint default_value)
192 gint value = default_value;
194 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), default_value);
195 g_return_val_if_fail (group && *group, default_value);
196 g_return_val_if_fail (key && *key, default_value);
198 /* when parsing the boolean, base it on the raw value from g_key_file_get_value(). */
199 str = g_key_file_get_value (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, group, key, NULL);
201 value = nm_config_parse_boolean (str, default_value);
208 nm_config_data_get_connectivity_uri (const NMConfigData *self)
210 g_return_val_if_fail (self, NULL);
212 return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.uri;
216 nm_config_data_get_connectivity_interval (const NMConfigData *self)
218 g_return_val_if_fail (self, 0);
220 return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.interval;
224 nm_config_data_get_connectivity_response (const NMConfigData *self)
226 g_return_val_if_fail (self != NULL, NULL);
228 return NM_CONFIG_DATA_GET_PRIVATE (self)->connectivity.response;
232 nm_config_data_get_no_auto_default (const NMConfigData *self)
234 g_return_val_if_fail (self, FALSE);
236 return (const char *const*) NM_CONFIG_DATA_GET_PRIVATE (self)->no_auto_default.arr;
240 nm_config_data_get_no_auto_default_for_device (const NMConfigData *self, NMDevice *device)
242 NMConfigDataPrivate *priv;
244 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
245 g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
247 priv = NM_CONFIG_DATA_GET_PRIVATE (self);
248 return nm_device_spec_match_list (device, priv->no_auto_default.specs)
249 || nm_device_spec_match_list (device, priv->no_auto_default.specs_config);
253 nm_config_data_get_dns_mode (const NMConfigData *self)
255 g_return_val_if_fail (self, NULL);
257 return NM_CONFIG_DATA_GET_PRIVATE (self)->dns_mode;
261 nm_config_data_get_rc_manager (const NMConfigData *self)
263 g_return_val_if_fail (self, NULL);
265 return NM_CONFIG_DATA_GET_PRIVATE (self)->rc_manager;
269 nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device)
271 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
272 g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
274 return nm_device_spec_match_list (device, NM_CONFIG_DATA_GET_PRIVATE (self)->ignore_carrier);
278 nm_config_data_get_assume_ipv6ll_only (const NMConfigData *self, NMDevice *device)
280 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
281 g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
283 return nm_device_spec_match_list (device, NM_CONFIG_DATA_GET_PRIVATE (self)->assume_ipv6ll_only);
287 nm_config_data_clone_keyfile_intern (const NMConfigData *self)
289 NMConfigDataPrivate *priv;
292 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
294 priv = NM_CONFIG_DATA_GET_PRIVATE (self);
296 keyfile = nm_config_create_keyfile ();
297 if (priv->keyfile_intern)
298 _nm_keyfile_copy (keyfile, priv->keyfile_intern);
303 _nm_config_data_get_keyfile (const NMConfigData *self)
305 return NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile;
309 _nm_config_data_get_keyfile_intern (const NMConfigData *self)
311 return NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile_intern;
315 _nm_config_data_get_keyfile_user (const NMConfigData *self)
317 return NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile_user;
320 /************************************************************************/
323 * nm_config_data_get_groups:
324 * @self: the #NMConfigData instance
326 * Returns: (transfer full): the list of groups in the configuration. The order
327 * of the section is undefined, as the configuration gets merged from multiple
331 nm_config_data_get_groups (const NMConfigData *self)
333 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), NULL);
335 return g_key_file_get_groups (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, NULL);
339 nm_config_data_get_keys (const NMConfigData *self, const char *group)
341 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), NULL);
342 g_return_val_if_fail (group && *group, NULL);
344 return g_key_file_get_keys (NM_CONFIG_DATA_GET_PRIVATE (self)->keyfile, group, NULL, NULL);
348 * nm_config_data_is_intern_atomic_group:
350 * @group: name of the group to check.
352 * whether a configuration group @group exists and is entirely overwritten
353 * by internal configuration, i.e. whether it is an atomic group that is
356 * It doesn't say, that there actually is a user setting that was overwritten. That
357 * means there could be no corresponding section defined in user configuration
358 * that required overwriting.
360 * Returns: %TRUE if @group exists and is an atomic group set via internal configuration.
363 nm_config_data_is_intern_atomic_group (const NMConfigData *self, const char *group)
365 NMConfigDataPrivate *priv;
367 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
368 g_return_val_if_fail (group && *group, FALSE);
370 priv = NM_CONFIG_DATA_GET_PRIVATE (self);
372 if ( !priv->keyfile_intern
373 || !g_key_file_has_key (priv->keyfile_intern, group, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, NULL))
376 /* we have a .was entry for the section. That means that the section would be overwritten
377 * from user configuration. But it doesn't mean that the merged configuration contains this
378 * groups, because the internal setting could hide the user section.
379 * Only return TRUE, if we actually have such a group in the merged configuration.*/
380 return g_key_file_has_group (priv->keyfile, group);
383 /************************************************************************/
386 _merge_keyfiles (GKeyFile *keyfile_user, GKeyFile *keyfile_intern)
388 gs_strfreev char **groups = NULL;
393 keyfile = nm_config_create_keyfile ();
395 _nm_keyfile_copy (keyfile, keyfile_user);
399 groups = g_key_file_get_groups (keyfile_intern, &ngroups);
403 /* we must reverse the order of the connection settings so that we
404 * have lowest priority last. */
405 _nm_config_sort_groups (groups, ngroups);
406 for (g = 0; groups[g]; g++) {
407 const char *group = groups[g];
408 gs_strfreev char **keys = NULL;
409 gboolean is_intern, is_atomic = FALSE;
411 keys = g_key_file_get_keys (keyfile_intern, group, NULL, NULL);
415 is_intern = g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN);
417 && g_key_file_has_key (keyfile_intern, group, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS, NULL)) {
418 /* the entire section is atomically overwritten by @keyfile_intern. */
419 g_key_file_remove_group (keyfile, group, NULL);
423 for (k = 0; keys[k]; k++) {
424 const char *key = keys[k];
425 gs_free char *value = NULL;
427 if (is_atomic && strcmp (key, NM_CONFIG_KEYFILE_KEY_ATOMIC_SECTION_WAS) == 0)
430 if ( !is_intern && !is_atomic
431 && _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_WAS)) {
432 const char *key_base = &key[NM_STRLEN (NM_CONFIG_KEYFILE_KEYPREFIX_WAS)];
434 if (!g_key_file_has_key (keyfile_intern, group, key_base, NULL))
435 g_key_file_remove_key (keyfile, group, key_base, NULL);
438 if (!is_intern && !is_atomic && _HAS_PREFIX (key, NM_CONFIG_KEYFILE_KEYPREFIX_SET))
441 value = g_key_file_get_value (keyfile_intern, group, key, NULL);
442 g_key_file_set_value (keyfile, group, key, value);
448 /************************************************************************/
451 _nm_config_data_log_sort (const char **pa, const char **pb, gpointer dummy)
453 gboolean a_is_connection, b_is_connection;
454 gboolean a_is_intern, b_is_intern;
458 /* we sort intern groups to the end. */
459 a_is_intern = g_str_has_prefix (a, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN);
460 b_is_intern = g_str_has_prefix (b, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN);
462 if (a_is_intern && b_is_intern)
469 /* we sort connection groups before intern groups (to the end). */
470 a_is_connection = a && g_str_has_prefix (a, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION);
471 b_is_connection = b && g_str_has_prefix (b, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION);
473 if (a_is_connection && b_is_connection) {
474 /* if both are connection groups, we want the explicit [connection] group first. */
475 a_is_connection = a[NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0';
476 b_is_connection = b[NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0';
478 if (a_is_connection != b_is_connection) {
483 /* the sections are ordered lowest-priority first. Reverse their order. */
484 return pa < pb ? 1 : -1;
486 if (a_is_connection && !b_is_connection)
488 if (b_is_connection && !a_is_connection)
496 nm_config_data_log (const NMConfigData *self,
498 const char *key_prefix,
499 /* FILE* */ gpointer print_stream)
501 NMConfigDataPrivate *priv;
502 gs_strfreev char **groups = NULL;
505 FILE *stream = print_stream;
507 g_return_if_fail (NM_IS_CONFIG_DATA (self));
509 if (!stream && !nm_logging_enabled (LOGL_DEBUG, LOGD_CORE))
517 #define _LOG(stream, prefix, ...) \
520 _nm_log (LOGL_DEBUG, LOGD_CORE, 0, "%s"_NM_UTILS_MACRO_FIRST(__VA_ARGS__)"%s", prefix _NM_UTILS_MACRO_REST (__VA_ARGS__), ""); \
522 fprintf (stream, "%s"_NM_UTILS_MACRO_FIRST(__VA_ARGS__)"%s", prefix _NM_UTILS_MACRO_REST (__VA_ARGS__), "\n"); \
525 priv = NM_CONFIG_DATA_GET_PRIVATE (self);
527 groups = g_key_file_get_groups (priv->keyfile, &ngroups);
531 if (groups && groups[0]) {
532 g_qsort_with_data (groups, ngroups,
534 (GCompareDataFunc) _nm_config_data_log_sort,
539 _LOG (stream, prefix, "config-data[%p]: %lu groups", self, (unsigned long) ngroups);
541 for (g = 0; g < ngroups; g++) {
542 const char *group = groups[g];
543 gs_strfreev char **keys = NULL;
546 is_atomic = nm_config_data_is_intern_atomic_group (self, group);
548 _LOG (stream, prefix, "");
549 _LOG (stream, prefix, "[%s]%s", group, is_atomic && !stream ? " # atomic section" : "");
551 keys = g_key_file_get_keys (priv->keyfile, group, NULL, NULL);
552 for (k = 0; keys && keys[k]; k++) {
553 const char *key = keys[k];
554 gs_free char *value = NULL;
556 value = g_key_file_get_value (priv->keyfile, group, key, NULL);
557 _LOG (stream, prefix, "%s%s=%s", key_prefix, key, value);
564 /************************************************************************/
567 nm_global_dns_config_get_searches (const NMGlobalDnsConfig *dns)
569 g_return_val_if_fail (dns, NULL);
571 return (const char *const *) dns->searches;
575 nm_global_dns_config_get_options (const NMGlobalDnsConfig *dns)
577 g_return_val_if_fail (dns, NULL);
579 return (const char *const *) dns->options;
583 nm_global_dns_config_get_num_domains (const NMGlobalDnsConfig *dns)
585 g_return_val_if_fail (dns, 0);
586 g_return_val_if_fail (dns->domains, 0);
588 return g_hash_table_size (dns->domains);
592 nm_global_dns_config_get_domain (const NMGlobalDnsConfig *dns, guint i)
594 NMGlobalDnsDomain *domain;
596 g_return_val_if_fail (dns, NULL);
597 g_return_val_if_fail (dns->domains, NULL);
598 g_return_val_if_fail (dns->domain_list, NULL);
599 g_return_val_if_fail (i < g_strv_length (dns->domain_list), NULL);
601 domain = g_hash_table_lookup (dns->domains, dns->domain_list[i]);
602 g_return_val_if_fail (domain, NULL);
607 NMGlobalDnsDomain *nm_global_dns_config_lookup_domain (const NMGlobalDnsConfig *dns, const char *name)
609 g_return_val_if_fail (dns, NULL);
610 g_return_val_if_fail (dns->domains, NULL);
611 g_return_val_if_fail (name, NULL);
613 return g_hash_table_lookup (dns->domains, name);
617 nm_global_dns_domain_get_name (const NMGlobalDnsDomain *domain)
619 g_return_val_if_fail (domain, NULL);
621 return (const char *) domain->name;
625 nm_global_dns_domain_get_servers (const NMGlobalDnsDomain *domain)
627 g_return_val_if_fail (domain, NULL);
629 return (const char *const *) domain->servers;
633 nm_global_dns_domain_get_options (const NMGlobalDnsDomain *domain)
635 g_return_val_if_fail (domain, NULL);
636 return (const char *const *) domain->options;
640 nm_global_dns_config_is_internal (const NMGlobalDnsConfig *dns)
642 return dns->internal;
646 nm_global_dns_config_is_empty (const NMGlobalDnsConfig *dns)
648 g_return_val_if_fail (dns, TRUE);
649 g_return_val_if_fail (dns->domains, TRUE);
651 return (!dns->searches || g_strv_length (dns->searches) == 0)
652 && (!dns->options || g_strv_length (dns->options) == 0)
653 && g_hash_table_size (dns->domains) == 0;
657 nm_global_dns_config_update_checksum (const NMGlobalDnsConfig *dns, GChecksum *sum)
659 NMGlobalDnsDomain *domain;
663 g_return_if_fail (dns);
664 g_return_if_fail (dns->domains);
665 g_return_if_fail (sum);
667 for (i = 0; dns->searches && dns->searches[i]; i++)
668 g_checksum_update (sum, (guchar *) dns->searches[i], strlen (dns->searches[i]));
669 for (i = 0; dns->options && dns->options[i]; i++)
670 g_checksum_update (sum, (guchar *) dns->options[i], strlen (dns->options[i]));
672 keys = g_list_sort (g_hash_table_get_keys (dns->domains), (GCompareFunc) strcmp);
673 for (key = keys; key; key = g_list_next (key)) {
675 domain = g_hash_table_lookup (dns->domains, key->data);
676 g_assert (domain != NULL);
677 g_checksum_update (sum, (guchar *) domain->name, strlen (domain->name));
679 for (i = 0; domain->servers && domain->servers[i]; i++)
680 g_checksum_update (sum, (guchar *) domain->servers[i], strlen (domain->servers[i]));
681 for (i = 0; domain->options && domain->options[i]; i++)
682 g_checksum_update (sum, (guchar *) domain->options[i], strlen (domain->options[i]));
688 global_dns_domain_free (NMGlobalDnsDomain *domain)
691 g_free (domain->name);
692 g_strfreev (domain->servers);
693 g_strfreev (domain->options);
699 nm_global_dns_config_free (NMGlobalDnsConfig *conf)
702 g_strfreev (conf->searches);
703 g_strfreev (conf->options);
704 g_free (conf->domain_list);
705 g_hash_table_unref (conf->domains);
711 nm_config_data_get_global_dns_config (const NMConfigData *self)
713 g_return_val_if_fail (NM_IS_CONFIG_DATA (self), NULL);
715 return NM_CONFIG_DATA_GET_PRIVATE (self)->global_dns;
719 global_dns_config_update_domain_list (NMGlobalDnsConfig *dns)
723 g_free (dns->domain_list);
724 dns->domain_list = (char **) g_hash_table_get_keys_as_array (dns->domains, &length);
727 static NMGlobalDnsConfig *
728 load_global_dns (GKeyFile *keyfile, gboolean internal)
730 NMGlobalDnsConfig *conf;
731 char *group, *domain_prefix;
732 gs_strfreev char **groups = NULL;
733 int g, i, j, domain_prefix_len;
734 gboolean default_found = FALSE;
738 ? NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS
739 : NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS;
740 domain_prefix = internal
741 ? NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN
742 : NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN;
743 domain_prefix_len = strlen (domain_prefix);
745 if (!nm_config_keyfile_has_global_dns_config (keyfile, internal))
748 conf = g_malloc0 (sizeof (NMGlobalDnsConfig));
749 conf->domains = g_hash_table_new_full (g_str_hash, g_str_equal,
750 g_free, (GDestroyNotify) global_dns_domain_free);
752 strv = g_key_file_get_string_list (keyfile, group, "searches", NULL, NULL);
754 conf->searches = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
756 strv = g_key_file_get_string_list (keyfile, group, "options", NULL, NULL);
758 _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
759 for (i = 0, j = 0; strv[i]; i++) {
760 if (_nm_utils_dns_option_validate (strv[i], NULL, NULL, TRUE, NULL))
766 conf->options = strv;
769 groups = g_key_file_get_groups (keyfile, NULL);
770 for (g = 0; groups[g]; g++) {
772 char **servers = NULL, **options = NULL;
773 NMGlobalDnsDomain *domain;
775 if ( !g_str_has_prefix (groups[g], domain_prefix)
776 || !groups[g][domain_prefix_len])
779 strv = g_key_file_get_string_list (keyfile, groups[g], "servers", NULL, NULL);
781 _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
782 for (i = 0, j = 0; strv[i]; i++) {
783 if ( nm_utils_ipaddr_valid (AF_INET, strv[i])
784 || nm_utils_ipaddr_valid (AF_INET6, strv[i]))
800 strv = g_key_file_get_string_list (keyfile, groups[g], "options", NULL, NULL);
802 options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
804 name = strdup (&groups[g][domain_prefix_len]);
805 domain = g_malloc0 (sizeof (NMGlobalDnsDomain));
807 domain->servers = servers;
808 domain->options = options;
810 g_hash_table_insert (conf->domains, strdup (name), domain);
812 if (!strcmp (name, "*"))
813 default_found = TRUE;
816 if (!default_found) {
817 nm_log_dbg (LOGD_CORE, "%s global DNS configuration is missing default domain, ignore it",
818 internal ? "internal" : "user");
819 nm_global_dns_config_free (conf);
823 conf->internal = internal;
824 global_dns_config_update_domain_list (conf);
830 nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns, GValue *value)
832 GVariantBuilder conf_builder, domains_builder, domain_builder;
833 NMGlobalDnsDomain *domain;
836 g_variant_builder_init (&conf_builder, G_VARIANT_TYPE ("a{sv}"));
841 g_variant_builder_add (&conf_builder, "{sv}", "searches",
842 g_variant_new_strv ((const char *const *) dns->searches, -1));
846 g_variant_builder_add (&conf_builder, "{sv}", "options",
847 g_variant_new_strv ((const char *const *) dns->options, -1));
850 g_variant_builder_init (&domains_builder, G_VARIANT_TYPE ("a{sv}"));
852 g_hash_table_iter_init (&iter, dns->domains);
853 while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &domain)) {
855 g_variant_builder_init (&domain_builder, G_VARIANT_TYPE ("a{sv}"));
857 if (domain->servers) {
858 g_variant_builder_add (&domain_builder, "{sv}", "servers",
859 g_variant_new_strv ((const char *const *) domain->servers, -1));
861 if (domain->options) {
862 g_variant_builder_add (&domain_builder, "{sv}", "options",
863 g_variant_new_strv ((const char *const *) domain->options, -1));
866 g_variant_builder_add (&domains_builder, "{sv}", domain->name,
867 g_variant_builder_end (&domain_builder));
870 g_variant_builder_add (&conf_builder, "{sv}", "domains",
871 g_variant_builder_end (&domains_builder));
873 g_value_take_variant (value, g_variant_builder_end (&conf_builder));
876 static NMGlobalDnsDomain *
877 global_dns_domain_from_dbus (char *name, GVariant *variant)
879 NMGlobalDnsDomain *domain;
885 if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}")))
888 domain = g_malloc0 (sizeof (NMGlobalDnsDomain));
889 domain->name = g_strdup (name);
891 g_variant_iter_init (&iter, variant);
892 while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) {
894 if ( !g_strcmp0 (key, "servers")
895 && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
896 strv = g_variant_dup_strv (val, NULL);
897 _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
898 for (i = 0, j = 0; strv && strv[i]; i++) {
899 if ( nm_utils_ipaddr_valid (AF_INET, strv[i])
900 || nm_utils_ipaddr_valid (AF_INET6, strv[i]))
907 domain->servers = strv;
910 } else if ( !g_strcmp0 (key, "options")
911 && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
912 strv = g_variant_dup_strv (val, NULL);
913 domain->options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
916 g_variant_unref (val);
919 /* At least one server is required */
920 if (!domain->servers) {
921 global_dns_domain_free (domain);
929 nm_global_dns_config_from_dbus (const GValue *value, GError **error)
931 NMGlobalDnsConfig *dns_config;
932 GVariant *variant, *val;
937 if (!G_VALUE_HOLDS_VARIANT (value)) {
938 g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
939 "invalid value type");
943 variant = g_value_get_variant (value);
944 if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}"))) {
945 g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
946 "invalid variant type");
950 dns_config = g_malloc0 (sizeof (NMGlobalDnsConfig));
951 dns_config->domains = g_hash_table_new_full (g_str_hash, g_str_equal,
952 g_free, (GDestroyNotify) global_dns_domain_free);
954 g_variant_iter_init (&iter, variant);
955 while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) {
957 if ( !g_strcmp0 (key, "searches")
958 && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
959 strv = g_variant_dup_strv (val, NULL);
960 dns_config->searches = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
961 } else if ( !g_strcmp0 (key, "options")
962 && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) {
963 strv = g_variant_dup_strv (val, NULL);
964 _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE);
966 for (i = 0, j = 0; strv && strv[i]; i++) {
967 if (_nm_utils_dns_option_validate (strv[i], NULL, NULL, TRUE, NULL))
976 dns_config->options = strv;
977 } else if ( !g_strcmp0 (key, "domains")
978 && g_variant_is_of_type (val, G_VARIANT_TYPE ("a{sv}"))) {
979 NMGlobalDnsDomain *domain;
980 GVariantIter domain_iter;
984 g_variant_iter_init (&domain_iter, val);
985 while (g_variant_iter_next (&domain_iter, "{&sv}", &k, &v)) {
987 domain = global_dns_domain_from_dbus (k, v);
989 g_hash_table_insert (dns_config->domains, strdup (k), domain);
994 g_variant_unref (val);
997 /* An empty value is valid and clears the internal configuration */
998 if ( !nm_global_dns_config_is_empty (dns_config)
999 && !nm_global_dns_config_lookup_domain (dns_config, "*")) {
1000 g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
1001 "Global DNS configuration is missing the default domain");
1002 nm_global_dns_config_free (dns_config);
1006 global_dns_config_update_domain_list (dns_config);
1011 global_dns_equal (NMGlobalDnsConfig *old, NMGlobalDnsConfig *new)
1013 NMGlobalDnsDomain *domain_old, *domain_new;
1014 gpointer key, value_old, value_new;
1015 GHashTableIter iter;
1023 if ( !_nm_utils_strv_equal (old->options, new->options)
1024 || !_nm_utils_strv_equal (old->searches, new->searches))
1027 if ((!old->domains || !new->domains) && old->domains != new->domains)
1030 if (g_hash_table_size (old->domains) != g_hash_table_size (new->domains))
1033 g_hash_table_iter_init (&iter, old->domains);
1034 while (g_hash_table_iter_next (&iter, &key, &value_old)) {
1035 value_new = g_hash_table_lookup (new->domains, key);
1039 domain_old = value_old;
1040 domain_new = value_new;
1042 if ( !_nm_utils_strv_equal (domain_old->options, domain_new->options)
1043 || !_nm_utils_strv_equal (domain_old->servers, domain_new->servers))
1050 /************************************************************************/
1053 nm_config_data_get_connection_default (const NMConfigData *self,
1054 const char *property,
1057 NMConfigDataPrivate *priv;
1058 const ConnectionInfo *connection_info;
1060 g_return_val_if_fail (self, NULL);
1061 g_return_val_if_fail (property && *property, NULL);
1062 g_return_val_if_fail (strchr (property, '.'), NULL);
1064 priv = NM_CONFIG_DATA_GET_PRIVATE (self);
1066 if (!priv->connection_infos)
1069 for (connection_info = &priv->connection_infos[0]; connection_info->group_name; connection_info++) {
1073 /* FIXME: Here we use g_key_file_get_string(). This should be in sync with what keyfile-reader
1076 * Unfortunately that is currently not possible because keyfile-reader does the two steps
1077 * string_to_value(keyfile_to_string(keyfile)) in one. Optimally, keyfile library would
1078 * expose both functions, and we would return here keyfile_to_string(keyfile).
1079 * The caller then could convert the string to the proper value via string_to_value(value). */
1080 value = g_key_file_get_string (priv->keyfile, connection_info->group_name, property, NULL);
1081 if (!value && !connection_info->stop_match)
1085 if (connection_info->match_device.has)
1086 match = device && nm_device_spec_match_list (device, connection_info->match_device.spec);
1096 _get_connection_info_init (ConnectionInfo *connection_info, GKeyFile *keyfile, char *group)
1098 /* pass ownership of @group on... */
1099 connection_info->group_name = group;
1101 connection_info->match_device.spec = nm_config_get_match_spec (keyfile,
1104 &connection_info->match_device.has);
1105 connection_info->stop_match = nm_config_keyfile_get_boolean (keyfile, group, "stop-match", FALSE);
1108 static ConnectionInfo *
1109 _get_connection_infos (GKeyFile *keyfile)
1112 gsize i, j, ngroups;
1113 char *connection_tag = NULL;
1114 ConnectionInfo *connection_infos = NULL;
1116 /* get the list of existing [connection.\+] sections that we consider
1117 * for nm_config_data_get_connection_default().
1119 * We expect the sections in their right order, with lowest priority
1120 * first. Only exception is the (literal) [connection] section, which
1121 * we will always reorder to the end. */
1122 groups = g_key_file_get_groups (keyfile, &ngroups);
1125 else if (ngroups > 0) {
1126 for (i = 0, j = 0; i < ngroups; i++) {
1127 if (g_str_has_prefix (groups[i], NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)) {
1128 if (groups[i][NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0')
1129 connection_tag = groups[i];
1131 groups[j++] = groups[i];
1138 connection_infos = g_new0 (ConnectionInfo, ngroups + 1 + (connection_tag ? 1 : 0));
1139 for (i = 0; i < ngroups; i++) {
1140 /* pass ownership of @group on... */
1141 _get_connection_info_init (&connection_infos[i], keyfile, groups[ngroups - i - 1]);
1143 if (connection_tag) {
1144 /* pass ownership of @connection_tag on... */
1145 _get_connection_info_init (&connection_infos[i], keyfile, connection_tag);
1149 return connection_infos;
1152 /************************************************************************/
1155 _slist_str_equals (GSList *a, GSList *b)
1157 while (a && b && g_strcmp0 (a->data, b->data) == 0) {
1165 nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data)
1167 NMConfigChangeFlags changes = NM_CONFIG_CHANGE_NONE;
1168 NMConfigDataPrivate *priv_old, *priv_new;
1170 g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NM_CONFIG_CHANGE_NONE);
1171 g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NM_CONFIG_CHANGE_NONE);
1173 priv_old = NM_CONFIG_DATA_GET_PRIVATE (old_data);
1174 priv_new = NM_CONFIG_DATA_GET_PRIVATE (new_data);
1176 if (!_nm_keyfile_equals (priv_old->keyfile_user, priv_new->keyfile_user, TRUE))
1177 changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_USER;
1179 if (!_nm_keyfile_equals (priv_old->keyfile_intern, priv_new->keyfile_intern, TRUE))
1180 changes |= NM_CONFIG_CHANGE_VALUES | NM_CONFIG_CHANGE_VALUES_INTERN;
1182 if ( g_strcmp0 (nm_config_data_get_config_main_file (old_data), nm_config_data_get_config_main_file (new_data)) != 0
1183 || g_strcmp0 (nm_config_data_get_config_description (old_data), nm_config_data_get_config_description (new_data)) != 0)
1184 changes |= NM_CONFIG_CHANGE_CONFIG_FILES;
1186 if ( nm_config_data_get_connectivity_interval (old_data) != nm_config_data_get_connectivity_interval (new_data)
1187 || g_strcmp0 (nm_config_data_get_connectivity_uri (old_data), nm_config_data_get_connectivity_uri (new_data))
1188 || g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data)))
1189 changes |= NM_CONFIG_CHANGE_CONNECTIVITY;
1191 if ( !_slist_str_equals (priv_old->no_auto_default.specs, priv_new->no_auto_default.specs)
1192 || !_slist_str_equals (priv_old->no_auto_default.specs_config, priv_new->no_auto_default.specs_config))
1193 changes |= NM_CONFIG_CHANGE_NO_AUTO_DEFAULT;
1195 if (g_strcmp0 (nm_config_data_get_dns_mode (old_data), nm_config_data_get_dns_mode (new_data)))
1196 changes |= NM_CONFIG_CHANGE_DNS_MODE;
1198 if (g_strcmp0 (nm_config_data_get_rc_manager (old_data), nm_config_data_get_rc_manager (new_data)))
1199 changes |= NM_CONFIG_CHANGE_RC_MANAGER;
1201 if (!global_dns_equal (priv_old->global_dns, priv_new->global_dns))
1202 changes |= NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG;
1207 /************************************************************************/
1210 get_property (GObject *object,
1215 NMConfigData *self = NM_CONFIG_DATA (object);
1218 case PROP_CONFIG_MAIN_FILE:
1219 g_value_set_string (value, nm_config_data_get_config_main_file (self));
1221 case PROP_CONFIG_DESCRIPTION:
1222 g_value_set_string (value, nm_config_data_get_config_description (self));
1224 case PROP_CONNECTIVITY_URI:
1225 g_value_set_string (value, nm_config_data_get_connectivity_uri (self));
1227 case PROP_CONNECTIVITY_INTERVAL:
1228 g_value_set_uint (value, nm_config_data_get_connectivity_interval (self));
1230 case PROP_CONNECTIVITY_RESPONSE:
1231 g_value_set_string (value, nm_config_data_get_connectivity_response (self));
1234 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1240 set_property (GObject *object,
1242 const GValue *value,
1245 NMConfigData *self = NM_CONFIG_DATA (object);
1246 NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self);
1248 /* This type is immutable. All properties are construct only. */
1250 case PROP_CONFIG_MAIN_FILE:
1251 priv->config_main_file = g_value_dup_string (value);
1253 case PROP_CONFIG_DESCRIPTION:
1254 priv->config_description = g_value_dup_string (value);
1256 case PROP_KEYFILE_USER:
1257 priv->keyfile_user = g_value_dup_boxed (value);
1258 if ( priv->keyfile_user
1259 && !_nm_keyfile_has_values (priv->keyfile_user)) {
1260 g_key_file_unref (priv->keyfile_user);
1261 priv->keyfile_user = NULL;
1264 case PROP_KEYFILE_INTERN:
1265 priv->keyfile_intern = g_value_dup_boxed (value);
1266 if ( priv->keyfile_intern
1267 && !_nm_keyfile_has_values (priv->keyfile_intern)) {
1268 g_key_file_unref (priv->keyfile_intern);
1269 priv->keyfile_intern = NULL;
1272 case PROP_NO_AUTO_DEFAULT:
1274 char **value_arr = g_value_get_boxed (value);
1277 priv->no_auto_default.arr = g_new (char *, g_strv_length (value_arr) + 1);
1278 priv->no_auto_default.specs = NULL;
1280 for (i = 0; value_arr && value_arr[i]; i++) {
1282 && nm_utils_hwaddr_valid (value_arr[i], -1)
1283 && _nm_utils_strv_find_first (value_arr, i, value_arr[i]) < 0) {
1284 priv->no_auto_default.arr[j++] = g_strdup (value_arr[i]);
1285 priv->no_auto_default.specs = g_slist_prepend (priv->no_auto_default.specs, g_strdup_printf ("mac:%s", value_arr[i]));
1288 priv->no_auto_default.arr[j++] = NULL;
1289 priv->no_auto_default.specs = g_slist_reverse (priv->no_auto_default.specs);
1293 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1299 dispose (GObject *object)
1304 finalize (GObject *gobject)
1306 NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (gobject);
1309 g_free (priv->config_main_file);
1310 g_free (priv->config_description);
1312 g_free (priv->connectivity.uri);
1313 g_free (priv->connectivity.response);
1315 g_slist_free_full (priv->no_auto_default.specs, g_free);
1316 g_slist_free_full (priv->no_auto_default.specs_config, g_free);
1317 g_strfreev (priv->no_auto_default.arr);
1319 g_free (priv->dns_mode);
1320 g_free (priv->rc_manager);
1322 g_slist_free_full (priv->ignore_carrier, g_free);
1323 g_slist_free_full (priv->assume_ipv6ll_only, g_free);
1325 nm_global_dns_config_free (priv->global_dns);
1327 if (priv->connection_infos) {
1328 for (i = 0; priv->connection_infos[i].group_name; i++) {
1329 g_free (priv->connection_infos[i].group_name);
1330 g_slist_free_full (priv->connection_infos[i].match_device.spec, g_free);
1332 g_free (priv->connection_infos);
1335 g_key_file_unref (priv->keyfile);
1336 if (priv->keyfile_user)
1337 g_key_file_unref (priv->keyfile_user);
1338 if (priv->keyfile_intern)
1339 g_key_file_unref (priv->keyfile_intern);
1341 G_OBJECT_CLASS (nm_config_data_parent_class)->finalize (gobject);
1343 g_free (priv->value_cached);
1347 nm_config_data_init (NMConfigData *self)
1352 constructed (GObject *object)
1354 NMConfigData *self = NM_CONFIG_DATA (object);
1355 NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self);
1358 priv->keyfile = _merge_keyfiles (priv->keyfile_user, priv->keyfile_intern);
1360 priv->connection_infos = _get_connection_infos (priv->keyfile);
1362 priv->connectivity.uri = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "uri", NULL));
1363 priv->connectivity.response = g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "response", NULL);
1365 /* On missing config value, fallback to 300. On invalid value, disable connectivity checking by setting
1366 * the interval to zero. */
1367 interval = g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "interval", NULL);
1368 priv->connectivity.interval = interval
1369 ? _nm_utils_ascii_str_to_int64 (interval, 10, 0, G_MAXUINT, 0)
1370 : NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL;
1373 priv->dns_mode = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "dns", NULL));
1374 priv->rc_manager = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "rc-manager", NULL));
1376 priv->ignore_carrier = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "ignore-carrier", NULL);
1377 priv->assume_ipv6ll_only = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "assume-ipv6ll-only", NULL);
1379 priv->no_auto_default.specs_config = nm_config_get_match_spec (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "no-auto-default", NULL);
1381 priv->global_dns = load_global_dns (priv->keyfile_user, FALSE);
1382 if (!priv->global_dns)
1383 priv->global_dns = load_global_dns (priv->keyfile_intern, TRUE);
1385 G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object);
1389 nm_config_data_new (const char *config_main_file,
1390 const char *config_description,
1391 const char *const*no_auto_default,
1392 GKeyFile *keyfile_user,
1393 GKeyFile *keyfile_intern)
1395 return g_object_new (NM_TYPE_CONFIG_DATA,
1396 NM_CONFIG_DATA_CONFIG_MAIN_FILE, config_main_file,
1397 NM_CONFIG_DATA_CONFIG_DESCRIPTION, config_description,
1398 NM_CONFIG_DATA_KEYFILE_USER, keyfile_user,
1399 NM_CONFIG_DATA_KEYFILE_INTERN, keyfile_intern,
1400 NM_CONFIG_DATA_NO_AUTO_DEFAULT, no_auto_default,
1405 nm_config_data_new_update_keyfile_intern (const NMConfigData *base, GKeyFile *keyfile_intern)
1407 NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (base);
1409 return g_object_new (NM_TYPE_CONFIG_DATA,
1410 NM_CONFIG_DATA_CONFIG_MAIN_FILE, priv->config_main_file,
1411 NM_CONFIG_DATA_CONFIG_DESCRIPTION, priv->config_description,
1412 NM_CONFIG_DATA_KEYFILE_USER, priv->keyfile_user, /* the keyfile is unchanged. It's safe to share it. */
1413 NM_CONFIG_DATA_KEYFILE_INTERN, keyfile_intern,
1414 NM_CONFIG_DATA_NO_AUTO_DEFAULT, priv->no_auto_default.arr,
1419 nm_config_data_new_update_no_auto_default (const NMConfigData *base,
1420 const char *const*no_auto_default)
1422 NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (base);
1424 return g_object_new (NM_TYPE_CONFIG_DATA,
1425 NM_CONFIG_DATA_CONFIG_MAIN_FILE, priv->config_main_file,
1426 NM_CONFIG_DATA_CONFIG_DESCRIPTION, priv->config_description,
1427 NM_CONFIG_DATA_KEYFILE_USER, priv->keyfile_user, /* the keyfile is unchanged. It's safe to share it. */
1428 NM_CONFIG_DATA_KEYFILE_INTERN, priv->keyfile_intern,
1429 NM_CONFIG_DATA_NO_AUTO_DEFAULT, no_auto_default,
1434 nm_config_data_class_init (NMConfigDataClass *config_class)
1436 GObjectClass *object_class = G_OBJECT_CLASS (config_class);
1438 g_type_class_add_private (config_class, sizeof (NMConfigDataPrivate));
1440 object_class->constructed = constructed;
1441 object_class->dispose = dispose;
1442 object_class->finalize = finalize;
1443 object_class->get_property = get_property;
1444 object_class->set_property = set_property;
1446 g_object_class_install_property
1447 (object_class, PROP_CONFIG_MAIN_FILE,
1448 g_param_spec_string (NM_CONFIG_DATA_CONFIG_MAIN_FILE, "", "",
1451 G_PARAM_CONSTRUCT_ONLY |
1452 G_PARAM_STATIC_STRINGS));
1454 g_object_class_install_property
1455 (object_class, PROP_CONFIG_DESCRIPTION,
1456 g_param_spec_string (NM_CONFIG_DATA_CONFIG_DESCRIPTION, "", "",
1459 G_PARAM_CONSTRUCT_ONLY |
1460 G_PARAM_STATIC_STRINGS));
1462 g_object_class_install_property
1463 (object_class, PROP_KEYFILE_USER,
1464 g_param_spec_boxed (NM_CONFIG_DATA_KEYFILE_USER, "", "",
1467 G_PARAM_CONSTRUCT_ONLY |
1468 G_PARAM_STATIC_STRINGS));
1470 g_object_class_install_property
1471 (object_class, PROP_KEYFILE_INTERN,
1472 g_param_spec_boxed (NM_CONFIG_DATA_KEYFILE_INTERN, "", "",
1475 G_PARAM_CONSTRUCT_ONLY |
1476 G_PARAM_STATIC_STRINGS));
1478 g_object_class_install_property
1479 (object_class, PROP_CONNECTIVITY_URI,
1480 g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_URI, "", "",
1483 G_PARAM_STATIC_STRINGS));
1485 g_object_class_install_property
1486 (object_class, PROP_CONNECTIVITY_INTERVAL,
1487 g_param_spec_uint (NM_CONFIG_DATA_CONNECTIVITY_INTERVAL, "", "",
1490 G_PARAM_STATIC_STRINGS));
1492 g_object_class_install_property
1493 (object_class, PROP_CONNECTIVITY_RESPONSE,
1494 g_param_spec_string (NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, "", "",
1497 G_PARAM_STATIC_STRINGS));
1499 g_object_class_install_property
1500 (object_class, PROP_NO_AUTO_DEFAULT,
1501 g_param_spec_boxed (NM_CONFIG_DATA_NO_AUTO_DEFAULT, "", "",
1504 G_PARAM_CONSTRUCT_ONLY |
1505 G_PARAM_STATIC_STRINGS));