diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2015-07-03 11:06:39 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2015-10-01 09:05:08 +0200 |
commit | c83ac1ed412e8f220c507b9b9177c3bcf6800658 (patch) | |
tree | e7aeaa3fbd70878f8fd1a1cf49449992f8eb3bcd | |
parent | dd6fbe7bfa78770c965538f045c3814a146ccdf6 (diff) | |
download | NetworkManager-c83ac1ed412e8f220c507b9b9177c3bcf6800658.tar.gz |
manager: export DNS global configuration D-Bus property
-rw-r--r-- | introspection/nm-manager.xml | 14 | ||||
-rw-r--r-- | policy/org.freedesktop.NetworkManager.policy.in.in | 10 | ||||
-rw-r--r-- | src/nm-auth-utils.h | 1 | ||||
-rw-r--r-- | src/nm-config-data.c | 182 | ||||
-rw-r--r-- | src/nm-config-data.h | 3 | ||||
-rw-r--r-- | src/nm-config.c | 67 | ||||
-rw-r--r-- | src/nm-config.h | 2 | ||||
-rw-r--r-- | src/nm-manager.c | 100 | ||||
-rw-r--r-- | src/nm-manager.h | 1 |
9 files changed, 364 insertions, 16 deletions
diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml index 8548072cee..88f477d62f 100644 --- a/introspection/nm-manager.xml +++ b/introspection/nm-manager.xml @@ -368,6 +368,20 @@ </tp:docstring> </property> + <property name="GlobalDnsConfiguration" type="a{sv}" access="readwrite"> + <tp:docstring> + Dictionary of global DNS settings where the key is one of + "searches", "options" and "domains". The values for the + "searches" and "options" keys are string arrays describing the + list of search domains and resolver options, respectively. + The value of the "domains" key is a second-level dictionary, + where each key is a domain name, and each key's value is a + third-level dictionary with the keys "servers" and + "options". "servers" is a string array of DNS servers, + "options" is a string array of domain-specific options. + </tp:docstring> + </property> + <signal name="PropertiesChanged"> <tp:docstring> NetworkManager's properties changed. diff --git a/policy/org.freedesktop.NetworkManager.policy.in.in b/policy/org.freedesktop.NetworkManager.policy.in.in index daefd80f20..4df6d7e133 100644 --- a/policy/org.freedesktop.NetworkManager.policy.in.in +++ b/policy/org.freedesktop.NetworkManager.policy.in.in @@ -112,5 +112,15 @@ </defaults> </action> + <action id="org.freedesktop.NetworkManager.settings.modify.global-dns"> + <_description>Modify persistent global DNS configuration</_description> + <_message>System policy prevents modification of the persistent global DNS configuration</_message> + <defaults> + <allow_any>auth_admin_keep</allow_any> + <allow_inactive>auth_admin_keep</allow_inactive> + <allow_active>auth_admin_keep</allow_active> + </defaults> + </action> + </policyconfig> diff --git a/src/nm-auth-utils.h b/src/nm-auth-utils.h index c6cad52a6d..6eb0fda07e 100644 --- a/src/nm-auth-utils.h +++ b/src/nm-auth-utils.h @@ -35,6 +35,7 @@ #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM "org.freedesktop.NetworkManager.settings.modify.system" #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own" #define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns" typedef struct NMAuthChain NMAuthChain; diff --git a/src/nm-config-data.c b/src/nm-config-data.c index cfca59aa4b..1d0d362577 100644 --- a/src/nm-config-data.c +++ b/src/nm-config-data.c @@ -812,6 +812,188 @@ load_global_dns (GKeyFile *keyfile, gboolean internal) return conf; } + +void +nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns, GValue *value) +{ + GVariantBuilder conf_builder, domains_builder, domain_builder; + NMGlobalDnsDomain *domain; + GHashTableIter iter; + + g_variant_builder_init (&conf_builder, G_VARIANT_TYPE ("a{sv}")); + if (!dns) + goto out; + + if (dns->searches) { + g_variant_builder_add (&conf_builder, "{sv}", "searches", + g_variant_new_strv ((const char *const *) dns->searches, -1)); + } + + if (dns->options) { + g_variant_builder_add (&conf_builder, "{sv}", "options", + g_variant_new_strv ((const char *const *) dns->options, -1)); + } + + g_variant_builder_init (&domains_builder, G_VARIANT_TYPE ("a{sv}")); + + g_hash_table_iter_init (&iter, dns->domains); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &domain)) { + + g_variant_builder_init (&domain_builder, G_VARIANT_TYPE ("a{sv}")); + + if (domain->servers) { + g_variant_builder_add (&domain_builder, "{sv}", "servers", + g_variant_new_strv ((const char *const *) domain->servers, -1)); + } + if (domain->options) { + g_variant_builder_add (&domain_builder, "{sv}", "options", + g_variant_new_strv ((const char *const *) domain->options, -1)); + } + + g_variant_builder_add (&domains_builder, "{sv}", domain->name, + g_variant_builder_end (&domain_builder)); + } + + g_variant_builder_add (&conf_builder, "{sv}", "domains", + g_variant_builder_end (&domains_builder)); +out: + g_value_take_variant (value, g_variant_builder_end (&conf_builder)); +} + +static NMGlobalDnsDomain * +global_dns_domain_from_dbus (char *name, GVariant *variant) +{ + NMGlobalDnsDomain *domain; + GVariantIter iter; + char **strv, *key; + GVariant *val; + int i, j; + + if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}"))) + return NULL; + + domain = g_malloc0 (sizeof (NMGlobalDnsDomain)); + domain->name = g_strdup (name); + + g_variant_iter_init (&iter, variant); + while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) { + + if ( !g_strcmp0 (key, "servers") + && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) { + strv = g_variant_dup_strv (val, NULL); + _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE); + for (i = 0, j = 0; strv && strv[i]; i++) { + if ( nm_utils_ipaddr_valid (AF_INET, strv[i]) + || nm_utils_ipaddr_valid (AF_INET6, strv[i])) + strv[j++] = strv[i]; + else + g_free (strv[i]); + } + if (j) { + strv[j] = NULL; + domain->servers = strv; + } else + g_free (strv); + } else if ( !g_strcmp0 (key, "options") + && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) { + strv = g_variant_dup_strv (val, NULL); + domain->options = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE); + } + + g_variant_unref (val); + } + + /* At least one server is required */ + if (!domain->servers) { + global_dns_domain_free (domain); + return NULL; + } + + return domain; +} + +NMGlobalDnsConfig * +nm_global_dns_config_from_dbus (const GValue *value, GError **error) +{ + NMGlobalDnsConfig *dns_config; + GVariant *variant, *val; + GVariantIter iter; + char **strv, *key; + int i, j; + + if (!G_VALUE_HOLDS_VARIANT (value)) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, + "invalid value type"); + return NULL; + } + + variant = g_value_get_variant (value); + if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("a{sv}"))) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, + "invalid variant type"); + return NULL; + } + + dns_config = g_malloc0 (sizeof (NMGlobalDnsConfig)); + dns_config->domains = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) global_dns_domain_free); + + g_variant_iter_init (&iter, variant); + while (g_variant_iter_next (&iter, "{&sv}", &key, &val)) { + + if ( !g_strcmp0 (key, "searches") + && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) { + strv = g_variant_dup_strv (val, NULL); + dns_config->searches = _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE); + } else if ( !g_strcmp0 (key, "options") + && g_variant_is_of_type (val, G_VARIANT_TYPE ("as"))) { + strv = g_variant_dup_strv (val, NULL); + _nm_utils_strv_cleanup (strv, TRUE, TRUE, TRUE); + + for (i = 0, j = 0; strv && strv[i]; i++) { + if (_nm_utils_dns_option_validate (strv[i], NULL, NULL, TRUE, NULL)) + strv[j++] = strv[i]; + else + g_free (strv[i]); + } + + if (strv) + strv[j] = NULL; + + dns_config->options = strv; + } else if ( !g_strcmp0 (key, "domains") + && g_variant_is_of_type (val, G_VARIANT_TYPE ("a{sv}"))) { + NMGlobalDnsDomain *domain; + GVariantIter domain_iter; + GVariant *v; + char *k; + + g_variant_iter_init (&domain_iter, val); + while (g_variant_iter_next (&domain_iter, "{&sv}", &k, &v)) { + if (k) { + domain = global_dns_domain_from_dbus (k, v); + if (domain) + g_hash_table_insert (dns_config->domains, strdup (k), domain); + } + g_variant_unref (v); + } + } + g_variant_unref (val); + } + + /* An empty value is valid and clears the internal configuration */ + if ( !nm_global_dns_config_is_empty (dns_config) + && !nm_global_dns_config_lookup_domain (dns_config, "*")) { + g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, + "Global DNS configuration is missing the default domain"); + nm_global_dns_config_free (dns_config); + return NULL; + } + + global_dns_config_update_domain_list (dns_config); + return dns_config; +} + static gboolean global_dns_equal (NMGlobalDnsConfig *old, NMGlobalDnsConfig *new) { diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 41a7cd5e84..4c0be72a8b 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -153,6 +153,9 @@ gboolean nm_global_dns_config_is_empty (const NMGlobalDnsConfig *dns); void nm_global_dns_config_update_checksum (const NMGlobalDnsConfig *dns, GChecksum *sum); void nm_global_dns_config_free (NMGlobalDnsConfig *conf); +NMGlobalDnsConfig *nm_global_dns_config_from_dbus (const GValue *value, GError **error); +void nm_global_dns_config_to_dbus (const NMGlobalDnsConfig *dns_config, GValue *value); + /* private accessors */ GKeyFile *_nm_config_data_get_keyfile (const NMConfigData *self); GKeyFile *_nm_config_data_get_keyfile_user (const NMConfigData *self); diff --git a/src/nm-config.c b/src/nm-config.c index bf5811d480..9edfac1b0a 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -1431,6 +1431,73 @@ nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *group, con /************************************************************************/ +gboolean +nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError **error) +{ + NMConfigPrivate *priv; + GKeyFile *keyfile; + char **groups; + const NMGlobalDnsConfig *old_global_dns; + guint i; + + g_return_val_if_fail (NM_IS_CONFIG (self), FALSE); + + priv = NM_CONFIG_GET_PRIVATE (self); + g_return_val_if_fail (priv->config_data, FALSE); + + old_global_dns = nm_config_data_get_global_dns_config (priv->config_data); + if (old_global_dns && !nm_global_dns_config_is_internal (old_global_dns)) { + g_set_error_literal (error, 1, 0, + "Global DNS configuration already set via configuration file"); + return FALSE; + } + + keyfile = nm_config_data_clone_keyfile_intern (priv->config_data); + + /* Remove existing groups */ + g_key_file_remove_group (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NULL); + groups = g_key_file_get_groups (keyfile, NULL); + for (i = 0; groups[i]; i++) { + if (g_str_has_prefix (groups[i], NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN)) + g_key_file_remove_group (keyfile, groups[i], NULL); + } + g_strfreev (groups); + + /* An empty configuration removes everything from internal configuration file */ + if (nm_global_dns_config_is_empty (global_dns)) + goto done; + + /* Set new values */ + g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_ENABLE, "yes"); + + nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, + "searches", nm_global_dns_config_get_searches (global_dns), + -1); + + nm_config_keyfile_set_string_list (keyfile, NM_CONFIG_KEYFILE_GROUP_INTERN_GLOBAL_DNS, + "options", nm_global_dns_config_get_options (global_dns), + -1); + + for (i = 0; i < nm_global_dns_config_get_num_domains (global_dns); i++) { + NMGlobalDnsDomain *domain = nm_global_dns_config_get_domain (global_dns, i); + gs_free char *group_name; + + group_name = g_strdup_printf (NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN_GLOBAL_DNS_DOMAIN "%s", + nm_global_dns_domain_get_name (domain)); + + nm_config_keyfile_set_string_list (keyfile, group_name, "servers", + nm_global_dns_domain_get_servers (domain), -1); + nm_config_keyfile_set_string_list (keyfile, group_name, "options", + nm_global_dns_domain_get_options (domain), -1); + } + +done: + nm_config_set_values (self, keyfile, TRUE, FALSE); + g_key_file_unref (keyfile); + + return TRUE; +} + /** * nm_config_set_values: * @self: the NMConfig instance diff --git a/src/nm-config.h b/src/nm-config.h index c52b3dceb6..0e96c3e85c 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -147,6 +147,8 @@ GSList *nm_config_get_device_match_spec (const GKeyFile *keyfile, const char *gr void _nm_config_sort_groups (char **groups, gsize ngroups); +gboolean nm_config_set_global_dns (NMConfig *self, NMGlobalDnsConfig *global_dns, GError **error); + G_END_DECLS #endif /* __NETWORKMANAGER_CONFIG_H__ */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 107039f40a..1253f99188 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -181,6 +181,7 @@ enum { PROP_ACTIVATING_CONNECTION, PROP_DEVICES, PROP_METERED, + PROP_GLOBAL_DNS_CONFIGURATION, /* Not exported */ PROP_HOSTNAME, @@ -424,6 +425,9 @@ _config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeF NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data), NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data), NULL); + + if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) + g_object_notify (G_OBJECT (self), NM_MANAGER_GLOBAL_DNS_CONFIGURATION); } /************************************************************************/ @@ -4430,7 +4434,6 @@ typedef struct { char *audit_prop_value; GType interface_type; const char *glib_propname; - gboolean set_enable; } PropertyFilterData; static void @@ -4453,9 +4456,12 @@ prop_set_auth_done_cb (NMAuthChain *chain, PropertyFilterData *pfd = user_data; NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (pfd->self); NMAuthCallResult result; - GDBusMessage *reply; + GDBusMessage *reply = NULL; const char *error_message; NMExportedObject *object; + const NMGlobalDnsConfig *global_dns; + gs_unref_variant GVariant *value = NULL; + GVariant *args; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); result = nm_auth_chain_get_result (chain, pfd->permission); @@ -4485,9 +4491,29 @@ prop_set_auth_done_cb (NMAuthChain *chain, goto done; } - /* ... but set the property on the @object itself. It would be correct to set the property - * on the skeleton interface, but as it is now, the result is the same. */ - g_object_set (object, pfd->glib_propname, pfd->set_enable, NULL); + args = g_dbus_message_get_body (pfd->message); + g_variant_get (args, "(&s&sv)", NULL, NULL, &value); + g_assert (pfd->glib_propname); + + if (!strcmp (pfd->glib_propname, NM_MANAGER_GLOBAL_DNS_CONFIGURATION)) { + g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a{sv}"))); + global_dns = nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)); + + if (global_dns && !nm_global_dns_config_is_internal (global_dns)) { + reply = g_dbus_message_new_method_error (pfd->message, + NM_PERM_DENIED_ERROR, + (error_message = "Global DNS configuration already set via configuration file")); + goto done; + } + /* ... but set the property on the @object itself. It would be correct to set the property + * on the skeleton interface, but as it is now, the result is the same. */ + g_object_set (object, pfd->glib_propname, value, NULL); + } else { + g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)); + /* the same here */ + g_object_set (object, pfd->glib_propname, g_variant_get_boolean (value), NULL); + } + reply = g_dbus_message_new_method_reply (pfd->message); g_dbus_message_set_body (reply, g_variant_new_tuple (NULL, 0)); error_message = NULL; @@ -4552,14 +4578,15 @@ prop_filter (GDBusConnection *connection, gpointer user_data) { gs_unref_object NMManager *self = NULL; - GVariant *args, *value = NULL; + GVariant *args; const char *propiface = NULL; const char *propname = NULL; const char *glib_propname = NULL, *permission = NULL; const char *audit_op = NULL; - gboolean set_enable; GType interface_type = G_TYPE_INVALID; PropertyFilterData *pfd; + const GVariantType *expected_type = G_VARIANT_TYPE_BOOLEAN; + gs_unref_variant GVariant *value = NULL; self = g_weak_ref_get (user_data); if (!self) @@ -4576,17 +4603,10 @@ prop_filter (GDBusConnection *connection, || g_strcmp0 (g_dbus_message_get_member (message), "Set") != 0) return message; - /* Only filter calls with correct arguments (all filtered properties are boolean) */ args = g_dbus_message_get_body (message); if (!g_variant_is_of_type (args, G_VARIANT_TYPE ("(ssv)"))) return message; g_variant_get (args, "(&s&sv)", &propiface, &propname, &value); - if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) { - g_variant_unref (value); - return message; - } - set_enable = g_variant_get_boolean (value); - g_variant_unref (value); /* Only filter calls to filtered properties, on existing objects */ if (!strcmp (propiface, NM_DBUS_INTERFACE)) { @@ -4602,6 +4622,11 @@ prop_filter (GDBusConnection *connection, glib_propname = NM_MANAGER_WIMAX_ENABLED; permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX; audit_op = NM_AUDIT_OP_RADIO_CONTROL; + } else if (!strcmp (propname, "GlobalDnsConfiguration")) { + glib_propname = NM_MANAGER_GLOBAL_DNS_CONFIGURATION; + permission = NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS; + audit_op = NM_AUDIT_OP_NET_CONTROL; + expected_type = G_VARIANT_TYPE ("a{sv}"); } else return message; interface_type = NMDBUS_TYPE_MANAGER_SKELETON; @@ -4620,6 +4645,9 @@ prop_filter (GDBusConnection *connection, } else return message; + if (!g_variant_is_of_type (value, expected_type)) + return message; + /* This filter function is called from a gdbus worker thread which we can't * make other D-Bus calls from. In particular, we cannot call * org.freedesktop.DBus.GetConnectionUnixUser to find the remote UID. @@ -4632,9 +4660,13 @@ prop_filter (GDBusConnection *connection, pfd->permission = permission; pfd->interface_type = interface_type; pfd->glib_propname = glib_propname; - pfd->set_enable = set_enable; pfd->audit_op = audit_op; - pfd->audit_prop_value = g_strdup_printf ("%s:%d", pfd->glib_propname, pfd->set_enable); + if (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)) { + pfd->audit_prop_value = g_strdup_printf ("%s:%d", pfd->glib_propname, + g_variant_get_boolean (value)); + } else + pfd->audit_prop_value = g_strdup (pfd->glib_propname); + g_idle_add (do_set_property_check, pfd); return NULL; @@ -5028,6 +5060,8 @@ get_property (GObject *object, guint prop_id, { NMManager *self = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMConfigData *config_data; + const NMGlobalDnsConfig *dns_config; const char *type; switch (prop_id) { @@ -5097,6 +5131,11 @@ get_property (GObject *object, guint prop_id, case PROP_METERED: g_value_set_uint (value, priv->metered); break; + case PROP_GLOBAL_DNS_CONFIGURATION: + config_data = nm_config_get_data (priv->config); + dns_config = nm_config_data_get_global_dns_config (config_data); + nm_global_dns_config_to_dbus (dns_config, value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -5109,6 +5148,8 @@ set_property (GObject *object, guint prop_id, { NMManager *self = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMGlobalDnsConfig *dns_config; + GError *error = NULL; switch (prop_id) { case PROP_NETWORKING_ENABLED: @@ -5128,6 +5169,18 @@ set_property (GObject *object, guint prop_id, case PROP_WIMAX_ENABLED: /* WIMAX is depreacted. This does nothing. */ break; + case PROP_GLOBAL_DNS_CONFIGURATION: + dns_config = nm_global_dns_config_from_dbus (value, &error); + if (!error) + nm_config_set_global_dns (priv->config, dns_config, &error); + + nm_global_dns_config_free (dns_config); + + if (error) { + nm_log_dbg (LOGD_CORE, "set global DNS failed with error: %s", error->message); + g_error_free (error); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -5395,6 +5448,21 @@ nm_manager_class_init (NMManagerClass *manager_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * NMManager:global-dns-configuration: + * + * The global DNS configuration. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_GLOBAL_DNS_CONFIGURATION, + g_param_spec_variant (NM_MANAGER_GLOBAL_DNS_CONFIGURATION, "", "", + G_VARIANT_TYPE ("a{sv}"), + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + /* signals */ signals[DEVICE_ADDED] = g_signal_new ("device-added", diff --git a/src/nm-manager.h b/src/nm-manager.h index 39123f8b41..7807f450c8 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -49,6 +49,7 @@ #define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection" #define NM_MANAGER_DEVICES "devices" #define NM_MANAGER_METERED "metered" +#define NM_MANAGER_GLOBAL_DNS_CONFIGURATION "global-dns-configuration" /* Not exported */ #define NM_MANAGER_HOSTNAME "hostname" |