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