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