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