summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-07-03 11:06:39 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-10-01 09:05:08 +0200
commitc83ac1ed412e8f220c507b9b9177c3bcf6800658 (patch)
treee7aeaa3fbd70878f8fd1a1cf49449992f8eb3bcd
parentdd6fbe7bfa78770c965538f045c3814a146ccdf6 (diff)
downloadNetworkManager-c83ac1ed412e8f220c507b9b9177c3bcf6800658.tar.gz
manager: export DNS global configuration D-Bus property
-rw-r--r--introspection/nm-manager.xml14
-rw-r--r--policy/org.freedesktop.NetworkManager.policy.in.in10
-rw-r--r--src/nm-auth-utils.h1
-rw-r--r--src/nm-config-data.c182
-rw-r--r--src/nm-config-data.h3
-rw-r--r--src/nm-config.c67
-rw-r--r--src/nm-config.h2
-rw-r--r--src/nm-manager.c100
-rw-r--r--src/nm-manager.h1
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"