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 static struct hostent * 569 android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he) 570 { 571 uint32_t size; 572 char buf[4]; 573 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL; 574 575 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp 576 // and changes here need to be matched there. 577 int result_code = strtol(buf, NULL, 10); 578 if (result_code != DnsProxyQueryResult) { 579 fread(&size, 1, sizeof(size), proxy); 580 *he = HOST_NOT_FOUND; 581 return NULL; 582 } 583 584 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 585 size = ntohl(size); 586 587 memset(hp, 0, sizeof(*hp)); 588 char *ptr = hbuf; 589 char *hbuf_end = hbuf + hbuflen; 590 591 if (ptr + size > hbuf_end) { 592 goto nospc; 593 } 594 if (fread(ptr, 1, size, proxy) != size) return NULL; 595 hp->h_name = ptr; 596 ptr += size; 597 598 char *aliases_ptrs[MAXALIASES]; 599 char **aliases = &aliases_ptrs[0]; 600 601 while (1) { 602 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 603 size = ntohl(size); 604 605 if (size == 0) { 606 *aliases = NULL; 607 break; 608 } 609 if (ptr + size > hbuf_end) { 610 goto nospc; 611 } 612 if (fread(ptr, 1, size, proxy) != size) return NULL; 613 if (aliases < &aliases_ptrs[MAXALIASES - 1]) { 614 *aliases++ = ptr; 615 } 616 ptr += size; 617 } 618 619 // Fix alignment after variable-length data. 620 ptr = (char*)ALIGN(ptr); 621 622 int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases); 623 if (ptr + aliases_len > hbuf_end) { 624 goto nospc; 625 } 626 hp->h_aliases = (void*)ptr; 627 memcpy(ptr, aliases_ptrs, aliases_len); 628 ptr += aliases_len; 629 630 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 631 hp->h_addrtype = ntohl(size); 632 633 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 634 hp->h_length = ntohl(size); 635 636 char *addr_ptrs[MAXADDRS]; 637 char **addr_p = &addr_ptrs[0]; 638 639 while (1) { 640 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 641 size = ntohl(size); 642 if (size == 0) { 643 *addr_p = NULL; 644 break; 645 } 646 if (ptr + size > hbuf_end) { 647 goto nospc; 648 } 649 if (fread(ptr, 1, size, proxy) != size) return NULL; 650 if (addr_p < &addr_ptrs[MAXADDRS - 1]) { 651 *addr_p++ = ptr; 652 } 653 ptr += size; 654 } 655 656 // Fix alignment after variable-length data. 657 ptr = (char*)ALIGN(ptr); 658 659 int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list); 660 if (ptr + addrs_len > hbuf_end) { 661 goto nospc; 662 } 663 hp->h_addr_list = (void*)ptr; 664 memcpy(ptr, addr_ptrs, addrs_len); 665 *he = NETDB_SUCCESS; 666 return hp; 667 668 nospc: 669 *he = NETDB_INTERNAL; 670 errno = ENOSPC; 671 return NULL; 672 } 673 674 static struct hostent * 675 gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf, 676 size_t buflen, int *he) 677 { 678 const char *cp; 679 struct getnamaddr info; 680 char hbuf[MAXHOSTNAMELEN]; 681 size_t size; 682 static const ns_dtab dtab[] = { 683 NS_FILES_CB(_hf_gethtbyname, NULL) 684 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ 685 NS_NIS_CB(_yp_gethtbyname, NULL) 686 NS_NULL_CB 687 }; 688 689 _DIAGASSERT(name != NULL); 690 691 switch (af) { 692 case AF_INET: 693 size = NS_INADDRSZ; 694 break; 695 case AF_INET6: 696 size = NS_IN6ADDRSZ; 697 break; 698 default: 699 *he = NETDB_INTERNAL; 700 errno = EAFNOSUPPORT; 701 return NULL; 702 } 703 if (buflen < size) 704 goto nospc; 705 706 hp->h_addrtype = af; 707 hp->h_length = (int)size; 708 709 /* 710 * if there aren't any dots, it could be a user-level alias. 711 * this is also done in res_nquery() since we are not the only 712 * function that looks up host names. 713 */ 714 if (!strchr(name, '.') && (cp = res_hostalias(res, name, 715 hbuf, sizeof(hbuf)))) 716 name = cp; 717 718 /* 719 * disallow names consisting only of digits/dots, unless 720 * they end in a dot. 721 */ 722 if (isdigit((u_char) name[0])) 723 for (cp = name;; ++cp) { 724 if (!*cp) { 725 if (*--cp == '.') 726 break; 727 /* 728 * All-numeric, no dot at the end. 729 * Fake up a hostent as if we'd actually 730 * done a lookup. 731 */ 732 goto fake; 733 } 734 if (!isdigit((u_char) *cp) && *cp != '.') 735 break; 736 } 737 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || 738 name[0] == ':') 739 for (cp = name;; ++cp) { 740 if (!*cp) { 741 if (*--cp == '.') 742 break; 743 /* 744 * All-IPv6-legal, no dot at the end. 745 * Fake up a hostent as if we'd actually 746 * done a lookup. 747 */ 748 goto fake; 749 } 750 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') 751 break; 752 } 753 754 *he = NETDB_INTERNAL; 755 info.hp = hp; 756 info.buf = buf; 757 info.buflen = buflen; 758 info.he = he; 759 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname", 760 default_dns_files, name, strlen(name), af) != NS_SUCCESS) 761 return NULL; 762 *he = NETDB_SUCCESS; 763 return hp; 764 nospc: 765 *he = NETDB_INTERNAL; 766 errno = ENOSPC; 767 return NULL; 768 fake: 769 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen); 770 HENT_ARRAY(hp->h_aliases, 0, buf, buflen); 771 772 hp->h_aliases[0] = NULL; 773 if (size > buflen) 774 goto nospc; 775 776 if (inet_pton(af, name, buf) <= 0) { 777 *he = HOST_NOT_FOUND; 778 return NULL; 779 } 780 hp->h_addr_list[0] = buf; 781 hp->h_addr_list[1] = NULL; 782 buf += size; 783 buflen -= size; 784 HENT_SCOPY(hp->h_name, name, buf, buflen); 785 if (res->options & RES_USE_INET6) 786 map_v4v6_hostent(hp, &buf, buf + buflen); 787 *he = NETDB_SUCCESS; 788 return hp; 789 } 790 791 static struct hostent * 792 gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf, 793 size_t hbuflen, int *errorp, const struct android_net_context *netcontext) 794 { 795 FILE* proxy = fdopen(__netdClientDispatch.dnsOpenProxy(), "r+"); 796 if (proxy == NULL) { 797 // Either we're not supposed to be using the proxy or the proxy is unavailable. 798 res_setnetcontext(res, netcontext); 799 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp); 800 } 801 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid); 802 803 // This is writing to system/netd/server/DnsProxyListener.cpp and changes 804 // here need to be matched there. 805 if (fprintf(proxy, "gethostbyname %u %s %d", 806 netid, 807 name == NULL ? "^" : name, 808 af) < 0) { 809 fclose(proxy); 810 return NULL; 811 } 812 813 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { 814 fclose(proxy); 815 return NULL; 816 } 817 818 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp); 819 fclose(proxy); 820 return result; 821 } 822 823 /* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */ 824 int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf, 825 size_t buflen, struct hostent **result, int *h_errnop) 826 { 827 *result = android_gethostbyaddrfornetcontext_proxy_internal( 828 addr, len, af, hp, buf, buflen, h_errnop, &NETCONTEXT_UNSET); 829 return h_errno_to_result(h_errnop); 830 } 831 832 static struct hostent * 833 android_gethostbyaddrfornetcontext_real(const void *addr, socklen_t len, int af, struct hostent *hp, 834 char *buf, size_t buflen, int *he, 835 const struct android_net_context *netcontext) 836 { 837 const u_char *uaddr = (const u_char *)addr; 838 socklen_t size; 839 struct getnamaddr info; 840 static const ns_dtab dtab[] = { 841 NS_FILES_CB(_hf_gethtbyaddr, NULL) 842 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */ 843 NS_NIS_CB(_yp_gethtbyaddr, NULL) 844 NS_NULL_CB 845 }; 846 847 _DIAGASSERT(addr != NULL); 848 849 if (af == AF_INET6 && len == NS_IN6ADDRSZ && 850 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) || 851 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) { 852 *he = HOST_NOT_FOUND; 853 return NULL; 854 } 855 if (af == AF_INET6 && len == NS_IN6ADDRSZ && 856 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) || 857 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) { 858 /* Unmap. */ 859 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ; 860 addr = uaddr; 861 af = AF_INET; 862 len = NS_INADDRSZ; 863 } 864 switch (af) { 865 case AF_INET: 866 size = NS_INADDRSZ; 867 break; 868 case AF_INET6: 869 size = NS_IN6ADDRSZ; 870 break; 871 default: 872 errno = EAFNOSUPPORT; 873 *he = NETDB_INTERNAL; 874 return NULL; 875 } 876 if (size != len) { 877 errno = EINVAL; 878 *he = NETDB_INTERNAL; 879 return NULL; 880 } 881 info.hp = hp; 882 info.buf = buf; 883 info.buflen = buflen; 884 info.he = he; 885 *he = NETDB_INTERNAL; 886 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr", 887 default_dns_files, uaddr, len, af, netcontext) != NS_SUCCESS) 888 return NULL; 889 *he = NETDB_SUCCESS; 890 return hp; 891 } 892 893 static struct hostent* 894 android_gethostbyaddrfornetcontext_proxy_internal(const void* addr, socklen_t len, int af, 895 struct hostent *hp, char *hbuf, size_t hbuflen, int *he, 896 const struct android_net_context *netcontext) 897 { 898 FILE* proxy = fdopen(__netdClientDispatch.dnsOpenProxy(), "r+"); 899 if (proxy == NULL) { 900 // Either we're not supposed to be using the proxy or the proxy is unavailable. 901 return android_gethostbyaddrfornetcontext_real(addr,len, af, hp, hbuf, hbuflen, he, netcontext); 902 } 903 char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6 904 const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf)); 905 if (addrStr == NULL) { 906 fclose(proxy); 907 return NULL; 908 } 909 910 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid); 911 912 if (fprintf(proxy, "gethostbyaddr %s %d %d %u", 913 addrStr, len, af, netid) < 0) { 914 fclose(proxy); 915 return NULL; 916 } 917 918 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { 919 fclose(proxy); 920 return NULL; 921 } 922 923 struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he); 924 fclose(proxy); 925 return result; 926 } 927 928 struct hostent* 929 netbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he) 930 { 931 char *p, *name; 932 char *cp, **q; 933 int af, len; 934 size_t anum; 935 char **aliases; 936 size_t maxaliases; 937 struct in6_addr host_addr; 938 939 if (hf == NULL) { 940 *he = NETDB_INTERNAL; 941 errno = EINVAL; 942 return NULL; 943 } 944 p = NULL; 945 setup(aliases, maxaliases); 946 947 /* Allocate a new space to read file lines like upstream does. 948 * To keep reentrancy we cannot use __res_get_static()->hostbuf here, 949 * as the buffer may be used to store content for a previous hostent 950 * returned by non-reentrant functions like gethostbyname(). 951 */ 952 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf); 953 if ((p = malloc(line_buf_size)) == NULL) { 954 goto nospc; 955 } 956 for (;;) { 957 if (!fgets(p, line_buf_size, hf)) { 958 free(p); 959 free(aliases); 960 *he = HOST_NOT_FOUND; 961 return NULL; 962 } 963 if (*p == '#') { 964 continue; 965 } 966 if (!(cp = strpbrk(p, "#\n"))) { 967 continue; 968 } 969 *cp = '\0'; 970 if (!(cp = strpbrk(p, " \t"))) 971 continue; 972 *cp++ = '\0'; 973 if (inet_pton(AF_INET6, p, &host_addr) > 0) { 974 af = AF_INET6; 975 len = NS_IN6ADDRSZ; 976 } else { 977 if (inet_pton(AF_INET, p, &host_addr) <= 0) 978 continue; 979 980 res_state res = __res_get_state(); 981 if (res == NULL) 982 goto nospc; 983 if (res->options & RES_USE_INET6) { 984 map_v4v6_address(buf, buf); 985 af = AF_INET6; 986 len = NS_IN6ADDRSZ; 987 } else { 988 af = AF_INET; 989 len = NS_INADDRSZ; 990 } 991 __res_put_state(res); 992 } 993 994 /* if this is not something we're looking for, skip it. */ 995 if (hent->h_addrtype != 0 && hent->h_addrtype != af) 996 continue; 997 if (hent->h_length != 0 && hent->h_length != len) 998 continue; 999 1000 while (*cp == ' ' || *cp == '\t') 1001 cp++; 1002 if ((cp = strpbrk(name = cp, " \t")) != NULL) 1003 *cp++ = '\0'; 1004 q = aliases; 1005 while (cp && *cp) { 1006 if (*cp == ' ' || *cp == '\t') { 1007 cp++; 1008 continue; 1009 } 1010 addalias(q, cp, aliases, maxaliases); 1011 if ((cp = strpbrk(cp, " \t")) != NULL) 1012 *cp++ = '\0'; 1013 } 1014 break; 1015 } 1016 hent->h_length = len; 1017 hent->h_addrtype = af; 1018 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen); 1019 anum = (size_t)(q - aliases); 1020 HENT_ARRAY(hent->h_aliases, anum, buf, buflen); 1021 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, 1022 buflen); 1023 hent->h_addr_list[1] = NULL; 1024 1025 HENT_SCOPY(hent->h_name, name, buf, buflen); 1026 for (size_t i = 0; i < anum; i++) 1027 HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen); 1028 hent->h_aliases[anum] = NULL; 1029 1030 *he = NETDB_SUCCESS; 1031 free(p); 1032 free(aliases); 1033 return hent; 1034 nospc: 1035 free(p); 1036 free(aliases); 1037 errno = ENOSPC; 1038 *he = NETDB_INTERNAL; 1039 return NULL; 1040 } 1041 1042 static void 1043 map_v4v6_address(const char *src, char *dst) 1044 { 1045 u_char *p = (u_char *)dst; 1046 char tmp[NS_INADDRSZ]; 1047 int i; 1048 1049 _DIAGASSERT(src != NULL); 1050 _DIAGASSERT(dst != NULL); 1051 1052 /* Stash a temporary copy so our caller can update in place. */ 1053 (void)memcpy(tmp, src, NS_INADDRSZ); 1054 /* Mark this ipv6 addr as a mapped ipv4. */ 1055 for (i = 0; i < 10; i++) 1056 *p++ = 0x00; 1057 *p++ = 0xff; 1058 *p++ = 0xff; 1059 /* Retrieve the saved copy and we're done. */ 1060 (void)memcpy(p, tmp, NS_INADDRSZ); 1061 } 1062 1063 static void 1064 map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) 1065 { 1066 char **ap; 1067 1068 _DIAGASSERT(hp != NULL); 1069 _DIAGASSERT(bpp != NULL); 1070 _DIAGASSERT(ep != NULL); 1071 1072 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) 1073 return; 1074 hp->h_addrtype = AF_INET6; 1075 hp->h_length = NS_IN6ADDRSZ; 1076 for (ap = hp->h_addr_list; *ap; ap++) { 1077 int i = (int)(sizeof(align) - 1078 (size_t)((u_long)*bpp % sizeof(align))); 1079 1080 if (ep - *bpp < (i + NS_IN6ADDRSZ)) { 1081 /* Out of memory. Truncate address list here. XXX */ 1082 *ap = NULL; 1083 return; 1084 } 1085 *bpp += i; 1086 map_v4v6_address(*ap, *bpp); 1087 *ap = *bpp; 1088 *bpp += NS_IN6ADDRSZ; 1089 } 1090 } 1091 1092 static void 1093 addrsort(char **ap, int num, res_state res) 1094 { 1095 int i, j; 1096 char **p; 1097 short aval[MAXADDRS]; 1098 int needsort = 0; 1099 1100 _DIAGASSERT(ap != NULL); 1101 1102 p = ap; 1103 for (i = 0; i < num; i++, p++) { 1104 for (j = 0 ; (unsigned)j < res->nsort; j++) 1105 if (res->sort_list[j].addr.s_addr == 1106 (((struct in_addr *)(void *)(*p))->s_addr & 1107 res->sort_list[j].mask)) 1108 break; 1109 aval[i] = j; 1110 if (needsort == 0 && i > 0 && j < aval[i-1]) 1111 needsort = i; 1112 } 1113 if (!needsort) 1114 return; 1115 1116 while (needsort < num) { 1117 for (j = needsort - 1; j >= 0; j--) { 1118 if (aval[j] > aval[j+1]) { 1119 char *hp; 1120 1121 i = aval[j]; 1122 aval[j] = aval[j+1]; 1123 aval[j+1] = i; 1124 1125 hp = ap[j]; 1126 ap[j] = ap[j+1]; 1127 ap[j+1] = hp; 1128 } else 1129 break; 1130 } 1131 needsort++; 1132 } 1133 } 1134 1135 /*ARGSUSED*/ 1136 static int 1137 _dns_gethtbyname(void *rv, void *cb_data, va_list ap) 1138 { 1139 querybuf *buf; 1140 int n, type; 1141 struct hostent *hp; 1142 const char *name; 1143 res_state res; 1144 struct getnamaddr *info = rv; 1145 1146 _DIAGASSERT(rv != NULL); 1147 1148 name = va_arg(ap, char *); 1149 /* NOSTRICT skip string len */(void)va_arg(ap, int); 1150 info->hp->h_addrtype = va_arg(ap, int); 1151 1152 switch (info->hp->h_addrtype) { 1153 case AF_INET: 1154 info->hp->h_length = NS_INADDRSZ; 1155 type = T_A; 1156 break; 1157 case AF_INET6: 1158 info->hp->h_length = NS_IN6ADDRSZ; 1159 type = T_AAAA; 1160 break; 1161 default: 1162 return NS_UNAVAIL; 1163 } 1164 buf = malloc(sizeof(*buf)); 1165 if (buf == NULL) { 1166 *info->he = NETDB_INTERNAL; 1167 return NS_NOTFOUND; 1168 } 1169 res = __res_get_state(); 1170 if (res == NULL) { 1171 free(buf); 1172 return NS_NOTFOUND; 1173 } 1174 n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf)); 1175 if (n < 0) { 1176 free(buf); 1177 debugprintf("res_nsearch failed (%d)\n", res, n); 1178 __res_put_state(res); 1179 return NS_NOTFOUND; 1180 } 1181 hp = getanswer(buf, n, name, type, res, info->hp, info->buf, 1182 info->buflen, info->he); 1183 free(buf); 1184 __res_put_state(res); 1185 if (hp == NULL) 1186 switch (*info->he) { 1187 case HOST_NOT_FOUND: 1188 return NS_NOTFOUND; 1189 case TRY_AGAIN: 1190 return NS_TRYAGAIN; 1191 default: 1192 return NS_UNAVAIL; 1193 } 1194 return NS_SUCCESS; 1195 } 1196 1197 /*ARGSUSED*/ 1198 static int 1199 _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap) 1200 { 1201 char qbuf[MAXDNAME + 1], *qp, *ep; 1202 int n; 1203 querybuf *buf; 1204 struct hostent *hp; 1205 const unsigned char *uaddr; 1206 int advance; 1207 res_state res; 1208 char *bf; 1209 size_t blen; 1210 struct getnamaddr *info = rv; 1211 const struct android_net_context *netcontext; 1212 1213 _DIAGASSERT(rv != NULL); 1214 1215 uaddr = va_arg(ap, unsigned char *); 1216 info->hp->h_length = va_arg(ap, int); 1217 info->hp->h_addrtype = va_arg(ap, int); 1218 netcontext = va_arg(ap, const struct android_net_context *); 1219 1220 switch (info->hp->h_addrtype) { 1221 case AF_INET: 1222 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", 1223 (uaddr[3] & 0xff), (uaddr[2] & 0xff), 1224 (uaddr[1] & 0xff), (uaddr[0] & 0xff)); 1225 break; 1226 1227 case AF_INET6: 1228 qp = qbuf; 1229 ep = qbuf + sizeof(qbuf) - 1; 1230 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { 1231 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", 1232 uaddr[n] & 0xf, 1233 ((unsigned int)uaddr[n] >> 4) & 0xf); 1234 if (advance > 0 && qp + advance < ep) 1235 qp += advance; 1236 else { 1237 *info->he = NETDB_INTERNAL; 1238 return NS_NOTFOUND; 1239 } 1240 } 1241 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) { 1242 *info->he = NETDB_INTERNAL; 1243 return NS_NOTFOUND; 1244 } 1245 break; 1246 default: 1247 return NS_UNAVAIL; 1248 } 1249 1250 buf = malloc(sizeof(*buf)); 1251 if (buf == NULL) { 1252 *info->he = NETDB_INTERNAL; 1253 return NS_NOTFOUND; 1254 } 1255 res = __res_get_state(); 1256 if (res == NULL) { 1257 free(buf); 1258 return NS_NOTFOUND; 1259 } 1260 res_setnetcontext(res, netcontext); 1261 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf)); 1262 if (n < 0) { 1263 free(buf); 1264 debugprintf("res_nquery failed (%d)\n", res, n); 1265 __res_put_state(res); 1266 return NS_NOTFOUND; 1267 } 1268 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, 1269 info->buflen, info->he); 1270 free(buf); 1271 if (hp == NULL) { 1272 __res_put_state(res); 1273 switch (*info->he) { 1274 case HOST_NOT_FOUND: 1275 return NS_NOTFOUND; 1276 case TRY_AGAIN: 1277 return NS_TRYAGAIN; 1278 default: 1279 return NS_UNAVAIL; 1280 } 1281 } 1282 1283 bf = (void *)(hp->h_addr_list + 2); 1284 blen = (size_t)(bf - info->buf); 1285 if (blen + info->hp->h_length > info->buflen) 1286 goto nospc; 1287 hp->h_addr_list[0] = bf; 1288 hp->h_addr_list[1] = NULL; 1289 (void)memcpy(bf, uaddr, (size_t)info->hp->h_length); 1290 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) { 1291 if (blen + NS_IN6ADDRSZ > info->buflen) 1292 goto nospc; 1293 map_v4v6_address(bf, bf); 1294 hp->h_addrtype = AF_INET6; 1295 hp->h_length = NS_IN6ADDRSZ; 1296 } 1297 1298 __res_put_state(res); 1299 *info->he = NETDB_SUCCESS; 1300 return NS_SUCCESS; 1301 nospc: 1302 errno = ENOSPC; 1303 *info->he = NETDB_INTERNAL; 1304 return NS_UNAVAIL; 1305 } 1306 1307 #ifdef YP 1308 /*ARGSUSED*/ 1309 static struct hostent * 1310 _yp_hostent(char *line, int af, struct getnamaddr *info) 1311 { 1312 struct in6_addr host_addrs[MAXADDRS]; 1313 char **aliases; 1314 size_t maxaliases; 1315 char *p = line; 1316 char *cp, **q, *ptr; 1317 size_t len, anum, i; 1318 int addrok; 1319 int more; 1320 size_t naddrs; 1321 struct hostent *hp = info->hp; 1322 1323 _DIAGASSERT(line != NULL); 1324 1325 hp->h_name = NULL; 1326 hp->h_addrtype = af; 1327 switch (af) { 1328 case AF_INET: 1329 hp->h_length = NS_INADDRSZ; 1330 break; 1331 case AF_INET6: 1332 hp->h_length = NS_IN6ADDRSZ; 1333 break; 1334 default: 1335 return NULL; 1336 } 1337 setup(aliases, maxaliases); 1338 naddrs = 0; 1339 q = aliases; 1340 1341 nextline: 1342 /* check for host_addrs overflow */ 1343 if (naddrs >= __arraycount(host_addrs)) 1344 goto done; 1345 1346 more = 0; 1347 cp = strpbrk(p, " \t"); 1348 if (cp == NULL) 1349 goto done; 1350 *cp++ = '\0'; 1351 1352 /* p has should have an address */ 1353 addrok = inet_pton(af, p, &host_addrs[naddrs]); 1354 if (addrok != 1) { 1355 /* skip to the next line */ 1356 while (cp && *cp) { 1357 if (*cp == '\n') { 1358 cp++; 1359 goto nextline; 1360 } 1361 cp++; 1362 } 1363 goto done; 1364 } 1365 naddrs++; 1366 1367 while (*cp == ' ' || *cp == '\t') 1368 cp++; 1369 p = cp; 1370 cp = strpbrk(p, " \t\n"); 1371 if (cp != NULL) { 1372 if (*cp == '\n') 1373 more = 1; 1374 *cp++ = '\0'; 1375 } 1376 if (!hp->h_name) 1377 hp->h_name = p; 1378 else if (strcmp(hp->h_name, p) == 0) 1379 ; 1380 else 1381 addalias(q, p, aliases, maxaliases); 1382 p = cp; 1383 if (more) 1384 goto nextline; 1385 1386 while (cp && *cp) { 1387 if (*cp == ' ' || *cp == '\t') { 1388 cp++; 1389 continue; 1390 } 1391 if (*cp == '\n') { 1392 cp++; 1393 goto nextline; 1394 } 1395 addalias(q, cp, aliases, maxaliases); 1396 cp = strpbrk(cp, " \t"); 1397 if (cp != NULL) 1398 *cp++ = '\0'; 1399 } 1400 1401 done: 1402 if (hp->h_name == NULL) { 1403 free(aliases); 1404 return NULL; 1405 } 1406 1407 ptr = info->buf; 1408 len = info->buflen; 1409 1410 anum = (size_t)(q - aliases); 1411 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len); 1412 HENT_ARRAY(hp->h_aliases, anum, ptr, len); 1413 1414 for (i = 0; i < naddrs; i++) 1415 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length, 1416 ptr, len); 1417 hp->h_addr_list[naddrs] = NULL; 1418 1419 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len); 1420 1421 for (i = 0; i < anum; i++) 1422 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); 1423 hp->h_aliases[anum] = NULL; 1424 free(aliases); 1425 1426 return hp; 1427 nospc: 1428 free(aliases); 1429 *info->he = NETDB_INTERNAL; 1430 errno = ENOSPC; 1431 return NULL; 1432 } 1433 1434 /*ARGSUSED*/ 1435 int 1436 _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap) 1437 { 1438 struct hostent *hp = NULL; 1439 char *ypcurrent; 1440 int ypcurrentlen, r; 1441 char name[INET6_ADDRSTRLEN]; /* XXX enough? */ 1442 const unsigned char *uaddr; 1443 int af; 1444 const char *map; 1445 struct getnamaddr *info = rv; 1446 1447 _DIAGASSERT(rv != NULL); 1448 1449 uaddr = va_arg(ap, unsigned char *); 1450 /* NOSTRICT skip len */(void)va_arg(ap, int); 1451 af = va_arg(ap, int); 1452 1453 if (!__ypdomain) { 1454 if (_yp_check(&__ypdomain) == 0) 1455 return NS_UNAVAIL; 1456 } 1457 /* 1458 * XXX unfortunately, we cannot support IPv6 extended scoped address 1459 * notation here. gethostbyaddr() is not scope-aware. too bad. 1460 */ 1461 if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL) 1462 return NS_UNAVAIL; 1463 switch (af) { 1464 case AF_INET: 1465 map = "hosts.byaddr"; 1466 break; 1467 default: 1468 map = "ipnodes.byaddr"; 1469 break; 1470 } 1471 ypcurrent = NULL; 1472 r = yp_match(__ypdomain, map, name, 1473 (int)strlen(name), &ypcurrent, &ypcurrentlen); 1474 if (r == 0) 1475 hp = _yp_hostent(ypcurrent, af, info); 1476 else 1477 hp = NULL; 1478 free(ypcurrent); 1479 if (hp == NULL) { 1480 *info->he = HOST_NOT_FOUND; 1481 return NS_NOTFOUND; 1482 } 1483 return NS_SUCCESS; 1484 } 1485 1486 /*ARGSUSED*/ 1487 int 1488 _yp_gethtbyname(void *rv, void *cb_data, va_list ap) 1489 { 1490 struct hostent *hp; 1491 char *ypcurrent; 1492 int ypcurrentlen, r; 1493 const char *name; 1494 int af; 1495 const char *map; 1496 struct getnamaddr *info = rv; 1497 1498 _DIAGASSERT(rv != NULL); 1499 1500 name = va_arg(ap, char *); 1501 /* NOSTRICT skip string len */(void)va_arg(ap, int); 1502 af = va_arg(ap, int); 1503 1504 if (!__ypdomain) { 1505 if (_yp_check(&__ypdomain) == 0) 1506 return NS_UNAVAIL; 1507 } 1508 switch (af) { 1509 case AF_INET: 1510 map = "hosts.byname"; 1511 break; 1512 default: 1513 map = "ipnodes.byname"; 1514 break; 1515 } 1516 ypcurrent = NULL; 1517 r = yp_match(__ypdomain, map, name, 1518 (int)strlen(name), &ypcurrent, &ypcurrentlen); 1519 if (r == 0) 1520 hp = _yp_hostent(ypcurrent, af, info); 1521 else 1522 hp = NULL; 1523 free(ypcurrent); 1524 if (hp == NULL) { 1525 *info->he = HOST_NOT_FOUND; 1526 return NS_NOTFOUND; 1527 } 1528 return NS_SUCCESS; 1529 } 1530 #endif 1531 1532 /* 1533 * Non-reentrant versions. 1534 */ 1535 1536 struct hostent * 1537 gethostbyname(const char *name) 1538 { 1539 struct hostent *result = NULL; 1540 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1541 1542 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); 1543 return result; 1544 } 1545 1546 struct hostent * 1547 gethostbyname2(const char *name, int af) 1548 { 1549 struct hostent *result = NULL; 1550 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1551 1552 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); 1553 return result; 1554 } 1555 1556 // android_gethostby*fornet can be called in two different contexts. 1557 // - In the proxy client context (proxy != NULL), |netid| is |app_netid|. 1558 // - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|. 1559 // The netcontext is constructed before checking which context we are in. 1560 // Therefore, we have to populate both fields, and rely on the downstream code to check whether 1561 // |proxy == NULL|, and use that info to query the field that matches the caller's intent. 1562 static struct android_net_context make_context(unsigned netid, unsigned mark) { 1563 struct android_net_context netcontext = NETCONTEXT_UNSET; 1564 netcontext.app_netid = netid; 1565 netcontext.app_mark = mark; 1566 netcontext.dns_netid = netid; 1567 netcontext.dns_mark = mark; 1568 return netcontext; 1569 } 1570 1571 struct hostent * 1572 android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark) 1573 { 1574 const struct android_net_context netcontext = make_context(netid, mark); 1575 return android_gethostbynamefornetcontext(name, af, &netcontext); 1576 } 1577 1578 struct hostent * 1579 android_gethostbynamefornetcontext(const char *name, int af, 1580 const struct android_net_context *netcontext) 1581 { 1582 struct hostent *hp; 1583 res_state res = __res_get_state(); 1584 if (res == NULL) 1585 return NULL; 1586 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1587 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), 1588 &h_errno, netcontext); 1589 __res_put_state(res); 1590 return hp; 1591 } 1592 1593 struct hostent * 1594 gethostbyaddr(const void *addr, socklen_t len, int af) 1595 { 1596 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET); 1597 } 1598 1599 struct hostent * 1600 android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) 1601 { 1602 const struct android_net_context netcontext = make_context(netid, mark); 1603 return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext); 1604 } 1605 1606 struct hostent * 1607 android_gethostbyaddrfornetcontext(const void *addr, socklen_t len, int af, 1608 const struct android_net_context *netcontext) 1609 { 1610 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext); 1611 } 1612 1613 __LIBC_HIDDEN__ struct hostent* 1614 android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af, 1615 const struct android_net_context *netcontext) 1616 { 1617 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1618 return android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, &rs->host, rs->hostbuf, 1619 sizeof(rs->hostbuf), &h_errno, netcontext); 1620 } 1621 1622 struct hostent * 1623 gethostent(void) 1624 { 1625 res_static rs = __res_get_static(); 1626 if (!rs->hostf) { 1627 sethostent_r(&rs->hostf); 1628 if (!rs->hostf) { 1629 h_errno = NETDB_INTERNAL; 1630 return NULL; 1631 } 1632 } 1633 memset(&rs->host, 0, sizeof(rs->host)); 1634 return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno); 1635 } 1636