summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-06-19 11:37:33 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-06-19 11:37:33 +0200
commitda6b7d9cc97509a17f1f212094d7c8dd410dbba6 (patch)
treea2d8b39059f2bd2221e240cd78cb8853b74c3141
parent028fe6d4898509b5f0c69d39c1dbab78c1152a82 (diff)
downloadNetworkManager-da6b7d9cc97509a17f1f212094d7c8dd410dbba6.tar.gz
manager: introduce new SetGlobalDnsConfig D-Bus method
-rw-r--r--introspection/nm-manager.xml13
-rw-r--r--src/nm-config-data.c173
-rw-r--r--src/nm-config-data.h3
-rw-r--r--src/nm-manager.c25
4 files changed, 208 insertions, 6 deletions
diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml
index d0682e5cac..3620a2df92 100644
--- a/introspection/nm-manager.xml
+++ b/introspection/nm-manager.xml
@@ -261,6 +261,19 @@
<arg name="state" type="u" direction="out" tp:type="NM_STATE"/>
</method>
+ <method name="SetGlobalDnsConfig">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_set_global_dns_config"/>
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <tp:docstring>
+ Change the global static DNS configuration.
+ </tp:docstring>
+ <arg name="config" type="a{sv}" direction="in">
+ <tp:docstring>
+ The new global DNS configuration.
+ </tp:docstring>
+ </arg>
+ </method>
+
<property name="Devices" type="ao" access="read">
<tp:docstring>
The list of network devices/interfaces NetworkManager knows about.
diff --git a/src/nm-config-data.c b/src/nm-config-data.c
index 70528ac099..d9c9d6b97c 100644
--- a/src/nm-config-data.c
+++ b/src/nm-config-data.c
@@ -573,6 +573,26 @@ strv_to_slist (char **strv)
return g_slist_reverse (list);
}
+static char **
+slist_to_strv (GSList *slist)
+{
+ GSList *iter;
+ char **strv;
+ int len, i;
+
+ len = g_slist_length (slist);
+ strv = g_new (char *, len + 1);
+
+ for (i = 0, iter = slist; iter; iter = iter->next, i++)
+ strv[i] = g_strdup (iter->data);
+ strv[i] = NULL;
+
+ return strv;
+}
+
+#define GLOB_DNS_INTERN_GROUP NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_DATA_GLOBAL_DNS_GROUP
+#define GLOB_DNS_INTERN_DOM_PREFIX NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_DATA_GLOBAL_DNS_DOMAIN_PREFIX
+
static NMGlobalDnsConfig *
load_global_dns_config (GKeyFile *keyfile, gboolean internal)
{
@@ -583,12 +603,8 @@ load_global_dns_config (GKeyFile *keyfile, gboolean internal)
g_return_val_if_fail (keyfile, NULL);
- group = internal ?
- NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_DATA_GLOBAL_DNS_GROUP :
- NM_CONFIG_DATA_GLOBAL_DNS_GROUP;
- domain_prefix = internal ?
- NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN NM_CONFIG_DATA_GLOBAL_DNS_DOMAIN_PREFIX :
- NM_CONFIG_DATA_GLOBAL_DNS_GROUP;
+ group = internal ? GLOB_DNS_INTERN_GROUP : NM_CONFIG_DATA_GLOBAL_DNS_GROUP;
+ domain_prefix = internal ? GLOB_DNS_INTERN_DOM_PREFIX : NM_CONFIG_DATA_GLOBAL_DNS_GROUP;
if (!g_key_file_has_group (keyfile, group))
return NULL;
@@ -703,6 +719,151 @@ global_dns_config_equals (NMGlobalDnsConfig *old, NMGlobalDnsConfig *new)
return TRUE;
}
+static NMGlobalDnsDomainConfig *
+build_dns_global_domain_from_hash (const char *name, GHashTable *hash)
+{
+ NMGlobalDnsDomainConfig *domain;
+ char **strv, **ptr;
+
+ domain = g_malloc0 (sizeof (NMGlobalDnsDomainConfig));
+
+ strv = g_hash_table_lookup (hash, "servers");
+ if (strv) {
+ for (ptr = strv; *ptr; ptr++)
+ domain->servers = g_slist_prepend (domain->servers, *ptr);
+ domain->servers = g_slist_reverse (domain->servers);
+ }
+
+ strv = g_hash_table_lookup (hash, "options");
+ if (strv) {
+ for (ptr = strv; *ptr; ptr++)
+ domain->options = g_slist_prepend (domain->options, *ptr);
+ domain->options = g_slist_reverse (domain->options);
+ }
+
+ return domain;
+}
+
+static GKeyFile *
+global_dns_config_update_keyfile (const NMConfigData *self, NMGlobalDnsConfig *dns_conf)
+{
+ GKeyFile *keyfile;
+ GHashTableIter iter;
+ char **groups;
+ int g;
+ gpointer key, value;
+ char **values;
+
+ g_return_val_if_fail (NM_IS_CONFIG_DATA (self), NULL);
+ g_return_val_if_fail (dns_conf, NULL);
+
+ keyfile = nm_config_data_clone_keyfile_intern (self);
+
+ /* Remove existing groups */
+ g_key_file_remove_group (keyfile, GLOB_DNS_INTERN_GROUP, NULL);
+
+ groups = g_key_file_get_groups (keyfile, NULL);
+ for (g = 0; groups[g]; g++) {
+ if (g_str_has_prefix (groups[g], GLOB_DNS_INTERN_DOM_PREFIX))
+ g_key_file_remove_group (keyfile, groups[g], NULL);
+ }
+ g_strfreev (groups);
+
+ /* Set new options */
+ values = slist_to_strv (dns_conf->searches);
+ g_key_file_set_string_list (keyfile, GLOB_DNS_INTERN_GROUP, "searches",
+ (const char *const *) values, g_strv_length (values));
+ g_strfreev (values);
+
+ values = slist_to_strv (dns_conf->options);
+ g_key_file_set_string_list (keyfile, GLOB_DNS_INTERN_GROUP, "options",
+ (const char *const *) values, g_strv_length (values));
+ g_strfreev (values);
+
+ g = 0;
+ g_hash_table_iter_init (&iter, dns_conf->domains);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ char group_name[32];
+ NMGlobalDnsDomainConfig *domain_conf = (NMGlobalDnsDomainConfig *) value;
+
+ snprintf (group_name, sizeof (group_name), GLOB_DNS_INTERN_DOM_PREFIX "%u", (unsigned int) g++);
+ g_key_file_set_string (keyfile, group_name, "domain", (char *) key);
+
+ if (domain_conf->servers) {
+ values = slist_to_strv (domain_conf->servers);
+ g_key_file_set_string_list (keyfile, group_name, "servers",
+ (const char *const *) values, g_strv_length (values));
+ g_strfreev (values);
+ }
+
+ if (domain_conf->options) {
+ values = slist_to_strv (domain_conf->options);
+ g_key_file_set_string_list (keyfile, group_name, "options",
+ (const char *const *) values, g_strv_length (values));
+ g_strfreev (values);
+ }
+ }
+
+ return keyfile;
+}
+
+GKeyFile *
+nm_config_data_update_global_dns_config (const NMConfigData *self,
+ GHashTable *hash,
+ GError **error)
+{
+ NMConfigDataPrivate *priv;
+ NMGlobalDnsConfig *config;
+ GValue *val;
+ char **strv, **ptr;
+
+ g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
+ priv = NM_CONFIG_DATA_GET_PRIVATE (self);
+
+ if (priv->global_dns_config && !priv->global_dns_config->internal) {
+ g_set_error_literal (error, 1, 0, "Global DNS configuration already set from user configuration");
+ return FALSE;
+ }
+
+ config = g_malloc0 (sizeof (NMGlobalDnsConfig));
+ config->domains = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, free_global_dns_domain);
+
+ val = g_hash_table_lookup (hash, "searches");
+ if (val) {
+ strv = (char **) g_value_get_boxed (val);
+ for (ptr = strv; *ptr; ptr++)
+ config->searches = g_slist_prepend (config->searches, *ptr);
+ config->searches = g_slist_reverse (config->searches);
+ }
+
+ val = g_hash_table_lookup (hash, "options");
+ if (val) {
+ strv = (char **) g_value_get_boxed (val);
+ for (ptr = strv; *ptr; ptr++)
+ config->options = g_slist_prepend (config->options, *ptr);
+ config->options = g_slist_reverse (config->options);
+ }
+
+ val = g_hash_table_lookup (hash, "domains");
+ if (val) {
+ GHashTable *table = (GHashTable *) g_value_get_boxed (val);
+ GHashTableIter iter;
+ gpointer key, value;
+ NMGlobalDnsDomainConfig *domain;
+
+ g_hash_table_iter_init (&iter, table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ domain = build_dns_global_domain_from_hash ((char *)key, (GHashTable *) value);
+ if (domain)
+ g_hash_table_insert (config->domains, g_strdup ((char *) key), domain);
+ }
+ }
+
+ nm_config_data_set_global_dns_config (self, config);
+ return global_dns_config_update_keyfile (self, config);
+}
+
/************************************************************************/
char *
diff --git a/src/nm-config-data.h b/src/nm-config-data.h
index 8f44fb6d6b..0faf627269 100644
--- a/src/nm-config-data.h
+++ b/src/nm-config-data.h
@@ -137,6 +137,9 @@ gboolean nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *
gboolean nm_config_data_get_assume_ipv6ll_only (const NMConfigData *self, NMDevice *device);
NMGlobalDnsConfig *nm_config_data_get_global_dns_config (const NMConfigData *self);
void nm_config_data_set_global_dns_config (const NMConfigData *self, NMGlobalDnsConfig *conf);
+GKeyFile *nm_config_data_update_global_dns_config (const NMConfigData *self,
+ GHashTable *hash,
+ GError **error);
char *nm_config_data_get_connection_default (const NMConfigData *self,
const char *property,
diff --git a/src/nm-manager.c b/src/nm-manager.c
index bf9e69a368..f02f4742af 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -111,6 +111,10 @@ static void impl_manager_get_logging (NMManager *manager,
static void impl_manager_check_connectivity (NMManager *manager,
DBusGMethodInvocation *context);
+static void impl_manager_set_global_dns_config (NMManager *manager,
+ GHashTable *settings,
+ DBusGMethodInvocation *context);
+
#include "nm-manager-glue.h"
static void add_device (NMManager *self, NMDevice *device, gboolean try_assume);
@@ -3945,6 +3949,27 @@ impl_manager_check_connectivity (NMManager *manager,
}
static void
+impl_manager_set_global_dns_config (NMManager *manager,
+ GHashTable *settings,
+ DBusGMethodInvocation *context)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
+ NMConfigData *data;
+ GError *error = NULL;
+ GKeyFile *keyfile;
+
+ data = nm_config_get_data (priv->config);
+ keyfile = nm_config_data_update_global_dns_config (data, settings, &error);
+ nm_config_set_values (priv->config, keyfile, TRUE, FALSE);
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ } else
+ dbus_g_method_return (context);
+}
+
+static void
start_factory (NMDeviceFactory *factory, gpointer user_data)
{
nm_device_factory_start (factory);