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 #ifndef __minix 875 ai->ai_addrlen = ai->ai_addr->sa_len = addrlen; 876 #else /* __minix */ 877 ai->ai_addrlen = addrlen; 878 #endif 879 880 } 881 882 return ai; 883 } 884 885 static struct addrinfo * 886 get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 887 { 888 char *p; 889 struct addrinfo *ai; 890 struct sockaddr *save; 891 892 _DIAGASSERT(pai != NULL); 893 _DIAGASSERT(afd != NULL); 894 _DIAGASSERT(addr != NULL); 895 896 ai = allocaddrinfo((socklen_t)afd->a_socklen); 897 if (ai == NULL) 898 return NULL; 899 900 save = ai->ai_addr; 901 memcpy(ai, pai, sizeof(struct addrinfo)); 902 903 /* since we just overwrote all of ai, we have 904 to restore ai_addr and ai_addrlen */ 905 ai->ai_addr = save; 906 ai->ai_addrlen = (socklen_t)afd->a_socklen; 907 908 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 909 p = (char *)(void *)(ai->ai_addr); 910 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 911 return ai; 912 } 913 914 static int 915 get_portmatch(const struct addrinfo *ai, const char *servname, 916 struct servent_data *svd) 917 { 918 919 _DIAGASSERT(ai != NULL); 920 /* servname may be NULL */ 921 922 return get_port(ai, servname, 1, svd); 923 } 924 925 static int 926 get_port(const struct addrinfo *ai, const char *servname, int matchonly, 927 struct servent_data *svd) 928 { 929 const char *proto; 930 struct servent *sp; 931 int port; 932 int allownumeric; 933 934 _DIAGASSERT(ai != NULL); 935 /* servname may be NULL */ 936 937 if (servname == NULL) 938 return 0; 939 switch (ai->ai_family) { 940 case AF_INET: 941 #ifdef AF_INET6 942 case AF_INET6: 943 #endif 944 break; 945 default: 946 return 0; 947 } 948 949 switch (ai->ai_socktype) { 950 case SOCK_RAW: 951 return EAI_SERVICE; 952 case SOCK_DGRAM: 953 case SOCK_STREAM: 954 allownumeric = 1; 955 break; 956 case ANY: 957 /* 958 * This was 0. It is now 1 so that queries specifying 959 * a NULL hint, or hint without socktype (but, hopefully, 960 * with protocol) and numeric address actually work. 961 */ 962 allownumeric = 1; 963 break; 964 default: 965 return EAI_SOCKTYPE; 966 } 967 968 port = str2number(servname); 969 if (port >= 0) { 970 if (!allownumeric) 971 return EAI_SERVICE; 972 if (port < 0 || port > 65535) 973 return EAI_SERVICE; 974 port = htons(port); 975 } else { 976 struct servent sv; 977 if (ai->ai_flags & AI_NUMERICSERV) 978 return EAI_NONAME; 979 980 switch (ai->ai_socktype) { 981 case SOCK_DGRAM: 982 proto = "udp"; 983 break; 984 case SOCK_STREAM: 985 proto = "tcp"; 986 break; 987 default: 988 proto = NULL; 989 break; 990 } 991 992 sp = getservbyname_r(servname, proto, &sv, svd); 993 if (sp == NULL) 994 return EAI_SERVICE; 995 port = sp->s_port; 996 } 997 998 if (!matchonly) { 999 switch (ai->ai_family) { 1000 case AF_INET: 1001 ((struct sockaddr_in *)(void *) 1002 ai->ai_addr)->sin_port = port; 1003 break; 1004 #ifdef INET6 1005 case AF_INET6: 1006 ((struct sockaddr_in6 *)(void *) 1007 ai->ai_addr)->sin6_port = port; 1008 break; 1009 #endif 1010 } 1011 } 1012 1013 return 0; 1014 } 1015 1016 static const struct afd * 1017 find_afd(int af) 1018 { 1019 const struct afd *afd; 1020 1021 if (af == PF_UNSPEC) 1022 return NULL; 1023 for (afd = afdl; afd->a_af; afd++) { 1024 if (afd->a_af == af) 1025 return afd; 1026 } 1027 return NULL; 1028 } 1029 1030 /* 1031 * AI_ADDRCONFIG check: Build a mask containing a bit set for each address 1032 * family configured in the system. 1033 * 1034 */ 1035 static int 1036 addrconfig(uint64_t *mask) 1037 { 1038 struct ifaddrs *ifaddrs, *ifa; 1039 1040 if (getifaddrs(&ifaddrs) == -1) 1041 return -1; 1042 1043 *mask = 0; 1044 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) 1045 if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP)) { 1046 _DIAGASSERT(ifa->ifa_addr->sa_family < 64); 1047 *mask |= (uint64_t)1 << ifa->ifa_addr->sa_family; 1048 } 1049 1050 freeifaddrs(ifaddrs); 1051 return 0; 1052 } 1053 1054 #ifdef INET6 1055 /* convert a string to a scope identifier. XXX: IPv6 specific */ 1056 static int 1057 ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 1058 { 1059 u_long lscopeid; 1060 struct in6_addr *a6; 1061 char *ep; 1062 1063 _DIAGASSERT(scope != NULL); 1064 _DIAGASSERT(sin6 != NULL); 1065 _DIAGASSERT(scopeid != NULL); 1066 1067 a6 = &sin6->sin6_addr; 1068 1069 /* empty scopeid portion is invalid */ 1070 if (*scope == '\0') 1071 return -1; 1072 1073 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 1074 /* 1075 * We currently assume a one-to-one mapping between links 1076 * and interfaces, so we simply use interface indices for 1077 * like-local scopes. 1078 */ 1079 *scopeid = if_nametoindex(scope); 1080 if (*scopeid == 0) 1081 goto trynumeric; 1082 return 0; 1083 } 1084 1085 /* still unclear about literal, allow numeric only - placeholder */ 1086 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 1087 goto trynumeric; 1088 if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 1089 goto trynumeric; 1090 else 1091 goto trynumeric; /* global */ 1092 1093 /* try to convert to a numeric id as a last resort */ 1094 trynumeric: 1095 errno = 0; 1096 lscopeid = strtoul(scope, &ep, 10); 1097 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 1098 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 1099 return 0; 1100 else 1101 return -1; 1102 } 1103 #endif 1104 1105 /* code duplicate with gethnamaddr.c */ 1106 1107 static const char AskedForGot[] = 1108 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 1109 1110 static struct addrinfo * 1111 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 1112 const struct addrinfo *pai) 1113 { 1114 struct addrinfo sentinel, *cur; 1115 struct addrinfo ai; 1116 const struct afd *afd; 1117 char *canonname; 1118 const HEADER *hp; 1119 const u_char *cp; 1120 int n; 1121 const u_char *eom; 1122 char *bp, *ep; 1123 int type, class, ancount, qdcount; 1124 int haveanswer, had_error; 1125 char tbuf[MAXDNAME]; 1126 int (*name_ok) (const char *); 1127 char hostbuf[8*1024]; 1128 1129 _DIAGASSERT(answer != NULL); 1130 _DIAGASSERT(qname != NULL); 1131 _DIAGASSERT(pai != NULL); 1132 1133 memset(&sentinel, 0, sizeof(sentinel)); 1134 cur = &sentinel; 1135 1136 canonname = NULL; 1137 eom = answer->buf + anslen; 1138 switch (qtype) { 1139 case T_A: 1140 case T_AAAA: 1141 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 1142 name_ok = res_hnok; 1143 break; 1144 default: 1145 return NULL; /* XXX should be abort(); */ 1146 } 1147 /* 1148 * find first satisfactory answer 1149 */ 1150 hp = &answer->hdr; 1151 ancount = ntohs(hp->ancount); 1152 qdcount = ntohs(hp->qdcount); 1153 bp = hostbuf; 1154 ep = hostbuf + sizeof hostbuf; 1155 cp = answer->buf + HFIXEDSZ; 1156 if (qdcount != 1) { 1157 h_errno = NO_RECOVERY; 1158 return (NULL); 1159 } 1160 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1161 if ((n < 0) || !(*name_ok)(bp)) { 1162 h_errno = NO_RECOVERY; 1163 return (NULL); 1164 } 1165 cp += n + QFIXEDSZ; 1166 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 1167 /* res_send() has already verified that the query name is the 1168 * same as the one we sent; this just gets the expanded name 1169 * (i.e., with the succeeding search-domain tacked on). 1170 */ 1171 n = (int)strlen(bp) + 1; /* for the \0 */ 1172 if (n >= MAXHOSTNAMELEN) { 1173 h_errno = NO_RECOVERY; 1174 return (NULL); 1175 } 1176 canonname = bp; 1177 bp += n; 1178 /* The qname can be abbreviated, but h_name is now absolute. */ 1179 qname = canonname; 1180 } 1181 haveanswer = 0; 1182 had_error = 0; 1183 while (ancount-- > 0 && cp < eom && !had_error) { 1184 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1185 if ((n < 0) || !(*name_ok)(bp)) { 1186 had_error++; 1187 continue; 1188 } 1189 cp += n; /* name */ 1190 type = _getshort(cp); 1191 cp += INT16SZ; /* type */ 1192 class = _getshort(cp); 1193 cp += INT16SZ + INT32SZ; /* class, TTL */ 1194 n = _getshort(cp); 1195 cp += INT16SZ; /* len */ 1196 if (class != C_IN) { 1197 /* XXX - debug? syslog? */ 1198 cp += n; 1199 continue; /* XXX - had_error++ ? */ 1200 } 1201 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 1202 type == T_CNAME) { 1203 n = dn_expand(answer->buf, eom, cp, tbuf, (int)sizeof tbuf); 1204 if ((n < 0) || !(*name_ok)(tbuf)) { 1205 had_error++; 1206 continue; 1207 } 1208 cp += n; 1209 /* Get canonical name. */ 1210 n = (int)strlen(tbuf) + 1; /* for the \0 */ 1211 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 1212 had_error++; 1213 continue; 1214 } 1215 strlcpy(bp, tbuf, (size_t)(ep - bp)); 1216 canonname = bp; 1217 bp += n; 1218 continue; 1219 } 1220 if (qtype == T_ANY) { 1221 if (!(type == T_A || type == T_AAAA)) { 1222 cp += n; 1223 continue; 1224 } 1225 } else if (type != qtype) { 1226 if (type != T_KEY && type != T_SIG) { 1227 struct syslog_data sd = SYSLOG_DATA_INIT; 1228 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1229 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 1230 qname, p_class(C_IN), p_type(qtype), 1231 p_type(type)); 1232 } 1233 cp += n; 1234 continue; /* XXX - had_error++ ? */ 1235 } 1236 switch (type) { 1237 case T_A: 1238 case T_AAAA: 1239 if (strcasecmp(canonname, bp) != 0) { 1240 struct syslog_data sd = SYSLOG_DATA_INIT; 1241 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1242 AskedForGot, canonname, bp); 1243 cp += n; 1244 continue; /* XXX - had_error++ ? */ 1245 } 1246 if (type == T_A && n != INADDRSZ) { 1247 cp += n; 1248 continue; 1249 } 1250 if (type == T_AAAA && n != IN6ADDRSZ) { 1251 cp += n; 1252 continue; 1253 } 1254 if (type == T_AAAA) { 1255 struct in6_addr in6; 1256 memcpy(&in6, cp, IN6ADDRSZ); 1257 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 1258 cp += n; 1259 continue; 1260 } 1261 } 1262 if (!haveanswer) { 1263 int nn; 1264 1265 canonname = bp; 1266 nn = (int)strlen(bp) + 1; /* for the \0 */ 1267 bp += nn; 1268 } 1269 1270 /* don't overwrite pai */ 1271 ai = *pai; 1272 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 1273 afd = find_afd(ai.ai_family); 1274 if (afd == NULL) { 1275 cp += n; 1276 continue; 1277 } 1278 cur->ai_next = get_ai(&ai, afd, (const char *)cp); 1279 if (cur->ai_next == NULL) 1280 had_error++; 1281 while (cur && cur->ai_next) 1282 cur = cur->ai_next; 1283 cp += n; 1284 break; 1285 default: 1286 abort(); 1287 } 1288 if (!had_error) 1289 haveanswer++; 1290 } 1291 if (haveanswer) { 1292 if (!canonname) 1293 (void)get_canonname(pai, sentinel.ai_next, qname); 1294 else 1295 (void)get_canonname(pai, sentinel.ai_next, canonname); 1296 h_errno = NETDB_SUCCESS; 1297 return sentinel.ai_next; 1298 } 1299 1300 h_errno = NO_RECOVERY; 1301 return NULL; 1302 } 1303 1304 #define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr) 1305 #define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr) 1306 1307 static void 1308 aisort(struct addrinfo *s, res_state res) 1309 { 1310 struct addrinfo head, *t, *p; 1311 int i; 1312 1313 head.ai_next = NULL; 1314 t = &head; 1315 1316 for (i = 0; i < res->nsort; i++) { 1317 p = s; 1318 while (p->ai_next) { 1319 if ((p->ai_next->ai_family != AF_INET) 1320 || SORTMATCH(p, res->sort_list[i])) { 1321 t->ai_next = p->ai_next; 1322 t = t->ai_next; 1323 p->ai_next = p->ai_next->ai_next; 1324 } else { 1325 p = p->ai_next; 1326 } 1327 } 1328 } 1329 1330 /* add rest of list and reset s to the new list*/ 1331 t->ai_next = s->ai_next; 1332 s->ai_next = head.ai_next; 1333 } 1334 1335 /*ARGSUSED*/ 1336 static int 1337 _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 1338 { 1339 struct addrinfo *ai; 1340 querybuf *buf, *buf2; 1341 const char *name; 1342 const struct addrinfo *pai; 1343 struct addrinfo sentinel, *cur; 1344 struct res_target q, q2; 1345 res_state res; 1346 1347 name = va_arg(ap, char *); 1348 pai = va_arg(ap, const struct addrinfo *); 1349 1350 memset(&q, 0, sizeof(q)); 1351 memset(&q2, 0, sizeof(q2)); 1352 memset(&sentinel, 0, sizeof(sentinel)); 1353 cur = &sentinel; 1354 1355 buf = malloc(sizeof(*buf)); 1356 if (buf == NULL) { 1357 h_errno = NETDB_INTERNAL; 1358 return NS_NOTFOUND; 1359 } 1360 buf2 = malloc(sizeof(*buf2)); 1361 if (buf2 == NULL) { 1362 free(buf); 1363 h_errno = NETDB_INTERNAL; 1364 return NS_NOTFOUND; 1365 } 1366 1367 switch (pai->ai_family) { 1368 case AF_UNSPEC: 1369 /* prefer IPv6 */ 1370 q.name = name; 1371 q.qclass = C_IN; 1372 q.qtype = T_AAAA; 1373 q.answer = buf->buf; 1374 q.anslen = sizeof(buf->buf); 1375 q.next = &q2; 1376 q2.name = name; 1377 q2.qclass = C_IN; 1378 q2.qtype = T_A; 1379 q2.answer = buf2->buf; 1380 q2.anslen = sizeof(buf2->buf); 1381 break; 1382 case AF_INET: 1383 q.name = name; 1384 q.qclass = C_IN; 1385 q.qtype = T_A; 1386 q.answer = buf->buf; 1387 q.anslen = sizeof(buf->buf); 1388 break; 1389 case AF_INET6: 1390 q.name = name; 1391 q.qclass = C_IN; 1392 q.qtype = T_AAAA; 1393 q.answer = buf->buf; 1394 q.anslen = sizeof(buf->buf); 1395 break; 1396 default: 1397 free(buf); 1398 free(buf2); 1399 return NS_UNAVAIL; 1400 } 1401 1402 res = __res_get_state(); 1403 if (res == NULL) { 1404 free(buf); 1405 free(buf2); 1406 return NS_NOTFOUND; 1407 } 1408 1409 if (res_searchN(name, &q, res) < 0) { 1410 __res_put_state(res); 1411 free(buf); 1412 free(buf2); 1413 return NS_NOTFOUND; 1414 } 1415 ai = getanswer(buf, q.n, q.name, q.qtype, pai); 1416 if (ai) { 1417 cur->ai_next = ai; 1418 while (cur && cur->ai_next) 1419 cur = cur->ai_next; 1420 } 1421 if (q.next) { 1422 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); 1423 if (ai) 1424 cur->ai_next = ai; 1425 } 1426 free(buf); 1427 free(buf2); 1428 if (sentinel.ai_next == NULL) { 1429 __res_put_state(res); 1430 switch (h_errno) { 1431 case HOST_NOT_FOUND: 1432 return NS_NOTFOUND; 1433 case TRY_AGAIN: 1434 return NS_TRYAGAIN; 1435 default: 1436 return NS_UNAVAIL; 1437 } 1438 } 1439 1440 if (res->nsort) 1441 aisort(&sentinel, res); 1442 1443 __res_put_state(res); 1444 1445 *((struct addrinfo **)rv) = sentinel.ai_next; 1446 return NS_SUCCESS; 1447 } 1448 1449 static void 1450 _sethtent(FILE **hostf) 1451 { 1452 1453 if (!*hostf) 1454 *hostf = fopen(_PATH_HOSTS, "re"); 1455 else 1456 rewind(*hostf); 1457 } 1458 1459 static void 1460 _endhtent(FILE **hostf) 1461 { 1462 1463 if (*hostf) { 1464 (void) fclose(*hostf); 1465 *hostf = NULL; 1466 } 1467 } 1468 1469 static struct addrinfo * 1470 _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 1471 { 1472 char *p; 1473 char *cp, *tname, *cname; 1474 struct addrinfo hints, *res0, *res; 1475 int error; 1476 const char *addr; 1477 char hostbuf[8*1024]; 1478 1479 _DIAGASSERT(name != NULL); 1480 _DIAGASSERT(pai != NULL); 1481 1482 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re"))) 1483 return (NULL); 1484 again: 1485 if (!(p = fgets(hostbuf, (int)sizeof hostbuf, *hostf))) 1486 return (NULL); 1487 if (*p == '#') 1488 goto again; 1489 if (!(cp = strpbrk(p, "#\n"))) 1490 goto again; 1491 *cp = '\0'; 1492 if (!(cp = strpbrk(p, " \t"))) 1493 goto again; 1494 *cp++ = '\0'; 1495 addr = p; 1496 /* if this is not something we're looking for, skip it. */ 1497 cname = NULL; 1498 while (cp && *cp) { 1499 if (*cp == ' ' || *cp == '\t') { 1500 cp++; 1501 continue; 1502 } 1503 if (!cname) 1504 cname = cp; 1505 tname = cp; 1506 if ((cp = strpbrk(cp, " \t")) != NULL) 1507 *cp++ = '\0'; 1508 if (strcasecmp(name, tname) == 0) 1509 goto found; 1510 } 1511 goto again; 1512 1513 found: 1514 hints = *pai; 1515 hints.ai_flags = AI_NUMERICHOST; 1516 error = getaddrinfo(addr, NULL, &hints, &res0); 1517 if (error) 1518 goto again; 1519 for (res = res0; res; res = res->ai_next) { 1520 /* cover it up */ 1521 res->ai_flags = pai->ai_flags; 1522 1523 if (pai->ai_flags & AI_CANONNAME) { 1524 if (get_canonname(pai, res, cname) != 0) { 1525 freeaddrinfo(res0); 1526 goto again; 1527 } 1528 } 1529 } 1530 return res0; 1531 } 1532 1533 /*ARGSUSED*/ 1534 static int 1535 _files_getaddrinfo(void *rv, void *cb_data, va_list ap) 1536 { 1537 const char *name; 1538 const struct addrinfo *pai; 1539 struct addrinfo sentinel, *cur; 1540 struct addrinfo *p; 1541 #ifndef _REENTRANT 1542 static 1543 #endif 1544 FILE *hostf = NULL; 1545 1546 name = va_arg(ap, char *); 1547 pai = va_arg(ap, const struct addrinfo *); 1548 1549 memset(&sentinel, 0, sizeof(sentinel)); 1550 cur = &sentinel; 1551 1552 _sethtent(&hostf); 1553 while ((p = _gethtent(&hostf, name, pai)) != NULL) { 1554 cur->ai_next = p; 1555 while (cur && cur->ai_next) 1556 cur = cur->ai_next; 1557 } 1558 _endhtent(&hostf); 1559 1560 *((struct addrinfo **)rv) = sentinel.ai_next; 1561 if (sentinel.ai_next == NULL) 1562 return NS_NOTFOUND; 1563 return NS_SUCCESS; 1564 } 1565 1566 #ifdef YP 1567 /*ARGSUSED*/ 1568 static struct addrinfo * 1569 _yphostent(char *line, const struct addrinfo *pai) 1570 { 1571 struct addrinfo sentinel, *cur; 1572 struct addrinfo hints, *res, *res0; 1573 int error; 1574 char *p; 1575 const char *addr, *canonname; 1576 char *nextline; 1577 char *cp; 1578 1579 _DIAGASSERT(line != NULL); 1580 _DIAGASSERT(pai != NULL); 1581 1582 p = line; 1583 addr = canonname = NULL; 1584 1585 memset(&sentinel, 0, sizeof(sentinel)); 1586 cur = &sentinel; 1587 1588 nextline: 1589 /* terminate line */ 1590 cp = strchr(p, '\n'); 1591 if (cp) { 1592 *cp++ = '\0'; 1593 nextline = cp; 1594 } else 1595 nextline = NULL; 1596 1597 cp = strpbrk(p, " \t"); 1598 if (cp == NULL) { 1599 if (canonname == NULL) 1600 return (NULL); 1601 else 1602 goto done; 1603 } 1604 *cp++ = '\0'; 1605 1606 addr = p; 1607 1608 while (cp && *cp) { 1609 if (*cp == ' ' || *cp == '\t') { 1610 cp++; 1611 continue; 1612 } 1613 if (!canonname) 1614 canonname = cp; 1615 if ((cp = strpbrk(cp, " \t")) != NULL) 1616 *cp++ = '\0'; 1617 } 1618 1619 hints = *pai; 1620 hints.ai_flags = AI_NUMERICHOST; 1621 error = getaddrinfo(addr, NULL, &hints, &res0); 1622 if (error == 0) { 1623 for (res = res0; res; res = res->ai_next) { 1624 /* cover it up */ 1625 res->ai_flags = pai->ai_flags; 1626 1627 if (pai->ai_flags & AI_CANONNAME) 1628 (void)get_canonname(pai, res, canonname); 1629 } 1630 } else 1631 res0 = NULL; 1632 if (res0) { 1633 cur->ai_next = res0; 1634 while (cur->ai_next) 1635 cur = cur->ai_next; 1636 } 1637 1638 if (nextline) { 1639 p = nextline; 1640 goto nextline; 1641 } 1642 1643 done: 1644 return sentinel.ai_next; 1645 } 1646 1647 /*ARGSUSED*/ 1648 static int 1649 _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) 1650 { 1651 struct addrinfo sentinel, *cur; 1652 struct addrinfo *ai = NULL; 1653 char *ypbuf; 1654 int ypbuflen, r; 1655 const char *name; 1656 const struct addrinfo *pai; 1657 char *ypdomain; 1658 1659 if (_yp_check(&ypdomain) == 0) 1660 return NS_UNAVAIL; 1661 1662 name = va_arg(ap, char *); 1663 pai = va_arg(ap, const struct addrinfo *); 1664 1665 memset(&sentinel, 0, sizeof(sentinel)); 1666 cur = &sentinel; 1667 1668 /* hosts.byname is only for IPv4 (Solaris8) */ 1669 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { 1670 r = yp_match(ypdomain, "hosts.byname", name, 1671 (int)strlen(name), &ypbuf, &ypbuflen); 1672 if (r == 0) { 1673 struct addrinfo ai4; 1674 1675 ai4 = *pai; 1676 ai4.ai_family = AF_INET; 1677 ai = _yphostent(ypbuf, &ai4); 1678 if (ai) { 1679 cur->ai_next = ai; 1680 while (cur && cur->ai_next) 1681 cur = cur->ai_next; 1682 } 1683 } 1684 free(ypbuf); 1685 } 1686 1687 /* ipnodes.byname can hold both IPv4/v6 */ 1688 r = yp_match(ypdomain, "ipnodes.byname", name, 1689 (int)strlen(name), &ypbuf, &ypbuflen); 1690 if (r == 0) { 1691 ai = _yphostent(ypbuf, pai); 1692 if (ai) 1693 cur->ai_next = ai; 1694 free(ypbuf); 1695 } 1696 1697 if (sentinel.ai_next == NULL) { 1698 h_errno = HOST_NOT_FOUND; 1699 return NS_NOTFOUND; 1700 } 1701 *((struct addrinfo **)rv) = sentinel.ai_next; 1702 return NS_SUCCESS; 1703 } 1704 #endif 1705 1706 /* resolver logic */ 1707 1708 /* 1709 * Formulate a normal query, send, and await answer. 1710 * Returned answer is placed in supplied buffer "answer". 1711 * Perform preliminary check of answer, returning success only 1712 * if no error is indicated and the answer count is nonzero. 1713 * Return the size of the response on success, -1 on error. 1714 * Error number is left in h_errno. 1715 * 1716 * Caller must parse answer and determine whether it answers the question. 1717 */ 1718 static int 1719 res_queryN(const char *name, /* domain name */ struct res_target *target, 1720 res_state res) 1721 { 1722 u_char buf[MAXPACKET]; 1723 HEADER *hp; 1724 int n; 1725 struct res_target *t; 1726 int rcode; 1727 int ancount; 1728 1729 _DIAGASSERT(name != NULL); 1730 /* XXX: target may be NULL??? */ 1731 1732 rcode = NOERROR; 1733 ancount = 0; 1734 1735 for (t = target; t; t = t->next) { 1736 int class, type; 1737 u_char *answer; 1738 int anslen; 1739 1740 hp = (HEADER *)(void *)t->answer; 1741 hp->rcode = NOERROR; /* default */ 1742 1743 /* make it easier... */ 1744 class = t->qclass; 1745 type = t->qtype; 1746 answer = t->answer; 1747 anslen = t->anslen; 1748 #ifdef DEBUG 1749 if (res->options & RES_DEBUG) 1750 printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 1751 #endif 1752 1753 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, 1754 buf, (int)sizeof(buf)); 1755 #ifdef RES_USE_EDNS0 1756 if (n > 0 && (res->options & RES_USE_EDNS0) != 0) 1757 n = res_nopt(res, n, buf, (int)sizeof(buf), anslen); 1758 #endif 1759 if (n <= 0) { 1760 #ifdef DEBUG 1761 if (res->options & RES_DEBUG) 1762 printf(";; res_nquery: mkquery failed\n"); 1763 #endif 1764 h_errno = NO_RECOVERY; 1765 return n; 1766 } 1767 n = res_nsend(res, buf, n, answer, anslen); 1768 #if 0 1769 if (n < 0) { 1770 #ifdef DEBUG 1771 if (res->options & RES_DEBUG) 1772 printf(";; res_query: send error\n"); 1773 #endif 1774 h_errno = TRY_AGAIN; 1775 return n; 1776 } 1777 #endif 1778 1779 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 1780 rcode = hp->rcode; /* record most recent error */ 1781 #ifdef DEBUG 1782 if (res->options & RES_DEBUG) 1783 printf(";; rcode = %u, ancount=%u\n", hp->rcode, 1784 ntohs(hp->ancount)); 1785 #endif 1786 continue; 1787 } 1788 1789 ancount += ntohs(hp->ancount); 1790 1791 t->n = n; 1792 } 1793 1794 if (ancount == 0) { 1795 switch (rcode) { 1796 case NXDOMAIN: 1797 h_errno = HOST_NOT_FOUND; 1798 break; 1799 case SERVFAIL: 1800 h_errno = TRY_AGAIN; 1801 break; 1802 case NOERROR: 1803 h_errno = NO_DATA; 1804 break; 1805 case FORMERR: 1806 case NOTIMP: 1807 case REFUSED: 1808 default: 1809 h_errno = NO_RECOVERY; 1810 break; 1811 } 1812 return -1; 1813 } 1814 return ancount; 1815 } 1816 1817 /* 1818 * Formulate a normal query, send, and retrieve answer in supplied buffer. 1819 * Return the size of the response on success, -1 on error. 1820 * If enabled, implement search rules until answer or unrecoverable failure 1821 * is detected. Error code, if any, is left in h_errno. 1822 */ 1823 static int 1824 res_searchN(const char *name, struct res_target *target, res_state res) 1825 { 1826 const char *cp, * const *domain; 1827 HEADER *hp; 1828 u_int dots; 1829 int trailing_dot, ret, saved_herrno; 1830 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 1831 1832 _DIAGASSERT(name != NULL); 1833 _DIAGASSERT(target != NULL); 1834 1835 hp = (HEADER *)(void *)target->answer; /*XXX*/ 1836 1837 errno = 0; 1838 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 1839 dots = 0; 1840 for (cp = name; *cp; cp++) 1841 dots += (*cp == '.'); 1842 trailing_dot = 0; 1843 if (cp > name && *--cp == '.') 1844 trailing_dot++; 1845 1846 /* 1847 * if there aren't any dots, it could be a user-level alias 1848 */ 1849 if (!dots && (cp = __hostalias(name)) != NULL) { 1850 ret = res_queryN(cp, target, res); 1851 return ret; 1852 } 1853 1854 /* 1855 * If there are dots in the name already, let's just give it a try 1856 * 'as is'. The threshold can be set with the "ndots" option. 1857 */ 1858 saved_herrno = -1; 1859 if (dots >= res->ndots) { 1860 ret = res_querydomainN(name, NULL, target, res); 1861 if (ret > 0) 1862 return (ret); 1863 saved_herrno = h_errno; 1864 tried_as_is++; 1865 } 1866 1867 /* 1868 * We do at least one level of search if 1869 * - there is no dot and RES_DEFNAME is set, or 1870 * - there is at least one dot, there is no trailing dot, 1871 * and RES_DNSRCH is set. 1872 */ 1873 if ((!dots && (res->options & RES_DEFNAMES)) || 1874 (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 1875 int done = 0; 1876 1877 for (domain = (const char * const *)res->dnsrch; 1878 *domain && !done; 1879 domain++) { 1880 1881 ret = res_querydomainN(name, *domain, target, res); 1882 if (ret > 0) 1883 return ret; 1884 1885 /* 1886 * If no server present, give up. 1887 * If name isn't found in this domain, 1888 * keep trying higher domains in the search list 1889 * (if that's enabled). 1890 * On a NO_DATA error, keep trying, otherwise 1891 * a wildcard entry of another type could keep us 1892 * from finding this entry higher in the domain. 1893 * If we get some other error (negative answer or 1894 * server failure), then stop searching up, 1895 * but try the input name below in case it's 1896 * fully-qualified. 1897 */ 1898 if (errno == ECONNREFUSED) { 1899 h_errno = TRY_AGAIN; 1900 return -1; 1901 } 1902 1903 switch (h_errno) { 1904 case NO_DATA: 1905 got_nodata++; 1906 /* FALLTHROUGH */ 1907 case HOST_NOT_FOUND: 1908 /* keep trying */ 1909 break; 1910 case TRY_AGAIN: 1911 if (hp->rcode == SERVFAIL) { 1912 /* try next search element, if any */ 1913 got_servfail++; 1914 break; 1915 } 1916 /* FALLTHROUGH */ 1917 default: 1918 /* anything else implies that we're done */ 1919 done++; 1920 } 1921 /* 1922 * if we got here for some reason other than DNSRCH, 1923 * we only wanted one iteration of the loop, so stop. 1924 */ 1925 if (!(res->options & RES_DNSRCH)) 1926 done++; 1927 } 1928 } 1929 1930 /* 1931 * if we have not already tried the name "as is", do that now. 1932 * note that we do this regardless of how many dots were in the 1933 * name or whether it ends with a dot. 1934 */ 1935 if (!tried_as_is) { 1936 ret = res_querydomainN(name, NULL, target, res); 1937 if (ret > 0) 1938 return ret; 1939 } 1940 1941 /* 1942 * if we got here, we didn't satisfy the search. 1943 * if we did an initial full query, return that query's h_errno 1944 * (note that we wouldn't be here if that query had succeeded). 1945 * else if we ever got a nodata, send that back as the reason. 1946 * else send back meaningless h_errno, that being the one from 1947 * the last DNSRCH we did. 1948 */ 1949 if (saved_herrno != -1) 1950 h_errno = saved_herrno; 1951 else if (got_nodata) 1952 h_errno = NO_DATA; 1953 else if (got_servfail) 1954 h_errno = TRY_AGAIN; 1955 return -1; 1956 } 1957 1958 /* 1959 * Perform a call on res_query on the concatenation of name and domain, 1960 * removing a trailing dot from name if domain is NULL. 1961 */ 1962 static int 1963 res_querydomainN(const char *name, const char *domain, 1964 struct res_target *target, res_state res) 1965 { 1966 char nbuf[MAXDNAME]; 1967 const char *longname = nbuf; 1968 size_t n, d; 1969 1970 _DIAGASSERT(name != NULL); 1971 /* XXX: target may be NULL??? */ 1972 1973 #ifdef DEBUG 1974 if (res->options & RES_DEBUG) 1975 printf(";; res_querydomain(%s, %s)\n", 1976 name, domain?domain:"<Nil>"); 1977 #endif 1978 if (domain == NULL) { 1979 /* 1980 * Check for trailing '.'; 1981 * copy without '.' if present. 1982 */ 1983 n = strlen(name); 1984 if (n + 1 > sizeof(nbuf)) { 1985 h_errno = NO_RECOVERY; 1986 return -1; 1987 } 1988 if (n > 0 && name[--n] == '.') { 1989 strncpy(nbuf, name, n); 1990 nbuf[n] = '\0'; 1991 } else 1992 longname = name; 1993 } else { 1994 n = strlen(name); 1995 d = strlen(domain); 1996 if (n + 1 + d + 1 > sizeof(nbuf)) { 1997 h_errno = NO_RECOVERY; 1998 return -1; 1999 } 2000 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 2001 } 2002 return res_queryN(longname, target, res); 2003 } 2004