Remove Name_Service definition.
[kopensolaris-gnu/glibc.git] / resolv / gethnamaddr.c
index b80595b..7be2315 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -55,9 +51,9 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)gethostnamadr.c    8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -71,7 +67,7 @@ static char rcsid[] = "$Id$";
 #include <errno.h>
 #include <syslog.h>
 
-#include "res_hconf.h"
+#define RESOLVSORT
 
 #ifndef LOG_AUTH
 # define LOG_AUTH 0
@@ -80,43 +76,55 @@ static char rcsid[] = "$Id$";
 #define MULTI_PTRS_ARE_ALIASES 1       /* XXX - experimental */
 
 #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
+# include <stdlib.h>
 # include <string.h>
 #else
 # include "../conf/portability.h"
 #endif
+
 #if defined(USE_OPTIONS_H)
 # include <../conf/options.h>
 #endif
 
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
 #define        MAXALIASES      35
 #define        MAXADDRS        35
-#define        MAXADDRBUFSIZE  8192
 
 static const char AskedForGot[] =
                          "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
 
 static char *h_addr_ptrs[MAXADDRS + 1];
-static struct hostent *gethostbyname_ipv4 __P((const char *));
 
 static struct hostent host;
 static char *host_aliases[MAXALIASES];
-static char hostbuf[MAXADDRBUFSIZE];
+static char hostbuf[8*1024];
 static u_char host_addr[16];   /* IPv4 or IPv6 */
 static FILE *hostf = NULL;
 static int stayopen = 0;
 
-static void map_v4v6_address __P((const char *src, char *dst));
-static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
+static void map_v4v6_address (const char *src, char *dst) __THROW;
+static void map_v4v6_hostent (struct hostent *hp, char **bp, int *len) __THROW;
 
 #ifdef RESOLVSORT
-static void addrsort __P((char **, int));
+extern void addrsort (char **, int) __THROW;
 #endif
 
-#if PACKETSZ > 1024
+#if PACKETSZ > 65536
 #define        MAXPACKET       PACKETSZ
 #else
-#define        MAXPACKET       1024
+#define        MAXPACKET       65536
+#endif
+
+/* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length.  */
+#ifdef MAXHOSTNAMELEN
+# undef MAXHOSTNAMELEN
 #endif
+#define MAXHOSTNAMELEN 256
 
 typedef union {
     HEADER hdr;
@@ -128,11 +136,13 @@ typedef union {
     char ac;
 } align;
 
+#ifndef h_errno
 extern int h_errno;
+#endif
 
 #ifdef DEBUG
 static void
-dprintf(msg, num)
+Dprintf(msg, num)
        char *msg;
        int num;
 {
@@ -140,31 +150,45 @@ dprintf(msg, num)
                int save = errno;
 
                printf(msg, num);
-               errno = save;
+               __set_errno (save);
        }
 }
 #else
-# define dprintf(msg, num) /*nada*/
+# define Dprintf(msg, num) /*nada*/
 #endif
 
+#define BOUNDED_INCR(x) \
+       do { \
+               cp += x; \
+               if (cp > eom) { \
+                       __set_h_errno (NO_RECOVERY); \
+                       return (NULL); \
+               } \
+       } while (0)
+
+#define BOUNDS_CHECK(ptr, count) \
+       do { \
+               if ((ptr) + (count) > eom) { \
+                       __set_h_errno (NO_RECOVERY); \
+                       return (NULL); \
+               } \
+       } while (0)
+
+
 static struct hostent *
-getanswer(answer, anslen, qname, qtype)
-       const querybuf *answer;
-       int anslen;
-       const char *qname;
-       int qtype;
+getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
 {
        register const HEADER *hp;
        register const u_char *cp;
        register int n;
-       const u_char *eom;
+       const u_char *eom, *erdata;
        char *bp, **ap, **hap;
        int type, class, buflen, ancount, qdcount;
        int haveanswer, had_error;
        int toobig = 0;
-       char tbuf[MAXDNAME+1];
+       char tbuf[MAXDNAME];
        const char *tname;
-       int (*name_ok) __P((const char *));
+       int (*name_ok) (const char *);
 
        tname = qname;
        host.h_name = NULL;
@@ -188,23 +212,28 @@ getanswer(answer, anslen, qname, qtype)
        qdcount = ntohs(hp->qdcount);
        bp = hostbuf;
        buflen = sizeof hostbuf;
-       cp = answer->buf + HFIXEDSZ;
+       cp = answer->buf;
+       BOUNDED_INCR(HFIXEDSZ);
        if (qdcount != 1) {
-               h_errno = NO_RECOVERY;
+               __set_h_errno (NO_RECOVERY);
                return (NULL);
        }
        n = dn_expand(answer->buf, eom, cp, bp, buflen);
        if ((n < 0) || !(*name_ok)(bp)) {
-               h_errno = NO_RECOVERY;
+               __set_h_errno (NO_RECOVERY);
                return (NULL);
        }
-       cp += n + QFIXEDSZ;
+       BOUNDED_INCR(n + QFIXEDSZ);
        if (qtype == T_A || qtype == T_AAAA) {
                /* res_send() has already verified that the query name is the
                 * same as the one we sent; this just gets the expanded name
                 * (i.e., with the succeeding search-domain tacked on).
                 */
                n = strlen(bp) + 1;             /* for the \0 */
+               if (n >= MAXHOSTNAMELEN) {
+                       __set_h_errno (NO_RECOVERY);
+                       return (NULL);
+               }
                host.h_name = bp;
                bp += n;
                buflen -= n;
@@ -226,12 +255,15 @@ getanswer(answer, anslen, qname, qtype)
                        continue;
                }
                cp += n;                        /* name */
-               type = _getshort(cp);
-               cp += INT16SZ;                  /* type */
-               class = _getshort(cp);
-               cp += INT16SZ + INT32SZ;        /* class, TTL */
-               n = _getshort(cp);
+               BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+               type = ns_get16(cp);
+               cp += INT16SZ;                  /* type */
+               class = ns_get16(cp);
+               cp += INT16SZ + INT32SZ;        /* class, TTL */
+               n = ns_get16(cp);
                cp += INT16SZ;                  /* len */
+               BOUNDS_CHECK(cp, n);
+               erdata = cp + n;
                if (class != C_IN) {
                        /* XXX - debug? syslog? */
                        cp += n;
@@ -246,14 +278,22 @@ getanswer(answer, anslen, qname, qtype)
                                continue;
                        }
                        cp += n;
+                       if (cp != erdata) {
+                               __set_h_errno (NO_RECOVERY);
+                               return (NULL);
+                       }
                        /* Store alias. */
                        *ap++ = bp;
                        n = strlen(bp) + 1;     /* for the \0 */
+                       if (n >= MAXHOSTNAMELEN) {
+                               had_error++;
+                               continue;
+                       }
                        bp += n;
                        buflen -= n;
                        /* Get canonical name. */
                        n = strlen(tbuf) + 1;   /* for the \0 */
-                       if (n > buflen) {
+                       if (n > buflen || n >= MAXHOSTNAMELEN) {
                                had_error++;
                                continue;
                        }
@@ -265,14 +305,18 @@ getanswer(answer, anslen, qname, qtype)
                }
                if (qtype == T_PTR && type == T_CNAME) {
                        n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
-                       if ((n < 0) || !res_hnok(tbuf)) {
+                       if (n < 0 || !res_dnok(tbuf)) {
                                had_error++;
                                continue;
                        }
                        cp += n;
+                       if (cp != erdata) {
+                               __set_h_errno (NO_RECOVERY);
+                               return (NULL);
+                       }
                        /* Get canonical name. */
                        n = strlen(tbuf) + 1;   /* for the \0 */
-                       if (n > buflen) {
+                       if (n > buflen || n >= MAXHOSTNAMELEN) {
                                had_error++;
                                continue;
                        }
@@ -282,6 +326,18 @@ getanswer(answer, anslen, qname, qtype)
                        buflen -= n;
                        continue;
                }
+               if ((type == T_SIG) || (type == T_KEY) || (type == T_NXT)) {
+                       /* We don't support DNSSEC yet.  For now, ignore
+                        * the record and send a low priority message
+                        * to syslog.
+                        */
+                       syslog(LOG_DEBUG|LOG_AUTH,
+              "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+                              qname, p_class(C_IN), p_type(qtype),
+                              p_type(type));
+                       cp += n;
+                       continue;
+               }
                if (type != qtype) {
                        syslog(LOG_NOTICE|LOG_AUTH,
               "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
@@ -305,6 +361,10 @@ getanswer(answer, anslen, qname, qtype)
                        }
 #if MULTI_PTRS_ARE_ALIASES
                        cp += n;
+                       if (cp != erdata) {
+                               __set_h_errno (NO_RECOVERY);
+                               return (NULL);
+                       }
                        if (!haveanswer)
                                host.h_name = bp;
                        else if (ap < &host_aliases[MAXALIASES-1])
@@ -313,6 +373,10 @@ getanswer(answer, anslen, qname, qtype)
                                n = -1;
                        if (n != -1) {
                                n = strlen(bp) + 1;     /* for the \0 */
+                               if (n >= MAXHOSTNAMELEN) {
+                                       had_error++;
+                                       break;
+                               }
                                bp += n;
                                buflen -= n;
                        }
@@ -321,11 +385,15 @@ getanswer(answer, anslen, qname, qtype)
                        host.h_name = bp;
                        if (_res.options & RES_USE_INET6) {
                                n = strlen(bp) + 1;     /* for the \0 */
+                               if (n >= MAXHOSTNAMELEN) {
+                                       had_error++;
+                                       break;
+                               }
                                bp += n;
                                buflen -= n;
                                map_v4v6_hostent(&host, &bp, &buflen);
                        }
-                       h_errno = NETDB_SUCCESS;
+                       __set_h_errno (NETDB_SUCCESS);
                        return (&host);
 #endif
                case T_A:
@@ -336,12 +404,11 @@ getanswer(answer, anslen, qname, qtype)
                                cp += n;
                                continue;       /* XXX - had_error++ ? */
                        }
-                       if (haveanswer) {
-                               if (n != host.h_length) {
-                                       cp += n;
-                                       continue;
-                               }
-                       } else {
+                       if (n != host.h_length) {
+                               cp += n;
+                               continue;
+                       }
+                       if (!haveanswer) {
                                register int nn;
 
                                host.h_name = bp;
@@ -350,23 +417,33 @@ getanswer(answer, anslen, qname, qtype)
                                buflen -= nn;
                        }
 
+                       /* XXX: when incrementing bp, we have to decrement
+                        * buflen by the same amount --okir */
+                       buflen -= sizeof(align) - ((u_long)bp % sizeof(align));
+
                        bp += sizeof(align) - ((u_long)bp % sizeof(align));
 
                        if (bp + n >= &hostbuf[sizeof hostbuf]) {
-                               dprintf("size (%d) too big\n", n);
+                               Dprintf("size (%d) too big\n", n);
                                had_error++;
                                continue;
                        }
                        if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
-                               if (!toobig++)
-                                       dprintf("Too many addresses (%d)\n",
+                               if (!toobig++) {
+                                       Dprintf("Too many addresses (%d)\n",
                                                MAXADDRS);
+                               }
                                cp += n;
                                continue;
                        }
-                       bcopy(cp, *hap++ = bp, n);
+                       memmove(*hap++ = bp, cp, n);
                        bp += n;
+                       buflen -= n;
                        cp += n;
+                       if (cp != erdata) {
+                               __set_h_errno (NO_RECOVERY);
+                               return (NULL);
+                       }
                        break;
                default:
                        abort();
@@ -388,8 +465,8 @@ getanswer(answer, anslen, qname, qtype)
 # endif /*RESOLVSORT*/
                if (!host.h_name) {
                        n = strlen(qname) + 1;  /* for the \0 */
-                       if (n > buflen)
-                               goto try_again;
+                       if (n > buflen || n >= MAXHOSTNAMELEN)
+                               goto no_recovery;
                        strcpy(bp, qname);
                        host.h_name = bp;
                        bp += n;
@@ -397,20 +474,27 @@ getanswer(answer, anslen, qname, qtype)
                }
                if (_res.options & RES_USE_INET6)
                        map_v4v6_hostent(&host, &bp, &buflen);
-               h_errno = NETDB_SUCCESS;
+               __set_h_errno (NETDB_SUCCESS);
                return (&host);
        }
try_again:
-       h_errno = TRY_AGAIN;
no_recovery:
+       __set_h_errno (NO_RECOVERY);
        return (NULL);
 }
 
+extern struct hostent *gethostbyname2(const char *name, int af);
+libresolv_hidden_proto (gethostbyname2)
+
 struct hostent *
 gethostbyname(name)
        const char *name;
 {
        struct hostent *hp;
 
+       if (__res_maybe_init (&_res, 0) == -1) {
+               __set_h_errno (NETDB_INTERNAL);
+               return (NULL);
+       }
        if (_res.options & RES_USE_INET6) {
                hp = gethostbyname2(name, AF_INET6);
                if (hp)
@@ -424,14 +508,19 @@ gethostbyname2(name, af)
        const char *name;
        int af;
 {
-       querybuf buf;
+       union
+       {
+         querybuf *buf;
+         u_char *ptr;
+       } buf;
+       querybuf *origbuf;
        register const char *cp;
        char *bp;
-       int i, n, size, type, len;
-       extern struct hostent *_gethtbyname2();
+       int n, size, type, len;
+       struct hostent *ret;
 
-       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
-               h_errno = NETDB_INTERNAL;
+       if (__res_maybe_init (&_res, 0) == -1) {
+               __set_h_errno (NETDB_INTERNAL);
                return (NULL);
        }
 
@@ -445,8 +534,8 @@ gethostbyname2(name, af)
                type = T_AAAA;
                break;
        default:
-               h_errno = NETDB_INTERNAL;
-               errno = EAFNOSUPPORT;
+               __set_h_errno (NETDB_INTERNAL);
+               __set_errno (EAFNOSUPPORT);
                return (NULL);
        }
 
@@ -475,9 +564,8 @@ gethostbyname2(name, af)
                                 * Fake up a hostent as if we'd actually
                                 * done a lookup.
                                 */
-                               if (inet_pton(af, name, host_addr,
-                                              sizeof host_addr) <= 0) {
-                                       h_errno = HOST_NOT_FOUND;
+                               if (inet_pton(af, name, host_addr) <= 0) {
+                                       __set_h_errno (HOST_NOT_FOUND);
                                        return (NULL);
                                }
                                strncpy(hostbuf, name, MAXDNAME);
@@ -487,90 +575,95 @@ gethostbyname2(name, af)
                                host.h_name = hostbuf;
                                host.h_aliases = host_aliases;
                                host_aliases[0] = NULL;
-                               h_addr_ptrs[0] = (char *)&host_addr;
+                               h_addr_ptrs[0] = (char *)host_addr;
                                h_addr_ptrs[1] = NULL;
                                host.h_addr_list = h_addr_ptrs;
                                if (_res.options & RES_USE_INET6)
                                        map_v4v6_hostent(&host, &bp, &len);
-                               h_errno = NETDB_SUCCESS;
+                               __set_h_errno (NETDB_SUCCESS);
                                return (&host);
                        }
                        if (!isdigit(*cp) && *cp != '.')
                                break;
+               }
+       if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
+           name[0] == ':')
+               for (cp = name;; ++cp) {
+                       if (!*cp) {
+                               if (*--cp == '.')
+                                       break;
+                               /*
+                                * All-IPv6-legal, no dot at the end.
+                                * Fake up a hostent as if we'd actually
+                                * done a lookup.
+                                */
+                               if (inet_pton(af, name, host_addr) <= 0) {
+                                       __set_h_errno (HOST_NOT_FOUND);
+                                       return (NULL);
+                               }
+                               strncpy(hostbuf, name, MAXDNAME);
+                               hostbuf[MAXDNAME] = '\0';
+                               bp = hostbuf + MAXDNAME;
+                               len = sizeof hostbuf - MAXDNAME;
+                               host.h_name = hostbuf;
+                               host.h_aliases = host_aliases;
+                               host_aliases[0] = NULL;
+                               h_addr_ptrs[0] = (char *)host_addr;
+                               h_addr_ptrs[1] = NULL;
+                               host.h_addr_list = h_addr_ptrs;
+                               __set_h_errno (NETDB_SUCCESS);
+                               return (&host);
+                       }
+                       if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
+                               break;
                }
 
-       h_errno = HOST_NOT_FOUND;
-       for (i = 0; i < _res_hconf.num_services; ++i) {
-               struct hostent * hp;
-               char * cp = (char *) name;
-
-               if (_res_hconf.num_trimdomains > 0) {
-                       size_t name_len = strlen(name);
-
-                       cp = malloc(name_len + 1);
-                       memcpy(cp, name, name_len + 1);
-                       _res_hconf_trim_domain(cp);
-               }
-
-               hp = NULL;
-               switch (_res_hconf.service[i]) {
-                     case SERVICE_BIND:
-                       if ((n = res_search(cp, C_IN, type,
-                                           buf.buf, sizeof(buf))) < 0)
-                       {
-                               dprintf("res_search failed (%d)\n", n);
-                               break;
-                       }
-                       hp = getanswer(&buf, n, cp, type);
-                       break;
+       buf.buf = origbuf = (querybuf *) alloca (1024);
 
-                     case SERVICE_HOSTS:
-                       hp = _gethtbyname2(cp, af);
-                       break;
-#ifdef HAVE_NYS
-                     case SERVICE_NIS:
-                       hp = _getnishost(cp, "hosts.byname");
-                       break;
-#endif
-                     default:
-                       break;
-               }
-               if (cp != name)
-                       free(cp);
-               if (hp) {
-                       if ((_res_hconf.flags & HCONF_FLAG_REORDER)
-                           && hp->h_addr_list[0] && hp->h_addr_list[1])
-                               _res_hconf_reorder_addrs(hp);
-                       _res_hconf_trim_domains(hp);
-                       return hp;
-               }
+       if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024,
+                                   &buf.ptr)) < 0) {
+               if (buf.buf != origbuf)
+                       free (buf.buf);
+               Dprintf("res_nsearch failed (%d)\n", n);
+               if (errno == ECONNREFUSED)
+                       return (_gethtbyname2(name, af));
+               return (NULL);
        }
-       if (h_errno == NETDB_SUCCESS)
-               h_errno = HOST_NOT_FOUND;
-       return NULL;
+       ret = getanswer(buf.buf, n, name, type);
+       if (buf.buf != origbuf)
+               free (buf.buf);
+       return ret;
 }
+libresolv_hidden_def (gethostbyname2)
 
 struct hostent *
 gethostbyaddr(addr, len, af)
-       const char *addr;       /* XXX should have been def'd as u_char! */
-       int len, af;
+       const void *addr;
+       socklen_t len;
+       int af;
 {
        const u_char *uaddr = (const u_char *)addr;
        static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
        static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
-       int n, size;
-       querybuf buf;
+       int n;
+       socklen_t size;
+       union
+       {
+         querybuf *buf;
+         u_char *ptr;
+       } buf;
+       querybuf *orig_buf;
        register struct hostent *hp;
-       char qbuf[MAXDNAME+1], *qp;
+       char qbuf[MAXDNAME+1], *qp = NULL;
+#ifdef SUNSECURITY
        register struct hostent *rhp;
        char **haddr;
        u_long old_options;
        char hname2[MAXDNAME+1];
-       int i, old_num_trimdomains;
-       extern struct hostent *_gethtbyaddr();
+#endif /*SUNSECURITY*/
 
-       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
-               h_errno = NETDB_INTERNAL;
+       if (__res_maybe_init (&_res, 0) == -1) {
+               __set_h_errno (NETDB_INTERNAL);
                return (NULL);
        }
        if (af == AF_INET6 && len == IN6ADDRSZ &&
@@ -590,139 +683,103 @@ gethostbyaddr(addr, len, af)
                size = IN6ADDRSZ;
                break;
        default:
-               errno = EAFNOSUPPORT;
-               h_errno = NETDB_INTERNAL;
+               __set_errno (EAFNOSUPPORT);
+               __set_h_errno (NETDB_INTERNAL);
                return (NULL);
        }
        if (size != len) {
-               errno = EINVAL;
-               h_errno = NETDB_INTERNAL;
+               __set_errno (EINVAL);
+               __set_h_errno (NETDB_INTERNAL);
                return (NULL);
        }
+       switch (af) {
+       case AF_INET:
+               (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+                              (uaddr[3] & 0xff),
+                              (uaddr[2] & 0xff),
+                              (uaddr[1] & 0xff),
+                              (uaddr[0] & 0xff));
+               break;
+       case AF_INET6:
+               qp = qbuf;
+               for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+                       qp += SPRINTF((qp, "%x.%x.",
+                                      uaddr[n] & 0xf,
+                                      (uaddr[n] >> 4) & 0xf));
+               }
+               strcpy(qp, "ip6.arpa");
+               break;
+       default:
+               abort();
+       }
 
-       h_errno = NETDB_SUCCESS;
-       for (i = 0; i < _res_hconf.num_services; ++i) {
-               hp = NULL;
-               switch (_res_hconf.service[i]) {
-               case SERVICE_BIND:
-                       switch (af) {
-                       case AF_INET:
-                               (void) sprintf(qbuf,
-                                              "%u.%u.%u.%u.in-addr.arpa",
-                                              (uaddr[3] & 0xff),
-                                              (uaddr[2] & 0xff),
-                                              (uaddr[1] & 0xff),
-                                              (uaddr[0] & 0xff));
-                               break;
-                       case AF_INET6:
-                               qp = qbuf;
-                               for (n = IN6ADDRSZ - 1; n >= 0; n--) {
-                                       qp += sprintf(qp, "%x.%x.",
-                                                     uaddr[n] & 0xf,
-                                                     (uaddr[n] >> 4) & 0xf);
-                               }
-                               strcpy(qp, "ip6.int");
-                               break;
-                       default:
-                               abort();
-                       }
-                       n = res_query(qbuf, C_IN, T_PTR,
-                                     (u_char *)buf.buf, sizeof buf.buf);
-                       if (n < 0) {
-                               dprintf("res_query failed (%d)\n", n);
-                               break;
-                       }
-                       hp = getanswer(&buf, n, qbuf, T_PTR);
-                       if (!hp)
-                               break;  /* h_errno was set by getanswer() */
-                       if (af == AF_INET
-                           && (_res_hconf.flags & HCONF_FLAG_SPOOF)) {
-                               /*
-                                * Turn off search as the name should
-                                * be absolute, 'localhost' should be
-                                * matched by defnames
-                                */
-                               strncpy(hname2, hp->h_name, MAXDNAME);
-                               hname2[MAXDNAME] = '\0';
-                               old_options = _res.options;
-                               /*
-                                * Also turn off domain trimming to prevent it
-                                * from causing the name comparison to fail.
-                                */
-                               old_num_trimdomains =
-                                       _res_hconf.num_trimdomains;
-                               _res.options &= ~RES_DNSRCH;
-                               _res.options |= RES_DEFNAMES;
-                               rhp = gethostbyname(hname2);
-                               _res.options = old_options;
-                               /* There must be an A record and
-                                  the names must match.  */
-                               if (!rhp || strcmp(hname2, rhp->h_name)) {
-                                       syslog(LOG_NOTICE|LOG_AUTH,
-                                              "gethostbyaddr: No A record for"
-                                              " %s (verifying [%s])",
-                                              hname2,
-                                              inet_ntoa(*((struct in_addr *)
-                                                          addr)));
-                                       h_errno = HOST_NOT_FOUND;
-                                       break;
-                               }
-                               for (haddr = rhp->h_addr_list; *haddr; haddr++)
-                                       if (!memcmp(*haddr, addr, INADDRSZ))
-                                               break;
-                               if (!*haddr) {
-                                       syslog(LOG_NOTICE|LOG_AUTH,
-                                              "gethostbyaddr: A record of %s"
-                                              " != PTR record [%s]",
-                                              hname2,
-                                              inet_ntoa(*((struct in_addr *)
-                                                          addr)));
-                                       h_errno = HOST_NOT_FOUND;
-                                       break;
-                               }
-                       }
-                       hp->h_addrtype = af;
-                       hp->h_length = len;
-                       bcopy(addr, host_addr, len);
-                       h_addr_ptrs[0] = (char *)host_addr;
-                       h_addr_ptrs[1] = NULL;
-                       if (af == AF_INET && (_res.options & RES_USE_INET6)) {
-                               map_v4v6_address((char*)host_addr,
-                                                (char*)host_addr);
-                               hp->h_addrtype = AF_INET6;
-                               hp->h_length = IN6ADDRSZ;
-                       }
-                       h_errno = NETDB_SUCCESS;
-                       break;
-
-               case SERVICE_HOSTS:
-                       hp = _gethtbyaddr(addr, len, af);
-                       break;
-
-#ifdef HAVE_NYS
-               case SERVICE_NIS:
-                       if (af == AF_INET) {
-                               sprintf(qbuf, "%u.%u.%u.%u",
-                                       (unsigned)addr[0] & 0xff,
-                                       (unsigned)addr[1] & 0xff,
-                                       (unsigned)addr[2] & 0xff,
-                                       (unsigned)addr[3] & 0xff);
-                               hp = _getnishost(qbuf, "hosts.byaddr");
-                       }
-                       break;
-#endif
+       buf.buf = orig_buf = (querybuf *) alloca (1024);
 
-               default:
+       n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
+                             &buf.ptr);
+       if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) {
+               strcpy(qp, "ip6.int");
+               n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf,
+                                     buf.buf != orig_buf ? MAXPACKET : 1024,
+                                     &buf.ptr);
+       }
+       if (n < 0) {
+               if (buf.buf != orig_buf)
+                       free (buf.buf);
+               Dprintf("res_nquery failed (%d)\n", n);
+               if (errno == ECONNREFUSED)
+                       return (_gethtbyaddr(addr, len, af));
+               return (NULL);
+       }
+       hp = getanswer(buf.buf, n, qbuf, T_PTR);
+       if (buf.buf != orig_buf)
+               free (buf.buf);
+       if (!hp)
+               return (NULL);  /* h_errno was set by getanswer() */
+#ifdef SUNSECURITY
+       if (af == AF_INET) {
+           /*
+            * turn off search as the name should be absolute,
+            * 'localhost' should be matched by defnames
+            */
+           strncpy(hname2, hp->h_name, MAXDNAME);
+           hname2[MAXDNAME] = '\0';
+           old_options = _res.options;
+           _res.options &= ~RES_DNSRCH;
+           _res.options |= RES_DEFNAMES;
+           if (!(rhp = gethostbyname(hname2))) {
+               syslog(LOG_NOTICE|LOG_AUTH,
+                      "gethostbyaddr: No A record for %s (verifying [%s])",
+                      hname2, inet_ntoa(*((struct in_addr *)addr)));
+               _res.options = old_options;
+               __set_h_errno (HOST_NOT_FOUND);
+               return (NULL);
+           }
+           _res.options = old_options;
+           for (haddr = rhp->h_addr_list; *haddr; haddr++)
+               if (!memcmp(*haddr, addr, INADDRSZ))
                        break;
-               }
-               if (hp) {
-                       _res_hconf_trim_domains(hp);
-                       return hp;
-               }
+           if (!*haddr) {
+               syslog(LOG_NOTICE|LOG_AUTH,
+                      "gethostbyaddr: A record of %s != PTR record [%s]",
+                      hname2, inet_ntoa(*((struct in_addr *)addr)));
+               __set_h_errno (HOST_NOT_FOUND);
+               return (NULL);
+           }
        }
-       if (h_errno == NETDB_SUCCESS)
-               h_errno = HOST_NOT_FOUND;
-       return NULL;
+#endif /*SUNSECURITY*/
+       hp->h_addrtype = af;
+       hp->h_length = len;
+       memmove(host_addr, addr, len);
+       h_addr_ptrs[0] = (char *)host_addr;
+       h_addr_ptrs[1] = NULL;
+       if (af == AF_INET && (_res.options & RES_USE_INET6)) {
+               map_v4v6_address((char*)host_addr, (char*)host_addr);
+               hp->h_addrtype = AF_INET6;
+               hp->h_length = IN6ADDRSZ;
+       }
+       __set_h_errno (NETDB_SUCCESS);
+       return (hp);
 }
 
 void
@@ -735,6 +792,7 @@ _sethtent(f)
                rewind(hostf);
        stayopen = f;
 }
+libresolv_hidden_def (_sethtent)
 
 void
 _endhtent()
@@ -753,12 +811,12 @@ _gethtent()
        int af, len;
 
        if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
-               h_errno = NETDB_INTERNAL;
+               __set_h_errno (NETDB_INTERNAL);
                return (NULL);
        }
  again:
        if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
-               h_errno = HOST_NOT_FOUND;
+               __set_h_errno (HOST_NOT_FOUND);
                return (NULL);
        }
        if (*p == '#')
@@ -769,13 +827,12 @@ _gethtent()
        if (!(cp = strpbrk(p, " \t")))
                goto again;
        *cp++ = '\0';
-       if ((_res.options & RES_USE_INET6) &&
-           inet_pton(AF_INET6, p, host_addr, sizeof host_addr) > 0) {
+       if (inet_pton(AF_INET6, p, host_addr) > 0) {
                af = AF_INET6;
                len = IN6ADDRSZ;
-       } else if (inet_pton(AF_INET, p, host_addr, sizeof host_addr) > 0) {
+       } else if (inet_pton(AF_INET, p, host_addr) > 0) {
                if (_res.options & RES_USE_INET6) {
-                       map_v4v6_address((char*)&host_addr, (char*)&host_addr);
+                       map_v4v6_address((char*)host_addr, (char*)host_addr);
                        af = AF_INET6;
                        len = IN6ADDRSZ;
                } else {
@@ -785,7 +842,7 @@ _gethtent()
        } else {
                goto again;
        }
-       h_addr_ptrs[0] = (char *)&host_addr;
+       h_addr_ptrs[0] = (char *)host_addr;
        h_addr_ptrs[1] = NULL;
        host.h_addr_list = h_addr_ptrs;
        host.h_length = len;
@@ -794,7 +851,7 @@ _gethtent()
                cp++;
        host.h_name = cp;
        q = host.h_aliases = host_aliases;
-       if (cp = strpbrk(cp, " \t"))
+       if ((cp = strpbrk(cp, " \t")))
                *cp++ = '\0';
        while (cp && *cp) {
                if (*cp == ' ' || *cp == '\t') {
@@ -803,63 +860,19 @@ _gethtent()
                }
                if (q < &host_aliases[MAXALIASES - 1])
                        *q++ = cp;
-               if (cp = strpbrk(cp, " \t"))
+               if ((cp = strpbrk(cp, " \t")))
                        *cp++ = '\0';
        }
        *q = NULL;
-       if (_res.options & RES_USE_INET6) {
-               char *bp = hostbuf;
-               int buflen = sizeof hostbuf;
-
-               map_v4v6_hostent(&host, &bp, &buflen);
-       }
-       h_errno = NETDB_SUCCESS;
+       __set_h_errno (NETDB_SUCCESS);
        return (&host);
 }
+libresolv_hidden_def (_gethtent)
 
-struct hstorage {
-       char    name[MAXHOSTNAMELEN + 1];       /* canonical name */
-       char ** alp;                            /* address list pointer */
-       char *  abp;                            /* address buffer pointer */
-       char *  addr_list[MAXADDRS + 1];        /* address list storage */
-       char    addr_buf[MAXADDRBUFSIZE];       /* addresses storage */
-};
-
-static void
-append_addr (struct hstorage * hs, struct hostent *p)
-{
-       if (hs->alp < hs->addr_list + MAXADDRS
-           && hs->abp + p->h_length < hs->addr_buf + MAXADDRBUFSIZE)
-       {
-               hs->alp[0] = hs->abp;
-               hs->alp[1] = 0;
-               memcpy(hs->abp, p->h_addr_list[0], p->h_length);
-               hs->abp += p->h_length;
-               ++hs->alp;
-       }
-}
-
-/*
- * Lookup IP address and aliases for host NAME.  If multiaddress mode
- * is enabled, the entire /etc/hosts file is searched and the union of
- * all addresses found for NAME is returned (this may be slow with
- * large /etc/hosts files, but is convenient for smallish sites that
- * don't want to go through the complexity of running named locally).
- * If multiaddress mode is enabled, the address returned in
- * h_addr_list[0] is one that is on the same net as one of the host's
- * local addresses (if such an address exists).  For compatibility
- * with the BIND version of gethostbyname(), the alias field is empty
- * unless the name being looked up is an alias itself.  In the latter
- * case, the name field contains the canonical name and the alias
- * field the name that is being looked up.  A difference from the BIND
- * version is that this is true even if the alias applies only to one
- * of the interfaces on the target host.o
- */
 struct hostent *
 _gethtbyname(name)
        const char *name;
 {
-       extern struct hostent *_gethtbyname2 __P((const char *, int));
        struct hostent *hp;
 
        if (_res.options & RES_USE_INET6) {
@@ -879,153 +892,37 @@ _gethtbyname2(name, af)
        register char **cp;
 
        _sethtent(0);
-
-       if (_res_hconf.flags & HCONF_FLAG_MULTI) {
-               /*
-                * More statics; not pretty, but it would require
-                * interface changes to make these functions
-                * reentrant.
-                */
-               static char * aliases[2];
-               static char alias[MAXHOSTNAMELEN + 1];
-               static struct hstorage self, target;
-               static struct hostent ht;
-               int found;
-
-               aliases[0] = aliases[1] = 0;
-
-               gethostname(self.name, sizeof(self.name));
-               self.alp = self.addr_list;
-               self.abp = self.addr_buf;
-
-               strncpy(target.name, name, MAXHOSTNAMELEN);
-               target.name[MAXHOSTNAMELEN] = '\0';
-               target.alp = target.addr_list;
-               target.abp = target.addr_buf;
-
-               _sethtent(0);
-               while ((p = _gethtent()) != 0) {
-                       found = 1;
-
-                       if (p->h_addrtype != af)
-                               continue;
-                       if (strcasecmp(p->h_name, name) != 0) {
-                               found = 0;
-                               for (cp = p->h_aliases; *cp; ++cp)
-                                       if (strcasecmp(*cp, name) == 0) {
-                                               found = 1;
-                                               if (!aliases[0]) {
-                                                       strcpy(target.name,
-                                                              p->h_name);
-                                                       strncpy(alias, name,
-                                                               MAXHOSTNAMELEN);
-                                                       alias[MAXHOSTNAMELEN]
-                                                               = '\0';
-                                                       aliases[0] = alias;
-                                               }
-                                               break;
-                                       }
-                       }
-                       if (found) {
-                               /* they better be all the same type and length! */
-                               ht.h_addrtype = p->h_addrtype;
-                               ht.h_length = p->h_length;
-                               append_addr(&target, p);
-                               /*
-                                * If the current hostentry is for the target host, we don't
-                                * check for the local host name.  This nicely optimizes the
-                                * case where NAME is a local name since address ordering
-                                * doesn't matter in that case.
-                                */
-                               continue;
-                       }
-                       found = 1;
-                       if (strcasecmp(p->h_name, self.name) != 0) {
-                               found = 0;
-                               for (cp = p->h_aliases; *cp; ++cp)
-                                       if (strcasecmp(*cp, self.name) == 0) {
-                                               found = 1;
-                                               break;
-                                       }
-                       }
-                       if (found) {
-                               append_addr(&self, p);
-                       }
-               }
-               _endhtent();
-
-               if (target.alp == target.addr_list)
-                       return NULL;            /* found nothing */
-
-               ht.h_aliases   = aliases;
-               ht.h_name      = target.name;
-               ht.h_addr_list = target.addr_list;
-               /*
-                * XXX (davidm) Isn't this subsumed by REORDER???
-                *
-                * Finding the `best' address is necessarily address
-                * specific.  For now, we do IPv4 addresses only.
-                */
-               if (af == AF_INET) {
-                       u_int32_t a1, a2, diff, mindiff = ~0;
-                       int i, j, bestaddr = 0;
-
-                       for (i = 0; self.addr_list[i]; ++i) {
-                               for (j = 0; target.addr_list[j]; ++j) {
-                                       memcpy(&a1, self.addr_list[i], 4);
-                                       memcpy(&a2, target.addr_list[j], 4);
-                                       a1 = ntohl(a1);
-                                       a2 = ntohl(a2);
-                                       diff = a1 ^ a2;
-                                       if (diff < mindiff) {
-                                               bestaddr = j;
-                                               mindiff = diff;
-                                       }
-                               }
-                       }
-                       if (bestaddr > 0) {
-                               char * tmp;
-
-                               tmp = target.addr_list[0];
-                               target.addr_list[0] = target.addr_list[bestaddr];
-                               target.addr_list[bestaddr] = tmp;
-                       }
-               } else if (af == AF_INET6) {
-                       /* XXX To do!!! */
-               }
-               ht.h_addr_list = target.addr_list;
-               return &ht;
-       } else {
-               _sethtent(0);
-               while (p = _gethtent()) {
-                       if (p->h_addrtype != af)
-                               continue;
-                       if (strcasecmp(p->h_name, name) == 0)
-                               break;
-                       for (cp = p->h_aliases; *cp != 0; cp++)
-                               if (strcasecmp(*cp, name) == 0)
-                                       goto found;
-               }
+       while ((p = _gethtent())) {
+               if (p->h_addrtype != af)
+                       continue;
+               if (strcasecmp(p->h_name, name) == 0)
+                       break;
+               for (cp = p->h_aliases; *cp != 0; cp++)
+                       if (strcasecmp(*cp, name) == 0)
+                               goto found;
        }
  found:
        _endhtent();
        return (p);
 }
+libresolv_hidden_def (_gethtbyname2)
 
 struct hostent *
 _gethtbyaddr(addr, len, af)
        const char *addr;
-       int len, af;
+       size_t len;
+       int af;
 {
        register struct hostent *p;
 
        _sethtent(0);
-       while (p = _gethtent())
+       while ((p = _gethtent()))
                if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
                        break;
        _endhtent();
        return (p);
 }
+libresolv_hidden_def (_gethtbyaddr)
 
 static void
 map_v4v6_address(src, dst)
@@ -1037,14 +934,14 @@ map_v4v6_address(src, dst)
        int i;
 
        /* Stash a temporary copy so our caller can update in place. */
-       bcopy(src, tmp, INADDRSZ);
+       memcpy(tmp, src, INADDRSZ);
        /* Mark this ipv6 addr as a mapped ipv4. */
        for (i = 0; i < 10; i++)
                *p++ = 0x00;
        *p++ = 0xff;
        *p++ = 0xff;
        /* Retrieve the saved copy and we're done. */
-       bcopy(tmp, (void*)p, INADDRSZ);
+       memcpy((void*)p, tmp, INADDRSZ);
 }
 
 static void
@@ -1077,7 +974,7 @@ map_v4v6_hostent(hp, bpp, lenp)
 }
 
 #ifdef RESOLVSORT
-static void
+extern void
 addrsort(ap, num)
        char **ap;
        int num;
@@ -1146,7 +1043,8 @@ ht_gethostbyname(name)
 struct hostent *
 ht_gethostbyaddr(addr, len, af)
        const char *addr;
-       int len, af;
+       size_t len;
+       int af;
 {
        return (_gethtbyaddr(addr, len, af));
 }
@@ -1154,47 +1052,7 @@ ht_gethostbyaddr(addr, len, af)
 struct hostent *
 gethostent()
 {
-       struct hostent * hp;
-       int i;
-
-       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
-               h_errno = NETDB_INTERNAL;
-               return (NULL);
-       }
-
-       /*
-        * This doesn't look quite right.  Shouldn't we read one
-        * service until it returns 0, then move on to the next
-        * service?  If so, it requires adding some state and
-        * initializing that state in sethostent().
-        * (davidm@azstarnet.com)
-        */
-       for (i = 0; i < _res_hconf.num_services; ++i) {
-               hp = NULL;
-               switch (_res_hconf.service[i]) {
-                     case SERVICE_HOSTS:
-                       hp = _gethtent ();
-                       break;
-
-#ifdef HAVE_NYS
-                     case SERVICE_NIS:
-                       hp = _getnishost (NULL, "hosts.byname");
-                       break;
-#endif
-
-                     case SERVICE_BIND:
-                     default:
-                       break;
-               }
-               if (hp) {
-                       if ((_res_hconf.flags & HCONF_FLAG_REORDER)
-                           && hp->h_addr_list[0] && hp->h_addr_list[1])
-                               _res_hconf_reorder_addrs (hp);
-                       return hp;
-               }
-       }
-       h_errno = HOST_NOT_FOUND;
-       return NULL;
+       return (_gethtent());
 }
 
 void