Add IPv6 support for determining FQDN during ADS join.
authorDavid Holder <david.holder@erion.co.uk>
Tue, 12 May 2015 16:40:29 +0000 (17:40 +0100)
committerJeremy Allison <jra@samba.org>
Tue, 12 May 2015 21:35:32 +0000 (23:35 +0200)
Signed-off-by: David Holder <david.holder@erion.co.uk>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Böhme <rb@sernet.de>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Tue May 12 23:35:32 CEST 2015 on sn-devel-104

source3/lib/util.c

index ec0757e18cdf0d73238b5726d0c0735b2f2a0bac..1d768202448086dcee51746dfef2190e9f573ef1 100644 (file)
@@ -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;
        }
+       full = result->ai_canonname;
 
-       /* Find out if the fqdn is returned as an alias
+       /* 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;
-                       }
-               }
+        * 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;
 }