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