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