From 0fe65069781330052da120966b596025cd83deb1 Mon Sep 17 00:00:00 2001 From: David Holder Date: Tue, 12 May 2015 17:40:29 +0100 Subject: [PATCH] Add IPv6 support for determining FQDN during ADS join. Signed-off-by: David Holder --- source3/lib/util.c | 60 +++++++++++++++++++++++++++++++-------------------- 1 files changed, 36 insertions(+), 24 deletions(-) diff --git a/source3/lib/util.c b/source3/lib/util.c index ec0757e..7713074 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -1836,48 +1836,60 @@ bool unix_wild_match(const char *pattern, const char *string) } /********************************************************************** - Converts a name to a fully qualified domain name. - Returns true if lookup succeeded, false if not (then fqdn is set to name) - Note we deliberately use gethostbyname here, not getaddrinfo as we want - to examine the h_aliases and I don't know how to do that with getaddrinfo. -***********************************************************************/ + Converts a name to a fully qualified domain name. + Returns true if lookup succeeded, false if not (then fqdn is set to name) + Uses getaddrinfo() with AI_CANONNAME flag to obtain the official + canonical name of the host. getaddrinfo() may use a variety of sources + including /etc/hosts to obtain the domainname. It expects aliases in + /etc/hosts to NOT be the FQDN. The FQDN should come first. +************************************************************************/ bool name_to_fqdn(fstring fqdn, const char *name) { char *full = NULL; - struct hostent *hp = gethostbyname(name); + struct addrinfo hints; + struct addrinfo *result; + int s; + + /* Configure hints to obtain canonical name */ + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + hints.ai_flags = AI_CANONNAME; /* Get host's FQDN */ + hints.ai_protocol = 0; /* Any protocol */ - if (!hp || !hp->h_name || !*hp->h_name) { + s = getaddrinfo(name, NULL, &hints, &result); + if (s != 0) { + DEBUG(1, ("getaddrinfo: %s\n", gai_strerror(s))); DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name)); fstrcpy(fqdn, name); return false; - } - - /* Find out if the fqdn is returned as an alias - * to cope with /etc/hosts files where the first - * name is not the fqdn but the short name */ - if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) { - int i; - for (i = 0; hp->h_aliases[i]; i++) { - if (strchr_m(hp->h_aliases[i], '.')) { - full = hp->h_aliases[i]; - break; - } - } + } + full = result->ai_canonname; + + /* Find out if the FQDN is returned as an alias + * to cope with /etc/hosts files where the first + * name is not the FQDN but the short name. + * getaddrinfo provides no easy way of handling aliases + * in /etc/hosts. Users should make sure the FQDN + * comes first in /etc/hosts. */ + if (full && (! strchr_m(full, '.'))) { + DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n")); + DEBUGADD(1, (" Full qualified domain names (FQDNs) should not be specified\n")); + DEBUGADD(1, (" as an alias in /etc/hosts. FQDN should be the first name\n")); + DEBUGADD(1, (" prior to any aliases.\n")); } if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) { DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n")); DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n")); DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n")); DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n")); - full = hp->h_name; - } - if (!full) { - full = hp->h_name; } DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full)); fstrcpy(fqdn, full); + freeaddrinfo(result); /* No longer needed */ return true; } -- 1.7.1