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