Move to protocol independent code in most of lib/util_sock.c
authorJeremy Allison <jra@samba.org>
Mon, 15 Oct 2007 23:11:48 +0000 (16:11 -0700)
committerJeremy Allison <jra@samba.org>
Mon, 15 Oct 2007 23:11:48 +0000 (16:11 -0700)
We don't use gethostbyname any more except in one case where
we're looking for host aliases (I don't know how to do that
with getaddrinfo yet). New function should be getaddrinfo().
Next step will be fixing lib/access.c, and then changing
libsmb/namequery.c to cope with IPv6 address returns.
Jeremy.

source/lib/interface.c
source/lib/system.c
source/lib/util.c
source/lib/util_sock.c
source/libsmb/namequery.c
source/nsswitch/winbind_krb5_locator.c

index ded70683e0ddcabdbde3c699dbd154d77bf82e9f..d2aa69a2893edf51f8c267c8a71dfe4173a71c1b 100644 (file)
@@ -461,7 +461,7 @@ static void interpret_interface(char *token)
        /* maybe it is a DNS name */
        p = strchr_m(token,'/');
        if (p == NULL) {
-               if (!interpret_string_addr(&ss, token)) {
+               if (!interpret_string_addr(&ss, token, 0)) {
                        DEBUG(2, ("interpret_interface: Can't find address "
                                  "for %s\n", token));
                        return;
@@ -481,7 +481,7 @@ static void interpret_interface(char *token)
 
        /* parse it into an IP address/netmasklength pair */
        *p = 0;
-       goodaddr = interpret_string_addr(&ss, token);
+       goodaddr = interpret_string_addr(&ss, token, 0);
        *p++ = '/';
 
        if (!goodaddr) {
@@ -492,7 +492,7 @@ static void interpret_interface(char *token)
        }
 
        if (strlen(p) > 2) {
-               goodaddr = interpret_string_addr(&ss_mask, p);
+               goodaddr = interpret_string_addr(&ss_mask, p, 0);
                if (!goodaddr) {
                        DEBUG(2,("interpret_interface: "
                                "can't determine netmask from %s\n",
index bc7de847675c70975a6ce21a7f1a80289e0b2313..bf35722ea59ddff5fdb207cfa20b0b9144e3115c 100644 (file)
@@ -682,49 +682,6 @@ int sys_chroot(const char *dname)
 #endif
 }
 
-/**************************************************************************
-A wrapper for gethostbyname() that tries avoids looking up hostnames
-in the root domain, which can cause dial-on-demand links to come up for no
-apparent reason.
-****************************************************************************/
-
-struct hostent *sys_gethostbyname(const char *name)
-{
-#ifdef REDUCE_ROOT_DNS_LOOKUPS
-       char query[HOST_NAME_MAX], hostname[HOST_NAME_MAX];
-       char *domain;
-
-       /* Does this name have any dots in it? If so, make no change */
-
-       if (strchr_m(name, '.'))
-               return(gethostbyname(name));
-
-       /* Get my hostname, which should have domain name
-               attached. If not, just do the gethostname on the
-               original string.
-       */
-
-       gethostname(hostname, sizeof(hostname) - 1);
-       hostname[sizeof(hostname) - 1] = 0;
-       if ((domain = strchr_m(hostname, '.')) == NULL)
-               return(gethostbyname(name));
-
-       /* Attach domain name to query and do modified query.
-               If names too large, just do gethostname on the
-               original string.
-       */
-
-       if((strlen(name) + strlen(domain)) >= sizeof(query))
-               return(gethostbyname(name));
-
-       slprintf(query, sizeof(query)-1, "%s%s", name, domain);
-       return(gethostbyname(query));
-#else /* REDUCE_ROOT_DNS_LOOKUPS */
-       return(gethostbyname(name));
-#endif /* REDUCE_ROOT_DNS_LOOKUPS */
-}
-
-
 #if defined(HAVE_POSIX_CAPABILITIES)
 
 #ifdef HAVE_SYS_CAPABILITY_H
index f457e53c47f4aa160342815a6dc6a45f788582b9..b25190b2f778e2f7a8d12d7dbe56860a5ea3fadd 100644 (file)
@@ -1208,37 +1208,6 @@ BOOL get_myname(char *my_name)
        return(True);
 }
 
-/****************************************************************************
- Get my own canonical name, including domain.
-****************************************************************************/
-
-BOOL get_mydnsfullname(fstring my_dnsname)
-{
-       static fstring dnshostname;
-       struct hostent *hp;
-
-       if (!*dnshostname) {
-               /* get my host name */
-               if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
-                       *dnshostname = '\0';
-                       DEBUG(0,("gethostname failed\n"));
-                       return False;
-               } 
-
-               /* Ensure null termination. */
-               dnshostname[sizeof(dnshostname)-1] = '\0';
-
-               /* Ensure we get the cannonical name. */
-               if (!(hp = sys_gethostbyname(dnshostname))) {
-                       *dnshostname = '\0';
-                       return False;
-               }
-               fstrcpy(dnshostname, hp->h_name);
-       }
-       fstrcpy(my_dnsname, dnshostname);
-       return True;
-}
-
 /****************************************************************************
  Get my own domain name.
 ****************************************************************************/
@@ -2742,48 +2711,48 @@ 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)
+ 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.
 ***********************************************************************/
-                                                                                                                                                   
-BOOL name_to_fqdn(fstring fqdn, const char *name)
-{
-       struct hostent *hp = sys_gethostbyname(name);
-
-       if ( hp && hp->h_name && *hp->h_name ) {
-               char *full = NULL;
-
-               /* 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;
-                               }
-                       }
-               }
-               if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
-                       DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
-                       DEBUGADD(1, ("    Specifing 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);
-               return True;
-       } else {
+bool name_to_fqdn(fstring fqdn, const char *name)
+{
+       char *full = NULL;
+       struct hostent *hp = gethostbyname(name);
+
+       if (!hp || !hp->h_name || !*hp->h_name) {
                DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
                fstrcpy(fqdn, name);
-               return False;
+               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;
+                       }
+               }
+       }
+       if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
+               DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
+               DEBUGADD(1, ("    Specifing 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);
+       return true;
 }
 
 /**********************************************************************
index 8079932620815f15be5b3336239193b6dc1436a9..eb3b35339c181aa455b49eaec41a51db2c76a54e 100644 (file)
@@ -29,63 +29,133 @@ static int client_fd = -1;
 static char client_ip_string[INET6_ADDRSTRLEN];
 
 /****************************************************************************
- Return true if a string could be a pure IPv4 address.
+ Return true if a string could be an IPv4 address.
 ****************************************************************************/
 
 bool is_ipaddress_v4(const char *str)
 {
-       bool pure_address = true;
-       int i;
+       int ret = -1;
+       struct in_addr dest;
 
-       for (i=0; pure_address && str[i]; i++) {
-               if (!(isdigit((int)str[i]) || str[i] == '.')) {
-                       pure_address = false;
-               }
+       ret = inet_pton(AF_INET, str, &dest);
+       if (ret > 0) {
+               return true;
        }
+       return false;
+}
 
-       /* Check that a pure number is not misinterpreted as an IP */
-       pure_address = pure_address && (strchr_m(str, '.') != NULL);
-       return pure_address;
+/****************************************************************************
+ Return true if a string could be an IPv4 or IPv6 address.
+****************************************************************************/
+
+bool is_ipaddress(const char *str)
+{
+       int ret = -1;
+
+#if defined(AF_INET6)
+       struct in6_addr dest6;
+
+       ret = inet_pton(AF_INET6, str, &dest6);
+       if (ret > 0) {
+               return true;
+       }
+#endif
+       return is_ipaddress_v4(str);
+}
+
+/*******************************************************************
+ Wrap getaddrinfo...
+******************************************************************/
+
+static bool interpret_string_addr_internal(struct addrinfo **ppres,
+                                       const char *str, int flags)
+{
+       int ret;
+       struct addrinfo hints;
+
+       memset(&hints, '\0', sizeof(hints));
+       /* By default make sure it supports TCP. */
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = flags;
+
+       ret = getaddrinfo(str, NULL,
+                       &hints,
+                       ppres);
+       if (ret) {
+               DEBUG(3,("interpret_string_addr_interal: getaddrinfo failed "
+                       "for name %s [%s]\n",
+                       str,
+                       gai_strerror(ret) ));
+               return false;
+       }
+       return true;
 }
 
 /****************************************************************************
  Interpret an internet address or name into an IP address in 4 byte form.
+ RETURNS IN NETWORK BYTE ORDER (big endian).
 ****************************************************************************/
 
 uint32 interpret_addr(const char *str)
 {
-       struct hostent *hp;
-       uint32 res;
+       uint32 ret;
 
-       if (strcmp(str,"0.0.0.0") == 0)
-               return(0);
-       if (strcmp(str,"255.255.255.255") == 0)
-               return(0xFFFFFFFF);
-
-       /* if it's in the form of an IP address then
+       /* If it's in the form of an IP address then
         * get the lib to interpret it */
        if (is_ipaddress_v4(str)) {
-               res = inet_addr(str);
+               struct in_addr dest;
+
+               if (inet_pton(AF_INET, str, &dest) <= 0) {
+                       /* Error - this shouldn't happen ! */
+                       DEBUG(0,("interpret_addr: inet_pton failed "
+                               "host %s\n",
+                               str));
+                       return 0;
+               }
+               ret = dest.s_addr; /* NETWORK BYTE ORDER ! */
        } else {
-               /* otherwise assume it's a network name of some sort and use
-                       sys_gethostbyname */
-               if ((hp = sys_gethostbyname(str)) == 0) {
-                       DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
+               /* Otherwise assume it's a network name of some sort and use
+                       getadddrinfo. */
+               struct addrinfo *res = NULL;
+               struct addrinfo *res_list = NULL;
+               if (!interpret_string_addr_internal(&res_list,
+                                       str,
+                                       AI_ADDRCONFIG)) {
+                       DEBUG(3,("interpret_addr: Unknown host. %s\n",str));
                        return 0;
                }
 
-               if(hp->h_addr == NULL) {
-                       DEBUG(3,("sys_gethostbyname: host address is "
+               /* Find the first IPv4 address. */
+               for (res = res_list; res; res = res->ai_next) {
+                       if (res->ai_family != AF_INET) {
+                               continue;
+                       }
+                       if (res->ai_addr == NULL) {
+                               continue;
+                       }
+                       break;
+               }
+               if(res == NULL) {
+                       DEBUG(3,("interpret_addr: host address is "
                                "invalid for host %s\n",str));
+                       if (res_list) {
+                               freeaddrinfo(res_list);
+                       }
                        return 0;
                }
-               putip((char *)&res,(char *)hp->h_addr);
+               putip((char *)&ret,
+                       &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr);
+               if (res_list) {
+                       freeaddrinfo(res_list);
+               }
        }
 
-       if (res == (uint32)-1)
-               return(0);
+       /* This is so bogus - all callers need fixing... JRA. */
+       if (ret == (uint32)-1) {
+               return 0;
+       }
 
-       return(res);
+       return ret;
 }
 
 /*******************************************************************
@@ -105,31 +175,20 @@ struct in_addr *interpret_addr2(const char *str)
  struct sockaddr_storage.
 ******************************************************************/
 
-bool interpret_string_addr(struct sockaddr_storage *pss, const char *str)
+bool interpret_string_addr(struct sockaddr_storage *pss,
+               const char *str,
+               int flags)
 {
-       int ret;
        struct addrinfo *res = NULL;
-       struct addrinfo hints;
 
        memset(pss,'\0', sizeof(*pss));
 
-       memset(&hints, '\0', sizeof(hints));
-       /* By default make sure it supports TCP. */
-       hints.ai_socktype = SOCK_STREAM;
-       hints.ai_flags = AI_ADDRCONFIG;
-
-       ret = getaddrinfo(str, NULL,
-                       &hints,
-                       &res);
-
-       if (ret) {
-               DEBUG(3,("interpret_string_addr: getaddrinfo failed for "
-                       "name %s [%s]\n",
-                       str,
-                       gai_strerror(ret) ));
+       if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) {
+               return false;
+       }
+       if (!res) {
                return false;
        }
-
        /* Copy the first sockaddr. */
        memcpy(pss, res->ai_addr, res->ai_addrlen);
        freeaddrinfo(res);
@@ -155,7 +214,8 @@ bool is_loopback_addr(const struct sockaddr_storage *pss)
 {
 #if defined(AF_INET6)
        if (pss->ss_family == AF_INET) {
-               struct in6_addr *pin6 = &((struct sockaddr_in6 *)pss)->sin6_addr;
+               struct in6_addr *pin6 =
+                       &((struct sockaddr_in6 *)pss)->sin6_addr;
                return IN6_IS_ADDR_LOOPBACK(pin6);
        }
 #endif
@@ -185,7 +245,8 @@ bool is_zero_addr(const struct sockaddr_storage *pss)
 {
 #if defined(AF_INET6)
        if (pss->ss_family == AF_INET) {
-               struct in6_addr *pin6 = &((struct sockaddr_in6 *)pss)->sin6_addr;
+               struct in6_addr *pin6 =
+                       &((struct sockaddr_in6 *)pss)->sin6_addr;
                return IN6_IS_ADDR_UNSPECIFIED(pin6);
        }
 #endif
@@ -1215,7 +1276,7 @@ bool send_smb(int fd, char *buffer)
 int open_socket_in(int type,
                int port,
                int dlevel,
-               uint32 socket_addr,
+               uint32 socket_addr, /* NETWORK BYTE ORDER */
                bool rebind )
 {
        struct sockaddr_in sock;
@@ -1595,22 +1656,14 @@ static bool matchname(const char *remotehost,
                const struct sockaddr_storage *pss,
                socklen_t len)
 {
-       struct addrinfo hints;
        struct addrinfo *res = NULL;
        struct addrinfo *ailist = NULL;
        char addr_buf[INET6_ADDRSTRLEN];
-       int ret = -1;
-
-       memset(&hints,'\0',sizeof(struct addrinfo));
-       /* By default make sure it supports TCP. */
-       hints.ai_socktype = SOCK_STREAM;
-       hints.ai_flags = AI_ADDRCONFIG|AI_CANONNAME;
-
-       ret = getaddrinfo(remotehost, NULL,
-                       &hints,
-                       &res);
+       bool ret = interpret_string_addr_internal(&ailist,
+                       remotehost,
+                       AI_ADDRCONFIG|AI_CANONNAME);
 
-       if (ret || res == NULL) {
+       if (!ret || ailist == NULL) {
                DEBUG(3,("matchname: getaddrinfo failed for "
                        "name %s [%s]\n",
                        remotehost,
@@ -1622,24 +1675,25 @@ static bool matchname(const char *remotehost,
         * Make sure that getaddrinfo() returns the "correct" host name.
         */
 
-       if (res->ai_canonname == NULL ||
-               (!strequal(remotehost, res->ai_canonname) &&
+       if (ailist->ai_canonname == NULL ||
+               (!strequal(remotehost, ailist->ai_canonname) &&
                 !strequal(remotehost, "localhost"))) {
                DEBUG(0,("matchname: host name/name mismatch: %s != %s\n",
                         remotehost,
-                        res->ai_canonname ? res->ai_canonname : "(NULL)"));
-               freeaddrinfo(res);
+                        ailist->ai_canonname ?
+                                ailist->ai_canonname : "(NULL)"));
+               freeaddrinfo(ailist);
                return false;
        }
 
        /* Look up the host address in the address list we just got. */
-       for (ailist = res; ailist; ailist = ailist->ai_next) {
-               if (!ailist->ai_addr) {
+       for (res = ailist; res; res = res->ai_next) {
+               if (!res->ai_addr) {
                        continue;
                }
-               if (addr_equal((const struct sockaddr_storage *)ailist->ai_addr,
+               if (addr_equal((const struct sockaddr_storage *)res->ai_addr,
                                        pss)) {
-                       freeaddrinfo(res);
+                       freeaddrinfo(ailist);
                        return true;
                }
        }
@@ -1655,9 +1709,11 @@ static bool matchname(const char *remotehost,
                        sizeof(addr_buf),
                        pss,
                        len),
-                res->ai_canonname ? res->ai_canonname : "(NULL)"));
+                ailist->ai_canonname ? ailist->ai_canonname : "(NULL)"));
 
-       freeaddrinfo(res);
+       if (ailist) {
+               freeaddrinfo(ailist);
+       }
        return false;
 }
 
@@ -1837,8 +1893,62 @@ out_umask:
 #endif /* HAVE_UNIXSOCKET */
 }
 
+/****************************************************************************
+ Get my own canonical name, including domain.
+****************************************************************************/
+
+bool get_mydnsfullname(fstring my_dnsname)
+{
+       static fstring dnshostname;
+
+       if (!*dnshostname) {
+               struct addrinfo *res = NULL;
+               bool ret;
+
+               /* get my host name */
+               if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
+                       *dnshostname = '\0';
+                       DEBUG(0,("get_mydnsfullname: gethostname failed\n"));
+                       return false;
+               }
+
+               /* Ensure null termination. */
+               dnshostname[sizeof(dnshostname)-1] = '\0';
+
+               ret = interpret_string_addr_internal(&res,
+                                       dnshostname,
+                                       AI_ADDRCONFIG|AI_CANONNAME);
+
+               if (!ret || res == NULL) {
+                       DEBUG(3,("get_mydnsfullname: getaddrinfo failed for "
+                               "name %s [%s]\n",
+                               dnshostname,
+                               gai_strerror(ret) ));
+                       return false;
+               }
+
+               /*
+                * Make sure that getaddrinfo() returns the "correct" host name.
+                */
+
+               if (res->ai_canonname == NULL) {
+                       DEBUG(3,("get_mydnsfullname: failed to get "
+                               "canonical name for %s\n",
+                               dnshostname));
+                       freeaddrinfo(res);
+                       return false;
+               }
+
+
+               fstrcpy(dnshostname, res->ai_canonname);
+               freeaddrinfo(res);
+       }
+       fstrcpy(my_dnsname, dnshostname);
+       return true;
+}
+
 /************************************************************
- Is this my name ? Needs fixing for IPv6.
+ Is this my name ?
 ************************************************************/
 
 bool is_myname_or_ipaddr(const char *s)
@@ -1846,83 +1956,82 @@ bool is_myname_or_ipaddr(const char *s)
        fstring name, dnsname;
        char *servername;
 
-       if ( !s ) {
+       if (!s) {
                return false;
        }
 
-       /* santize the string from '\\name' */
+       /* Santize the string from '\\name' */
+       fstrcpy(name, s);
 
-       fstrcpy( name, s );
-
-       servername = strrchr_m( name, '\\' );
-       if ( !servername )
+       servername = strrchr_m(name, '\\' );
+       if (!servername) {
                servername = name;
-       else
+       } else {
                servername++;
+       }
 
-       /* optimize for the common case */
-
-       if (strequal(servername, global_myname()))
+       /* Optimize for the common case */
+       if (strequal(servername, global_myname())) {
                return true;
+       }
 
-       /* check for an alias */
-
-       if (is_myname(servername))
+       /* Check for an alias */
+       if (is_myname(servername)) {
                return true;
+       }
 
-       /* check for loopback */
-
-       if (strequal(servername, "127.0.0.1"))
+       /* Check for loopback */
+       if (strequal(servername, "127.0.0.1") ||
+                       strequal(servername, "::1")) {
                return true;
+       }
 
-       if (strequal(servername, "localhost"))
+       if (strequal(servername, "localhost")) {
                return true;
+       }
 
-       /* maybe it's my dns name */
-
-       if ( get_mydnsfullname( dnsname ) )
-               if ( strequal( servername, dnsname ) )
+       /* Maybe it's my dns name */
+       if (get_mydnsfullname(dnsname)) {
+               if (strequal(servername, dnsname)) {
                        return true;
+               }
+       }
 
-       /* handle possible CNAME records */
-
-       if ( !is_ipaddress_v4( servername ) ) {
-               /* use DNS to resolve the name, but only the first address */
-               struct hostent *hp;
-
-               if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
-                       struct in_addr return_ip;
-                       putip( (char*)&return_ip, (char*)hp->h_addr );
-                       fstrcpy( name, inet_ntoa( return_ip ) );
+       /* Handle possible CNAME records - convert to an IP addr. */
+       if (!is_ipaddress(servername)) {
+               /* Use DNS to resolve the name, but only the first address */
+               struct sockaddr_storage ss;
+               if (interpret_string_addr(&ss, servername,0)) {
+                       print_sockaddr(name,
+                                       sizeof(name),
+                                       &ss,
+                                       sizeof(ss));
                        servername = name;
                }
        }
 
-       /* maybe its an IP address? */
-       if (is_ipaddress_v4(servername)) {
+       /* Maybe its an IP address? */
+       if (is_ipaddress(servername)) {
                struct sockaddr_storage ss;
                struct iface_struct nics[MAX_INTERFACES];
                int i, n;
-               struct in_addr ip;
 
-               ip = *interpret_addr2(servername);
-               if (is_zero_ip_v4(ip) || is_loopback_ip_v4(ip)) {
+               if (!interpret_string_addr(&ss, servername, AI_NUMERICHOST)) {
                        return false;
                }
 
-               in_addr_to_sockaddr_storage(&ss, ip);
+               if (is_zero_addr(&ss) || is_loopback_addr(&ss)) {
+                       return false;
+               }
 
                n = get_interfaces(nics, MAX_INTERFACES);
                for (i=0; i<n; i++) {
-                       if (nics[i].ip.ss_family != AF_INET) {
-                               continue;
-                       }
                        if (addr_equal(&nics[i].ip, &ss)) {
                                return true;
                        }
                }
        }
 
-       /* no match */
+       /* No match */
        return false;
 }
index 182d3641f71bbb0161b7d843ac1efc0858ded6ba..5459210c64f13ee805281db3519d9d79e3422868 100644 (file)
@@ -1028,8 +1028,12 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
        /*
         * "host" means do a localhost, or dns lookup.
         */
-       struct hostent *hp;
-       
+       struct addrinfo hints;
+       struct addrinfo *ailist = NULL;
+       struct addrinfo *res = NULL;
+       int ret = -1;
+       int i = 0;
+
        if ( name_type != 0x20 && name_type != 0x0) {
                DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
                return NT_STATUS_INVALID_PARAMETER;
@@ -1039,18 +1043,54 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
        *return_count = 0;
 
        DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
-       
-       if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
+
+       ZERO_STRUCT(hints);
+       /* By default make sure it supports TCP. */
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = AI_ADDRCONFIG;
+
+       ret = getaddrinfo(name,
+                       NULL,
+                       &hints,
+                       &ailist);
+       if (ret) {
+               DEBUG(3,("resolve_hosts: getaddrinfo failed for name %s [%s]\n",
+                       name,
+                       gai_strerror(ret) ));
+       }
+
+       for (res = ailist; res; res = res->ai_next) {
                struct in_addr return_ip;
-               putip((char *)&return_ip,(char *)hp->h_addr);
-               *return_iplist = SMB_MALLOC_P(struct ip_service);
-               if(*return_iplist == NULL) {
+
+               /* IPv4 only for now until I convert ip_service */
+               if (res->ai_family != AF_INET) {
+                       continue;
+               }
+               if (!res->ai_addr) {
+                       continue;
+               }
+
+               putip((char *)&return_ip,
+                       &((struct sockaddr_in *)res->ai_addr)->sin_addr);
+
+               *return_count += 1;
+               i++;
+
+               *return_iplist = SMB_REALLOC_ARRAY(*return_iplist,
+                                               struct ip_service,
+                                               *return_count);
+               if (!*return_iplist) {
                        DEBUG(3,("resolve_hosts: malloc fail !\n"));
+                       freeaddrinfo(ailist);
                        return NT_STATUS_NO_MEMORY;
                }
-               (*return_iplist)->ip   = return_ip;
-               (*return_iplist)->port = PORT_NONE;
-               *return_count = 1;
+               (*return_iplist)[i].ip   = return_ip;
+               (*return_iplist)[i].port = PORT_NONE;
+       }
+       if (ailist) {
+               freeaddrinfo(ailist);
+       }
+       if (*return_count) {
                return NT_STATUS_OK;
        }
        return NT_STATUS_UNSUCCESSFUL;
index 18a9fe3429f0c333e84dda843582940ccf845f9a..dc2664b67c21cf7b1170eae8a93c8ce117e43fb9 100644 (file)
@@ -171,7 +171,7 @@ static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
                                                    int (*cbfunc)(void *, int, struct sockaddr *),
                                                    void *cbdata)
 {
-       struct addrinfo *out;
+       struct addrinfo *out = NULL;
        int ret;
        int count = 3;
 
@@ -206,7 +206,6 @@ static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
 #endif
 
        freeaddrinfo(out);
-
        return ret;
 }