1/* $NetBSD: getaddrinfo.c,v 1.82 2006/03/25 12:09:40 rpaulo Exp $ */ 2/* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */ 3 4/* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33/* 34 * Issues to be discussed: 35 * - Thread safe-ness must be checked. 36 * - Return values. There are nonstandard return values defined and used 37 * in the source code. This is because RFC2553 is silent about which error 38 * code must be returned for which situation. 39 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 40 * says to use inet_aton() to convert IPv4 numeric to binary (alows 41 * classful form as a result). 42 * current code - disallow classful form for IPv4 (due to use of inet_pton). 43 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is 44 * invalid. 45 * current code - SEGV on freeaddrinfo(NULL) 46 * Note: 47 * - We use getipnodebyname() just for thread-safeness. There's no intent 48 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to 49 * getipnodebyname(). 50 * - The code filters out AFs that are not supported by the kernel, 51 * when globbing NULL hostname (to loopback, or wildcard). Is it the right 52 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 53 * in ai_flags? 54 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. 55 * (1) what should we do against numeric hostname (2) what should we do 56 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? 57 * non-loopback address configured? global address configured? 58 * - To avoid search order issue, we have a big amount of code duplicate 59 * from gethnamaddr.c and some other places. The issues that there's no 60 * lower layer function to lookup "IPv4 or IPv6" record. Calling 61 * gethostbyname2 from getaddrinfo will end up in wrong search order, as 62 * follows: 63 * - The code makes use of following calls when asked to resolver with 64 * ai_family = PF_UNSPEC: 65 * getipnodebyname(host, AF_INET6); 66 * getipnodebyname(host, AF_INET); 67 * This will result in the following queries if the node is configure to 68 * prefer /etc/hosts than DNS: 69 * lookup /etc/hosts for IPv6 address 70 * lookup DNS for IPv6 address 71 * lookup /etc/hosts for IPv4 address 72 * lookup DNS for IPv4 address 73 * which may not meet people's requirement. 74 * The right thing to happen is to have underlying layer which does 75 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. 76 * This would result in a bit of code duplicate with _dns_ghbyname() and 77 * friends. 78 */ 79 80#include <fcntl.h> 81#include <sys/cdefs.h> 82#include <sys/types.h> 83#include <sys/stat.h> 84#include <sys/param.h> 85#include <sys/socket.h> 86#include <sys/un.h> 87#include <net/if.h> 88#include <netinet/in.h> 89#include <arpa/inet.h> 90#include "arpa_nameser.h" 91#include <assert.h> 92#include <ctype.h> 93#include <errno.h> 94#include <netdb.h> 95#include "resolv_private.h" 96#include <stddef.h> 97#include <stdio.h> 98#include <stdlib.h> 99#include <string.h> 100#include <strings.h> 101#include <unistd.h> 102 103#include <syslog.h> 104#include <stdarg.h> 105#include "nsswitch.h" 106 107#ifdef ANDROID_CHANGES 108#include <sys/system_properties.h> 109#endif /* ANDROID_CHANGES */ 110 111typedef union sockaddr_union { 112 struct sockaddr generic; 113 struct sockaddr_in in; 114 struct sockaddr_in6 in6; 115} sockaddr_union; 116 117#define SUCCESS 0 118#define ANY 0 119#define YES 1 120#define NO 0 121 122static const char in_addrany[] = { 0, 0, 0, 0 }; 123static const char in_loopback[] = { 127, 0, 0, 1 }; 124#ifdef INET6 125static const char in6_addrany[] = { 126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 127}; 128static const char in6_loopback[] = { 129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 130}; 131#endif 132 133// This should be synchronized to ResponseCode.h 134static const int DnsProxyQueryResult = 222; 135 136static const struct afd { 137 int a_af; 138 int a_addrlen; 139 int a_socklen; 140 int a_off; 141 const char *a_addrany; 142 const char *a_loopback; 143 int a_scoped; 144} afdl [] = { 145#ifdef INET6 146 {PF_INET6, sizeof(struct in6_addr), 147 sizeof(struct sockaddr_in6), 148 offsetof(struct sockaddr_in6, sin6_addr), 149 in6_addrany, in6_loopback, 1}, 150#endif 151 {PF_INET, sizeof(struct in_addr), 152 sizeof(struct sockaddr_in), 153 offsetof(struct sockaddr_in, sin_addr), 154 in_addrany, in_loopback, 0}, 155 {0, 0, 0, 0, NULL, NULL, 0}, 156}; 157 158struct explore { 159 int e_af; 160 int e_socktype; 161 int e_protocol; 162 const char *e_protostr; 163 int e_wild; 164#define WILD_AF(ex) ((ex)->e_wild & 0x01) 165#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 166#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 167}; 168 169static const struct explore explore[] = { 170#if 0 171 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, 172#endif 173#ifdef INET6 174 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 175 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 176 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 177#endif 178 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 179 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 180 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 181 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 182 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 183 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, 184 { -1, 0, 0, NULL, 0 }, 185}; 186 187#ifdef INET6 188#define PTON_MAX 16 189#else 190#define PTON_MAX 4 191#endif 192 193static const ns_src default_dns_files[] = { 194 { NSSRC_FILES, NS_SUCCESS }, 195 { NSSRC_DNS, NS_SUCCESS }, 196 { 0, 0 } 197}; 198 199#define MAXPACKET (64*1024) 200 201typedef union { 202 HEADER hdr; 203 u_char buf[MAXPACKET]; 204} querybuf; 205 206struct res_target { 207 struct res_target *next; 208 const char *name; /* domain name */ 209 int qclass, qtype; /* class and type of query */ 210 u_char *answer; /* buffer to put answer */ 211 int anslen; /* size of answer buffer */ 212 int n; /* result length */ 213}; 214 215static int str2number(const char *); 216static int explore_fqdn(const struct addrinfo *, const char *, 217 const char *, struct addrinfo **, const char *iface); 218static int explore_null(const struct addrinfo *, 219 const char *, struct addrinfo **); 220static int explore_numeric(const struct addrinfo *, const char *, 221 const char *, struct addrinfo **, const char *); 222static int explore_numeric_scope(const struct addrinfo *, const char *, 223 const char *, struct addrinfo **); 224static int get_canonname(const struct addrinfo *, 225 struct addrinfo *, const char *); 226static struct addrinfo *get_ai(const struct addrinfo *, 227 const struct afd *, const char *); 228static int get_portmatch(const struct addrinfo *, const char *); 229static int get_port(const struct addrinfo *, const char *, int); 230static const struct afd *find_afd(int); 231#ifdef INET6 232static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); 233#endif 234 235static struct addrinfo *getanswer(const querybuf *, int, const char *, int, 236 const struct addrinfo *); 237static int _dns_getaddrinfo(void *, void *, va_list); 238static void _sethtent(FILE **); 239static void _endhtent(FILE **); 240static struct addrinfo *_gethtent(FILE **, const char *, 241 const struct addrinfo *); 242static int _files_getaddrinfo(void *, void *, va_list); 243 244static int res_queryN(const char *, struct res_target *, res_state); 245static int res_searchN(const char *, struct res_target *, res_state); 246static int res_querydomainN(const char *, const char *, 247 struct res_target *, res_state); 248 249static const char * const ai_errlist[] = { 250 "Success", 251 "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 252 "Temporary failure in name resolution", /* EAI_AGAIN */ 253 "Invalid value for ai_flags", /* EAI_BADFLAGS */ 254 "Non-recoverable failure in name resolution", /* EAI_FAIL */ 255 "ai_family not supported", /* EAI_FAMILY */ 256 "Memory allocation failure", /* EAI_MEMORY */ 257 "No address associated with hostname", /* EAI_NODATA */ 258 "hostname nor servname provided, or not known", /* EAI_NONAME */ 259 "servname not supported for ai_socktype", /* EAI_SERVICE */ 260 "ai_socktype not supported", /* EAI_SOCKTYPE */ 261 "System error returned in errno", /* EAI_SYSTEM */ 262 "Invalid value for hints", /* EAI_BADHINTS */ 263 "Resolved protocol is unknown", /* EAI_PROTOCOL */ 264 "Argument buffer overflow", /* EAI_OVERFLOW */ 265 "Unknown error", /* EAI_MAX */ 266}; 267 268/* XXX macros that make external reference is BAD. */ 269 270#define GET_AI(ai, afd, addr) \ 271do { \ 272 /* external reference: pai, error, and label free */ \ 273 (ai) = get_ai(pai, (afd), (addr)); \ 274 if ((ai) == NULL) { \ 275 error = EAI_MEMORY; \ 276 goto free; \ 277 } \ 278} while (/*CONSTCOND*/0) 279 280#define GET_PORT(ai, serv) \ 281do { \ 282 /* external reference: error and label free */ \ 283 error = get_port((ai), (serv), 0); \ 284 if (error != 0) \ 285 goto free; \ 286} while (/*CONSTCOND*/0) 287 288#define GET_CANONNAME(ai, str) \ 289do { \ 290 /* external reference: pai, error and label free */ \ 291 error = get_canonname(pai, (ai), (str)); \ 292 if (error != 0) \ 293 goto free; \ 294} while (/*CONSTCOND*/0) 295 296#define ERR(err) \ 297do { \ 298 /* external reference: error, and label bad */ \ 299 error = (err); \ 300 goto bad; \ 301 /*NOTREACHED*/ \ 302} while (/*CONSTCOND*/0) 303 304#define MATCH_FAMILY(x, y, w) \ 305 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \ 306 (y) == PF_UNSPEC))) 307#define MATCH(x, y, w) \ 308 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) 309 310const char * 311gai_strerror(int ecode) 312{ 313 if (ecode < 0 || ecode > EAI_MAX) 314 ecode = EAI_MAX; 315 return ai_errlist[ecode]; 316} 317 318void 319freeaddrinfo(struct addrinfo *ai) 320{ 321 struct addrinfo *next; 322 323 assert(ai != NULL); 324 325 do { 326 next = ai->ai_next; 327 if (ai->ai_canonname) 328 free(ai->ai_canonname); 329 /* no need to free(ai->ai_addr) */ 330 free(ai); 331 ai = next; 332 } while (ai); 333} 334 335static int 336str2number(const char *p) 337{ 338 char *ep; 339 unsigned long v; 340 341 assert(p != NULL); 342 343 if (*p == '\0') 344 return -1; 345 ep = NULL; 346 errno = 0; 347 v = strtoul(p, &ep, 10); 348 if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) 349 return v; 350 else 351 return -1; 352} 353 354/* 355 * Connect a UDP socket to a given unicast address. This will cause no network 356 * traffic, but will fail fast if the system has no or limited reachability to 357 * the destination (e.g., no IPv4 address, no IPv6 default route, ...). 358 */ 359static int 360_test_connect(int pf, struct sockaddr *addr, size_t addrlen) { 361 int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP); 362 if (s < 0) 363 return 0; 364 int ret; 365 do { 366 ret = connect(s, addr, addrlen); 367 } while (ret < 0 && errno == EINTR); 368 int success = (ret == 0); 369 do { 370 ret = close(s); 371 } while (ret < 0 && errno == EINTR); 372 return success; 373} 374 375/* 376 * The following functions determine whether IPv4 or IPv6 connectivity is 377 * available in order to implement AI_ADDRCONFIG. 378 * 379 * Strictly speaking, AI_ADDRCONFIG should not look at whether connectivity is 380 * available, but whether addresses of the specified family are "configured 381 * on the local system". However, bionic doesn't currently support getifaddrs, 382 * so checking for connectivity is the next best thing. 383 */ 384static int 385_have_ipv6() { 386 static const struct sockaddr_in6 sin6_test = { 387 .sin6_family = AF_INET6, 388 .sin6_addr.s6_addr = { // 2000:: 389 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 390 }; 391 sockaddr_union addr = { .in6 = sin6_test }; 392 return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6)); 393} 394 395static int 396_have_ipv4() { 397 static const struct sockaddr_in sin_test = { 398 .sin_family = AF_INET, 399 .sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8 400 }; 401 sockaddr_union addr = { .in = sin_test }; 402 return _test_connect(PF_INET, &addr.generic, sizeof(addr.in)); 403} 404 405// Returns 0 on success, else returns on error. 406static int 407android_getaddrinfo_proxy( 408 const char *hostname, const char *servname, 409 const struct addrinfo *hints, struct addrinfo **res, const char *iface) 410{ 411 int sock; 412 const int one = 1; 413 struct sockaddr_un proxy_addr; 414 FILE* proxy = NULL; 415 int success = 0; 416 417 // Clear this at start, as we use its non-NULLness later (in the 418 // error path) to decide if we have to free up any memory we 419 // allocated in the process (before failing). 420 *res = NULL; 421 422 // Bogus things we can't serialize. Don't use the proxy. These will fail - let them. 423 if ((hostname != NULL && 424 strcspn(hostname, " \n\r\t^'\"") != strlen(hostname)) || 425 (servname != NULL && 426 strcspn(servname, " \n\r\t^'\"") != strlen(servname))) { 427 return EAI_NODATA; 428 } 429 430 sock = socket(AF_UNIX, SOCK_STREAM, 0); 431 if (sock < 0) { 432 return EAI_NODATA; 433 } 434 435 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 436 memset(&proxy_addr, 0, sizeof(proxy_addr)); 437 proxy_addr.sun_family = AF_UNIX; 438 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", 439 sizeof(proxy_addr.sun_path)); 440 if (TEMP_FAILURE_RETRY(connect(sock, 441 (const struct sockaddr*) &proxy_addr, 442 sizeof(proxy_addr))) != 0) { 443 close(sock); 444 return EAI_NODATA; 445 } 446 447 // Send the request. 448 proxy = fdopen(sock, "r+"); 449 if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d %s", 450 hostname == NULL ? "^" : hostname, 451 servname == NULL ? "^" : servname, 452 hints == NULL ? -1 : hints->ai_flags, 453 hints == NULL ? -1 : hints->ai_family, 454 hints == NULL ? -1 : hints->ai_socktype, 455 hints == NULL ? -1 : hints->ai_protocol, 456 iface == NULL ? "^" : iface) < 0) { 457 goto exit; 458 } 459 // literal NULL byte at end, required by FrameworkListener 460 if (fputc(0, proxy) == EOF || 461 fflush(proxy) != 0) { 462 goto exit; 463 } 464 465 char buf[4]; 466 // read result code for gethostbyaddr 467 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) { 468 goto exit; 469 } 470 471 int result_code = (int)strtol(buf, NULL, 10); 472 // verify the code itself 473 if (result_code != DnsProxyQueryResult ) { 474 fread(buf, 1, sizeof(buf), proxy); 475 goto exit; 476 } 477 478 struct addrinfo* ai = NULL; 479 struct addrinfo** nextres = res; 480 while (1) { 481 uint32_t addrinfo_len; 482 if (fread(&addrinfo_len, sizeof(addrinfo_len), 483 1, proxy) != 1) { 484 break; 485 } 486 addrinfo_len = ntohl(addrinfo_len); 487 if (addrinfo_len == 0) { 488 success = 1; 489 break; 490 } 491 492 if (addrinfo_len < sizeof(struct addrinfo)) { 493 break; 494 } 495 struct addrinfo* ai = calloc(1, addrinfo_len + 496 sizeof(struct sockaddr_storage)); 497 if (ai == NULL) { 498 break; 499 } 500 501 if (fread(ai, addrinfo_len, 1, proxy) != 1) { 502 // Error; fall through. 503 break; 504 } 505 506 // Zero out the pointer fields we copied which aren't 507 // valid in this address space. 508 ai->ai_addr = NULL; 509 ai->ai_canonname = NULL; 510 ai->ai_next = NULL; 511 512 // struct sockaddr 513 uint32_t addr_len; 514 if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) { 515 break; 516 } 517 addr_len = ntohl(addr_len); 518 if (addr_len != 0) { 519 if (addr_len > sizeof(struct sockaddr_storage)) { 520 // Bogus; too big. 521 break; 522 } 523 struct sockaddr* addr = (struct sockaddr*)(ai + 1); 524 if (fread(addr, addr_len, 1, proxy) != 1) { 525 break; 526 } 527 ai->ai_addr = addr; 528 } 529 530 // cannonname 531 uint32_t name_len; 532 if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) { 533 break; 534 } 535 name_len = ntohl(name_len); 536 if (name_len != 0) { 537 ai->ai_canonname = (char*) malloc(name_len); 538 if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) { 539 break; 540 } 541 if (ai->ai_canonname[name_len - 1] != '\0') { 542 // The proxy should be returning this 543 // NULL-terminated. 544 break; 545 } 546 } 547 548 *nextres = ai; 549 nextres = &ai->ai_next; 550 ai = NULL; 551 } 552 553 if (ai != NULL) { 554 // Clean up partially-built addrinfo that we never ended up 555 // attaching to the response. 556 freeaddrinfo(ai); 557 } 558exit: 559 if (proxy != NULL) { 560 fclose(proxy); 561 } 562 563 if (success) { 564 return 0; 565 } 566 567 // Proxy failed; 568 // clean up memory we might've allocated. 569 if (*res) { 570 freeaddrinfo(*res); 571 *res = NULL; 572 } 573 return EAI_NODATA; 574} 575 576int 577getaddrinfo(const char *hostname, const char *servname, 578 const struct addrinfo *hints, struct addrinfo **res) 579{ 580 return android_getaddrinfoforiface(hostname, servname, hints, NULL, res); 581} 582 583int 584android_getaddrinfoforiface(const char *hostname, const char *servname, 585 const struct addrinfo *hints, const char *iface, struct addrinfo **res) 586{ 587 struct addrinfo sentinel; 588 struct addrinfo *cur; 589 int error = 0; 590 struct addrinfo ai; 591 struct addrinfo ai0; 592 struct addrinfo *pai; 593 const struct explore *ex; 594 const char* cache_mode = getenv("ANDROID_DNS_MODE"); 595 596 /* hostname is allowed to be NULL */ 597 /* servname is allowed to be NULL */ 598 /* hints is allowed to be NULL */ 599 assert(res != NULL); 600 memset(&sentinel, 0, sizeof(sentinel)); 601 cur = &sentinel; 602 pai = &ai; 603 pai->ai_flags = 0; 604 pai->ai_family = PF_UNSPEC; 605 pai->ai_socktype = ANY; 606 pai->ai_protocol = ANY; 607 pai->ai_addrlen = 0; 608 pai->ai_canonname = NULL; 609 pai->ai_addr = NULL; 610 pai->ai_next = NULL; 611 612 if (hostname == NULL && servname == NULL) 613 return EAI_NONAME; 614 if (hints) { 615 /* error check for hints */ 616 if (hints->ai_addrlen || hints->ai_canonname || 617 hints->ai_addr || hints->ai_next) 618 ERR(EAI_BADHINTS); /* xxx */ 619 if (hints->ai_flags & ~AI_MASK) 620 ERR(EAI_BADFLAGS); 621 switch (hints->ai_family) { 622 case PF_UNSPEC: 623 case PF_INET: 624#ifdef INET6 625 case PF_INET6: 626#endif 627 break; 628 default: 629 ERR(EAI_FAMILY); 630 } 631 memcpy(pai, hints, sizeof(*pai)); 632 633 /* 634 * if both socktype/protocol are specified, check if they 635 * are meaningful combination. 636 */ 637 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 638 for (ex = explore; ex->e_af >= 0; ex++) { 639 if (pai->ai_family != ex->e_af) 640 continue; 641 if (ex->e_socktype == ANY) 642 continue; 643 if (ex->e_protocol == ANY) 644 continue; 645 if (pai->ai_socktype == ex->e_socktype 646 && pai->ai_protocol != ex->e_protocol) { 647 ERR(EAI_BADHINTS); 648 } 649 } 650 } 651 } 652 653 /* 654 * check for special cases. (1) numeric servname is disallowed if 655 * socktype/protocol are left unspecified. (2) servname is disallowed 656 * for raw and other inet{,6} sockets. 657 */ 658 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 659#ifdef PF_INET6 660 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 661#endif 662 ) { 663 ai0 = *pai; /* backup *pai */ 664 665 if (pai->ai_family == PF_UNSPEC) { 666#ifdef PF_INET6 667 pai->ai_family = PF_INET6; 668#else 669 pai->ai_family = PF_INET; 670#endif 671 } 672 error = get_portmatch(pai, servname); 673 if (error) 674 ERR(error); 675 676 *pai = ai0; 677 } 678 679 ai0 = *pai; 680 681 /* NULL hostname, or numeric hostname */ 682 for (ex = explore; ex->e_af >= 0; ex++) { 683 *pai = ai0; 684 685 /* PF_UNSPEC entries are prepared for DNS queries only */ 686 if (ex->e_af == PF_UNSPEC) 687 continue; 688 689 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 690 continue; 691 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 692 continue; 693 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 694 continue; 695 696 if (pai->ai_family == PF_UNSPEC) 697 pai->ai_family = ex->e_af; 698 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 699 pai->ai_socktype = ex->e_socktype; 700 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 701 pai->ai_protocol = ex->e_protocol; 702 703 if (hostname == NULL) 704 error = explore_null(pai, servname, &cur->ai_next); 705 else 706 error = explore_numeric_scope(pai, hostname, servname, 707 &cur->ai_next); 708 709 if (error) 710 goto free; 711 712 while (cur->ai_next) 713 cur = cur->ai_next; 714 } 715 716 /* 717 * XXX 718 * If numeric representation of AF1 can be interpreted as FQDN 719 * representation of AF2, we need to think again about the code below. 720 */ 721 if (sentinel.ai_next) 722 goto good; 723 724 if (hostname == NULL) 725 ERR(EAI_NODATA); 726 if (pai->ai_flags & AI_NUMERICHOST) 727 ERR(EAI_NONAME); 728 729 /* 730 * BEGIN ANDROID CHANGES; proxying to the cache 731 */ 732 if (cache_mode == NULL || strcmp(cache_mode, "local") != 0) { 733 // we're not the proxy - pass the request to them 734 return android_getaddrinfo_proxy(hostname, servname, hints, res, iface); 735 } 736 737 /* 738 * hostname as alphabetical name. 739 * we would like to prefer AF_INET6 than AF_INET, so we'll make a 740 * outer loop by AFs. 741 */ 742 for (ex = explore; ex->e_af >= 0; ex++) { 743 *pai = ai0; 744 745 /* require exact match for family field */ 746 if (pai->ai_family != ex->e_af) 747 continue; 748 749 if (!MATCH(pai->ai_socktype, ex->e_socktype, 750 WILD_SOCKTYPE(ex))) { 751 continue; 752 } 753 if (!MATCH(pai->ai_protocol, ex->e_protocol, 754 WILD_PROTOCOL(ex))) { 755 continue; 756 } 757 758 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 759 pai->ai_socktype = ex->e_socktype; 760 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 761 pai->ai_protocol = ex->e_protocol; 762 763 error = explore_fqdn(pai, hostname, servname, 764 &cur->ai_next, iface); 765 766 while (cur && cur->ai_next) 767 cur = cur->ai_next; 768 } 769 770 /* XXX */ 771 if (sentinel.ai_next) 772 error = 0; 773 774 if (error) 775 goto free; 776 if (error == 0) { 777 if (sentinel.ai_next) { 778 good: 779 *res = sentinel.ai_next; 780 return SUCCESS; 781 } else 782 error = EAI_FAIL; 783 } 784 free: 785 bad: 786 if (sentinel.ai_next) 787 freeaddrinfo(sentinel.ai_next); 788 *res = NULL; 789 return error; 790} 791 792/* 793 * FQDN hostname, DNS lookup 794 */ 795static int 796explore_fqdn(const struct addrinfo *pai, const char *hostname, 797 const char *servname, struct addrinfo **res, const char *iface) 798{ 799 struct addrinfo *result; 800 struct addrinfo *cur; 801 int error = 0; 802 static const ns_dtab dtab[] = { 803 NS_FILES_CB(_files_getaddrinfo, NULL) 804 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ 805 NS_NIS_CB(_yp_getaddrinfo, NULL) 806 { 0, 0, 0 } 807 }; 808 809 assert(pai != NULL); 810 /* hostname may be NULL */ 811 /* servname may be NULL */ 812 assert(res != NULL); 813 814 result = NULL; 815 816 /* 817 * if the servname does not match socktype/protocol, ignore it. 818 */ 819 if (get_portmatch(pai, servname) != 0) 820 return 0; 821 822 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", 823 default_dns_files, hostname, pai, iface)) { 824 case NS_TRYAGAIN: 825 error = EAI_AGAIN; 826 goto free; 827 case NS_UNAVAIL: 828 error = EAI_FAIL; 829 goto free; 830 case NS_NOTFOUND: 831 error = EAI_NODATA; 832 goto free; 833 case NS_SUCCESS: 834 error = 0; 835 for (cur = result; cur; cur = cur->ai_next) { 836 GET_PORT(cur, servname); 837 /* canonname should be filled already */ 838 } 839 break; 840 } 841 842 *res = result; 843 844 return 0; 845 846free: 847 if (result) 848 freeaddrinfo(result); 849 return error; 850} 851 852/* 853 * hostname == NULL. 854 * passive socket -> anyaddr (0.0.0.0 or ::) 855 * non-passive socket -> localhost (127.0.0.1 or ::1) 856 */ 857static int 858explore_null(const struct addrinfo *pai, const char *servname, 859 struct addrinfo **res) 860{ 861 int s; 862 const struct afd *afd; 863 struct addrinfo *cur; 864 struct addrinfo sentinel; 865 int error; 866 867 assert(pai != NULL); 868 /* servname may be NULL */ 869 assert(res != NULL); 870 871 *res = NULL; 872 sentinel.ai_next = NULL; 873 cur = &sentinel; 874 875 /* 876 * filter out AFs that are not supported by the kernel 877 * XXX errno? 878 */ 879 s = socket(pai->ai_family, SOCK_DGRAM, 0); 880 if (s < 0) { 881 if (errno != EMFILE) 882 return 0; 883 } else 884 close(s); 885 886 /* 887 * if the servname does not match socktype/protocol, ignore it. 888 */ 889 if (get_portmatch(pai, servname) != 0) 890 return 0; 891 892 afd = find_afd(pai->ai_family); 893 if (afd == NULL) 894 return 0; 895 896 if (pai->ai_flags & AI_PASSIVE) { 897 GET_AI(cur->ai_next, afd, afd->a_addrany); 898 /* xxx meaningless? 899 * GET_CANONNAME(cur->ai_next, "anyaddr"); 900 */ 901 GET_PORT(cur->ai_next, servname); 902 } else { 903 GET_AI(cur->ai_next, afd, afd->a_loopback); 904 /* xxx meaningless? 905 * GET_CANONNAME(cur->ai_next, "localhost"); 906 */ 907 GET_PORT(cur->ai_next, servname); 908 } 909 cur = cur->ai_next; 910 911 *res = sentinel.ai_next; 912 return 0; 913 914free: 915 if (sentinel.ai_next) 916 freeaddrinfo(sentinel.ai_next); 917 return error; 918} 919 920/* 921 * numeric hostname 922 */ 923static int 924explore_numeric(const struct addrinfo *pai, const char *hostname, 925 const char *servname, struct addrinfo **res, const char *canonname) 926{ 927 const struct afd *afd; 928 struct addrinfo *cur; 929 struct addrinfo sentinel; 930 int error; 931 char pton[PTON_MAX]; 932 933 assert(pai != NULL); 934 /* hostname may be NULL */ 935 /* servname may be NULL */ 936 assert(res != NULL); 937 938 *res = NULL; 939 sentinel.ai_next = NULL; 940 cur = &sentinel; 941 942 /* 943 * if the servname does not match socktype/protocol, ignore it. 944 */ 945 if (get_portmatch(pai, servname) != 0) 946 return 0; 947 948 afd = find_afd(pai->ai_family); 949 if (afd == NULL) 950 return 0; 951 952 switch (afd->a_af) { 953#if 0 /*X/Open spec*/ 954 case AF_INET: 955 if (inet_aton(hostname, (struct in_addr *)pton) == 1) { 956 if (pai->ai_family == afd->a_af || 957 pai->ai_family == PF_UNSPEC /*?*/) { 958 GET_AI(cur->ai_next, afd, pton); 959 GET_PORT(cur->ai_next, servname); 960 if ((pai->ai_flags & AI_CANONNAME)) { 961 /* 962 * Set the numeric address itself as 963 * the canonical name, based on a 964 * clarification in rfc2553bis-03. 965 */ 966 GET_CANONNAME(cur->ai_next, canonname); 967 } 968 while (cur && cur->ai_next) 969 cur = cur->ai_next; 970 } else 971 ERR(EAI_FAMILY); /*xxx*/ 972 } 973 break; 974#endif 975 default: 976 if (inet_pton(afd->a_af, hostname, pton) == 1) { 977 if (pai->ai_family == afd->a_af || 978 pai->ai_family == PF_UNSPEC /*?*/) { 979 GET_AI(cur->ai_next, afd, pton); 980 GET_PORT(cur->ai_next, servname); 981 if ((pai->ai_flags & AI_CANONNAME)) { 982 /* 983 * Set the numeric address itself as 984 * the canonical name, based on a 985 * clarification in rfc2553bis-03. 986 */ 987 GET_CANONNAME(cur->ai_next, canonname); 988 } 989 while (cur->ai_next) 990 cur = cur->ai_next; 991 } else 992 ERR(EAI_FAMILY); /*xxx*/ 993 } 994 break; 995 } 996 997 *res = sentinel.ai_next; 998 return 0; 999 1000free: 1001bad: 1002 if (sentinel.ai_next) 1003 freeaddrinfo(sentinel.ai_next); 1004 return error; 1005} 1006 1007/* 1008 * numeric hostname with scope 1009 */ 1010static int 1011explore_numeric_scope(const struct addrinfo *pai, const char *hostname, 1012 const char *servname, struct addrinfo **res) 1013{ 1014#if !defined(SCOPE_DELIMITER) || !defined(INET6) 1015 return explore_numeric(pai, hostname, servname, res, hostname); 1016#else 1017 const struct afd *afd; 1018 struct addrinfo *cur; 1019 int error; 1020 char *cp, *hostname2 = NULL, *scope, *addr; 1021 struct sockaddr_in6 *sin6; 1022 1023 assert(pai != NULL); 1024 /* hostname may be NULL */ 1025 /* servname may be NULL */ 1026 assert(res != NULL); 1027 1028 /* 1029 * if the servname does not match socktype/protocol, ignore it. 1030 */ 1031 if (get_portmatch(pai, servname) != 0) 1032 return 0; 1033 1034 afd = find_afd(pai->ai_family); 1035 if (afd == NULL) 1036 return 0; 1037 1038 if (!afd->a_scoped) 1039 return explore_numeric(pai, hostname, servname, res, hostname); 1040 1041 cp = strchr(hostname, SCOPE_DELIMITER); 1042 if (cp == NULL) 1043 return explore_numeric(pai, hostname, servname, res, hostname); 1044 1045 /* 1046 * Handle special case of <scoped_address><delimiter><scope id> 1047 */ 1048 hostname2 = strdup(hostname); 1049 if (hostname2 == NULL) 1050 return EAI_MEMORY; 1051 /* terminate at the delimiter */ 1052 hostname2[cp - hostname] = '\0'; 1053 addr = hostname2; 1054 scope = cp + 1; 1055 1056 error = explore_numeric(pai, addr, servname, res, hostname); 1057 if (error == 0) { 1058 u_int32_t scopeid; 1059 1060 for (cur = *res; cur; cur = cur->ai_next) { 1061 if (cur->ai_family != AF_INET6) 1062 continue; 1063 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 1064 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { 1065 free(hostname2); 1066 return(EAI_NODATA); /* XXX: is return OK? */ 1067 } 1068 sin6->sin6_scope_id = scopeid; 1069 } 1070 } 1071 1072 free(hostname2); 1073 1074 return error; 1075#endif 1076} 1077 1078static int 1079get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) 1080{ 1081 1082 assert(pai != NULL); 1083 assert(ai != NULL); 1084 assert(str != NULL); 1085 1086 if ((pai->ai_flags & AI_CANONNAME) != 0) { 1087 ai->ai_canonname = strdup(str); 1088 if (ai->ai_canonname == NULL) 1089 return EAI_MEMORY; 1090 } 1091 return 0; 1092} 1093 1094static struct addrinfo * 1095get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 1096{ 1097 char *p; 1098 struct addrinfo *ai; 1099 1100 assert(pai != NULL); 1101 assert(afd != NULL); 1102 assert(addr != NULL); 1103 1104 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 1105 + (afd->a_socklen)); 1106 if (ai == NULL) 1107 return NULL; 1108 1109 memcpy(ai, pai, sizeof(struct addrinfo)); 1110 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); 1111 memset(ai->ai_addr, 0, (size_t)afd->a_socklen); 1112 1113#ifdef HAVE_SA_LEN 1114 ai->ai_addr->sa_len = afd->a_socklen; 1115#endif 1116 1117 ai->ai_addrlen = afd->a_socklen; 1118#if defined (__alpha__) || (defined(__i386__) && defined(_LP64)) || defined(__sparc64__) 1119 ai->__ai_pad0 = 0; 1120#endif 1121 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 1122 p = (char *)(void *)(ai->ai_addr); 1123 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 1124 return ai; 1125} 1126 1127static int 1128get_portmatch(const struct addrinfo *ai, const char *servname) 1129{ 1130 1131 assert(ai != NULL); 1132 /* servname may be NULL */ 1133 1134 return get_port(ai, servname, 1); 1135} 1136 1137static int 1138get_port(const struct addrinfo *ai, const char *servname, int matchonly) 1139{ 1140 const char *proto; 1141 struct servent *sp; 1142 int port; 1143 int allownumeric; 1144 1145 assert(ai != NULL); 1146 /* servname may be NULL */ 1147 1148 if (servname == NULL) 1149 return 0; 1150 switch (ai->ai_family) { 1151 case AF_INET: 1152#ifdef AF_INET6 1153 case AF_INET6: 1154#endif 1155 break; 1156 default: 1157 return 0; 1158 } 1159 1160 switch (ai->ai_socktype) { 1161 case SOCK_RAW: 1162 return EAI_SERVICE; 1163 case SOCK_DGRAM: 1164 case SOCK_STREAM: 1165 allownumeric = 1; 1166 break; 1167 case ANY: 1168#if 1 /* ANDROID-SPECIFIC CHANGE TO MATCH GLIBC */ 1169 allownumeric = 1; 1170#else 1171 allownumeric = 0; 1172#endif 1173 break; 1174 default: 1175 return EAI_SOCKTYPE; 1176 } 1177 1178 port = str2number(servname); 1179 if (port >= 0) { 1180 if (!allownumeric) 1181 return EAI_SERVICE; 1182 if (port < 0 || port > 65535) 1183 return EAI_SERVICE; 1184 port = htons(port); 1185 } else { 1186 if (ai->ai_flags & AI_NUMERICSERV) 1187 return EAI_NONAME; 1188 1189 switch (ai->ai_socktype) { 1190 case SOCK_DGRAM: 1191 proto = "udp"; 1192 break; 1193 case SOCK_STREAM: 1194 proto = "tcp"; 1195 break; 1196 default: 1197 proto = NULL; 1198 break; 1199 } 1200 1201 if ((sp = getservbyname(servname, proto)) == NULL) 1202 return EAI_SERVICE; 1203 port = sp->s_port; 1204 } 1205 1206 if (!matchonly) { 1207 switch (ai->ai_family) { 1208 case AF_INET: 1209 ((struct sockaddr_in *)(void *) 1210 ai->ai_addr)->sin_port = port; 1211 break; 1212#ifdef INET6 1213 case AF_INET6: 1214 ((struct sockaddr_in6 *)(void *) 1215 ai->ai_addr)->sin6_port = port; 1216 break; 1217#endif 1218 } 1219 } 1220 1221 return 0; 1222} 1223 1224static const struct afd * 1225find_afd(int af) 1226{ 1227 const struct afd *afd; 1228 1229 if (af == PF_UNSPEC) 1230 return NULL; 1231 for (afd = afdl; afd->a_af; afd++) { 1232 if (afd->a_af == af) 1233 return afd; 1234 } 1235 return NULL; 1236} 1237 1238#ifdef INET6 1239/* convert a string to a scope identifier. XXX: IPv6 specific */ 1240static int 1241ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 1242{ 1243 u_long lscopeid; 1244 struct in6_addr *a6; 1245 char *ep; 1246 1247 assert(scope != NULL); 1248 assert(sin6 != NULL); 1249 assert(scopeid != NULL); 1250 1251 a6 = &sin6->sin6_addr; 1252 1253 /* empty scopeid portion is invalid */ 1254 if (*scope == '\0') 1255 return -1; 1256 1257 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 1258 /* 1259 * We currently assume a one-to-one mapping between links 1260 * and interfaces, so we simply use interface indices for 1261 * like-local scopes. 1262 */ 1263 *scopeid = if_nametoindex(scope); 1264 if (*scopeid == 0) 1265 goto trynumeric; 1266 return 0; 1267 } 1268 1269 /* still unclear about literal, allow numeric only - placeholder */ 1270 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 1271 goto trynumeric; 1272 if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 1273 goto trynumeric; 1274 else 1275 goto trynumeric; /* global */ 1276 1277 /* try to convert to a numeric id as a last resort */ 1278 trynumeric: 1279 errno = 0; 1280 lscopeid = strtoul(scope, &ep, 10); 1281 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 1282 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 1283 return 0; 1284 else 1285 return -1; 1286} 1287#endif 1288 1289/* code duplicate with gethnamaddr.c */ 1290 1291static const char AskedForGot[] = 1292 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 1293 1294static struct addrinfo * 1295getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 1296 const struct addrinfo *pai) 1297{ 1298 struct addrinfo sentinel, *cur; 1299 struct addrinfo ai; 1300 const struct afd *afd; 1301 char *canonname; 1302 const HEADER *hp; 1303 const u_char *cp; 1304 int n; 1305 const u_char *eom; 1306 char *bp, *ep; 1307 int type, class, ancount, qdcount; 1308 int haveanswer, had_error; 1309 char tbuf[MAXDNAME]; 1310 int (*name_ok) (const char *); 1311 char hostbuf[8*1024]; 1312 1313 assert(answer != NULL); 1314 assert(qname != NULL); 1315 assert(pai != NULL); 1316 1317 memset(&sentinel, 0, sizeof(sentinel)); 1318 cur = &sentinel; 1319 1320 canonname = NULL; 1321 eom = answer->buf + anslen; 1322 switch (qtype) { 1323 case T_A: 1324 case T_AAAA: 1325 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 1326 name_ok = res_hnok; 1327 break; 1328 default: 1329 return NULL; /* XXX should be abort(); */ 1330 } 1331 /* 1332 * find first satisfactory answer 1333 */ 1334 hp = &answer->hdr; 1335 ancount = ntohs(hp->ancount); 1336 qdcount = ntohs(hp->qdcount); 1337 bp = hostbuf; 1338 ep = hostbuf + sizeof hostbuf; 1339 cp = answer->buf + HFIXEDSZ; 1340 if (qdcount != 1) { 1341 h_errno = NO_RECOVERY; 1342 return (NULL); 1343 } 1344 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 1345 if ((n < 0) || !(*name_ok)(bp)) { 1346 h_errno = NO_RECOVERY; 1347 return (NULL); 1348 } 1349 cp += n + QFIXEDSZ; 1350 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 1351 /* res_send() has already verified that the query name is the 1352 * same as the one we sent; this just gets the expanded name 1353 * (i.e., with the succeeding search-domain tacked on). 1354 */ 1355 n = strlen(bp) + 1; /* for the \0 */ 1356 if (n >= MAXHOSTNAMELEN) { 1357 h_errno = NO_RECOVERY; 1358 return (NULL); 1359 } 1360 canonname = bp; 1361 bp += n; 1362 /* The qname can be abbreviated, but h_name is now absolute. */ 1363 qname = canonname; 1364 } 1365 haveanswer = 0; 1366 had_error = 0; 1367 while (ancount-- > 0 && cp < eom && !had_error) { 1368 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 1369 if ((n < 0) || !(*name_ok)(bp)) { 1370 had_error++; 1371 continue; 1372 } 1373 cp += n; /* name */ 1374 type = _getshort(cp); 1375 cp += INT16SZ; /* type */ 1376 class = _getshort(cp); 1377 cp += INT16SZ + INT32SZ; /* class, TTL */ 1378 n = _getshort(cp); 1379 cp += INT16SZ; /* len */ 1380 if (class != C_IN) { 1381 /* XXX - debug? syslog? */ 1382 cp += n; 1383 continue; /* XXX - had_error++ ? */ 1384 } 1385 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 1386 type == T_CNAME) { 1387 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 1388 if ((n < 0) || !(*name_ok)(tbuf)) { 1389 had_error++; 1390 continue; 1391 } 1392 cp += n; 1393 /* Get canonical name. */ 1394 n = strlen(tbuf) + 1; /* for the \0 */ 1395 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 1396 had_error++; 1397 continue; 1398 } 1399 strlcpy(bp, tbuf, (size_t)(ep - bp)); 1400 canonname = bp; 1401 bp += n; 1402 continue; 1403 } 1404 if (qtype == T_ANY) { 1405 if (!(type == T_A || type == T_AAAA)) { 1406 cp += n; 1407 continue; 1408 } 1409 } else if (type != qtype) { 1410 if (type != T_KEY && type != T_SIG) 1411 syslog(LOG_NOTICE|LOG_AUTH, 1412 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 1413 qname, p_class(C_IN), p_type(qtype), 1414 p_type(type)); 1415 cp += n; 1416 continue; /* XXX - had_error++ ? */ 1417 } 1418 switch (type) { 1419 case T_A: 1420 case T_AAAA: 1421 if (strcasecmp(canonname, bp) != 0) { 1422 syslog(LOG_NOTICE|LOG_AUTH, 1423 AskedForGot, canonname, bp); 1424 cp += n; 1425 continue; /* XXX - had_error++ ? */ 1426 } 1427 if (type == T_A && n != INADDRSZ) { 1428 cp += n; 1429 continue; 1430 } 1431 if (type == T_AAAA && n != IN6ADDRSZ) { 1432 cp += n; 1433 continue; 1434 } 1435 if (type == T_AAAA) { 1436 struct in6_addr in6; 1437 memcpy(&in6, cp, IN6ADDRSZ); 1438 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 1439 cp += n; 1440 continue; 1441 } 1442 } 1443 if (!haveanswer) { 1444 int nn; 1445 1446 canonname = bp; 1447 nn = strlen(bp) + 1; /* for the \0 */ 1448 bp += nn; 1449 } 1450 1451 /* don't overwrite pai */ 1452 ai = *pai; 1453 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 1454 afd = find_afd(ai.ai_family); 1455 if (afd == NULL) { 1456 cp += n; 1457 continue; 1458 } 1459 cur->ai_next = get_ai(&ai, afd, (const char *)cp); 1460 if (cur->ai_next == NULL) 1461 had_error++; 1462 while (cur && cur->ai_next) 1463 cur = cur->ai_next; 1464 cp += n; 1465 break; 1466 default: 1467 abort(); 1468 } 1469 if (!had_error) 1470 haveanswer++; 1471 } 1472 if (haveanswer) { 1473 if (!canonname) 1474 (void)get_canonname(pai, sentinel.ai_next, qname); 1475 else 1476 (void)get_canonname(pai, sentinel.ai_next, canonname); 1477 h_errno = NETDB_SUCCESS; 1478 return sentinel.ai_next; 1479 } 1480 1481 h_errno = NO_RECOVERY; 1482 return NULL; 1483} 1484 1485struct addrinfo_sort_elem { 1486 struct addrinfo *ai; 1487 int has_src_addr; 1488 sockaddr_union src_addr; 1489 int original_order; 1490}; 1491 1492/*ARGSUSED*/ 1493static int 1494_get_scope(const struct sockaddr *addr) 1495{ 1496 if (addr->sa_family == AF_INET6) { 1497 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 1498 if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) { 1499 return IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr); 1500 } else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) || 1501 IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) { 1502 /* 1503 * RFC 4291 section 2.5.3 says loopback is to be treated as having 1504 * link-local scope. 1505 */ 1506 return IPV6_ADDR_SCOPE_LINKLOCAL; 1507 } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) { 1508 return IPV6_ADDR_SCOPE_SITELOCAL; 1509 } else { 1510 return IPV6_ADDR_SCOPE_GLOBAL; 1511 } 1512 } else if (addr->sa_family == AF_INET) { 1513 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; 1514 unsigned long int na = ntohl(addr4->sin_addr.s_addr); 1515 1516 if (IN_LOOPBACK(na) || /* 127.0.0.0/8 */ 1517 (na & 0xffff0000) == 0xa9fe0000) { /* 169.254.0.0/16 */ 1518 return IPV6_ADDR_SCOPE_LINKLOCAL; 1519 } else { 1520 /* 1521 * RFC 6724 section 3.2. Other IPv4 addresses, including private addresses 1522 * and shared addresses (100.64.0.0/10), are assigned global scope. 1523 */ 1524 return IPV6_ADDR_SCOPE_GLOBAL; 1525 } 1526 } else { 1527 /* 1528 * This should never happen. 1529 * Return a scope with low priority as a last resort. 1530 */ 1531 return IPV6_ADDR_SCOPE_NODELOCAL; 1532 } 1533} 1534 1535/* These macros are modelled after the ones in <netinet/in6.h>. */ 1536 1537/* RFC 4380, section 2.6 */ 1538#define IN6_IS_ADDR_TEREDO(a) \ 1539 ((*(const uint32_t *)(const void *)(&(a)->s6_addr[0]) == ntohl(0x20010000))) 1540 1541/* RFC 3056, section 2. */ 1542#define IN6_IS_ADDR_6TO4(a) \ 1543 (((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02)) 1544 1545/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */ 1546#define IN6_IS_ADDR_6BONE(a) \ 1547 (((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe)) 1548 1549/* 1550 * Get the label for a given IPv4/IPv6 address. 1551 * RFC 6724, section 2.1. 1552 */ 1553 1554/*ARGSUSED*/ 1555static int 1556_get_label(const struct sockaddr *addr) 1557{ 1558 if (addr->sa_family == AF_INET) { 1559 return 4; 1560 } else if (addr->sa_family == AF_INET6) { 1561 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr; 1562 if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { 1563 return 0; 1564 } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { 1565 return 4; 1566 } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) { 1567 return 2; 1568 } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) { 1569 return 5; 1570 } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) { 1571 return 13; 1572 } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) { 1573 return 3; 1574 } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) { 1575 return 11; 1576 } else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) { 1577 return 12; 1578 } else { 1579 /* All other IPv6 addresses, including global unicast addresses. */ 1580 return 1; 1581 } 1582 } else { 1583 /* 1584 * This should never happen. 1585 * Return a semi-random label as a last resort. 1586 */ 1587 return 1; 1588 } 1589} 1590 1591/* 1592 * Get the precedence for a given IPv4/IPv6 address. 1593 * RFC 6724, section 2.1. 1594 */ 1595 1596/*ARGSUSED*/ 1597static int 1598_get_precedence(const struct sockaddr *addr) 1599{ 1600 if (addr->sa_family == AF_INET) { 1601 return 35; 1602 } else if (addr->sa_family == AF_INET6) { 1603 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 1604 if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { 1605 return 50; 1606 } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { 1607 return 35; 1608 } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) { 1609 return 30; 1610 } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) { 1611 return 5; 1612 } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) { 1613 return 3; 1614 } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) || 1615 IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) || 1616 IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) { 1617 return 1; 1618 } else { 1619 /* All other IPv6 addresses, including global unicast addresses. */ 1620 return 40; 1621 } 1622 } else { 1623 return 1; 1624 } 1625} 1626 1627/* 1628 * Find number of matching initial bits between the two addresses a1 and a2. 1629 */ 1630 1631/*ARGSUSED*/ 1632static int 1633_common_prefix_len(const struct in6_addr *a1, const struct in6_addr *a2) 1634{ 1635 const char *p1 = (const char *)a1; 1636 const char *p2 = (const char *)a2; 1637 unsigned i; 1638 1639 for (i = 0; i < sizeof(*a1); ++i) { 1640 int x, j; 1641 1642 if (p1[i] == p2[i]) { 1643 continue; 1644 } 1645 x = p1[i] ^ p2[i]; 1646 for (j = 0; j < CHAR_BIT; ++j) { 1647 if (x & (1 << (CHAR_BIT - 1))) { 1648 return i * CHAR_BIT + j; 1649 } 1650 x <<= 1; 1651 } 1652 } 1653 return sizeof(*a1) * CHAR_BIT; 1654} 1655 1656/* 1657 * Compare two source/destination address pairs. 1658 * RFC 6724, section 6. 1659 */ 1660 1661/*ARGSUSED*/ 1662static int 1663_rfc6724_compare(const void *ptr1, const void* ptr2) 1664{ 1665 const struct addrinfo_sort_elem *a1 = (const struct addrinfo_sort_elem *)ptr1; 1666 const struct addrinfo_sort_elem *a2 = (const struct addrinfo_sort_elem *)ptr2; 1667 int scope_src1, scope_dst1, scope_match1; 1668 int scope_src2, scope_dst2, scope_match2; 1669 int label_src1, label_dst1, label_match1; 1670 int label_src2, label_dst2, label_match2; 1671 int precedence1, precedence2; 1672 int prefixlen1, prefixlen2; 1673 1674 /* Rule 1: Avoid unusable destinations. */ 1675 if (a1->has_src_addr != a2->has_src_addr) { 1676 return a2->has_src_addr - a1->has_src_addr; 1677 } 1678 1679 /* Rule 2: Prefer matching scope. */ 1680 scope_src1 = _get_scope(&a1->src_addr.generic); 1681 scope_dst1 = _get_scope(a1->ai->ai_addr); 1682 scope_match1 = (scope_src1 == scope_dst1); 1683 1684 scope_src2 = _get_scope(&a2->src_addr.generic); 1685 scope_dst2 = _get_scope(a2->ai->ai_addr); 1686 scope_match2 = (scope_src2 == scope_dst2); 1687 1688 if (scope_match1 != scope_match2) { 1689 return scope_match2 - scope_match1; 1690 } 1691 1692 /* 1693 * Rule 3: Avoid deprecated addresses. 1694 * TODO(sesse): We don't currently have a good way of finding this. 1695 */ 1696 1697 /* 1698 * Rule 4: Prefer home addresses. 1699 * TODO(sesse): We don't currently have a good way of finding this. 1700 */ 1701 1702 /* Rule 5: Prefer matching label. */ 1703 label_src1 = _get_label(&a1->src_addr.generic); 1704 label_dst1 = _get_label(a1->ai->ai_addr); 1705 label_match1 = (label_src1 == label_dst1); 1706 1707 label_src2 = _get_label(&a2->src_addr.generic); 1708 label_dst2 = _get_label(a2->ai->ai_addr); 1709 label_match2 = (label_src2 == label_dst2); 1710 1711 if (label_match1 != label_match2) { 1712 return label_match2 - label_match1; 1713 } 1714 1715 /* Rule 6: Prefer higher precedence. */ 1716 precedence1 = _get_precedence(a1->ai->ai_addr); 1717 precedence2 = _get_precedence(a2->ai->ai_addr); 1718 if (precedence1 != precedence2) { 1719 return precedence2 - precedence1; 1720 } 1721 1722 /* 1723 * Rule 7: Prefer native transport. 1724 * TODO(sesse): We don't currently have a good way of finding this. 1725 */ 1726 1727 /* Rule 8: Prefer smaller scope. */ 1728 if (scope_dst1 != scope_dst2) { 1729 return scope_dst1 - scope_dst2; 1730 } 1731 1732 /* 1733 * Rule 9: Use longest matching prefix. 1734 * We implement this for IPv6 only, as the rules in RFC 6724 don't seem 1735 * to work very well directly applied to IPv4. (glibc uses information from 1736 * the routing table for a custom IPv4 implementation here.) 1737 */ 1738 if (a1->has_src_addr && a1->ai->ai_addr->sa_family == AF_INET6 && 1739 a2->has_src_addr && a2->ai->ai_addr->sa_family == AF_INET6) { 1740 const struct sockaddr_in6 *a1_src = &a1->src_addr.in6; 1741 const struct sockaddr_in6 *a1_dst = (const struct sockaddr_in6 *)a1->ai->ai_addr; 1742 const struct sockaddr_in6 *a2_src = &a2->src_addr.in6; 1743 const struct sockaddr_in6 *a2_dst = (const struct sockaddr_in6 *)a2->ai->ai_addr; 1744 prefixlen1 = _common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr); 1745 prefixlen2 = _common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr); 1746 if (prefixlen1 != prefixlen2) { 1747 return prefixlen2 - prefixlen1; 1748 } 1749 } 1750 1751 /* 1752 * Rule 10: Leave the order unchanged. 1753 * We need this since qsort() is not necessarily stable. 1754 */ 1755 return a1->original_order - a2->original_order; 1756} 1757 1758/* 1759 * Find the source address that will be used if trying to connect to the given 1760 * address. src_addr must be large enough to hold a struct sockaddr_in6. 1761 * 1762 * Returns 1 if a source address was found, 0 if the address is unreachable, 1763 * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are 1764 * undefined. 1765 */ 1766 1767/*ARGSUSED*/ 1768static int 1769_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr) 1770{ 1771 int sock; 1772 int ret; 1773 socklen_t len; 1774 1775 switch (addr->sa_family) { 1776 case AF_INET: 1777 len = sizeof(struct sockaddr_in); 1778 break; 1779 case AF_INET6: 1780 len = sizeof(struct sockaddr_in6); 1781 break; 1782 default: 1783 /* No known usable source address for non-INET families. */ 1784 return 0; 1785 } 1786 1787 sock = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); 1788 if (sock == -1) { 1789 if (errno == EAFNOSUPPORT) { 1790 return 0; 1791 } else { 1792 return -1; 1793 } 1794 } 1795 1796 do { 1797 ret = connect(sock, addr, len); 1798 } while (ret == -1 && errno == EINTR); 1799 1800 if (ret == -1) { 1801 close(sock); 1802 return 0; 1803 } 1804 1805 if (getsockname(sock, src_addr, &len) == -1) { 1806 close(sock); 1807 return -1; 1808 } 1809 close(sock); 1810 return 1; 1811} 1812 1813/* 1814 * Sort the linked list starting at sentinel->ai_next in RFC6724 order. 1815 * Will leave the list unchanged if an error occurs. 1816 */ 1817 1818/*ARGSUSED*/ 1819static void 1820_rfc6724_sort(struct addrinfo *list_sentinel) 1821{ 1822 struct addrinfo *cur; 1823 int nelem = 0, i; 1824 struct addrinfo_sort_elem *elems; 1825 1826 cur = list_sentinel->ai_next; 1827 while (cur) { 1828 ++nelem; 1829 cur = cur->ai_next; 1830 } 1831 1832 elems = (struct addrinfo_sort_elem *)malloc(nelem * sizeof(struct addrinfo_sort_elem)); 1833 if (elems == NULL) { 1834 goto error; 1835 } 1836 1837 /* 1838 * Convert the linked list to an array that also contains the candidate 1839 * source address for each destination address. 1840 */ 1841 for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) { 1842 int has_src_addr; 1843 assert(cur != NULL); 1844 elems[i].ai = cur; 1845 elems[i].original_order = i; 1846 1847 has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic); 1848 if (has_src_addr == -1) { 1849 goto error; 1850 } 1851 elems[i].has_src_addr = has_src_addr; 1852 } 1853 1854 /* Sort the addresses, and rearrange the linked list so it matches the sorted order. */ 1855 qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), _rfc6724_compare); 1856 1857 list_sentinel->ai_next = elems[0].ai; 1858 for (i = 0; i < nelem - 1; ++i) { 1859 elems[i].ai->ai_next = elems[i + 1].ai; 1860 } 1861 elems[nelem - 1].ai->ai_next = NULL; 1862 1863error: 1864 free(elems); 1865} 1866 1867static int _using_alt_dns() 1868{ 1869 char propname[PROP_NAME_MAX]; 1870 char propvalue[PROP_VALUE_MAX]; 1871 1872 propvalue[0] = 0; 1873 snprintf(propname, sizeof(propname), "net.dns1.%d", getpid()); 1874 if (__system_property_get(propname, propvalue) > 0 ) { 1875 return 1; 1876 } 1877 return 0; 1878} 1879 1880/*ARGSUSED*/ 1881static int 1882_dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 1883{ 1884 struct addrinfo *ai; 1885 querybuf *buf, *buf2; 1886 const char *name; 1887 const struct addrinfo *pai; 1888 struct addrinfo sentinel, *cur; 1889 struct res_target q, q2; 1890 res_state res; 1891 const char* iface; 1892 1893 name = va_arg(ap, char *); 1894 pai = va_arg(ap, const struct addrinfo *); 1895 iface = va_arg(ap, char *); 1896 //fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name); 1897 1898 memset(&q, 0, sizeof(q)); 1899 memset(&q2, 0, sizeof(q2)); 1900 memset(&sentinel, 0, sizeof(sentinel)); 1901 cur = &sentinel; 1902 1903 buf = malloc(sizeof(*buf)); 1904 if (buf == NULL) { 1905 h_errno = NETDB_INTERNAL; 1906 return NS_NOTFOUND; 1907 } 1908 buf2 = malloc(sizeof(*buf2)); 1909 if (buf2 == NULL) { 1910 free(buf); 1911 h_errno = NETDB_INTERNAL; 1912 return NS_NOTFOUND; 1913 } 1914 1915 switch (pai->ai_family) { 1916 case AF_UNSPEC: 1917 /* prefer IPv6 */ 1918 q.name = name; 1919 q.qclass = C_IN; 1920 q.answer = buf->buf; 1921 q.anslen = sizeof(buf->buf); 1922 int query_ipv6 = 1, query_ipv4 = 1; 1923 if (pai->ai_flags & AI_ADDRCONFIG) { 1924 // Only implement AI_ADDRCONFIG if the application is not 1925 // using its own DNS servers, since our implementation 1926 // only works on the default connection. 1927 if (!_using_alt_dns()) { 1928 query_ipv6 = _have_ipv6(); 1929 query_ipv4 = _have_ipv4(); 1930 } 1931 } 1932 if (query_ipv6) { 1933 q.qtype = T_AAAA; 1934 if (query_ipv4) { 1935 q.next = &q2; 1936 q2.name = name; 1937 q2.qclass = C_IN; 1938 q2.qtype = T_A; 1939 q2.answer = buf2->buf; 1940 q2.anslen = sizeof(buf2->buf); 1941 } 1942 } else if (query_ipv4) { 1943 q.qtype = T_A; 1944 } else { 1945 free(buf); 1946 free(buf2); 1947 return NS_NOTFOUND; 1948 } 1949 break; 1950 case AF_INET: 1951 q.name = name; 1952 q.qclass = C_IN; 1953 q.qtype = T_A; 1954 q.answer = buf->buf; 1955 q.anslen = sizeof(buf->buf); 1956 break; 1957 case AF_INET6: 1958 q.name = name; 1959 q.qclass = C_IN; 1960 q.qtype = T_AAAA; 1961 q.answer = buf->buf; 1962 q.anslen = sizeof(buf->buf); 1963 break; 1964 default: 1965 free(buf); 1966 free(buf2); 1967 return NS_UNAVAIL; 1968 } 1969 1970 res = __res_get_state(); 1971 if (res == NULL) { 1972 free(buf); 1973 free(buf2); 1974 return NS_NOTFOUND; 1975 } 1976 1977 /* this just sets our iface val in the thread private data so we don't have to 1978 * modify the api's all the way down to res_send.c's res_nsend. We could 1979 * fully populate the thread private data here, but if we get down there 1980 * and have a cache hit that would be wasted, so we do the rest there on miss 1981 */ 1982 res_setiface(res, iface); 1983 if (res_searchN(name, &q, res) < 0) { 1984 __res_put_state(res); 1985 free(buf); 1986 free(buf2); 1987 return NS_NOTFOUND; 1988 } 1989 ai = getanswer(buf, q.n, q.name, q.qtype, pai); 1990 if (ai) { 1991 cur->ai_next = ai; 1992 while (cur && cur->ai_next) 1993 cur = cur->ai_next; 1994 } 1995 if (q.next) { 1996 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); 1997 if (ai) 1998 cur->ai_next = ai; 1999 } 2000 free(buf); 2001 free(buf2); 2002 if (sentinel.ai_next == NULL) { 2003 __res_put_state(res); 2004 switch (h_errno) { 2005 case HOST_NOT_FOUND: 2006 return NS_NOTFOUND; 2007 case TRY_AGAIN: 2008 return NS_TRYAGAIN; 2009 default: 2010 return NS_UNAVAIL; 2011 } 2012 } 2013 2014 _rfc6724_sort(&sentinel); 2015 2016 __res_put_state(res); 2017 2018 *((struct addrinfo **)rv) = sentinel.ai_next; 2019 return NS_SUCCESS; 2020} 2021 2022static void 2023_sethtent(FILE **hostf) 2024{ 2025 2026 if (!*hostf) 2027 *hostf = fopen(_PATH_HOSTS, "r" ); 2028 else 2029 rewind(*hostf); 2030} 2031 2032static void 2033_endhtent(FILE **hostf) 2034{ 2035 2036 if (*hostf) { 2037 (void) fclose(*hostf); 2038 *hostf = NULL; 2039 } 2040} 2041 2042static struct addrinfo * 2043_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 2044{ 2045 char *p; 2046 char *cp, *tname, *cname; 2047 struct addrinfo hints, *res0, *res; 2048 int error; 2049 const char *addr; 2050 char hostbuf[8*1024]; 2051 2052// fprintf(stderr, "_gethtent() name = '%s'\n", name); 2053 assert(name != NULL); 2054 assert(pai != NULL); 2055 2056 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" ))) 2057 return (NULL); 2058 again: 2059 if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf))) 2060 return (NULL); 2061 if (*p == '#') 2062 goto again; 2063 if (!(cp = strpbrk(p, "#\n"))) 2064 goto again; 2065 *cp = '\0'; 2066 if (!(cp = strpbrk(p, " \t"))) 2067 goto again; 2068 *cp++ = '\0'; 2069 addr = p; 2070 /* if this is not something we're looking for, skip it. */ 2071 cname = NULL; 2072 while (cp && *cp) { 2073 if (*cp == ' ' || *cp == '\t') { 2074 cp++; 2075 continue; 2076 } 2077 if (!cname) 2078 cname = cp; 2079 tname = cp; 2080 if ((cp = strpbrk(cp, " \t")) != NULL) 2081 *cp++ = '\0'; 2082// fprintf(stderr, "\ttname = '%s'", tname); 2083 if (strcasecmp(name, tname) == 0) 2084 goto found; 2085 } 2086 goto again; 2087 2088found: 2089 hints = *pai; 2090 hints.ai_flags = AI_NUMERICHOST; 2091 error = getaddrinfo(addr, NULL, &hints, &res0); 2092 if (error) 2093 goto again; 2094 for (res = res0; res; res = res->ai_next) { 2095 /* cover it up */ 2096 res->ai_flags = pai->ai_flags; 2097 2098 if (pai->ai_flags & AI_CANONNAME) { 2099 if (get_canonname(pai, res, cname) != 0) { 2100 freeaddrinfo(res0); 2101 goto again; 2102 } 2103 } 2104 } 2105 return res0; 2106} 2107 2108/*ARGSUSED*/ 2109static int 2110_files_getaddrinfo(void *rv, void *cb_data, va_list ap) 2111{ 2112 const char *name; 2113 const struct addrinfo *pai; 2114 struct addrinfo sentinel, *cur; 2115 struct addrinfo *p; 2116 FILE *hostf = NULL; 2117 2118 name = va_arg(ap, char *); 2119 pai = va_arg(ap, struct addrinfo *); 2120 2121// fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name); 2122 memset(&sentinel, 0, sizeof(sentinel)); 2123 cur = &sentinel; 2124 2125 _sethtent(&hostf); 2126 while ((p = _gethtent(&hostf, name, pai)) != NULL) { 2127 cur->ai_next = p; 2128 while (cur && cur->ai_next) 2129 cur = cur->ai_next; 2130 } 2131 _endhtent(&hostf); 2132 2133 *((struct addrinfo **)rv) = sentinel.ai_next; 2134 if (sentinel.ai_next == NULL) 2135 return NS_NOTFOUND; 2136 return NS_SUCCESS; 2137} 2138 2139/* resolver logic */ 2140 2141/* 2142 * Formulate a normal query, send, and await answer. 2143 * Returned answer is placed in supplied buffer "answer". 2144 * Perform preliminary check of answer, returning success only 2145 * if no error is indicated and the answer count is nonzero. 2146 * Return the size of the response on success, -1 on error. 2147 * Error number is left in h_errno. 2148 * 2149 * Caller must parse answer and determine whether it answers the question. 2150 */ 2151static int 2152res_queryN(const char *name, /* domain name */ struct res_target *target, 2153 res_state res) 2154{ 2155 u_char buf[MAXPACKET]; 2156 HEADER *hp; 2157 int n; 2158 struct res_target *t; 2159 int rcode; 2160 int ancount; 2161 2162 assert(name != NULL); 2163 /* XXX: target may be NULL??? */ 2164 2165 rcode = NOERROR; 2166 ancount = 0; 2167 2168 for (t = target; t; t = t->next) { 2169 int class, type; 2170 u_char *answer; 2171 int anslen; 2172 2173 hp = (HEADER *)(void *)t->answer; 2174 hp->rcode = NOERROR; /* default */ 2175 2176 /* make it easier... */ 2177 class = t->qclass; 2178 type = t->qtype; 2179 answer = t->answer; 2180 anslen = t->anslen; 2181#ifdef DEBUG 2182 if (res->options & RES_DEBUG) 2183 printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 2184#endif 2185 2186 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, 2187 buf, sizeof(buf)); 2188#ifdef RES_USE_EDNS0 2189 if (n > 0 && (res->options & RES_USE_EDNS0) != 0) 2190 n = res_nopt(res, n, buf, sizeof(buf), anslen); 2191#endif 2192 if (n <= 0) { 2193#ifdef DEBUG 2194 if (res->options & RES_DEBUG) 2195 printf(";; res_nquery: mkquery failed\n"); 2196#endif 2197 h_errno = NO_RECOVERY; 2198 return n; 2199 } 2200 n = res_nsend(res, buf, n, answer, anslen); 2201#if 0 2202 if (n < 0) { 2203#ifdef DEBUG 2204 if (res->options & RES_DEBUG) 2205 printf(";; res_query: send error\n"); 2206#endif 2207 h_errno = TRY_AGAIN; 2208 return n; 2209 } 2210#endif 2211 2212 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 2213 rcode = hp->rcode; /* record most recent error */ 2214#ifdef DEBUG 2215 if (res->options & RES_DEBUG) 2216 printf(";; rcode = %u, ancount=%u\n", hp->rcode, 2217 ntohs(hp->ancount)); 2218#endif 2219 continue; 2220 } 2221 2222 ancount += ntohs(hp->ancount); 2223 2224 t->n = n; 2225 } 2226 2227 if (ancount == 0) { 2228 switch (rcode) { 2229 case NXDOMAIN: 2230 h_errno = HOST_NOT_FOUND; 2231 break; 2232 case SERVFAIL: 2233 h_errno = TRY_AGAIN; 2234 break; 2235 case NOERROR: 2236 h_errno = NO_DATA; 2237 break; 2238 case FORMERR: 2239 case NOTIMP: 2240 case REFUSED: 2241 default: 2242 h_errno = NO_RECOVERY; 2243 break; 2244 } 2245 return -1; 2246 } 2247 return ancount; 2248} 2249 2250/* 2251 * Formulate a normal query, send, and retrieve answer in supplied buffer. 2252 * Return the size of the response on success, -1 on error. 2253 * If enabled, implement search rules until answer or unrecoverable failure 2254 * is detected. Error code, if any, is left in h_errno. 2255 */ 2256static int 2257res_searchN(const char *name, struct res_target *target, res_state res) 2258{ 2259 const char *cp, * const *domain; 2260 HEADER *hp; 2261 u_int dots; 2262 int trailing_dot, ret, saved_herrno; 2263 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 2264 2265 assert(name != NULL); 2266 assert(target != NULL); 2267 2268 hp = (HEADER *)(void *)target->answer; /*XXX*/ 2269 2270 errno = 0; 2271 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 2272 dots = 0; 2273 for (cp = name; *cp; cp++) 2274 dots += (*cp == '.'); 2275 trailing_dot = 0; 2276 if (cp > name && *--cp == '.') 2277 trailing_dot++; 2278 2279 2280 //fprintf(stderr, "res_searchN() name = '%s'\n", name); 2281 2282 /* 2283 * if there aren't any dots, it could be a user-level alias 2284 */ 2285 if (!dots && (cp = __hostalias(name)) != NULL) { 2286 ret = res_queryN(cp, target, res); 2287 return ret; 2288 } 2289 2290 /* 2291 * If there are dots in the name already, let's just give it a try 2292 * 'as is'. The threshold can be set with the "ndots" option. 2293 */ 2294 saved_herrno = -1; 2295 if (dots >= res->ndots) { 2296 ret = res_querydomainN(name, NULL, target, res); 2297 if (ret > 0) 2298 return (ret); 2299 saved_herrno = h_errno; 2300 tried_as_is++; 2301 } 2302 2303 /* 2304 * We do at least one level of search if 2305 * - there is no dot and RES_DEFNAME is set, or 2306 * - there is at least one dot, there is no trailing dot, 2307 * and RES_DNSRCH is set. 2308 */ 2309 if ((!dots && (res->options & RES_DEFNAMES)) || 2310 (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 2311 int done = 0; 2312 2313 for (domain = (const char * const *)res->dnsrch; 2314 *domain && !done; 2315 domain++) { 2316 2317 ret = res_querydomainN(name, *domain, target, res); 2318 if (ret > 0) 2319 return ret; 2320 2321 /* 2322 * If no server present, give up. 2323 * If name isn't found in this domain, 2324 * keep trying higher domains in the search list 2325 * (if that's enabled). 2326 * On a NO_DATA error, keep trying, otherwise 2327 * a wildcard entry of another type could keep us 2328 * from finding this entry higher in the domain. 2329 * If we get some other error (negative answer or 2330 * server failure), then stop searching up, 2331 * but try the input name below in case it's 2332 * fully-qualified. 2333 */ 2334 if (errno == ECONNREFUSED) { 2335 h_errno = TRY_AGAIN; 2336 return -1; 2337 } 2338 2339 switch (h_errno) { 2340 case NO_DATA: 2341 got_nodata++; 2342 /* FALLTHROUGH */ 2343 case HOST_NOT_FOUND: 2344 /* keep trying */ 2345 break; 2346 case TRY_AGAIN: 2347 if (hp->rcode == SERVFAIL) { 2348 /* try next search element, if any */ 2349 got_servfail++; 2350 break; 2351 } 2352 /* FALLTHROUGH */ 2353 default: 2354 /* anything else implies that we're done */ 2355 done++; 2356 } 2357 /* 2358 * if we got here for some reason other than DNSRCH, 2359 * we only wanted one iteration of the loop, so stop. 2360 */ 2361 if (!(res->options & RES_DNSRCH)) 2362 done++; 2363 } 2364 } 2365 2366 /* 2367 * if we have not already tried the name "as is", do that now. 2368 * note that we do this regardless of how many dots were in the 2369 * name or whether it ends with a dot. 2370 */ 2371 if (!tried_as_is) { 2372 ret = res_querydomainN(name, NULL, target, res); 2373 if (ret > 0) 2374 return ret; 2375 } 2376 2377 /* 2378 * if we got here, we didn't satisfy the search. 2379 * if we did an initial full query, return that query's h_errno 2380 * (note that we wouldn't be here if that query had succeeded). 2381 * else if we ever got a nodata, send that back as the reason. 2382 * else send back meaningless h_errno, that being the one from 2383 * the last DNSRCH we did. 2384 */ 2385 if (saved_herrno != -1) 2386 h_errno = saved_herrno; 2387 else if (got_nodata) 2388 h_errno = NO_DATA; 2389 else if (got_servfail) 2390 h_errno = TRY_AGAIN; 2391 return -1; 2392} 2393 2394/* 2395 * Perform a call on res_query on the concatenation of name and domain, 2396 * removing a trailing dot from name if domain is NULL. 2397 */ 2398static int 2399res_querydomainN(const char *name, const char *domain, 2400 struct res_target *target, res_state res) 2401{ 2402 char nbuf[MAXDNAME]; 2403 const char *longname = nbuf; 2404 size_t n, d; 2405 2406 assert(name != NULL); 2407 /* XXX: target may be NULL??? */ 2408 2409#ifdef DEBUG 2410 if (res->options & RES_DEBUG) 2411 printf(";; res_querydomain(%s, %s)\n", 2412 name, domain?domain:"<Nil>"); 2413#endif 2414 if (domain == NULL) { 2415 /* 2416 * Check for trailing '.'; 2417 * copy without '.' if present. 2418 */ 2419 n = strlen(name); 2420 if (n + 1 > sizeof(nbuf)) { 2421 h_errno = NO_RECOVERY; 2422 return -1; 2423 } 2424 if (n > 0 && name[--n] == '.') { 2425 strncpy(nbuf, name, n); 2426 nbuf[n] = '\0'; 2427 } else 2428 longname = name; 2429 } else { 2430 n = strlen(name); 2431 d = strlen(domain); 2432 if (n + 1 + d + 1 > sizeof(nbuf)) { 2433 h_errno = NO_RECOVERY; 2434 return -1; 2435 } 2436 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 2437 } 2438 return res_queryN(longname, target, res); 2439} 2440