From 759bf7946669a70d42c7d8a5f8f56f661ccfb45f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Jun 2010 11:59:46 -0700 Subject: [PATCH] dns: include domain part of hostname in resolv.conf 'searches' (rh #600407) Add the current domain name (from the hostname) to the searches list. The bug report is that when the hostname is set to something like 'dcbw.foobar.com' (ie an FQDN) that pinging 'dcbw' doesn't work because the resolver doesn't have anything to append to 'dcbw' when looking it up. --- src/named-manager/nm-named-manager.c | 62 ++++++++++++++++++++++++++++ src/named-manager/nm-named-manager.h | 5 ++- src/nm-policy.c | 6 +++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/named-manager/nm-named-manager.c b/src/named-manager/nm-named-manager.c index fc3b6e2c17..dc1a6c1db6 100644 --- a/src/named-manager/nm-named-manager.c +++ b/src/named-manager/nm-named-manager.c @@ -66,6 +66,13 @@ struct NMNamedManagerPrivate { NMIP6Config *ip6_vpn_config; NMIP6Config *ip6_device_config; GSList *configs; + char *hostname; + + /* This is a hack because SUSE's netconfig always wants changes + * associated with a network interface, but sometimes a change isn't + * associated with a network interface (like hostnames). + */ + char *last_iface; }; @@ -512,6 +519,11 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error) priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr); + if (iface) { + g_free (priv->last_iface); + priv->last_iface = g_strdup (iface); + } + rc.nameservers = g_ptr_array_new (); rc.domain = NULL; rc.searches = g_ptr_array_new (); @@ -545,6 +557,20 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error) g_assert_not_reached (); } + /* Add the current domain name (from the hostname) to the searches list; + * see rh #600407. The bug report is that when the hostname is set to + * something like 'dcbw.foobar.com' (ie an FQDN) that pinging 'dcbw' doesn't + * work because the resolver doesn't have anything to append to 'dcbw' when + * looking it up. + */ + if (priv->hostname) { + const char *hostsearch = strchr (priv->hostname, '.'); + + /* +1 to get rid of the dot */ + if (hostsearch && strlen (hostsearch + 1)) + add_string_item (rc.searches, hostsearch + 1); + } + domain = rc.domain; /* Per 'man resolv.conf', the search list is limited to 6 domains @@ -742,6 +768,40 @@ nm_named_manager_remove_ip6_config (NMNamedManager *mgr, return TRUE; } +void +nm_named_manager_set_hostname (NMNamedManager *mgr, + const char *hostname) +{ + NMNamedManagerPrivate *priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr); + GError *error = NULL; + const char *filtered = NULL; + + /* Certain hostnames we don't want to include in resolv.conf 'searches' */ + if ( hostname + && strcmp (hostname, "localhost.localdomain") + && strcmp (hostname, "localhost6.localdomain6") + && !strstr (hostname, ".in-addr.arpa") + && strchr (hostname, '.')) { + filtered = hostname; + } + + if ( (!priv->hostname && !filtered) + || (priv->hostname && filtered && !strcmp (priv->hostname, filtered))) + return; + + g_free (priv->hostname); + priv->hostname = g_strdup (filtered); + + /* Passing the last interface here is completely bogus, but SUSE's netconfig + * wants one. But hostname changes are system-wide and *not* tied to a + * specific interface, so netconfig can't really handle this. Fake it. + */ + if (!rewrite_resolv_conf (mgr, priv->last_iface, &error)) { + nm_log_warn (LOGD_DNS, "could not commit DNS changes: '%s'", error ? error->message : "(none)"); + g_clear_error (&error); + } +} + static void nm_named_manager_init (NMNamedManager *mgr) @@ -755,6 +815,8 @@ nm_named_manager_finalize (GObject *object) g_slist_foreach (priv->configs, (GFunc) g_object_unref, NULL); g_slist_free (priv->configs); + g_free (priv->hostname); + g_free (priv->last_iface); G_OBJECT_CLASS (nm_named_manager_parent_class)->finalize (object); } diff --git a/src/named-manager/nm-named-manager.h b/src/named-manager/nm-named-manager.h index 47c8e7115d..27d5bc259d 100644 --- a/src/named-manager/nm-named-manager.h +++ b/src/named-manager/nm-named-manager.h @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2004 - 2005 Colin Walters - * Copyright (C) 2004 - 2008 Red Hat, Inc. + * Copyright (C) 2004 - 2010 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. * and others */ @@ -87,6 +87,9 @@ gboolean nm_named_manager_remove_ip6_config (NMNamedManager *mgr, const char *iface, NMIP6Config *config); +void nm_named_manager_set_hostname (NMNamedManager *mgr, + const char *hostname); + G_END_DECLS #endif /* __NM_NAMED_MANAGER_H__ */ diff --git a/src/nm-policy.c b/src/nm-policy.c index 352be12dc1..833a58764c 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -235,8 +235,14 @@ _set_hostname (NMPolicy *policy, char ip6_addr[INET6_ADDRSTRLEN + 1]; if (change_hostname) { + NMNamedManager *named_mgr; + g_free (policy->cur_hostname); policy->cur_hostname = g_strdup (new_hostname); + + named_mgr = nm_named_manager_get (); + nm_named_manager_set_hostname (named_mgr, policy->cur_hostname); + g_object_unref (named_mgr); } /* Get the default IPv4 and IPv6 addresses so we can assign