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 cp += (x); \ 190 if (cp > eom) \ 191 goto no_recovery; \ 192 } while (/*CONSTCOND*/0) 193 194 #define BOUNDS_CHECK(ptr, count) \ 195 do { \ 196 if ((ptr) + (count) > eom) \ 197 goto no_recovery; \ 198 } while (/*CONSTCOND*/0) 199 200 static struct hostent * 201 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 202 res_state res, struct hostent *hent, char *buf, size_t buflen, int *he) 203 { 204 const HEADER *hp; 205 const u_char *cp; 206 int n; 207 size_t qlen; 208 const u_char *eom, *erdata; 209 char *bp, **ap, **hap, *ep; 210 int type, class, ancount, qdcount; 211 int haveanswer, had_error; 212 int toobig = 0; 213 char tbuf[MAXDNAME]; 214 char **aliases; 215 size_t maxaliases; 216 char *addr_ptrs[MAXADDRS]; 217 const char *tname; 218 int (*name_ok)(const char *); 219 220 _DIAGASSERT(answer != NULL); 221 _DIAGASSERT(qname != NULL); 222 223 tname = qname; 224 hent->h_name = NULL; 225 eom = answer->buf + anslen; 226 switch (qtype) { 227 case T_A: 228 case T_AAAA: 229 name_ok = res_hnok; 230 break; 231 case T_PTR: 232 name_ok = res_dnok; 233 break; 234 default: 235 *he = NO_RECOVERY; 236 return NULL; /* XXX should be abort(); */ 237 } 238 239 setup(aliases, maxaliases); 240 /* 241 * find first satisfactory answer 242 */ 243 hp = &answer->hdr; 244 ancount = ntohs(hp->ancount); 245 qdcount = ntohs(hp->qdcount); 246 bp = buf; 247 ep = buf + buflen; 248 cp = answer->buf; 249 BOUNDED_INCR(HFIXEDSZ); 250 if (qdcount != 1) 251 goto no_recovery; 252 253 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 254 if ((n < 0) || !maybe_ok(res, bp, name_ok)) 255 goto no_recovery; 256 257 BOUNDED_INCR(n + QFIXEDSZ); 258 if (qtype == T_A || qtype == T_AAAA) { 259 /* res_send() has already verified that the query name is the 260 * same as the one we sent; this just gets the expanded name 261 * (i.e., with the succeeding search-domain tacked on). 262 */ 263 n = (int)strlen(bp) + 1; /* for the \0 */ 264 if (n >= MAXHOSTNAMELEN) 265 goto no_recovery; 266 hent->h_name = bp; 267 bp += n; 268 /* The qname can be abbreviated, but h_name is now absolute. */ 269 qname = hent->h_name; 270 } 271 hent->h_aliases = ap = aliases; 272 hent->h_addr_list = hap = addr_ptrs; 273 *ap = NULL; 274 *hap = NULL; 275 haveanswer = 0; 276 had_error = 0; 277 while (ancount-- > 0 && cp < eom && !had_error) { 278 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 279 if ((n < 0) || !maybe_ok(res, bp, name_ok)) { 280 had_error++; 281 continue; 282 } 283 cp += n; /* name */ 284 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 285 type = _getshort(cp); 286 cp += INT16SZ; /* type */ 287 class = _getshort(cp); 288 cp += INT16SZ + INT32SZ; /* class, TTL */ 289 n = _getshort(cp); 290 cp += INT16SZ; /* len */ 291 BOUNDS_CHECK(cp, n); 292 erdata = cp + n; 293 if (class != C_IN) { 294 /* XXX - debug? syslog? */ 295 cp += n; 296 continue; /* XXX - had_error++ ? */ 297 } 298 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { 299 n = dn_expand(answer->buf, eom, cp, tbuf, 300 (int)sizeof tbuf); 301 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) { 302 had_error++; 303 continue; 304 } 305 cp += n; 306 if (cp != erdata) 307 goto no_recovery; 308 /* Store alias. */ 309 addalias(ap, bp, aliases, maxaliases); 310 n = (int)strlen(bp) + 1; /* for the \0 */ 311 if (n >= MAXHOSTNAMELEN) { 312 had_error++; 313 continue; 314 } 315 bp += n; 316 /* Get canonical name. */ 317 n = (int)strlen(tbuf) + 1; /* for the \0 */ 318 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 319 had_error++; 320 continue; 321 } 322 strlcpy(bp, tbuf, (size_t)(ep - bp)); 323 hent->h_name = bp; 324 bp += n; 325 continue; 326 } 327 if (qtype == T_PTR && type == T_CNAME) { 328 n = dn_expand(answer->buf, eom, cp, tbuf, 329 (int)sizeof tbuf); 330 if (n < 0 || !maybe_dnok(res, tbuf)) { 331 had_error++; 332 continue; 333 } 334 cp += n; 335 if (cp != erdata) 336 goto no_recovery; 337 /* Get canonical name. */ 338 n = (int)strlen(tbuf) + 1; /* for the \0 */ 339 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 340 had_error++; 341 continue; 342 } 343 strlcpy(bp, tbuf, (size_t)(ep - bp)); 344 tname = bp; 345 bp += n; 346 continue; 347 } 348 if (type != qtype) { 349 if (type != T_KEY && type != T_SIG) 350 syslog(LOG_NOTICE|LOG_AUTH, 351 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 352 qname, p_class(C_IN), p_type(qtype), 353 p_type(type)); 354 cp += n; 355 continue; /* XXX - had_error++ ? */ 356 } 357 switch (type) { 358 case T_PTR: 359 if (strcasecmp(tname, bp) != 0) { 360 syslog(LOG_NOTICE|LOG_AUTH, 361 AskedForGot, qname, bp); 362 cp += n; 363 continue; /* XXX - had_error++ ? */ 364 } 365 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 366 if ((n < 0) || !maybe_hnok(res, bp)) { 367 had_error++; 368 break; 369 } 370 #if MULTI_PTRS_ARE_ALIASES 371 cp += n; 372 if (cp != erdata) 373 goto no_recovery; 374 if (!haveanswer) 375 hent->h_name = bp; 376 else 377 addalias(ap, bp, aliases, maxaliases); 378 if (n != -1) { 379 n = (int)strlen(bp) + 1; /* for the \0 */ 380 if (n >= MAXHOSTNAMELEN) { 381 had_error++; 382 break; 383 } 384 bp += n; 385 } 386 break; 387 #else 388 hent->h_name = bp; 389 if (res->options & RES_USE_INET6) { 390 n = strlen(bp) + 1; /* for the \0 */ 391 if (n >= MAXHOSTNAMELEN) { 392 had_error++; 393 break; 394 } 395 bp += n; 396 map_v4v6_hostent(hent, &bp, ep); 397 } 398 goto success; 399 #endif 400 case T_A: 401 case T_AAAA: 402 if (strcasecmp(hent->h_name, bp) != 0) { 403 syslog(LOG_NOTICE|LOG_AUTH, 404 AskedForGot, hent->h_name, bp); 405 cp += n; 406 continue; /* XXX - had_error++ ? */ 407 } 408 if (n != hent->h_length) { 409 cp += n; 410 continue; 411 } 412 if (type == T_AAAA) { 413 struct in6_addr in6; 414 memcpy(&in6, cp, NS_IN6ADDRSZ); 415 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 416 cp += n; 417 continue; 418 } 419 } 420 if (!haveanswer) { 421 int nn; 422 423 hent->h_name = bp; 424 nn = (int)strlen(bp) + 1; /* for the \0 */ 425 bp += nn; 426 } 427 428 bp += sizeof(align) - 429 (size_t)((u_long)bp % sizeof(align)); 430 431 if (bp + n >= ep) { 432 debugprintf("size (%d) too big\n", res, n); 433 had_error++; 434 continue; 435 } 436 if (hap >= &addr_ptrs[MAXADDRS - 1]) { 437 if (!toobig++) { 438 debugprintf("Too many addresses (%d)\n", 439 res, MAXADDRS); 440 } 441 cp += n; 442 continue; 443 } 444 (void)memcpy(*hap++ = bp, cp, (size_t)n); 445 bp += n; 446 cp += n; 447 if (cp != erdata) 448 goto no_recovery; 449 break; 450 default: 451 abort(); 452 } 453 if (!had_error) 454 haveanswer++; 455 } 456 if (haveanswer) { 457 *ap = NULL; 458 *hap = NULL; 459 /* 460 * Note: we sort even if host can take only one address 461 * in its return structures - should give it the "best" 462 * address in that case, not some random one 463 */ 464 if (res->nsort && haveanswer > 1 && qtype == T_A) 465 addrsort(addr_ptrs, haveanswer, res); 466 if (!hent->h_name) { 467 n = (int)strlen(qname) + 1; /* for the \0 */ 468 if (n > ep - bp || n >= MAXHOSTNAMELEN) 469 goto no_recovery; 470 strlcpy(bp, qname, (size_t)(ep - bp)); 471 hent->h_name = bp; 472 bp += n; 473 } 474 if (res->options & RES_USE_INET6) 475 map_v4v6_hostent(hent, &bp, ep); 476 goto success; 477 } 478 no_recovery: 479 free(aliases); 480 *he = NO_RECOVERY; 481 return NULL; 482 success: 483 bp = (char *)ALIGN(bp); 484 n = (int)(ap - aliases); 485 qlen = (n + 1) * sizeof(*hent->h_aliases); 486 if ((size_t)(ep - bp) < qlen) 487 goto nospc; 488 hent->h_aliases = (void *)bp; 489 memcpy(bp, aliases, qlen); 490 free(aliases); 491 aliases = NULL; 492 493 bp += qlen; 494 n = (int)(hap - addr_ptrs); 495 qlen = (n + 1) * sizeof(*hent->h_addr_list); 496 if ((size_t)(ep - bp) < qlen) 497 goto nospc; 498 hent->h_addr_list = (void *)bp; 499 memcpy(bp, addr_ptrs, qlen); 500 *he = NETDB_SUCCESS; 501 return hent; 502 nospc: 503 free(aliases); 504 errno = ENOSPC; 505 *he = NETDB_INTERNAL; 506 return NULL; 507 } 508 509 /* The prototype of gethostbyname_r is from glibc, not that in netbsd. */ 510 int 511 gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, 512 struct hostent **result, int *errorp) 513 { 514 res_state res = __res_get_state(); 515 516 if (res == NULL) { 517 *result = NULL; 518 *errorp = NETDB_INTERNAL; 519 return -1; 520 } 521 522 _DIAGASSERT(name != NULL); 523 524 if (res->options & RES_USE_INET6) { 525 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp, NETID_UNSET, 526 MARK_UNSET); 527 if (*result) { 528 __res_put_state(res); 529 return 0; 530 } 531 } 532 *result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, NETID_UNSET, 533 MARK_UNSET); 534 __res_put_state(res); 535 if (!*result && errno == ENOSPC) { 536 errno = ERANGE; 537 return ERANGE; /* Return error as in linux manual page. */ 538 } 539 return (*result) ? 0 : -1; 540 } 541 542 /* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */ 543 int 544 gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf, 545 size_t buflen, struct hostent **result, int *errorp) 546 { 547 res_state res = __res_get_state(); 548 549 if (res == NULL) { 550 *result = NULL; 551 *errorp = NETDB_INTERNAL; 552 return -1; 553 } 554 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, NETID_UNSET, 555 MARK_UNSET); 556 __res_put_state(res); 557 if (!*result && errno == ENOSPC) { 558 errno = ERANGE; 559 return ERANGE; 560 } 561 return (*result) ? 0 : -1; 562 } 563 564 __LIBC_HIDDEN__ FILE* android_open_proxy() { 565 const char* cache_mode = getenv("ANDROID_DNS_MODE"); 566 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0); 567 if (!use_proxy) { 568 return NULL; 569 } 570 571 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 572 if (s == -1) { 573 return NULL; 574 } 575 576 const int one = 1; 577 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 578 579 struct sockaddr_un proxy_addr; 580 memset(&proxy_addr, 0, sizeof(proxy_addr)); 581 proxy_addr.sun_family = AF_UNIX; 582 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path)); 583 584 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) { 585 close(s); 586 return NULL; 587 } 588 589 return fdopen(s, "r+"); 590 } 591 592 static struct hostent * 593 android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he) 594 { 595 uint32_t size; 596 char buf[4]; 597 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL; 598 599 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp 600 // and changes here need to be matched there. 601 int result_code = strtol(buf, NULL, 10); 602 if (result_code != DnsProxyQueryResult) { 603 fread(&size, 1, sizeof(size), proxy); 604 *he = HOST_NOT_FOUND; 605 return NULL; 606 } 607 608 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 609 size = ntohl(size); 610 611 memset(hp, 0, sizeof(*hp)); 612 char *ptr = hbuf; 613 char *hbuf_end = hbuf + hbuflen; 614 615 if (ptr + size > hbuf_end) { 616 goto nospc; 617 } 618 if (fread(ptr, 1, size, proxy) != size) return NULL; 619 hp->h_name = ptr; 620 ptr += size; 621 622 char *aliases_ptrs[MAXALIASES]; 623 char **aliases = &aliases_ptrs[0]; 624 625 while (1) { 626 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 627 size = ntohl(size); 628 629 if (size == 0) { 630 *aliases = NULL; 631 break; 632 } 633 if (ptr + size > hbuf_end) { 634 goto nospc; 635 } 636 if (fread(ptr, 1, size, proxy) != size) return NULL; 637 if (aliases < &aliases_ptrs[MAXALIASES - 1]) { 638 *aliases++ = ptr; 639 } 640 ptr += size; 641 } 642 643 // Fix alignment after variable-length data. 644 ptr = (char*)ALIGN(ptr); 645 646 int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases); 647 if (ptr + aliases_len > hbuf_end) { 648 goto nospc; 649 } 650 hp->h_aliases = (void*)ptr; 651 memcpy(ptr, aliases_ptrs, aliases_len); 652 ptr += aliases_len; 653 654 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 655 hp->h_addrtype = ntohl(size); 656 657 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 658 hp->h_length = ntohl(size); 659 660 char *addr_ptrs[MAXADDRS]; 661 char **addr_p = &addr_ptrs[0]; 662 663 while (1) { 664 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL; 665 size = ntohl(size); 666 if (size == 0) { 667 *addr_p = NULL; 668 break; 669 } 670 if (ptr + size > hbuf_end) { 671 goto nospc; 672 } 673 if (fread(ptr, 1, size, proxy) != size) return NULL; 674 if (addr_p < &addr_ptrs[MAXADDRS - 1]) { 675 *addr_p++ = ptr; 676 } 677 ptr += size; 678 } 679 680 // Fix alignment after variable-length data. 681 ptr = (char*)ALIGN(ptr); 682 683 int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list); 684 if (ptr + addrs_len > hbuf_end) { 685 goto nospc; 686 } 687 hp->h_addr_list = (void*)ptr; 688 memcpy(ptr, addr_ptrs, addrs_len); 689 *he = NETDB_SUCCESS; 690 return hp; 691 692 nospc: 693 *he = NETDB_INTERNAL; 694 errno = ENOSPC; 695 return NULL; 696 } 697 698 static struct hostent * 699 gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf, 700 size_t buflen, int *he) 701 { 702 const char *cp; 703 struct getnamaddr info; 704 char hbuf[MAXHOSTNAMELEN]; 705 size_t size; 706 static const ns_dtab dtab[] = { 707 NS_FILES_CB(_hf_gethtbyname, NULL) 708 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ 709 NS_NIS_CB(_yp_gethtbyname, NULL) 710 NS_NULL_CB 711 }; 712 713 _DIAGASSERT(name != NULL); 714 715 switch (af) { 716 case AF_INET: 717 size = NS_INADDRSZ; 718 break; 719 case AF_INET6: 720 size = NS_IN6ADDRSZ; 721 break; 722 default: 723 *he = NETDB_INTERNAL; 724 errno = EAFNOSUPPORT; 725 return NULL; 726 } 727 if (buflen < size) 728 goto nospc; 729 730 hp->h_addrtype = af; 731 hp->h_length = (int)size; 732 733 /* 734 * if there aren't any dots, it could be a user-level alias. 735 * this is also done in res_nquery() since we are not the only 736 * function that looks up host names. 737 */ 738 if (!strchr(name, '.') && (cp = res_hostalias(res, name, 739 hbuf, sizeof(hbuf)))) 740 name = cp; 741 742 /* 743 * disallow names consisting only of digits/dots, unless 744 * they end in a dot. 745 */ 746 if (isdigit((u_char) name[0])) 747 for (cp = name;; ++cp) { 748 if (!*cp) { 749 if (*--cp == '.') 750 break; 751 /* 752 * All-numeric, no dot at the end. 753 * Fake up a hostent as if we'd actually 754 * done a lookup. 755 */ 756 goto fake; 757 } 758 if (!isdigit((u_char) *cp) && *cp != '.') 759 break; 760 } 761 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || 762 name[0] == ':') 763 for (cp = name;; ++cp) { 764 if (!*cp) { 765 if (*--cp == '.') 766 break; 767 /* 768 * All-IPv6-legal, no dot at the end. 769 * Fake up a hostent as if we'd actually 770 * done a lookup. 771 */ 772 goto fake; 773 } 774 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') 775 break; 776 } 777 778 *he = NETDB_INTERNAL; 779 info.hp = hp; 780 info.buf = buf; 781 info.buflen = buflen; 782 info.he = he; 783 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname", 784 default_dns_files, name, strlen(name), af) != NS_SUCCESS) 785 return NULL; 786 *he = NETDB_SUCCESS; 787 return hp; 788 nospc: 789 *he = NETDB_INTERNAL; 790 errno = ENOSPC; 791 return NULL; 792 fake: 793 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen); 794 HENT_ARRAY(hp->h_aliases, 0, buf, buflen); 795 796 hp->h_aliases[0] = NULL; 797 if (size > buflen) 798 goto nospc; 799 800 if (inet_pton(af, name, buf) <= 0) { 801 *he = HOST_NOT_FOUND; 802 return NULL; 803 } 804 hp->h_addr_list[0] = buf; 805 hp->h_addr_list[1] = NULL; 806 buf += size; 807 buflen -= size; 808 HENT_SCOPY(hp->h_name, name, buf, buflen); 809 if (res->options & RES_USE_INET6) 810 map_v4v6_hostent(hp, &buf, buf + buflen); 811 *he = NETDB_SUCCESS; 812 return hp; 813 } 814 815 // very similar in proxy-ness to android_getaddrinfo_proxy 816 static struct hostent * 817 gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf, 818 size_t hbuflen, int *errorp, unsigned netid, unsigned mark) 819 { 820 FILE* proxy = android_open_proxy(); 821 if (proxy == NULL) { 822 // Either we're not supposed to be using the proxy or the proxy is unavailable. 823 res_setnetid(res, netid); 824 res_setmark(res, mark); 825 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp); 826 } 827 828 netid = __netdClientDispatch.netIdForResolv(netid); 829 830 // This is writing to system/netd/server/DnsProxyListener.cpp and changes 831 // here need to be matched there. 832 if (fprintf(proxy, "gethostbyname %u %s %d", 833 netid, 834 name == NULL ? "^" : name, 835 af) < 0) { 836 fclose(proxy); 837 return NULL; 838 } 839 840 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { 841 fclose(proxy); 842 return NULL; 843 } 844 845 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp); 846 fclose(proxy); 847 return result; 848 } 849 850 /* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */ 851 int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf, 852 size_t buflen, struct hostent **result, int *h_errnop) 853 { 854 *result = android_gethostbyaddrfornet_proxy_internal(addr, len, af, hp, buf, buflen, h_errnop, 855 NETID_UNSET, MARK_UNSET); 856 if (!*result && errno == ENOSPC) { 857 errno = ERANGE; 858 return ERANGE; 859 } 860 return (*result) ? 0 : -1; 861 } 862 863 static struct hostent * 864 android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, struct hostent *hp, 865 char *buf, size_t buflen, int *he, unsigned netid, unsigned mark) 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, netid, mark) != NS_SUCCESS) 918 return NULL; 919 *he = NETDB_SUCCESS; 920 return hp; 921 } 922 923 static struct hostent* 924 android_gethostbyaddrfornet_proxy_internal(const void* addr, socklen_t len, int af, 925 struct hostent *hp, char *hbuf, size_t hbuflen, int *he, 926 unsigned netid, unsigned mark) 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_gethostbyaddrfornet_real(addr,len, af, hp, hbuf, hbuflen, he, netid, mark); 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 netid = __netdClientDispatch.netIdForResolv(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 unsigned netid, mark; 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 netid = va_arg(ap, unsigned); 1250 mark = va_arg(ap, unsigned); 1251 1252 switch (info->hp->h_addrtype) { 1253 case AF_INET: 1254 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", 1255 (uaddr[3] & 0xff), (uaddr[2] & 0xff), 1256 (uaddr[1] & 0xff), (uaddr[0] & 0xff)); 1257 break; 1258 1259 case AF_INET6: 1260 qp = qbuf; 1261 ep = qbuf + sizeof(qbuf) - 1; 1262 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { 1263 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", 1264 uaddr[n] & 0xf, 1265 ((unsigned int)uaddr[n] >> 4) & 0xf); 1266 if (advance > 0 && qp + advance < ep) 1267 qp += advance; 1268 else { 1269 *info->he = NETDB_INTERNAL; 1270 return NS_NOTFOUND; 1271 } 1272 } 1273 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) { 1274 *info->he = NETDB_INTERNAL; 1275 return NS_NOTFOUND; 1276 } 1277 break; 1278 default: 1279 return NS_UNAVAIL; 1280 } 1281 1282 buf = malloc(sizeof(*buf)); 1283 if (buf == NULL) { 1284 *info->he = NETDB_INTERNAL; 1285 return NS_NOTFOUND; 1286 } 1287 res = __res_get_state(); 1288 if (res == NULL) { 1289 free(buf); 1290 return NS_NOTFOUND; 1291 } 1292 res_setnetid(res, netid); 1293 res_setmark(res, mark); 1294 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf)); 1295 if (n < 0) { 1296 free(buf); 1297 debugprintf("res_nquery failed (%d)\n", res, n); 1298 __res_put_state(res); 1299 return NS_NOTFOUND; 1300 } 1301 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, 1302 info->buflen, info->he); 1303 free(buf); 1304 if (hp == NULL) { 1305 __res_put_state(res); 1306 switch (*info->he) { 1307 case HOST_NOT_FOUND: 1308 return NS_NOTFOUND; 1309 case TRY_AGAIN: 1310 return NS_TRYAGAIN; 1311 default: 1312 return NS_UNAVAIL; 1313 } 1314 } 1315 1316 bf = (void *)(hp->h_addr_list + 2); 1317 blen = (size_t)(bf - info->buf); 1318 if (blen + info->hp->h_length > info->buflen) 1319 goto nospc; 1320 hp->h_addr_list[0] = bf; 1321 hp->h_addr_list[1] = NULL; 1322 (void)memcpy(bf, uaddr, (size_t)info->hp->h_length); 1323 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) { 1324 if (blen + NS_IN6ADDRSZ > info->buflen) 1325 goto nospc; 1326 map_v4v6_address(bf, bf); 1327 hp->h_addrtype = AF_INET6; 1328 hp->h_length = NS_IN6ADDRSZ; 1329 } 1330 1331 __res_put_state(res); 1332 *info->he = NETDB_SUCCESS; 1333 return NS_SUCCESS; 1334 nospc: 1335 errno = ENOSPC; 1336 *info->he = NETDB_INTERNAL; 1337 return NS_UNAVAIL; 1338 } 1339 1340 #ifdef YP 1341 /*ARGSUSED*/ 1342 static struct hostent * 1343 _yp_hostent(char *line, int af, struct getnamaddr *info) 1344 { 1345 struct in6_addr host_addrs[MAXADDRS]; 1346 char **aliases; 1347 size_t maxaliases; 1348 char *p = line; 1349 char *cp, **q, *ptr; 1350 size_t len, anum, i; 1351 int addrok; 1352 int more; 1353 size_t naddrs; 1354 struct hostent *hp = info->hp; 1355 1356 _DIAGASSERT(line != NULL); 1357 1358 hp->h_name = NULL; 1359 hp->h_addrtype = af; 1360 switch (af) { 1361 case AF_INET: 1362 hp->h_length = NS_INADDRSZ; 1363 break; 1364 case AF_INET6: 1365 hp->h_length = NS_IN6ADDRSZ; 1366 break; 1367 default: 1368 return NULL; 1369 } 1370 setup(aliases, maxaliases); 1371 naddrs = 0; 1372 q = aliases; 1373 1374 nextline: 1375 /* check for host_addrs overflow */ 1376 if (naddrs >= __arraycount(host_addrs)) 1377 goto done; 1378 1379 more = 0; 1380 cp = strpbrk(p, " \t"); 1381 if (cp == NULL) 1382 goto done; 1383 *cp++ = '\0'; 1384 1385 /* p has should have an address */ 1386 addrok = inet_pton(af, p, &host_addrs[naddrs]); 1387 if (addrok != 1) { 1388 /* skip to the next line */ 1389 while (cp && *cp) { 1390 if (*cp == '\n') { 1391 cp++; 1392 goto nextline; 1393 } 1394 cp++; 1395 } 1396 goto done; 1397 } 1398 naddrs++; 1399 1400 while (*cp == ' ' || *cp == '\t') 1401 cp++; 1402 p = cp; 1403 cp = strpbrk(p, " \t\n"); 1404 if (cp != NULL) { 1405 if (*cp == '\n') 1406 more = 1; 1407 *cp++ = '\0'; 1408 } 1409 if (!hp->h_name) 1410 hp->h_name = p; 1411 else if (strcmp(hp->h_name, p) == 0) 1412 ; 1413 else 1414 addalias(q, p, aliases, maxaliases); 1415 p = cp; 1416 if (more) 1417 goto nextline; 1418 1419 while (cp && *cp) { 1420 if (*cp == ' ' || *cp == '\t') { 1421 cp++; 1422 continue; 1423 } 1424 if (*cp == '\n') { 1425 cp++; 1426 goto nextline; 1427 } 1428 addalias(q, cp, aliases, maxaliases); 1429 cp = strpbrk(cp, " \t"); 1430 if (cp != NULL) 1431 *cp++ = '\0'; 1432 } 1433 1434 done: 1435 if (hp->h_name == NULL) { 1436 free(aliases); 1437 return NULL; 1438 } 1439 1440 ptr = info->buf; 1441 len = info->buflen; 1442 1443 anum = (size_t)(q - aliases); 1444 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len); 1445 HENT_ARRAY(hp->h_aliases, anum, ptr, len); 1446 1447 for (i = 0; i < naddrs; i++) 1448 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length, 1449 ptr, len); 1450 hp->h_addr_list[naddrs] = NULL; 1451 1452 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len); 1453 1454 for (i = 0; i < anum; i++) 1455 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); 1456 hp->h_aliases[anum] = NULL; 1457 free(aliases); 1458 1459 return hp; 1460 nospc: 1461 free(aliases); 1462 *info->he = NETDB_INTERNAL; 1463 errno = ENOSPC; 1464 return NULL; 1465 } 1466 1467 /*ARGSUSED*/ 1468 int 1469 _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap) 1470 { 1471 struct hostent *hp = NULL; 1472 char *ypcurrent; 1473 int ypcurrentlen, r; 1474 char name[INET6_ADDRSTRLEN]; /* XXX enough? */ 1475 const unsigned char *uaddr; 1476 int af; 1477 const char *map; 1478 struct getnamaddr *info = rv; 1479 1480 _DIAGASSERT(rv != NULL); 1481 1482 uaddr = va_arg(ap, unsigned char *); 1483 /* NOSTRICT skip len */(void)va_arg(ap, int); 1484 af = va_arg(ap, int); 1485 1486 if (!__ypdomain) { 1487 if (_yp_check(&__ypdomain) == 0) 1488 return NS_UNAVAIL; 1489 } 1490 /* 1491 * XXX unfortunately, we cannot support IPv6 extended scoped address 1492 * notation here. gethostbyaddr() is not scope-aware. too bad. 1493 */ 1494 if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL) 1495 return NS_UNAVAIL; 1496 switch (af) { 1497 case AF_INET: 1498 map = "hosts.byaddr"; 1499 break; 1500 default: 1501 map = "ipnodes.byaddr"; 1502 break; 1503 } 1504 ypcurrent = NULL; 1505 r = yp_match(__ypdomain, map, name, 1506 (int)strlen(name), &ypcurrent, &ypcurrentlen); 1507 if (r == 0) 1508 hp = _yp_hostent(ypcurrent, af, info); 1509 else 1510 hp = NULL; 1511 free(ypcurrent); 1512 if (hp == NULL) { 1513 *info->he = HOST_NOT_FOUND; 1514 return NS_NOTFOUND; 1515 } 1516 return NS_SUCCESS; 1517 } 1518 1519 /*ARGSUSED*/ 1520 int 1521 _yp_gethtbyname(void *rv, void *cb_data, va_list ap) 1522 { 1523 struct hostent *hp; 1524 char *ypcurrent; 1525 int ypcurrentlen, r; 1526 const char *name; 1527 int af; 1528 const char *map; 1529 struct getnamaddr *info = rv; 1530 1531 _DIAGASSERT(rv != NULL); 1532 1533 name = va_arg(ap, char *); 1534 /* NOSTRICT skip string len */(void)va_arg(ap, int); 1535 af = va_arg(ap, int); 1536 1537 if (!__ypdomain) { 1538 if (_yp_check(&__ypdomain) == 0) 1539 return NS_UNAVAIL; 1540 } 1541 switch (af) { 1542 case AF_INET: 1543 map = "hosts.byname"; 1544 break; 1545 default: 1546 map = "ipnodes.byname"; 1547 break; 1548 } 1549 ypcurrent = NULL; 1550 r = yp_match(__ypdomain, map, name, 1551 (int)strlen(name), &ypcurrent, &ypcurrentlen); 1552 if (r == 0) 1553 hp = _yp_hostent(ypcurrent, af, info); 1554 else 1555 hp = NULL; 1556 free(ypcurrent); 1557 if (hp == NULL) { 1558 *info->he = HOST_NOT_FOUND; 1559 return NS_NOTFOUND; 1560 } 1561 return NS_SUCCESS; 1562 } 1563 #endif 1564 1565 /* 1566 * Non-reentrant versions. 1567 */ 1568 1569 struct hostent * 1570 gethostbyname(const char *name) 1571 { 1572 struct hostent *result = NULL; 1573 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1574 1575 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); 1576 return result; 1577 } 1578 1579 struct hostent * 1580 gethostbyname2(const char *name, int af) 1581 { 1582 struct hostent *result = NULL; 1583 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1584 1585 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno); 1586 return result; 1587 } 1588 1589 struct hostent * 1590 android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark) 1591 { 1592 struct hostent *hp; 1593 res_state res = __res_get_state(); 1594 if (res == NULL) 1595 return NULL; 1596 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1597 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), 1598 &h_errno, netid, mark); 1599 __res_put_state(res); 1600 return hp; 1601 } 1602 1603 struct hostent * 1604 gethostbyaddr(const void *addr, socklen_t len, int af) 1605 { 1606 return android_gethostbyaddrfornet_proxy(addr, len, af, NETID_UNSET, MARK_UNSET); 1607 } 1608 1609 struct hostent * 1610 android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark) 1611 { 1612 return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark); 1613 } 1614 1615 __LIBC_HIDDEN__ struct hostent* 1616 android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af, 1617 unsigned netid, unsigned mark) 1618 { 1619 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */ 1620 return android_gethostbyaddrfornet_proxy_internal(addr, len, af, &rs->host, rs->hostbuf, 1621 sizeof(rs->hostbuf), &h_errno, netid, mark); 1622 } 1623 1624 struct hostent * 1625 gethostent(void) 1626 { 1627 res_static rs = __res_get_static(); 1628 if (!rs->hostf) { 1629 sethostent_r(&rs->hostf); 1630 if (!rs->hostf) { 1631 h_errno = NETDB_INTERNAL; 1632 return NULL; 1633 } 1634 } 1635 memset(&rs->host, 0, sizeof(rs->host)); 1636 return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno); 1637 } 1638