diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2015-06-19 11:37:33 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2015-06-19 11:37:33 +0200 |
commit | da6b7d9cc97509a17f1f212094d7c8dd410dbba6 (patch) | |
tree | a2d8b39059f2bd2221e240cd78cb8853b74c3141 | |
parent | 028fe6d4898509b5f0c69d39c1dbab78c1152a82 (diff) | |
download | NetworkManager-da6b7d9cc97509a17f1f212094d7c8dd410dbba6.tar.gz |
manager: introduce new SetGlobalDnsConfig D-Bus method
-rw-r--r-- | introspection/nm-manager.xml | 13 | ||||
-rw-r--r-- | src/nm-config-data.c | 173 | ||||
-rw-r--r-- | src/nm-config-data.h | 3 | ||||
-rw-r--r-- | src/nm-manager.c | 25 |
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); |