diff options
Diffstat (limited to 'src/nm-policy-hostname.c')
| -rw-r--r-- | src/nm-policy-hostname.c | 116 |
1 files changed, 95 insertions, 21 deletions
diff --git a/src/nm-policy-hostname.c b/src/nm-policy-hostname.c index a273a920..42a2e0f9 100644 --- a/src/nm-policy-hostname.c +++ b/src/nm-policy-hostname.c @@ -24,6 +24,7 @@ #include <errno.h> #include <netdb.h> #include <ctype.h> +#include <arpa/inet.h> #include <glib.h> @@ -40,7 +41,10 @@ struct HostnameThread { gboolean dead; int ret; - guint32 ip4_addr; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + struct sockaddr *addr; + size_t addr_size; char hostname[NI_MAXHOST + 1]; HostnameThreadCallback callback; @@ -53,9 +57,10 @@ hostname_thread_run_cb (gpointer user_data) HostnameThread *ht = (HostnameThread *) user_data; const char *hostname = NULL; - if (strlen (ht->hostname)) + if (strlen (ht->hostname) && strcmp (ht->hostname, ".")) hostname = ht->hostname; + nm_log_dbg (LOGD_DNS, "(%p) calling address reverse-lookup result handler", ht); (*ht->callback) (ht, ht->ret, hostname, ht->user_data); return FALSE; } @@ -64,9 +69,10 @@ static gpointer hostname_thread_worker (gpointer data) { HostnameThread *ht = (HostnameThread *) data; - struct sockaddr_in addr; int i; + nm_log_dbg (LOGD_DNS, "(%p) starting address reverse-lookup", ht); + g_mutex_lock (ht->lock); if (ht->dead) { g_mutex_unlock (ht->lock); @@ -74,21 +80,22 @@ hostname_thread_worker (gpointer data) } g_mutex_unlock (ht->lock); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ht->ip4_addr; - - ht->ret = getnameinfo ((struct sockaddr *) &addr, sizeof (struct sockaddr_in), - ht->hostname, NI_MAXHOST, NULL, 0, - NI_NAMEREQD); + ht->ret = getnameinfo (ht->addr, ht->addr_size, ht->hostname, NI_MAXHOST, NULL, 0, NI_NAMEREQD); if (ht->ret == 0) { + nm_log_dbg (LOGD_DNS, "(%p) address reverse-lookup returned hostname '%s'", + ht, ht->hostname); for (i = 0; i < strlen (ht->hostname); i++) ht->hostname[i] = tolower (ht->hostname[i]); + } else { + nm_log_dbg (LOGD_DNS, "(%p) address reverse-lookup failed: (%d) %s", + ht, ht->ret, gai_strerror (ht->ret)); } /* Don't track the idle handler ID because by the time the g_idle_add() * returns the ID, the handler may already have run and freed the * HostnameThread. */ + nm_log_dbg (LOGD_DNS, "(%p) scheduling address reverse-lookup result handler", ht); g_idle_add (hostname_thread_run_cb, ht); return (gpointer) TRUE; } @@ -98,15 +105,21 @@ hostname_thread_free (HostnameThread *ht) { g_return_if_fail (ht != NULL); + nm_log_dbg (LOGD_DNS, "(%p) freeing reverse-lookup thread", ht); + g_mutex_free (ht->lock); memset (ht, 0, sizeof (HostnameThread)); g_free (ht); } HostnameThread * -hostname_thread_new (guint32 ip4_addr, HostnameThreadCallback callback, gpointer user_data) +hostname4_thread_new (guint32 ip4_addr, + HostnameThreadCallback callback, + gpointer user_data) { HostnameThread *ht; + struct sockaddr_in addr4; + char buf[INET_ADDRSTRLEN + 1]; ht = g_malloc0 (sizeof (HostnameThread)); g_assert (ht); @@ -114,14 +127,59 @@ hostname_thread_new (guint32 ip4_addr, HostnameThreadCallback callback, gpointer ht->lock = g_mutex_new (); ht->callback = callback; ht->user_data = user_data; - ht->ip4_addr = ip4_addr; + + ht->addr4.sin_family = AF_INET; + ht->addr4.sin_addr.s_addr = ip4_addr; + ht->addr = (struct sockaddr *) &ht->addr4; + ht->addr_size = sizeof (ht->addr4); ht->thread = g_thread_create (hostname_thread_worker, ht, FALSE, NULL); if (!ht->thread) { hostname_thread_free (ht); - ht = NULL; + return NULL; } + if (!inet_ntop (AF_INET, &addr4.sin_addr, buf, sizeof (buf))) + strcpy (buf, "(unknown)"); + + nm_log_dbg (LOGD_DNS, "(%p) started IPv4 reverse-lookup thread for address '%s'", + ht, buf); + + return ht; +} + +HostnameThread * +hostname6_thread_new (const struct in6_addr *ip6_addr, + HostnameThreadCallback callback, + gpointer user_data) +{ + HostnameThread *ht; + char buf[INET6_ADDRSTRLEN + 1]; + + ht = g_malloc0 (sizeof (HostnameThread)); + g_assert (ht); + + ht->lock = g_mutex_new (); + ht->callback = callback; + ht->user_data = user_data; + + ht->addr6.sin6_family = AF_INET6; + ht->addr6.sin6_addr = *ip6_addr; + ht->addr = (struct sockaddr *) &ht->addr6; + ht->addr_size = sizeof (ht->addr6); + + ht->thread = g_thread_create (hostname_thread_worker, ht, FALSE, NULL); + if (!ht->thread) { + hostname_thread_free (ht); + return NULL; + } + + if (!inet_ntop (AF_INET, ip6_addr, buf, sizeof (buf))) + strcpy (buf, "(unknown)"); + + nm_log_dbg (LOGD_DNS, "(%p) started IPv6 reverse-lookup thread for address '%s'", + ht, buf); + return ht; } @@ -130,6 +188,8 @@ hostname_thread_kill (HostnameThread *ht) { g_return_if_fail (ht != NULL); + nm_log_dbg (LOGD_DNS, "(%p) stopping reverse-lookup thread", ht); + g_mutex_lock (ht->lock); ht->dead = TRUE; g_mutex_unlock (ht->lock); @@ -145,20 +205,24 @@ hostname_thread_is_dead (HostnameThread *ht) /************************************************************************/ -#define FALLBACK_HOSTNAME "localhost.localdomain" +#define FALLBACK_HOSTNAME4 "localhost.localdomain" +#define FALLBACK_HOSTNAME6 "localhost6.localdomain6" gboolean -nm_policy_set_system_hostname (const char *new_hostname, const char *msg) +nm_policy_set_system_hostname (const char *new_hostname, + const char *ip4_addr, + const char *ip6_addr, + const char *msg) { char old_hostname[HOST_NAME_MAX + 1]; int ret = 0; const char *name; - gboolean set_hostname = TRUE, changed = FALSE; + gboolean set_hostname = TRUE, changed = FALSE, old_valid = TRUE; if (new_hostname) g_warn_if_fail (strlen (new_hostname)); - name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME; + name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4; old_hostname[HOST_NAME_MAX] = '\0'; errno = 0; @@ -166,11 +230,15 @@ nm_policy_set_system_hostname (const char *new_hostname, const char *msg) if (ret != 0) { nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s", errno, strerror (errno)); + old_valid = FALSE; } else { /* Don't set the hostname if it isn't actually changing */ if ( (new_hostname && !strcmp (old_hostname, new_hostname)) - || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME))) + || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4))) set_hostname = FALSE; + + if (old_hostname[0] == '\0') + old_valid = FALSE; } if (set_hostname) { @@ -190,13 +258,19 @@ nm_policy_set_system_hostname (const char *new_hostname, const char *msg) * nm_policy_hosts_update_etc_hosts() will just return and won't touch * /etc/hosts at all. */ - if (!nm_policy_hosts_update_etc_hosts (name, FALLBACK_HOSTNAME, &changed)) { + if (!nm_policy_hosts_update_etc_hosts (name, + old_valid ? old_hostname : NULL, + FALLBACK_HOSTNAME4, + FALLBACK_HOSTNAME6, + ip4_addr, + ip6_addr, + &changed)) { /* error updating /etc/hosts; fallback to localhost.localdomain */ - nm_log_info (LOGD_DNS, "Setting system hostname to '" FALLBACK_HOSTNAME "' (error updating /etc/hosts)"); - ret = sethostname (FALLBACK_HOSTNAME, strlen (FALLBACK_HOSTNAME)); + nm_log_info (LOGD_DNS, "Setting system hostname to '" FALLBACK_HOSTNAME4 "' (error updating /etc/hosts)"); + ret = sethostname (FALLBACK_HOSTNAME4, strlen (FALLBACK_HOSTNAME4)); if (ret != 0) { nm_log_warn (LOGD_DNS, "couldn't set the fallback system hostname (%s): (%d) %s", - FALLBACK_HOSTNAME, errno, strerror (errno)); + FALLBACK_HOSTNAME4, errno, strerror (errno)); } } |