gethnamaddr.c revision a2177c6ccb65104659543c895b753458abfadcab
1/* $NetBSD: gethnamaddr.c,v 1.91 2014/06/19 15:08:18 christos Exp $ */ 2 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. 17 * 3. Neither the name of the University nor the names of its contributors 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 54#include <sys/cdefs.h> 55#include <sys/types.h> 56 57#include <sys/param.h> 58#include <sys/socket.h> 59#include <sys/un.h> 60#include <netinet/in.h> 61#include <arpa/inet.h> 62#include <arpa/nameser.h> 63#include "NetdClientDispatch.h" 64#include "resolv_netid.h" 65#include "resolv_private.h" 66#include "resolv_cache.h" 67#include <assert.h> 68#include <ctype.h> 69#include <errno.h> 70#include <netdb.h> 71#include <stdarg.h> 72#include <stdbool.h> 73#include <stdio.h> 74#include <strings.h> 75#include <syslog.h> 76#include <unistd.h> 77 78#define ALIGNBYTES (sizeof(uintptr_t) - 1) 79#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES) 80 81#ifndef LOG_AUTH 82# define LOG_AUTH 0 83#endif 84 85#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ 86 87#include "nsswitch.h" 88#include <stdlib.h> 89#include <string.h> 90 91#include "hostent.h" 92 93#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \ 94 (ok)(nm) != 0) 95#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) 96#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) 97 98#define addalias(d, s, arr, siz) do { \ 99 if (d >= &arr[siz]) { \ 100 char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \ 101 if (xptr == NULL) \ 102 goto nospc; \ 103 d = xptr + (d - arr); \ 104 arr = xptr; \ 105 siz += 10; \ 106 } \ 107 *d++ = s; \ 108} while (/*CONSTCOND*/0) 109 110#define setup(arr, siz) do { \ 111 arr = malloc((siz = 10) * sizeof(*arr)); \ 112 if (arr == NULL) \ 113 goto nospc; \ 114} while (/*CONSTCOND*/0) 115 116// This should be synchronized to ResponseCode.h 117static const int DnsProxyQueryResult = 222; 118 119static const char AskedForGot[] = 120 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 121 122#define MAXPACKET (64*1024) 123 124typedef union { 125 HEADER hdr; 126 u_char buf[MAXPACKET]; 127} querybuf; 128 129typedef union { 130 int32_t al; 131 char ac; 132} align; 133 134#ifdef DEBUG 135static void debugprintf(const char *, res_state, ...) 136 __attribute__((__format__(__printf__, 1, 3))); 137#endif 138static struct hostent *getanswer(const querybuf *, int, const char *, int, 139 res_state, struct hostent *, char *, size_t, int *); 140static void map_v4v6_address(const char *, char *); 141static void map_v4v6_hostent(struct hostent *, char **, char *); 142static void addrsort(char **, int, res_state); 143 144void ht_sethostent(int); 145void ht_endhostent(void); 146struct hostent *ht_gethostbyname(char *); 147struct hostent *ht_gethostbyaddr(const char *, int, int); 148void dns_service(void); 149#undef dn_skipname 150int dn_skipname(const u_char *, const u_char *); 151static int _dns_gethtbyaddr(void *, void *, va_list); 152static int _dns_gethtbyname(void *, void *, va_list); 153 154static struct hostent *gethostbyname_internal(const char *, int, res_state, 155 struct hostent *, char *, size_t, int *, unsigned, unsigned); 156static struct hostent* android_gethostbyaddrfornet_proxy_internal(const void*, socklen_t, 157 int, struct hostent *, char *, size_t, int *, unsigned, unsigned); 158 159static const ns_src default_dns_files[] = { 160 { NSSRC_FILES, NS_SUCCESS }, 161 { NSSRC_DNS, NS_SUCCESS }, 162 { 0, 0 } 163}; 164 165 166#ifdef DEBUG 167static void 168debugprintf(const char *msg, res_state res, ...) 169{ 170 _DIAGASSERT(msg != NULL); 171 172 if (res->options & RES_DEBUG) { 173 int save = errno; 174 va_list ap; 175 176 va_start (ap, res); 177 vprintf(msg, ap); 178 va_end (ap); 179 180 errno = save; 181 } 182} 183#else 184# define debugprintf(msg, res, num) /*nada*/ 185#endif 186 187#define BOUNDED_INCR(x) \ 188 do { \ 189 cp += (x); \ 190 if (cp > eom) \ 191 goto no_recovery; \ 192 } while (/*CONSTCOND*/0) 193 194#define BOUNDS_CHECK(ptr, count) \ 195 do { \ 196 if ((ptr) + (count) > eom) \ 197 goto no_recovery; \ 198 } while (/*CONSTCOND*/0) 199 200static struct hostent * 201getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 202 res_state res, struct hostent *hent, char *buf, size_t buflen, int *he) 203{ 204 const HEADER *hp; 205 const u_char *cp; 206 int n; 207 size_t qlen; 208 const u_char *eom, *erdata; 209 char *bp, **ap, **hap, *ep; 210 int type, class, ancount, qdcount; 211 int haveanswer, had_error; 212 int toobig = 0; 213 char tbuf[MAXDNAME]; 214 char **aliases; 215 size_t maxaliases; 216 char *addr_ptrs[MAXADDRS]; 217 const char *tname; 218 int (*name_ok)(const char *); 219 220 _DIAGASSERT(answer != NULL); 221 _DIAGASSERT(qname != NULL); 222 223 tname = qname; 224 hent->h_name = NULL; 225 eom = answer->buf + anslen; 226 switch (qtype) { 227 case T_A: 228 case T_AAAA: 229 name_ok = res_hnok; 230 break; 231 case T_PTR: 232 name_ok = res_dnok; 233 break; 234 default: 235 *he = NO_RECOVERY; 236 return NULL; /* XXX should be abort(); */ 237 } 238 239 setup(aliases, maxaliases); 240 /* 241 * find first satisfactory answer 242 */ 243 hp = &answer->hdr; 244 ancount = ntohs(hp->ancount); 245 qdcount = ntohs(hp->qdcount); 246 bp = buf; 247 ep = buf + buflen; 248 cp = answer->buf; 249 BOUNDED_INCR(HFIXEDSZ); 250 if (qdcount != 1) 251 goto no_recovery; 252 253 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 254 if ((n < 0) || !maybe_ok(res, bp, name_ok)) 255 goto no_recovery; 256 257 BOUNDED_INCR(n + QFIXEDSZ); 258 if (qtype == T_A || qtype == T_AAAA) { 259 /* res_send() has already verified that the query name is the 260 * same as the one we sent; this just gets the expanded name 261 * (i.e., with the succeeding search-domain tacked on). 262 */ 263 n = (int)strlen(bp) + 1; /* for the \0 */ 264 if (n >= MAXHOSTNAMELEN) 265 goto no_recovery; 266 hent->h_name = bp; 267 bp += n; 268 /* The qname can be abbreviated, but h_name is now absolute. */ 269 qname = hent->h_name; 270 } 271 hent->h_aliases = ap = aliases; 272 hent->h_addr_list = hap = addr_ptrs; 273 *ap = NULL; 274 *hap = NULL; 275 haveanswer = 0; 276 had_error = 0; 277 while (ancount-- > 0 && cp < eom && !had_error) { 278 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 279 if ((n < 0) || !maybe_ok(res, bp, name_ok)) { 280 had_error++; 281 continue; 282 } 283 cp += n; /* name */ 284 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 285 type = _getshort(cp); 286 cp += INT16SZ; /* type */ 287 class = _getshort(cp); 288 cp += INT16SZ + INT32SZ; /* class, TTL */ 289 n = _getshort(cp); 290 cp += INT16SZ; /* len */ 291 BOUNDS_CHECK(cp, n); 292 erdata = cp + n; 293 if (class != C_IN) { 294 /* XXX - debug? syslog? */ 295 cp += n; 296 continue; /* XXX - had_error++ ? */ 297 } 298 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { 299 n = dn_expand(answer->buf, eom, cp, tbuf, 300 (int)sizeof tbuf); 301 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) { 302 had_error++; 303 continue; 304 } 305 cp += n; 306 if (cp != erdata) 307 goto no_recovery; 308 /* Store alias. */ 309 addalias(ap, bp, aliases, maxaliases); 310 n = (int)strlen(bp) + 1; /* for the \0 */ 311 if (n >= MAXHOSTNAMELEN) { 312 had_error++; 313 continue; 314 } 315 bp += n; 316 /* Get canonical name. */ 317 n = (int)strlen(tbuf) + 1; /* for the \0 */ 318 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 319 had_error++; 320 continue; 321 } 322 strlcpy(bp, tbuf, (size_t)(ep - bp)); 323 hent->h_name = bp; 324 bp += n; 325 continue; 326 } 327 if (qtype == T_PTR && type == T_CNAME) { 328 n = dn_expand(answer->buf, eom, cp, tbuf, 329 (int)sizeof tbuf); 330 if (n < 0 || !maybe_dnok(res, tbuf)) { 331 had_error++; 332 continue; 333 } 334 cp += n; 335 if (cp != erdata) 336 goto no_recovery; 337 /* Get canonical name. */ 338 n = (int)strlen(tbuf) + 1; /* for the \0 */ 339 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 340 had_error++; 341 continue; 342 } 343 strlcpy(bp, tbuf, (size_t)(ep - bp)); 344 tname = bp; 345 bp += n; 346 continue; 347 } 348 if (type != qtype) { 349 if (type != T_KEY && type != T_SIG) 350 syslog(LOG_NOTICE|LOG_AUTH, 351 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 352 qname, p_class(C_IN), p_type(qtype), 353 p_type(type)); 354 cp += n; 355 continue; /* XXX - had_error++ ? */ 356 } 357 switch (type) { 358 case T_PTR: 359 if (strcasecmp(tname, bp) != 0) { 360 syslog(LOG_NOTICE|LOG_AUTH, 361 AskedForGot, qname, bp); 362 cp += n; 363 continue; /* XXX - had_error++ ? */ 364 } 365 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 366 if ((n < 0) || !maybe_hnok(res, bp)) { 367 had_error++; 368 break; 369 } 370#if MULTI_PTRS_ARE_ALIASES 371 cp += n; 372 if (cp != erdata) 373 goto no_recovery; 374 if (!haveanswer) 375 hent->h_name = bp; 376 else 377 addalias(ap, bp, aliases, maxaliases); 378 if (n != -1) { 379 n = (int)strlen(bp) + 1; /* for the \0 */ 380 if (n >= MAXHOSTNAMELEN) { 381 had_error++; 382 break; 383 } 384 bp += n; 385 } 386 break; 387#else 388 hent->h_name = bp; 389 if (res->options & RES_USE_INET6) { 390 n = strlen(bp) + 1; /* for the \0 */ 391 if (n >= MAXHOSTNAMELEN) { 392 had_error++; 393 break; 394 } 395 bp += n; 396 map_v4v6_hostent(hent, &bp, ep); 397 } 398 goto success; 399#endif 400 case T_A: 401 case T_AAAA: 402 if (strcasecmp(hent->h_name, bp) != 0) { 403 syslog(LOG_NOTICE|LOG_AUTH, 404 AskedForGot, hent->h_name, bp); 405 cp += n; 406 continue; /* XXX - had_error++ ? */ 407 } 408 if (n != hent->h_length) { 409 cp += n; 410 continue; 411 } 412 if (type == T_AAAA) { 413 struct in6_addr in6; 414 memcpy(&in6, cp, NS_IN6ADDRSZ); 415 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 416 cp += n; 417 continue; 418 } 419 } 420 if (!haveanswer) { 421 int nn; 422 423 hent->h_name = bp; 424 nn = (int)strlen(bp) + 1; /* for the \0 */ 425 bp += nn; 426 } 427 428 bp += sizeof(align) - 429 (size_t)((u_long)bp % sizeof(align)); 430 431 if (bp + n >= ep) { 432 debugprintf("size (%d) too big\n", res, n); 433 had_error++; 434 continue; 435 } 436 if (hap >= &addr_ptrs[MAXADDRS - 1]) { 437 if (!toobig++) { 438 debugprintf("Too many addresses (%d)\n", 439 res, MAXADDRS); 440 } 441 cp += n; 442 continue; 443 } 444 (void)memcpy(*hap++ = bp, cp, (size_t)n); 445 bp += n; 446 cp += n; 447 if (cp != erdata) 448 goto no_recovery; 449 break; 450 default: 451 abort(); 452 } 453 if (!had_error) 454 haveanswer++; 455 } 456 if (haveanswer) { 457 *ap = NULL; 458 *hap = NULL; 459 /* 460 * Note: we sort even if host can take only one address 461 * in its return structures - should give it the "best" 462 * address in that case, not some random one 463 */ 464 if (res->nsort && haveanswer > 1 && qtype == T_A) 465 addrsort(addr_ptrs, haveanswer, res); 466 if (!hent->h_name) { 467 n = (int)strlen(qname) + 1; /* for the \0 */ 468 if (n > ep - bp || n >= MAXHOSTNAMELEN) 469 goto no_recovery; 470 strlcpy(bp, qname, (size_t)(ep - bp)); 471 hent->h_name = bp; 472 bp += n; 473 } 474 if (res->options & RES_USE_INET6) 475 map_v4v6_hostent(hent, &bp, ep); 476 goto success; 477 } 478no_recovery: 479 free(aliases); 480 *he = NO_RECOVERY; 481 return NULL; 482success: 483 bp = (char *)ALIGN(bp); 484 n = (int)(ap - aliases); 485 qlen = (n + 1) * sizeof(*hent->h_aliases); 486 if ((size_t)(ep - bp) < qlen) 487 goto nospc; 488 hent->h_aliases = (void *)bp; 489 memcpy(bp, aliases, qlen); 490 free(aliases); 491 aliases = NULL; 492 493 bp += qlen; 494 n = (int)(hap - addr_ptrs); 495 qlen = (n + 1) * sizeof(*hent->h_addr_list); 496 if ((size_t)(ep - bp) < qlen) 497 goto nospc; 498 hent->h_addr_list = (void *)bp; 499 memcpy(bp, addr_ptrs, qlen); 500 *he = NETDB_SUCCESS; 501 return hent; 502nospc: 503 free(aliases); 504 errno = ENOSPC; 505 *he = NETDB_INTERNAL; 506 return NULL; 507} 508 509/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */ 510int 511gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, 512 struct hostent **result, int *errorp) 513{ 514 res_state res = __res_get_state(); 515 516 if (res == NULL) { 517 *result = NULL; 518 *errorp = NETDB_INTERNAL; 519 return -1; 520 } 521 522 _DIAGASSERT(name != NULL); 523 524 if (res->options & RES_USE_INET6) { 525 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp, NETID_UNSET, 526 MARK_UNSET); 527 if (*result) { 528 __res_put_state(res); 529 return 0; 530 } 531 } 532 *result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, NETID_UNSET, 533 MARK_UNSET); 534 __res_put_state(res); 535 if (!*result && errno == ENOSPC) { 536 errno = ERANGE; 537 return ERANGE; /* Return error as in linux manual page. */ 538 } 539 return (*result) ? 0 : -1; 540} 541 542/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */ 543int 544gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf, 545 size_t buflen, struct hostent **result, int *errorp) 546{ 547 res_state res = __res_get_state(); 548 549 if (res == NULL) { 550 *result = NULL; 551 *errorp = NETDB_INTERNAL; 552 return -1; 553 } 554 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, NETID_UNSET, 555 MARK_UNSET); 556 __res_put_state(res); 557 if (!*result && errno == ENOSPC) { 558 errno = ERANGE; 559 return ERANGE; 560 } 561 return (*result) ? 0 : -1; 562} 563 564__LIBC_HIDDEN__ FILE* android_open_proxy() { 565 const char* cache_mode = getenv("ANDROID_DNS_MODE"); 566 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0); 567 if (!use_proxy) { 568 return NULL; 569 } 570 571 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 572 if (s == -1) { 573 return NULL; 574 } 575 576 const int one = 1; 577 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 578 579 struct sockaddr_un proxy_addr; 580 memset(&proxy_addr, 0, sizeof(proxy_addr)); 581 proxy_addr.sun_family = AF_UNIX; 582 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path)); 583 584 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) { 585 close(s); 586 return NULL; 587 } 588 589 return fdopen(s, "r+"); 590} 591 592static struct hostent * 593android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he) 594{ 595 uint32_t size; 596 char buf[4]; 597 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL; 598 599 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp 600 // and changes here need to be matched there. 601 int result_code = strtol(buf, NULL, 10); 602 if (result_code != DnsProxyQueryResult) { 603 fread(&size, 1, sizeof(size), proxy); 604 *he = HOST_NOT_FOUND; 605 return NULL; 606 } 607 608 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 609 size = ntohl(size); 610 611 memset(hp, 0, sizeof(*hp)); 612 char *ptr = hbuf; 613 char *hbuf_end = hbuf + hbuflen; 614 615 if (ptr + size > hbuf_end) { 616 goto nospc; 617 } 618 if (fread(ptr, 1, size, proxy) != size) return NULL; 619 hp->h_name = ptr; 620 ptr += size; 621 622 char *aliases_ptrs[MAXALIASES]; 623 char **aliases = &aliases_ptrs[0]; 624 625 while (1) { 626 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 627 size = ntohl(size); 628 629 if (size == 0) { 630 *aliases = NULL; 631 break; 632 } 633 if (ptr + size > hbuf_end) { 634 goto nospc; 635 } 636 if (fread(ptr, 1, size, proxy) != size) return NULL; 637 if (aliases < &aliases_ptrs[MAXALIASES - 1]) { 638 *aliases++ = ptr; 639 } 640 ptr += size; 641 } 642 643 int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases); 644 if (ptr + aliases_len > hbuf_end) { 645 goto nospc; 646 } 647 hp->h_aliases = (void*)ptr; 648 memcpy(ptr, aliases_ptrs, aliases_len); 649 ptr += aliases_len; 650 651 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 652 hp->h_addrtype = ntohl(size); 653 654 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 655 hp->h_length = ntohl(size); 656 657 char *addr_ptrs[MAXADDRS]; 658 char **addr_p = &addr_ptrs[0]; 659 660 while (1) { 661 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 662 size = ntohl(size); 663 if (size == 0) { 664 *addr_p = NULL; 665 break; 666 } 667 if (ptr + size > hbuf_end) { 668 goto nospc; 669 } 670 if (fread(ptr, 1, size, proxy) != size) return NULL; 671 if (addr_p < &addr_ptrs[MAXADDRS - 1]) { 672 *addr_p++ = ptr; 673 } 674 ptr += size; 675 } 676 677 int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list); 678 if (ptr + addrs_len > hbuf_end) { 679 goto nospc; 680 } 681 hp->h_addr_list = (void*)ptr; 682 memcpy(ptr, addr_ptrs, addrs_len); 683 *he = NETDB_SUCCESS; 684 return hp; 685 686nospc: 687 *he = NETDB_INTERNAL; 688 errno = ENOSPC; 689 return NULL; 690} 691 692static struct hostent * 693gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf, 694 size_t buflen, int *he) 695{ 696 const char *cp; 697 struct getnamaddr info; 698 char hbuf[MAXHOSTNAMELEN]; 699 size_t size; 700 static const ns_dtab dtab[] = { 701 NS_FILES_CB(_hf_gethtbyname, NULL) 702 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ 703 NS_NIS_CB(_yp_gethtbyname, NULL) 704 NS_NULL_CB 705 }; 706 707 _DIAGASSERT(name != NULL); 708 709 switch (af) { 710 case AF_INET: 711 size = NS_INADDRSZ; 712 break; 713 case AF_INET6: 714 size = NS_IN6ADDRSZ; 715 break; 716 default: 717 *he = NETDB_INTERNAL; 718 errno = EAFNOSUPPORT; 719 return NULL; 720 } 721 if (buflen < size) 722 goto nospc; 723 724 hp->h_addrtype = af; 725 hp->h_length = (int)size; 726 727 /* 728 * if there aren't any dots, it could be a user-level alias. 729 * this is also done in res_nquery() since we are not the only 730 * function that looks up host names. 731 */ 732 if (!strchr(name, '.') && (cp = res_hostalias(res, name, 733 hbuf, sizeof(hbuf)))) 734 name = cp; 735 736 /* 737 * disallow names consisting only of digits/dots, unless 738 * they end in a dot. 739 */ 740 if (isdigit((u_char) name[0])) 741 for (cp = name;; ++cp) { 742 if (!*cp) { 743 if (*--cp == '.') 744 break; 745 /* 746 * All-numeric, no dot at the end. 747 * Fake up a hostent as if we'd actually 748 * done a lookup. 749 */ 750 goto fake; 751 } 752 if (!isdigit((u_char) *cp) && *cp != '.') 753 break; 754 } 755 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || 756 name[0] == ':') 757 for (cp = name;; ++cp) { 758 if (!*cp) { 759 if (*--cp == '.') 760 break; 761 /* 762 * All-IPv6-legal, no dot at the end. 763 * Fake up a hostent as if we'd actually 764 * done a lookup. 765 */ 766 goto fake; 767 } 768 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') 769 break; 770 } 771 772 *he = NETDB_INTERNAL; 773 info.hp = hp; 774 info.buf = buf; 775 info.buflen = buflen; 776 info.he = he; 777 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname", 778 default_dns_files, name, strlen(name), af) != NS_SUCCESS) 779 return NULL; 780 *he = NETDB_SUCCESS; 781 return hp; 782nospc: 783 *he = NETDB_INTERNAL; 784 errno = ENOSPC; 785 return NULL; 786fake: 787 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen); 788 HENT_ARRAY(hp->h_aliases, 0, buf, buflen); 789 790 hp->h_aliases[0] = NULL; 791 if (size > buflen) 792 goto nospc; 793 794 if (inet_pton(af, name, buf) <= 0) { 795 *he = HOST_NOT_FOUND; 796 return NULL; 797 } 798 hp->h_addr_list[0] = buf; 799 hp->h_addr_list[1] = NULL; 800 buf += size; 801 buflen -= size; 802 HENT_SCOPY(hp->h_name, name, buf, buflen); 803 if (res->options & RES_USE_INET6) 804 map_v4v6_hostent(hp, &buf, buf + buflen); 805 *he = NETDB_SUCCESS; 806 return hp; 807} 808 809// very similar in proxy-ness to android_getaddrinfo_proxy 810static struct hostent * 811gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf, 812 size_t hbuflen, int *errorp, unsigned netid, unsigned mark) 813{ 814 FILE* proxy = android_open_proxy(); 815 if (proxy == NULL) { 816 // Either we're not supposed to be using the proxy or the proxy is unavailable. 817 res_setnetid(res, netid); 818 res_setmark(res, mark); 819 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp); 820 } 821 822 netid = __netdClientDispatch.netIdForResolv(netid); 823 824 // This is writing to system/netd/server/DnsProxyListener.cpp and changes 825 // here need to be matched there. 826 if (fprintf(proxy, "gethostbyname %u %s %d", 827 netid, 828 name == NULL ? "^" : name, 829 af) < 0) { 830 fclose(proxy); 831 return NULL; 832 } 833 834 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { 835 fclose(proxy); 836 return NULL; 837 } 838 839 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp); 840 fclose(proxy); 841 return result; 842} 843 844/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */ 845int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf, 846 size_t buflen, struct hostent **result, int *h_errnop) 847{ 848 *result = android_gethostbyaddrfornet_proxy_internal(addr, len, af, hp, buf, buflen, h_errnop, 849 NETID_UNSET, MARK_UNSET); 850 if (!*result && errno == ENOSPC) { 851 errno = ERANGE; 852 return ERANGE; 853 } 854 return (*result) ? 0 : -1; 855} 856 857static struct hostent * 858android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, struct hostent *hp, 859 char *buf, size_t buflen, int *he, unsigned netid, unsigned mark) 860{ 861 const u_char *uaddr = (const u_char *)addr; 862 socklen_t size; 863 struct getnamaddr info; 864 static const ns_dtab dtab[] = { 865 NS_FILES_CB(_hf_gethtbyaddr, NULL) 866 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */ 867 NS_NIS_CB(_yp_gethtbyaddr, NULL) 868 NS_NULL_CB 869 }; 870 871 _DIAGASSERT(addr != NULL); 872 873 if (af == AF_INET6 && len == NS_IN6ADDRSZ && 874 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) || 875 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) { 876 *he = HOST_NOT_FOUND; 877 return NULL; 878 } 879 if (af == AF_INET6 && len == NS_IN6ADDRSZ && 880 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) || 881 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) { 882 /* Unmap. */ 883 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ; 884 addr = uaddr; 885 af = AF_INET; 886 len = NS_INADDRSZ; 887 } 888 switch (af) { 889 case AF_INET: 890 size = NS_INADDRSZ; 891 break; 892 case AF_INET6: 893 size = NS_IN6ADDRSZ; 894 break; 895 default: 896 errno = EAFNOSUPPORT; 897 *he = NETDB_INTERNAL; 898 return NULL; 899 } 900 if (size != len) { 901 errno = EINVAL; 902 *he = NETDB_INTERNAL; 903 return NULL; 904 } 905 info.hp = hp; 906 info.buf = buf; 907 info.buflen = buflen; 908 info.he = he; 909 *he = NETDB_INTERNAL; 910 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr", 911 default_dns_files, uaddr, len, af, netid, mark) != NS_SUCCESS) 912 return NULL; 913 *he = NETDB_SUCCESS; 914 return hp; 915} 916 917static struct hostent* 918android_gethostbyaddrfornet_proxy_internal(const void* addr, socklen_t len, int af, 919 struct hostent *hp, char *hbuf, size_t hbuflen, int *he, 920 unsigned netid, unsigned mark) 921{ 922 FILE* proxy = android_open_proxy(); 923 if (proxy == NULL) { 924 // Either we're not supposed to be using the proxy or the proxy is unavailable. 925 return android_gethostbyaddrfornet_real(addr,len, af, hp, hbuf, hbuflen, he, netid, mark); 926 } 927 928 char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6 929 const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf)); 930 if (addrStr == NULL) { 931 fclose(proxy); 932 return NULL; 933 } 934 935 netid = __netdClientDispatch.netIdForResolv(netid); 936 937 if (fprintf(proxy, "gethostbyaddr %s %d %d %u", 938 addrStr, len, af, netid) < 0) { 939 fclose(proxy); 940 return NULL; 941 } 942 943 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { 944 fclose(proxy); 945 return NULL; 946 } 947 948 struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he); 949 fclose(proxy); 950 return result; 951} 952 953struct hostent* 954netbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he) 955{ 956 char *p, *name; 957 char *cp, **q; 958 int af, len; 959 size_t anum; 960 char **aliases; 961 size_t maxaliases; 962 struct in6_addr host_addr; 963 964 if (hf == NULL) { 965 *he = NETDB_INTERNAL; 966 errno = EINVAL; 967 return NULL; 968 } 969 p = NULL; 970 setup(aliases, maxaliases); 971 972 /* Allocate a new space to read file lines like upstream does. 973 * To keep reentrancy we cannot use __res_get_static()->hostbuf here, 974 * as the buffer may be used to store content for a previous hostent 975 * returned by non-reentrant functions like gethostbyname(). 976 */ 977 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf); 978 if ((p = malloc(line_buf_size)) == NULL) { 979 goto nospc; 980 } 981 for (;;) { 982 if (!fgets(p, line_buf_size, hf)) { 983 free(p); 984 free(aliases); 985 *he = HOST_NOT_FOUND; 986 return NULL; 987 } 988 if (*p == '#') { 989 continue; 990 } 991 if (!(cp = strpbrk(p, "#\n"))) { 992 continue; 993 } 994 *cp = '\0'; 995 if (!(cp = strpbrk(p, " \t"))) 996 continue; 997 *cp++ = '\0'; 998 if (inet_pton(AF_INET6, p, &host_addr) > 0) { 999 af = AF_INET6; 1000 len = NS_IN6ADDRSZ; 1001 } else { 1002 if (inet_pton(AF_INET, p, &host_addr) <= 0) 1003 continue; 1004 1005 res_state res = __res_get_state(); 1006 if (res == NULL) 1007 goto nospc; 1008 if (res->options & RES_USE_INET6) { 1009 map_v4v6_address(buf, buf); 1010 af = AF_INET6; 1011 len = NS_IN6ADDRSZ; 1012 } else { 1013 af = AF_INET; 1014 len = NS_INADDRSZ; 1015 } 1016 __res_put_state(res); 1017 } 1018 1019 /* if this is not something we're looking for, skip it. */ 1020 if (hent->h_addrtype != 0 && hent->h_addrtype != af) 1021 continue; 1022 if (hent->h_length != 0 && hent->h_length != len) 1023 continue; 1024 1025 while (*cp == ' ' || *cp == '\t') 1026 cp++; 1027 if ((cp = strpbrk(name = cp, " \t")) != NULL) 1028 *cp++ = '\0'; 1029 q = aliases; 1030 while (cp && *cp) { 1031 if (*cp == ' ' || *cp == '\t') { 1032 cp++; 1033 continue; 1034 } 1035 addalias(q, cp, aliases, maxaliases); 1036 if ((cp = strpbrk(cp, " \t")) != NULL) 1037 *cp++ = '\0'; 1038 } 1039 break; 1040 } 1041 hent->h_length = len; 1042 hent->h_addrtype = af; 1043 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen); 1044 anum = (size_t)(q - aliases); 1045 HENT_ARRAY(hent->h_aliases, anum, buf, buflen); 1046 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, 1047 buflen); 1048 hent->h_addr_list[1] = NULL; 1049 1050 HENT_SCOPY(hent->h_name, name, buf, buflen); 1051 for (size_t i = 0; i < anum; i++) 1052 HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen); 1053 hent->h_aliases[anum] = NULL; 1054 1055 *he = NETDB_SUCCESS; 1056 free(p); 1057 free(aliases); 1058 return hent; 1059nospc: 1060 free(p); 1061 free(aliases); 1062 errno = ENOSPC; 1063 *he = NETDB_INTERNAL; 1064 return NULL; 1065} 1066 1067static void 1068map_v4v6_address(const char *src, char *dst) 1069{ 1070 u_char *p = (u_char *)dst; 1071 char tmp[NS_INADDRSZ]; 1072 int i; 1073 1074 _DIAGASSERT(src != NULL); 1075 _DIAGASSERT(dst != NULL); 1076 1077 /* Stash a temporary copy so our caller can update in place. */ 1078 (void)memcpy(tmp, src, NS_INADDRSZ); 1079 /* Mark this ipv6 addr as a mapped ipv4. */ 1080 for (i = 0; i < 10; i++) 1081 *p++ = 0x00; 1082 *p++ = 0xff; 1083 *p++ = 0xff; 1084 /* Retrieve the saved copy and we're done. */ 1085 (void)memcpy(p, tmp, NS_INADDRSZ); 1086} 1087 1088static void 1089map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) 1090{ 1091 char **ap; 1092 1093 _DIAGASSERT(hp != NULL); 1094 _DIAGASSERT(bpp != NULL); 1095 _DIAGASSERT(ep != NULL); 1096 1097 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) 1098 return; 1099 hp->h_addrtype = AF_INET6; 1100 hp->h_length = NS_IN6ADDRSZ; 1101 for (ap = hp->h_addr_list; *ap; ap++) { 1102 int i = (int)(sizeof(align) - 1103 (size_t)((u_long)*bpp % sizeof(align))); 1104 1105 if (ep - *bpp < (i + NS_IN6ADDRSZ)) { 1106 /* Out of memory. Truncate address list here. XXX */ 1107 *ap = NULL; 1108 return; 1109 } 1110 *bpp += i; 1111 map_v4v6_address(*ap, *bpp); 1112 *ap = *bpp; 1113 *bpp += NS_IN6ADDRSZ; 1114 } 1115} 1116 1117static void 1118addrsort(char **ap, int num, res_state res) 1119{ 1120 int i, j; 1121 char **p; 1122 short aval[MAXADDRS]; 1123 int needsort = 0; 1124 1125 _DIAGASSERT(ap != NULL); 1126 1127 p = ap; 1128 for (i = 0; i < num; i++, p++) { 1129 for (j = 0 ; (unsigned)j < res->nsort; j++) 1130 if (res->sort_list[j].addr.s_addr == 1131 (((struct in_addr *)(void *)(*p))->s_addr & 1132 res->sort_list[j].mask)) 1133 break; 1134 aval[i] = j; 1135 if (needsort == 0 && i > 0 && j < aval[i-1]) 1136 needsort = i; 1137 } 1138 if (!needsort) 1139 return; 1140 1141 while (needsort < num) { 1142 for (j = needsort - 1; j >= 0; j--) { 1143 if (aval[j] > aval[j+1]) { 1144 char *hp; 1145 1146 i = aval[j]; 1147 aval[j] = aval[j+1]; 1148 aval[j+1] = i; 1149 1150 hp = ap[j]; 1151 ap[j] = ap[j+1]; 1152 ap[j+1] = hp; 1153 } else 1154 break; 1155 } 1156 needsort++; 1157 } 1158} 1159 1160/*ARGSUSED*/ 1161static int 1162_dns_gethtbyname(void *rv, void *cb_data, va_list ap) 1163{ 1164 querybuf *buf; 1165 int n, type; 1166 struct hostent *hp; 1167 const char *name; 1168 res_state res; 1169 struct getnamaddr *info = rv; 1170 1171 _DIAGASSERT(rv != NULL); 1172 1173 name = va_arg(ap, char *); 1174 /* NOSTRICT skip string len */(void)va_arg(ap, int); 1175 info->hp->h_addrtype = va_arg(ap, int); 1176 1177 switch (info->hp->h_addrtype) { 1178 case AF_INET: 1179 info->hp->h_length = NS_INADDRSZ; 1180 type = T_A; 1181 break; 1182 case AF_INET6: 1183 info->hp->h_length = NS_IN6ADDRSZ; 1184 type = T_AAAA; 1185 break; 1186 default: 1187 return NS_UNAVAIL; 1188 } 1189 buf = malloc(sizeof(*buf)); 1190 if (buf == NULL) { 1191 *info->he = NETDB_INTERNAL; 1192 return NS_NOTFOUND; 1193 } 1194 res = __res_get_state(); 1195 if (res == NULL) { 1196 free(buf); 1197 return NS_NOTFOUND; 1198 } 1199 n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf)); 1200 if (n < 0) { 1201 free(buf); 1202 debugprintf("res_nsearch failed (%d)\n", res, n); 1203 __res_put_state(res); 1204 return NS_NOTFOUND; 1205 } 1206 hp = getanswer(buf, n, name, type, res, info->hp, info->buf, 1207 info->buflen, info->he); 1208 free(buf); 1209 __res_put_state(res); 1210 if (hp == NULL) 1211 switch (*info->he) { 1212 case HOST_NOT_FOUND: 1213 return NS_NOTFOUND; 1214 case TRY_AGAIN: 1215 return NS_TRYAGAIN; 1216 default: 1217 return NS_UNAVAIL; 1218 } 1219 return NS_SUCCESS; 1220} 1221 1222/*ARGSUSED*/ 1223static int 1224_dns_gethtbyaddr(void *rv, void *cb_data, va_list ap) 1225{ 1226 char qbuf[MAXDNAME + 1], *qp, *ep; 1227 int n; 1228 querybuf *buf; 1229 struct hostent *hp; 1230 const unsigned char *uaddr; 1231 int advance; 1232 res_state res; 1233 char *bf; 1234 size_t blen; 1235 struct getnamaddr *info = rv; 1236 unsigned netid, mark; 1237 1238 _DIAGASSERT(rv != NULL); 1239 1240 uaddr = va_arg(ap, unsigned char *); 1241 info->hp->h_length = va_arg(ap, int); 1242 info->hp->h_addrtype = va_arg(ap, int); 1243 netid = va_arg(ap, unsigned); 1244 mark = va_arg(ap, unsigned); 1245 1246 switch (info->hp->h_addrtype) { 1247 case AF_INET: 1248 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", 1249 (uaddr[3] & 0xff), (uaddr[2] & 0xff), 1250 (uaddr[1] & 0xff), (uaddr[0] & 0xff)); 1251 break; 1252 1253 case AF_INET6: 1254 qp = qbuf; 1255 ep = qbuf + sizeof(qbuf) - 1; 1256 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { 1257 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", 1258 uaddr[n] & 0xf, 1259 ((unsigned int)uaddr[n] >> 4) & 0xf); 1260 if (advance > 0 && qp + advance < ep) 1261 qp += advance; 1262 else { 1263 *info->he = NETDB_INTERNAL; 1264 return NS_NOTFOUND; 1265 } 1266 } 1267 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) { 1268 *info->he = NETDB_INTERNAL; 1269 return NS_NOTFOUND; 1270 } 1271 break; 1272 default: 1273 return NS_UNAVAIL; 1274 } 1275 1276 buf = malloc(sizeof(*buf)); 1277 if (buf == NULL) { 1278 *info->he = NETDB_INTERNAL; 1279 return NS_NOTFOUND; 1280 } 1281 res = __res_get_state(); 1282 if (res == NULL) { 1283 free(buf); 1284 return NS_NOTFOUND; 1285 } 1286 res_setnetid(res, netid); 1287 res_setmark(res, mark); 1288 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf)); 1289 if (n < 0) { 1290 free(buf); 1291 debugprintf("res_nquery failed (%d)\n", res, n); 1292 __res_put_state(res); 1293 return NS_NOTFOUND; 1294 } 1295 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, 1296 info->buflen, info->he); 1297 free(buf); 1298 if (hp == NULL) { 1299 __res_put_state(res); 1300 switch (*info->he) { 1301 case HOST_NOT_FOUND: 1302 return NS_NOTFOUND; 1303 case TRY_AGAIN: 1304 return NS_TRYAGAIN; 1305 default: 1306 return NS_UNAVAIL; 1307 } 1308 } 1309 1310 bf = (void *)(hp->h_addr_list + 2); 1311 blen = (size_t)(bf - info->buf); 1312 if (blen + info->hp->h_length > info->buflen) 1313 goto nospc; 1314 hp->h_addr_list[0] = bf; 1315 hp->h_addr_list[1] = NULL; 1316 (void)memcpy(bf, uaddr, (size_t)info->hp->h_length); 1317 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) { 1318 if (blen + NS_IN6ADDRSZ > info->buflen) 1319 goto nospc; 1320 map_v4v6_address(bf, bf); 1321 hp->h_addrtype = AF_INET6; 1322 hp->h_length = NS_IN6ADDRSZ; 1323 } 1324 1325 __res_put_state(res); 1326 *info->he = NETDB_SUCCESS; 1327 return NS_SUCCESS; 1328nospc: 1329 errno = ENOSPC; 1330 *info->he = NETDB_INTERNAL; 1331 return NS_UNAVAIL; 1332} 1333 1334#ifdef YP 1335/*ARGSUSED*/ 1336static struct hostent * 1337_yp_hostent(char *line, int af, struct getnamaddr *info) 1338{ 1339 struct in6_addr host_addrs[MAXADDRS]; 1340 char **aliases; 1341 size_t maxaliases; 1342 char *p = line; 1343 char *cp, **q, *ptr; 1344 size_t len, anum, i; 1345 int addrok; 1346 int more; 1347 size_t naddrs; 1348 struct hostent *hp = info->hp; 1349 1350 _DIAGASSERT(line != NULL); 1351 1352 hp->h_name = NULL; 1353 hp->h_addrtype = af; 1354 switch (af) { 1355 case AF_INET: 1356 hp->h_length = NS_INADDRSZ; 1357 break; 1358 case AF_INET6: 1359 hp->h_length = NS_IN6ADDRSZ; 1360 break; 1361 default: 1362 return NULL; 1363 } 1364 setup(aliases, maxaliases); 1365 naddrs = 0; 1366 q = aliases; 1367 1368nextline: 1369 /* check for host_addrs overflow */ 1370 if (naddrs >= __arraycount(host_addrs)) 1371 goto done; 1372 1373 more = 0; 1374 cp = strpbrk(p, " \t"); 1375 if (cp == NULL) 1376 goto done; 1377 *cp++ = '\0'; 1378 1379 /* p has should have an address */ 1380 addrok = inet_pton(af, p, &host_addrs[naddrs]); 1381 if (addrok != 1) { 1382 /* skip to the next line */ 1383 while (cp && *cp) { 1384 if (*cp == '\n') { 1385 cp++; 1386 goto nextline; 1387 } 1388 cp++; 1389 } 1390 goto done; 1391 } 1392 naddrs++; 1393 1394 while (*cp == ' ' || *cp == '\t') 1395 cp++; 1396 p = cp; 1397 cp = strpbrk(p, " \t\n"); 1398 if (cp != NULL) { 1399 if (*cp == '\n') 1400 more = 1; 1401 *cp++ = '\0'; 1402 } 1403 if (!hp->h_name) 1404 hp->h_name = p; 1405 else if (strcmp(hp->h_name, p) == 0) 1406 ; 1407 else 1408 addalias(q, p, aliases, maxaliases); 1409 p = cp; 1410 if (more) 1411 goto nextline; 1412 1413 while (cp && *cp) { 1414 if (*cp == ' ' || *cp == '\t') { 1415 cp++; 1416 continue; 1417 } 1418 if (*cp == '\n') { 1419 cp++; 1420 goto nextline; 1421 } 1422 addalias(q, cp, aliases, maxaliases); 1423 cp = strpbrk(cp, " \t"); 1424 if (cp != NULL) 1425 *cp++ = '\0'; 1426 } 1427 1428done: 1429 if (hp->h_name == NULL) { 1430 free(aliases); 1431 return NULL; 1432 } 1433 1434 ptr = info->buf; 1435 len = info->buflen; 1436 1437 anum = (size_t)(q - aliases); 1438 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len); 1439 HENT_ARRAY(hp->h_aliases, anum, ptr, len); 1440 1441 for (i = 0; i < naddrs; i++) 1442 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length, 1443 ptr, len); 1444 hp->h_addr_list[naddrs] = NULL; 1445 1446 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len); 1447 1448 for (i = 0; i < anum; i++) 1449 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); 1450 hp->h_aliases[anum] = NULL; 1451 free(aliases); 1452 1453 return hp; 1454nospc: 1455 free(aliases); 1456 *info->he = NETDB_INTERNAL; 1457 errno = ENOSPC; 1458 return NULL; 1459} 1460 1461/*ARGSUSED*/ 1462int 1463_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap) 1464{ 1465 struct hostent *hp = NULL; 1466 char *ypcurrent; 1467 int ypcurrentlen, r; 1468 char name[INET6_ADDRSTRLEN]; /* XXX enough? */ 1469 const unsigned char *uaddr; 1470 int af; 1471 const char *map; 1472 struct getnamaddr *info = rv; 1473 1474 _DIAGASSERT(rv != NULL); 1475 1476 uaddr = va_arg(ap, unsigned char *); 1477 /* NOSTRICT skip len */(void)va_arg(ap, int); 1478 af = va_arg(ap, int); 1479 1480 if (!__ypdomain) { 1481 if (_yp_check(&__ypdomain) == 0) 1482 return NS_UNAVAIL; 1483 } 1484 /* 1485 * XXX unfortunately, we cannot support IPv6 extended scoped address 1486 * notation here. gethostbyaddr() is not scope-aware. too bad. 1487 */ 1488 if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL) 1489 return NS_UNAVAIL; 1490 switch (af) { 1491 case AF_INET: 1492 map = "hosts.byaddr"; 1493 break; 1494 default: 1495 map = "ipnodes.byaddr"; 1496 break; 1497 } 1498 ypcurrent = NULL; 1499 r = yp_match(__ypdomain, map, name, 1500 (int)strlen(name), &ypcurrent, &ypcurrentlen); 1501 if (r == 0) 1502 hp = _yp_hostent(ypcurrent, af, info); 1503 else 1504 hp = NULL; 1505 free(ypcurrent); 1506 if (hp == NULL) { 1507 *info->he = HOST_NOT_FOUND; 1508 return NS_NOTFOUND; 1509 } 1510 return NS_SUCCESS; 1511} 1512 1513/*ARGSUSED*/ 1514int 1515_yp_gethtbyname(void *rv, void *cb_data, va_list ap) 1516{ 1517 struct hostent *hp; 1518 char *ypcurrent; 1519 int ypcurrentlen, r; 1520 const char *name; 1521 int af; 1522 const char *map; 1523 struct getnamaddr *info = rv; 1524 1525 _DIAGASSERT(rv != NULL); 1526 1527 name = va_arg(ap, char *); 1528 /* NOSTRICT skip string len */(void)va_arg(ap, int); 1529 af = va_arg(ap, int); 1530 1531 if (!__ypdomain) { 1532 if (_yp_check(&__ypdomain) == 0) 1533 return NS_UNAVAIL; 1534 } 1535 switch (af) { 1536 case AF_INET: 1537 map = "hosts.byname"; 1538 break; 1539 default: 1540 map = "ipnodes.byname"; 1541 break; 1542 } 1543 ypcurrent = NULL; 1544 r = yp_match(__ypdomain, map, name, 1545 (int)strlen(name), &ypcurrent, &ypcurrentlen); 1546 if (r == 0) 1547 hp = _yp_hostent(ypcurrent, af, info); 1548 else 1549 hp = NULL; 1550 free(ypcurrent); 1551 if (hp == NULL) { 1552 *info->he = HOST_NOT_FOUND; 1553 return NS_NOTFOUND; 1554 } 1555 return NS_SUCCESS; 1556} 1557#endif 1558 1559/* 1560 * Non-reentrant versions. 1561 */ 1562 1563struct hostent * 1564gethostbyname(const char *name) 1565{ 1566 struct hostent *result = NULL; 1567 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1568 1569 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); 1570 return result; 1571} 1572 1573struct hostent * 1574gethostbyname2(const char *name, int af) 1575{ 1576 struct hostent *result = NULL; 1577 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1578 1579 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); 1580 return result; 1581} 1582 1583struct hostent * 1584android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark) 1585{ 1586 struct hostent *hp; 1587 res_state res = __res_get_state(); 1588 if (res == NULL) 1589 return NULL; 1590 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1591 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), 1592 &h_errno, netid, mark); 1593 __res_put_state(res); 1594 return hp; 1595} 1596 1597struct hostent * 1598gethostbyaddr(const void *addr, socklen_t len, int af) 1599{ 1600 return android_gethostbyaddrfornet_proxy(addr, len, af, NETID_UNSET, MARK_UNSET); 1601} 1602 1603struct hostent * 1604android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) 1605{ 1606 return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark); 1607} 1608 1609__LIBC_HIDDEN__ struct hostent* 1610android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af, 1611 unsigned netid, unsigned mark) 1612{ 1613 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1614 return android_gethostbyaddrfornet_proxy_internal(addr, len, af, &rs->host, rs->hostbuf, 1615 sizeof(rs->hostbuf), &h_errno, netid, mark); 1616} 1617 1618struct hostent * 1619gethostent(void) 1620{ 1621 res_static rs = __res_get_static(); 1622 if (!rs->hostf) { 1623 sethostent_r(&rs->hostf); 1624 if (!rs->hostf) { 1625 h_errno = NETDB_INTERNAL; 1626 return NULL; 1627 } 1628 } 1629 memset(&rs->host, 0, sizeof(rs->host)); 1630 return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno); 1631} 1632