From b4767a5c1f6ed5515064f26b64ceb5de14fb7e3f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 11 May 2009 20:02:07 -0400 Subject: [PATCH] dns: fix handling of searches and domains in resolv.conf Fix a few issues here: - nm_utils_merge_ip4_config() didn't reset domains, which would cause domains to still be used even if the user elected to ignore DHCP-provided DNS - nm_ip4_config_add_domain() and nm_ip4_config_add_search() didn't filter duplicates - nm_ip4_config_reset_searches() leaked everything - If the user had specified an appended search in the connection, that search would be added to the 'searches' field in resolv.conf, but any server returned domains in 'domain_name' would be ignored because at least one search existed. --- src/NetworkManagerUtils.c | 1 + src/named-manager/nm-named-manager.c | 99 +++++++++++++++++----------- src/nm-ip4-config.c | 50 +++++++++++--- src/nm-ip4-config.h | 1 + 4 files changed, 103 insertions(+), 48 deletions(-) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 8ed3648c9..ae498d8c1 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -204,6 +204,7 @@ nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting) if (nm_setting_ip4_config_get_ignore_auto_dns (setting)) { nm_ip4_config_reset_nameservers (ip4_config); + nm_ip4_config_reset_domains (ip4_config); nm_ip4_config_reset_searches (ip4_config); } diff --git a/src/named-manager/nm-named-manager.c b/src/named-manager/nm-named-manager.c index cc150ef1b..bccc9de62 100644 --- a/src/named-manager/nm-named-manager.c +++ b/src/named-manager/nm-named-manager.c @@ -107,16 +107,15 @@ merge_one_ip4_config (NMIP4Config *dst, NMIP4Config *src) nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i)); num = nm_ip4_config_get_num_searches (src); - if (num > 0) { - for (i = 0; i < num; i++) - nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); - } else { - /* If no search domains were specified, add the 'domain' list to - * search domains. - */ - for (i = 0; i < num_domains; i++) - nm_ip4_config_add_search (dst, nm_ip4_config_get_domain (src, i)); - } + for (i = 0; i < num; i++) + nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); + + /* Add the 'domain' list to searches as well since overloading the + * 'domain_name' DHCP field used to be the way you got searches + * into resolv.conf. + */ + for (i = 0; i < num_domains; i++) + nm_ip4_config_add_search (dst, nm_ip4_config_get_domain (src, i)); } @@ -169,10 +168,10 @@ write_to_netconfig (gint fd, const char *key, const char *value) static gboolean dispatch_netconfig (const char *domain, - char **searches, - char **nameservers, - const char *iface, - GError **error) + char **searches, + char **nameservers, + const char *iface, + GError **error) { gint fd; char *str; @@ -213,9 +212,9 @@ dispatch_netconfig (const char *domain, static gboolean write_resolv_conf (FILE *f, const char *domain, - char **searches, - char **nameservers, - GError **error) + char **searches, + char **nameservers, + GError **error) { char *domain_str = NULL; char *searches_str = NULL; @@ -283,10 +282,10 @@ write_resolv_conf (FILE *f, const char *domain, #ifdef RESOLVCONF_PATH static gboolean dispatch_resolvconf (const char *domain, - char **searches, - char **nameservers, - const char *iface, - GError **error) + char **searches, + char **nameservers, + const char *iface, + GError **error) { char *cmd; FILE *f; @@ -324,10 +323,10 @@ dispatch_resolvconf (const char *domain, static gboolean update_resolv_conf (const char *domain, - char **searches, - char **nameservers, - const char *iface, - GError **error) + char **searches, + char **nameservers, + const char *iface, + GError **error) { const char *tmp_resolv_conf = RESOLV_CONF ".tmp"; char tmp_resolv_conf_realpath [PATH_MAX]; @@ -381,6 +380,35 @@ update_resolv_conf (const char *domain, return *error ? FALSE : TRUE; } +static char ** +compute_searches (guint32 num, NMIP4Config *config, gboolean searches) +{ + GPtrArray *array; + size_t len, elem_len; + const char *elem; + int i; + + /* Search list is limited to 6 domains total per 'man resolv.conf' */ + if (num > 6) + num = 6; + + array = g_ptr_array_sized_new (num + 1); + for (i = 0, len = 0; i < num; i++) { + elem = searches ? nm_ip4_config_get_search (config, i) + : nm_ip4_config_get_domain (config, i); + elem_len = strlen (elem); + + /* The search list is limited to 256 characters per 'man resolv.conf' */ + if (len + elem_len > 255) + break; + + g_ptr_array_add (array, g_strdup (elem)); + len += elem_len + 1; /* +1 for spaces */ + } + + g_ptr_array_add (array, NULL); + return (char **) g_ptr_array_free (array, FALSE); +} static gboolean rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error) @@ -433,21 +461,10 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error) domain = nm_ip4_config_get_domain (composite, 0); /* Searches */ - if (num_searches > 0) { - array = g_ptr_array_sized_new (num_searches + 1); - for (i = 0; i < num_searches; i++) - g_ptr_array_add (array, g_strdup (nm_ip4_config_get_search (composite, i))); - - g_ptr_array_add (array, NULL); - searches = (char **) g_ptr_array_free (array, FALSE); - } else if (num_domains > 0) { - array = g_ptr_array_sized_new (num_domains + 1); - for (i = 0; i < num_domains; i++) - g_ptr_array_add (array, g_strdup (nm_ip4_config_get_domain (composite, i))); - - g_ptr_array_add (array, NULL); - searches = (char **) g_ptr_array_free (array, FALSE); - } + if (num_searches > 0) + searches = compute_searches (num_searches, composite, TRUE); + else if (num_domains > 0) + searches = compute_searches (num_searches, composite, FALSE); /* Name servers */ num_nameservers = nm_ip4_config_get_num_nameservers (composite); @@ -473,6 +490,8 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error) nameservers = (char **) g_ptr_array_free (array, FALSE); } + g_object_unref (composite); + #ifdef RESOLVCONF_PATH success = dispatch_resolvconf (domain, searches, nameservers, iface, error); #endif diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 40d3f5fa6..6dcc2dbcf 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -352,14 +352,21 @@ void nm_ip4_config_reset_routes (NMIP4Config *config) void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain) { + NMIP4ConfigPrivate *priv; + int i; + g_return_if_fail (NM_IS_IP4_CONFIG (config)); g_return_if_fail (domain != NULL); g_return_if_fail (strlen (domain) > 0); - if (!strlen (domain)) - return; + priv = NM_IP4_CONFIG_GET_PRIVATE (config); - g_ptr_array_add (NM_IP4_CONFIG_GET_PRIVATE (config)->domains, g_strdup (domain)); + for (i = 0; i < priv->domains->len; i++) { + if (!strcmp (g_ptr_array_index (priv->domains, i), domain)) + return; + } + + g_ptr_array_add (priv->domains, g_strdup (domain)); } const char *nm_ip4_config_get_domain (NMIP4Config *config, guint i) @@ -376,13 +383,37 @@ guint32 nm_ip4_config_get_num_domains (NMIP4Config *config) return NM_IP4_CONFIG_GET_PRIVATE (config)->domains->len; } +void nm_ip4_config_reset_domains (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv; + int i; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + for (i = 0; i < priv->domains->len; i++) + g_free (g_ptr_array_index (priv->domains, i)); + g_ptr_array_free (priv->domains, TRUE); + priv->domains = g_ptr_array_sized_new (3); +} + void nm_ip4_config_add_search (NMIP4Config *config, const char *search) { + NMIP4ConfigPrivate *priv; + int i; + g_return_if_fail (config != NULL); g_return_if_fail (search != NULL); g_return_if_fail (strlen (search) > 0); - g_ptr_array_add (NM_IP4_CONFIG_GET_PRIVATE (config)->searches, g_strdup (search)); + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + for (i = 0; i < priv->searches->len; i++) { + if (!strcmp (g_ptr_array_index (priv->searches, i), search)) + return; + } + + g_ptr_array_add (priv->searches, g_strdup (search)); } const char *nm_ip4_config_get_search (NMIP4Config *config, guint i) @@ -402,12 +433,15 @@ guint32 nm_ip4_config_get_num_searches (NMIP4Config *config) void nm_ip4_config_reset_searches (NMIP4Config *config) { NMIP4ConfigPrivate *priv; + int i; g_return_if_fail (NM_IS_IP4_CONFIG (config)); priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (priv->searches->len) - g_ptr_array_remove_range (priv->searches, 0, priv->searches->len); + for (i = 0; i < priv->searches->len; i++) + g_free (g_ptr_array_index (priv->searches, i)); + g_ptr_array_free (priv->searches, TRUE); + priv->searches = g_ptr_array_sized_new (3); } guint32 nm_ip4_config_get_mtu (NMIP4Config *config) @@ -696,8 +730,8 @@ nm_ip4_config_init (NMIP4Config *config) priv->nameservers = g_array_new (FALSE, TRUE, sizeof (guint32)); priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32)); - priv->domains = g_ptr_array_new (); - priv->searches = g_ptr_array_new (); + priv->domains = g_ptr_array_sized_new (3); + priv->searches = g_ptr_array_sized_new (3); } static void diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index c2244b80a..04999f877 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -83,6 +83,7 @@ void nm_ip4_config_reset_routes (NMIP4Config *config); void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain); const char * nm_ip4_config_get_domain (NMIP4Config *config, guint i); guint32 nm_ip4_config_get_num_domains (NMIP4Config *config); +void nm_ip4_config_reset_domains (NMIP4Config *config); void nm_ip4_config_add_search (NMIP4Config *config, const char *search); const char * nm_ip4_config_get_search (NMIP4Config *config, guint i);