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