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