xref: /minix/lib/libc/net/gethnamaddr.c (revision 0a6a1f1d)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 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*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 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 
9884d9c625SLionel Sambuc #include "hostent.h"
9984d9c625SLionel 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 
111*0a6a1f1dSLionel Sambuc #define addalias(d, s, arr, siz) do {			\
112*0a6a1f1dSLionel Sambuc 	if (d >= &arr[siz]) {				\
113*0a6a1f1dSLionel Sambuc 		char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
114*0a6a1f1dSLionel Sambuc 		if (xptr == NULL)			\
115*0a6a1f1dSLionel Sambuc 			goto nospc;			\
116*0a6a1f1dSLionel Sambuc 		d = xptr + (d - arr);			\
117*0a6a1f1dSLionel Sambuc 		arr = xptr;				\
118*0a6a1f1dSLionel Sambuc 		siz += 10;				\
119*0a6a1f1dSLionel Sambuc 	}						\
120*0a6a1f1dSLionel Sambuc 	*d++ = s;					\
121*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0)
122*0a6a1f1dSLionel Sambuc 
123*0a6a1f1dSLionel Sambuc #define setup(arr, siz) do {				\
124*0a6a1f1dSLionel Sambuc 	arr = malloc((siz = 10) * sizeof(*arr)); 	\
125*0a6a1f1dSLionel Sambuc 	if (arr == NULL)				\
126*0a6a1f1dSLionel Sambuc 		goto nospc;				\
127*0a6a1f1dSLionel Sambuc } while (/*CONSTCOND*/0)
128*0a6a1f1dSLionel Sambuc 
129f14fb602SLionel Sambuc 
1302fe8fb19SBen Gras static const char AskedForGot[] =
1312fe8fb19SBen Gras     "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1322fe8fb19SBen Gras 
1332fe8fb19SBen Gras 
1342fe8fb19SBen Gras #ifdef YP
1352fe8fb19SBen Gras static char *__ypdomain;
1362fe8fb19SBen Gras #endif
1372fe8fb19SBen Gras 
1382fe8fb19SBen Gras #define	MAXPACKET	(64*1024)
1392fe8fb19SBen Gras 
1402fe8fb19SBen Gras typedef union {
1412fe8fb19SBen Gras 	HEADER hdr;
1422fe8fb19SBen Gras 	u_char buf[MAXPACKET];
1432fe8fb19SBen Gras } querybuf;
1442fe8fb19SBen Gras 
1452fe8fb19SBen Gras typedef union {
1462fe8fb19SBen Gras 	int32_t al;
1472fe8fb19SBen Gras 	char ac;
1482fe8fb19SBen Gras } align;
1492fe8fb19SBen Gras 
1502fe8fb19SBen Gras #ifdef DEBUG
1512fe8fb19SBen Gras static void debugprintf(const char *, res_state, ...)
1522fe8fb19SBen Gras 	__attribute__((__format__(__printf__, 1, 3)));
1532fe8fb19SBen Gras #endif
1542fe8fb19SBen Gras static struct hostent *getanswer(const querybuf *, int, const char *, int,
15584d9c625SLionel Sambuc     res_state, struct hostent *, char *, size_t, int *);
1562fe8fb19SBen Gras static void map_v4v6_address(const char *, char *);
1572fe8fb19SBen Gras static void map_v4v6_hostent(struct hostent *, char **, char *);
1582fe8fb19SBen Gras static void addrsort(char **, int, res_state);
1592fe8fb19SBen Gras 
1602fe8fb19SBen Gras void dns_service(void);
1612fe8fb19SBen Gras #undef dn_skipname
1622fe8fb19SBen Gras int dn_skipname(const u_char *, const u_char *);
16384d9c625SLionel Sambuc 
1642fe8fb19SBen Gras #ifdef YP
16584d9c625SLionel Sambuc static struct hostent *_yp_hostent(char *, int, struct getnamaddr *);
1662fe8fb19SBen Gras #endif
1672fe8fb19SBen Gras 
16884d9c625SLionel Sambuc static struct hostent *gethostbyname_internal(const char *, int, res_state,
16984d9c625SLionel Sambuc     struct hostent *, char *, size_t, int *);
1702fe8fb19SBen Gras 
1712fe8fb19SBen Gras static const ns_src default_dns_files[] = {
1722fe8fb19SBen Gras 	{ NSSRC_FILES, 	NS_SUCCESS },
1732fe8fb19SBen Gras 	{ NSSRC_DNS, 	NS_SUCCESS },
1742fe8fb19SBen Gras 	{ 0, 0 }
1752fe8fb19SBen Gras };
1762fe8fb19SBen Gras 
1772fe8fb19SBen Gras 
1782fe8fb19SBen Gras #ifdef DEBUG
1792fe8fb19SBen Gras static void
debugprintf(const char * msg,res_state res,...)1802fe8fb19SBen Gras debugprintf(const char *msg, res_state res, ...)
1812fe8fb19SBen Gras {
1822fe8fb19SBen Gras 	_DIAGASSERT(msg != NULL);
1832fe8fb19SBen Gras 
1842fe8fb19SBen Gras 	if (res->options & RES_DEBUG) {
1852fe8fb19SBen Gras 		int save = errno;
1862fe8fb19SBen Gras 		va_list ap;
1872fe8fb19SBen Gras 
1882fe8fb19SBen Gras 		va_start (ap, res);
1892fe8fb19SBen Gras 		vprintf(msg, ap);
1902fe8fb19SBen Gras 		va_end (ap);
1912fe8fb19SBen Gras 
1922fe8fb19SBen Gras 		errno = save;
1932fe8fb19SBen Gras 	}
1942fe8fb19SBen Gras }
1952fe8fb19SBen Gras #else
1962fe8fb19SBen Gras # define debugprintf(msg, res, num) /*nada*/
1972fe8fb19SBen Gras #endif
1982fe8fb19SBen Gras 
1992fe8fb19SBen Gras #define BOUNDED_INCR(x) \
2002fe8fb19SBen Gras 	do { \
2012fe8fb19SBen Gras 		cp += (x); \
202*0a6a1f1dSLionel Sambuc 		if (cp > eom) \
203*0a6a1f1dSLionel Sambuc 			goto no_recovery; \
2042fe8fb19SBen Gras 	} while (/*CONSTCOND*/0)
2052fe8fb19SBen Gras 
2062fe8fb19SBen Gras #define BOUNDS_CHECK(ptr, count) \
2072fe8fb19SBen Gras 	do { \
208*0a6a1f1dSLionel Sambuc 		if ((ptr) + (count) > eom) \
209*0a6a1f1dSLionel Sambuc 			goto no_recovery; \
2102fe8fb19SBen Gras 	} while (/*CONSTCOND*/0)
2112fe8fb19SBen Gras 
2122fe8fb19SBen Gras static struct hostent *
getanswer(const querybuf * answer,int anslen,const char * qname,int qtype,res_state res,struct hostent * hent,char * buf,size_t buflen,int * he)2132fe8fb19SBen Gras getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
21484d9c625SLionel Sambuc     res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
2152fe8fb19SBen Gras {
2162fe8fb19SBen Gras 	const HEADER *hp;
2172fe8fb19SBen Gras 	const u_char *cp;
2182fe8fb19SBen Gras 	int n;
21984d9c625SLionel Sambuc 	size_t qlen;
2202fe8fb19SBen Gras 	const u_char *eom, *erdata;
2212fe8fb19SBen Gras 	char *bp, **ap, **hap, *ep;
2222fe8fb19SBen Gras 	int type, class, ancount, qdcount;
2232fe8fb19SBen Gras 	int haveanswer, had_error;
2242fe8fb19SBen Gras 	int toobig = 0;
2252fe8fb19SBen Gras 	char tbuf[MAXDNAME];
226*0a6a1f1dSLionel Sambuc 	char **aliases;
227*0a6a1f1dSLionel Sambuc 	size_t maxaliases;
22884d9c625SLionel Sambuc 	char *addr_ptrs[MAXADDRS];
2292fe8fb19SBen Gras 	const char *tname;
2302fe8fb19SBen Gras 	int (*name_ok)(const char *);
2312fe8fb19SBen Gras 
2322fe8fb19SBen Gras 	_DIAGASSERT(answer != NULL);
2332fe8fb19SBen Gras 	_DIAGASSERT(qname != NULL);
2342fe8fb19SBen Gras 
2352fe8fb19SBen Gras 	tname = qname;
23684d9c625SLionel Sambuc 	hent->h_name = NULL;
2372fe8fb19SBen Gras 	eom = answer->buf + anslen;
2382fe8fb19SBen Gras 	switch (qtype) {
2392fe8fb19SBen Gras 	case T_A:
2402fe8fb19SBen Gras 	case T_AAAA:
2412fe8fb19SBen Gras 		name_ok = res_hnok;
2422fe8fb19SBen Gras 		break;
2432fe8fb19SBen Gras 	case T_PTR:
2442fe8fb19SBen Gras 		name_ok = res_dnok;
2452fe8fb19SBen Gras 		break;
2462fe8fb19SBen Gras 	default:
247*0a6a1f1dSLionel Sambuc 		*he = NO_RECOVERY;
2482fe8fb19SBen Gras 		return NULL;	/* XXX should be abort(); */
2492fe8fb19SBen Gras 	}
250*0a6a1f1dSLionel Sambuc 
251*0a6a1f1dSLionel Sambuc 	setup(aliases, maxaliases);
2522fe8fb19SBen Gras 	/*
2532fe8fb19SBen Gras 	 * find first satisfactory answer
2542fe8fb19SBen Gras 	 */
2552fe8fb19SBen Gras 	hp = &answer->hdr;
2562fe8fb19SBen Gras 	ancount = ntohs(hp->ancount);
2572fe8fb19SBen Gras 	qdcount = ntohs(hp->qdcount);
25884d9c625SLionel Sambuc 	bp = buf;
25984d9c625SLionel Sambuc 	ep = buf + buflen;
2602fe8fb19SBen Gras 	cp = answer->buf;
2612fe8fb19SBen Gras 	BOUNDED_INCR(HFIXEDSZ);
26284d9c625SLionel Sambuc 	if (qdcount != 1)
26384d9c625SLionel Sambuc 		goto no_recovery;
26484d9c625SLionel Sambuc 
265f14fb602SLionel Sambuc 	n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
26684d9c625SLionel Sambuc 	if ((n < 0) || !maybe_ok(res, bp, name_ok))
26784d9c625SLionel Sambuc 		goto no_recovery;
26884d9c625SLionel Sambuc 
2692fe8fb19SBen Gras 	BOUNDED_INCR(n + QFIXEDSZ);
2702fe8fb19SBen Gras 	if (qtype == T_A || qtype == T_AAAA) {
2712fe8fb19SBen Gras 		/* res_send() has already verified that the query name is the
2722fe8fb19SBen Gras 		 * same as the one we sent; this just gets the expanded name
2732fe8fb19SBen Gras 		 * (i.e., with the succeeding search-domain tacked on).
2742fe8fb19SBen Gras 		 */
275f14fb602SLionel Sambuc 		n = (int)strlen(bp) + 1;		/* for the \0 */
27684d9c625SLionel Sambuc 		if (n >= MAXHOSTNAMELEN)
27784d9c625SLionel Sambuc 			goto no_recovery;
27884d9c625SLionel Sambuc 		hent->h_name = bp;
2792fe8fb19SBen Gras 		bp += n;
2802fe8fb19SBen Gras 		/* The qname can be abbreviated, but h_name is now absolute. */
28184d9c625SLionel Sambuc 		qname = hent->h_name;
2822fe8fb19SBen Gras 	}
28384d9c625SLionel Sambuc 	hent->h_aliases = ap = aliases;
28484d9c625SLionel Sambuc 	hent->h_addr_list = hap = addr_ptrs;
2852fe8fb19SBen Gras 	*ap = NULL;
2862fe8fb19SBen Gras 	*hap = NULL;
2872fe8fb19SBen Gras 	haveanswer = 0;
2882fe8fb19SBen Gras 	had_error = 0;
2892fe8fb19SBen Gras 	while (ancount-- > 0 && cp < eom && !had_error) {
290f14fb602SLionel Sambuc 		n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
291f14fb602SLionel Sambuc 		if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
2922fe8fb19SBen Gras 			had_error++;
2932fe8fb19SBen Gras 			continue;
2942fe8fb19SBen Gras 		}
2952fe8fb19SBen Gras 		cp += n;			/* name */
2962fe8fb19SBen Gras 		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
2972fe8fb19SBen Gras 		type = _getshort(cp);
2982fe8fb19SBen Gras  		cp += INT16SZ;			/* type */
2992fe8fb19SBen Gras 		class = _getshort(cp);
3002fe8fb19SBen Gras  		cp += INT16SZ + INT32SZ;	/* class, TTL */
3012fe8fb19SBen Gras 		n = _getshort(cp);
3022fe8fb19SBen Gras 		cp += INT16SZ;			/* len */
3032fe8fb19SBen Gras 		BOUNDS_CHECK(cp, n);
3042fe8fb19SBen Gras 		erdata = cp + n;
3052fe8fb19SBen Gras 		if (class != C_IN) {
3062fe8fb19SBen Gras 			/* XXX - debug? syslog? */
3072fe8fb19SBen Gras 			cp += n;
3082fe8fb19SBen Gras 			continue;		/* XXX - had_error++ ? */
3092fe8fb19SBen Gras 		}
3102fe8fb19SBen Gras 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
31184d9c625SLionel Sambuc 			n = dn_expand(answer->buf, eom, cp, tbuf,
31284d9c625SLionel Sambuc 			    (int)sizeof tbuf);
313f14fb602SLionel Sambuc 			if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
3142fe8fb19SBen Gras 				had_error++;
3152fe8fb19SBen Gras 				continue;
3162fe8fb19SBen Gras 			}
3172fe8fb19SBen Gras 			cp += n;
31884d9c625SLionel Sambuc 			if (cp != erdata)
31984d9c625SLionel Sambuc 				goto no_recovery;
3202fe8fb19SBen Gras 			/* Store alias. */
321*0a6a1f1dSLionel Sambuc 			addalias(ap, bp, aliases, maxaliases);
322f14fb602SLionel Sambuc 			n = (int)strlen(bp) + 1;	/* for the \0 */
3232fe8fb19SBen Gras 			if (n >= MAXHOSTNAMELEN) {
3242fe8fb19SBen Gras 				had_error++;
3252fe8fb19SBen Gras 				continue;
3262fe8fb19SBen Gras 			}
3272fe8fb19SBen Gras 			bp += n;
3282fe8fb19SBen Gras 			/* Get canonical name. */
329f14fb602SLionel Sambuc 			n = (int)strlen(tbuf) + 1;	/* for the \0 */
3302fe8fb19SBen Gras 			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
3312fe8fb19SBen Gras 				had_error++;
3322fe8fb19SBen Gras 				continue;
3332fe8fb19SBen Gras 			}
3342fe8fb19SBen Gras 			strlcpy(bp, tbuf, (size_t)(ep - bp));
33584d9c625SLionel Sambuc 			hent->h_name = bp;
3362fe8fb19SBen Gras 			bp += n;
3372fe8fb19SBen Gras 			continue;
3382fe8fb19SBen Gras 		}
3392fe8fb19SBen Gras 		if (qtype == T_PTR && type == T_CNAME) {
34084d9c625SLionel Sambuc 			n = dn_expand(answer->buf, eom, cp, tbuf,
34184d9c625SLionel Sambuc 			    (int)sizeof tbuf);
342f14fb602SLionel Sambuc 			if (n < 0 || !maybe_dnok(res, tbuf)) {
3432fe8fb19SBen Gras 				had_error++;
3442fe8fb19SBen Gras 				continue;
3452fe8fb19SBen Gras 			}
3462fe8fb19SBen Gras 			cp += n;
34784d9c625SLionel Sambuc 			if (cp != erdata)
34884d9c625SLionel Sambuc 				goto no_recovery;
3492fe8fb19SBen Gras 			/* Get canonical name. */
350f14fb602SLionel Sambuc 			n = (int)strlen(tbuf) + 1;	/* for the \0 */
3512fe8fb19SBen Gras 			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
3522fe8fb19SBen Gras 				had_error++;
3532fe8fb19SBen Gras 				continue;
3542fe8fb19SBen Gras 			}
3552fe8fb19SBen Gras 			strlcpy(bp, tbuf, (size_t)(ep - bp));
3562fe8fb19SBen Gras 			tname = bp;
3572fe8fb19SBen Gras 			bp += n;
3582fe8fb19SBen Gras 			continue;
3592fe8fb19SBen Gras 		}
3602fe8fb19SBen Gras 		if (type != qtype) {
3612fe8fb19SBen Gras 			if (type != T_KEY && type != T_SIG)
3622fe8fb19SBen Gras 				syslog(LOG_NOTICE|LOG_AUTH,
3632fe8fb19SBen Gras 	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
3642fe8fb19SBen Gras 				       qname, p_class(C_IN), p_type(qtype),
3652fe8fb19SBen Gras 				       p_type(type));
3662fe8fb19SBen Gras 			cp += n;
3672fe8fb19SBen Gras 			continue;		/* XXX - had_error++ ? */
3682fe8fb19SBen Gras 		}
3692fe8fb19SBen Gras 		switch (type) {
3702fe8fb19SBen Gras 		case T_PTR:
3712fe8fb19SBen Gras 			if (strcasecmp(tname, bp) != 0) {
3722fe8fb19SBen Gras 				syslog(LOG_NOTICE|LOG_AUTH,
3732fe8fb19SBen Gras 				       AskedForGot, qname, bp);
3742fe8fb19SBen Gras 				cp += n;
3752fe8fb19SBen Gras 				continue;	/* XXX - had_error++ ? */
3762fe8fb19SBen Gras 			}
377f14fb602SLionel Sambuc 			n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
378f14fb602SLionel Sambuc 			if ((n < 0) || !maybe_hnok(res, bp)) {
3792fe8fb19SBen Gras 				had_error++;
3802fe8fb19SBen Gras 				break;
3812fe8fb19SBen Gras 			}
3822fe8fb19SBen Gras #if MULTI_PTRS_ARE_ALIASES
3832fe8fb19SBen Gras 			cp += n;
38484d9c625SLionel Sambuc 			if (cp != erdata)
38584d9c625SLionel Sambuc 				goto no_recovery;
3862fe8fb19SBen Gras 			if (!haveanswer)
38784d9c625SLionel Sambuc 				hent->h_name = bp;
3882fe8fb19SBen Gras 			else
389*0a6a1f1dSLionel Sambuc 				addalias(ap, bp, aliases, maxaliases);
3902fe8fb19SBen Gras 			if (n != -1) {
391f14fb602SLionel Sambuc 				n = (int)strlen(bp) + 1;	/* for the \0 */
3922fe8fb19SBen Gras 				if (n >= MAXHOSTNAMELEN) {
3932fe8fb19SBen Gras 					had_error++;
3942fe8fb19SBen Gras 					break;
3952fe8fb19SBen Gras 				}
3962fe8fb19SBen Gras 				bp += n;
3972fe8fb19SBen Gras 			}
3982fe8fb19SBen Gras 			break;
3992fe8fb19SBen Gras #else
40084d9c625SLionel Sambuc 			hent->h_name = bp;
4012fe8fb19SBen Gras 			if (res->options & RES_USE_INET6) {
4022fe8fb19SBen Gras 				n = strlen(bp) + 1;	/* for the \0 */
4032fe8fb19SBen Gras 				if (n >= MAXHOSTNAMELEN) {
4042fe8fb19SBen Gras 					had_error++;
4052fe8fb19SBen Gras 					break;
4062fe8fb19SBen Gras 				}
4072fe8fb19SBen Gras 				bp += n;
40884d9c625SLionel Sambuc 				map_v4v6_hostent(hent, &bp, ep);
4092fe8fb19SBen Gras 			}
41084d9c625SLionel Sambuc 			goto success;
4112fe8fb19SBen Gras #endif
4122fe8fb19SBen Gras 		case T_A:
4132fe8fb19SBen Gras 		case T_AAAA:
41484d9c625SLionel Sambuc 			if (strcasecmp(hent->h_name, bp) != 0) {
4152fe8fb19SBen Gras 				syslog(LOG_NOTICE|LOG_AUTH,
41684d9c625SLionel Sambuc 				       AskedForGot, hent->h_name, bp);
4172fe8fb19SBen Gras 				cp += n;
4182fe8fb19SBen Gras 				continue;	/* XXX - had_error++ ? */
4192fe8fb19SBen Gras 			}
42084d9c625SLionel Sambuc 			if (n != hent->h_length) {
4212fe8fb19SBen Gras 				cp += n;
4222fe8fb19SBen Gras 				continue;
4232fe8fb19SBen Gras 			}
4242fe8fb19SBen Gras 			if (type == T_AAAA) {
4252fe8fb19SBen Gras 				struct in6_addr in6;
42684d9c625SLionel Sambuc 				memcpy(&in6, cp, NS_IN6ADDRSZ);
4272fe8fb19SBen Gras 				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
4282fe8fb19SBen Gras 					cp += n;
4292fe8fb19SBen Gras 					continue;
4302fe8fb19SBen Gras 				}
4312fe8fb19SBen Gras 			}
4322fe8fb19SBen Gras 			if (!haveanswer) {
4332fe8fb19SBen Gras 				int nn;
4342fe8fb19SBen Gras 
43584d9c625SLionel Sambuc 				hent->h_name = bp;
436f14fb602SLionel Sambuc 				nn = (int)strlen(bp) + 1;	/* for the \0 */
4372fe8fb19SBen Gras 				bp += nn;
4382fe8fb19SBen Gras 			}
4392fe8fb19SBen Gras 
4402fe8fb19SBen Gras 			bp += sizeof(align) -
4412fe8fb19SBen Gras 			    (size_t)((u_long)bp % sizeof(align));
4422fe8fb19SBen Gras 
44384d9c625SLionel Sambuc 			if (bp + n >= ep) {
4442fe8fb19SBen Gras 				debugprintf("size (%d) too big\n", res, n);
4452fe8fb19SBen Gras 				had_error++;
4462fe8fb19SBen Gras 				continue;
4472fe8fb19SBen Gras 			}
44884d9c625SLionel Sambuc 			if (hap >= &addr_ptrs[MAXADDRS - 1]) {
4492fe8fb19SBen Gras 				if (!toobig++) {
4502fe8fb19SBen Gras 					debugprintf("Too many addresses (%d)\n",
4512fe8fb19SBen Gras 						res, MAXADDRS);
4522fe8fb19SBen Gras 				}
4532fe8fb19SBen Gras 				cp += n;
4542fe8fb19SBen Gras 				continue;
4552fe8fb19SBen Gras 			}
4562fe8fb19SBen Gras 			(void)memcpy(*hap++ = bp, cp, (size_t)n);
4572fe8fb19SBen Gras 			bp += n;
4582fe8fb19SBen Gras 			cp += n;
45984d9c625SLionel Sambuc 			if (cp != erdata)
46084d9c625SLionel Sambuc 				goto no_recovery;
4612fe8fb19SBen Gras 			break;
4622fe8fb19SBen Gras 		default:
4632fe8fb19SBen Gras 			abort();
4642fe8fb19SBen Gras 		}
4652fe8fb19SBen Gras 		if (!had_error)
4662fe8fb19SBen Gras 			haveanswer++;
4672fe8fb19SBen Gras 	}
4682fe8fb19SBen Gras 	if (haveanswer) {
4692fe8fb19SBen Gras 		*ap = NULL;
4702fe8fb19SBen Gras 		*hap = NULL;
4712fe8fb19SBen Gras 		/*
4722fe8fb19SBen Gras 		 * Note: we sort even if host can take only one address
4732fe8fb19SBen Gras 		 * in its return structures - should give it the "best"
4742fe8fb19SBen Gras 		 * address in that case, not some random one
4752fe8fb19SBen Gras 		 */
4762fe8fb19SBen Gras 		if (res->nsort && haveanswer > 1 && qtype == T_A)
47784d9c625SLionel Sambuc 			addrsort(addr_ptrs, haveanswer, res);
47884d9c625SLionel Sambuc 		if (!hent->h_name) {
479f14fb602SLionel Sambuc 			n = (int)strlen(qname) + 1;	/* for the \0 */
4802fe8fb19SBen Gras 			if (n > ep - bp || n >= MAXHOSTNAMELEN)
4812fe8fb19SBen Gras 				goto no_recovery;
4822fe8fb19SBen Gras 			strlcpy(bp, qname, (size_t)(ep - bp));
48384d9c625SLionel Sambuc 			hent->h_name = bp;
4842fe8fb19SBen Gras 			bp += n;
4852fe8fb19SBen Gras 		}
4862fe8fb19SBen Gras 		if (res->options & RES_USE_INET6)
48784d9c625SLionel Sambuc 			map_v4v6_hostent(hent, &bp, ep);
48884d9c625SLionel Sambuc 	    	goto success;
4892fe8fb19SBen Gras 	}
4902fe8fb19SBen Gras no_recovery:
491*0a6a1f1dSLionel Sambuc 	free(aliases);
49284d9c625SLionel Sambuc 	*he = NO_RECOVERY;
49384d9c625SLionel Sambuc 	return NULL;
49484d9c625SLionel Sambuc success:
49584d9c625SLionel Sambuc 	bp = (char *)ALIGN(bp);
49684d9c625SLionel Sambuc 	n = (int)(ap - aliases);
49784d9c625SLionel Sambuc 	qlen = (n + 1) * sizeof(*hent->h_aliases);
49884d9c625SLionel Sambuc 	if ((size_t)(ep - bp) < qlen)
49984d9c625SLionel Sambuc 		goto nospc;
50084d9c625SLionel Sambuc 	hent->h_aliases = (void *)bp;
50184d9c625SLionel Sambuc 	memcpy(bp, aliases, qlen);
502*0a6a1f1dSLionel Sambuc 	free(aliases);
503*0a6a1f1dSLionel Sambuc 	aliases = NULL;
50484d9c625SLionel Sambuc 
50584d9c625SLionel Sambuc 	bp += qlen;
50684d9c625SLionel Sambuc 	n = (int)(hap - addr_ptrs);
50784d9c625SLionel Sambuc 	qlen = (n + 1) * sizeof(*hent->h_addr_list);
50884d9c625SLionel Sambuc 	if ((size_t)(ep - bp) < qlen)
50984d9c625SLionel Sambuc 		goto nospc;
51084d9c625SLionel Sambuc 	hent->h_addr_list = (void *)bp;
51184d9c625SLionel Sambuc 	memcpy(bp, addr_ptrs, qlen);
51284d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
51384d9c625SLionel Sambuc 	return hent;
51484d9c625SLionel Sambuc nospc:
515*0a6a1f1dSLionel Sambuc 	free(aliases);
51684d9c625SLionel Sambuc 	errno = ENOSPC;
51784d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
5182fe8fb19SBen Gras 	return NULL;
5192fe8fb19SBen Gras }
5202fe8fb19SBen Gras 
5212fe8fb19SBen Gras struct hostent *
gethostbyname_r(const char * name,struct hostent * hp,char * buf,size_t buflen,int * he)52284d9c625SLionel Sambuc gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
52384d9c625SLionel Sambuc     int *he)
5242fe8fb19SBen Gras {
5252fe8fb19SBen Gras 	res_state res = __res_get_state();
5262fe8fb19SBen Gras 
52784d9c625SLionel Sambuc 	if (res == NULL) {
52884d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
5292fe8fb19SBen Gras 		return NULL;
53084d9c625SLionel Sambuc 	}
5312fe8fb19SBen Gras 
5322fe8fb19SBen Gras 	_DIAGASSERT(name != NULL);
5332fe8fb19SBen Gras 
5342fe8fb19SBen Gras 	if (res->options & RES_USE_INET6) {
535*0a6a1f1dSLionel Sambuc 		struct hostent *nhp = gethostbyname_internal(name, AF_INET6,
536*0a6a1f1dSLionel Sambuc 		    res, hp, buf, buflen, he);
537*0a6a1f1dSLionel Sambuc 		if (nhp) {
5382fe8fb19SBen Gras 			__res_put_state(res);
539*0a6a1f1dSLionel Sambuc 			return nhp;
5402fe8fb19SBen Gras 		}
5412fe8fb19SBen Gras 	}
54284d9c625SLionel Sambuc 	hp = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, he);
5432fe8fb19SBen Gras 	__res_put_state(res);
5442fe8fb19SBen Gras 	return hp;
5452fe8fb19SBen Gras }
5462fe8fb19SBen Gras 
5472fe8fb19SBen Gras struct hostent *
gethostbyname2_r(const char * name,int af,struct hostent * hp,char * buf,size_t buflen,int * he)54884d9c625SLionel Sambuc gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
54984d9c625SLionel Sambuc     size_t buflen, int *he)
5502fe8fb19SBen Gras {
5512fe8fb19SBen Gras 	res_state res = __res_get_state();
5522fe8fb19SBen Gras 
55384d9c625SLionel Sambuc 	if (res == NULL) {
55484d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
5552fe8fb19SBen Gras 		return NULL;
55684d9c625SLionel Sambuc 	}
55784d9c625SLionel Sambuc 	hp = gethostbyname_internal(name, af, res, hp, buf, buflen, he);
5582fe8fb19SBen Gras 	__res_put_state(res);
5592fe8fb19SBen Gras 	return hp;
5602fe8fb19SBen Gras }
5612fe8fb19SBen Gras 
5622fe8fb19SBen Gras static struct hostent *
gethostbyname_internal(const char * name,int af,res_state res,struct hostent * hp,char * buf,size_t buflen,int * he)56384d9c625SLionel Sambuc gethostbyname_internal(const char *name, int af, res_state res,
56484d9c625SLionel Sambuc     struct hostent *hp, char *buf, size_t buflen, int *he)
5652fe8fb19SBen Gras {
5662fe8fb19SBen Gras 	const char *cp;
56784d9c625SLionel Sambuc 	struct getnamaddr info;
568*0a6a1f1dSLionel Sambuc 	char hbuf[MAXHOSTNAMELEN];
56984d9c625SLionel Sambuc 	size_t size;
5702fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
57184d9c625SLionel Sambuc 		NS_FILES_CB(_hf_gethtbyname, NULL)
5722fe8fb19SBen Gras 		{ NSSRC_DNS, _dns_gethtbyname, NULL },	/* force -DHESIOD */
5732fe8fb19SBen Gras 		NS_NIS_CB(_yp_gethtbyname, NULL)
5742fe8fb19SBen Gras 		NS_NULL_CB
5752fe8fb19SBen Gras 	};
5762fe8fb19SBen Gras 
5772fe8fb19SBen Gras 	_DIAGASSERT(name != NULL);
5782fe8fb19SBen Gras 
5792fe8fb19SBen Gras 	switch (af) {
5802fe8fb19SBen Gras 	case AF_INET:
58184d9c625SLionel Sambuc 		size = NS_INADDRSZ;
5822fe8fb19SBen Gras 		break;
5832fe8fb19SBen Gras 	case AF_INET6:
58484d9c625SLionel Sambuc 		size = NS_IN6ADDRSZ;
5852fe8fb19SBen Gras 		break;
5862fe8fb19SBen Gras 	default:
58784d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
5882fe8fb19SBen Gras 		errno = EAFNOSUPPORT;
5892fe8fb19SBen Gras 		return NULL;
5902fe8fb19SBen Gras 	}
59184d9c625SLionel Sambuc 	if (buflen < size)
59284d9c625SLionel Sambuc 		goto nospc;
5932fe8fb19SBen Gras 
59484d9c625SLionel Sambuc 	hp->h_addrtype = af;
59584d9c625SLionel Sambuc 	hp->h_length = (int)size;
5962fe8fb19SBen Gras 
5972fe8fb19SBen Gras 	/*
5982fe8fb19SBen Gras 	 * if there aren't any dots, it could be a user-level alias.
5992fe8fb19SBen Gras 	 * this is also done in res_nquery() since we are not the only
6002fe8fb19SBen Gras 	 * function that looks up host names.
6012fe8fb19SBen Gras 	 */
602*0a6a1f1dSLionel Sambuc 	if (!strchr(name, '.') && (cp = res_hostalias(res, name,
603*0a6a1f1dSLionel Sambuc 	    hbuf, sizeof(hbuf))))
6042fe8fb19SBen Gras 		name = cp;
6052fe8fb19SBen Gras 
6062fe8fb19SBen Gras 	/*
6072fe8fb19SBen Gras 	 * disallow names consisting only of digits/dots, unless
6082fe8fb19SBen Gras 	 * they end in a dot.
6092fe8fb19SBen Gras 	 */
6102fe8fb19SBen Gras 	if (isdigit((u_char) name[0]))
6112fe8fb19SBen Gras 		for (cp = name;; ++cp) {
6122fe8fb19SBen Gras 			if (!*cp) {
6132fe8fb19SBen Gras 				if (*--cp == '.')
6142fe8fb19SBen Gras 					break;
6152fe8fb19SBen Gras 				/*
6162fe8fb19SBen Gras 				 * All-numeric, no dot at the end.
6172fe8fb19SBen Gras 				 * Fake up a hostent as if we'd actually
6182fe8fb19SBen Gras 				 * done a lookup.
6192fe8fb19SBen Gras 				 */
62084d9c625SLionel Sambuc 				goto fake;
6212fe8fb19SBen Gras 			}
6222fe8fb19SBen Gras 			if (!isdigit((u_char) *cp) && *cp != '.')
6232fe8fb19SBen Gras 				break;
6242fe8fb19SBen Gras 		}
6252fe8fb19SBen Gras 	if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
6262fe8fb19SBen Gras 	    name[0] == ':')
6272fe8fb19SBen Gras 		for (cp = name;; ++cp) {
6282fe8fb19SBen Gras 			if (!*cp) {
6292fe8fb19SBen Gras 				if (*--cp == '.')
6302fe8fb19SBen Gras 					break;
6312fe8fb19SBen Gras 				/*
6322fe8fb19SBen Gras 				 * All-IPv6-legal, no dot at the end.
6332fe8fb19SBen Gras 				 * Fake up a hostent as if we'd actually
6342fe8fb19SBen Gras 				 * done a lookup.
6352fe8fb19SBen Gras 				 */
63684d9c625SLionel Sambuc 				goto fake;
6372fe8fb19SBen Gras 			}
6382fe8fb19SBen Gras 			if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
6392fe8fb19SBen Gras 				break;
6402fe8fb19SBen Gras 		}
6412fe8fb19SBen Gras 
64284d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
64384d9c625SLionel Sambuc 	info.hp = hp;
64484d9c625SLionel Sambuc 	info.buf = buf;
64584d9c625SLionel Sambuc 	info.buflen = buflen;
64684d9c625SLionel Sambuc 	info.he = he;
64784d9c625SLionel Sambuc 	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
6482fe8fb19SBen Gras 	    default_dns_files, name, strlen(name), af) != NS_SUCCESS)
6492fe8fb19SBen Gras 		return NULL;
65084d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
65184d9c625SLionel Sambuc 	return hp;
65284d9c625SLionel Sambuc nospc:
65384d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
65484d9c625SLionel Sambuc 	errno = ENOSPC;
65584d9c625SLionel Sambuc 	return NULL;
65684d9c625SLionel Sambuc fake:
65784d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
65884d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
65984d9c625SLionel Sambuc 
66084d9c625SLionel Sambuc 	hp->h_aliases[0] = NULL;
66184d9c625SLionel Sambuc 	if (size > buflen)
66284d9c625SLionel Sambuc 		goto nospc;
66384d9c625SLionel Sambuc 
66484d9c625SLionel Sambuc 	if (inet_pton(af, name, buf) <= 0) {
66584d9c625SLionel Sambuc 		*he = HOST_NOT_FOUND;
66684d9c625SLionel Sambuc 		return NULL;
66784d9c625SLionel Sambuc 	}
66884d9c625SLionel Sambuc 	hp->h_addr_list[0] = buf;
66984d9c625SLionel Sambuc 	hp->h_addr_list[1] = NULL;
67084d9c625SLionel Sambuc 	buf += size;
67184d9c625SLionel Sambuc 	buflen -= size;
67284d9c625SLionel Sambuc 	HENT_SCOPY(hp->h_name, name, buf, buflen);
67384d9c625SLionel Sambuc 	if (res->options & RES_USE_INET6)
67484d9c625SLionel Sambuc 		map_v4v6_hostent(hp, &buf, buf + buflen);
67584d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
6762fe8fb19SBen Gras 	return hp;
6772fe8fb19SBen Gras }
6782fe8fb19SBen Gras 
6792fe8fb19SBen Gras struct hostent *
gethostbyaddr_r(const void * addr,socklen_t len,int af,struct hostent * hp,char * buf,size_t buflen,int * he)68084d9c625SLionel Sambuc gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
68184d9c625SLionel Sambuc     char *buf, size_t buflen, int *he)
6822fe8fb19SBen Gras {
6832fe8fb19SBen Gras 	const u_char *uaddr = (const u_char *)addr;
6842fe8fb19SBen Gras 	socklen_t size;
68584d9c625SLionel Sambuc 	struct getnamaddr info;
6862fe8fb19SBen Gras 	static const ns_dtab dtab[] = {
68784d9c625SLionel Sambuc 		NS_FILES_CB(_hf_gethtbyaddr, NULL)
6882fe8fb19SBen Gras 		{ NSSRC_DNS, _dns_gethtbyaddr, NULL },	/* force -DHESIOD */
6892fe8fb19SBen Gras 		NS_NIS_CB(_yp_gethtbyaddr, NULL)
6902fe8fb19SBen Gras 		NS_NULL_CB
6912fe8fb19SBen Gras 	};
6922fe8fb19SBen Gras 
6932fe8fb19SBen Gras 	_DIAGASSERT(addr != NULL);
6942fe8fb19SBen Gras 
69584d9c625SLionel Sambuc 	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
69684d9c625SLionel Sambuc 	    (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
69784d9c625SLionel Sambuc 	     IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
69884d9c625SLionel Sambuc 		*he = HOST_NOT_FOUND;
6992fe8fb19SBen Gras 		return NULL;
7002fe8fb19SBen Gras 	}
70184d9c625SLionel Sambuc 	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
70284d9c625SLionel Sambuc 	    (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
70384d9c625SLionel Sambuc 	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
7042fe8fb19SBen Gras 		/* Unmap. */
70584d9c625SLionel Sambuc 		uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
70684d9c625SLionel Sambuc 		addr = uaddr;
7072fe8fb19SBen Gras 		af = AF_INET;
70884d9c625SLionel Sambuc 		len = NS_INADDRSZ;
7092fe8fb19SBen Gras 	}
7102fe8fb19SBen Gras 	switch (af) {
7112fe8fb19SBen Gras 	case AF_INET:
71284d9c625SLionel Sambuc 		size = NS_INADDRSZ;
7132fe8fb19SBen Gras 		break;
7142fe8fb19SBen Gras 	case AF_INET6:
71584d9c625SLionel Sambuc 		size = NS_IN6ADDRSZ;
7162fe8fb19SBen Gras 		break;
7172fe8fb19SBen Gras 	default:
7182fe8fb19SBen Gras 		errno = EAFNOSUPPORT;
71984d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
7202fe8fb19SBen Gras 		return NULL;
7212fe8fb19SBen Gras 	}
7222fe8fb19SBen Gras 	if (size != len) {
7232fe8fb19SBen Gras 		errno = EINVAL;
72484d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
7252fe8fb19SBen Gras 		return NULL;
7262fe8fb19SBen Gras 	}
72784d9c625SLionel Sambuc 	info.hp = hp;
72884d9c625SLionel Sambuc 	info.buf = buf;
72984d9c625SLionel Sambuc 	info.buflen = buflen;
73084d9c625SLionel Sambuc 	info.he = he;
73184d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
73284d9c625SLionel Sambuc 	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
7332fe8fb19SBen Gras 	    default_dns_files, uaddr, len, af) != NS_SUCCESS)
7342fe8fb19SBen Gras 		return NULL;
73584d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
7362fe8fb19SBen Gras 	return hp;
7372fe8fb19SBen Gras }
7382fe8fb19SBen Gras 
7392fe8fb19SBen Gras struct hostent *
gethostent_r(FILE * hf,struct hostent * hent,char * buf,size_t buflen,int * he)74084d9c625SLionel Sambuc gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
7412fe8fb19SBen Gras {
74284d9c625SLionel Sambuc 	char *p, *name;
7432fe8fb19SBen Gras 	char *cp, **q;
7442fe8fb19SBen Gras 	int af, len;
745*0a6a1f1dSLionel Sambuc 	size_t anum;
746*0a6a1f1dSLionel Sambuc 	char **aliases;
747*0a6a1f1dSLionel Sambuc 	size_t maxaliases;
74884d9c625SLionel Sambuc 	struct in6_addr host_addr;
7492fe8fb19SBen Gras 
75084d9c625SLionel Sambuc 	if (hf == NULL) {
75184d9c625SLionel Sambuc 		*he = NETDB_INTERNAL;
75284d9c625SLionel Sambuc 		errno = EINVAL;
7532fe8fb19SBen Gras 		return NULL;
7542fe8fb19SBen Gras 	}
755*0a6a1f1dSLionel Sambuc 	p = NULL;
756*0a6a1f1dSLionel Sambuc 	setup(aliases, maxaliases);
757*0a6a1f1dSLionel Sambuc 	for (;;) {
758*0a6a1f1dSLionel Sambuc 		free(p);
759*0a6a1f1dSLionel Sambuc 		p = fparseln(hf, NULL, NULL, NULL, FPARSELN_UNESCALL);
760*0a6a1f1dSLionel Sambuc 		if (p == NULL) {
761*0a6a1f1dSLionel Sambuc 			free(aliases);
76284d9c625SLionel Sambuc 			*he = HOST_NOT_FOUND;
7632fe8fb19SBen Gras 			return NULL;
7642fe8fb19SBen Gras 		}
7652fe8fb19SBen Gras 		if (!(cp = strpbrk(p, " \t")))
766*0a6a1f1dSLionel Sambuc 			continue;
7672fe8fb19SBen Gras 		*cp++ = '\0';
76884d9c625SLionel Sambuc 		if (inet_pton(AF_INET6, p, &host_addr) > 0) {
7692fe8fb19SBen Gras 			af = AF_INET6;
77084d9c625SLionel Sambuc 			len = NS_IN6ADDRSZ;
771*0a6a1f1dSLionel Sambuc 		} else {
772*0a6a1f1dSLionel Sambuc 			if (inet_pton(AF_INET, p, &host_addr) <= 0)
773*0a6a1f1dSLionel Sambuc 				continue;
774*0a6a1f1dSLionel Sambuc 
7752fe8fb19SBen Gras 			res_state res = __res_get_state();
7762fe8fb19SBen Gras 			if (res == NULL)
777*0a6a1f1dSLionel Sambuc 				goto nospc;
7782fe8fb19SBen Gras 			if (res->options & RES_USE_INET6) {
77984d9c625SLionel Sambuc 				map_v4v6_address(buf, buf);
7802fe8fb19SBen Gras 				af = AF_INET6;
78184d9c625SLionel Sambuc 				len = NS_IN6ADDRSZ;
7822fe8fb19SBen Gras 			} else {
7832fe8fb19SBen Gras 				af = AF_INET;
78484d9c625SLionel Sambuc 				len = NS_INADDRSZ;
7852fe8fb19SBen Gras 			}
7862fe8fb19SBen Gras 			__res_put_state(res);
7872fe8fb19SBen Gras 		}
788*0a6a1f1dSLionel Sambuc 
7892fe8fb19SBen Gras 		/* if this is not something we're looking for, skip it. */
79084d9c625SLionel Sambuc 		if (hent->h_addrtype != 0 && hent->h_addrtype != af)
791*0a6a1f1dSLionel Sambuc 			continue;
79284d9c625SLionel Sambuc 		if (hent->h_length != 0 && hent->h_length != len)
793*0a6a1f1dSLionel Sambuc 			continue;
79484d9c625SLionel Sambuc 
7952fe8fb19SBen Gras 		while (*cp == ' ' || *cp == '\t')
7962fe8fb19SBen Gras 			cp++;
79784d9c625SLionel Sambuc 		if ((cp = strpbrk(name = cp, " \t")) != NULL)
7982fe8fb19SBen Gras 			*cp++ = '\0';
79984d9c625SLionel Sambuc 		q = aliases;
8002fe8fb19SBen Gras 		while (cp && *cp) {
8012fe8fb19SBen Gras 			if (*cp == ' ' || *cp == '\t') {
8022fe8fb19SBen Gras 				cp++;
8032fe8fb19SBen Gras 				continue;
8042fe8fb19SBen Gras 			}
805*0a6a1f1dSLionel Sambuc 			addalias(q, cp, aliases, maxaliases);
8062fe8fb19SBen Gras 			if ((cp = strpbrk(cp, " \t")) != NULL)
8072fe8fb19SBen Gras 				*cp++ = '\0';
8082fe8fb19SBen Gras 		}
809*0a6a1f1dSLionel Sambuc 		break;
810*0a6a1f1dSLionel Sambuc 	}
81184d9c625SLionel Sambuc 	hent->h_length = len;
81284d9c625SLionel Sambuc 	hent->h_addrtype = af;
81384d9c625SLionel Sambuc 	HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
81484d9c625SLionel Sambuc 	anum = (size_t)(q - aliases);
81584d9c625SLionel Sambuc 	HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
81684d9c625SLionel Sambuc 	HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
81784d9c625SLionel Sambuc 	    buflen);
81884d9c625SLionel Sambuc 	hent->h_addr_list[1] = NULL;
8192fe8fb19SBen Gras 
82084d9c625SLionel Sambuc 	HENT_SCOPY(hent->h_name, name, buf, buflen);
82184d9c625SLionel Sambuc 	for (size_t i = 0; i < anum; i++)
82284d9c625SLionel Sambuc 		HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
82384d9c625SLionel Sambuc 	hent->h_aliases[anum] = NULL;
8242fe8fb19SBen Gras 
82584d9c625SLionel Sambuc 	*he = NETDB_SUCCESS;
826*0a6a1f1dSLionel Sambuc 	free(p);
827*0a6a1f1dSLionel Sambuc 	free(aliases);
82884d9c625SLionel Sambuc 	return hent;
82984d9c625SLionel Sambuc nospc:
830*0a6a1f1dSLionel Sambuc 	free(p);
831*0a6a1f1dSLionel Sambuc 	free(aliases);
8322fe8fb19SBen Gras 	errno = ENOSPC;
83384d9c625SLionel Sambuc 	*he = NETDB_INTERNAL;
8342fe8fb19SBen Gras 	return NULL;
8352fe8fb19SBen Gras }
8362fe8fb19SBen Gras 
8372fe8fb19SBen Gras static void
map_v4v6_address(const char * src,char * dst)8382fe8fb19SBen Gras map_v4v6_address(const char *src, char *dst)
8392fe8fb19SBen Gras {
8402fe8fb19SBen Gras 	u_char *p = (u_char *)dst;
84184d9c625SLionel Sambuc 	char tmp[NS_INADDRSZ];
8422fe8fb19SBen Gras 	int i;
8432fe8fb19SBen Gras 
8442fe8fb19SBen Gras 	_DIAGASSERT(src != NULL);
8452fe8fb19SBen Gras 	_DIAGASSERT(dst != NULL);
8462fe8fb19SBen Gras 
8472fe8fb19SBen Gras 	/* Stash a temporary copy so our caller can update in place. */
84884d9c625SLionel Sambuc 	(void)memcpy(tmp, src, NS_INADDRSZ);
8492fe8fb19SBen Gras 	/* Mark this ipv6 addr as a mapped ipv4. */
8502fe8fb19SBen Gras 	for (i = 0; i < 10; i++)
8512fe8fb19SBen Gras 		*p++ = 0x00;
8522fe8fb19SBen Gras 	*p++ = 0xff;
8532fe8fb19SBen Gras 	*p++ = 0xff;
8542fe8fb19SBen Gras 	/* Retrieve the saved copy and we're done. */
85584d9c625SLionel Sambuc 	(void)memcpy(p, tmp, NS_INADDRSZ);
8562fe8fb19SBen Gras }
8572fe8fb19SBen Gras 
8582fe8fb19SBen Gras static void
map_v4v6_hostent(struct hostent * hp,char ** bpp,char * ep)8592fe8fb19SBen Gras map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
8602fe8fb19SBen Gras {
8612fe8fb19SBen Gras 	char **ap;
8622fe8fb19SBen Gras 
8632fe8fb19SBen Gras 	_DIAGASSERT(hp != NULL);
8642fe8fb19SBen Gras 	_DIAGASSERT(bpp != NULL);
8652fe8fb19SBen Gras 	_DIAGASSERT(ep != NULL);
8662fe8fb19SBen Gras 
86784d9c625SLionel Sambuc 	if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
8682fe8fb19SBen Gras 		return;
8692fe8fb19SBen Gras 	hp->h_addrtype = AF_INET6;
87084d9c625SLionel Sambuc 	hp->h_length = NS_IN6ADDRSZ;
8712fe8fb19SBen Gras 	for (ap = hp->h_addr_list; *ap; ap++) {
872f14fb602SLionel Sambuc 		int i = (int)(sizeof(align) -
873f14fb602SLionel Sambuc 		    (size_t)((u_long)*bpp % sizeof(align)));
8742fe8fb19SBen Gras 
87584d9c625SLionel Sambuc 		if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
8762fe8fb19SBen Gras 			/* Out of memory.  Truncate address list here.  XXX */
8772fe8fb19SBen Gras 			*ap = NULL;
8782fe8fb19SBen Gras 			return;
8792fe8fb19SBen Gras 		}
8802fe8fb19SBen Gras 		*bpp += i;
8812fe8fb19SBen Gras 		map_v4v6_address(*ap, *bpp);
8822fe8fb19SBen Gras 		*ap = *bpp;
88384d9c625SLionel Sambuc 		*bpp += NS_IN6ADDRSZ;
8842fe8fb19SBen Gras 	}
8852fe8fb19SBen Gras }
8862fe8fb19SBen Gras 
8872fe8fb19SBen Gras static void
addrsort(char ** ap,int num,res_state res)8882fe8fb19SBen Gras addrsort(char **ap, int num, res_state res)
8892fe8fb19SBen Gras {
8902fe8fb19SBen Gras 	int i, j;
8912fe8fb19SBen Gras 	char **p;
8922fe8fb19SBen Gras 	short aval[MAXADDRS];
8932fe8fb19SBen Gras 	int needsort = 0;
8942fe8fb19SBen Gras 
8952fe8fb19SBen Gras 	_DIAGASSERT(ap != NULL);
8962fe8fb19SBen Gras 
8972fe8fb19SBen Gras 	p = ap;
8982fe8fb19SBen Gras 	for (i = 0; i < num; i++, p++) {
8992fe8fb19SBen Gras 	    for (j = 0 ; (unsigned)j < res->nsort; j++)
9002fe8fb19SBen Gras 		if (res->sort_list[j].addr.s_addr ==
9012fe8fb19SBen Gras 		    (((struct in_addr *)(void *)(*p))->s_addr &
9022fe8fb19SBen Gras 		    res->sort_list[j].mask))
9032fe8fb19SBen Gras 			break;
9042fe8fb19SBen Gras 	    aval[i] = j;
9052fe8fb19SBen Gras 	    if (needsort == 0 && i > 0 && j < aval[i-1])
9062fe8fb19SBen Gras 		needsort = i;
9072fe8fb19SBen Gras 	}
9082fe8fb19SBen Gras 	if (!needsort)
9092fe8fb19SBen Gras 	    return;
9102fe8fb19SBen Gras 
9112fe8fb19SBen Gras 	while (needsort < num) {
9122fe8fb19SBen Gras 	    for (j = needsort - 1; j >= 0; j--) {
9132fe8fb19SBen Gras 		if (aval[j] > aval[j+1]) {
9142fe8fb19SBen Gras 		    char *hp;
9152fe8fb19SBen Gras 
9162fe8fb19SBen Gras 		    i = aval[j];
9172fe8fb19SBen Gras 		    aval[j] = aval[j+1];
9182fe8fb19SBen Gras 		    aval[j+1] = i;
9192fe8fb19SBen Gras 
9202fe8fb19SBen Gras 		    hp = ap[j];
9212fe8fb19SBen Gras 		    ap[j] = ap[j+1];
9222fe8fb19SBen Gras 		    ap[j+1] = hp;
9232fe8fb19SBen Gras 		} else
9242fe8fb19SBen Gras 		    break;
9252fe8fb19SBen Gras 	    }
9262fe8fb19SBen Gras 	    needsort++;
9272fe8fb19SBen Gras 	}
9282fe8fb19SBen Gras }
9292fe8fb19SBen Gras 
9302fe8fb19SBen Gras 
9312fe8fb19SBen Gras /*ARGSUSED*/
9322fe8fb19SBen Gras int
_dns_gethtbyname(void * rv,void * cb_data,va_list ap)9332fe8fb19SBen Gras _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
9342fe8fb19SBen Gras {
9352fe8fb19SBen Gras 	querybuf *buf;
9362fe8fb19SBen Gras 	int n, type;
9372fe8fb19SBen Gras 	struct hostent *hp;
9382fe8fb19SBen Gras 	const char *name;
9392fe8fb19SBen Gras 	res_state res;
94084d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
9412fe8fb19SBen Gras 
9422fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
9432fe8fb19SBen Gras 
9442fe8fb19SBen Gras 	name = va_arg(ap, char *);
94584d9c625SLionel Sambuc 	/* NOSTRICT skip string len */(void)va_arg(ap, int);
94684d9c625SLionel Sambuc 	info->hp->h_addrtype = va_arg(ap, int);
9472fe8fb19SBen Gras 
94884d9c625SLionel Sambuc 	switch (info->hp->h_addrtype) {
9492fe8fb19SBen Gras 	case AF_INET:
95084d9c625SLionel Sambuc 		info->hp->h_length = NS_INADDRSZ;
9512fe8fb19SBen Gras 		type = T_A;
9522fe8fb19SBen Gras 		break;
9532fe8fb19SBen Gras 	case AF_INET6:
95484d9c625SLionel Sambuc 		info->hp->h_length = NS_IN6ADDRSZ;
9552fe8fb19SBen Gras 		type = T_AAAA;
9562fe8fb19SBen Gras 		break;
9572fe8fb19SBen Gras 	default:
9582fe8fb19SBen Gras 		return NS_UNAVAIL;
9592fe8fb19SBen Gras 	}
9602fe8fb19SBen Gras 	buf = malloc(sizeof(*buf));
9612fe8fb19SBen Gras 	if (buf == NULL) {
96284d9c625SLionel Sambuc 		*info->he = NETDB_INTERNAL;
9632fe8fb19SBen Gras 		return NS_NOTFOUND;
9642fe8fb19SBen Gras 	}
9652fe8fb19SBen Gras 	res = __res_get_state();
9662fe8fb19SBen Gras 	if (res == NULL) {
9672fe8fb19SBen Gras 		free(buf);
968*0a6a1f1dSLionel Sambuc 		*info->he = NETDB_INTERNAL;
9692fe8fb19SBen Gras 		return NS_NOTFOUND;
9702fe8fb19SBen Gras 	}
971f14fb602SLionel Sambuc 	n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
9722fe8fb19SBen Gras 	if (n < 0) {
9732fe8fb19SBen Gras 		free(buf);
9742fe8fb19SBen Gras 		debugprintf("res_nsearch failed (%d)\n", res, n);
9752fe8fb19SBen Gras 		__res_put_state(res);
9762fe8fb19SBen Gras 		return NS_NOTFOUND;
9772fe8fb19SBen Gras 	}
97884d9c625SLionel Sambuc 	hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
97984d9c625SLionel Sambuc 	    info->buflen, info->he);
9802fe8fb19SBen Gras 	free(buf);
9812fe8fb19SBen Gras 	__res_put_state(res);
9822fe8fb19SBen Gras 	if (hp == NULL)
983*0a6a1f1dSLionel Sambuc 		switch (*info->he) {
9842fe8fb19SBen Gras 		case HOST_NOT_FOUND:
9852fe8fb19SBen Gras 			return NS_NOTFOUND;
9862fe8fb19SBen Gras 		case TRY_AGAIN:
9872fe8fb19SBen Gras 			return NS_TRYAGAIN;
9882fe8fb19SBen Gras 		default:
9892fe8fb19SBen Gras 			return NS_UNAVAIL;
9902fe8fb19SBen Gras 		}
9912fe8fb19SBen Gras 	return NS_SUCCESS;
9922fe8fb19SBen Gras }
9932fe8fb19SBen Gras 
9942fe8fb19SBen Gras /*ARGSUSED*/
9952fe8fb19SBen Gras int
_dns_gethtbyaddr(void * rv,void * cb_data,va_list ap)9962fe8fb19SBen Gras _dns_gethtbyaddr(void *rv, void	*cb_data, va_list ap)
9972fe8fb19SBen Gras {
9982fe8fb19SBen Gras 	char qbuf[MAXDNAME + 1], *qp, *ep;
9992fe8fb19SBen Gras 	int n;
10002fe8fb19SBen Gras 	querybuf *buf;
10012fe8fb19SBen Gras 	struct hostent *hp;
10022fe8fb19SBen Gras 	const unsigned char *uaddr;
100384d9c625SLionel Sambuc 	int advance;
10042fe8fb19SBen Gras 	res_state res;
100584d9c625SLionel Sambuc 	char *bf;
100684d9c625SLionel Sambuc 	size_t blen;
100784d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
10082fe8fb19SBen Gras 
10092fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
10102fe8fb19SBen Gras 
10112fe8fb19SBen Gras 	uaddr = va_arg(ap, unsigned char *);
101284d9c625SLionel Sambuc 	info->hp->h_length = va_arg(ap, int);
101384d9c625SLionel Sambuc 	info->hp->h_addrtype = va_arg(ap, int);
10142fe8fb19SBen Gras 
101584d9c625SLionel Sambuc 	switch (info->hp->h_addrtype) {
10162fe8fb19SBen Gras 	case AF_INET:
10172fe8fb19SBen Gras 		(void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
10182fe8fb19SBen Gras 		    (uaddr[3] & 0xff), (uaddr[2] & 0xff),
10192fe8fb19SBen Gras 		    (uaddr[1] & 0xff), (uaddr[0] & 0xff));
10202fe8fb19SBen Gras 		break;
10212fe8fb19SBen Gras 
10222fe8fb19SBen Gras 	case AF_INET6:
10232fe8fb19SBen Gras 		qp = qbuf;
10242fe8fb19SBen Gras 		ep = qbuf + sizeof(qbuf) - 1;
102584d9c625SLionel Sambuc 		for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
10262fe8fb19SBen Gras 			advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
10272fe8fb19SBen Gras 			    uaddr[n] & 0xf,
10282fe8fb19SBen Gras 			    ((unsigned int)uaddr[n] >> 4) & 0xf);
10292fe8fb19SBen Gras 			if (advance > 0 && qp + advance < ep)
10302fe8fb19SBen Gras 				qp += advance;
1031*0a6a1f1dSLionel Sambuc 			else
1032*0a6a1f1dSLionel Sambuc 				goto norecovery;
10332fe8fb19SBen Gras 		}
1034*0a6a1f1dSLionel Sambuc 		if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf))
1035*0a6a1f1dSLionel Sambuc 			goto norecovery;
10362fe8fb19SBen Gras 		break;
10372fe8fb19SBen Gras 	default:
1038*0a6a1f1dSLionel Sambuc 		goto norecovery;
10392fe8fb19SBen Gras 	}
10402fe8fb19SBen Gras 
10412fe8fb19SBen Gras 	buf = malloc(sizeof(*buf));
10422fe8fb19SBen Gras 	if (buf == NULL) {
1043*0a6a1f1dSLionel Sambuc 		goto nospc;
10442fe8fb19SBen Gras 	}
10452fe8fb19SBen Gras 	res = __res_get_state();
10462fe8fb19SBen Gras 	if (res == NULL) {
10472fe8fb19SBen Gras 		free(buf);
1048*0a6a1f1dSLionel Sambuc 		goto nospc;
10492fe8fb19SBen Gras 	}
1050f14fb602SLionel Sambuc 	n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
10512fe8fb19SBen Gras 	if (n < 0) {
10522fe8fb19SBen Gras 		free(buf);
10532fe8fb19SBen Gras 		debugprintf("res_nquery failed (%d)\n", res, n);
10542fe8fb19SBen Gras 		__res_put_state(res);
1055*0a6a1f1dSLionel Sambuc 		*info->he = HOST_NOT_FOUND;
10562fe8fb19SBen Gras 		return NS_NOTFOUND;
10572fe8fb19SBen Gras 	}
105884d9c625SLionel Sambuc 	hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
105984d9c625SLionel Sambuc 	    info->buflen, info->he);
10602fe8fb19SBen Gras 	free(buf);
10612fe8fb19SBen Gras 	if (hp == NULL) {
10622fe8fb19SBen Gras 		__res_put_state(res);
106384d9c625SLionel Sambuc 		switch (*info->he) {
10642fe8fb19SBen Gras 		case HOST_NOT_FOUND:
10652fe8fb19SBen Gras 			return NS_NOTFOUND;
10662fe8fb19SBen Gras 		case TRY_AGAIN:
10672fe8fb19SBen Gras 			return NS_TRYAGAIN;
10682fe8fb19SBen Gras 		default:
10692fe8fb19SBen Gras 			return NS_UNAVAIL;
10702fe8fb19SBen Gras 		}
10712fe8fb19SBen Gras 	}
107284d9c625SLionel Sambuc 
107384d9c625SLionel Sambuc 	bf = (void *)(hp->h_addr_list + 2);
107484d9c625SLionel Sambuc 	blen = (size_t)(bf - info->buf);
107584d9c625SLionel Sambuc 	if (blen + info->hp->h_length > info->buflen)
107684d9c625SLionel Sambuc 		goto nospc;
107784d9c625SLionel Sambuc 	hp->h_addr_list[0] = bf;
107884d9c625SLionel Sambuc 	hp->h_addr_list[1] = NULL;
107984d9c625SLionel Sambuc 	(void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
108084d9c625SLionel Sambuc 	if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1081*0a6a1f1dSLionel Sambuc 		if (blen + NS_IN6ADDRSZ > info->buflen) {
1082*0a6a1f1dSLionel Sambuc 			__res_put_state(res);
108384d9c625SLionel Sambuc 			goto nospc;
1084*0a6a1f1dSLionel Sambuc 		}
108584d9c625SLionel Sambuc 		map_v4v6_address(bf, bf);
10862fe8fb19SBen Gras 		hp->h_addrtype = AF_INET6;
108784d9c625SLionel Sambuc 		hp->h_length = NS_IN6ADDRSZ;
10882fe8fb19SBen Gras 	}
10892fe8fb19SBen Gras 
10902fe8fb19SBen Gras 	__res_put_state(res);
109184d9c625SLionel Sambuc 	*info->he = NETDB_SUCCESS;
10922fe8fb19SBen Gras 	return NS_SUCCESS;
109384d9c625SLionel Sambuc nospc:
109484d9c625SLionel Sambuc 	*info->he = NETDB_INTERNAL;
109584d9c625SLionel Sambuc 	return NS_UNAVAIL;
1096*0a6a1f1dSLionel Sambuc norecovery:
1097*0a6a1f1dSLionel Sambuc 	*info->he = NO_RECOVERY;
1098*0a6a1f1dSLionel Sambuc 	return NS_UNAVAIL;
10992fe8fb19SBen Gras }
11002fe8fb19SBen Gras 
11012fe8fb19SBen Gras #ifdef YP
11022fe8fb19SBen Gras /*ARGSUSED*/
110384d9c625SLionel Sambuc static struct hostent *
_yp_hostent(char * line,int af,struct getnamaddr * info)110484d9c625SLionel Sambuc _yp_hostent(char *line, int af, struct getnamaddr *info)
11052fe8fb19SBen Gras {
110684d9c625SLionel Sambuc 	struct in6_addr host_addrs[MAXADDRS];
1107*0a6a1f1dSLionel Sambuc 	char **aliases;
1108*0a6a1f1dSLionel Sambuc 	size_t maxaliases;
11092fe8fb19SBen Gras 	char *p = line;
111084d9c625SLionel Sambuc 	char *cp, **q, *ptr;
111184d9c625SLionel Sambuc 	size_t len, anum, i;
11122fe8fb19SBen Gras 	int addrok;
11132fe8fb19SBen Gras 	int more;
11142fe8fb19SBen Gras 	size_t naddrs;
111584d9c625SLionel Sambuc 	struct hostent *hp = info->hp;
11162fe8fb19SBen Gras 
11172fe8fb19SBen Gras 	_DIAGASSERT(line != NULL);
11182fe8fb19SBen Gras 
111984d9c625SLionel Sambuc 	hp->h_name = NULL;
112084d9c625SLionel Sambuc 	hp->h_addrtype = af;
11212fe8fb19SBen Gras 	switch (af) {
11222fe8fb19SBen Gras 	case AF_INET:
112384d9c625SLionel Sambuc 		hp->h_length = NS_INADDRSZ;
11242fe8fb19SBen Gras 		break;
11252fe8fb19SBen Gras 	case AF_INET6:
112684d9c625SLionel Sambuc 		hp->h_length = NS_IN6ADDRSZ;
11272fe8fb19SBen Gras 		break;
11282fe8fb19SBen Gras 	default:
11292fe8fb19SBen Gras 		return NULL;
11302fe8fb19SBen Gras 	}
1131*0a6a1f1dSLionel Sambuc 	setup(aliases, maxaliases);
11322fe8fb19SBen Gras 	naddrs = 0;
113384d9c625SLionel Sambuc 	q = aliases;
11342fe8fb19SBen Gras 
11352fe8fb19SBen Gras nextline:
11362fe8fb19SBen Gras 	/* check for host_addrs overflow */
113784d9c625SLionel Sambuc 	if (naddrs >= __arraycount(host_addrs))
11382fe8fb19SBen Gras 		goto done;
11392fe8fb19SBen Gras 
11402fe8fb19SBen Gras 	more = 0;
11412fe8fb19SBen Gras 	cp = strpbrk(p, " \t");
11422fe8fb19SBen Gras 	if (cp == NULL)
11432fe8fb19SBen Gras 		goto done;
11442fe8fb19SBen Gras 	*cp++ = '\0';
11452fe8fb19SBen Gras 
11462fe8fb19SBen Gras 	/* p has should have an address */
114784d9c625SLionel Sambuc 	addrok = inet_pton(af, p, &host_addrs[naddrs]);
11482fe8fb19SBen Gras 	if (addrok != 1) {
11492fe8fb19SBen Gras 		/* skip to the next line */
11502fe8fb19SBen Gras 		while (cp && *cp) {
11512fe8fb19SBen Gras 			if (*cp == '\n') {
11522fe8fb19SBen Gras 				cp++;
11532fe8fb19SBen Gras 				goto nextline;
11542fe8fb19SBen Gras 			}
11552fe8fb19SBen Gras 			cp++;
11562fe8fb19SBen Gras 		}
11572fe8fb19SBen Gras 		goto done;
11582fe8fb19SBen Gras 	}
1159*0a6a1f1dSLionel Sambuc 	naddrs++;
11602fe8fb19SBen Gras 
11612fe8fb19SBen Gras 	while (*cp == ' ' || *cp == '\t')
11622fe8fb19SBen Gras 		cp++;
11632fe8fb19SBen Gras 	p = cp;
11642fe8fb19SBen Gras 	cp = strpbrk(p, " \t\n");
11652fe8fb19SBen Gras 	if (cp != NULL) {
11662fe8fb19SBen Gras 		if (*cp == '\n')
11672fe8fb19SBen Gras 			more = 1;
11682fe8fb19SBen Gras 		*cp++ = '\0';
11692fe8fb19SBen Gras 	}
117084d9c625SLionel Sambuc 	if (!hp->h_name)
117184d9c625SLionel Sambuc 		hp->h_name = p;
117284d9c625SLionel Sambuc 	else if (strcmp(hp->h_name, p) == 0)
11732fe8fb19SBen Gras 		;
1174*0a6a1f1dSLionel Sambuc 	else
1175*0a6a1f1dSLionel Sambuc 		addalias(q, p, aliases, maxaliases);
11762fe8fb19SBen Gras 	p = cp;
11772fe8fb19SBen Gras 	if (more)
11782fe8fb19SBen Gras 		goto nextline;
11792fe8fb19SBen Gras 
11802fe8fb19SBen Gras 	while (cp && *cp) {
11812fe8fb19SBen Gras 		if (*cp == ' ' || *cp == '\t') {
11822fe8fb19SBen Gras 			cp++;
11832fe8fb19SBen Gras 			continue;
11842fe8fb19SBen Gras 		}
11852fe8fb19SBen Gras 		if (*cp == '\n') {
11862fe8fb19SBen Gras 			cp++;
11872fe8fb19SBen Gras 			goto nextline;
11882fe8fb19SBen Gras 		}
1189*0a6a1f1dSLionel Sambuc 		addalias(q, cp, aliases, maxaliases);
11902fe8fb19SBen Gras 		cp = strpbrk(cp, " \t");
11912fe8fb19SBen Gras 		if (cp != NULL)
11922fe8fb19SBen Gras 			*cp++ = '\0';
11932fe8fb19SBen Gras 	}
11942fe8fb19SBen Gras 
11952fe8fb19SBen Gras done:
1196*0a6a1f1dSLionel Sambuc 	if (hp->h_name == NULL) {
1197*0a6a1f1dSLionel Sambuc 		free(aliases);
11982fe8fb19SBen Gras 		return NULL;
1199*0a6a1f1dSLionel Sambuc 	}
120084d9c625SLionel Sambuc 
120184d9c625SLionel Sambuc 	ptr = info->buf;
120284d9c625SLionel Sambuc 	len = info->buflen;
120384d9c625SLionel Sambuc 
120484d9c625SLionel Sambuc 	anum = (size_t)(q - aliases);
120584d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
120684d9c625SLionel Sambuc 	HENT_ARRAY(hp->h_aliases, anum, ptr, len);
120784d9c625SLionel Sambuc 
120884d9c625SLionel Sambuc 	for (i = 0; i < naddrs; i++)
120984d9c625SLionel Sambuc 		HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
121084d9c625SLionel Sambuc 		    ptr, len);
121184d9c625SLionel Sambuc 	hp->h_addr_list[naddrs] = NULL;
121284d9c625SLionel Sambuc 
121384d9c625SLionel Sambuc 	HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
121484d9c625SLionel Sambuc 
121584d9c625SLionel Sambuc 	for (i = 0; i < anum; i++)
121684d9c625SLionel Sambuc 		HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
121784d9c625SLionel Sambuc 	hp->h_aliases[anum] = NULL;
1218*0a6a1f1dSLionel Sambuc 	free(aliases);
121984d9c625SLionel Sambuc 
122084d9c625SLionel Sambuc 	return hp;
122184d9c625SLionel Sambuc nospc:
1222*0a6a1f1dSLionel Sambuc 	free(aliases);
122384d9c625SLionel Sambuc 	*info->he = NETDB_INTERNAL;
122484d9c625SLionel Sambuc 	errno = ENOSPC;
122584d9c625SLionel Sambuc 	return NULL;
12262fe8fb19SBen Gras }
12272fe8fb19SBen Gras 
12282fe8fb19SBen Gras /*ARGSUSED*/
12292fe8fb19SBen Gras int
_yp_gethtbyaddr(void * rv,void * cb_data,va_list ap)12302fe8fb19SBen Gras _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
12312fe8fb19SBen Gras {
12322fe8fb19SBen Gras 	struct hostent *hp = NULL;
123384d9c625SLionel Sambuc 	char *ypcurrent;
123484d9c625SLionel Sambuc 	int ypcurrentlen, r;
12352fe8fb19SBen Gras 	char name[INET6_ADDRSTRLEN];	/* XXX enough? */
12362fe8fb19SBen Gras 	const unsigned char *uaddr;
12372fe8fb19SBen Gras 	int af;
12382fe8fb19SBen Gras 	const char *map;
123984d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
12402fe8fb19SBen Gras 
12412fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
12422fe8fb19SBen Gras 
12432fe8fb19SBen Gras 	uaddr = va_arg(ap, unsigned char *);
12442fe8fb19SBen Gras 	/* NOSTRICT skip len */(void)va_arg(ap, int);
12452fe8fb19SBen Gras 	af = va_arg(ap, int);
12462fe8fb19SBen Gras 
12472fe8fb19SBen Gras 	if (!__ypdomain) {
12482fe8fb19SBen Gras 		if (_yp_check(&__ypdomain) == 0)
12492fe8fb19SBen Gras 			return NS_UNAVAIL;
12502fe8fb19SBen Gras 	}
12512fe8fb19SBen Gras 	/*
12522fe8fb19SBen Gras 	 * XXX unfortunately, we cannot support IPv6 extended scoped address
12532fe8fb19SBen Gras 	 * notation here.  gethostbyaddr() is not scope-aware.  too bad.
12542fe8fb19SBen Gras 	 */
1255f14fb602SLionel Sambuc 	if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
12562fe8fb19SBen Gras 		return NS_UNAVAIL;
12572fe8fb19SBen Gras 	switch (af) {
12582fe8fb19SBen Gras 	case AF_INET:
12592fe8fb19SBen Gras 		map = "hosts.byaddr";
12602fe8fb19SBen Gras 		break;
12612fe8fb19SBen Gras 	default:
12622fe8fb19SBen Gras 		map = "ipnodes.byaddr";
12632fe8fb19SBen Gras 		break;
12642fe8fb19SBen Gras 	}
126584d9c625SLionel Sambuc 	ypcurrent = NULL;
12662fe8fb19SBen Gras 	r = yp_match(__ypdomain, map, name,
126784d9c625SLionel Sambuc 		(int)strlen(name), &ypcurrent, &ypcurrentlen);
12682fe8fb19SBen Gras 	if (r == 0)
126984d9c625SLionel Sambuc 		hp = _yp_hostent(ypcurrent, af, info);
127084d9c625SLionel Sambuc 	else
127184d9c625SLionel Sambuc 		hp = NULL;
127284d9c625SLionel Sambuc 	free(ypcurrent);
12732fe8fb19SBen Gras 	if (hp == NULL) {
127484d9c625SLionel Sambuc 		*info->he = HOST_NOT_FOUND;
12752fe8fb19SBen Gras 		return NS_NOTFOUND;
12762fe8fb19SBen Gras 	}
12772fe8fb19SBen Gras 	return NS_SUCCESS;
12782fe8fb19SBen Gras }
12792fe8fb19SBen Gras 
12802fe8fb19SBen Gras /*ARGSUSED*/
12812fe8fb19SBen Gras int
_yp_gethtbyname(void * rv,void * cb_data,va_list ap)12822fe8fb19SBen Gras _yp_gethtbyname(void *rv, void *cb_data, va_list ap)
12832fe8fb19SBen Gras {
128484d9c625SLionel Sambuc 	struct hostent *hp;
128584d9c625SLionel Sambuc 	char *ypcurrent;
128684d9c625SLionel Sambuc 	int ypcurrentlen, r;
12872fe8fb19SBen Gras 	const char *name;
12882fe8fb19SBen Gras 	int af;
12892fe8fb19SBen Gras 	const char *map;
129084d9c625SLionel Sambuc 	struct getnamaddr *info = rv;
12912fe8fb19SBen Gras 
12922fe8fb19SBen Gras 	_DIAGASSERT(rv != NULL);
12932fe8fb19SBen Gras 
12942fe8fb19SBen Gras 	name = va_arg(ap, char *);
129584d9c625SLionel Sambuc 	/* NOSTRICT skip string len */(void)va_arg(ap, int);
12962fe8fb19SBen Gras 	af = va_arg(ap, int);
12972fe8fb19SBen Gras 
12982fe8fb19SBen Gras 	if (!__ypdomain) {
12992fe8fb19SBen Gras 		if (_yp_check(&__ypdomain) == 0)
13002fe8fb19SBen Gras 			return NS_UNAVAIL;
13012fe8fb19SBen Gras 	}
13022fe8fb19SBen Gras 	switch (af) {
13032fe8fb19SBen Gras 	case AF_INET:
13042fe8fb19SBen Gras 		map = "hosts.byname";
13052fe8fb19SBen Gras 		break;
13062fe8fb19SBen Gras 	default:
13072fe8fb19SBen Gras 		map = "ipnodes.byname";
13082fe8fb19SBen Gras 		break;
13092fe8fb19SBen Gras 	}
131084d9c625SLionel Sambuc 	ypcurrent = NULL;
13112fe8fb19SBen Gras 	r = yp_match(__ypdomain, map, name,
131284d9c625SLionel Sambuc 		(int)strlen(name), &ypcurrent, &ypcurrentlen);
13132fe8fb19SBen Gras 	if (r == 0)
131484d9c625SLionel Sambuc 		hp = _yp_hostent(ypcurrent, af, info);
131584d9c625SLionel Sambuc 	else
131684d9c625SLionel Sambuc 		hp = NULL;
131784d9c625SLionel Sambuc 	free(ypcurrent);
13182fe8fb19SBen Gras 	if (hp == NULL) {
131984d9c625SLionel Sambuc 		*info->he = HOST_NOT_FOUND;
13202fe8fb19SBen Gras 		return NS_NOTFOUND;
13212fe8fb19SBen Gras 	}
13222fe8fb19SBen Gras 	return NS_SUCCESS;
13232fe8fb19SBen Gras }
13242fe8fb19SBen Gras #endif
132584d9c625SLionel Sambuc 
132684d9c625SLionel Sambuc /*
132784d9c625SLionel Sambuc  * Non-reentrant versions.
132884d9c625SLionel Sambuc  */
132984d9c625SLionel Sambuc FILE *_h_file;
133084d9c625SLionel Sambuc static struct hostent h_ent;
133184d9c625SLionel Sambuc static char h_buf[16384];
133284d9c625SLionel Sambuc 
133384d9c625SLionel Sambuc struct hostent *
gethostbyaddr(const void * addr,socklen_t len,int af)133484d9c625SLionel Sambuc gethostbyaddr(const void *addr, socklen_t len, int af) {
133584d9c625SLionel Sambuc 	return gethostbyaddr_r(addr, len, af, &h_ent, h_buf, sizeof(h_buf),
133684d9c625SLionel Sambuc 	    &h_errno);
133784d9c625SLionel Sambuc }
133884d9c625SLionel Sambuc 
133984d9c625SLionel Sambuc struct hostent *
gethostbyname(const char * name)134084d9c625SLionel Sambuc gethostbyname(const char *name) {
134184d9c625SLionel Sambuc 	return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno);
134284d9c625SLionel Sambuc }
134384d9c625SLionel Sambuc 
134484d9c625SLionel Sambuc struct hostent *
gethostbyname2(const char * name,int af)134584d9c625SLionel Sambuc gethostbyname2(const char *name, int af) {
134684d9c625SLionel Sambuc 	return gethostbyname2_r(name, af, &h_ent, h_buf, sizeof(h_buf),
134784d9c625SLionel Sambuc 	    &h_errno);
134884d9c625SLionel Sambuc }
134984d9c625SLionel Sambuc 
135084d9c625SLionel Sambuc struct hostent *
gethostent(void)135184d9c625SLionel Sambuc gethostent(void)
135284d9c625SLionel Sambuc {
135384d9c625SLionel Sambuc 	if (_h_file == NULL) {
135484d9c625SLionel Sambuc 		sethostent_r(&_h_file);
135584d9c625SLionel Sambuc 		if (_h_file == NULL) {
135684d9c625SLionel Sambuc 			h_errno = NETDB_INTERNAL;
135784d9c625SLionel Sambuc 			return NULL;
135884d9c625SLionel Sambuc 		}
135984d9c625SLionel Sambuc 	}
136084d9c625SLionel Sambuc 	memset(&h_ent, 0, sizeof(h_ent));
136184d9c625SLionel Sambuc 	return gethostent_r(_h_file, &h_ent, h_buf, sizeof(h_buf), &h_errno);
136284d9c625SLionel Sambuc }
136384d9c625SLionel Sambuc 
1364