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