1 /* $NetBSD: getaddrinfo.c,v 1.101 2012/06/08 07:54:14 martin 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 * - Return values. There are nonstandard return values defined and used 36 * in the source code. This is because RFC2553 is silent about which error 37 * code must be returned for which situation. 38 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 39 * says to use inet_aton() to convert IPv4 numeric to binary (alows 40 * classful form as a result). 41 * current code - disallow classful form for IPv4 (due to use of inet_pton). 42 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is 43 * invalid. 44 * current code - SEGV on freeaddrinfo(NULL) 45 * Note: 46 * - The code filters out AFs that are not supported by the kernel, 47 * when globbing NULL hostname (to loopback, or wildcard). Is it the right 48 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 49 * in ai_flags? 50 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. 51 * (1) what should we do against numeric hostname (2) what should we do 52 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? 53 * non-loopback address configured? global address configured? 54 */ 55 56 #include <sys/cdefs.h> 57 #if defined(LIBC_SCCS) && !defined(lint) 58 __RCSID("$NetBSD: getaddrinfo.c,v 1.101 2012/06/08 07:54:14 martin Exp $"); 59 #endif /* LIBC_SCCS and not lint */ 60 61 #include "namespace.h" 62 #include <sys/types.h> 63 #include <sys/param.h> 64 #include <sys/socket.h> 65 #include <net/if.h> 66 #include <netinet/in.h> 67 #include <arpa/inet.h> 68 #include <arpa/nameser.h> 69 #include <assert.h> 70 #include <ctype.h> 71 #include <errno.h> 72 #include <netdb.h> 73 #include <resolv.h> 74 #include <stddef.h> 75 #include <stdio.h> 76 #include <stdlib.h> 77 #include <string.h> 78 #include <unistd.h> 79 #include <ifaddrs.h> 80 81 #include <syslog.h> 82 #include <stdarg.h> 83 #include <nsswitch.h> 84 85 #ifdef YP 86 #include <rpc/rpc.h> 87 #include <rpcsvc/yp_prot.h> 88 #include <rpcsvc/ypclnt.h> 89 #endif 90 91 #include "servent.h" 92 93 #ifdef __weak_alias 94 __weak_alias(getaddrinfo,_getaddrinfo) 95 __weak_alias(freeaddrinfo,_freeaddrinfo) 96 __weak_alias(gai_strerror,_gai_strerror) 97 #endif 98 99 #define SUCCESS 0 100 #define ANY 0 101 #define YES 1 102 #define NO 0 103 104 static const char in_addrany[] = { 0, 0, 0, 0 }; 105 static const char in_loopback[] = { 127, 0, 0, 1 }; 106 #ifdef INET6 107 static const char in6_addrany[] = { 108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 109 }; 110 static const char in6_loopback[] = { 111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 112 }; 113 #endif 114 115 static const struct afd { 116 int a_af; 117 int a_addrlen; 118 int a_socklen; 119 int a_off; 120 const char *a_addrany; 121 const char *a_loopback; 122 int a_scoped; 123 } afdl [] = { 124 #ifdef INET6 125 {PF_INET6, sizeof(struct in6_addr), 126 sizeof(struct sockaddr_in6), 127 offsetof(struct sockaddr_in6, sin6_addr), 128 in6_addrany, in6_loopback, 1}, 129 #endif 130 {PF_INET, sizeof(struct in_addr), 131 sizeof(struct sockaddr_in), 132 offsetof(struct sockaddr_in, sin_addr), 133 in_addrany, in_loopback, 0}, 134 {0, 0, 0, 0, NULL, NULL, 0}, 135 }; 136 137 struct explore { 138 int e_af; 139 int e_socktype; 140 int e_protocol; 141 const char *e_protostr; 142 int e_wild; 143 #define WILD_AF(ex) ((ex)->e_wild & 0x01) 144 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 145 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 146 }; 147 148 static const struct explore explore[] = { 149 #if 0 150 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, 151 #endif 152 #ifdef INET6 153 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 154 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 155 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 156 #endif 157 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 158 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 159 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 160 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 161 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 162 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, 163 { -1, 0, 0, NULL, 0 }, 164 }; 165 166 #ifdef INET6 167 #define PTON_MAX 16 168 #else 169 #define PTON_MAX 4 170 #endif 171 172 static const ns_src default_dns_files[] = { 173 { NSSRC_FILES, NS_SUCCESS }, 174 { NSSRC_DNS, NS_SUCCESS }, 175 { 0, 0 } 176 }; 177 178 #define MAXPACKET (64*1024) 179 180 typedef union { 181 HEADER hdr; 182 u_char buf[MAXPACKET]; 183 } querybuf; 184 185 struct res_target { 186 struct res_target *next; 187 const char *name; /* domain name */ 188 int qclass, qtype; /* class and type of query */ 189 u_char *answer; /* buffer to put answer */ 190 int anslen; /* size of answer buffer */ 191 int n; /* result length */ 192 }; 193 194 static int str2number(const char *); 195 static int explore_fqdn(const struct addrinfo *, const char *, 196 const char *, struct addrinfo **, struct servent_data *); 197 static int explore_null(const struct addrinfo *, 198 const char *, struct addrinfo **, struct servent_data *); 199 static int explore_numeric(const struct addrinfo *, const char *, 200 const char *, struct addrinfo **, const char *, struct servent_data *); 201 static int explore_numeric_scope(const struct addrinfo *, const char *, 202 const char *, struct addrinfo **, struct servent_data *); 203 static int get_canonname(const struct addrinfo *, 204 struct addrinfo *, const char *); 205 static struct addrinfo *get_ai(const struct addrinfo *, 206 const struct afd *, const char *); 207 static int get_portmatch(const struct addrinfo *, const char *, 208 struct servent_data *); 209 static int get_port(const struct addrinfo *, const char *, int, 210 struct servent_data *); 211 static const struct afd *find_afd(int); 212 static int addrconfig(uint64_t *); 213 #ifdef INET6 214 static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); 215 #endif 216 217 static struct addrinfo *getanswer(const querybuf *, int, const char *, int, 218 const struct addrinfo *); 219 static void aisort(struct addrinfo *s, res_state res); 220 static int _dns_getaddrinfo(void *, void *, va_list); 221 static void _sethtent(FILE **); 222 static void _endhtent(FILE **); 223 static struct addrinfo *_gethtent(FILE **, const char *, 224 const struct addrinfo *); 225 static int _files_getaddrinfo(void *, void *, va_list); 226 #ifdef YP 227 static struct addrinfo *_yphostent(char *, const struct addrinfo *); 228 static int _yp_getaddrinfo(void *, void *, va_list); 229 #endif 230 231 static int res_queryN(const char *, struct res_target *, res_state); 232 static int res_searchN(const char *, struct res_target *, res_state); 233 static int res_querydomainN(const char *, const char *, 234 struct res_target *, res_state); 235 236 static const char * const ai_errlist[] = { 237 "Success", 238 "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 239 "Temporary failure in name resolution", /* EAI_AGAIN */ 240 "Invalid value for ai_flags", /* EAI_BADFLAGS */ 241 "Non-recoverable failure in name resolution", /* EAI_FAIL */ 242 "ai_family not supported", /* EAI_FAMILY */ 243 "Memory allocation failure", /* EAI_MEMORY */ 244 "No address associated with hostname", /* EAI_NODATA */ 245 "hostname nor servname provided, or not known", /* EAI_NONAME */ 246 "servname not supported for ai_socktype", /* EAI_SERVICE */ 247 "ai_socktype not supported", /* EAI_SOCKTYPE */ 248 "System error returned in errno", /* EAI_SYSTEM */ 249 "Invalid value for hints", /* EAI_BADHINTS */ 250 "Resolved protocol is unknown", /* EAI_PROTOCOL */ 251 "Argument buffer overflow", /* EAI_OVERFLOW */ 252 "Unknown error", /* EAI_MAX */ 253 }; 254 255 /* XXX macros that make external reference is BAD. */ 256 257 #define GET_AI(ai, afd, addr) \ 258 do { \ 259 /* external reference: pai, error, and label free */ \ 260 (ai) = get_ai(pai, (afd), (addr)); \ 261 if ((ai) == NULL) { \ 262 error = EAI_MEMORY; \ 263 goto free; \ 264 } \ 265 } while (/*CONSTCOND*/0) 266 267 #define GET_PORT(ai, serv, svd) \ 268 do { \ 269 /* external reference: error and label free */ \ 270 error = get_port((ai), (serv), 0, (svd)); \ 271 if (error != 0) \ 272 goto free; \ 273 } while (/*CONSTCOND*/0) 274 275 #define GET_CANONNAME(ai, str) \ 276 do { \ 277 /* external reference: pai, error and label free */ \ 278 error = get_canonname(pai, (ai), (str)); \ 279 if (error != 0) \ 280 goto free; \ 281 } while (/*CONSTCOND*/0) 282 283 #define ERR(err) \ 284 do { \ 285 /* external reference: error, and label bad */ \ 286 error = (err); \ 287 goto bad; \ 288 /*NOTREACHED*/ \ 289 } while (/*CONSTCOND*/0) 290 291 #define MATCH_FAMILY(x, y, w) \ 292 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \ 293 (y) == PF_UNSPEC))) 294 #define MATCH(x, y, w) \ 295 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) 296 297 const char * 298 gai_strerror(int ecode) 299 { 300 if (ecode < 0 || ecode > EAI_MAX) 301 ecode = EAI_MAX; 302 return ai_errlist[ecode]; 303 } 304 305 void 306 freeaddrinfo(struct addrinfo *ai) 307 { 308 struct addrinfo *next; 309 310 _DIAGASSERT(ai != NULL); 311 312 do { 313 next = ai->ai_next; 314 if (ai->ai_canonname) 315 free(ai->ai_canonname); 316 /* no need to free(ai->ai_addr) */ 317 free(ai); 318 ai = next; 319 } while (ai); 320 } 321 322 static int 323 str2number(const char *p) 324 { 325 char *ep; 326 unsigned long v; 327 328 _DIAGASSERT(p != NULL); 329 330 if (*p == '\0') 331 return -1; 332 ep = NULL; 333 errno = 0; 334 v = strtoul(p, &ep, 10); 335 if (errno == 0 && ep && *ep == '\0' && v <= INT_MAX) 336 return (int)v; 337 else 338 return -1; 339 } 340 341 int 342 getaddrinfo(const char *hostname, const char *servname, 343 const struct addrinfo *hints, struct addrinfo **res) 344 { 345 struct addrinfo sentinel; 346 struct addrinfo *cur; 347 int error = 0; 348 struct addrinfo ai; 349 struct addrinfo ai0; 350 struct addrinfo *pai; 351 const struct explore *ex; 352 struct servent_data svd; 353 uint64_t mask = (uint64_t)~0ULL; 354 355 /* hostname is allowed to be NULL */ 356 /* servname is allowed to be NULL */ 357 /* hints is allowed to be NULL */ 358 _DIAGASSERT(res != NULL); 359 360 (void)memset(&svd, 0, sizeof(svd)); 361 memset(&sentinel, 0, sizeof(sentinel)); 362 cur = &sentinel; 363 memset(&ai, 0, sizeof(ai)); 364 pai = &ai; 365 pai->ai_flags = 0; 366 pai->ai_family = PF_UNSPEC; 367 pai->ai_socktype = ANY; 368 pai->ai_protocol = ANY; 369 pai->ai_addrlen = 0; 370 pai->ai_canonname = NULL; 371 pai->ai_addr = NULL; 372 pai->ai_next = NULL; 373 374 if (hostname == NULL && servname == NULL) 375 return EAI_NONAME; 376 if (hints) { 377 /* error check for hints */ 378 if (hints->ai_addrlen || hints->ai_canonname || 379 hints->ai_addr || hints->ai_next) 380 ERR(EAI_BADHINTS); /* xxx */ 381 if (hints->ai_flags & ~AI_MASK) 382 ERR(EAI_BADFLAGS); 383 switch (hints->ai_family) { 384 case PF_UNSPEC: 385 case PF_INET: 386 #ifdef INET6 387 case PF_INET6: 388 #endif 389 break; 390 default: 391 ERR(EAI_FAMILY); 392 } 393 memcpy(pai, hints, sizeof(*pai)); 394 395 /* 396 * if both socktype/protocol are specified, check if they 397 * are meaningful combination. 398 */ 399 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 400 for (ex = explore; ex->e_af >= 0; ex++) { 401 if (pai->ai_family != ex->e_af) 402 continue; 403 if (ex->e_socktype == ANY) 404 continue; 405 if (ex->e_protocol == ANY) 406 continue; 407 if (pai->ai_socktype == ex->e_socktype 408 && pai->ai_protocol != ex->e_protocol) { 409 ERR(EAI_BADHINTS); 410 } 411 } 412 } 413 } 414 415 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && addrconfig(&mask) == -1) 416 ERR(EAI_FAIL); 417 418 /* 419 * check for special cases. (1) numeric servname is disallowed if 420 * socktype/protocol are left unspecified. (2) servname is disallowed 421 * for raw and other inet{,6} sockets. 422 */ 423 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 424 #ifdef PF_INET6 425 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 426 #endif 427 ) { 428 ai0 = *pai; /* backup *pai */ 429 430 if (pai->ai_family == PF_UNSPEC) { 431 #ifdef PF_INET6 432 pai->ai_family = PF_INET6; 433 #else 434 pai->ai_family = PF_INET; 435 #endif 436 } 437 error = get_portmatch(pai, servname, &svd); 438 if (error) 439 goto bad; 440 441 *pai = ai0; 442 } 443 444 ai0 = *pai; 445 446 /* NULL hostname, or numeric hostname */ 447 for (ex = explore; ex->e_af >= 0; ex++) { 448 *pai = ai0; 449 450 /* ADDRCONFIG check */ 451 if ((((uint64_t)1 << ex->e_af) & mask) == 0) 452 continue; 453 454 /* PF_UNSPEC entries are prepared for DNS queries only */ 455 if (ex->e_af == PF_UNSPEC) 456 continue; 457 458 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 459 continue; 460 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 461 continue; 462 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 463 continue; 464 if (pai->ai_family == PF_UNSPEC) 465 pai->ai_family = ex->e_af; 466 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 467 pai->ai_socktype = ex->e_socktype; 468 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 469 pai->ai_protocol = ex->e_protocol; 470 471 if (hostname == NULL) 472 error = explore_null(pai, servname, &cur->ai_next, 473 &svd); 474 else 475 error = explore_numeric_scope(pai, hostname, servname, 476 &cur->ai_next, &svd); 477 478 if (error) 479 goto free; 480 481 while (cur->ai_next) 482 cur = cur->ai_next; 483 } 484 485 /* 486 * XXX 487 * If numeric representation of AF1 can be interpreted as FQDN 488 * representation of AF2, we need to think again about the code below. 489 */ 490 if (sentinel.ai_next) 491 goto good; 492 493 if (hostname == NULL) 494 ERR(EAI_NODATA); 495 if (pai->ai_flags & AI_NUMERICHOST) 496 ERR(EAI_NONAME); 497 498 /* 499 * hostname as alphabetical name. 500 * we would like to prefer AF_INET6 than AF_INET, so we'll make a 501 * outer loop by AFs. 502 */ 503 for (ex = explore; ex->e_af >= 0; ex++) { 504 *pai = ai0; 505 506 507 /* ADDRCONFIG check */ 508 /* PF_UNSPEC entries are prepared for DNS queries only */ 509 if (ex->e_af != PF_UNSPEC && 510 (((uint64_t)1 << ex->e_af) & mask) == 0) 511 continue; 512 513 /* require exact match for family field */ 514 if (pai->ai_family != ex->e_af) 515 continue; 516 517 if (!MATCH(pai->ai_socktype, ex->e_socktype, 518 WILD_SOCKTYPE(ex))) { 519 continue; 520 } 521 if (!MATCH(pai->ai_protocol, ex->e_protocol, 522 WILD_PROTOCOL(ex))) { 523 continue; 524 } 525 526 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 527 pai->ai_socktype = ex->e_socktype; 528 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 529 pai->ai_protocol = ex->e_protocol; 530 531 error = explore_fqdn(pai, hostname, servname, &cur->ai_next, 532 &svd); 533 534 while (cur && cur->ai_next) 535 cur = cur->ai_next; 536 } 537 538 /* XXX */ 539 if (sentinel.ai_next) 540 error = 0; 541 542 if (error) 543 goto free; 544 545 if (sentinel.ai_next) { 546 good: 547 endservent_r(&svd); 548 *res = sentinel.ai_next; 549 return SUCCESS; 550 } else 551 error = EAI_FAIL; 552 free: 553 bad: 554 endservent_r(&svd); 555 if (sentinel.ai_next) 556 freeaddrinfo(sentinel.ai_next); 557 *res = NULL; 558 return error; 559 } 560 561 /* 562 * FQDN hostname, DNS lookup 563 */ 564 static int 565 explore_fqdn(const struct addrinfo *pai, const char *hostname, 566 const char *servname, struct addrinfo **res, struct servent_data *svd) 567 { 568 struct addrinfo *result; 569 struct addrinfo *cur; 570 int error = 0; 571 static const ns_dtab dtab[] = { 572 NS_FILES_CB(_files_getaddrinfo, NULL) 573 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ 574 NS_NIS_CB(_yp_getaddrinfo, NULL) 575 NS_NULL_CB 576 }; 577 578 _DIAGASSERT(pai != NULL); 579 /* hostname may be NULL */ 580 /* servname may be NULL */ 581 _DIAGASSERT(res != NULL); 582 583 result = NULL; 584 585 /* 586 * if the servname does not match socktype/protocol, ignore it. 587 */ 588 if (get_portmatch(pai, servname, svd) != 0) 589 return 0; 590 591 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", 592 default_dns_files, hostname, pai)) { 593 case NS_TRYAGAIN: 594 error = EAI_AGAIN; 595 goto free; 596 case NS_UNAVAIL: 597 error = EAI_FAIL; 598 goto free; 599 case NS_NOTFOUND: 600 error = EAI_NODATA; 601 goto free; 602 case NS_SUCCESS: 603 error = 0; 604 for (cur = result; cur; cur = cur->ai_next) { 605 GET_PORT(cur, servname, svd); 606 /* canonname should be filled already */ 607 } 608 break; 609 } 610 611 *res = result; 612 613 return 0; 614 615 free: 616 if (result) 617 freeaddrinfo(result); 618 return error; 619 } 620 621 /* 622 * hostname == NULL. 623 * passive socket -> anyaddr (0.0.0.0 or ::) 624 * non-passive socket -> localhost (127.0.0.1 or ::1) 625 */ 626 static int 627 explore_null(const struct addrinfo *pai, const char *servname, 628 struct addrinfo **res, struct servent_data *svd) 629 { 630 int s; 631 const struct afd *afd; 632 struct addrinfo *cur; 633 struct addrinfo sentinel; 634 int error; 635 636 _DIAGASSERT(pai != NULL); 637 /* servname may be NULL */ 638 _DIAGASSERT(res != NULL); 639 640 *res = NULL; 641 sentinel.ai_next = NULL; 642 cur = &sentinel; 643 644 /* 645 * filter out AFs that are not supported by the kernel 646 * XXX errno? 647 */ 648 s = socket(pai->ai_family, SOCK_DGRAM, 0); 649 if (s < 0) { 650 if (errno != EMFILE) 651 return 0; 652 } else 653 close(s); 654 655 /* 656 * if the servname does not match socktype/protocol, ignore it. 657 */ 658 if (get_portmatch(pai, servname, svd) != 0) 659 return 0; 660 661 afd = find_afd(pai->ai_family); 662 if (afd == NULL) 663 return 0; 664 665 if (pai->ai_flags & AI_PASSIVE) { 666 GET_AI(cur->ai_next, afd, afd->a_addrany); 667 /* xxx meaningless? 668 * GET_CANONNAME(cur->ai_next, "anyaddr"); 669 */ 670 GET_PORT(cur->ai_next, servname, svd); 671 } else { 672 GET_AI(cur->ai_next, afd, afd->a_loopback); 673 /* xxx meaningless? 674 * GET_CANONNAME(cur->ai_next, "localhost"); 675 */ 676 GET_PORT(cur->ai_next, servname, svd); 677 } 678 cur = cur->ai_next; 679 680 *res = sentinel.ai_next; 681 return 0; 682 683 free: 684 if (sentinel.ai_next) 685 freeaddrinfo(sentinel.ai_next); 686 return error; 687 } 688 689 /* 690 * numeric hostname 691 */ 692 static int 693 explore_numeric(const struct addrinfo *pai, const char *hostname, 694 const char *servname, struct addrinfo **res, const char *canonname, 695 struct servent_data *svd) 696 { 697 const struct afd *afd; 698 struct addrinfo *cur; 699 struct addrinfo sentinel; 700 int error; 701 char pton[PTON_MAX]; 702 703 _DIAGASSERT(pai != NULL); 704 /* hostname may be NULL */ 705 /* servname may be NULL */ 706 _DIAGASSERT(res != NULL); 707 708 *res = NULL; 709 sentinel.ai_next = NULL; 710 cur = &sentinel; 711 712 /* 713 * if the servname does not match socktype/protocol, ignore it. 714 */ 715 if (get_portmatch(pai, servname, svd) != 0) 716 return 0; 717 718 afd = find_afd(pai->ai_family); 719 if (afd == NULL) 720 return 0; 721 722 switch (afd->a_af) { 723 #if 0 /*X/Open spec*/ 724 case AF_INET: 725 if (inet_aton(hostname, (struct in_addr *)pton) == 1) { 726 if (pai->ai_family == afd->a_af || 727 pai->ai_family == PF_UNSPEC /*?*/) { 728 GET_AI(cur->ai_next, afd, pton); 729 GET_PORT(cur->ai_next, servname, svd); 730 if ((pai->ai_flags & AI_CANONNAME)) { 731 /* 732 * Set the numeric address itself as 733 * the canonical name, based on a 734 * clarification in rfc2553bis-03. 735 */ 736 GET_CANONNAME(cur->ai_next, canonname); 737 } 738 while (cur && cur->ai_next) 739 cur = cur->ai_next; 740 } else 741 ERR(EAI_FAMILY); /*xxx*/ 742 } 743 break; 744 #endif 745 default: 746 if (inet_pton(afd->a_af, hostname, pton) == 1) { 747 if (pai->ai_family == afd->a_af || 748 pai->ai_family == PF_UNSPEC /*?*/) { 749 GET_AI(cur->ai_next, afd, pton); 750 GET_PORT(cur->ai_next, servname, svd); 751 if ((pai->ai_flags & AI_CANONNAME)) { 752 /* 753 * Set the numeric address itself as 754 * the canonical name, based on a 755 * clarification in rfc2553bis-03. 756 */ 757 GET_CANONNAME(cur->ai_next, canonname); 758 } 759 while (cur->ai_next) 760 cur = cur->ai_next; 761 } else 762 ERR(EAI_FAMILY); /*xxx*/ 763 } 764 break; 765 } 766 767 *res = sentinel.ai_next; 768 return 0; 769 770 free: 771 bad: 772 if (sentinel.ai_next) 773 freeaddrinfo(sentinel.ai_next); 774 return error; 775 } 776 777 /* 778 * numeric hostname with scope 779 */ 780 static int 781 explore_numeric_scope(const struct addrinfo *pai, const char *hostname, 782 const char *servname, struct addrinfo **res, struct servent_data *svd) 783 { 784 #if !defined(SCOPE_DELIMITER) || !defined(INET6) 785 return explore_numeric(pai, hostname, servname, res, hostname, svd); 786 #else 787 const struct afd *afd; 788 struct addrinfo *cur; 789 int error; 790 char *cp, *hostname2 = NULL, *scope, *addr; 791 struct sockaddr_in6 *sin6; 792 793 _DIAGASSERT(pai != NULL); 794 /* hostname may be NULL */ 795 /* servname may be NULL */ 796 _DIAGASSERT(res != NULL); 797 798 /* 799 * if the servname does not match socktype/protocol, ignore it. 800 */ 801 if (get_portmatch(pai, servname, svd) != 0) 802 return 0; 803 804 afd = find_afd(pai->ai_family); 805 if (afd == NULL) 806 return 0; 807 808 if (!afd->a_scoped) 809 return explore_numeric(pai, hostname, servname, res, hostname, 810 svd); 811 812 cp = strchr(hostname, SCOPE_DELIMITER); 813 if (cp == NULL) 814 return explore_numeric(pai, hostname, servname, res, hostname, 815 svd); 816 817 /* 818 * Handle special case of <scoped_address><delimiter><scope id> 819 */ 820 hostname2 = strdup(hostname); 821 if (hostname2 == NULL) 822 return EAI_MEMORY; 823 /* terminate at the delimiter */ 824 hostname2[cp - hostname] = '\0'; 825 addr = hostname2; 826 scope = cp + 1; 827 828 error = explore_numeric(pai, addr, servname, res, hostname, svd); 829 if (error == 0) { 830 u_int32_t scopeid; 831 832 for (cur = *res; cur; cur = cur->ai_next) { 833 if (cur->ai_family != AF_INET6) 834 continue; 835 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 836 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { 837 free(hostname2); 838 return(EAI_NODATA); /* XXX: is return OK? */ 839 } 840 sin6->sin6_scope_id = scopeid; 841 } 842 } 843 844 free(hostname2); 845 846 return error; 847 #endif 848 } 849 850 static int 851 get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) 852 { 853 854 _DIAGASSERT(pai != NULL); 855 _DIAGASSERT(ai != NULL); 856 _DIAGASSERT(str != NULL); 857 858 if ((pai->ai_flags & AI_CANONNAME) != 0) { 859 ai->ai_canonname = strdup(str); 860 if (ai->ai_canonname == NULL) 861 return EAI_MEMORY; 862 } 863 return 0; 864 } 865 866 struct addrinfo * 867 allocaddrinfo(socklen_t addrlen) 868 { 869 struct addrinfo *ai; 870 871 ai = calloc(sizeof(struct addrinfo) + addrlen, 1); 872 if (ai) { 873 ai->ai_addr = (void *)(ai+1); 874 ai->ai_addrlen = ai->ai_addr->sa_len = addrlen; 875 } 876 877 return ai; 878 } 879 880 static struct addrinfo * 881 get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 882 { 883 char *p; 884 struct addrinfo *ai; 885 struct sockaddr *save; 886 887 _DIAGASSERT(pai != NULL); 888 _DIAGASSERT(afd != NULL); 889 _DIAGASSERT(addr != NULL); 890 891 ai = allocaddrinfo((socklen_t)afd->a_socklen); 892 if (ai == NULL) 893 return NULL; 894 895 save = ai->ai_addr; 896 memcpy(ai, pai, sizeof(struct addrinfo)); 897 898 /* since we just overwrote all of ai, we have 899 to restore ai_addr and ai_addrlen */ 900 ai->ai_addr = save; 901 ai->ai_addrlen = (socklen_t)afd->a_socklen; 902 903 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 904 p = (char *)(void *)(ai->ai_addr); 905 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 906 return ai; 907 } 908 909 static int 910 get_portmatch(const struct addrinfo *ai, const char *servname, 911 struct servent_data *svd) 912 { 913 914 _DIAGASSERT(ai != NULL); 915 /* servname may be NULL */ 916 917 return get_port(ai, servname, 1, svd); 918 } 919 920 static int 921 get_port(const struct addrinfo *ai, const char *servname, int matchonly, 922 struct servent_data *svd) 923 { 924 const char *proto; 925 struct servent *sp; 926 int port; 927 int allownumeric; 928 929 _DIAGASSERT(ai != NULL); 930 /* servname may be NULL */ 931 932 if (servname == NULL) 933 return 0; 934 switch (ai->ai_family) { 935 case AF_INET: 936 #ifdef AF_INET6 937 case AF_INET6: 938 #endif 939 break; 940 default: 941 return 0; 942 } 943 944 switch (ai->ai_socktype) { 945 case SOCK_RAW: 946 return EAI_SERVICE; 947 case SOCK_DGRAM: 948 case SOCK_STREAM: 949 allownumeric = 1; 950 break; 951 case ANY: 952 /* 953 * This was 0. It is now 1 so that queries specifying 954 * a NULL hint, or hint without socktype (but, hopefully, 955 * with protocol) and numeric address actually work. 956 */ 957 allownumeric = 1; 958 break; 959 default: 960 return EAI_SOCKTYPE; 961 } 962 963 port = str2number(servname); 964 if (port >= 0) { 965 if (!allownumeric) 966 return EAI_SERVICE; 967 if (port < 0 || port > 65535) 968 return EAI_SERVICE; 969 port = htons(port); 970 } else { 971 struct servent sv; 972 if (ai->ai_flags & AI_NUMERICSERV) 973 return EAI_NONAME; 974 975 switch (ai->ai_socktype) { 976 case SOCK_DGRAM: 977 proto = "udp"; 978 break; 979 case SOCK_STREAM: 980 proto = "tcp"; 981 break; 982 default: 983 proto = NULL; 984 break; 985 } 986 987 sp = getservbyname_r(servname, proto, &sv, svd); 988 if (sp == NULL) 989 return EAI_SERVICE; 990 port = sp->s_port; 991 } 992 993 if (!matchonly) { 994 switch (ai->ai_family) { 995 case AF_INET: 996 ((struct sockaddr_in *)(void *) 997 ai->ai_addr)->sin_port = port; 998 break; 999 #ifdef INET6 1000 case AF_INET6: 1001 ((struct sockaddr_in6 *)(void *) 1002 ai->ai_addr)->sin6_port = port; 1003 break; 1004 #endif 1005 } 1006 } 1007 1008 return 0; 1009 } 1010 1011 static const struct afd * 1012 find_afd(int af) 1013 { 1014 const struct afd *afd; 1015 1016 if (af == PF_UNSPEC) 1017 return NULL; 1018 for (afd = afdl; afd->a_af; afd++) { 1019 if (afd->a_af == af) 1020 return afd; 1021 } 1022 return NULL; 1023 } 1024 1025 /* 1026 * AI_ADDRCONFIG check: Build a mask containing a bit set for each address 1027 * family configured in the system. 1028 * 1029 */ 1030 static int 1031 addrconfig(uint64_t *mask) 1032 { 1033 struct ifaddrs *ifaddrs, *ifa; 1034 1035 if (getifaddrs(&ifaddrs) == -1) 1036 return -1; 1037 1038 *mask = 0; 1039 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) 1040 if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP)) { 1041 _DIAGASSERT(ifa->ifa_addr->sa_family < 64); 1042 *mask |= (uint64_t)1 << ifa->ifa_addr->sa_family; 1043 } 1044 1045 freeifaddrs(ifaddrs); 1046 return 0; 1047 } 1048 1049 #ifdef INET6 1050 /* convert a string to a scope identifier. XXX: IPv6 specific */ 1051 static int 1052 ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 1053 { 1054 u_long lscopeid; 1055 struct in6_addr *a6; 1056 char *ep; 1057 1058 _DIAGASSERT(scope != NULL); 1059 _DIAGASSERT(sin6 != NULL); 1060 _DIAGASSERT(scopeid != NULL); 1061 1062 a6 = &sin6->sin6_addr; 1063 1064 /* empty scopeid portion is invalid */ 1065 if (*scope == '\0') 1066 return -1; 1067 1068 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 1069 /* 1070 * We currently assume a one-to-one mapping between links 1071 * and interfaces, so we simply use interface indices for 1072 * like-local scopes. 1073 */ 1074 *scopeid = if_nametoindex(scope); 1075 if (*scopeid == 0) 1076 goto trynumeric; 1077 return 0; 1078 } 1079 1080 /* still unclear about literal, allow numeric only - placeholder */ 1081 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 1082 goto trynumeric; 1083 if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 1084 goto trynumeric; 1085 else 1086 goto trynumeric; /* global */ 1087 1088 /* try to convert to a numeric id as a last resort */ 1089 trynumeric: 1090 errno = 0; 1091 lscopeid = strtoul(scope, &ep, 10); 1092 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 1093 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 1094 return 0; 1095 else 1096 return -1; 1097 } 1098 #endif 1099 1100 /* code duplicate with gethnamaddr.c */ 1101 1102 static const char AskedForGot[] = 1103 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 1104 1105 static struct addrinfo * 1106 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 1107 const struct addrinfo *pai) 1108 { 1109 struct addrinfo sentinel, *cur; 1110 struct addrinfo ai; 1111 const struct afd *afd; 1112 char *canonname; 1113 const HEADER *hp; 1114 const u_char *cp; 1115 int n; 1116 const u_char *eom; 1117 char *bp, *ep; 1118 int type, class, ancount, qdcount; 1119 int haveanswer, had_error; 1120 char tbuf[MAXDNAME]; 1121 int (*name_ok) (const char *); 1122 char hostbuf[8*1024]; 1123 1124 _DIAGASSERT(answer != NULL); 1125 _DIAGASSERT(qname != NULL); 1126 _DIAGASSERT(pai != NULL); 1127 1128 memset(&sentinel, 0, sizeof(sentinel)); 1129 cur = &sentinel; 1130 1131 canonname = NULL; 1132 eom = answer->buf + anslen; 1133 switch (qtype) { 1134 case T_A: 1135 case T_AAAA: 1136 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 1137 name_ok = res_hnok; 1138 break; 1139 default: 1140 return NULL; /* XXX should be abort(); */ 1141 } 1142 /* 1143 * find first satisfactory answer 1144 */ 1145 hp = &answer->hdr; 1146 ancount = ntohs(hp->ancount); 1147 qdcount = ntohs(hp->qdcount); 1148 bp = hostbuf; 1149 ep = hostbuf + sizeof hostbuf; 1150 cp = answer->buf + HFIXEDSZ; 1151 if (qdcount != 1) { 1152 h_errno = NO_RECOVERY; 1153 return (NULL); 1154 } 1155 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1156 if ((n < 0) || !(*name_ok)(bp)) { 1157 h_errno = NO_RECOVERY; 1158 return (NULL); 1159 } 1160 cp += n + QFIXEDSZ; 1161 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 1162 /* res_send() has already verified that the query name is the 1163 * same as the one we sent; this just gets the expanded name 1164 * (i.e., with the succeeding search-domain tacked on). 1165 */ 1166 n = (int)strlen(bp) + 1; /* for the \0 */ 1167 if (n >= MAXHOSTNAMELEN) { 1168 h_errno = NO_RECOVERY; 1169 return (NULL); 1170 } 1171 canonname = bp; 1172 bp += n; 1173 /* The qname can be abbreviated, but h_name is now absolute. */ 1174 qname = canonname; 1175 } 1176 haveanswer = 0; 1177 had_error = 0; 1178 while (ancount-- > 0 && cp < eom && !had_error) { 1179 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1180 if ((n < 0) || !(*name_ok)(bp)) { 1181 had_error++; 1182 continue; 1183 } 1184 cp += n; /* name */ 1185 type = _getshort(cp); 1186 cp += INT16SZ; /* type */ 1187 class = _getshort(cp); 1188 cp += INT16SZ + INT32SZ; /* class, TTL */ 1189 n = _getshort(cp); 1190 cp += INT16SZ; /* len */ 1191 if (class != C_IN) { 1192 /* XXX - debug? syslog? */ 1193 cp += n; 1194 continue; /* XXX - had_error++ ? */ 1195 } 1196 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 1197 type == T_CNAME) { 1198 n = dn_expand(answer->buf, eom, cp, tbuf, (int)sizeof tbuf); 1199 if ((n < 0) || !(*name_ok)(tbuf)) { 1200 had_error++; 1201 continue; 1202 } 1203 cp += n; 1204 /* Get canonical name. */ 1205 n = (int)strlen(tbuf) + 1; /* for the \0 */ 1206 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 1207 had_error++; 1208 continue; 1209 } 1210 strlcpy(bp, tbuf, (size_t)(ep - bp)); 1211 canonname = bp; 1212 bp += n; 1213 continue; 1214 } 1215 if (qtype == T_ANY) { 1216 if (!(type == T_A || type == T_AAAA)) { 1217 cp += n; 1218 continue; 1219 } 1220 } else if (type != qtype) { 1221 if (type != T_KEY && type != T_SIG) { 1222 struct syslog_data sd = SYSLOG_DATA_INIT; 1223 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1224 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 1225 qname, p_class(C_IN), p_type(qtype), 1226 p_type(type)); 1227 } 1228 cp += n; 1229 continue; /* XXX - had_error++ ? */ 1230 } 1231 switch (type) { 1232 case T_A: 1233 case T_AAAA: 1234 if (strcasecmp(canonname, bp) != 0) { 1235 struct syslog_data sd = SYSLOG_DATA_INIT; 1236 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1237 AskedForGot, canonname, bp); 1238 cp += n; 1239 continue; /* XXX - had_error++ ? */ 1240 } 1241 if (type == T_A && n != INADDRSZ) { 1242 cp += n; 1243 continue; 1244 } 1245 if (type == T_AAAA && n != IN6ADDRSZ) { 1246 cp += n; 1247 continue; 1248 } 1249 if (type == T_AAAA) { 1250 struct in6_addr in6; 1251 memcpy(&in6, cp, IN6ADDRSZ); 1252 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 1253 cp += n; 1254 continue; 1255 } 1256 } 1257 if (!haveanswer) { 1258 int nn; 1259 1260 canonname = bp; 1261 nn = (int)strlen(bp) + 1; /* for the \0 */ 1262 bp += nn; 1263 } 1264 1265 /* don't overwrite pai */ 1266 ai = *pai; 1267 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 1268 afd = find_afd(ai.ai_family); 1269 if (afd == NULL) { 1270 cp += n; 1271 continue; 1272 } 1273 cur->ai_next = get_ai(&ai, afd, (const char *)cp); 1274 if (cur->ai_next == NULL) 1275 had_error++; 1276 while (cur && cur->ai_next) 1277 cur = cur->ai_next; 1278 cp += n; 1279 break; 1280 default: 1281 abort(); 1282 } 1283 if (!had_error) 1284 haveanswer++; 1285 } 1286 if (haveanswer) { 1287 if (!canonname) 1288 (void)get_canonname(pai, sentinel.ai_next, qname); 1289 else 1290 (void)get_canonname(pai, sentinel.ai_next, canonname); 1291 h_errno = NETDB_SUCCESS; 1292 return sentinel.ai_next; 1293 } 1294 1295 h_errno = NO_RECOVERY; 1296 return NULL; 1297 } 1298 1299 #define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr) 1300 #define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr) 1301 1302 static void 1303 aisort(struct addrinfo *s, res_state res) 1304 { 1305 struct addrinfo head, *t, *p; 1306 int i; 1307 1308 head.ai_next = NULL; 1309 t = &head; 1310 1311 for (i = 0; i < res->nsort; i++) { 1312 p = s; 1313 while (p->ai_next) { 1314 if ((p->ai_next->ai_family != AF_INET) 1315 || SORTMATCH(p, res->sort_list[i])) { 1316 t->ai_next = p->ai_next; 1317 t = t->ai_next; 1318 p->ai_next = p->ai_next->ai_next; 1319 } else { 1320 p = p->ai_next; 1321 } 1322 } 1323 } 1324 1325 /* add rest of list and reset s to the new list*/ 1326 t->ai_next = s->ai_next; 1327 s->ai_next = head.ai_next; 1328 } 1329 1330 /*ARGSUSED*/ 1331 static int 1332 _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 1333 { 1334 struct addrinfo *ai; 1335 querybuf *buf, *buf2; 1336 const char *name; 1337 const struct addrinfo *pai; 1338 struct addrinfo sentinel, *cur; 1339 struct res_target q, q2; 1340 res_state res; 1341 1342 name = va_arg(ap, char *); 1343 pai = va_arg(ap, const struct addrinfo *); 1344 1345 memset(&q, 0, sizeof(q)); 1346 memset(&q2, 0, sizeof(q2)); 1347 memset(&sentinel, 0, sizeof(sentinel)); 1348 cur = &sentinel; 1349 1350 buf = malloc(sizeof(*buf)); 1351 if (buf == NULL) { 1352 h_errno = NETDB_INTERNAL; 1353 return NS_NOTFOUND; 1354 } 1355 buf2 = malloc(sizeof(*buf2)); 1356 if (buf2 == NULL) { 1357 free(buf); 1358 h_errno = NETDB_INTERNAL; 1359 return NS_NOTFOUND; 1360 } 1361 1362 switch (pai->ai_family) { 1363 case AF_UNSPEC: 1364 /* prefer IPv6 */ 1365 q.name = name; 1366 q.qclass = C_IN; 1367 q.qtype = T_AAAA; 1368 q.answer = buf->buf; 1369 q.anslen = sizeof(buf->buf); 1370 q.next = &q2; 1371 q2.name = name; 1372 q2.qclass = C_IN; 1373 q2.qtype = T_A; 1374 q2.answer = buf2->buf; 1375 q2.anslen = sizeof(buf2->buf); 1376 break; 1377 case AF_INET: 1378 q.name = name; 1379 q.qclass = C_IN; 1380 q.qtype = T_A; 1381 q.answer = buf->buf; 1382 q.anslen = sizeof(buf->buf); 1383 break; 1384 case AF_INET6: 1385 q.name = name; 1386 q.qclass = C_IN; 1387 q.qtype = T_AAAA; 1388 q.answer = buf->buf; 1389 q.anslen = sizeof(buf->buf); 1390 break; 1391 default: 1392 free(buf); 1393 free(buf2); 1394 return NS_UNAVAIL; 1395 } 1396 1397 res = __res_get_state(); 1398 if (res == NULL) { 1399 free(buf); 1400 free(buf2); 1401 return NS_NOTFOUND; 1402 } 1403 1404 if (res_searchN(name, &q, res) < 0) { 1405 __res_put_state(res); 1406 free(buf); 1407 free(buf2); 1408 return NS_NOTFOUND; 1409 } 1410 ai = getanswer(buf, q.n, q.name, q.qtype, pai); 1411 if (ai) { 1412 cur->ai_next = ai; 1413 while (cur && cur->ai_next) 1414 cur = cur->ai_next; 1415 } 1416 if (q.next) { 1417 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); 1418 if (ai) 1419 cur->ai_next = ai; 1420 } 1421 free(buf); 1422 free(buf2); 1423 if (sentinel.ai_next == NULL) { 1424 __res_put_state(res); 1425 switch (h_errno) { 1426 case HOST_NOT_FOUND: 1427 return NS_NOTFOUND; 1428 case TRY_AGAIN: 1429 return NS_TRYAGAIN; 1430 default: 1431 return NS_UNAVAIL; 1432 } 1433 } 1434 1435 if (res->nsort) 1436 aisort(&sentinel, res); 1437 1438 __res_put_state(res); 1439 1440 *((struct addrinfo **)rv) = sentinel.ai_next; 1441 return NS_SUCCESS; 1442 } 1443 1444 static void 1445 _sethtent(FILE **hostf) 1446 { 1447 1448 if (!*hostf) 1449 *hostf = fopen(_PATH_HOSTS, "re"); 1450 else 1451 rewind(*hostf); 1452 } 1453 1454 static void 1455 _endhtent(FILE **hostf) 1456 { 1457 1458 if (*hostf) { 1459 (void) fclose(*hostf); 1460 *hostf = NULL; 1461 } 1462 } 1463 1464 static struct addrinfo * 1465 _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 1466 { 1467 char *p; 1468 char *cp, *tname, *cname; 1469 struct addrinfo hints, *res0, *res; 1470 int error; 1471 const char *addr; 1472 char hostbuf[8*1024]; 1473 1474 _DIAGASSERT(name != NULL); 1475 _DIAGASSERT(pai != NULL); 1476 1477 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re"))) 1478 return (NULL); 1479 again: 1480 if (!(p = fgets(hostbuf, (int)sizeof hostbuf, *hostf))) 1481 return (NULL); 1482 if (*p == '#') 1483 goto again; 1484 if (!(cp = strpbrk(p, "#\n"))) 1485 goto again; 1486 *cp = '\0'; 1487 if (!(cp = strpbrk(p, " \t"))) 1488 goto again; 1489 *cp++ = '\0'; 1490 addr = p; 1491 /* if this is not something we're looking for, skip it. */ 1492 cname = NULL; 1493 while (cp && *cp) { 1494 if (*cp == ' ' || *cp == '\t') { 1495 cp++; 1496 continue; 1497 } 1498 if (!cname) 1499 cname = cp; 1500 tname = cp; 1501 if ((cp = strpbrk(cp, " \t")) != NULL) 1502 *cp++ = '\0'; 1503 if (strcasecmp(name, tname) == 0) 1504 goto found; 1505 } 1506 goto again; 1507 1508 found: 1509 hints = *pai; 1510 hints.ai_flags = AI_NUMERICHOST; 1511 error = getaddrinfo(addr, NULL, &hints, &res0); 1512 if (error) 1513 goto again; 1514 for (res = res0; res; res = res->ai_next) { 1515 /* cover it up */ 1516 res->ai_flags = pai->ai_flags; 1517 1518 if (pai->ai_flags & AI_CANONNAME) { 1519 if (get_canonname(pai, res, cname) != 0) { 1520 freeaddrinfo(res0); 1521 goto again; 1522 } 1523 } 1524 } 1525 return res0; 1526 } 1527 1528 /*ARGSUSED*/ 1529 static int 1530 _files_getaddrinfo(void *rv, void *cb_data, va_list ap) 1531 { 1532 const char *name; 1533 const struct addrinfo *pai; 1534 struct addrinfo sentinel, *cur; 1535 struct addrinfo *p; 1536 #ifndef _REENTRANT 1537 static 1538 #endif 1539 FILE *hostf = NULL; 1540 1541 name = va_arg(ap, char *); 1542 pai = va_arg(ap, const struct addrinfo *); 1543 1544 memset(&sentinel, 0, sizeof(sentinel)); 1545 cur = &sentinel; 1546 1547 _sethtent(&hostf); 1548 while ((p = _gethtent(&hostf, name, pai)) != NULL) { 1549 cur->ai_next = p; 1550 while (cur && cur->ai_next) 1551 cur = cur->ai_next; 1552 } 1553 _endhtent(&hostf); 1554 1555 *((struct addrinfo **)rv) = sentinel.ai_next; 1556 if (sentinel.ai_next == NULL) 1557 return NS_NOTFOUND; 1558 return NS_SUCCESS; 1559 } 1560 1561 #ifdef YP 1562 /*ARGSUSED*/ 1563 static struct addrinfo * 1564 _yphostent(char *line, const struct addrinfo *pai) 1565 { 1566 struct addrinfo sentinel, *cur; 1567 struct addrinfo hints, *res, *res0; 1568 int error; 1569 char *p; 1570 const char *addr, *canonname; 1571 char *nextline; 1572 char *cp; 1573 1574 _DIAGASSERT(line != NULL); 1575 _DIAGASSERT(pai != NULL); 1576 1577 p = line; 1578 addr = canonname = NULL; 1579 1580 memset(&sentinel, 0, sizeof(sentinel)); 1581 cur = &sentinel; 1582 1583 nextline: 1584 /* terminate line */ 1585 cp = strchr(p, '\n'); 1586 if (cp) { 1587 *cp++ = '\0'; 1588 nextline = cp; 1589 } else 1590 nextline = NULL; 1591 1592 cp = strpbrk(p, " \t"); 1593 if (cp == NULL) { 1594 if (canonname == NULL) 1595 return (NULL); 1596 else 1597 goto done; 1598 } 1599 *cp++ = '\0'; 1600 1601 addr = p; 1602 1603 while (cp && *cp) { 1604 if (*cp == ' ' || *cp == '\t') { 1605 cp++; 1606 continue; 1607 } 1608 if (!canonname) 1609 canonname = cp; 1610 if ((cp = strpbrk(cp, " \t")) != NULL) 1611 *cp++ = '\0'; 1612 } 1613 1614 hints = *pai; 1615 hints.ai_flags = AI_NUMERICHOST; 1616 error = getaddrinfo(addr, NULL, &hints, &res0); 1617 if (error == 0) { 1618 for (res = res0; res; res = res->ai_next) { 1619 /* cover it up */ 1620 res->ai_flags = pai->ai_flags; 1621 1622 if (pai->ai_flags & AI_CANONNAME) 1623 (void)get_canonname(pai, res, canonname); 1624 } 1625 } else 1626 res0 = NULL; 1627 if (res0) { 1628 cur->ai_next = res0; 1629 while (cur->ai_next) 1630 cur = cur->ai_next; 1631 } 1632 1633 if (nextline) { 1634 p = nextline; 1635 goto nextline; 1636 } 1637 1638 done: 1639 return sentinel.ai_next; 1640 } 1641 1642 /*ARGSUSED*/ 1643 static int 1644 _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) 1645 { 1646 struct addrinfo sentinel, *cur; 1647 struct addrinfo *ai = NULL; 1648 char *ypbuf; 1649 int ypbuflen, r; 1650 const char *name; 1651 const struct addrinfo *pai; 1652 char *ypdomain; 1653 1654 if (_yp_check(&ypdomain) == 0) 1655 return NS_UNAVAIL; 1656 1657 name = va_arg(ap, char *); 1658 pai = va_arg(ap, const struct addrinfo *); 1659 1660 memset(&sentinel, 0, sizeof(sentinel)); 1661 cur = &sentinel; 1662 1663 /* hosts.byname is only for IPv4 (Solaris8) */ 1664 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { 1665 r = yp_match(ypdomain, "hosts.byname", name, 1666 (int)strlen(name), &ypbuf, &ypbuflen); 1667 if (r == 0) { 1668 struct addrinfo ai4; 1669 1670 ai4 = *pai; 1671 ai4.ai_family = AF_INET; 1672 ai = _yphostent(ypbuf, &ai4); 1673 if (ai) { 1674 cur->ai_next = ai; 1675 while (cur && cur->ai_next) 1676 cur = cur->ai_next; 1677 } 1678 } 1679 free(ypbuf); 1680 } 1681 1682 /* ipnodes.byname can hold both IPv4/v6 */ 1683 r = yp_match(ypdomain, "ipnodes.byname", name, 1684 (int)strlen(name), &ypbuf, &ypbuflen); 1685 if (r == 0) { 1686 ai = _yphostent(ypbuf, pai); 1687 if (ai) 1688 cur->ai_next = ai; 1689 free(ypbuf); 1690 } 1691 1692 if (sentinel.ai_next == NULL) { 1693 h_errno = HOST_NOT_FOUND; 1694 return NS_NOTFOUND; 1695 } 1696 *((struct addrinfo **)rv) = sentinel.ai_next; 1697 return NS_SUCCESS; 1698 } 1699 #endif 1700 1701 /* resolver logic */ 1702 1703 /* 1704 * Formulate a normal query, send, and await answer. 1705 * Returned answer is placed in supplied buffer "answer". 1706 * Perform preliminary check of answer, returning success only 1707 * if no error is indicated and the answer count is nonzero. 1708 * Return the size of the response on success, -1 on error. 1709 * Error number is left in h_errno. 1710 * 1711 * Caller must parse answer and determine whether it answers the question. 1712 */ 1713 static int 1714 res_queryN(const char *name, /* domain name */ struct res_target *target, 1715 res_state res) 1716 { 1717 u_char buf[MAXPACKET]; 1718 HEADER *hp; 1719 int n; 1720 struct res_target *t; 1721 int rcode; 1722 int ancount; 1723 1724 _DIAGASSERT(name != NULL); 1725 /* XXX: target may be NULL??? */ 1726 1727 rcode = NOERROR; 1728 ancount = 0; 1729 1730 for (t = target; t; t = t->next) { 1731 int class, type; 1732 u_char *answer; 1733 int anslen; 1734 1735 hp = (HEADER *)(void *)t->answer; 1736 hp->rcode = NOERROR; /* default */ 1737 1738 /* make it easier... */ 1739 class = t->qclass; 1740 type = t->qtype; 1741 answer = t->answer; 1742 anslen = t->anslen; 1743 #ifdef DEBUG 1744 if (res->options & RES_DEBUG) 1745 printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 1746 #endif 1747 1748 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, 1749 buf, (int)sizeof(buf)); 1750 #ifdef RES_USE_EDNS0 1751 if (n > 0 && (res->options & RES_USE_EDNS0) != 0) 1752 n = res_nopt(res, n, buf, (int)sizeof(buf), anslen); 1753 #endif 1754 if (n <= 0) { 1755 #ifdef DEBUG 1756 if (res->options & RES_DEBUG) 1757 printf(";; res_nquery: mkquery failed\n"); 1758 #endif 1759 h_errno = NO_RECOVERY; 1760 return n; 1761 } 1762 n = res_nsend(res, buf, n, answer, anslen); 1763 #if 0 1764 if (n < 0) { 1765 #ifdef DEBUG 1766 if (res->options & RES_DEBUG) 1767 printf(";; res_query: send error\n"); 1768 #endif 1769 h_errno = TRY_AGAIN; 1770 return n; 1771 } 1772 #endif 1773 1774 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 1775 rcode = hp->rcode; /* record most recent error */ 1776 #ifdef DEBUG 1777 if (res->options & RES_DEBUG) 1778 printf(";; rcode = %u, ancount=%u\n", hp->rcode, 1779 ntohs(hp->ancount)); 1780 #endif 1781 continue; 1782 } 1783 1784 ancount += ntohs(hp->ancount); 1785 1786 t->n = n; 1787 } 1788 1789 if (ancount == 0) { 1790 switch (rcode) { 1791 case NXDOMAIN: 1792 h_errno = HOST_NOT_FOUND; 1793 break; 1794 case SERVFAIL: 1795 h_errno = TRY_AGAIN; 1796 break; 1797 case NOERROR: 1798 h_errno = NO_DATA; 1799 break; 1800 case FORMERR: 1801 case NOTIMP: 1802 case REFUSED: 1803 default: 1804 h_errno = NO_RECOVERY; 1805 break; 1806 } 1807 return -1; 1808 } 1809 return ancount; 1810 } 1811 1812 /* 1813 * Formulate a normal query, send, and retrieve answer in supplied buffer. 1814 * Return the size of the response on success, -1 on error. 1815 * If enabled, implement search rules until answer or unrecoverable failure 1816 * is detected. Error code, if any, is left in h_errno. 1817 */ 1818 static int 1819 res_searchN(const char *name, struct res_target *target, res_state res) 1820 { 1821 const char *cp, * const *domain; 1822 HEADER *hp; 1823 u_int dots; 1824 int trailing_dot, ret, saved_herrno; 1825 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 1826 1827 _DIAGASSERT(name != NULL); 1828 _DIAGASSERT(target != NULL); 1829 1830 hp = (HEADER *)(void *)target->answer; /*XXX*/ 1831 1832 errno = 0; 1833 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 1834 dots = 0; 1835 for (cp = name; *cp; cp++) 1836 dots += (*cp == '.'); 1837 trailing_dot = 0; 1838 if (cp > name && *--cp == '.') 1839 trailing_dot++; 1840 1841 /* 1842 * if there aren't any dots, it could be a user-level alias 1843 */ 1844 if (!dots && (cp = __hostalias(name)) != NULL) { 1845 ret = res_queryN(cp, target, res); 1846 return ret; 1847 } 1848 1849 /* 1850 * If there are dots in the name already, let's just give it a try 1851 * 'as is'. The threshold can be set with the "ndots" option. 1852 */ 1853 saved_herrno = -1; 1854 if (dots >= res->ndots) { 1855 ret = res_querydomainN(name, NULL, target, res); 1856 if (ret > 0) 1857 return (ret); 1858 saved_herrno = h_errno; 1859 tried_as_is++; 1860 } 1861 1862 /* 1863 * We do at least one level of search if 1864 * - there is no dot and RES_DEFNAME is set, or 1865 * - there is at least one dot, there is no trailing dot, 1866 * and RES_DNSRCH is set. 1867 */ 1868 if ((!dots && (res->options & RES_DEFNAMES)) || 1869 (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 1870 int done = 0; 1871 1872 for (domain = (const char * const *)res->dnsrch; 1873 *domain && !done; 1874 domain++) { 1875 1876 ret = res_querydomainN(name, *domain, target, res); 1877 if (ret > 0) 1878 return ret; 1879 1880 /* 1881 * If no server present, give up. 1882 * If name isn't found in this domain, 1883 * keep trying higher domains in the search list 1884 * (if that's enabled). 1885 * On a NO_DATA error, keep trying, otherwise 1886 * a wildcard entry of another type could keep us 1887 * from finding this entry higher in the domain. 1888 * If we get some other error (negative answer or 1889 * server failure), then stop searching up, 1890 * but try the input name below in case it's 1891 * fully-qualified. 1892 */ 1893 if (errno == ECONNREFUSED) { 1894 h_errno = TRY_AGAIN; 1895 return -1; 1896 } 1897 1898 switch (h_errno) { 1899 case NO_DATA: 1900 got_nodata++; 1901 /* FALLTHROUGH */ 1902 case HOST_NOT_FOUND: 1903 /* keep trying */ 1904 break; 1905 case TRY_AGAIN: 1906 if (hp->rcode == SERVFAIL) { 1907 /* try next search element, if any */ 1908 got_servfail++; 1909 break; 1910 } 1911 /* FALLTHROUGH */ 1912 default: 1913 /* anything else implies that we're done */ 1914 done++; 1915 } 1916 /* 1917 * if we got here for some reason other than DNSRCH, 1918 * we only wanted one iteration of the loop, so stop. 1919 */ 1920 if (!(res->options & RES_DNSRCH)) 1921 done++; 1922 } 1923 } 1924 1925 /* 1926 * if we have not already tried the name "as is", do that now. 1927 * note that we do this regardless of how many dots were in the 1928 * name or whether it ends with a dot. 1929 */ 1930 if (!tried_as_is) { 1931 ret = res_querydomainN(name, NULL, target, res); 1932 if (ret > 0) 1933 return ret; 1934 } 1935 1936 /* 1937 * if we got here, we didn't satisfy the search. 1938 * if we did an initial full query, return that query's h_errno 1939 * (note that we wouldn't be here if that query had succeeded). 1940 * else if we ever got a nodata, send that back as the reason. 1941 * else send back meaningless h_errno, that being the one from 1942 * the last DNSRCH we did. 1943 */ 1944 if (saved_herrno != -1) 1945 h_errno = saved_herrno; 1946 else if (got_nodata) 1947 h_errno = NO_DATA; 1948 else if (got_servfail) 1949 h_errno = TRY_AGAIN; 1950 return -1; 1951 } 1952 1953 /* 1954 * Perform a call on res_query on the concatenation of name and domain, 1955 * removing a trailing dot from name if domain is NULL. 1956 */ 1957 static int 1958 res_querydomainN(const char *name, const char *domain, 1959 struct res_target *target, res_state res) 1960 { 1961 char nbuf[MAXDNAME]; 1962 const char *longname = nbuf; 1963 size_t n, d; 1964 1965 _DIAGASSERT(name != NULL); 1966 /* XXX: target may be NULL??? */ 1967 1968 #ifdef DEBUG 1969 if (res->options & RES_DEBUG) 1970 printf(";; res_querydomain(%s, %s)\n", 1971 name, domain?domain:"<Nil>"); 1972 #endif 1973 if (domain == NULL) { 1974 /* 1975 * Check for trailing '.'; 1976 * copy without '.' if present. 1977 */ 1978 n = strlen(name); 1979 if (n + 1 > sizeof(nbuf)) { 1980 h_errno = NO_RECOVERY; 1981 return -1; 1982 } 1983 if (n > 0 && name[--n] == '.') { 1984 strncpy(nbuf, name, n); 1985 nbuf[n] = '\0'; 1986 } else 1987 longname = name; 1988 } else { 1989 n = strlen(name); 1990 d = strlen(domain); 1991 if (n + 1 + d + 1 > sizeof(nbuf)) { 1992 h_errno = NO_RECOVERY; 1993 return -1; 1994 } 1995 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 1996 } 1997 return res_queryN(longname, target, res); 1998 } 1999