Module Name:    src
Committed By:   bouyer
Date:           Wed Dec 18 20:23:36 UTC 2013

Modified Files:
        src/lib/libc/net [netbsd-5]: gethnamaddr.c getnameinfo.3 getnameinfo.c
            sethostent.c
Added Files:
        src/lib/libc/net [netbsd-5]: hostent.h

Log Message:
Apply patch, requested by bad in ticket #1887:
        lib/libc/net/gethnamaddr.c                      1.79-1.82 via patch
        lib/libc/net/getnameinfo.3                      1.37-1.40 via patch
        lib/libc/net/getnameinfo.c                      1.4 via patch
        lib/libc/net/hostent.h                          1.1, 1.2 via patch
        lib/libc/net/sethostent.c                       1.17-1.19 via patch

Make getnameinfo(3) re-entrant (ahem __ypdomain).
Add not advertised reentrant functions: {get,set,end}hostent_r,
gethostbyname{,2}_r, gethostbyaddr_r. Make getnameinfo(3) use
gethostbyaddr_r(3).
Implement no-check-names.


To generate a diff of this commit:
cvs rdiff -u -r1.73 -r1.73.18.1 src/lib/libc/net/gethnamaddr.c
cvs rdiff -u -r1.36 -r1.36.26.1 src/lib/libc/net/getnameinfo.3
cvs rdiff -u -r1.45 -r1.45.24.1 src/lib/libc/net/getnameinfo.c
cvs rdiff -u -r0 -r1.2.2.2 src/lib/libc/net/hostent.h
cvs rdiff -u -r1.16 -r1.16.18.1 src/lib/libc/net/sethostent.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/net/gethnamaddr.c
diff -u src/lib/libc/net/gethnamaddr.c:1.73 src/lib/libc/net/gethnamaddr.c:1.73.18.1
--- src/lib/libc/net/gethnamaddr.c:1.73	Sat Jan 27 22:27:35 2007
+++ src/lib/libc/net/gethnamaddr.c	Wed Dec 18 20:23:35 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: gethnamaddr.c,v 1.73 2007/01/27 22:27:35 christos Exp $	*/
+/*	$NetBSD: gethnamaddr.c,v 1.73.18.1 2013/12/18 20:23:35 bouyer Exp $	*/
 
 /*
  * ++Copyright++ 1985, 1988, 1993
@@ -57,7 +57,7 @@
 static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
 static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp ";
 #else
-__RCSID("$NetBSD: gethnamaddr.c,v 1.73 2007/01/27 22:27:35 christos Exp $");
+__RCSID("$NetBSD: gethnamaddr.c,v 1.73.18.1 2013/12/18 20:23:35 bouyer Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -95,41 +95,38 @@ __RCSID("$NetBSD: gethnamaddr.c,v 1.73 2
 #include <rpcsvc/ypclnt.h>
 #endif
 
+#include "hostent.h"
+
 #if defined(_LIBC) && defined(__weak_alias)
 __weak_alias(gethostbyaddr,_gethostbyaddr)
 __weak_alias(gethostbyname,_gethostbyname)
 __weak_alias(gethostent,_gethostent)
 #endif
 
-#define	MAXALIASES	35
-#define	MAXADDRS	35
+#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
+                               (ok)(nm) != 0)
+#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
+#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
+
 
 static const char AskedForGot[] =
-			  "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+    "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
 
-static char *h_addr_ptrs[MAXADDRS + 1];
 
 #ifdef YP
 static char *__ypdomain;
 #endif
 
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[8*1024];
-static u_int32_t host_addr[16 / sizeof(u_int32_t)];	/* IPv4 or IPv6 */
-static FILE *hostf = NULL;
-static int stayopen = 0;
-
 #define	MAXPACKET	(64*1024)
 
 typedef union {
-    HEADER hdr;
-    u_char buf[MAXPACKET];
+	HEADER hdr;
+	u_char buf[MAXPACKET];
 } querybuf;
 
 typedef union {
-    int32_t al;
-    char ac;
+	int32_t al;
+	char ac;
 } align;
 
 #ifdef DEBUG
@@ -137,33 +134,21 @@ static void dprintf(const char *, res_st
 	__attribute__((__format__(__printf__, 1, 3)));
 #endif
 static struct hostent *getanswer(const querybuf *, int, const char *, int,
-    res_state);
+    res_state, struct hostent *, char *, size_t, int *);
 static void map_v4v6_address(const char *, char *);
 static void map_v4v6_hostent(struct hostent *, char **, char *);
 static void addrsort(char **, int, res_state);
 
-void _sethtent(int);
-void _endhtent(void);
-struct hostent *_gethtent(void);
-void ht_sethostent(int);
-void ht_endhostent(void);
-struct hostent *ht_gethostbyname(char *);
-struct hostent *ht_gethostbyaddr(const char *, int, int);
 void dns_service(void);
 #undef dn_skipname
 int dn_skipname(const u_char *, const u_char *);
-int _gethtbyaddr(void *, void *, va_list);
-int _gethtbyname(void *, void *, va_list);
-struct hostent *_gethtbyname2(const char *, int);
-int _dns_gethtbyaddr(void *, void *, va_list);
-int _dns_gethtbyname(void *, void *, va_list);
+
 #ifdef YP
-struct hostent *_yphostent(char *, int);
-int _yp_gethtbyaddr(void *, void *, va_list);
-int _yp_gethtbyname(void *, void *, va_list);
+static struct hostent *_yp_hostent(char *, int, struct getnamaddr *);
 #endif
 
-static struct hostent *gethostbyname_internal(const char *, int, res_state);
+static struct hostent *gethostbyname_internal(const char *, int, res_state,
+    struct hostent *, char *, size_t, int *);
 
 static const ns_src default_dns_files[] = {
 	{ NSSRC_FILES, 	NS_SUCCESS },
@@ -212,17 +197,20 @@ dprintf(const char *msg, res_state res, 
 
 static struct hostent *
 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
-    res_state res)
+    res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
 {
 	const HEADER *hp;
 	const u_char *cp;
 	int n;
+	size_t qlen;
 	const u_char *eom, *erdata;
 	char *bp, **ap, **hap, *ep;
 	int type, class, ancount, qdcount;
 	int haveanswer, had_error;
 	int toobig = 0;
 	char tbuf[MAXDNAME];
+	char *aliases[MAXALIASES];
+	char *addr_ptrs[MAXADDRS + 1];
 	const char *tname;
 	int (*name_ok)(const char *);
 
@@ -230,7 +218,7 @@ getanswer(const querybuf *answer, int an
 	_DIAGASSERT(qname != NULL);
 
 	tname = qname;
-	host.h_name = NULL;
+	hent->h_name = NULL;
 	eom = answer->buf + anslen;
 	switch (qtype) {
 	case T_A:
@@ -249,46 +237,40 @@ getanswer(const querybuf *answer, int an
 	hp = &answer->hdr;
 	ancount = ntohs(hp->ancount);
 	qdcount = ntohs(hp->qdcount);
-	bp = hostbuf;
-	ep = hostbuf + sizeof hostbuf;
+	bp = buf;
+	ep = buf + buflen;
 	cp = answer->buf;
 	BOUNDED_INCR(HFIXEDSZ);
-	if (qdcount != 1) {
-		h_errno = NO_RECOVERY;
-		return NULL;
-	}
-	n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
-	if ((n < 0) || !(*name_ok)(bp)) {
-		h_errno = NO_RECOVERY;
-		return NULL;
-	}
+	if (qdcount != 1)
+		goto no_recovery;
+
+	n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
+	if ((n < 0) || !maybe_ok(res, bp, name_ok))
+		goto no_recovery;
+
 	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) {
-			h_errno = NO_RECOVERY;
-			return NULL;
-		}
-		host.h_name = bp;
+		n = (int)strlen(bp) + 1;		/* for the \0 */
+		if (n >= MAXHOSTNAMELEN)
+			goto no_recovery;
+		hent->h_name = bp;
 		bp += n;
 		/* The qname can be abbreviated, but h_name is now absolute. */
-		qname = host.h_name;
+		qname = hent->h_name;
 	}
-	ap = host_aliases;
+	hent->h_aliases = ap = aliases;
+	hent->h_addr_list = hap = addr_ptrs;
 	*ap = NULL;
-	host.h_aliases = host_aliases;
-	hap = h_addr_ptrs;
 	*hap = NULL;
-	host.h_addr_list = h_addr_ptrs;
 	haveanswer = 0;
 	had_error = 0;
 	while (ancount-- > 0 && cp < eom && !had_error) {
-		n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
-		if ((n < 0) || !(*name_ok)(bp)) {
+		n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
+		if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
 			had_error++;
 			continue;
 		}
@@ -308,18 +290,17 @@ getanswer(const querybuf *answer, int an
 			continue;		/* XXX - had_error++ ? */
 		}
 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
-			if (ap >= &host_aliases[MAXALIASES-1])
+			if (ap >= &aliases[MAXALIASES-1])
 				continue;
-			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
-			if ((n < 0) || !(*name_ok)(tbuf)) {
+			n = dn_expand(answer->buf, eom, cp, tbuf,
+			    (int)sizeof tbuf);
+			if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
 				had_error++;
 				continue;
 			}
 			cp += n;
-			if (cp != erdata) {
-				h_errno = NO_RECOVERY;
-				return NULL;
-			}
+			if (cp != erdata)
+				goto no_recovery;
 			/* Store alias. */
 			*ap++ = bp;
 			n = strlen(bp) + 1;	/* for the \0 */
@@ -335,21 +316,20 @@ getanswer(const querybuf *answer, int an
 				continue;
 			}
 			strlcpy(bp, tbuf, (size_t)(ep - bp));
-			host.h_name = bp;
+			hent->h_name = bp;
 			bp += n;
 			continue;
 		}
 		if (qtype == T_PTR && type == T_CNAME) {
-			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
-			if (n < 0 || !res_dnok(tbuf)) {
+			n = dn_expand(answer->buf, eom, cp, tbuf,
+			    (int)sizeof tbuf);
+			if (n < 0 || !maybe_dnok(res, tbuf)) {
 				had_error++;
 				continue;
 			}
 			cp += n;
-			if (cp != erdata) {
-				h_errno = NO_RECOVERY;
-				return NULL;
-			}
+			if (cp != erdata)
+				goto no_recovery;
 			/* Get canonical name. */
 			n = strlen(tbuf) + 1;	/* for the \0 */
 			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
@@ -378,20 +358,18 @@ getanswer(const querybuf *answer, int an
 				cp += n;
 				continue;	/* XXX - had_error++ ? */
 			}
-			n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
-			if ((n < 0) || !res_hnok(bp)) {
+			n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
+			if ((n < 0) || !maybe_hnok(res, bp)) {
 				had_error++;
 				break;
 			}
 #if MULTI_PTRS_ARE_ALIASES
 			cp += n;
-			if (cp != erdata) {
-				h_errno = NO_RECOVERY;
-				return NULL;
-			}
+			if (cp != erdata)
+				goto no_recovery;
 			if (!haveanswer)
-				host.h_name = bp;
-			else if (ap < &host_aliases[MAXALIASES-1])
+				hent->h_name = bp;
+			else if (ap < &aliases[MAXALIASES-1])
 				*ap++ = bp;
 			else
 				n = -1;
@@ -405,7 +383,7 @@ getanswer(const querybuf *answer, int an
 			}
 			break;
 #else
-			host.h_name = bp;
+			hent->h_name = bp;
 			if (res->options & RES_USE_INET6) {
 				n = strlen(bp) + 1;	/* for the \0 */
 				if (n >= MAXHOSTNAMELEN) {
@@ -413,26 +391,25 @@ getanswer(const querybuf *answer, int an
 					break;
 				}
 				bp += n;
-				map_v4v6_hostent(&host, &bp, ep);
+				map_v4v6_hostent(hent, &bp, ep);
 			}
-			h_errno = NETDB_SUCCESS;
-			return &host;
+			goto success;
 #endif
 		case T_A:
 		case T_AAAA:
-			if (strcasecmp(host.h_name, bp) != 0) {
+			if (strcasecmp(hent->h_name, bp) != 0) {
 				syslog(LOG_NOTICE|LOG_AUTH,
-				       AskedForGot, host.h_name, bp);
+				       AskedForGot, hent->h_name, bp);
 				cp += n;
 				continue;	/* XXX - had_error++ ? */
 			}
-			if (n != host.h_length) {
+			if (n != hent->h_length) {
 				cp += n;
 				continue;
 			}
 			if (type == T_AAAA) {
 				struct in6_addr in6;
-				memcpy(&in6, cp, IN6ADDRSZ);
+				memcpy(&in6, cp, NS_IN6ADDRSZ);
 				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
 					cp += n;
 					continue;
@@ -441,20 +418,20 @@ getanswer(const querybuf *answer, int an
 			if (!haveanswer) {
 				int nn;
 
-				host.h_name = bp;
-				nn = strlen(bp) + 1;	/* for the \0 */
+				hent->h_name = bp;
+				nn = (int)strlen(bp) + 1;	/* for the \0 */
 				bp += nn;
 			}
 
 			bp += sizeof(align) -
 			    (size_t)((u_long)bp % sizeof(align));
 
-			if (bp + n >= &hostbuf[sizeof hostbuf]) {
+			if (bp + n >= ep) {
 				dprintf("size (%d) too big\n", res, n);
 				had_error++;
 				continue;
 			}
-			if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+			if (hap >= &addr_ptrs[MAXADDRS - 1]) {
 				if (!toobig++) {
 					dprintf("Too many addresses (%d)\n",
 						res, MAXADDRS);
@@ -465,10 +442,8 @@ getanswer(const querybuf *answer, int an
 			(void)memcpy(*hap++ = bp, cp, (size_t)n);
 			bp += n;
 			cp += n;
-			if (cp != erdata) {
-				h_errno = NO_RECOVERY;
-				return NULL;
-			}
+			if (cp != erdata)
+				goto no_recovery;
 			break;
 		default:
 			abort();
@@ -485,70 +460,96 @@ getanswer(const querybuf *answer, int an
 		 * address in that case, not some random one
 		 */
 		if (res->nsort && haveanswer > 1 && qtype == T_A)
-			addrsort(h_addr_ptrs, haveanswer, res);
-		if (!host.h_name) {
-			n = strlen(qname) + 1;	/* for the \0 */
+			addrsort(addr_ptrs, haveanswer, res);
+		if (!hent->h_name) {
+			n = (int)strlen(qname) + 1;	/* for the \0 */
 			if (n > ep - bp || n >= MAXHOSTNAMELEN)
 				goto no_recovery;
 			strlcpy(bp, qname, (size_t)(ep - bp));
-			host.h_name = bp;
+			hent->h_name = bp;
 			bp += n;
 		}
 		if (res->options & RES_USE_INET6)
-			map_v4v6_hostent(&host, &bp, ep);
-		h_errno = NETDB_SUCCESS;
-		return &host;
+			map_v4v6_hostent(hent, &bp, ep);
+	    	goto success;
 	}
- no_recovery:
-	h_errno = NO_RECOVERY;
+no_recovery:
+	*he = NO_RECOVERY;
+	return NULL;
+success:
+	bp = (char *)ALIGN(bp);
+	n = (int)(ap - aliases);
+	qlen = (n + 1) * sizeof(*hent->h_aliases);
+	if ((size_t)(ep - bp) < qlen)
+		goto nospc;
+	hent->h_aliases = (void *)bp;
+	memcpy(bp, aliases, qlen);
+
+	bp += qlen;
+	n = (int)(hap - addr_ptrs);
+	qlen = (n + 1) * sizeof(*hent->h_addr_list);
+	if ((size_t)(ep - bp) < qlen)
+		goto nospc;
+	hent->h_addr_list = (void *)bp;
+	memcpy(bp, addr_ptrs, qlen);
+	*he = NETDB_SUCCESS;
+	return hent;
+nospc:
+	errno = ENOSPC;
+	*he = NETDB_INTERNAL;
 	return NULL;
 }
 
 struct hostent *
-gethostbyname(const char *name)
+gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
+    int *he)
 {
-	struct hostent *hp;
 	res_state res = __res_get_state();
 
-	if (res == NULL)
+	if (res == NULL) {
+		*he = NETDB_INTERNAL;
 		return NULL;
+	}
 
 	_DIAGASSERT(name != NULL);
 
 	if (res->options & RES_USE_INET6) {
-		hp = gethostbyname_internal(name, AF_INET6, res);
+		hp = gethostbyname_internal(name, AF_INET6, res, hp, buf,
+		    buflen, he);
 		if (hp) {
 			__res_put_state(res);
 			return hp;
 		}
 	}
-	hp = gethostbyname_internal(name, AF_INET, res);
+	hp = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, he);
 	__res_put_state(res);
 	return hp;
 }
 
 struct hostent *
-gethostbyname2(const char *name, int af)
+gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
+    size_t buflen, int *he)
 {
-	struct hostent *hp;
 	res_state res = __res_get_state();
 
-	if (res == NULL)
+	if (res == NULL) {
+		*he = NETDB_INTERNAL;
 		return NULL;
-	hp = gethostbyname_internal(name, af, res);
+	}
+	hp = gethostbyname_internal(name, af, res, hp, buf, buflen, he);
 	__res_put_state(res);
 	return hp;
 }
 
 static struct hostent *
-gethostbyname_internal(const char *name, int af, res_state res)
+gethostbyname_internal(const char *name, int af, res_state res,
+    struct hostent *hp, char *buf, size_t buflen, int *he)
 {
 	const char *cp;
-	char *bp, *ep;
-	int size;
-	struct hostent *hp;
+	struct getnamaddr info;
+	size_t size;
 	static const ns_dtab dtab[] = {
-		NS_FILES_CB(_gethtbyname, NULL)
+		NS_FILES_CB(_hf_gethtbyname, NULL)
 		{ NSSRC_DNS, _dns_gethtbyname, NULL },	/* force -DHESIOD */
 		NS_NIS_CB(_yp_gethtbyname, NULL)
 		NS_NULL_CB
@@ -558,19 +559,21 @@ gethostbyname_internal(const char *name,
 
 	switch (af) {
 	case AF_INET:
-		size = INADDRSZ;
+		size = NS_INADDRSZ;
 		break;
 	case AF_INET6:
-		size = IN6ADDRSZ;
+		size = NS_IN6ADDRSZ;
 		break;
 	default:
-		h_errno = NETDB_INTERNAL;
+		*he = NETDB_INTERNAL;
 		errno = EAFNOSUPPORT;
 		return NULL;
 	}
+	if (buflen < size)
+		goto nospc;
 
-	host.h_addrtype = af;
-	host.h_length = size;
+	hp->h_addrtype = af;
+	hp->h_length = (int)size;
 
 	/*
 	 * if there aren't any dots, it could be a user-level alias.
@@ -594,25 +597,7 @@ gethostbyname_internal(const char *name,
 				 * Fake up a hostent as if we'd actually
 				 * done a lookup.
 				 */
-				if (inet_pton(af, name,
-				    (char *)(void *)host_addr) <= 0) {
-					h_errno = HOST_NOT_FOUND;
-					return NULL;
-				}
-				strncpy(hostbuf, name, MAXDNAME);
-				hostbuf[MAXDNAME] = '\0';
-				bp = hostbuf + MAXDNAME;
-				ep = hostbuf + sizeof hostbuf;
-				host.h_name = hostbuf;
-				host.h_aliases = host_aliases;
-				host_aliases[0] = NULL;
-				h_addr_ptrs[0] = (char *)(void *)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, ep);
-				h_errno = NETDB_SUCCESS;
-				return &host;
+				goto fake;
 			}
 			if (!isdigit((u_char) *cp) && *cp != '.') 
 				break;
@@ -628,46 +613,58 @@ gethostbyname_internal(const char *name,
 				 * Fake up a hostent as if we'd actually
 				 * done a lookup.
 				 */
-				if (inet_pton(af, name,
-				    (char *)(void *)host_addr) <= 0) {
-					h_errno = HOST_NOT_FOUND;
-					return NULL;
-				}
-				strncpy(hostbuf, name, MAXDNAME);
-				hostbuf[MAXDNAME] = '\0';
-				bp = hostbuf + MAXDNAME;
-				ep = hostbuf + sizeof hostbuf;
-				host.h_name = hostbuf;
-				host.h_aliases = host_aliases;
-				host_aliases[0] = NULL;
-				h_addr_ptrs[0] = (char *)(void *)host_addr;
-				h_addr_ptrs[1] = NULL;
-				host.h_addr_list = h_addr_ptrs;
-				h_errno = NETDB_SUCCESS;
-				return &host;
+				goto fake;
 			}
 			if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
 				break;
 		}
 
-	hp = NULL;
-	h_errno = NETDB_INTERNAL;
-	if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname",
+	*he = NETDB_INTERNAL;
+	info.hp = hp;
+	info.buf = buf;
+	info.buflen = buflen;
+	info.he = he;
+	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
 	    default_dns_files, name, strlen(name), af) != NS_SUCCESS)
 		return NULL;
-	h_errno = NETDB_SUCCESS;
+	*he = NETDB_SUCCESS;
+	return hp;
+nospc:
+	*he = NETDB_INTERNAL;
+	errno = ENOSPC;
+	return NULL;
+fake:
+	HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
+	HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
+
+	hp->h_aliases[0] = NULL;
+	if (size > buflen)
+		goto nospc;
+
+	if (inet_pton(af, name, buf) <= 0) {
+		*he = HOST_NOT_FOUND;
+		return NULL;
+	}
+	hp->h_addr_list[0] = buf;
+	hp->h_addr_list[1] = NULL;
+	buf += size;
+	buflen -= size;
+	HENT_SCOPY(hp->h_name, name, buf, buflen);
+	if (res->options & RES_USE_INET6)
+		map_v4v6_hostent(hp, &buf, buf + buflen);
+	*he = NETDB_SUCCESS;
 	return hp;
 }
 
 struct hostent *
-gethostbyaddr(const char *addr,	/* XXX should have been def'd as u_char! */
-    socklen_t len, int af)
+gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
+    char *buf, size_t buflen, int *he)
 {
 	const u_char *uaddr = (const u_char *)addr;
 	socklen_t size;
-	struct hostent *hp;
+	struct getnamaddr info;
 	static const ns_dtab dtab[] = {
-		NS_FILES_CB(_gethtbyaddr, NULL)
+		NS_FILES_CB(_hf_gethtbyaddr, NULL)
 		{ NSSRC_DNS, _dns_gethtbyaddr, NULL },	/* force -DHESIOD */
 		NS_NIS_CB(_yp_gethtbyaddr, NULL)
 		NS_NULL_CB
@@ -675,317 +672,163 @@ gethostbyaddr(const char *addr,	/* XXX s
 	
 	_DIAGASSERT(addr != NULL);
 
-	if (af == AF_INET6 && len == IN6ADDRSZ &&
-	    (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) ||
-	     IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) {
-		h_errno = HOST_NOT_FOUND;
+	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
+	    (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
+	     IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
+		*he = HOST_NOT_FOUND;
 		return NULL;
 	}
-	if (af == AF_INET6 && len == IN6ADDRSZ &&
-	    (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) ||
-	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) {
+	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
+	    (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
+	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
 		/* Unmap. */
-		addr += IN6ADDRSZ - INADDRSZ;
-		uaddr += IN6ADDRSZ - INADDRSZ;
+		uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
+		addr = uaddr;
 		af = AF_INET;
-		len = INADDRSZ;
+		len = NS_INADDRSZ;
 	}
 	switch (af) {
 	case AF_INET:
-		size = INADDRSZ;
+		size = NS_INADDRSZ;
 		break;
 	case AF_INET6:
-		size = IN6ADDRSZ;
+		size = NS_IN6ADDRSZ;
 		break;
 	default:
 		errno = EAFNOSUPPORT;
-		h_errno = NETDB_INTERNAL;
+		*he = NETDB_INTERNAL;
 		return NULL;
 	}
 	if (size != len) {
 		errno = EINVAL;
-		h_errno = NETDB_INTERNAL;
+		*he = NETDB_INTERNAL;
 		return NULL;
 	}
-	hp = NULL;
-	h_errno = NETDB_INTERNAL;
-	if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
+	info.hp = hp;
+	info.buf = buf;
+	info.buflen = buflen;
+	info.he = he;
+	*he = NETDB_INTERNAL;
+	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
 	    default_dns_files, uaddr, len, af) != NS_SUCCESS)
 		return NULL;
-	h_errno = NETDB_SUCCESS;
+	*he = NETDB_SUCCESS;
 	return hp;
 }
 
-void
-_sethtent(int f)
-{
-	if (!hostf)
-		hostf = fopen(_PATH_HOSTS, "r" );
-	else
-		rewind(hostf);
-	stayopen = f;
-}
-
-void
-_endhtent(void)
-{
-	if (hostf && !stayopen) {
-		(void) fclose(hostf);
-		hostf = NULL;
-	}
-}
-
 struct hostent *
-_gethtent(void)
+gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
 {
-	char *p;
+	char *p, *name;
 	char *cp, **q;
 	int af, len;
+	size_t llen, anum, i;
+	char *aliases[MAXALIASES];
+	struct in6_addr host_addr;
 
-	if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
-		h_errno = NETDB_INTERNAL;
+	if (hf == NULL) {
+		*he = NETDB_INTERNAL;
+		errno = EINVAL;
 		return NULL;
 	}
  again:
-	if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
-		h_errno = HOST_NOT_FOUND;
+	if ((p = fgetln(hf, &llen)) == NULL) {
+		*he = HOST_NOT_FOUND;
 		return NULL;
 	}
+	if (llen < 1)
+		goto again;
 	if (*p == '#')
 		goto again;
+	p[llen] = '\0';
 	if (!(cp = strpbrk(p, "#\n")))
 		goto again;
 	*cp = '\0';
 	if (!(cp = strpbrk(p, " \t")))
 		goto again;
 	*cp++ = '\0';
-	if (inet_pton(AF_INET6, p, (char *)(void *)host_addr) > 0) {
+	if (inet_pton(AF_INET6, p, &host_addr) > 0) {
 		af = AF_INET6;
-		len = IN6ADDRSZ;
-	} else if (inet_pton(AF_INET, p, (char *)(void *)host_addr) > 0) {
+		len = NS_IN6ADDRSZ;
+	} else if (inet_pton(AF_INET, p, &host_addr) > 0) {
 		res_state res = __res_get_state();
 		if (res == NULL)
 			return NULL;
 		if (res->options & RES_USE_INET6) {
-			map_v4v6_address((char *)(void *)host_addr,
-			    (char *)(void *)host_addr);
+			map_v4v6_address(buf, buf);
 			af = AF_INET6;
-			len = IN6ADDRSZ;
+			len = NS_IN6ADDRSZ;
 		} else {
 			af = AF_INET;
-			len = INADDRSZ;
+			len = NS_INADDRSZ;
 		}
 		__res_put_state(res);
 	} else {
 		goto again;
 	}
 	/* if this is not something we're looking for, skip it. */
-	if (host.h_addrtype != 0 && host.h_addrtype != af)
+	if (hent->h_addrtype != 0 && hent->h_addrtype != af)
 		goto again;
-	if (host.h_length != 0 && host.h_length != len)
+	if (hent->h_length != 0 && hent->h_length != len)
 		goto again;
-	h_addr_ptrs[0] = (char *)(void *)host_addr;
-	h_addr_ptrs[1] = NULL;
-	host.h_addr_list = h_addr_ptrs;
-	host.h_length = len;
-	host.h_addrtype = af;
+
 	while (*cp == ' ' || *cp == '\t')
 		cp++;
-	host.h_name = cp;
-	q = host.h_aliases = host_aliases;
-	if ((cp = strpbrk(cp, " \t")) != NULL)
+	if ((cp = strpbrk(name = cp, " \t")) != NULL)
 		*cp++ = '\0';
+	q = aliases;
 	while (cp && *cp) {
 		if (*cp == ' ' || *cp == '\t') {
 			cp++;
 			continue;
 		}
-		if (q < &host_aliases[MAXALIASES - 1])
-			*q++ = cp;
+		if (q >= &aliases[__arraycount(aliases)])
+			goto nospc;
+		*q++ = cp;
 		if ((cp = strpbrk(cp, " \t")) != NULL)
 			*cp++ = '\0';
 	}
-	*q = NULL;
-	h_errno = NETDB_SUCCESS;
-	return &host;
-}
-
-/*ARGSUSED*/
-int
-_gethtbyname(void *rv, void *cb_data, va_list ap)
-{
-	struct hostent *hp;
-	const char *name;
-	int af;
-
-	_DIAGASSERT(rv != NULL);
-
-	name = va_arg(ap, char *);
-	/* NOSTRICT skip len */(void)va_arg(ap, int);
-	af = va_arg(ap, int);
-
-	hp = NULL;
-#if 0
-	{
-		res_state res = __res_get_state();
-		if (res == NULL)
-			return NS_NOTFOUND;
-		if (res->options & RES_USE_INET6)
-			hp = _gethtbyname2(name, AF_INET6);
-		if (hp==NULL)
-			hp = _gethtbyname2(name, AF_INET);
-		__res_put_state(res);
-	}
-#else
-	hp = _gethtbyname2(name, af);
-#endif
-	*((struct hostent **)rv) = hp;
-	if (hp == NULL) {
-		h_errno = HOST_NOT_FOUND;
-		return NS_NOTFOUND;
-	}
-	return NS_SUCCESS;
-}
-
-struct hostent *
-_gethtbyname2(const char *name, int af)
-{
-	struct hostent *p;
-	char *tmpbuf, *ptr, **cp;
-	int num;
-	size_t len;
-
-	_DIAGASSERT(name != NULL);
-
-	_sethtent(stayopen);
-	ptr = tmpbuf = NULL;
-	num = 0;
-	while ((p = _gethtent()) != NULL && num < MAXADDRS) {
-		if (p->h_addrtype != af)
-			continue;
-		if (strcasecmp(p->h_name, name) != 0) {
-			for (cp = p->h_aliases; *cp != NULL; cp++)
-				if (strcasecmp(*cp, name) == 0)
-					break;
-			if (*cp == NULL) continue;
-		}
-
-		if (num == 0) {
-			size_t bufsize;
-			char *src;
-
-			bufsize = strlen(p->h_name) + 2 +
-				  MAXADDRS * p->h_length +
-				  ALIGNBYTES;
-			for (cp = p->h_aliases; *cp != NULL; cp++)
-				bufsize += strlen(*cp) + 1;
-
-			if ((tmpbuf = malloc(bufsize)) == NULL) {
-				h_errno = NETDB_INTERNAL;
-				return NULL;
-			}
-
-			ptr = tmpbuf;
-			src = p->h_name;
-			while ((*ptr++ = *src++) != '\0');
-			for (cp = p->h_aliases; *cp != NULL; cp++) {
-				src = *cp;
-				while ((*ptr++ = *src++) != '\0');
-			}
-			*ptr++ = '\0';
-
-			ptr = (char *)(void *)ALIGN(ptr);
-		}
-
-		(void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length);
-		ptr += p->h_length;
-		num++;
-	}
-	_endhtent();
-	if (num == 0) return NULL;
-
-	len = ptr - tmpbuf;
-	if (len > (sizeof(hostbuf) - ALIGNBYTES)) {
-		free(tmpbuf);
-		errno = ENOSPC;
-		h_errno = NETDB_INTERNAL;
-		return NULL;
-	}
-	ptr = memcpy((void *)ALIGN(hostbuf), tmpbuf, len);
-	free(tmpbuf);
-
-	host.h_name = ptr;
-	while (*ptr++);
-
-	cp = host_aliases;
-	while (*ptr) {
-		*cp++ = ptr;
-		while (*ptr++);
-	}
-	ptr++;
-	*cp = NULL;
-
-	ptr = (char *)(void *)ALIGN(ptr);
-	cp = h_addr_ptrs;
-	while (num--) {
-		*cp++ = ptr;
-		ptr += host.h_length;
-	}
-	*cp = NULL;
-
-	return &host;
-}
-
-/*ARGSUSED*/
-int
-_gethtbyaddr(void *rv, void *cb_data, va_list ap)
-{
-	struct hostent *p;
-	const unsigned char *addr;
-	int len, af;
-
-	_DIAGASSERT(rv != NULL);
-
-	addr = va_arg(ap, unsigned char *);
-	len = va_arg(ap, int);
-	af = va_arg(ap, int);
-	
-	host.h_length = len;
-	host.h_addrtype = af;
-
-	_sethtent(stayopen);
-	while ((p = _gethtent()) != NULL)
-		if (p->h_addrtype == af && !memcmp(p->h_addr, addr,
-		    (size_t)len))
-			break;
-	_endhtent();
-	*((struct hostent **)rv) = p;
-	if (p==NULL) {
-		h_errno = HOST_NOT_FOUND;
-		return NS_NOTFOUND;
-	}
-	return NS_SUCCESS;
+	hent->h_length = len;
+	hent->h_addrtype = af;
+	HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
+	anum = (size_t)(q - aliases);
+	HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
+	HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
+	    buflen);
+	hent->h_addr_list[1] = NULL;
+
+	HENT_SCOPY(hent->h_name, name, buf, buflen);
+	for (i = 0; i < anum; i++)
+		HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
+	hent->h_aliases[anum] = NULL;
+
+	*he = NETDB_SUCCESS;
+	return hent;
+nospc:
+	errno = ENOSPC;
+	*he = NETDB_INTERNAL;
+	return NULL;
 }
 
 static void
 map_v4v6_address(const char *src, char *dst)
 {
 	u_char *p = (u_char *)dst;
-	char tmp[INADDRSZ];
+	char tmp[NS_INADDRSZ];
 	int i;
 
 	_DIAGASSERT(src != NULL);
 	_DIAGASSERT(dst != NULL);
 
 	/* Stash a temporary copy so our caller can update in place. */
-	(void)memcpy(tmp, src, INADDRSZ);
+	(void)memcpy(tmp, src, NS_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. */
-	(void)memcpy((void *)p, tmp, INADDRSZ);
+	(void)memcpy(p, tmp, NS_INADDRSZ);
 }
 
 static void
@@ -997,14 +840,14 @@ map_v4v6_hostent(struct hostent *hp, cha
 	_DIAGASSERT(bpp != NULL);
 	_DIAGASSERT(ep != NULL);
 
-	if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+	if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
 		return;
 	hp->h_addrtype = AF_INET6;
-	hp->h_length = IN6ADDRSZ;
+	hp->h_length = NS_IN6ADDRSZ;
 	for (ap = hp->h_addr_list; *ap; ap++) {
 		int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align));
 
-		if (ep - *bpp < (i + IN6ADDRSZ)) {
+		if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
 			/* Out of memory.  Truncate address list here.  XXX */
 			*ap = NULL;
 			return;
@@ -1012,7 +855,7 @@ map_v4v6_hostent(struct hostent *hp, cha
 		*bpp += i;
 		map_v4v6_address(*ap, *bpp);
 		*ap = *bpp;
-		*bpp += IN6ADDRSZ;
+		*bpp += NS_IN6ADDRSZ;
 	}
 }
 
@@ -1059,13 +902,6 @@ addrsort(char **ap, int num, res_state r
 	}
 }
 
-struct hostent *
-gethostent(void)
-{
-	host.h_addrtype = 0;
-	host.h_length = 0;
-	return _gethtent();
-}
 
 /*ARGSUSED*/
 int
@@ -1075,20 +911,22 @@ _dns_gethtbyname(void *rv, void *cb_data
 	int n, type;
 	struct hostent *hp;
 	const char *name;
-	int af;
 	res_state res;
+	struct getnamaddr *info = rv;
 
 	_DIAGASSERT(rv != NULL);
 
 	name = va_arg(ap, char *);
-	/* NOSTRICT skip len */(void)va_arg(ap, int);
-	af = va_arg(ap, int);
+	/* NOSTRICT skip string len */(void)va_arg(ap, int);
+	info->hp->h_addrtype = va_arg(ap, int);
 
-	switch (af) {
+	switch (info->hp->h_addrtype) {
 	case AF_INET:
+		info->hp->h_length = NS_INADDRSZ;
 		type = T_A;
 		break;
 	case AF_INET6:
+		info->hp->h_length = NS_IN6ADDRSZ;
 		type = T_AAAA;
 		break;
 	default:
@@ -1096,7 +934,7 @@ _dns_gethtbyname(void *rv, void *cb_data
 	}
 	buf = malloc(sizeof(*buf));
 	if (buf == NULL) {
-		h_errno = NETDB_INTERNAL;
+		*info->he = NETDB_INTERNAL;
 		return NS_NOTFOUND;
 	}
 	res = __res_get_state();
@@ -1111,7 +949,8 @@ _dns_gethtbyname(void *rv, void *cb_data
 		__res_put_state(res);
 		return NS_NOTFOUND;
 	}
-	hp = getanswer(buf, n, name, type, res);
+	hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
+	    info->buflen, info->he);
 	free(buf);
 	__res_put_state(res);
 	if (hp == NULL)
@@ -1123,7 +962,6 @@ _dns_gethtbyname(void *rv, void *cb_data
 		default:
 			return NS_UNAVAIL;
 		}
-	*((struct hostent **)rv) = hp;
 	return NS_SUCCESS;
 }
 
@@ -1136,16 +974,19 @@ _dns_gethtbyaddr(void *rv, void	*cb_data
 	querybuf *buf;
 	struct hostent *hp;
 	const unsigned char *uaddr;
-	int len, af, advance;
+	int advance;
 	res_state res;
+	char *bf;
+	size_t blen;
+	struct getnamaddr *info = rv;
 
 	_DIAGASSERT(rv != NULL);
 
 	uaddr = va_arg(ap, unsigned char *);
-	len = va_arg(ap, int);
-	af = va_arg(ap, int);
+	info->hp->h_length = va_arg(ap, int);
+	info->hp->h_addrtype = va_arg(ap, int);
 
-	switch (af) {
+	switch (info->hp->h_addrtype) {
 	case AF_INET:
 		(void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
 		    (uaddr[3] & 0xff), (uaddr[2] & 0xff),
@@ -1155,29 +996,29 @@ _dns_gethtbyaddr(void *rv, void	*cb_data
 	case AF_INET6:
 		qp = qbuf;
 		ep = qbuf + sizeof(qbuf) - 1;
-		for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+		for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
 			advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
 			    uaddr[n] & 0xf,
 			    ((unsigned int)uaddr[n] >> 4) & 0xf);
 			if (advance > 0 && qp + advance < ep)
 				qp += advance;
 			else {
-				h_errno = NETDB_INTERNAL;
+				*info->he = NETDB_INTERNAL;
 				return NS_NOTFOUND;
 			}
 		}
 		if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
-			h_errno = NETDB_INTERNAL;
+			*info->he = NETDB_INTERNAL;
 			return NS_NOTFOUND;
 		}
 		break;
 	default:
-		abort();
+		return NS_UNAVAIL;
 	}
 
 	buf = malloc(sizeof(*buf));
 	if (buf == NULL) {
-		h_errno = NETDB_INTERNAL;
+		*info->he = NETDB_INTERNAL;
 		return NS_NOTFOUND;
 	}
 	res = __res_get_state();
@@ -1192,11 +1033,12 @@ _dns_gethtbyaddr(void *rv, void	*cb_data
 		__res_put_state(res);
 		return NS_NOTFOUND;
 	}
-	hp = getanswer(buf, n, qbuf, T_PTR, res);
+	hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
+	    info->buflen, info->he);
 	free(buf);
 	if (hp == NULL) {
 		__res_put_state(res);
-		switch (h_errno) {
+		switch (*info->he) {
 		case HOST_NOT_FOUND:
 			return NS_NOTFOUND;
 		case TRY_AGAIN:
@@ -1205,62 +1047,65 @@ _dns_gethtbyaddr(void *rv, void	*cb_data
 			return NS_UNAVAIL;
 		}
 	}
-	hp->h_addrtype = af;
-	hp->h_length = len;
-	(void)memcpy(host_addr, uaddr, (size_t)len);
-	h_addr_ptrs[0] = (char *)(void *)host_addr;
-	h_addr_ptrs[1] = NULL;
-	if (af == AF_INET && (res->options & RES_USE_INET6)) {
-		map_v4v6_address((char *)(void *)host_addr,
-		    (char *)(void *)host_addr);
+
+	bf = (void *)(hp->h_addr_list + 2);
+	blen = (size_t)(bf - info->buf);
+	if (blen + info->hp->h_length > info->buflen)
+		goto nospc;
+	hp->h_addr_list[0] = bf;
+	hp->h_addr_list[1] = NULL;
+	(void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
+	if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
+		if (blen + NS_IN6ADDRSZ > info->buflen)
+			goto nospc;
+		map_v4v6_address(bf, bf);
 		hp->h_addrtype = AF_INET6;
-		hp->h_length = IN6ADDRSZ;
+		hp->h_length = NS_IN6ADDRSZ;
 	}
 
 	__res_put_state(res);
-	*((struct hostent **)rv) = hp;
-	h_errno = NETDB_SUCCESS;
+	*info->he = NETDB_SUCCESS;
 	return NS_SUCCESS;
+nospc:
+	*info->he = NETDB_INTERNAL;
+	return NS_UNAVAIL;
 }
 
 #ifdef YP
 /*ARGSUSED*/
-struct hostent *
-_yphostent(char *line, int af)
+static struct hostent *
+_yp_hostent(char *line, int af, struct getnamaddr *info)
 {
-	static struct in_addr host_addrs[MAXADDRS];
-	static struct in6_addr host6_addrs[MAXADDRS];
+	struct in6_addr host_addrs[MAXADDRS];
+	char *aliases[MAXALIASES];
 	char *p = line;
-	char *cp, **q;
-	char **hap;
+	char *cp, **q, *ptr;
+	size_t len, anum, i;
 	int addrok;
 	int more;
 	size_t naddrs;
+	struct hostent *hp = info->hp;
 
 	_DIAGASSERT(line != NULL);
 
-	host.h_name = NULL;
-	host.h_addr_list = h_addr_ptrs;
-	host.h_addrtype = af;
+	hp->h_name = NULL;
+	hp->h_addrtype = af;
 	switch (af) {
 	case AF_INET:
-		host.h_length = INADDRSZ;
+		hp->h_length = NS_INADDRSZ;
 		break;
 	case AF_INET6:
-		host.h_length = IN6ADDRSZ;
+		hp->h_length = NS_IN6ADDRSZ;
 		break;
 	default:
 		return NULL;
 	}
-	hap = h_addr_ptrs;
-	q = host.h_aliases = host_aliases;
 	naddrs = 0;
+	q = aliases;
 
 nextline:
 	/* check for host_addrs overflow */
-	if (naddrs >= sizeof(host_addrs) / sizeof(host_addrs[0]))
-		goto done;
-	if (naddrs >= sizeof(host6_addrs) / sizeof(host6_addrs[0]))
+	if (naddrs >= __arraycount(host_addrs))
 		goto done;
 
 	more = 0;
@@ -1270,15 +1115,7 @@ nextline:
 	*cp++ = '\0';
 
 	/* p has should have an address */
-	addrok = 0;
-	switch (af) {
-	case AF_INET:
-		addrok = inet_aton(p, &host_addrs[naddrs]);
-		break;
-	case AF_INET6:
-		addrok = inet_pton(af, p, &host6_addrs[naddrs]);
-		break;
-	}
+	addrok = inet_pton(af, p, &host_addrs[naddrs]);
 	if (addrok != 1) {
 		/* skip to the next line */
 		while (cp && *cp) {
@@ -1288,19 +1125,9 @@ nextline:
 			}
 			cp++;
 		}
-
 		goto done;
 	}
 
-	switch (af) {
-	case AF_INET:
-		*hap++ = (char *)(void *)&host_addrs[naddrs++];
-		break;
-	case AF_INET6:
-		*hap++ = (char *)(void *)&host6_addrs[naddrs++];
-		break;
-	}
-
 	while (*cp == ' ' || *cp == '\t')
 		cp++;
 	p = cp;
@@ -1310,11 +1137,11 @@ nextline:
 			more = 1;
 		*cp++ = '\0';
 	}
-	if (!host.h_name)
-		host.h_name = p;
-	else if (strcmp(host.h_name, p)==0)
+	if (!hp->h_name)
+		hp->h_name = p;
+	else if (strcmp(hp->h_name, p) == 0)
 		;
-	else if (q < &host_aliases[MAXALIASES - 1])
+	else if (q < &aliases[MAXALIASES - 1])
 		*q++ = p;
 	p = cp;
 	if (more)
@@ -1329,7 +1156,7 @@ nextline:
 			cp++;
 			goto nextline;
 		}
-		if (q < &host_aliases[MAXALIASES - 1])
+		if (q < &aliases[MAXALIASES - 1])
 			*q++ = cp;
 		cp = strpbrk(cp, " \t");
 		if (cp != NULL)
@@ -1337,11 +1164,32 @@ nextline:
 	}
 
 done:
-	if (host.h_name == NULL)
+	if (hp->h_name == NULL)
 		return NULL;
-	*q = NULL;
-	*hap = NULL;
-	return &host;
+
+	ptr = info->buf;
+	len = info->buflen;
+
+	anum = (size_t)(q - aliases);
+	HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
+	HENT_ARRAY(hp->h_aliases, anum, ptr, len);
+
+	for (i = 0; i < naddrs; i++)
+		HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
+		    ptr, len);
+	hp->h_addr_list[naddrs] = NULL;
+
+	HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
+
+	for (i = 0; i < anum; i++)
+		HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
+	hp->h_aliases[anum] = NULL;
+
+	return hp;
+nospc:
+	*info->he = NETDB_INTERNAL;
+	errno = ENOSPC;
+	return NULL;
 }
 
 /*ARGSUSED*/
@@ -1349,12 +1197,13 @@ int
 _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
 {
 	struct hostent *hp = NULL;
-	static char *__ypcurrent;
-	int __ypcurrentlen, r;
+	char *ypcurrent;
+	int ypcurrentlen, r;
 	char name[INET6_ADDRSTRLEN];	/* XXX enough? */
 	const unsigned char *uaddr;
 	int af;
 	const char *map;
+	struct getnamaddr *info = rv;
 
 	_DIAGASSERT(rv != NULL);
 
@@ -1372,9 +1221,6 @@ _yp_gethtbyaddr(void *rv, void *cb_data,
 	 */
 	if (inet_ntop(af, uaddr, name, sizeof(name)) == NULL)
 		return NS_UNAVAIL;
-	if (__ypcurrent)
-		free(__ypcurrent);
-	__ypcurrent = NULL;
 	switch (af) {
 	case AF_INET:
 		map = "hosts.byaddr";
@@ -1383,15 +1229,18 @@ _yp_gethtbyaddr(void *rv, void *cb_data,
 		map = "ipnodes.byaddr";
 		break;
 	}
+	ypcurrent = NULL;
 	r = yp_match(__ypdomain, map, name,
-		(int)strlen(name), &__ypcurrent, &__ypcurrentlen);
+		(int)strlen(name), &ypcurrent, &ypcurrentlen);
 	if (r == 0)
-		hp = _yphostent(__ypcurrent, af);
+		hp = _yp_hostent(ypcurrent, af, info);
+	else
+		hp = NULL;
+	free(ypcurrent);
 	if (hp == NULL) {
-		h_errno = HOST_NOT_FOUND;
+		*info->he = HOST_NOT_FOUND;
 		return NS_NOTFOUND;
 	}
-	*((struct hostent **)rv) = hp;
 	return NS_SUCCESS;
 }
 
@@ -1399,26 +1248,24 @@ _yp_gethtbyaddr(void *rv, void *cb_data,
 int
 _yp_gethtbyname(void *rv, void *cb_data, va_list ap)
 {
-	struct hostent *hp = NULL;
-	static char *__ypcurrent;
-	int __ypcurrentlen, r;
+	struct hostent *hp;
+	char *ypcurrent;
+	int ypcurrentlen, r;
 	const char *name;
 	int af;
 	const char *map;
+	struct getnamaddr *info = rv;
 
 	_DIAGASSERT(rv != NULL);
 
 	name = va_arg(ap, char *);
-	/* NOSTRICT skip len */(void)va_arg(ap, int);
+	/* NOSTRICT skip string len */(void)va_arg(ap, int);
 	af = va_arg(ap, int);
 
 	if (!__ypdomain) {
 		if (_yp_check(&__ypdomain) == 0)
 			return NS_UNAVAIL;
 	}
-	if (__ypcurrent)
-		free(__ypcurrent);
-	__ypcurrent = NULL;
 	switch (af) {
 	case AF_INET:
 		map = "hosts.byname";
@@ -1427,15 +1274,57 @@ _yp_gethtbyname(void *rv, void *cb_data,
 		map = "ipnodes.byname";
 		break;
 	}
+	ypcurrent = NULL;
 	r = yp_match(__ypdomain, map, name,
-		(int)strlen(name), &__ypcurrent, &__ypcurrentlen);
+		(int)strlen(name), &ypcurrent, &ypcurrentlen);
 	if (r == 0)
-		hp = _yphostent(__ypcurrent, af);
+		hp = _yp_hostent(ypcurrent, af, info);
+	else
+		hp = NULL;
+	free(ypcurrent);
 	if (hp == NULL) {
-		h_errno = HOST_NOT_FOUND;
+		*info->he = HOST_NOT_FOUND;
 		return NS_NOTFOUND;
 	}
-	*((struct hostent **)rv) = hp;
 	return NS_SUCCESS;
 }
 #endif
+
+/*
+ * Non-reentrant versions.
+ */
+FILE *_h_file;
+static struct hostent h_ent;
+static char h_buf[16384];
+
+struct hostent *
+gethostbyaddr(const char *addr, size_t len, int af) {
+	return gethostbyaddr_r(addr, len, af, &h_ent, h_buf, sizeof(h_buf),
+	    &h_errno);
+}
+
+struct hostent *
+gethostbyname(const char *name) {
+	return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno);
+}
+
+struct hostent *
+gethostbyname2(const char *name, int af) {
+	return gethostbyname2_r(name, af, &h_ent, h_buf, sizeof(h_buf),
+	    &h_errno);
+}
+
+struct hostent *
+gethostent(void)
+{
+	if (_h_file == NULL) {
+		sethostent_r(&_h_file);
+		if (_h_file == NULL) {
+			h_errno = NETDB_INTERNAL;
+			return NULL;
+		}
+	}
+	memset(&h_ent, 0, sizeof(h_ent));
+	return gethostent_r(_h_file, &h_ent, h_buf, sizeof(h_buf), &h_errno);
+}
+

Index: src/lib/libc/net/getnameinfo.3
diff -u src/lib/libc/net/getnameinfo.3:1.36 src/lib/libc/net/getnameinfo.3:1.36.26.1
--- src/lib/libc/net/getnameinfo.3:1.36	Mon Mar 21 13:35:04 2005
+++ src/lib/libc/net/getnameinfo.3	Wed Dec 18 20:23:36 2013
@@ -1,4 +1,4 @@
-.\"	$NetBSD: getnameinfo.3,v 1.36 2005/03/21 13:35:04 kleink Exp $
+.\"	$NetBSD: getnameinfo.3,v 1.36.26.1 2013/12/18 20:23:36 bouyer Exp $
 .\"	$KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $
 .\"	$OpenBSD: getnameinfo.3,v 1.36 2004/12/21 09:48:20 jmc Exp $
 .\"
@@ -17,7 +17,7 @@
 .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 .\" PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd March 21, 2005
+.Dd August 18, 2013
 .Dt GETNAMEINFO 3
 .Os
 .Sh NAME
@@ -27,8 +27,8 @@
 .In netdb.h
 .Ft int
 .Fn getnameinfo "const struct sockaddr * restrict sa" "socklen_t salen" \
-    "char * restrict host" "size_t hostlen" "char * restrict serv" \
-    "size_t servlen" "int flags"
+    "char * restrict host" "socklen_t hostlen" "char * restrict serv" \
+    "socklen_t servlen" "int flags"
 .Sh DESCRIPTION
 The
 .Fn getnameinfo
@@ -47,11 +47,19 @@ The
 .Li sockaddr
 structure
 .Fa sa
-should point to either a
+should point to a
 .Li sockaddr_in
-or
+(for IPv4),
 .Li sockaddr_in6
-structure (for IPv4 or IPv6 respectively) that is
+(for IPv6),
+.Li sockaddr_atalk
+(for AppleTalk),
+.Li sockaddr_link
+(for link layer),
+or
+.Li sockaddr_local
+(for local/unix)
+structures that are
 .Fa salen
 bytes long.
 .Pp
@@ -74,7 +82,7 @@ and the maximum value for
 is
 .Dv NI_MAXSERV ,
 as defined by
-.Aq Pa netdb.h .
+.In netdb.h .
 If a length parameter is zero, no string will be stored.
 Otherwise, enough space must be provided to store the
 host name or service string plus a byte for the NUL terminator.
@@ -255,10 +263,6 @@ if (error == 0) {
 	    NULL, 0, NI_NUMERICHOST);
 }
 .Ed
-.Sh BUGS
-The implementation of
-.Fn getnameinfo
-is not thread-safe.
 .\".Pp
 .\".Ox
 .\"intentionally uses a different

Index: src/lib/libc/net/getnameinfo.c
diff -u src/lib/libc/net/getnameinfo.c:1.45 src/lib/libc/net/getnameinfo.c:1.45.24.1
--- src/lib/libc/net/getnameinfo.c:1.45	Sun Oct 15 16:14:46 2006
+++ src/lib/libc/net/getnameinfo.c	Wed Dec 18 20:23:36 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: getnameinfo.c,v 1.45 2006/10/15 16:14:46 christos Exp $	*/
+/*	$NetBSD: getnameinfo.c,v 1.45.24.1 2013/12/18 20:23:36 bouyer Exp $	*/
 /*	$KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $	*/
 
 /*
@@ -47,7 +47,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: getnameinfo.c,v 1.45 2006/10/15 16:14:46 christos Exp $");
+__RCSID("$NetBSD: getnameinfo.c,v 1.45.24.1 2013/12/18 20:23:36 bouyer Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
@@ -68,6 +68,7 @@ __RCSID("$NetBSD: getnameinfo.c,v 1.45 2
 #include <string.h>
 
 #include "servent.h"
+#include "hostent.h"
 
 #ifdef __weak_alias
 __weak_alias(getnameinfo,_getnameinfo)
@@ -290,7 +291,11 @@ getnameinfo_inet(sa, salen, host, hostle
 			break;
 		}
 	} else {
-		hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+		struct hostent hent;
+		char hbuf[4096];
+		int he;
+		hp = gethostbyaddr_r(addr, afd->a_addrlen, afd->a_af, &hent,
+		    hbuf, sizeof(hbuf), &he);
 
 		if (hp) {
 #if 0

Index: src/lib/libc/net/sethostent.c
diff -u src/lib/libc/net/sethostent.c:1.16 src/lib/libc/net/sethostent.c:1.16.18.1
--- src/lib/libc/net/sethostent.c:1.16	Sat Jan 27 22:27:35 2007
+++ src/lib/libc/net/sethostent.c	Wed Dec 18 20:23:36 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: sethostent.c,v 1.16 2007/01/27 22:27:35 christos Exp $	*/
+/*	$NetBSD: sethostent.c,v 1.16.18.1 2013/12/18 20:23:36 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1985, 1993
@@ -35,7 +35,7 @@
 static char sccsid[] = "@(#)sethostent.c	8.1 (Berkeley) 6/4/93";
 static char rcsid[] = "Id: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp ";
 #else
-__RCSID("$NetBSD: sethostent.c,v 1.16 2007/01/27 22:27:35 christos Exp $");
+__RCSID("$NetBSD: sethostent.c,v 1.16.18.1 2013/12/18 20:23:36 bouyer Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -43,24 +43,31 @@ __RCSID("$NetBSD: sethostent.c,v 1.16 20
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <string.h>
+#include <nsswitch.h>
 #include <netdb.h>
 #include <resolv.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "hostent.h"
 
 #ifdef __weak_alias
 __weak_alias(sethostent,_sethostent)
 __weak_alias(endhostent,_endhostent)
 #endif
 
-void	_endhtent __P((void));
 #ifndef _REENTRANT
-void	res_close __P((void));
+void	res_close(void);
 #endif
-void	_sethtent __P((int));
+
+static struct hostent *_hf_gethtbyname2(const char *, int, struct getnamaddr *);
 
 void
 /*ARGSUSED*/
-sethostent(stayopen)
-	int stayopen;
+sethostent(int stayopen)
 {
 #ifndef _REENTRANT
 	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
@@ -68,15 +75,215 @@ sethostent(stayopen)
 	if (stayopen)
 		_res.options |= RES_STAYOPEN | RES_USEVC;
 #endif
-	_sethtent(stayopen);
+	sethostent_r(&_h_file);
 }
 
 void
-endhostent()
+endhostent(void)
 {
 #ifndef _REENTRANT
 	_res.options &= ~(RES_STAYOPEN | RES_USEVC);
 	res_close();
 #endif
-	_endhtent();
+	endhostent_r(&_h_file);
+}
+static const char *_h_hosts = _PATH_HOSTS;
+
+void
+_hf_sethostsfile(const char *f) {
+	_h_hosts = f;
+}
+
+void
+sethostent_r(FILE **hf)
+{
+	if (!*hf)
+		*hf = fopen(_h_hosts, "re");
+	else
+		rewind(*hf);
+}
+
+void
+endhostent_r(FILE **hf)
+{
+	if (*hf) {
+		(void)fclose(*hf);
+		*hf = NULL;
+	}
+}
+
+/*ARGSUSED*/
+int
+_hf_gethtbyname(void *rv, void *cb_data, va_list ap)
+{
+	struct hostent *hp;
+	const char *name;
+	int af;
+	struct getnamaddr *info = rv;
+
+	_DIAGASSERT(rv != NULL);
+
+	name = va_arg(ap, char *);
+	/* NOSTRICT skip string len */(void)va_arg(ap, int);
+	af = va_arg(ap, int);
+
+#if 0
+	{
+		res_state res = __res_get_state();
+		if (res == NULL)
+			return NS_NOTFOUND;
+		if (res->options & RES_USE_INET6)
+			hp = _hf_gethtbyname2(name, AF_INET6, info);
+		else
+			hp = NULL;
+		if (hp == NULL)
+			hp = _hf_gethtbyname2(name, AF_INET, info);
+		__res_put_state(res);
+	}
+#else
+	hp = _hf_gethtbyname2(name, af, info);
+#endif
+	if (hp == NULL) {
+		*info->he = HOST_NOT_FOUND;
+		return NS_NOTFOUND;
+	}
+	return NS_SUCCESS;
+}
+
+struct hostent *
+_hf_gethtbyname2(const char *name, int af, struct getnamaddr *info)
+{
+	struct hostent *hp, hent;
+	char *buf, *ptr;
+	size_t len, anum, num, i;
+	FILE *hf;
+	char *aliases[MAXALIASES];
+	char *addr_ptrs[MAXADDRS];
+
+	_DIAGASSERT(name != NULL);
+
+	hf = NULL;
+	sethostent_r(&hf);
+	if (hf == NULL) {
+		errno = EINVAL;
+		*info->he = NETDB_INTERNAL;
+		return NULL;
+	}
+
+	if ((ptr = buf = malloc(len = info->buflen)) == NULL) {
+		*info->he = NETDB_INTERNAL;
+		return NULL;
+	}
+
+	anum = 0;		/* XXX: gcc */
+	hent.h_name = NULL;	/* XXX: gcc */
+	hent.h_addrtype = 0;	/* XXX: gcc */
+	hent.h_length = 0;	/* XXX: gcc */
+
+	for (num = 0; num < MAXADDRS;) {
+		info->hp->h_addrtype = af;
+		info->hp->h_length = 0;
+
+		hp = gethostent_r(hf, info->hp, info->buf, info->buflen,
+		    info->he);
+		if (hp == NULL)
+			break;
+
+		if (strcasecmp(hp->h_name, name) != 0) {
+			char **cp;
+			for (cp = hp->h_aliases; *cp != NULL; cp++)
+				if (strcasecmp(*cp, name) == 0)
+					break;
+			if (*cp == NULL) continue;
+		}
+
+		if (num == 0) {
+			hent.h_addrtype = af = hp->h_addrtype;
+			hent.h_length = hp->h_length;
+
+			HENT_SCOPY(hent.h_name, hp->h_name, ptr, len);
+			for (anum = 0; hp->h_aliases[anum]; anum++) {
+				if (anum >= __arraycount(aliases))
+					goto nospc;
+				HENT_SCOPY(aliases[anum], hp->h_aliases[anum],
+				    ptr, len);
+			}
+			ptr = (void *)ALIGN(ptr);
+			if ((size_t)(ptr - buf) >= info->buflen)
+				goto nospc;
+		}
+
+		if (num >= __arraycount(addr_ptrs))
+			goto nospc;
+		HENT_COPY(addr_ptrs[num], hp->h_addr_list[0], hp->h_length, ptr,
+		    len);
+		num++;
+	}
+	endhostent_r(&hf);
+
+	if (num == 0) {
+		*info->he = HOST_NOT_FOUND;
+		return NULL;
+	}
+
+	hp = info->hp;
+	ptr = info->buf;
+	len = info->buflen;
+
+	hp->h_addrtype = hent.h_addrtype;
+	hp->h_length = hent.h_length;
+
+	HENT_ARRAY(hp->h_aliases, anum, ptr, len);
+	HENT_ARRAY(hp->h_addr_list, num, ptr, len);
+
+	for (i = 0; i < num; i++)
+		HENT_COPY(hp->h_addr_list[i], addr_ptrs[i], hp->h_length, ptr,
+		    len);
+	hp->h_addr_list[num] = NULL;
+
+	HENT_SCOPY(hp->h_name, hent.h_name, ptr, len);
+
+	for (i = 0; i < anum; i++)
+		HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
+	hp->h_aliases[anum] = NULL;
+
+	return hp;
+nospc:
+	*info->he = NETDB_INTERNAL;
+	errno = ENOSPC;
+	return NULL;
+}
+
+/*ARGSUSED*/
+int
+_hf_gethtbyaddr(void *rv, void *cb_data, va_list ap)
+{
+	struct hostent *hp;
+	const unsigned char *addr;
+	struct getnamaddr *info = rv;
+	FILE *hf;
+
+	_DIAGASSERT(rv != NULL);
+
+	addr = va_arg(ap, unsigned char *);
+	info->hp->h_length = va_arg(ap, int);
+	info->hp->h_addrtype = va_arg(ap, int);
+	
+	hf = NULL;
+	sethostent_r(&hf);
+	if (hf == NULL) {
+		*info->he = NETDB_INTERNAL;
+		return NS_UNAVAIL;
+	}
+	while ((hp = gethostent_r(hf, info->hp, info->buf, info->buflen,
+	    info->he)) != NULL)
+		if (!memcmp(hp->h_addr_list[0], addr, (size_t)hp->h_length))
+			break;
+	endhostent_r(&hf);
+
+	if (hp == NULL) {
+		*info->he = HOST_NOT_FOUND;
+		return NS_NOTFOUND;
+	}
+	return NS_SUCCESS;
 }

Added files:

Index: src/lib/libc/net/hostent.h
diff -u /dev/null src/lib/libc/net/hostent.h:1.2.2.2
--- /dev/null	Wed Dec 18 20:23:36 2013
+++ src/lib/libc/net/hostent.h	Wed Dec 18 20:23:36 2013
@@ -0,0 +1,106 @@
+/*	$NetBSD: hostent.h,v 1.2.2.2 2013/12/18 20:23:36 bouyer Exp $	*/
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <stdarg.h>
+
+/*
+ * These are not being advertised because the interfaces are non-standard.
+ * There are versions by linux, aix, qnx, sun, etc. Our versions are used
+ * internally to provide thread safety; they mostly resemble qnx.
+ */
+void sethostent_r(FILE **);
+struct hostent	*gethostent_r(FILE *, struct hostent *, char *, size_t, int *);
+void endhostent_r(FILE **);
+
+struct hostent *gethostbyname_r(const char *, struct hostent *, char *, size_t,
+    int *);
+struct hostent *gethostbyname2_r(const char *, int, struct hostent *, char *,
+    size_t, int *);
+struct hostent *gethostbyaddr_r(const void *, socklen_t, int, struct hostent *,
+    char *, size_t, int *);
+
+extern FILE *_h_file;
+
+/*
+ * The following are internal API's and are used only for testing.
+ */
+struct getnamaddr {
+	struct hostent *hp;
+	char *buf;
+	size_t buflen;
+	int *he;
+};
+
+/* /etc/hosts lookup */
+void _hf_sethostsfile(const char *);
+int _hf_gethtbyaddr(void *, void *, va_list);
+int _hf_gethtbyname(void *, void *, va_list);
+
+/* DNS lookup */
+int _dns_gethtbyaddr(void *, void *, va_list);
+int _dns_gethtbyname(void *, void *, va_list);
+
+#ifdef YP
+/* NIS lookup */
+int _yp_gethtbyaddr(void *, void *, va_list);
+int _yp_gethtbyname(void *, void *, va_list);
+#endif
+
+#define HENT_ARRAY(dst, anum, ptr, len) \
+	do { \
+		size_t _len = (anum + 1) * sizeof(*dst); \
+		if (_len > len) \
+			goto nospc; \
+		dst = (void *)ptr; \
+		ptr += _len; \
+		len -= _len; \
+	} while (/*CONSTCOND*/0)
+
+#define HENT_COPY(dst, src, slen, ptr, len) \
+	do { \
+		if ((size_t)slen > len) \
+			goto nospc; \
+		memcpy(ptr, src, (size_t)slen); \
+		dst = ptr; \
+		ptr += slen; \
+		len -= slen; \
+	} while (/* CONSTCOND */0)
+
+#define HENT_SCOPY(dst, src, ptr, len) \
+	do { \
+		size_t _len = strlen(src) + 1; \
+		HENT_COPY(dst, src, _len, ptr, len); \
+	} while (/* CONSTCOND */0)
+
+#define	MAXALIASES	35
+#define	MAXADDRS	35

Reply via email to