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