xref: /minix/lib/libc/net/gethnamaddr.c (revision 84d9c625)
1*84d9c625SLionel Sambuc /*	$NetBSD: gethnamaddr.c,v 1.84 2013/08/27 09:56:12 christos Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*
42fe8fb19SBen Gras  * ++Copyright++ 1985, 1988, 1993
52fe8fb19SBen Gras  * -
62fe8fb19SBen Gras  * Copyright (c) 1985, 1988, 1993
72fe8fb19SBen Gras  *    The Regents of the University of California.  All rights reserved.
82fe8fb19SBen Gras  *
92fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
102fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
112fe8fb19SBen Gras  * are met:
122fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
132fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
142fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
152fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
162fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
172fe8fb19SBen Gras  * 3. Neither the name of the University nor the names of its contributors
182fe8fb19SBen Gras  *    may be used to endorse or promote products derived from this software
192fe8fb19SBen Gras  *    without specific prior written permission.
202fe8fb19SBen Gras  *
212fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
222fe8fb19SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232fe8fb19SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
242fe8fb19SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
252fe8fb19SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
262fe8fb19SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
272fe8fb19SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
282fe8fb19SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
292fe8fb19SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
302fe8fb19SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
312fe8fb19SBen Gras  * SUCH DAMAGE.
322fe8fb19SBen Gras  * -
332fe8fb19SBen Gras  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
342fe8fb19SBen Gras  *
352fe8fb19SBen Gras  * Permission to use, copy, modify, and distribute this software for any
362fe8fb19SBen Gras  * purpose with or without fee is hereby granted, provided that the above
372fe8fb19SBen Gras  * copyright notice and this permission notice appear in all copies, and that
382fe8fb19SBen Gras  * the name of Digital Equipment Corporation not be used in advertising or
392fe8fb19SBen Gras  * publicity pertaining to distribution of the document or software without
402fe8fb19SBen Gras  * specific, written prior permission.
412fe8fb19SBen Gras  *
422fe8fb19SBen Gras  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
432fe8fb19SBen Gras  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
442fe8fb19SBen Gras  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
452fe8fb19SBen Gras  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
462fe8fb19SBen Gras  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
472fe8fb19SBen Gras  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
482fe8fb19SBen Gras  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
492fe8fb19SBen Gras  * SOFTWARE.
502fe8fb19SBen Gras  * -
512fe8fb19SBen Gras  * --Copyright--
522fe8fb19SBen Gras  */
532fe8fb19SBen Gras 
542fe8fb19SBen Gras #include <sys/cdefs.h>
552fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
562fe8fb19SBen Gras #if 0
572fe8fb19SBen Gras static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
582fe8fb19SBen Gras static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp ";
592fe8fb19SBen Gras #else
60*84d9c625SLionel Sambuc __RCSID("$NetBSD: gethnamaddr.c,v 1.84 2013/08/27 09:56:12 christos Exp $");
612fe8fb19SBen Gras #endif
622fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
632fe8fb19SBen Gras 
642fe8fb19SBen Gras #if defined(_LIBC)
652fe8fb19SBen Gras #include "namespace.h"
662fe8fb19SBen Gras #endif
672fe8fb19SBen Gras #include <sys/param.h>
682fe8fb19SBen Gras #include <sys/socket.h>
692fe8fb19SBen Gras #include <netinet/in.h>
702fe8fb19SBen Gras #include <arpa/inet.h>
712fe8fb19SBen Gras #include <arpa/nameser.h>
722fe8fb19SBen Gras 
732fe8fb19SBen Gras #include <assert.h>
742fe8fb19SBen Gras #include <ctype.h>
752fe8fb19SBen Gras #include <errno.h>
762fe8fb19SBen Gras #include <netdb.h>
772fe8fb19SBen Gras #include <resolv.h>
782fe8fb19SBen Gras #include <stdarg.h>
792fe8fb19SBen Gras #include <stdio.h>
802fe8fb19SBen Gras #include <syslog.h>
812fe8fb19SBen Gras 
822fe8fb19SBen Gras #ifndef LOG_AUTH
832fe8fb19SBen Gras # define LOG_AUTH 0
842fe8fb19SBen Gras #endif
852fe8fb19SBen Gras 
862fe8fb19SBen Gras #define MULTI_PTRS_ARE_ALIASES 1	/* XXX - experimental */
872fe8fb19SBen Gras 
882fe8fb19SBen Gras #include <nsswitch.h>
892fe8fb19SBen Gras #include <stdlib.h>
902fe8fb19SBen Gras #include <string.h>
912fe8fb19SBen Gras 
922fe8fb19SBen Gras #ifdef YP
932fe8fb19SBen Gras #include <rpc/rpc.h>
942fe8fb19SBen Gras #include <rpcsvc/yp_prot.h>
952fe8fb19SBen Gras #include <rpcsvc/ypclnt.h>
962fe8fb19SBen Gras #endif
972fe8fb19SBen Gras 
98*84d9c625SLionel Sambuc #include "hostent.h"
99*84d9c625SLionel Sambuc 
1002fe8fb19SBen Gras #if defined(_LIBC) && defined(__weak_alias)
1012fe8fb19SBen Gras __weak_alias(gethostbyaddr,_gethostbyaddr)
1022fe8fb19SBen Gras __weak_alias(gethostbyname,_gethostbyname)
1032fe8fb19SBen Gras __weak_alias(gethostent,_gethostent)
1042fe8fb19SBen Gras #endif
1052fe8fb19SBen Gras 
106f14fb602SLionel Sambuc #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
107f14fb602SLionel Sambuc                                (ok)(nm) != 0)
108f14fb602SLionel Sambuc #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
109f14fb602SLionel Sambuc #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
110f14fb602SLionel Sambuc 
111f14fb602SLionel Sambuc 
1122fe8fb19SBen Gras static const char AskedForGot[] =
1132fe8fb19SBen Gras     "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1142fe8fb19SBen Gras 
1152fe8fb19SBen Gras 
1162fe8fb19SBen Gras #ifdef YP
1172fe8fb19SBen Gras static char *__ypdomain;
1182fe8fb19SBen Gras #endif
1192fe8fb19SBen Gras 
1202fe8fb19SBen Gras #define	MAXPACKET	(64*1024)
1212fe8fb19SBen Gras 
1222fe8fb19SBen Gras typedef union {
1232fe8fb19SBen Gras 	HEADER hdr;
1242fe8fb19SBen Gras 	u_char buf[MAXPACKET];
1252fe8fb19SBen Gras } querybuf;
1262fe8fb19SBen Gras 
1272fe8fb19SBen Gras typedef union {
1282fe8fb19SBen Gras 	int32_t al;
1292fe8fb19SBen Gras 	char ac;
1302fe8fb19SBen Gras } align;
1312fe8fb19SBen Gras 
1322fe8fb19SBen Gras #ifdef DEBUG
1332fe8fb19SBen Gras static void debugprintf(const char *, res_state, ...)
1342fe8fb19SBen Gras 	__attribute__((__format__(__printf__, 1, 3)));
1352fe8fb19SBen Gras #endif
1362fe8fb19SBen Gras static struct hostent *getanswer(const querybuf *, int, const char *, int,
137*84d9c625SLionel Sambuc     res_state, struct hostent *, char *, size_t, int *);
1382fe8fb19SBen Gras static void map_v4v6_address(const char *, char *);
1392fe8fb19SBen Gras static void map_v4v6_hostent(struct hostent *, char **, char *);
1402fe8fb19SBen Gras static void addrsort(char **, int, res_state);
1412fe8fb19SBen Gras 
1422fe8fb19SBen Gras void dns_service(void);
1432fe8fb19SBen Gras #undef dn_skipname
1442fe8fb19SBen Gras int dn_skipname(const u_char *, const u_char *);
145*84d9c625SLionel Sambuc 
1462fe8fb19SBen Gras #ifdef YP
147*84d9c625SLionel Sambuc static struct hostent *_yp_hostent(char *, int, struct getnamaddr *);
1482fe8fb19SBen Gras #endif
1492fe8fb19SBen Gras 
150*84d9c625SLionel Sambuc static struct hostent *gethostbyname_internal(const char *, int, res_state,
151*84d9c625SLionel Sambuc     struct hostent *, char *, size_t, int *);
1522fe8fb19SBen Gras 
1532fe8fb19SBen Gras static const ns_src default_dns_files[] = {
1542fe8fb19SBen Gras 	{ NSSRC_FILES, 	NS_SUCCESS },
1552fe8fb19SBen Gras 	{ NSSRC_DNS, 	NS_SUCCESS },
1562fe8fb19SBen Gras 	{ 0, 0 }
1572fe8fb19SBen Gras };
1582fe8fb19SBen Gras 
1592fe8fb19SBen Gras 
1602fe8fb19SBen Gras #ifdef DEBUG
1612fe8fb19SBen Gras static void
1622fe8fb19SBen Gras debugprintf(const char *msg, res_state res, ...)
1632fe8fb19SBen Gras {
1642fe8fb19SBen Gras 	_DIAGASSERT(msg != NULL);
1652fe8fb19SBen Gras 
1662fe8fb19SBen Gras 	if (res->options & RES_DEBUG) {
1672fe8fb19SBen Gras 		int save = errno;
1682fe8fb19SBen Gras 		va_list ap;
1692fe8fb19SBen Gras 
1702fe8fb19SBen Gras 		va_start (ap, res);
1712fe8fb19SBen Gras 		vprintf(msg, ap);
1722fe8fb19SBen Gras 		va_end (ap);
1732fe8fb19SBen Gras 
1742fe8fb19SBen Gras 		errno = save;
1752fe8fb19SBen Gras 	}
1762fe8fb19SBen Gras }
1772fe8fb19SBen Gras #else
1782fe8fb19SBen Gras # define debugprintf(msg, res, num) /*nada*/
1792fe8fb19SBen Gras #endif
1802fe8fb19SBen Gras 
1812fe8fb19SBen Gras #define BOUNDED_INCR(x) \
1822fe8fb19SBen Gras 	do { \
1832fe8fb19SBen Gras 		cp += (x); \
1842fe8fb19SBen Gras 		if (cp > eom) { \
1852fe8fb19SBen Gras 			h_errno = NO_RECOVERY; \
1862fe8fb19SBen Gras 			return NULL; \
1872fe8fb19SBen Gras 		} \
1882fe8fb19SBen Gras 	} while (/*CONSTCOND*/0)
1892fe8fb19SBen Gras 
1902fe8fb19SBen Gras #define BOUNDS_CHECK(ptr, count) \
1912fe8fb19SBen Gras 	do { \
1922fe8fb19SBen Gras 		if ((ptr) + (count) > eom) { \
1932fe8fb19SBen Gras 			h_errno = NO_RECOVERY; \
1942fe8fb19SBen Gras 			return NULL; \
1952fe8fb19SBen Gras 		} \
1962fe8fb19SBen Gras 	} while (/*CONSTCOND*/0)
1972fe8fb19SBen Gras 
1982fe8fb19SBen Gras static struct hostent *
1992fe8fb19SBen Gras getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
200*84d9c625SLionel Sambuc     res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
2012fe8fb19SBen Gras {
2022fe8fb19SBen Gras 	const HEADER *hp;
2032fe8fb19SBen Gras 	const u_char *cp;
2042fe8fb19SBen Gras 	int n;
205*84d9c625SLionel Sambuc 	size_t qlen;
2062fe8fb19SBen Gras 	const u_char *eom, *erdata;
2072fe8fb19SBen Gras 	char *bp, **ap, **hap, *ep;
2082fe8fb19SBen Gras 	int type, class, ancount, qdcount;
2092fe8fb19SBen Gras 	int haveanswer, had_error;
2102fe8fb19SBen Gras 	int toobig = 0;
2112fe8fb19SBen Gras 	char tbuf[MAXDNAME];
212*84d9c625SLionel Sambuc 	char *aliases[MAXALIASES];
213*84d9c625SLionel Sambuc 	char *addr_ptrs[MAXADDRS];
2142fe8fb19SBen Gras 	const char *tname;
2152fe8fb19SBen Gras 	int (*name_ok)(const char *);
2162fe8fb19SBen Gras 
2172fe8fb19SBen Gras 	_DIAGASSERT(answer != NULL);
2182fe8fb19SBen Gras 	_DIAGASSERT(qname != NULL);
2192fe8fb19SBen Gras 
2202fe8fb19SBen Gras 	tname = qname;
221*84d9c625SLionel Sambuc 	hent->h_name = NULL;
2222fe8fb19SBen Gras 	eom = answer->buf + anslen;
2232fe8fb19SBen Gras 	switch (qtype) {
2242fe8fb19SBen Gras 	case T_A:
2252fe8fb19SBen Gras 	case T_AAAA:
2262fe8fb19SBen Gras 		name_ok = res_hnok;
2272fe8fb19SBen Gras 		break;
2282fe8fb19SBen Gras 	case T_PTR:
2292fe8fb19SBen Gras 		name_ok = res_dnok;
2302fe8fb19SBen Gras 		break;
2312fe8fb19SBen Gras 	default:
2322fe8fb19SBen Gras 		return NULL;	/* XXX should be abort(); */
2332fe8fb19SBen Gras 	}
2342fe8fb19SBen Gras 	/*
2352fe8fb19SBen Gras 	 * find first satisfactory answer
2362fe8fb19SBen Gras 	 */
2372fe8fb19SBen Gras 	hp = &answer->hdr;
2382fe8fb19SBen Gras 	ancount = ntohs(hp->ancount);
2392fe8fb19SBen Gras 	qdcount = ntohs(hp->qdcount);
240*84d9c625SLionel Sambuc 	bp = buf;
241*84d9c625SLionel Sambuc 	ep = buf + buflen;
2422fe8fb19SBen Gras 	cp = answer->buf;
2432fe8fb19SBen Gras 	BOUNDED_INCR(HFIXEDSZ);
244*84d9c625SLionel Sambuc 	if (qdcount != 1)
245*84d9c625SLionel Sambuc 		goto no_recovery;
246*84d9c625SLionel Sambuc 
247f14fb602SLionel Sambuc 	n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
248*84d9c625SLionel Sambuc 	if ((n < 0) || !maybe_ok(res, bp, name_ok))
249*84d9c625SLionel Sambuc 		goto no_recovery;
250*84d9c625SLionel Sambuc 
2512fe8fb19SBen Gras 	BOUNDED_INCR(n + QFIXEDSZ);
2522fe8fb19SBen Gras 	if (qtype == T_A || qtype == T_AAAA) {
2532fe8fb19SBen Gras 		/* res_send() has already verified that the query name is the
2542fe8fb19SBen Gras 		 * same as the one we sent; this just gets the expanded name
2552fe8fb19SBen Gras 		 * (i.e., with the succeeding search-domain tacked on).
2562fe8fb19SBen Gras 		 */
257f14fb602SLionel Sambuc 		n = (int)strlen(bp) + 1;		/* for the \0 */
258*84d9c625SLionel Sambuc 		if (n >= MAXHOSTNAMELEN)
259*84d9c625SLionel Sambuc 			goto no_recovery;
260*84d9c625SLionel Sambuc 		hent->h_name = bp;
2612fe8fb19SBen Gras 		bp += n;
2622fe8fb19SBen Gras 		/* The qname can be abbreviated, but h_name is now absolute. */
263*84d9c625SLionel Sambuc 		qname = hent->h_name;
2642fe8fb19SBen Gras 	}
265*84d9c625SLionel Sambuc 	hent->h_aliases = ap = aliases;
266*84d9c625SLionel Sambuc 	hent->h_addr_list = hap = addr_ptrs;
2672fe8fb19SBen Gras 	*ap = NULL;
2682fe8fb19SBen Gras 	*hap = NULL;
2692fe8fb19SBen Gras 	haveanswer = 0;
2702fe8fb19SBen Gras 	had_error = 0;
2712fe8fb19SBen Gras 	while (ancount-- > 0 && cp < eom && !had_error) {
272f14fb602SLionel Sambuc 		n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
273f14fb602SLionel Sambuc 		if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
2742fe8fb19SBen Gras 			had_error++;
2752fe8fb19SBen Gras 			continue;
2762fe8fb19SBen Gras 		}
2772fe8fb19SBen Gras 		cp += n;			/* name */
2782fe8fb19SBen Gras 		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
2792fe8fb19SBen Gras 		type = _getshort(cp);
2802fe8fb19SBen Gras  		cp += INT16SZ;			/* type */
2812fe8fb19SBen Gras 		class = _getshort(cp);
2822fe8fb19SBen Gras  		cp += INT16SZ + INT32SZ;	/* class, TTL */
2832fe8fb19SBen Gras 		n = _getshort(cp);
2842fe8fb19SBen Gras 		cp += INT16SZ;			/* len */
2852fe8fb19SBen Gras 		BOUNDS_CHECK(cp, n);
2862fe8fb19SBen Gras 		erdata = cp + n;
2872fe8fb19SBen Gras 		if (class != C_IN) {
2882fe8fb19SBen Gras 			/* XXX - debug? syslog? */
2892fe8fb19SBen Gras 			cp += n;
2902fe8fb19SBen Gras 			continue;		/* XXX - had_error++ ? */
2912fe8fb19SBen Gras 		}
2922fe8fb19SBen Gras 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
293*84d9c625SLionel Sambuc 			if (ap >= &aliases[MAXALIASES-1])
2942fe8fb19SBen Gras 				continue;
295*84d9c625SLionel Sambuc 			n = dn_expand(answer->buf, eom, cp, tbuf,
296*84d9c625SLionel Sambuc 			    (int)sizeof tbuf);
297f14fb602SLionel Sambuc 			if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
2982fe8fb19SBen Gras 				had_error++;
2992fe8fb19SBen Gras 				continue;
3002fe8fb19SBen Gras 			}
3012fe8fb19SBen Gras 			cp += n;
302*84d9c625SLionel Sambuc 			if (cp != erdata)
303*84d9c625SLionel Sambuc 				goto no_recovery;
3042fe8fb19SBen Gras 			/* Store alias. */
3052fe8fb19SBen Gras 			*ap++ = bp;
306f14fb602SLionel Sambuc 			n = (int)strlen(bp) + 1;	/* for the \0 */
3072fe8fb19SBen Gras 			if (n >= MAXHOSTNAMELEN) {
3082fe8fb19SBen Gras 				had_error++;
3092fe8fb19SBen Gras 				continue;
3102fe8fb19SBen Gras 			}
3112fe8fb19SBen Gras 			bp += n;
3122fe8fb19SBen Gras 			/* Get canonical name. */
313f14fb602SLionel Sambuc 			n = (int)strlen(tbuf) + 1;	/* for the \0 */
3142fe8fb19SBen Gras 			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
3152fe8fb19SBen Gras 				had_error++;
3162fe8fb19SBen Gras 				continue;
3172fe8fb19SBen Gras 			}
3182fe8fb19SBen Gras 			strlcpy(bp, tbuf, (size_t)(ep - bp));
319*84d9c625SLionel Sambuc 			hent->h_name = bp;
3202fe8fb19SBen Gras 			bp += n;
3212fe8fb19SBen Gras 			continue;
3222fe8fb19SBen Gras 		}
3232fe8fb19SBen Gras 		if (qtype == T_PTR && type == T_CNAME) {
324*84d9c625SLionel Sambuc 			n = dn_expand(answer->buf, eom, cp, tbuf,
325*84d9c625SLionel Sambuc 			    (int)sizeof tbuf);
326f14fb602SLionel Sambuc 			if (n < 0 || !maybe_dnok(res, tbuf)) {
3272fe8fb19SBen Gras 				had_error++;
3282fe8fb19SBen Gras 				continue;
3292fe8fb19SBen Gras 			}
3302fe8fb19SBen Gras 			cp += n;
331*84d9c625SLionel Sambuc 			if (cp != erdata)
332*84d9c625SLionel Sambuc 				goto no_recovery;
3332fe8fb19SBen Gras 			/* Get canonical name. */
334f14fb602SLionel Sambuc 			n = (int)strlen(tbuf) + 1;	/* for the \0 */
3352fe8fb19SBen Gras 			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
3362fe8fb19SBen Gras 				had_error++;
3372fe8fb19SBen Gras 				continue;
3382fe8fb19SBen Gras 			}
3392fe8fb19SBen Gras 			strlcpy(bp, tbuf, (size_t)(ep - bp));
3402fe8fb19SBen Gras 			tname = bp;
3412fe8fb19SBen Gras 			bp += n;
3422fe8fb19SBen Gras 			continue;
3432fe8fb19SBen Gras 		}
3442fe8fb19SBen Gras 		if (type != qtype) {
3452fe8fb19SBen Gras 			if (type != T_KEY && type != T_SIG)
3462fe8fb19SBen Gras 				syslog(LOG_NOTICE|LOG_AUTH,
3472fe8fb19SBen Gras 	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
3482fe8fb19SBen Gras 				       qname, p_class(C_IN), p_type(qtype),
3492fe8fb19SBen Gras 				       p_type(type));
3502fe8fb19SBen Gras 			cp += n;
3512fe8fb19SBen Gras 			continue;		/* XXX - had_error++ ? */
3522fe8fb19SBen Gras 		}
3532fe8fb19SBen Gras 		switch (type) {
3542fe8fb19SBen Gras 		case T_PTR:
3552fe8fb19SBen Gras 			if (strcasecmp(tname, bp) != 0) {
3562fe8fb19SBen Gras 				syslog(LOG_NOTICE|LOG_AUTH,
3572fe8fb19SBen Gras 				       AskedForGot, qname, bp);
3582fe8fb19SBen Gras 				cp += n;
3592fe8fb19SBen Gras 				continue;	/* XXX - had_error++ ? */
3602fe8fb19SBen Gras 			}
361f14fb602SLionel Sambuc 			n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
362f14fb602SLionel Sambuc 			if ((n < 0) || !maybe_hnok(res, bp)) {
3632fe8fb19SBen Gras 				had_error++;
3642fe8fb19SBen Gras 				break;
3652fe8fb19SBen Gras 			}
3662fe8fb19SBen Gras #if MULTI_PTRS_ARE_ALIASES
3672fe8fb19SBen Gras 			cp += n;
368*84d9c625SLionel Sambuc 			if (cp != erdata)
369*84d9c625SLionel Sambuc 				goto no_recovery;
3702fe8fb19SBen Gras 			if (!haveanswer)
371*84d9c625SLionel Sambuc 				hent->h_name = bp;
372*84d9c625SLionel Sambuc 			else if (ap < &aliases[MAXALIASES-1])
3732fe8fb19SBen Gras 				*ap++ = bp;
3742fe8fb19SBen Gras 			else
3752fe8fb19SBen Gras 				n = -1;
3762fe8fb19SBen Gras 			if (n != -1) {
377f14fb602SLionel Sambuc 				n = (int)strlen(bp) + 1;	/* for the \0 */
3782fe8fb19SBen Gras 				if (n >= MAXHOSTNAMELEN) {
3792fe8fb19SBen Gras 					had_error++;
3802fe8fb19SBen Gras 					break;
3812fe8fb19SBen Gras 				}
3822fe8fb19SBen Gras 				bp += n;
3832fe8fb19SBen Gras 			}
3842fe8fb19SBen Gras 			break;
3852fe8fb19SBen Gras #else
386*84d9c625SLionel Sambuc 			hent->h_name = bp;
3872fe8fb19SBen Gras 			if (res->options & RES_USE_INET6) {
3882fe8fb19SBen Gras 				n = strlen(bp) + 1;	/* for the \0 */
3892fe8fb19SBen Gras 				if (n >= MAXHOSTNAMELEN) {
3902fe8fb19SBen Gras 					had_error++;
3912fe8fb19SBen Gras 					break;
3922fe8fb19SBen Gras 				}
3932fe8fb19SBen Gras 				bp += n;
394*84d9c625SLionel Sambuc 				map_v4v6_hostent(hent, &bp, ep);
3952fe8fb19SBen Gras 			}
396*84d9c625SLionel Sambuc 			goto success;
3972fe8fb19SBen Gras #endif
3982fe8fb19SBen Gras 		case T_A:
3992fe8fb19SBen Gras 		case T_AAAA:
400*84d9c625SLionel Sambuc 			if (strcasecmp(hent->h_name, bp) != 0) {
4012fe8fb19SBen Gras 				syslog(LOG_NOTICE|LOG_AUTH,
402*84d9c625SLionel Sambuc 				       AskedForGot, hent->h_name, bp);
4032fe8fb19SBen Gras 				cp += n;
4042fe8fb19SBen Gras 				continue;	/* XXX - had_error++ ? */
4052fe8fb19SBen Gras 			}
406*84d9c625SLionel Sambuc 			if (n != hent->h_length) {
4072fe8fb19SBen Gras 				cp += n;
4082fe8fb19SBen Gras 				continue;
4092fe8fb19SBen Gras 			}
4102fe8fb19SBen Gras 			if (type == T_AAAA) {
4112fe8fb19SBen Gras 				struct in6_addr in6;
412*84d9c625SLionel Sambuc 				memcpy(&in6, cp, NS_IN6ADDRSZ);
4132fe8fb19SBen Gras 				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
4142fe8fb19SBen Gras 					cp += n;
4152fe8fb19SBen Gras 					continue;
4162fe8fb19SBen Gras 				}
4172fe8fb19SBen Gras 			}
4182fe8fb19SBen Gras 			if (!haveanswer) {
4192fe8fb19SBen Gras 				int nn;
4202fe8fb19SBen Gras 
421*84d9c625SLionel Sambuc 				hent->h_name = bp;
422f14fb602SLionel Sambuc 				nn = (int)strlen(bp) + 1;	/* for the \0 */
4232fe8fb19SBen Gras 				bp += nn;
4242fe8fb19SBen Gras 			}
4252fe8fb19SBen Gras 
4262fe8fb19SBen Gras 			bp += sizeof(align) -
4272fe8fb19SBen Gras 			    (size_t)((u_long)bp % sizeof(align));
4282fe8fb19SBen Gras 
429*84d9c625SLionel Sambuc 			if (bp + n >= ep) {
4302fe8fb19SBen Gras 				debugprintf("size (%d) too big\n", res, n);
4312fe8fb19SBen Gras 				had_error++;
4322fe8fb19SBen Gras 				continue;
4332fe8fb19SBen Gras 			}
434*84d9c625SLionel Sambuc 			if (hap >= &addr_ptrs[MAXADDRS - 1]) {
4352fe8fb19SBen Gras 				if (!toobig++) {
4362fe8fb19SBen Gras 					debugprintf("Too many addresses (%d)\n",
4372fe8fb19SBen Gras 						res, MAXADDRS);
4382fe8fb19SBen Gras 				}
4392fe8fb19SBen Gras 				cp += n;
4402fe8fb19SBen Gras 				continue;
4412fe8fb19SBen Gras 			}
4422fe8fb19SBen Gras 			(void)memcpy(*hap++ = bp, cp, (size_t)n);
4432fe8fb19SBen Gras 			bp += n;
4442fe8fb19SBen Gras 			cp += n;
445*84d9c625SLionel Sambuc 			if (cp != erdata)
446*84d9c625SLionel Sambuc 				goto no_recovery;
4472fe8fb19SBen Gras 			break;
4482fe8fb19SBen Gras 		default:
4492fe8fb19SBen Gras 			abort();
4502fe8fb19SBen Gras 		}
4512fe8fb19SBen Gras 		if (!had_error)
4522fe8fb19SBen Gras 			haveanswer++;
4532fe8fb19SBen Gras 	}
4542fe8fb19SBen Gras 	if (haveanswer) {
4552fe8fb19SBen Gras 		*ap = NULL;
4562fe8fb19SBen Gras 		*hap = NULL;
4572fe8fb19SBen Gras 		/*
4582fe8fb19SBen Gras 		 * Note: we sort even if host can take only one address
4592fe8fb19SBen Gras 		 * in its return structures - should give it the "best"
4602fe8fb19SBen Gras 		 * address in that case, not some random one
4612fe8fb19SBen Gras 		 */
4622fe8fb19SBen Gras 		if (res->nsort && haveanswer > 1 && qtype == T_A)
463*84d9c625SLionel Sambuc 			addrsort(addr_ptrs, haveanswer, res);
464*84d9c625SLionel Sambuc 		if (!hent->h_name) {
465f14fb602SLionel Sambuc 			n = (int)strlen(qname) + 1;	/* for the \0 */
4662fe8fb19SBen Gras 			if (n > ep - bp || n >= MAXHOSTNAMELEN)
4672fe8fb19SBen Gras 				goto no_recovery;
4682fe8fb19SBen Gras 			strlcpy(bp, qname, (size_t)(ep - bp));
469*84d9c625SLionel Sambuc 			hent->h_name = bp;
4702fe8fb19SBen Gras 			bp += n;
4712fe8fb19SBen Gras 		}
4722fe8fb19SBen Gras 		if (res->options & RES_USE_INET6)
473*84d9c625SLionel Sambuc 			map_v4v6_hostent(hent, &bp, ep);
474*84d9c625SLionel Sambuc 	    	goto success;
4752fe8fb19SBen Gras 	}
4762fe8fb19SBen Gras no_recovery:
477*84d9c625SLionel Sambuc 	*he = NO_RECOVERY;
478*84d9c625SLionel Sambuc 	return NULL;
479*84d9c625SLionel Sambuc success:
480*84d9c625SLionel Sambuc 	bp = (char *)ALIGN(bp);
481*84d9c625SLionel Sambuc 	n = (int)(ap - aliases);
482*84d9c625SLionel Sambuc 	qlen = (n + 1) * sizeof(*hent->h_aliases);
483*84d9c625SLionel Sambuc 	if ((size_t)(ep - bp) < qlen)
484*84d9c625SLionel Sambuc 		goto nospc;
485*84d9c625SLionel Sambuc 	hent->h_aliases = (void *)bp;
486*84d9c625SLionel Sambuc 	memcpy(bp, aliases, qlen);
487*84d9c625SLionel Sambuc 
488*84d9c625SLionel Sambuc 	bp += qlen;
489*84d9c625SLionel Sambuc 	n = (int)(hap - addr_ptrs);
490*84d9c625SLionel Sambuc 	qlen = (n + 1) * sizeof(*hent->h_addr_list);
491*84d9c625SLionel Sambuc 	if ((size_t)(ep - bp) < qlen)
492*84d9c625SLionel Sambuc 		goto nospc;
493*84d9c625SLionel Sambuc 	hent->h_addr_list = (void *)bp;
494*84d9c625SLionel Sambuc 	memcpy(bp, addr_ptrs, qlen);
495*84d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
496*84d9c625SLionel Sambuc 	return hent;
497*84d9c625SLionel Sambuc nospc:
498*84d9c625SLionel Sambuc 	errno = ENOSPC;
499*84d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
5002fe8fb19SBen Gras 	return NULL;
5012fe8fb19SBen Gras }
5022fe8fb19SBen Gras 
5032fe8fb19SBen Gras struct hostent *
504*84d9c625SLionel Sambuc gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
505*84d9c625SLionel Sambuc     int *he)
5062fe8fb19SBen Gras {
5072fe8fb19SBen Gras 	res_state res = __res_get_state();
5082fe8fb19SBen Gras 
509*84d9c625SLionel Sambuc 	if (res == NULL) {
510*84d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
5112fe8fb19SBen Gras 		return NULL;
512*84d9c625SLionel Sambuc 	}
5132fe8fb19SBen Gras 
5142fe8fb19SBen Gras 	_DIAGASSERT(name != NULL);
5152fe8fb19SBen Gras 
5162fe8fb19SBen Gras 	if (res->options & RES_USE_INET6) {
517*84d9c625SLionel Sambuc 		hp = gethostbyname_internal(name, AF_INET6, res, hp, buf,
518*84d9c625SLionel Sambuc 		    buflen, he);
5192fe8fb19SBen Gras 		if (hp) {
5202fe8fb19SBen Gras 			__res_put_state(res);
5212fe8fb19SBen Gras 			return hp;
5222fe8fb19SBen Gras 		}
5232fe8fb19SBen Gras 	}
524*84d9c625SLionel Sambuc 	hp = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, he);
5252fe8fb19SBen Gras 	__res_put_state(res);
5262fe8fb19SBen Gras 	return hp;
5272fe8fb19SBen Gras }
5282fe8fb19SBen Gras 
5292fe8fb19SBen Gras struct hostent *
530*84d9c625SLionel Sambuc gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
531*84d9c625SLionel Sambuc     size_t buflen, int *he)
5322fe8fb19SBen Gras {
5332fe8fb19SBen Gras 	res_state res = __res_get_state();
5342fe8fb19SBen Gras 
535*84d9c625SLionel Sambuc 	if (res == NULL) {
536*84d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
5372fe8fb19SBen Gras 		return NULL;
538*84d9c625SLionel Sambuc 	}
539*84d9c625SLionel Sambuc 	hp = gethostbyname_internal(name, af, res, hp, buf, buflen, he);
5402fe8fb19SBen Gras 	__res_put_state(res);
5412fe8fb19SBen Gras 	return hp;
5422fe8fb19SBen Gras }
5432fe8fb19SBen Gras 
5442fe8fb19SBen Gras static struct hostent *
545*84d9c625SLionel Sambuc gethostbyname_internal(const char *name, int af, res_state res,
546*84d9c625SLionel Sambuc     struct hostent *hp, char *buf, size_t buflen, int *he)
5472fe8fb19SBen Gras {
5482fe8fb19SBen Gras 	const char *cp;
549*84d9c625SLionel Sambuc 	struct getnamaddr info;
550*84d9c625SLionel Sambuc 	size_t size;
5512fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
552*84d9c625SLionel Sambuc 		NS_FILES_CB(_hf_gethtbyname, NULL)
5532fe8fb19SBen Gras 		{ NSSRC_DNS, _dns_gethtbyname, NULL },	/* force -DHESIOD */
5542fe8fb19SBen Gras 		NS_NIS_CB(_yp_gethtbyname, NULL)
5552fe8fb19SBen Gras 		NS_NULL_CB
5562fe8fb19SBen Gras 	};
5572fe8fb19SBen Gras 
5582fe8fb19SBen Gras 	_DIAGASSERT(name != NULL);
5592fe8fb19SBen Gras 
5602fe8fb19SBen Gras 	switch (af) {
5612fe8fb19SBen Gras 	case AF_INET:
562*84d9c625SLionel Sambuc 		size = NS_INADDRSZ;
5632fe8fb19SBen Gras 		break;
5642fe8fb19SBen Gras 	case AF_INET6:
565*84d9c625SLionel Sambuc 		size = NS_IN6ADDRSZ;
5662fe8fb19SBen Gras 		break;
5672fe8fb19SBen Gras 	default:
568*84d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
5692fe8fb19SBen Gras 		errno = EAFNOSUPPORT;
5702fe8fb19SBen Gras 		return NULL;
5712fe8fb19SBen Gras 	}
572*84d9c625SLionel Sambuc 	if (buflen < size)
573*84d9c625SLionel Sambuc 		goto nospc;
5742fe8fb19SBen Gras 
575*84d9c625SLionel Sambuc 	hp->h_addrtype = af;
576*84d9c625SLionel Sambuc 	hp->h_length = (int)size;
5772fe8fb19SBen Gras 
5782fe8fb19SBen Gras 	/*
5792fe8fb19SBen Gras 	 * if there aren't any dots, it could be a user-level alias.
5802fe8fb19SBen Gras 	 * this is also done in res_nquery() since we are not the only
5812fe8fb19SBen Gras 	 * function that looks up host names.
5822fe8fb19SBen Gras 	 */
5832fe8fb19SBen Gras 	if (!strchr(name, '.') && (cp = __hostalias(name)))
5842fe8fb19SBen Gras 		name = cp;
5852fe8fb19SBen Gras 
5862fe8fb19SBen Gras 	/*
5872fe8fb19SBen Gras 	 * disallow names consisting only of digits/dots, unless
5882fe8fb19SBen Gras 	 * they end in a dot.
5892fe8fb19SBen Gras 	 */
5902fe8fb19SBen Gras 	if (isdigit((u_char) name[0]))
5912fe8fb19SBen Gras 		for (cp = name;; ++cp) {
5922fe8fb19SBen Gras 			if (!*cp) {
5932fe8fb19SBen Gras 				if (*--cp == '.')
5942fe8fb19SBen Gras 					break;
5952fe8fb19SBen Gras 				/*
5962fe8fb19SBen Gras 				 * All-numeric, no dot at the end.
5972fe8fb19SBen Gras 				 * Fake up a hostent as if we'd actually
5982fe8fb19SBen Gras 				 * done a lookup.
5992fe8fb19SBen Gras 				 */
600*84d9c625SLionel Sambuc 				goto fake;
6012fe8fb19SBen Gras 			}
6022fe8fb19SBen Gras 			if (!isdigit((u_char) *cp) && *cp != '.')
6032fe8fb19SBen Gras 				break;
6042fe8fb19SBen Gras 		}
6052fe8fb19SBen Gras 	if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
6062fe8fb19SBen Gras 	    name[0] == ':')
6072fe8fb19SBen Gras 		for (cp = name;; ++cp) {
6082fe8fb19SBen Gras 			if (!*cp) {
6092fe8fb19SBen Gras 				if (*--cp == '.')
6102fe8fb19SBen Gras 					break;
6112fe8fb19SBen Gras 				/*
6122fe8fb19SBen Gras 				 * All-IPv6-legal, no dot at the end.
6132fe8fb19SBen Gras 				 * Fake up a hostent as if we'd actually
6142fe8fb19SBen Gras 				 * done a lookup.
6152fe8fb19SBen Gras 				 */
616*84d9c625SLionel Sambuc 				goto fake;
6172fe8fb19SBen Gras 			}
6182fe8fb19SBen Gras 			if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
6192fe8fb19SBen Gras 				break;
6202fe8fb19SBen Gras 		}
6212fe8fb19SBen Gras 
622*84d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
623*84d9c625SLionel Sambuc 	info.hp = hp;
624*84d9c625SLionel Sambuc 	info.buf = buf;
625*84d9c625SLionel Sambuc 	info.buflen = buflen;
626*84d9c625SLionel Sambuc 	info.he = he;
627*84d9c625SLionel Sambuc 	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
6282fe8fb19SBen Gras 	    default_dns_files, name, strlen(name), af) != NS_SUCCESS)
6292fe8fb19SBen Gras 		return NULL;
630*84d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
631*84d9c625SLionel Sambuc 	return hp;
632*84d9c625SLionel Sambuc nospc:
633*84d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
634*84d9c625SLionel Sambuc 	errno = ENOSPC;
635*84d9c625SLionel Sambuc 	return NULL;
636*84d9c625SLionel Sambuc fake:
637*84d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
638*84d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
639*84d9c625SLionel Sambuc 
640*84d9c625SLionel Sambuc 	hp->h_aliases[0] = NULL;
641*84d9c625SLionel Sambuc 	if (size > buflen)
642*84d9c625SLionel Sambuc 		goto nospc;
643*84d9c625SLionel Sambuc 
644*84d9c625SLionel Sambuc 	if (inet_pton(af, name, buf) <= 0) {
645*84d9c625SLionel Sambuc 		*he = HOST_NOT_FOUND;
646*84d9c625SLionel Sambuc 		return NULL;
647*84d9c625SLionel Sambuc 	}
648*84d9c625SLionel Sambuc 	hp->h_addr_list[0] = buf;
649*84d9c625SLionel Sambuc 	hp->h_addr_list[1] = NULL;
650*84d9c625SLionel Sambuc 	buf += size;
651*84d9c625SLionel Sambuc 	buflen -= size;
652*84d9c625SLionel Sambuc 	HENT_SCOPY(hp->h_name, name, buf, buflen);
653*84d9c625SLionel Sambuc 	if (res->options & RES_USE_INET6)
654*84d9c625SLionel Sambuc 		map_v4v6_hostent(hp, &buf, buf + buflen);
655*84d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
6562fe8fb19SBen Gras 	return hp;
6572fe8fb19SBen Gras }
6582fe8fb19SBen Gras 
6592fe8fb19SBen Gras struct hostent *
660*84d9c625SLionel Sambuc gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
661*84d9c625SLionel Sambuc     char *buf, size_t buflen, int *he)
6622fe8fb19SBen Gras {
6632fe8fb19SBen Gras 	const u_char *uaddr = (const u_char *)addr;
6642fe8fb19SBen Gras 	socklen_t size;
665*84d9c625SLionel Sambuc 	struct getnamaddr info;
6662fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
667*84d9c625SLionel Sambuc 		NS_FILES_CB(_hf_gethtbyaddr, NULL)
6682fe8fb19SBen Gras 		{ NSSRC_DNS, _dns_gethtbyaddr, NULL },	/* force -DHESIOD */
6692fe8fb19SBen Gras 		NS_NIS_CB(_yp_gethtbyaddr, NULL)
6702fe8fb19SBen Gras 		NS_NULL_CB
6712fe8fb19SBen Gras 	};
6722fe8fb19SBen Gras 
6732fe8fb19SBen Gras 	_DIAGASSERT(addr != NULL);
6742fe8fb19SBen Gras 
675*84d9c625SLionel Sambuc 	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
676*84d9c625SLionel Sambuc 	    (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
677*84d9c625SLionel Sambuc 	     IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
678*84d9c625SLionel Sambuc 		*he = HOST_NOT_FOUND;
6792fe8fb19SBen Gras 		return NULL;
6802fe8fb19SBen Gras 	}
681*84d9c625SLionel Sambuc 	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
682*84d9c625SLionel Sambuc 	    (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
683*84d9c625SLionel Sambuc 	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
6842fe8fb19SBen Gras 		/* Unmap. */
685*84d9c625SLionel Sambuc 		uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
686*84d9c625SLionel Sambuc 		addr = uaddr;
6872fe8fb19SBen Gras 		af = AF_INET;
688*84d9c625SLionel Sambuc 		len = NS_INADDRSZ;
6892fe8fb19SBen Gras 	}
6902fe8fb19SBen Gras 	switch (af) {
6912fe8fb19SBen Gras 	case AF_INET:
692*84d9c625SLionel Sambuc 		size = NS_INADDRSZ;
6932fe8fb19SBen Gras 		break;
6942fe8fb19SBen Gras 	case AF_INET6:
695*84d9c625SLionel Sambuc 		size = NS_IN6ADDRSZ;
6962fe8fb19SBen Gras 		break;
6972fe8fb19SBen Gras 	default:
6982fe8fb19SBen Gras 		errno = EAFNOSUPPORT;
699*84d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
7002fe8fb19SBen Gras 		return NULL;
7012fe8fb19SBen Gras 	}
7022fe8fb19SBen Gras 	if (size != len) {
7032fe8fb19SBen Gras 		errno = EINVAL;
704*84d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
7052fe8fb19SBen Gras 		return NULL;
7062fe8fb19SBen Gras 	}
707*84d9c625SLionel Sambuc 	info.hp = hp;
708*84d9c625SLionel Sambuc 	info.buf = buf;
709*84d9c625SLionel Sambuc 	info.buflen = buflen;
710*84d9c625SLionel Sambuc 	info.he = he;
711*84d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
712*84d9c625SLionel Sambuc 	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
7132fe8fb19SBen Gras 	    default_dns_files, uaddr, len, af) != NS_SUCCESS)
7142fe8fb19SBen Gras 		return NULL;
715*84d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
7162fe8fb19SBen Gras 	return hp;
7172fe8fb19SBen Gras }
7182fe8fb19SBen Gras 
7192fe8fb19SBen Gras struct hostent *
720*84d9c625SLionel Sambuc gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
7212fe8fb19SBen Gras {
722*84d9c625SLionel Sambuc 	char *p, *name;
7232fe8fb19SBen Gras 	char *cp, **q;
7242fe8fb19SBen Gras 	int af, len;
725*84d9c625SLionel Sambuc 	size_t llen, anum;
726*84d9c625SLionel Sambuc 	char *aliases[MAXALIASES];
727*84d9c625SLionel Sambuc 	struct in6_addr host_addr;
7282fe8fb19SBen Gras 
729*84d9c625SLionel Sambuc 	if (hf == NULL) {
730*84d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
731*84d9c625SLionel Sambuc 		errno = EINVAL;
7322fe8fb19SBen Gras 		return NULL;
7332fe8fb19SBen Gras 	}
7342fe8fb19SBen Gras  again:
735*84d9c625SLionel Sambuc 	if ((p = fgetln(hf, &llen)) == NULL) {
736*84d9c625SLionel Sambuc 		*he = HOST_NOT_FOUND;
7372fe8fb19SBen Gras 		return NULL;
7382fe8fb19SBen Gras 	}
739*84d9c625SLionel Sambuc 	if (llen < 1)
740*84d9c625SLionel Sambuc 		goto again;
7412fe8fb19SBen Gras 	if (*p == '#')
7422fe8fb19SBen Gras 		goto again;
743*84d9c625SLionel Sambuc 	p[llen] = '\0';
7442fe8fb19SBen Gras 	if (!(cp = strpbrk(p, "#\n")))
7452fe8fb19SBen Gras 		goto again;
7462fe8fb19SBen Gras 	*cp = '\0';
7472fe8fb19SBen Gras 	if (!(cp = strpbrk(p, " \t")))
7482fe8fb19SBen Gras 		goto again;
7492fe8fb19SBen Gras 	*cp++ = '\0';
750*84d9c625SLionel Sambuc 	if (inet_pton(AF_INET6, p, &host_addr) > 0) {
7512fe8fb19SBen Gras 		af = AF_INET6;
752*84d9c625SLionel Sambuc 		len = NS_IN6ADDRSZ;
753*84d9c625SLionel Sambuc 	} else if (inet_pton(AF_INET, p, &host_addr) > 0) {
7542fe8fb19SBen Gras 		res_state res = __res_get_state();
7552fe8fb19SBen Gras 		if (res == NULL)
7562fe8fb19SBen Gras 			return NULL;
7572fe8fb19SBen Gras 		if (res->options & RES_USE_INET6) {
758*84d9c625SLionel Sambuc 			map_v4v6_address(buf, buf);
7592fe8fb19SBen Gras 			af = AF_INET6;
760*84d9c625SLionel Sambuc 			len = NS_IN6ADDRSZ;
7612fe8fb19SBen Gras 		} else {
7622fe8fb19SBen Gras 			af = AF_INET;
763*84d9c625SLionel Sambuc 			len = NS_INADDRSZ;
7642fe8fb19SBen Gras 		}
7652fe8fb19SBen Gras 		__res_put_state(res);
7662fe8fb19SBen Gras 	} else {
7672fe8fb19SBen Gras 		goto again;
7682fe8fb19SBen Gras 	}
7692fe8fb19SBen Gras 	/* if this is not something we're looking for, skip it. */
770*84d9c625SLionel Sambuc 	if (hent->h_addrtype != 0 && hent->h_addrtype != af)
7712fe8fb19SBen Gras 		goto again;
772*84d9c625SLionel Sambuc 	if (hent->h_length != 0 && hent->h_length != len)
7732fe8fb19SBen Gras 		goto again;
774*84d9c625SLionel Sambuc 
7752fe8fb19SBen Gras 	while (*cp == ' ' || *cp == '\t')
7762fe8fb19SBen Gras 		cp++;
777*84d9c625SLionel Sambuc 	if ((cp = strpbrk(name = cp, " \t")) != NULL)
7782fe8fb19SBen Gras 		*cp++ = '\0';
779*84d9c625SLionel Sambuc 	q = aliases;
7802fe8fb19SBen Gras 	while (cp && *cp) {
7812fe8fb19SBen Gras 		if (*cp == ' ' || *cp == '\t') {
7822fe8fb19SBen Gras 			cp++;
7832fe8fb19SBen Gras 			continue;
7842fe8fb19SBen Gras 		}
785*84d9c625SLionel Sambuc 		if (q >= &aliases[__arraycount(aliases)])
786*84d9c625SLionel Sambuc 			goto nospc;
7872fe8fb19SBen Gras 		*q++ = cp;
7882fe8fb19SBen Gras 		if ((cp = strpbrk(cp, " \t")) != NULL)
7892fe8fb19SBen Gras 			*cp++ = '\0';
7902fe8fb19SBen Gras 	}
791*84d9c625SLionel Sambuc 	hent->h_length = len;
792*84d9c625SLionel Sambuc 	hent->h_addrtype = af;
793*84d9c625SLionel Sambuc 	HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
794*84d9c625SLionel Sambuc 	anum = (size_t)(q - aliases);
795*84d9c625SLionel Sambuc 	HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
796*84d9c625SLionel Sambuc 	HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
797*84d9c625SLionel Sambuc 	    buflen);
798*84d9c625SLionel Sambuc 	hent->h_addr_list[1] = NULL;
7992fe8fb19SBen Gras 
800*84d9c625SLionel Sambuc 	HENT_SCOPY(hent->h_name, name, buf, buflen);
801*84d9c625SLionel Sambuc 	for (size_t i = 0; i < anum; i++)
802*84d9c625SLionel Sambuc 		HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
803*84d9c625SLionel Sambuc 	hent->h_aliases[anum] = NULL;
8042fe8fb19SBen Gras 
805*84d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
806*84d9c625SLionel Sambuc 	return hent;
807*84d9c625SLionel Sambuc nospc:
8082fe8fb19SBen Gras 	errno = ENOSPC;
809*84d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
8102fe8fb19SBen Gras 	return NULL;
8112fe8fb19SBen Gras }
8122fe8fb19SBen Gras 
8132fe8fb19SBen Gras static void
8142fe8fb19SBen Gras map_v4v6_address(const char *src, char *dst)
8152fe8fb19SBen Gras {
8162fe8fb19SBen Gras 	u_char *p = (u_char *)dst;
817*84d9c625SLionel Sambuc 	char tmp[NS_INADDRSZ];
8182fe8fb19SBen Gras 	int i;
8192fe8fb19SBen Gras 
8202fe8fb19SBen Gras 	_DIAGASSERT(src != NULL);
8212fe8fb19SBen Gras 	_DIAGASSERT(dst != NULL);
8222fe8fb19SBen Gras 
8232fe8fb19SBen Gras 	/* Stash a temporary copy so our caller can update in place. */
824*84d9c625SLionel Sambuc 	(void)memcpy(tmp, src, NS_INADDRSZ);
8252fe8fb19SBen Gras 	/* Mark this ipv6 addr as a mapped ipv4. */
8262fe8fb19SBen Gras 	for (i = 0; i < 10; i++)
8272fe8fb19SBen Gras 		*p++ = 0x00;
8282fe8fb19SBen Gras 	*p++ = 0xff;
8292fe8fb19SBen Gras 	*p++ = 0xff;
8302fe8fb19SBen Gras 	/* Retrieve the saved copy and we're done. */
831*84d9c625SLionel Sambuc 	(void)memcpy(p, tmp, NS_INADDRSZ);
8322fe8fb19SBen Gras }
8332fe8fb19SBen Gras 
8342fe8fb19SBen Gras static void
8352fe8fb19SBen Gras map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
8362fe8fb19SBen Gras {
8372fe8fb19SBen Gras 	char **ap;
8382fe8fb19SBen Gras 
8392fe8fb19SBen Gras 	_DIAGASSERT(hp != NULL);
8402fe8fb19SBen Gras 	_DIAGASSERT(bpp != NULL);
8412fe8fb19SBen Gras 	_DIAGASSERT(ep != NULL);
8422fe8fb19SBen Gras 
843*84d9c625SLionel Sambuc 	if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
8442fe8fb19SBen Gras 		return;
8452fe8fb19SBen Gras 	hp->h_addrtype = AF_INET6;
846*84d9c625SLionel Sambuc 	hp->h_length = NS_IN6ADDRSZ;
8472fe8fb19SBen Gras 	for (ap = hp->h_addr_list; *ap; ap++) {
848f14fb602SLionel Sambuc 		int i = (int)(sizeof(align) -
849f14fb602SLionel Sambuc 		    (size_t)((u_long)*bpp % sizeof(align)));
8502fe8fb19SBen Gras 
851*84d9c625SLionel Sambuc 		if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
8522fe8fb19SBen Gras 			/* Out of memory.  Truncate address list here.  XXX */
8532fe8fb19SBen Gras 			*ap = NULL;
8542fe8fb19SBen Gras 			return;
8552fe8fb19SBen Gras 		}
8562fe8fb19SBen Gras 		*bpp += i;
8572fe8fb19SBen Gras 		map_v4v6_address(*ap, *bpp);
8582fe8fb19SBen Gras 		*ap = *bpp;
859*84d9c625SLionel Sambuc 		*bpp += NS_IN6ADDRSZ;
8602fe8fb19SBen Gras 	}
8612fe8fb19SBen Gras }
8622fe8fb19SBen Gras 
8632fe8fb19SBen Gras static void
8642fe8fb19SBen Gras addrsort(char **ap, int num, res_state res)
8652fe8fb19SBen Gras {
8662fe8fb19SBen Gras 	int i, j;
8672fe8fb19SBen Gras 	char **p;
8682fe8fb19SBen Gras 	short aval[MAXADDRS];
8692fe8fb19SBen Gras 	int needsort = 0;
8702fe8fb19SBen Gras 
8712fe8fb19SBen Gras 	_DIAGASSERT(ap != NULL);
8722fe8fb19SBen Gras 
8732fe8fb19SBen Gras 	p = ap;
8742fe8fb19SBen Gras 	for (i = 0; i < num; i++, p++) {
8752fe8fb19SBen Gras 	    for (j = 0 ; (unsigned)j < res->nsort; j++)
8762fe8fb19SBen Gras 		if (res->sort_list[j].addr.s_addr ==
8772fe8fb19SBen Gras 		    (((struct in_addr *)(void *)(*p))->s_addr &
8782fe8fb19SBen Gras 		    res->sort_list[j].mask))
8792fe8fb19SBen Gras 			break;
8802fe8fb19SBen Gras 	    aval[i] = j;
8812fe8fb19SBen Gras 	    if (needsort == 0 && i > 0 && j < aval[i-1])
8822fe8fb19SBen Gras 		needsort = i;
8832fe8fb19SBen Gras 	}
8842fe8fb19SBen Gras 	if (!needsort)
8852fe8fb19SBen Gras 	    return;
8862fe8fb19SBen Gras 
8872fe8fb19SBen Gras 	while (needsort < num) {
8882fe8fb19SBen Gras 	    for (j = needsort - 1; j >= 0; j--) {
8892fe8fb19SBen Gras 		if (aval[j] > aval[j+1]) {
8902fe8fb19SBen Gras 		    char *hp;
8912fe8fb19SBen Gras 
8922fe8fb19SBen Gras 		    i = aval[j];
8932fe8fb19SBen Gras 		    aval[j] = aval[j+1];
8942fe8fb19SBen Gras 		    aval[j+1] = i;
8952fe8fb19SBen Gras 
8962fe8fb19SBen Gras 		    hp = ap[j];
8972fe8fb19SBen Gras 		    ap[j] = ap[j+1];
8982fe8fb19SBen Gras 		    ap[j+1] = hp;
8992fe8fb19SBen Gras 		} else
9002fe8fb19SBen Gras 		    break;
9012fe8fb19SBen Gras 	    }
9022fe8fb19SBen Gras 	    needsort++;
9032fe8fb19SBen Gras 	}
9042fe8fb19SBen Gras }
9052fe8fb19SBen Gras 
9062fe8fb19SBen Gras 
9072fe8fb19SBen Gras /*ARGSUSED*/
9082fe8fb19SBen Gras int
9092fe8fb19SBen Gras _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
9102fe8fb19SBen Gras {
9112fe8fb19SBen Gras 	querybuf *buf;
9122fe8fb19SBen Gras 	int n, type;
9132fe8fb19SBen Gras 	struct hostent *hp;
9142fe8fb19SBen Gras 	const char *name;
9152fe8fb19SBen Gras 	res_state res;
916*84d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
9172fe8fb19SBen Gras 
9182fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
9192fe8fb19SBen Gras 
9202fe8fb19SBen Gras 	name = va_arg(ap, char *);
921*84d9c625SLionel Sambuc 	/* NOSTRICT skip string len */(void)va_arg(ap, int);
922*84d9c625SLionel Sambuc 	info->hp->h_addrtype = va_arg(ap, int);
9232fe8fb19SBen Gras 
924*84d9c625SLionel Sambuc 	switch (info->hp->h_addrtype) {
9252fe8fb19SBen Gras 	case AF_INET:
926*84d9c625SLionel Sambuc 		info->hp->h_length = NS_INADDRSZ;
9272fe8fb19SBen Gras 		type = T_A;
9282fe8fb19SBen Gras 		break;
9292fe8fb19SBen Gras 	case AF_INET6:
930*84d9c625SLionel Sambuc 		info->hp->h_length = NS_IN6ADDRSZ;
9312fe8fb19SBen Gras 		type = T_AAAA;
9322fe8fb19SBen Gras 		break;
9332fe8fb19SBen Gras 	default:
9342fe8fb19SBen Gras 		return NS_UNAVAIL;
9352fe8fb19SBen Gras 	}
9362fe8fb19SBen Gras 	buf = malloc(sizeof(*buf));
9372fe8fb19SBen Gras 	if (buf == NULL) {
938*84d9c625SLionel Sambuc 		*info->he = NETDB_INTERNAL;
9392fe8fb19SBen Gras 		return NS_NOTFOUND;
9402fe8fb19SBen Gras 	}
9412fe8fb19SBen Gras 	res = __res_get_state();
9422fe8fb19SBen Gras 	if (res == NULL) {
9432fe8fb19SBen Gras 		free(buf);
9442fe8fb19SBen Gras 		return NS_NOTFOUND;
9452fe8fb19SBen Gras 	}
946f14fb602SLionel Sambuc 	n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
9472fe8fb19SBen Gras 	if (n < 0) {
9482fe8fb19SBen Gras 		free(buf);
9492fe8fb19SBen Gras 		debugprintf("res_nsearch failed (%d)\n", res, n);
9502fe8fb19SBen Gras 		__res_put_state(res);
9512fe8fb19SBen Gras 		return NS_NOTFOUND;
9522fe8fb19SBen Gras 	}
953*84d9c625SLionel Sambuc 	hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
954*84d9c625SLionel Sambuc 	    info->buflen, info->he);
9552fe8fb19SBen Gras 	free(buf);
9562fe8fb19SBen Gras 	__res_put_state(res);
9572fe8fb19SBen Gras 	if (hp == NULL)
9582fe8fb19SBen Gras 		switch (h_errno) {
9592fe8fb19SBen Gras 		case HOST_NOT_FOUND:
9602fe8fb19SBen Gras 			return NS_NOTFOUND;
9612fe8fb19SBen Gras 		case TRY_AGAIN:
9622fe8fb19SBen Gras 			return NS_TRYAGAIN;
9632fe8fb19SBen Gras 		default:
9642fe8fb19SBen Gras 			return NS_UNAVAIL;
9652fe8fb19SBen Gras 		}
9662fe8fb19SBen Gras 	return NS_SUCCESS;
9672fe8fb19SBen Gras }
9682fe8fb19SBen Gras 
9692fe8fb19SBen Gras /*ARGSUSED*/
9702fe8fb19SBen Gras int
9712fe8fb19SBen Gras _dns_gethtbyaddr(void *rv, void	*cb_data, va_list ap)
9722fe8fb19SBen Gras {
9732fe8fb19SBen Gras 	char qbuf[MAXDNAME + 1], *qp, *ep;
9742fe8fb19SBen Gras 	int n;
9752fe8fb19SBen Gras 	querybuf *buf;
9762fe8fb19SBen Gras 	struct hostent *hp;
9772fe8fb19SBen Gras 	const unsigned char *uaddr;
978*84d9c625SLionel Sambuc 	int advance;
9792fe8fb19SBen Gras 	res_state res;
980*84d9c625SLionel Sambuc 	char *bf;
981*84d9c625SLionel Sambuc 	size_t blen;
982*84d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
9832fe8fb19SBen Gras 
9842fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
9852fe8fb19SBen Gras 
9862fe8fb19SBen Gras 	uaddr = va_arg(ap, unsigned char *);
987*84d9c625SLionel Sambuc 	info->hp->h_length = va_arg(ap, int);
988*84d9c625SLionel Sambuc 	info->hp->h_addrtype = va_arg(ap, int);
9892fe8fb19SBen Gras 
990*84d9c625SLionel Sambuc 	switch (info->hp->h_addrtype) {
9912fe8fb19SBen Gras 	case AF_INET:
9922fe8fb19SBen Gras 		(void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
9932fe8fb19SBen Gras 		    (uaddr[3] & 0xff), (uaddr[2] & 0xff),
9942fe8fb19SBen Gras 		    (uaddr[1] & 0xff), (uaddr[0] & 0xff));
9952fe8fb19SBen Gras 		break;
9962fe8fb19SBen Gras 
9972fe8fb19SBen Gras 	case AF_INET6:
9982fe8fb19SBen Gras 		qp = qbuf;
9992fe8fb19SBen Gras 		ep = qbuf + sizeof(qbuf) - 1;
1000*84d9c625SLionel Sambuc 		for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
10012fe8fb19SBen Gras 			advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
10022fe8fb19SBen Gras 			    uaddr[n] & 0xf,
10032fe8fb19SBen Gras 			    ((unsigned int)uaddr[n] >> 4) & 0xf);
10042fe8fb19SBen Gras 			if (advance > 0 && qp + advance < ep)
10052fe8fb19SBen Gras 				qp += advance;
10062fe8fb19SBen Gras 			else {
1007*84d9c625SLionel Sambuc 				*info->he = NETDB_INTERNAL;
10082fe8fb19SBen Gras 				return NS_NOTFOUND;
10092fe8fb19SBen Gras 			}
10102fe8fb19SBen Gras 		}
10112fe8fb19SBen Gras 		if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
1012*84d9c625SLionel Sambuc 			*info->he = NETDB_INTERNAL;
10132fe8fb19SBen Gras 			return NS_NOTFOUND;
10142fe8fb19SBen Gras 		}
10152fe8fb19SBen Gras 		break;
10162fe8fb19SBen Gras 	default:
1017*84d9c625SLionel Sambuc 		return NS_UNAVAIL;
10182fe8fb19SBen Gras 	}
10192fe8fb19SBen Gras 
10202fe8fb19SBen Gras 	buf = malloc(sizeof(*buf));
10212fe8fb19SBen Gras 	if (buf == NULL) {
1022*84d9c625SLionel Sambuc 		*info->he = NETDB_INTERNAL;
10232fe8fb19SBen Gras 		return NS_NOTFOUND;
10242fe8fb19SBen Gras 	}
10252fe8fb19SBen Gras 	res = __res_get_state();
10262fe8fb19SBen Gras 	if (res == NULL) {
10272fe8fb19SBen Gras 		free(buf);
10282fe8fb19SBen Gras 		return NS_NOTFOUND;
10292fe8fb19SBen Gras 	}
1030f14fb602SLionel Sambuc 	n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
10312fe8fb19SBen Gras 	if (n < 0) {
10322fe8fb19SBen Gras 		free(buf);
10332fe8fb19SBen Gras 		debugprintf("res_nquery failed (%d)\n", res, n);
10342fe8fb19SBen Gras 		__res_put_state(res);
10352fe8fb19SBen Gras 		return NS_NOTFOUND;
10362fe8fb19SBen Gras 	}
1037*84d9c625SLionel Sambuc 	hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
1038*84d9c625SLionel Sambuc 	    info->buflen, info->he);
10392fe8fb19SBen Gras 	free(buf);
10402fe8fb19SBen Gras 	if (hp == NULL) {
10412fe8fb19SBen Gras 		__res_put_state(res);
1042*84d9c625SLionel Sambuc 		switch (*info->he) {
10432fe8fb19SBen Gras 		case HOST_NOT_FOUND:
10442fe8fb19SBen Gras 			return NS_NOTFOUND;
10452fe8fb19SBen Gras 		case TRY_AGAIN:
10462fe8fb19SBen Gras 			return NS_TRYAGAIN;
10472fe8fb19SBen Gras 		default:
10482fe8fb19SBen Gras 			return NS_UNAVAIL;
10492fe8fb19SBen Gras 		}
10502fe8fb19SBen Gras 	}
1051*84d9c625SLionel Sambuc 
1052*84d9c625SLionel Sambuc 	bf = (void *)(hp->h_addr_list + 2);
1053*84d9c625SLionel Sambuc 	blen = (size_t)(bf - info->buf);
1054*84d9c625SLionel Sambuc 	if (blen + info->hp->h_length > info->buflen)
1055*84d9c625SLionel Sambuc 		goto nospc;
1056*84d9c625SLionel Sambuc 	hp->h_addr_list[0] = bf;
1057*84d9c625SLionel Sambuc 	hp->h_addr_list[1] = NULL;
1058*84d9c625SLionel Sambuc 	(void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
1059*84d9c625SLionel Sambuc 	if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1060*84d9c625SLionel Sambuc 		if (blen + NS_IN6ADDRSZ > info->buflen)
1061*84d9c625SLionel Sambuc 			goto nospc;
1062*84d9c625SLionel Sambuc 		map_v4v6_address(bf, bf);
10632fe8fb19SBen Gras 		hp->h_addrtype = AF_INET6;
1064*84d9c625SLionel Sambuc 		hp->h_length = NS_IN6ADDRSZ;
10652fe8fb19SBen Gras 	}
10662fe8fb19SBen Gras 
10672fe8fb19SBen Gras 	__res_put_state(res);
1068*84d9c625SLionel Sambuc 	*info->he = NETDB_SUCCESS;
10692fe8fb19SBen Gras 	return NS_SUCCESS;
1070*84d9c625SLionel Sambuc nospc:
1071*84d9c625SLionel Sambuc 	*info->he = NETDB_INTERNAL;
1072*84d9c625SLionel Sambuc 	return NS_UNAVAIL;
10732fe8fb19SBen Gras }
10742fe8fb19SBen Gras 
10752fe8fb19SBen Gras #ifdef YP
10762fe8fb19SBen Gras /*ARGSUSED*/
1077*84d9c625SLionel Sambuc static struct hostent *
1078*84d9c625SLionel Sambuc _yp_hostent(char *line, int af, struct getnamaddr *info)
10792fe8fb19SBen Gras {
1080*84d9c625SLionel Sambuc 	struct in6_addr host_addrs[MAXADDRS];
1081*84d9c625SLionel Sambuc 	char *aliases[MAXALIASES];
10822fe8fb19SBen Gras 	char *p = line;
1083*84d9c625SLionel Sambuc 	char *cp, **q, *ptr;
1084*84d9c625SLionel Sambuc 	size_t len, anum, i;
10852fe8fb19SBen Gras 	int addrok;
10862fe8fb19SBen Gras 	int more;
10872fe8fb19SBen Gras 	size_t naddrs;
1088*84d9c625SLionel Sambuc 	struct hostent *hp = info->hp;
10892fe8fb19SBen Gras 
10902fe8fb19SBen Gras 	_DIAGASSERT(line != NULL);
10912fe8fb19SBen Gras 
1092*84d9c625SLionel Sambuc 	hp->h_name = NULL;
1093*84d9c625SLionel Sambuc 	hp->h_addrtype = af;
10942fe8fb19SBen Gras 	switch (af) {
10952fe8fb19SBen Gras 	case AF_INET:
1096*84d9c625SLionel Sambuc 		hp->h_length = NS_INADDRSZ;
10972fe8fb19SBen Gras 		break;
10982fe8fb19SBen Gras 	case AF_INET6:
1099*84d9c625SLionel Sambuc 		hp->h_length = NS_IN6ADDRSZ;
11002fe8fb19SBen Gras 		break;
11012fe8fb19SBen Gras 	default:
11022fe8fb19SBen Gras 		return NULL;
11032fe8fb19SBen Gras 	}
11042fe8fb19SBen Gras 	naddrs = 0;
1105*84d9c625SLionel Sambuc 	q = aliases;
11062fe8fb19SBen Gras 
11072fe8fb19SBen Gras nextline:
11082fe8fb19SBen Gras 	/* check for host_addrs overflow */
1109*84d9c625SLionel Sambuc 	if (naddrs >= __arraycount(host_addrs))
11102fe8fb19SBen Gras 		goto done;
11112fe8fb19SBen Gras 
11122fe8fb19SBen Gras 	more = 0;
11132fe8fb19SBen Gras 	cp = strpbrk(p, " \t");
11142fe8fb19SBen Gras 	if (cp == NULL)
11152fe8fb19SBen Gras 		goto done;
11162fe8fb19SBen Gras 	*cp++ = '\0';
11172fe8fb19SBen Gras 
11182fe8fb19SBen Gras 	/* p has should have an address */
1119*84d9c625SLionel Sambuc 	addrok = inet_pton(af, p, &host_addrs[naddrs]);
11202fe8fb19SBen Gras 	if (addrok != 1) {
11212fe8fb19SBen Gras 		/* skip to the next line */
11222fe8fb19SBen Gras 		while (cp && *cp) {
11232fe8fb19SBen Gras 			if (*cp == '\n') {
11242fe8fb19SBen Gras 				cp++;
11252fe8fb19SBen Gras 				goto nextline;
11262fe8fb19SBen Gras 			}
11272fe8fb19SBen Gras 			cp++;
11282fe8fb19SBen Gras 		}
11292fe8fb19SBen Gras 		goto done;
11302fe8fb19SBen Gras 	}
11312fe8fb19SBen Gras 
11322fe8fb19SBen Gras 	while (*cp == ' ' || *cp == '\t')
11332fe8fb19SBen Gras 		cp++;
11342fe8fb19SBen Gras 	p = cp;
11352fe8fb19SBen Gras 	cp = strpbrk(p, " \t\n");
11362fe8fb19SBen Gras 	if (cp != NULL) {
11372fe8fb19SBen Gras 		if (*cp == '\n')
11382fe8fb19SBen Gras 			more = 1;
11392fe8fb19SBen Gras 		*cp++ = '\0';
11402fe8fb19SBen Gras 	}
1141*84d9c625SLionel Sambuc 	if (!hp->h_name)
1142*84d9c625SLionel Sambuc 		hp->h_name = p;
1143*84d9c625SLionel Sambuc 	else if (strcmp(hp->h_name, p) == 0)
11442fe8fb19SBen Gras 		;
1145*84d9c625SLionel Sambuc 	else if (q < &aliases[MAXALIASES - 1])
11462fe8fb19SBen Gras 		*q++ = p;
11472fe8fb19SBen Gras 	p = cp;
11482fe8fb19SBen Gras 	if (more)
11492fe8fb19SBen Gras 		goto nextline;
11502fe8fb19SBen Gras 
11512fe8fb19SBen Gras 	while (cp && *cp) {
11522fe8fb19SBen Gras 		if (*cp == ' ' || *cp == '\t') {
11532fe8fb19SBen Gras 			cp++;
11542fe8fb19SBen Gras 			continue;
11552fe8fb19SBen Gras 		}
11562fe8fb19SBen Gras 		if (*cp == '\n') {
11572fe8fb19SBen Gras 			cp++;
11582fe8fb19SBen Gras 			goto nextline;
11592fe8fb19SBen Gras 		}
1160*84d9c625SLionel Sambuc 		if (q < &aliases[MAXALIASES - 1])
11612fe8fb19SBen Gras 			*q++ = cp;
11622fe8fb19SBen Gras 		cp = strpbrk(cp, " \t");
11632fe8fb19SBen Gras 		if (cp != NULL)
11642fe8fb19SBen Gras 			*cp++ = '\0';
11652fe8fb19SBen Gras 	}
11662fe8fb19SBen Gras 
11672fe8fb19SBen Gras done:
1168*84d9c625SLionel Sambuc 	if (hp->h_name == NULL)
11692fe8fb19SBen Gras 		return NULL;
1170*84d9c625SLionel Sambuc 
1171*84d9c625SLionel Sambuc 	ptr = info->buf;
1172*84d9c625SLionel Sambuc 	len = info->buflen;
1173*84d9c625SLionel Sambuc 
1174*84d9c625SLionel Sambuc 	anum = (size_t)(q - aliases);
1175*84d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1176*84d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_aliases, anum, ptr, len);
1177*84d9c625SLionel Sambuc 
1178*84d9c625SLionel Sambuc 	for (i = 0; i < naddrs; i++)
1179*84d9c625SLionel Sambuc 		HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
1180*84d9c625SLionel Sambuc 		    ptr, len);
1181*84d9c625SLionel Sambuc 	hp->h_addr_list[naddrs] = NULL;
1182*84d9c625SLionel Sambuc 
1183*84d9c625SLionel Sambuc 	HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
1184*84d9c625SLionel Sambuc 
1185*84d9c625SLionel Sambuc 	for (i = 0; i < anum; i++)
1186*84d9c625SLionel Sambuc 		HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1187*84d9c625SLionel Sambuc 	hp->h_aliases[anum] = NULL;
1188*84d9c625SLionel Sambuc 
1189*84d9c625SLionel Sambuc 	return hp;
1190*84d9c625SLionel Sambuc nospc:
1191*84d9c625SLionel Sambuc 	*info->he = NETDB_INTERNAL;
1192*84d9c625SLionel Sambuc 	errno = ENOSPC;
1193*84d9c625SLionel Sambuc 	return NULL;
11942fe8fb19SBen Gras }
11952fe8fb19SBen Gras 
11962fe8fb19SBen Gras /*ARGSUSED*/
11972fe8fb19SBen Gras int
11982fe8fb19SBen Gras _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
11992fe8fb19SBen Gras {
12002fe8fb19SBen Gras 	struct hostent *hp = NULL;
1201*84d9c625SLionel Sambuc 	char *ypcurrent;
1202*84d9c625SLionel Sambuc 	int ypcurrentlen, r;
12032fe8fb19SBen Gras 	char name[INET6_ADDRSTRLEN];	/* XXX enough? */
12042fe8fb19SBen Gras 	const unsigned char *uaddr;
12052fe8fb19SBen Gras 	int af;
12062fe8fb19SBen Gras 	const char *map;
1207*84d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
12082fe8fb19SBen Gras 
12092fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
12102fe8fb19SBen Gras 
12112fe8fb19SBen Gras 	uaddr = va_arg(ap, unsigned char *);
12122fe8fb19SBen Gras 	/* NOSTRICT skip len */(void)va_arg(ap, int);
12132fe8fb19SBen Gras 	af = va_arg(ap, int);
12142fe8fb19SBen Gras 
12152fe8fb19SBen Gras 	if (!__ypdomain) {
12162fe8fb19SBen Gras 		if (_yp_check(&__ypdomain) == 0)
12172fe8fb19SBen Gras 			return NS_UNAVAIL;
12182fe8fb19SBen Gras 	}
12192fe8fb19SBen Gras 	/*
12202fe8fb19SBen Gras 	 * XXX unfortunately, we cannot support IPv6 extended scoped address
12212fe8fb19SBen Gras 	 * notation here.  gethostbyaddr() is not scope-aware.  too bad.
12222fe8fb19SBen Gras 	 */
1223f14fb602SLionel Sambuc 	if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
12242fe8fb19SBen Gras 		return NS_UNAVAIL;
12252fe8fb19SBen Gras 	switch (af) {
12262fe8fb19SBen Gras 	case AF_INET:
12272fe8fb19SBen Gras 		map = "hosts.byaddr";
12282fe8fb19SBen Gras 		break;
12292fe8fb19SBen Gras 	default:
12302fe8fb19SBen Gras 		map = "ipnodes.byaddr";
12312fe8fb19SBen Gras 		break;
12322fe8fb19SBen Gras 	}
1233*84d9c625SLionel Sambuc 	ypcurrent = NULL;
12342fe8fb19SBen Gras 	r = yp_match(__ypdomain, map, name,
1235*84d9c625SLionel Sambuc 		(int)strlen(name), &ypcurrent, &ypcurrentlen);
12362fe8fb19SBen Gras 	if (r == 0)
1237*84d9c625SLionel Sambuc 		hp = _yp_hostent(ypcurrent, af, info);
1238*84d9c625SLionel Sambuc 	else
1239*84d9c625SLionel Sambuc 		hp = NULL;
1240*84d9c625SLionel Sambuc 	free(ypcurrent);
12412fe8fb19SBen Gras 	if (hp == NULL) {
1242*84d9c625SLionel Sambuc 		*info->he = HOST_NOT_FOUND;
12432fe8fb19SBen Gras 		return NS_NOTFOUND;
12442fe8fb19SBen Gras 	}
12452fe8fb19SBen Gras 	return NS_SUCCESS;
12462fe8fb19SBen Gras }
12472fe8fb19SBen Gras 
12482fe8fb19SBen Gras /*ARGSUSED*/
12492fe8fb19SBen Gras int
12502fe8fb19SBen Gras _yp_gethtbyname(void *rv, void *cb_data, va_list ap)
12512fe8fb19SBen Gras {
1252*84d9c625SLionel Sambuc 	struct hostent *hp;
1253*84d9c625SLionel Sambuc 	char *ypcurrent;
1254*84d9c625SLionel Sambuc 	int ypcurrentlen, r;
12552fe8fb19SBen Gras 	const char *name;
12562fe8fb19SBen Gras 	int af;
12572fe8fb19SBen Gras 	const char *map;
1258*84d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
12592fe8fb19SBen Gras 
12602fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
12612fe8fb19SBen Gras 
12622fe8fb19SBen Gras 	name = va_arg(ap, char *);
1263*84d9c625SLionel Sambuc 	/* NOSTRICT skip string len */(void)va_arg(ap, int);
12642fe8fb19SBen Gras 	af = va_arg(ap, int);
12652fe8fb19SBen Gras 
12662fe8fb19SBen Gras 	if (!__ypdomain) {
12672fe8fb19SBen Gras 		if (_yp_check(&__ypdomain) == 0)
12682fe8fb19SBen Gras 			return NS_UNAVAIL;
12692fe8fb19SBen Gras 	}
12702fe8fb19SBen Gras 	switch (af) {
12712fe8fb19SBen Gras 	case AF_INET:
12722fe8fb19SBen Gras 		map = "hosts.byname";
12732fe8fb19SBen Gras 		break;
12742fe8fb19SBen Gras 	default:
12752fe8fb19SBen Gras 		map = "ipnodes.byname";
12762fe8fb19SBen Gras 		break;
12772fe8fb19SBen Gras 	}
1278*84d9c625SLionel Sambuc 	ypcurrent = NULL;
12792fe8fb19SBen Gras 	r = yp_match(__ypdomain, map, name,
1280*84d9c625SLionel Sambuc 		(int)strlen(name), &ypcurrent, &ypcurrentlen);
12812fe8fb19SBen Gras 	if (r == 0)
1282*84d9c625SLionel Sambuc 		hp = _yp_hostent(ypcurrent, af, info);
1283*84d9c625SLionel Sambuc 	else
1284*84d9c625SLionel Sambuc 		hp = NULL;
1285*84d9c625SLionel Sambuc 	free(ypcurrent);
12862fe8fb19SBen Gras 	if (hp == NULL) {
1287*84d9c625SLionel Sambuc 		*info->he = HOST_NOT_FOUND;
12882fe8fb19SBen Gras 		return NS_NOTFOUND;
12892fe8fb19SBen Gras 	}
12902fe8fb19SBen Gras 	return NS_SUCCESS;
12912fe8fb19SBen Gras }
12922fe8fb19SBen Gras #endif
1293*84d9c625SLionel Sambuc 
1294*84d9c625SLionel Sambuc /*
1295*84d9c625SLionel Sambuc  * Non-reentrant versions.
1296*84d9c625SLionel Sambuc  */
1297*84d9c625SLionel Sambuc FILE *_h_file;
1298*84d9c625SLionel Sambuc static struct hostent h_ent;
1299*84d9c625SLionel Sambuc static char h_buf[16384];
1300*84d9c625SLionel Sambuc 
1301*84d9c625SLionel Sambuc struct hostent *
1302*84d9c625SLionel Sambuc gethostbyaddr(const void *addr, socklen_t len, int af) {
1303*84d9c625SLionel Sambuc 	return gethostbyaddr_r(addr, len, af, &h_ent, h_buf, sizeof(h_buf),
1304*84d9c625SLionel Sambuc 	    &h_errno);
1305*84d9c625SLionel Sambuc }
1306*84d9c625SLionel Sambuc 
1307*84d9c625SLionel Sambuc struct hostent *
1308*84d9c625SLionel Sambuc gethostbyname(const char *name) {
1309*84d9c625SLionel Sambuc 	return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno);
1310*84d9c625SLionel Sambuc }
1311*84d9c625SLionel Sambuc 
1312*84d9c625SLionel Sambuc struct hostent *
1313*84d9c625SLionel Sambuc gethostbyname2(const char *name, int af) {
1314*84d9c625SLionel Sambuc 	return gethostbyname2_r(name, af, &h_ent, h_buf, sizeof(h_buf),
1315*84d9c625SLionel Sambuc 	    &h_errno);
1316*84d9c625SLionel Sambuc }
1317*84d9c625SLionel Sambuc 
1318*84d9c625SLionel Sambuc struct hostent *
1319*84d9c625SLionel Sambuc gethostent(void)
1320*84d9c625SLionel Sambuc {
1321*84d9c625SLionel Sambuc 	if (_h_file == NULL) {
1322*84d9c625SLionel Sambuc 		sethostent_r(&_h_file);
1323*84d9c625SLionel Sambuc 		if (_h_file == NULL) {
1324*84d9c625SLionel Sambuc 			h_errno = NETDB_INTERNAL;
1325*84d9c625SLionel Sambuc 			return NULL;
1326*84d9c625SLionel Sambuc 		}
1327*84d9c625SLionel Sambuc 	}
1328*84d9c625SLionel Sambuc 	memset(&h_ent, 0, sizeof(h_ent));
1329*84d9c625SLionel Sambuc 	return gethostent_r(_h_file, &h_ent, h_buf, sizeof(h_buf), &h_errno);
1330*84d9c625SLionel Sambuc }
1331*84d9c625SLionel Sambuc 
1332