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