Annotation of src/lib/libc/net/gethnamaddr.c, Revision 1.93
1.93 ! is 1: /* $NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 christos Exp $ */
1.2 mrg 2:
1.1 mrg 3: /*
4: * ++Copyright++ 1985, 1988, 1993
5: * -
6: * Copyright (c) 1985, 1988, 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
1.55 agc 17: * 3. Neither the name of the University nor the names of its contributors
1.1 mrg 18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: * -
33: * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34: *
35: * Permission to use, copy, modify, and distribute this software for any
36: * purpose with or without fee is hereby granted, provided that the above
37: * copyright notice and this permission notice appear in all copies, and that
38: * the name of Digital Equipment Corporation not be used in advertising or
39: * publicity pertaining to distribution of the document or software without
40: * specific, written prior permission.
41: *
42: * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43: * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45: * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49: * SOFTWARE.
50: * -
51: * --Copyright--
52: */
53:
1.2 mrg 54: #include <sys/cdefs.h>
1.1 mrg 55: #if defined(LIBC_SCCS) && !defined(lint)
1.2 mrg 56: #if 0
1.1 mrg 57: static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
1.4 perry 58: static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp ";
1.2 mrg 59: #else
1.93 ! is 60: __RCSID("$NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 christos Exp $");
1.2 mrg 61: #endif
1.1 mrg 62: #endif /* LIBC_SCCS and not lint */
63:
1.6 kleink 64: #if defined(_LIBC)
1.3 thorpej 65: #include "namespace.h"
1.6 kleink 66: #endif
1.1 mrg 67: #include <sys/param.h>
68: #include <sys/socket.h>
69: #include <netinet/in.h>
70: #include <arpa/inet.h>
71: #include <arpa/nameser.h>
72:
1.25 lukem 73: #include <assert.h>
74: #include <ctype.h>
75: #include <errno.h>
1.1 mrg 76: #include <netdb.h>
77: #include <resolv.h>
1.44 wiz 78: #include <stdarg.h>
1.25 lukem 79: #include <stdio.h>
1.1 mrg 80: #include <syslog.h>
81:
82: #ifndef LOG_AUTH
83: # define LOG_AUTH 0
84: #endif
85:
86: #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
87:
1.9 lukem 88: #include <nsswitch.h>
1.2 mrg 89: #include <stdlib.h>
90: #include <string.h>
1.1 mrg 91:
1.2 mrg 92: #ifdef YP
93: #include <rpc/rpc.h>
94: #include <rpcsvc/yp_prot.h>
95: #include <rpcsvc/ypclnt.h>
1.5 kleink 96: #endif
97:
1.80 christos 98: #include "hostent.h"
99:
1.6 kleink 100: #if defined(_LIBC) && defined(__weak_alias)
1.29 mycroft 101: __weak_alias(gethostbyaddr,_gethostbyaddr)
102: __weak_alias(gethostbyname,_gethostbyname)
1.63 ginsbach 103: __weak_alias(gethostent,_gethostent)
1.1 mrg 104: #endif
105:
1.79 christos 106: #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
107: (ok)(nm) != 0)
108: #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
109: #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
110:
1.87 christos 111: #define addalias(d, s, arr, siz) do { \
1.89 drochner 112: if (d >= &arr[siz]) { \
113: char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
1.87 christos 114: if (xptr == NULL) \
115: goto nospc; \
116: d = xptr + (d - arr); \
117: arr = xptr; \
118: siz += 10; \
119: } \
120: *d++ = s; \
1.86 christos 121: } while (/*CONSTCOND*/0)
122:
1.87 christos 123: #define setup(arr, siz) do { \
1.89 drochner 124: arr = malloc((siz = 10) * sizeof(*arr)); \
1.87 christos 125: if (arr == NULL) \
126: goto nospc; \
1.86 christos 127: } while (/*CONSTCOND*/0)
128:
1.79 christos 129:
1.1 mrg 130: static const char AskedForGot[] =
1.80 christos 131: "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1.1 mrg 132:
133:
1.2 mrg 134: #ifdef YP
135: static char *__ypdomain;
136: #endif
137:
1.52 itojun 138: #define MAXPACKET (64*1024)
1.1 mrg 139:
140: typedef union {
1.80 christos 141: HEADER hdr;
142: u_char buf[MAXPACKET];
1.1 mrg 143: } querybuf;
144:
145: typedef union {
1.80 christos 146: int32_t al;
147: char ac;
1.1 mrg 148: } align;
149:
150: #ifdef DEBUG
1.76 christos 151: static void debugprintf(const char *, res_state, ...)
1.59 christos 152: __attribute__((__format__(__printf__, 1, 3)));
1.2 mrg 153: #endif
1.59 christos 154: static struct hostent *getanswer(const querybuf *, int, const char *, int,
1.80 christos 155: res_state, struct hostent *, char *, size_t, int *);
1.59 christos 156: static void map_v4v6_address(const char *, char *);
157: static void map_v4v6_hostent(struct hostent *, char **, char *);
1.66 tsarna 158: static void addrsort(char **, int, res_state);
1.2 mrg 159:
1.59 christos 160: void dns_service(void);
1.39 christos 161: #undef dn_skipname
1.59 christos 162: int dn_skipname(const u_char *, const u_char *);
1.80 christos 163:
1.2 mrg 164: #ifdef YP
1.80 christos 165: static struct hostent *_yp_hostent(char *, int, struct getnamaddr *);
1.2 mrg 166: #endif
167:
1.80 christos 168: static struct hostent *gethostbyname_internal(const char *, int, res_state,
169: struct hostent *, char *, size_t, int *);
1.59 christos 170:
1.12 lukem 171: static const ns_src default_dns_files[] = {
1.27 lukem 172: { NSSRC_FILES, NS_SUCCESS },
1.11 lukem 173: { NSSRC_DNS, NS_SUCCESS },
1.71 christos 174: { 0, 0 }
1.11 lukem 175: };
176:
1.2 mrg 177:
178: #ifdef DEBUG
1.1 mrg 179: static void
1.76 christos 180: debugprintf(const char *msg, res_state res, ...)
1.1 mrg 181: {
1.25 lukem 182: _DIAGASSERT(msg != NULL);
183:
1.59 christos 184: if (res->options & RES_DEBUG) {
1.1 mrg 185: int save = errno;
1.38 sommerfe 186: va_list ap;
1.1 mrg 187:
1.68 christos 188: va_start (ap, res);
1.38 sommerfe 189: vprintf(msg, ap);
190: va_end (ap);
191:
1.1 mrg 192: errno = save;
193: }
194: }
195: #else
1.76 christos 196: # define debugprintf(msg, res, num) /*nada*/
1.1 mrg 197: #endif
198:
1.32 itojun 199: #define BOUNDED_INCR(x) \
200: do { \
1.58 enami 201: cp += (x); \
1.90 christos 202: if (cp > eom) \
203: goto no_recovery; \
1.34 christos 204: } while (/*CONSTCOND*/0)
1.32 itojun 205:
206: #define BOUNDS_CHECK(ptr, count) \
207: do { \
1.90 christos 208: if ((ptr) + (count) > eom) \
209: goto no_recovery; \
1.34 christos 210: } while (/*CONSTCOND*/0)
1.32 itojun 211:
1.1 mrg 212: static struct hostent *
1.59 christos 213: getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
1.80 christos 214: res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
1.1 mrg 215: {
1.25 lukem 216: const HEADER *hp;
217: const u_char *cp;
218: int n;
1.80 christos 219: size_t qlen;
1.32 itojun 220: const u_char *eom, *erdata;
1.46 itojun 221: char *bp, **ap, **hap, *ep;
222: int type, class, ancount, qdcount;
1.1 mrg 223: int haveanswer, had_error;
224: int toobig = 0;
225: char tbuf[MAXDNAME];
1.86 christos 226: char **aliases;
227: size_t maxaliases;
1.83 christos 228: char *addr_ptrs[MAXADDRS];
1.1 mrg 229: const char *tname;
1.59 christos 230: int (*name_ok)(const char *);
1.1 mrg 231:
1.25 lukem 232: _DIAGASSERT(answer != NULL);
233: _DIAGASSERT(qname != NULL);
234:
1.1 mrg 235: tname = qname;
1.80 christos 236: hent->h_name = NULL;
1.1 mrg 237: eom = answer->buf + anslen;
238: switch (qtype) {
239: case T_A:
240: case T_AAAA:
241: name_ok = res_hnok;
242: break;
243: case T_PTR:
244: name_ok = res_dnok;
245: break;
246: default:
1.92 christos 247: *he = NO_RECOVERY;
1.59 christos 248: return NULL; /* XXX should be abort(); */
1.1 mrg 249: }
1.86 christos 250:
251: setup(aliases, maxaliases);
1.1 mrg 252: /*
253: * find first satisfactory answer
254: */
255: hp = &answer->hdr;
256: ancount = ntohs(hp->ancount);
257: qdcount = ntohs(hp->qdcount);
1.80 christos 258: bp = buf;
259: ep = buf + buflen;
1.32 itojun 260: cp = answer->buf;
261: BOUNDED_INCR(HFIXEDSZ);
1.80 christos 262: if (qdcount != 1)
263: goto no_recovery;
264:
1.78 christos 265: n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
1.80 christos 266: if ((n < 0) || !maybe_ok(res, bp, name_ok))
267: goto no_recovery;
268:
1.32 itojun 269: BOUNDED_INCR(n + QFIXEDSZ);
1.1 mrg 270: if (qtype == T_A || qtype == T_AAAA) {
271: /* res_send() has already verified that the query name is the
272: * same as the one we sent; this just gets the expanded name
273: * (i.e., with the succeeding search-domain tacked on).
274: */
1.78 christos 275: n = (int)strlen(bp) + 1; /* for the \0 */
1.80 christos 276: if (n >= MAXHOSTNAMELEN)
277: goto no_recovery;
278: hent->h_name = bp;
1.1 mrg 279: bp += n;
280: /* The qname can be abbreviated, but h_name is now absolute. */
1.80 christos 281: qname = hent->h_name;
1.1 mrg 282: }
1.80 christos 283: hent->h_aliases = ap = aliases;
284: hent->h_addr_list = hap = addr_ptrs;
1.1 mrg 285: *ap = NULL;
286: *hap = NULL;
287: haveanswer = 0;
288: had_error = 0;
289: while (ancount-- > 0 && cp < eom && !had_error) {
1.78 christos 290: n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
1.79 christos 291: if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
1.1 mrg 292: had_error++;
293: continue;
294: }
295: cp += n; /* name */
1.32 itojun 296: BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
1.1 mrg 297: type = _getshort(cp);
298: cp += INT16SZ; /* type */
299: class = _getshort(cp);
300: cp += INT16SZ + INT32SZ; /* class, TTL */
301: n = _getshort(cp);
302: cp += INT16SZ; /* len */
1.32 itojun 303: BOUNDS_CHECK(cp, n);
304: erdata = cp + n;
1.1 mrg 305: if (class != C_IN) {
306: /* XXX - debug? syslog? */
307: cp += n;
308: continue; /* XXX - had_error++ ? */
309: }
310: if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
1.80 christos 311: n = dn_expand(answer->buf, eom, cp, tbuf,
312: (int)sizeof tbuf);
1.79 christos 313: if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
1.1 mrg 314: had_error++;
315: continue;
316: }
317: cp += n;
1.80 christos 318: if (cp != erdata)
319: goto no_recovery;
1.1 mrg 320: /* Store alias. */
1.87 christos 321: addalias(ap, bp, aliases, maxaliases);
1.78 christos 322: n = (int)strlen(bp) + 1; /* for the \0 */
1.1 mrg 323: if (n >= MAXHOSTNAMELEN) {
324: had_error++;
325: continue;
326: }
327: bp += n;
328: /* Get canonical name. */
1.78 christos 329: n = (int)strlen(tbuf) + 1; /* for the \0 */
1.46 itojun 330: if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1.1 mrg 331: had_error++;
332: continue;
333: }
1.54 itojun 334: strlcpy(bp, tbuf, (size_t)(ep - bp));
1.80 christos 335: hent->h_name = bp;
1.1 mrg 336: bp += n;
337: continue;
338: }
339: if (qtype == T_PTR && type == T_CNAME) {
1.80 christos 340: n = dn_expand(answer->buf, eom, cp, tbuf,
341: (int)sizeof tbuf);
1.79 christos 342: if (n < 0 || !maybe_dnok(res, tbuf)) {
1.1 mrg 343: had_error++;
344: continue;
345: }
346: cp += n;
1.80 christos 347: if (cp != erdata)
348: goto no_recovery;
1.1 mrg 349: /* Get canonical name. */
1.78 christos 350: n = (int)strlen(tbuf) + 1; /* for the \0 */
1.46 itojun 351: if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1.1 mrg 352: had_error++;
353: continue;
354: }
1.54 itojun 355: strlcpy(bp, tbuf, (size_t)(ep - bp));
1.1 mrg 356: tname = bp;
357: bp += n;
358: continue;
359: }
360: if (type != qtype) {
1.93 ! is 361: if (type != T_KEY && type != T_SIG && type != T_DNAME)
1.28 assar 362: syslog(LOG_NOTICE|LOG_AUTH,
1.1 mrg 363: "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1.28 assar 364: qname, p_class(C_IN), p_type(qtype),
365: p_type(type));
1.1 mrg 366: cp += n;
367: continue; /* XXX - had_error++ ? */
368: }
369: switch (type) {
370: case T_PTR:
371: if (strcasecmp(tname, bp) != 0) {
372: syslog(LOG_NOTICE|LOG_AUTH,
373: AskedForGot, qname, bp);
374: cp += n;
375: continue; /* XXX - had_error++ ? */
376: }
1.78 christos 377: n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
1.79 christos 378: if ((n < 0) || !maybe_hnok(res, bp)) {
1.1 mrg 379: had_error++;
380: break;
381: }
382: #if MULTI_PTRS_ARE_ALIASES
383: cp += n;
1.80 christos 384: if (cp != erdata)
385: goto no_recovery;
1.1 mrg 386: if (!haveanswer)
1.80 christos 387: hent->h_name = bp;
1.87 christos 388: else
389: addalias(ap, bp, aliases, maxaliases);
1.1 mrg 390: if (n != -1) {
1.78 christos 391: n = (int)strlen(bp) + 1; /* for the \0 */
1.1 mrg 392: if (n >= MAXHOSTNAMELEN) {
393: had_error++;
394: break;
395: }
396: bp += n;
397: }
398: break;
399: #else
1.80 christos 400: hent->h_name = bp;
1.59 christos 401: if (res->options & RES_USE_INET6) {
1.1 mrg 402: n = strlen(bp) + 1; /* for the \0 */
403: if (n >= MAXHOSTNAMELEN) {
404: had_error++;
405: break;
406: }
407: bp += n;
1.80 christos 408: map_v4v6_hostent(hent, &bp, ep);
1.1 mrg 409: }
1.80 christos 410: goto success;
1.1 mrg 411: #endif
412: case T_A:
413: case T_AAAA:
1.80 christos 414: if (strcasecmp(hent->h_name, bp) != 0) {
1.1 mrg 415: syslog(LOG_NOTICE|LOG_AUTH,
1.80 christos 416: AskedForGot, hent->h_name, bp);
1.1 mrg 417: cp += n;
418: continue; /* XXX - had_error++ ? */
419: }
1.80 christos 420: if (n != hent->h_length) {
1.1 mrg 421: cp += n;
422: continue;
1.51 itojun 423: }
424: if (type == T_AAAA) {
425: struct in6_addr in6;
1.80 christos 426: memcpy(&in6, cp, NS_IN6ADDRSZ);
1.51 itojun 427: if (IN6_IS_ADDR_V4MAPPED(&in6)) {
428: cp += n;
429: continue;
430: }
1.1 mrg 431: }
432: if (!haveanswer) {
1.25 lukem 433: int nn;
1.1 mrg 434:
1.80 christos 435: hent->h_name = bp;
1.78 christos 436: nn = (int)strlen(bp) + 1; /* for the \0 */
1.1 mrg 437: bp += nn;
438: }
439:
1.14 lukem 440: bp += sizeof(align) -
441: (size_t)((u_long)bp % sizeof(align));
1.1 mrg 442:
1.80 christos 443: if (bp + n >= ep) {
1.76 christos 444: debugprintf("size (%d) too big\n", res, n);
1.1 mrg 445: had_error++;
446: continue;
447: }
1.80 christos 448: if (hap >= &addr_ptrs[MAXADDRS - 1]) {
1.71 christos 449: if (!toobig++) {
1.76 christos 450: debugprintf("Too many addresses (%d)\n",
1.59 christos 451: res, MAXADDRS);
1.71 christos 452: }
1.1 mrg 453: cp += n;
454: continue;
455: }
1.7 kleink 456: (void)memcpy(*hap++ = bp, cp, (size_t)n);
1.1 mrg 457: bp += n;
458: cp += n;
1.80 christos 459: if (cp != erdata)
460: goto no_recovery;
1.1 mrg 461: break;
462: default:
463: abort();
464: }
465: if (!had_error)
466: haveanswer++;
467: }
468: if (haveanswer) {
469: *ap = NULL;
470: *hap = NULL;
471: /*
472: * Note: we sort even if host can take only one address
473: * in its return structures - should give it the "best"
474: * address in that case, not some random one
475: */
1.59 christos 476: if (res->nsort && haveanswer > 1 && qtype == T_A)
1.80 christos 477: addrsort(addr_ptrs, haveanswer, res);
478: if (!hent->h_name) {
1.78 christos 479: n = (int)strlen(qname) + 1; /* for the \0 */
1.46 itojun 480: if (n > ep - bp || n >= MAXHOSTNAMELEN)
1.1 mrg 481: goto no_recovery;
1.54 itojun 482: strlcpy(bp, qname, (size_t)(ep - bp));
1.80 christos 483: hent->h_name = bp;
1.1 mrg 484: bp += n;
485: }
1.59 christos 486: if (res->options & RES_USE_INET6)
1.80 christos 487: map_v4v6_hostent(hent, &bp, ep);
488: goto success;
1.1 mrg 489: }
1.80 christos 490: no_recovery:
1.86 christos 491: free(aliases);
1.80 christos 492: *he = NO_RECOVERY;
493: return NULL;
494: success:
495: bp = (char *)ALIGN(bp);
496: n = (int)(ap - aliases);
497: qlen = (n + 1) * sizeof(*hent->h_aliases);
498: if ((size_t)(ep - bp) < qlen)
499: goto nospc;
500: hent->h_aliases = (void *)bp;
501: memcpy(bp, aliases, qlen);
1.86 christos 502: free(aliases);
1.90 christos 503: aliases = NULL;
1.80 christos 504:
505: bp += qlen;
506: n = (int)(hap - addr_ptrs);
507: qlen = (n + 1) * sizeof(*hent->h_addr_list);
508: if ((size_t)(ep - bp) < qlen)
509: goto nospc;
510: hent->h_addr_list = (void *)bp;
511: memcpy(bp, addr_ptrs, qlen);
512: *he = NETDB_SUCCESS;
513: return hent;
514: nospc:
1.86 christos 515: free(aliases);
1.80 christos 516: errno = ENOSPC;
517: *he = NETDB_INTERNAL;
1.59 christos 518: return NULL;
1.1 mrg 519: }
520:
521: struct hostent *
1.80 christos 522: gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
523: int *he)
1.1 mrg 524: {
1.59 christos 525: res_state res = __res_get_state();
1.1 mrg 526:
1.80 christos 527: if (res == NULL) {
528: *he = NETDB_INTERNAL;
1.60 christos 529: return NULL;
1.80 christos 530: }
1.60 christos 531:
1.25 lukem 532: _DIAGASSERT(name != NULL);
533:
1.59 christos 534: if (res->options & RES_USE_INET6) {
1.85 christos 535: struct hostent *nhp = gethostbyname_internal(name, AF_INET6,
536: res, hp, buf, buflen, he);
537: if (nhp) {
1.59 christos 538: __res_put_state(res);
1.85 christos 539: return nhp;
1.59 christos 540: }
1.1 mrg 541: }
1.80 christos 542: hp = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, he);
1.59 christos 543: __res_put_state(res);
544: return hp;
1.1 mrg 545: }
546:
547: struct hostent *
1.80 christos 548: gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
549: size_t buflen, int *he)
1.59 christos 550: {
551: res_state res = __res_get_state();
1.60 christos 552:
1.80 christos 553: if (res == NULL) {
554: *he = NETDB_INTERNAL;
1.60 christos 555: return NULL;
1.80 christos 556: }
557: hp = gethostbyname_internal(name, af, res, hp, buf, buflen, he);
1.59 christos 558: __res_put_state(res);
559: return hp;
560: }
561:
562: static struct hostent *
1.80 christos 563: gethostbyname_internal(const char *name, int af, res_state res,
564: struct hostent *hp, char *buf, size_t buflen, int *he)
1.1 mrg 565: {
1.2 mrg 566: const char *cp;
1.80 christos 567: struct getnamaddr info;
1.85 christos 568: char hbuf[MAXHOSTNAMELEN];
1.80 christos 569: size_t size;
1.12 lukem 570: static const ns_dtab dtab[] = {
1.80 christos 571: NS_FILES_CB(_hf_gethtbyname, NULL)
1.9 lukem 572: { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
1.11 lukem 573: NS_NIS_CB(_yp_gethtbyname, NULL)
1.71 christos 574: NS_NULL_CB
1.9 lukem 575: };
1.1 mrg 576:
1.25 lukem 577: _DIAGASSERT(name != NULL);
578:
1.1 mrg 579: switch (af) {
580: case AF_INET:
1.80 christos 581: size = NS_INADDRSZ;
1.1 mrg 582: break;
583: case AF_INET6:
1.80 christos 584: size = NS_IN6ADDRSZ;
1.1 mrg 585: break;
586: default:
1.80 christos 587: *he = NETDB_INTERNAL;
1.1 mrg 588: errno = EAFNOSUPPORT;
1.59 christos 589: return NULL;
1.1 mrg 590: }
1.80 christos 591: if (buflen < size)
592: goto nospc;
1.1 mrg 593:
1.80 christos 594: hp->h_addrtype = af;
595: hp->h_length = (int)size;
1.1 mrg 596:
597: /*
1.75 wiz 598: * if there aren't any dots, it could be a user-level alias.
1.59 christos 599: * this is also done in res_nquery() since we are not the only
1.1 mrg 600: * function that looks up host names.
601: */
1.85 christos 602: if (!strchr(name, '.') && (cp = res_hostalias(res, name,
603: hbuf, sizeof(hbuf))))
1.1 mrg 604: name = cp;
605:
606: /*
607: * disallow names consisting only of digits/dots, unless
608: * they end in a dot.
609: */
1.35 itohy 610: if (isdigit((u_char) name[0]))
1.1 mrg 611: for (cp = name;; ++cp) {
612: if (!*cp) {
613: if (*--cp == '.')
614: break;
615: /*
616: * All-numeric, no dot at the end.
617: * Fake up a hostent as if we'd actually
618: * done a lookup.
619: */
1.80 christos 620: goto fake;
1.1 mrg 621: }
1.35 itohy 622: if (!isdigit((u_char) *cp) && *cp != '.')
1.1 mrg 623: break;
624: }
1.35 itohy 625: if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
1.1 mrg 626: name[0] == ':')
627: for (cp = name;; ++cp) {
628: if (!*cp) {
629: if (*--cp == '.')
630: break;
631: /*
632: * All-IPv6-legal, no dot at the end.
633: * Fake up a hostent as if we'd actually
634: * done a lookup.
635: */
1.80 christos 636: goto fake;
1.1 mrg 637: }
1.35 itohy 638: if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
1.1 mrg 639: break;
640: }
641:
1.80 christos 642: *he = NETDB_INTERNAL;
643: info.hp = hp;
644: info.buf = buf;
645: info.buflen = buflen;
646: info.he = he;
647: if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
1.45 itojun 648: default_dns_files, name, strlen(name), af) != NS_SUCCESS)
1.59 christos 649: return NULL;
1.80 christos 650: *he = NETDB_SUCCESS;
651: return hp;
652: nospc:
653: *he = NETDB_INTERNAL;
654: errno = ENOSPC;
655: return NULL;
656: fake:
1.84 christos 657: HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
658: HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
1.80 christos 659:
660: hp->h_aliases[0] = NULL;
661: if (size > buflen)
662: goto nospc;
663:
664: if (inet_pton(af, name, buf) <= 0) {
665: *he = HOST_NOT_FOUND;
666: return NULL;
667: }
668: hp->h_addr_list[0] = buf;
669: hp->h_addr_list[1] = NULL;
670: buf += size;
671: buflen -= size;
1.84 christos 672: HENT_SCOPY(hp->h_name, name, buf, buflen);
1.80 christos 673: if (res->options & RES_USE_INET6)
674: map_v4v6_hostent(hp, &buf, buf + buflen);
675: *he = NETDB_SUCCESS;
1.59 christos 676: return hp;
1.1 mrg 677: }
678:
679: struct hostent *
1.80 christos 680: gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
681: char *buf, size_t buflen, int *he)
1.1 mrg 682: {
683: const u_char *uaddr = (const u_char *)addr;
1.53 thorpej 684: socklen_t size;
1.80 christos 685: struct getnamaddr info;
1.12 lukem 686: static const ns_dtab dtab[] = {
1.80 christos 687: NS_FILES_CB(_hf_gethtbyaddr, NULL)
1.9 lukem 688: { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
1.11 lukem 689: NS_NIS_CB(_yp_gethtbyaddr, NULL)
1.71 christos 690: NS_NULL_CB
1.9 lukem 691: };
1.1 mrg 692:
1.25 lukem 693: _DIAGASSERT(addr != NULL);
694:
1.80 christos 695: if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
696: (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
697: IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
698: *he = HOST_NOT_FOUND;
1.59 christos 699: return NULL;
1.41 itojun 700: }
1.80 christos 701: if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
702: (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
703: IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
1.1 mrg 704: /* Unmap. */
1.80 christos 705: uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
706: addr = uaddr;
1.1 mrg 707: af = AF_INET;
1.80 christos 708: len = NS_INADDRSZ;
1.1 mrg 709: }
710: switch (af) {
711: case AF_INET:
1.80 christos 712: size = NS_INADDRSZ;
1.1 mrg 713: break;
714: case AF_INET6:
1.80 christos 715: size = NS_IN6ADDRSZ;
1.1 mrg 716: break;
717: default:
718: errno = EAFNOSUPPORT;
1.80 christos 719: *he = NETDB_INTERNAL;
1.59 christos 720: return NULL;
1.1 mrg 721: }
722: if (size != len) {
723: errno = EINVAL;
1.80 christos 724: *he = NETDB_INTERNAL;
1.59 christos 725: return NULL;
1.1 mrg 726: }
1.80 christos 727: info.hp = hp;
728: info.buf = buf;
729: info.buflen = buflen;
730: info.he = he;
731: *he = NETDB_INTERNAL;
732: if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
1.11 lukem 733: default_dns_files, uaddr, len, af) != NS_SUCCESS)
1.59 christos 734: return NULL;
1.80 christos 735: *he = NETDB_SUCCESS;
1.59 christos 736: return hp;
1.1 mrg 737: }
738:
739: struct hostent *
1.80 christos 740: gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
1.1 mrg 741: {
1.80 christos 742: char *p, *name;
1.25 lukem 743: char *cp, **q;
1.1 mrg 744: int af, len;
1.91 christos 745: size_t anum;
1.86 christos 746: char **aliases;
747: size_t maxaliases;
1.80 christos 748: struct in6_addr host_addr;
1.1 mrg 749:
1.80 christos 750: if (hf == NULL) {
751: *he = NETDB_INTERNAL;
752: errno = EINVAL;
1.59 christos 753: return NULL;
1.1 mrg 754: }
1.91 christos 755: p = NULL;
1.86 christos 756: setup(aliases, maxaliases);
1.91 christos 757: for (;;) {
758: free(p);
759: p = fparseln(hf, NULL, NULL, NULL, FPARSELN_UNESCALL);
760: if (p == NULL) {
761: free(aliases);
762: *he = HOST_NOT_FOUND;
763: return NULL;
764: }
765: if (!(cp = strpbrk(p, " \t")))
766: continue;
767: *cp++ = '\0';
768: if (inet_pton(AF_INET6, p, &host_addr) > 0) {
1.1 mrg 769: af = AF_INET6;
1.80 christos 770: len = NS_IN6ADDRSZ;
1.1 mrg 771: } else {
1.91 christos 772: if (inet_pton(AF_INET, p, &host_addr) <= 0)
773: continue;
774:
775: res_state res = __res_get_state();
776: if (res == NULL)
777: goto nospc;
778: if (res->options & RES_USE_INET6) {
779: map_v4v6_address(buf, buf);
780: af = AF_INET6;
781: len = NS_IN6ADDRSZ;
782: } else {
783: af = AF_INET;
784: len = NS_INADDRSZ;
785: }
786: __res_put_state(res);
1.1 mrg 787: }
1.80 christos 788:
1.91 christos 789: /* if this is not something we're looking for, skip it. */
790: if (hent->h_addrtype != 0 && hent->h_addrtype != af)
791: continue;
792: if (hent->h_length != 0 && hent->h_length != len)
793: continue;
794:
795: while (*cp == ' ' || *cp == '\t')
1.1 mrg 796: cp++;
1.91 christos 797: if ((cp = strpbrk(name = cp, " \t")) != NULL)
798: *cp++ = '\0';
799: q = aliases;
800: while (cp && *cp) {
801: if (*cp == ' ' || *cp == '\t') {
802: cp++;
803: continue;
804: }
805: addalias(q, cp, aliases, maxaliases);
806: if ((cp = strpbrk(cp, " \t")) != NULL)
807: *cp++ = '\0';
1.1 mrg 808: }
1.91 christos 809: break;
1.1 mrg 810: }
1.80 christos 811: hent->h_length = len;
812: hent->h_addrtype = af;
1.84 christos 813: HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
1.80 christos 814: anum = (size_t)(q - aliases);
1.84 christos 815: HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
816: HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
817: buflen);
1.80 christos 818: hent->h_addr_list[1] = NULL;
819:
1.84 christos 820: HENT_SCOPY(hent->h_name, name, buf, buflen);
1.80 christos 821: for (size_t i = 0; i < anum; i++)
1.84 christos 822: HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
1.80 christos 823: hent->h_aliases[anum] = NULL;
824:
825: *he = NETDB_SUCCESS;
1.91 christos 826: free(p);
1.86 christos 827: free(aliases);
1.80 christos 828: return hent;
829: nospc:
1.91 christos 830: free(p);
1.86 christos 831: free(aliases);
1.80 christos 832: errno = ENOSPC;
833: *he = NETDB_INTERNAL;
834: return NULL;
1.1 mrg 835: }
836:
837: static void
1.59 christos 838: map_v4v6_address(const char *src, char *dst)
1.1 mrg 839: {
840: u_char *p = (u_char *)dst;
1.80 christos 841: char tmp[NS_INADDRSZ];
1.1 mrg 842: int i;
843:
1.25 lukem 844: _DIAGASSERT(src != NULL);
845: _DIAGASSERT(dst != NULL);
846:
1.1 mrg 847: /* Stash a temporary copy so our caller can update in place. */
1.80 christos 848: (void)memcpy(tmp, src, NS_INADDRSZ);
1.1 mrg 849: /* Mark this ipv6 addr as a mapped ipv4. */
850: for (i = 0; i < 10; i++)
851: *p++ = 0x00;
852: *p++ = 0xff;
853: *p++ = 0xff;
854: /* Retrieve the saved copy and we're done. */
1.80 christos 855: (void)memcpy(p, tmp, NS_INADDRSZ);
1.1 mrg 856: }
857:
858: static void
1.59 christos 859: map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1.1 mrg 860: {
861: char **ap;
862:
1.25 lukem 863: _DIAGASSERT(hp != NULL);
864: _DIAGASSERT(bpp != NULL);
1.47 itojun 865: _DIAGASSERT(ep != NULL);
1.25 lukem 866:
1.80 christos 867: if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
1.1 mrg 868: return;
869: hp->h_addrtype = AF_INET6;
1.80 christos 870: hp->h_length = NS_IN6ADDRSZ;
1.1 mrg 871: for (ap = hp->h_addr_list; *ap; ap++) {
1.78 christos 872: int i = (int)(sizeof(align) -
873: (size_t)((u_long)*bpp % sizeof(align)));
1.1 mrg 874:
1.80 christos 875: if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
1.1 mrg 876: /* Out of memory. Truncate address list here. XXX */
877: *ap = NULL;
878: return;
879: }
880: *bpp += i;
881: map_v4v6_address(*ap, *bpp);
882: *ap = *bpp;
1.80 christos 883: *bpp += NS_IN6ADDRSZ;
1.1 mrg 884: }
885: }
886:
887: static void
1.59 christos 888: addrsort(char **ap, int num, res_state res)
1.1 mrg 889: {
890: int i, j;
891: char **p;
892: short aval[MAXADDRS];
893: int needsort = 0;
894:
1.25 lukem 895: _DIAGASSERT(ap != NULL);
896:
1.1 mrg 897: p = ap;
898: for (i = 0; i < num; i++, p++) {
1.59 christos 899: for (j = 0 ; (unsigned)j < res->nsort; j++)
900: if (res->sort_list[j].addr.s_addr ==
1.14 lukem 901: (((struct in_addr *)(void *)(*p))->s_addr &
1.59 christos 902: res->sort_list[j].mask))
1.1 mrg 903: break;
904: aval[i] = j;
905: if (needsort == 0 && i > 0 && j < aval[i-1])
906: needsort = i;
907: }
908: if (!needsort)
909: return;
910:
911: while (needsort < num) {
912: for (j = needsort - 1; j >= 0; j--) {
913: if (aval[j] > aval[j+1]) {
914: char *hp;
915:
916: i = aval[j];
917: aval[j] = aval[j+1];
918: aval[j+1] = i;
919:
920: hp = ap[j];
921: ap[j] = ap[j+1];
922: ap[j+1] = hp;
923: } else
924: break;
925: }
926: needsort++;
927: }
928: }
929:
930:
1.13 christos 931: /*ARGSUSED*/
1.9 lukem 932: int
1.61 ginsbach 933: _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
1.9 lukem 934: {
1.52 itojun 935: querybuf *buf;
1.9 lukem 936: int n, type;
937: struct hostent *hp;
938: const char *name;
1.59 christos 939: res_state res;
1.80 christos 940: struct getnamaddr *info = rv;
1.9 lukem 941:
1.25 lukem 942: _DIAGASSERT(rv != NULL);
943:
1.9 lukem 944: name = va_arg(ap, char *);
1.80 christos 945: /* NOSTRICT skip string len */(void)va_arg(ap, int);
946: info->hp->h_addrtype = va_arg(ap, int);
1.9 lukem 947:
1.80 christos 948: switch (info->hp->h_addrtype) {
1.9 lukem 949: case AF_INET:
1.80 christos 950: info->hp->h_length = NS_INADDRSZ;
1.9 lukem 951: type = T_A;
952: break;
953: case AF_INET6:
1.80 christos 954: info->hp->h_length = NS_IN6ADDRSZ;
1.9 lukem 955: type = T_AAAA;
956: break;
957: default:
958: return NS_UNAVAIL;
959: }
1.52 itojun 960: buf = malloc(sizeof(*buf));
961: if (buf == NULL) {
1.80 christos 962: *info->he = NETDB_INTERNAL;
1.52 itojun 963: return NS_NOTFOUND;
964: }
1.59 christos 965: res = __res_get_state();
1.69 christos 966: if (res == NULL) {
967: free(buf);
1.92 christos 968: *info->he = NETDB_INTERNAL;
1.60 christos 969: return NS_NOTFOUND;
1.69 christos 970: }
1.78 christos 971: n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
1.52 itojun 972: if (n < 0) {
973: free(buf);
1.76 christos 974: debugprintf("res_nsearch failed (%d)\n", res, n);
1.59 christos 975: __res_put_state(res);
1.9 lukem 976: return NS_NOTFOUND;
977: }
1.80 christos 978: hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
979: info->buflen, info->he);
1.52 itojun 980: free(buf);
1.59 christos 981: __res_put_state(res);
1.9 lukem 982: if (hp == NULL)
1.92 christos 983: switch (*info->he) {
1.9 lukem 984: case HOST_NOT_FOUND:
985: return NS_NOTFOUND;
986: case TRY_AGAIN:
987: return NS_TRYAGAIN;
988: default:
989: return NS_UNAVAIL;
990: }
991: return NS_SUCCESS;
992: }
993:
1.13 christos 994: /*ARGSUSED*/
1.9 lukem 995: int
1.59 christos 996: _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1.9 lukem 997: {
1.49 itojun 998: char qbuf[MAXDNAME + 1], *qp, *ep;
1.9 lukem 999: int n;
1.52 itojun 1000: querybuf *buf;
1.9 lukem 1001: struct hostent *hp;
1002: const unsigned char *uaddr;
1.80 christos 1003: int advance;
1.59 christos 1004: res_state res;
1.80 christos 1005: char *bf;
1006: size_t blen;
1007: struct getnamaddr *info = rv;
1.9 lukem 1008:
1.25 lukem 1009: _DIAGASSERT(rv != NULL);
1010:
1.9 lukem 1011: uaddr = va_arg(ap, unsigned char *);
1.80 christos 1012: info->hp->h_length = va_arg(ap, int);
1013: info->hp->h_addrtype = va_arg(ap, int);
1.9 lukem 1014:
1.80 christos 1015: switch (info->hp->h_addrtype) {
1.9 lukem 1016: case AF_INET:
1.43 itojun 1017: (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
1018: (uaddr[3] & 0xff), (uaddr[2] & 0xff),
1019: (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1.9 lukem 1020: break;
1021:
1022: case AF_INET6:
1023: qp = qbuf;
1.49 itojun 1024: ep = qbuf + sizeof(qbuf) - 1;
1.80 christos 1025: for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
1.49 itojun 1026: advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
1027: uaddr[n] & 0xf,
1.43 itojun 1028: ((unsigned int)uaddr[n] >> 4) & 0xf);
1.49 itojun 1029: if (advance > 0 && qp + advance < ep)
1.43 itojun 1030: qp += advance;
1.92 christos 1031: else
1032: goto norecovery;
1.50 itojun 1033: }
1.92 christos 1034: if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf))
1035: goto norecovery;
1.9 lukem 1036: break;
1037: default:
1.92 christos 1038: goto norecovery;
1.9 lukem 1039: }
1040:
1.52 itojun 1041: buf = malloc(sizeof(*buf));
1042: if (buf == NULL) {
1.92 christos 1043: goto nospc;
1.52 itojun 1044: }
1.59 christos 1045: res = __res_get_state();
1.70 christos 1046: if (res == NULL) {
1047: free(buf);
1.92 christos 1048: goto nospc;
1.70 christos 1049: }
1.78 christos 1050: n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
1.9 lukem 1051: if (n < 0) {
1.52 itojun 1052: free(buf);
1.76 christos 1053: debugprintf("res_nquery failed (%d)\n", res, n);
1.59 christos 1054: __res_put_state(res);
1.92 christos 1055: *info->he = HOST_NOT_FOUND;
1.9 lukem 1056: return NS_NOTFOUND;
1057: }
1.80 christos 1058: hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
1059: info->buflen, info->he);
1.52 itojun 1060: free(buf);
1.59 christos 1061: if (hp == NULL) {
1062: __res_put_state(res);
1.80 christos 1063: switch (*info->he) {
1.9 lukem 1064: case HOST_NOT_FOUND:
1065: return NS_NOTFOUND;
1066: case TRY_AGAIN:
1067: return NS_TRYAGAIN;
1068: default:
1069: return NS_UNAVAIL;
1070: }
1.59 christos 1071: }
1.80 christos 1072:
1073: bf = (void *)(hp->h_addr_list + 2);
1074: blen = (size_t)(bf - info->buf);
1075: if (blen + info->hp->h_length > info->buflen)
1076: goto nospc;
1077: hp->h_addr_list[0] = bf;
1078: hp->h_addr_list[1] = NULL;
1079: (void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
1080: if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1.92 christos 1081: if (blen + NS_IN6ADDRSZ > info->buflen) {
1082: __res_put_state(res);
1.80 christos 1083: goto nospc;
1.92 christos 1084: }
1.80 christos 1085: map_v4v6_address(bf, bf);
1.9 lukem 1086: hp->h_addrtype = AF_INET6;
1.80 christos 1087: hp->h_length = NS_IN6ADDRSZ;
1.9 lukem 1088: }
1089:
1.59 christos 1090: __res_put_state(res);
1.80 christos 1091: *info->he = NETDB_SUCCESS;
1.9 lukem 1092: return NS_SUCCESS;
1.80 christos 1093: nospc:
1094: *info->he = NETDB_INTERNAL;
1095: return NS_UNAVAIL;
1.92 christos 1096: norecovery:
1097: *info->he = NO_RECOVERY;
1098: return NS_UNAVAIL;
1.9 lukem 1099: }
1100:
1.2 mrg 1101: #ifdef YP
1.13 christos 1102: /*ARGSUSED*/
1.80 christos 1103: static struct hostent *
1104: _yp_hostent(char *line, int af, struct getnamaddr *info)
1.2 mrg 1105: {
1.80 christos 1106: struct in6_addr host_addrs[MAXADDRS];
1.86 christos 1107: char **aliases;
1108: size_t maxaliases;
1.2 mrg 1109: char *p = line;
1.80 christos 1110: char *cp, **q, *ptr;
1111: size_t len, anum, i;
1.37 itojun 1112: int addrok;
1.2 mrg 1113: int more;
1.53 thorpej 1114: size_t naddrs;
1.80 christos 1115: struct hostent *hp = info->hp;
1.2 mrg 1116:
1.25 lukem 1117: _DIAGASSERT(line != NULL);
1118:
1.80 christos 1119: hp->h_name = NULL;
1120: hp->h_addrtype = af;
1.37 itojun 1121: switch (af) {
1122: case AF_INET:
1.80 christos 1123: hp->h_length = NS_INADDRSZ;
1.37 itojun 1124: break;
1125: case AF_INET6:
1.80 christos 1126: hp->h_length = NS_IN6ADDRSZ;
1.37 itojun 1127: break;
1128: default:
1.59 christos 1129: return NULL;
1.37 itojun 1130: }
1.86 christos 1131: setup(aliases, maxaliases);
1.37 itojun 1132: naddrs = 0;
1.80 christos 1133: q = aliases;
1.2 mrg 1134:
1135: nextline:
1.36 itojun 1136: /* check for host_addrs overflow */
1.80 christos 1137: if (naddrs >= __arraycount(host_addrs))
1.36 itojun 1138: goto done;
1139:
1.2 mrg 1140: more = 0;
1141: cp = strpbrk(p, " \t");
1.36 itojun 1142: if (cp == NULL)
1143: goto done;
1.2 mrg 1144: *cp++ = '\0';
1145:
1.37 itojun 1146: /* p has should have an address */
1.80 christos 1147: addrok = inet_pton(af, p, &host_addrs[naddrs]);
1.37 itojun 1148: if (addrok != 1) {
1149: /* skip to the next line */
1150: while (cp && *cp) {
1151: if (*cp == '\n') {
1152: cp++;
1153: goto nextline;
1154: }
1155: cp++;
1156: }
1157: goto done;
1158: }
1.85 christos 1159: naddrs++;
1.37 itojun 1160:
1.2 mrg 1161: while (*cp == ' ' || *cp == '\t')
1162: cp++;
1163: p = cp;
1164: cp = strpbrk(p, " \t\n");
1165: if (cp != NULL) {
1166: if (*cp == '\n')
1167: more = 1;
1168: *cp++ = '\0';
1169: }
1.80 christos 1170: if (!hp->h_name)
1171: hp->h_name = p;
1172: else if (strcmp(hp->h_name, p) == 0)
1.2 mrg 1173: ;
1.87 christos 1174: else
1175: addalias(q, p, aliases, maxaliases);
1.2 mrg 1176: p = cp;
1177: if (more)
1178: goto nextline;
1179:
1180: while (cp && *cp) {
1181: if (*cp == ' ' || *cp == '\t') {
1182: cp++;
1183: continue;
1184: }
1185: if (*cp == '\n') {
1186: cp++;
1187: goto nextline;
1188: }
1.87 christos 1189: addalias(q, cp, aliases, maxaliases);
1.2 mrg 1190: cp = strpbrk(cp, " \t");
1191: if (cp != NULL)
1192: *cp++ = '\0';
1193: }
1.37 itojun 1194:
1.2 mrg 1195: done:
1.86 christos 1196: if (hp->h_name == NULL) {
1197: free(aliases);
1.59 christos 1198: return NULL;
1.86 christos 1199: }
1.80 christos 1200:
1201: ptr = info->buf;
1202: len = info->buflen;
1203:
1204: anum = (size_t)(q - aliases);
1.84 christos 1205: HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1206: HENT_ARRAY(hp->h_aliases, anum, ptr, len);
1.80 christos 1207:
1208: for (i = 0; i < naddrs; i++)
1.84 christos 1209: HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
1.80 christos 1210: ptr, len);
1211: hp->h_addr_list[naddrs] = NULL;
1212:
1.84 christos 1213: HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
1.80 christos 1214:
1215: for (i = 0; i < anum; i++)
1.84 christos 1216: HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1.80 christos 1217: hp->h_aliases[anum] = NULL;
1.86 christos 1218: free(aliases);
1.80 christos 1219:
1220: return hp;
1221: nospc:
1.86 christos 1222: free(aliases);
1.80 christos 1223: *info->he = NETDB_INTERNAL;
1224: errno = ENOSPC;
1225: return NULL;
1.2 mrg 1226: }
1227:
1.13 christos 1228: /*ARGSUSED*/
1.9 lukem 1229: int
1.59 christos 1230: _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1.2 mrg 1231: {
1.59 christos 1232: struct hostent *hp = NULL;
1.80 christos 1233: char *ypcurrent;
1234: int ypcurrentlen, r;
1.37 itojun 1235: char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1.9 lukem 1236: const unsigned char *uaddr;
1.17 christos 1237: int af;
1.37 itojun 1238: const char *map;
1.80 christos 1239: struct getnamaddr *info = rv;
1.9 lukem 1240:
1.25 lukem 1241: _DIAGASSERT(rv != NULL);
1242:
1.9 lukem 1243: uaddr = va_arg(ap, unsigned char *);
1.17 christos 1244: /* NOSTRICT skip len */(void)va_arg(ap, int);
1.9 lukem 1245: af = va_arg(ap, int);
1.2 mrg 1246:
1247: if (!__ypdomain) {
1248: if (_yp_check(&__ypdomain) == 0)
1.9 lukem 1249: return NS_UNAVAIL;
1.2 mrg 1250: }
1.9 lukem 1251: /*
1.37 itojun 1252: * XXX unfortunately, we cannot support IPv6 extended scoped address
1253: * notation here. gethostbyaddr() is not scope-aware. too bad.
1.9 lukem 1254: */
1.78 christos 1255: if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
1.37 itojun 1256: return NS_UNAVAIL;
1257: switch (af) {
1258: case AF_INET:
1259: map = "hosts.byaddr";
1260: break;
1261: default:
1262: map = "ipnodes.byaddr";
1263: break;
1264: }
1.80 christos 1265: ypcurrent = NULL;
1.37 itojun 1266: r = yp_match(__ypdomain, map, name,
1.80 christos 1267: (int)strlen(name), &ypcurrent, &ypcurrentlen);
1.59 christos 1268: if (r == 0)
1.80 christos 1269: hp = _yp_hostent(ypcurrent, af, info);
1270: else
1271: hp = NULL;
1272: free(ypcurrent);
1.59 christos 1273: if (hp == NULL) {
1.80 christos 1274: *info->he = HOST_NOT_FOUND;
1.9 lukem 1275: return NS_NOTFOUND;
1276: }
1277: return NS_SUCCESS;
1.2 mrg 1278: }
1279:
1.13 christos 1280: /*ARGSUSED*/
1.9 lukem 1281: int
1.59 christos 1282: _yp_gethtbyname(void *rv, void *cb_data, va_list ap)
1.2 mrg 1283: {
1.80 christos 1284: struct hostent *hp;
1285: char *ypcurrent;
1286: int ypcurrentlen, r;
1.9 lukem 1287: const char *name;
1.17 christos 1288: int af;
1.37 itojun 1289: const char *map;
1.80 christos 1290: struct getnamaddr *info = rv;
1.25 lukem 1291:
1292: _DIAGASSERT(rv != NULL);
1.9 lukem 1293:
1294: name = va_arg(ap, char *);
1.80 christos 1295: /* NOSTRICT skip string len */(void)va_arg(ap, int);
1.9 lukem 1296: af = va_arg(ap, int);
1.2 mrg 1297:
1298: if (!__ypdomain) {
1299: if (_yp_check(&__ypdomain) == 0)
1.9 lukem 1300: return NS_UNAVAIL;
1.2 mrg 1301: }
1.37 itojun 1302: switch (af) {
1303: case AF_INET:
1304: map = "hosts.byname";
1305: break;
1306: default:
1307: map = "ipnodes.byname";
1308: break;
1309: }
1.80 christos 1310: ypcurrent = NULL;
1.37 itojun 1311: r = yp_match(__ypdomain, map, name,
1.80 christos 1312: (int)strlen(name), &ypcurrent, &ypcurrentlen);
1.59 christos 1313: if (r == 0)
1.80 christos 1314: hp = _yp_hostent(ypcurrent, af, info);
1315: else
1316: hp = NULL;
1317: free(ypcurrent);
1.59 christos 1318: if (hp == NULL) {
1.80 christos 1319: *info->he = HOST_NOT_FOUND;
1.9 lukem 1320: return NS_NOTFOUND;
1321: }
1322: return NS_SUCCESS;
1.2 mrg 1323: }
1324: #endif
1.80 christos 1325:
1326: /*
1327: * Non-reentrant versions.
1328: */
1329: FILE *_h_file;
1330: static struct hostent h_ent;
1331: static char h_buf[16384];
1332:
1333: struct hostent *
1.82 christos 1334: gethostbyaddr(const void *addr, socklen_t len, int af) {
1.80 christos 1335: return gethostbyaddr_r(addr, len, af, &h_ent, h_buf, sizeof(h_buf),
1336: &h_errno);
1337: }
1338:
1339: struct hostent *
1340: gethostbyname(const char *name) {
1341: return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno);
1342: }
1343:
1344: struct hostent *
1345: gethostbyname2(const char *name, int af) {
1346: return gethostbyname2_r(name, af, &h_ent, h_buf, sizeof(h_buf),
1347: &h_errno);
1348: }
1349:
1350: struct hostent *
1351: gethostent(void)
1352: {
1353: if (_h_file == NULL) {
1354: sethostent_r(&_h_file);
1355: if (_h_file == NULL) {
1356: h_errno = NETDB_INTERNAL;
1357: return NULL;
1358: }
1359: }
1360: memset(&h_ent, 0, sizeof(h_ent));
1361: return gethostent_r(_h_file, &h_ent, h_buf, sizeof(h_buf), &h_errno);
1362: }
1.84 christos 1363:
CVSweb <webmaster@jp.NetBSD.org>