1/* $NetBSD$ */ 2 3/* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */ 4 5/* 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34/*! \file 35 * Issues to be discussed: 36 *\li Thread safe-ness must be checked. 37 *\li 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 *\li IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 41 * says to use inet_aton() to convert IPv4 numeric to binary (allows 42 * classful form as a result). 43 * current code - disallow classful form for IPv4 (due to use of inet_pton). 44 *\li freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is 45 * invalid. 46 * current code - SEGV on freeaddrinfo(NULL) 47 * Note: 48 *\li We use getipnodebyname() just for thread-safeness. There's no intent 49 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to 50 * getipnodebyname(). 51 *\li The code filters out AFs that are not supported by the kernel, 52 * when globbing NULL hostname (to loopback, or wildcard). Is it the right 53 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 54 * in ai_flags? 55 *\li (post-2553) semantics of AI_ADDRCONFIG itself is too vague. 56 * (1) what should we do against numeric hostname (2) what should we do 57 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? 58 * non-loopback address configured? global address configured? 59 * \par Additional Issue: 60 * To avoid search order issue, we have a big amount of code duplicate 61 * from gethnamaddr.c and some other places. The issues that there's no 62 * lower layer function to lookup "IPv4 or IPv6" record. Calling 63 * gethostbyname2 from getaddrinfo will end up in wrong search order, as 64 * follows: 65 * \li The code makes use of following calls when asked to resolver with 66 * ai_family = PF_UNSPEC: 67 *\code getipnodebyname(host, AF_INET6); 68 * getipnodebyname(host, AF_INET); 69 *\endcode 70 * \li This will result in the following queries if the node is configure to 71 * prefer /etc/hosts than DNS: 72 *\code 73 * lookup /etc/hosts for IPv6 address 74 * lookup DNS for IPv6 address 75 * lookup /etc/hosts for IPv4 address 76 * lookup DNS for IPv4 address 77 *\endcode 78 * which may not meet people's requirement. 79 * \li The right thing to happen is to have underlying layer which does 80 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. 81 * This would result in a bit of code duplicate with _dns_ghbyname() and 82 * friends. 83 */ 84 85#include "port_before.h" 86 87#include <sys/types.h> 88#include <sys/param.h> 89#include <sys/socket.h> 90 91#include <net/if.h> 92#include <netinet/in.h> 93 94#include <arpa/inet.h> 95#include <arpa/nameser.h> 96 97#include <netdb.h> 98#include <resolv.h> 99#include <string.h> 100#include <stdlib.h> 101#include <stddef.h> 102#include <ctype.h> 103#include <unistd.h> 104#include <stdio.h> 105#include <errno.h> 106 107#include <stdarg.h> 108 109#include <irs.h> 110#include <isc/assertions.h> 111 112#include "port_after.h" 113 114#include "irs_data.h" 115 116#define SUCCESS 0 117#define ANY 0 118#define YES 1 119#define NO 0 120 121static const char in_addrany[] = { 0, 0, 0, 0 }; 122static const char in6_addrany[] = { 123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 124}; 125static const char in_loopback[] = { 127, 0, 0, 1 }; 126static const char in6_loopback[] = { 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 128}; 129 130static const struct afd { 131 int a_af; 132 int a_addrlen; 133 int a_socklen; 134 int a_off; 135 const char *a_addrany; 136 const char *a_loopback; 137 int a_scoped; 138} afdl [] = { 139 {PF_INET6, sizeof(struct in6_addr), 140 sizeof(struct sockaddr_in6), 141 offsetof(struct sockaddr_in6, sin6_addr), 142 in6_addrany, in6_loopback, 1}, 143 {PF_INET, sizeof(struct in_addr), 144 sizeof(struct sockaddr_in), 145 offsetof(struct sockaddr_in, sin_addr), 146 in_addrany, in_loopback, 0}, 147 {0, 0, 0, 0, NULL, NULL, 0}, 148}; 149 150struct explore { 151 int e_af; 152 int e_socktype; 153 int e_protocol; 154 const char *e_protostr; 155 int e_wild; 156#define WILD_AF(ex) ((ex)->e_wild & 0x01) 157#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 158#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 159}; 160 161static const struct explore explore[] = { 162#if 0 163 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, 164#endif 165 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 166 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 167 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 168 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 169 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 170 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 171 { -1, 0, 0, NULL, 0 }, 172}; 173 174#define PTON_MAX 16 175 176static int str_isnumber __P((const char *)); 177static int explore_fqdn __P((const struct addrinfo *, const char *, 178 const char *, struct addrinfo **)); 179static int explore_copy __P((const struct addrinfo *, const struct addrinfo *, 180 struct addrinfo **)); 181static int explore_null __P((const struct addrinfo *, 182 const char *, struct addrinfo **)); 183static int explore_numeric __P((const struct addrinfo *, const char *, 184 const char *, struct addrinfo **)); 185static int explore_numeric_scope __P((const struct addrinfo *, const char *, 186 const char *, struct addrinfo **)); 187static int get_canonname __P((const struct addrinfo *, 188 struct addrinfo *, const char *)); 189static struct addrinfo *get_ai __P((const struct addrinfo *, 190 const struct afd *, const char *)); 191static struct addrinfo *copy_ai __P((const struct addrinfo *)); 192static int get_portmatch __P((const struct addrinfo *, const char *)); 193static int get_port __P((const struct addrinfo *, const char *, int)); 194static const struct afd *find_afd __P((int)); 195static int addrconfig __P((int)); 196static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *, 197 u_int32_t *scopeidp)); 198static struct net_data *init __P((void)); 199 200struct addrinfo *hostent2addrinfo __P((struct hostent *, 201 const struct addrinfo *)); 202struct addrinfo *addr2addrinfo __P((const struct addrinfo *, 203 const char *)); 204 205#if 0 206static const char *ai_errlist[] = { 207 "Success", 208 "Address family for hostname not supported", /*%< EAI_ADDRFAMILY */ 209 "Temporary failure in name resolution", /*%< EAI_AGAIN */ 210 "Invalid value for ai_flags", /*%< EAI_BADFLAGS */ 211 "Non-recoverable failure in name resolution", /*%< EAI_FAIL */ 212 "ai_family not supported", /*%< EAI_FAMILY */ 213 "Memory allocation failure", /*%< EAI_MEMORY */ 214 "No address associated with hostname", /*%< EAI_NODATA */ 215 "hostname nor servname provided, or not known", /*%< EAI_NONAME */ 216 "servname not supported for ai_socktype", /*%< EAI_SERVICE */ 217 "ai_socktype not supported", /*%< EAI_SOCKTYPE */ 218 "System error returned in errno", /*%< EAI_SYSTEM */ 219 "Invalid value for hints", /*%< EAI_BADHINTS */ 220 "Resolved protocol is unknown", /*%< EAI_PROTOCOL */ 221 "Unknown error", /*%< EAI_MAX */ 222}; 223#endif 224 225/* XXX macros that make external reference is BAD. */ 226 227#define GET_AI(ai, afd, addr) \ 228do { \ 229 /* external reference: pai, error, and label free */ \ 230 (ai) = get_ai(pai, (afd), (addr)); \ 231 if ((ai) == NULL) { \ 232 error = EAI_MEMORY; \ 233 goto free; \ 234 } \ 235} while (/*CONSTCOND*/0) 236 237#define GET_PORT(ai, serv) \ 238do { \ 239 /* external reference: error and label free */ \ 240 error = get_port((ai), (serv), 0); \ 241 if (error != 0) \ 242 goto free; \ 243} while (/*CONSTCOND*/0) 244 245#define GET_CANONNAME(ai, str) \ 246do { \ 247 /* external reference: pai, error and label free */ \ 248 error = get_canonname(pai, (ai), (str)); \ 249 if (error != 0) \ 250 goto free; \ 251} while (/*CONSTCOND*/0) 252 253#ifndef SOLARIS2 254#define SETERROR(err) \ 255do { \ 256 /* external reference: error, and label bad */ \ 257 error = (err); \ 258 goto bad; \ 259 /*NOTREACHED*/ \ 260} while (/*CONSTCOND*/0) 261#else 262#define SETERROR(err) \ 263do { \ 264 /* external reference: error, and label bad */ \ 265 error = (err); \ 266 if (error == error) \ 267 goto bad; \ 268} while (/*CONSTCOND*/0) 269#endif 270 271 272#define MATCH_FAMILY(x, y, w) \ 273 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) 274#define MATCH(x, y, w) \ 275 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) 276 277#if 0 /*%< bind8 has its own version */ 278char * 279gai_strerror(ecode) 280 int ecode; 281{ 282 if (ecode < 0 || ecode > EAI_MAX) 283 ecode = EAI_MAX; 284 return ai_errlist[ecode]; 285} 286#endif 287 288void 289freeaddrinfo(ai) 290 struct addrinfo *ai; 291{ 292 struct addrinfo *next; 293 294 do { 295 next = ai->ai_next; 296 if (ai->ai_canonname) 297 free(ai->ai_canonname); 298 /* no need to free(ai->ai_addr) */ 299 free(ai); 300 ai = next; 301 } while (ai); 302} 303 304static int 305str_isnumber(p) 306 const char *p; 307{ 308 char *ep; 309 310 if (*p == '\0') 311 return NO; 312 ep = NULL; 313 errno = 0; 314 (void)strtoul(p, &ep, 10); 315 if (errno == 0 && ep && *ep == '\0') 316 return YES; 317 else 318 return NO; 319} 320 321int 322getaddrinfo(hostname, servname, hints, res) 323 const char *hostname, *servname; 324 const struct addrinfo *hints; 325 struct addrinfo **res; 326{ 327 struct addrinfo sentinel; 328 struct addrinfo *cur; 329 int error = 0; 330 struct addrinfo ai, ai0, *afai = NULL; 331 struct addrinfo *pai; 332 const struct explore *ex; 333 334 memset(&sentinel, 0, sizeof(sentinel)); 335 cur = &sentinel; 336 pai = &ai; 337 pai->ai_flags = 0; 338 pai->ai_family = PF_UNSPEC; 339 pai->ai_socktype = ANY; 340 pai->ai_protocol = ANY; 341#if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9) 342 /* 343 * clear _ai_pad to preserve binary 344 * compatibility with previously compiled 64-bit 345 * applications in a pre-SUSv3 environment by 346 * guaranteeing the upper 32-bits are empty. 347 */ 348 pai->_ai_pad = 0; 349#endif 350 pai->ai_addrlen = 0; 351 pai->ai_canonname = NULL; 352 pai->ai_addr = NULL; 353 pai->ai_next = NULL; 354 355 if (hostname == NULL && servname == NULL) 356 return EAI_NONAME; 357 if (hints) { 358 /* error check for hints */ 359 if (hints->ai_addrlen || hints->ai_canonname || 360 hints->ai_addr || hints->ai_next) 361 SETERROR(EAI_BADHINTS); /*%< xxx */ 362 if (hints->ai_flags & ~AI_MASK) 363 SETERROR(EAI_BADFLAGS); 364 switch (hints->ai_family) { 365 case PF_UNSPEC: 366 case PF_INET: 367 case PF_INET6: 368 break; 369 default: 370 SETERROR(EAI_FAMILY); 371 } 372 memcpy(pai, hints, sizeof(*pai)); 373 374#if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9) 375 /* 376 * We need to clear _ai_pad to preserve binary 377 * compatibility. See prior comment. 378 */ 379 pai->_ai_pad = 0; 380#endif 381 /* 382 * if both socktype/protocol are specified, check if they 383 * are meaningful combination. 384 */ 385 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 386 for (ex = explore; ex->e_af >= 0; ex++) { 387 if (pai->ai_family != ex->e_af) 388 continue; 389 if (ex->e_socktype == ANY) 390 continue; 391 if (ex->e_protocol == ANY) 392 continue; 393 if (pai->ai_socktype == ex->e_socktype && 394 pai->ai_protocol != ex->e_protocol) { 395 SETERROR(EAI_BADHINTS); 396 } 397 } 398 } 399 } 400 401 /* 402 * post-2553: AI_ALL and AI_V4MAPPED are effective only against 403 * AF_INET6 query. They needs to be ignored if specified in other 404 * occassions. 405 */ 406 switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { 407 case AI_V4MAPPED: 408 case AI_ALL | AI_V4MAPPED: 409 if (pai->ai_family != AF_INET6) 410 pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); 411 break; 412 case AI_ALL: 413#if 1 414 /* illegal */ 415 SETERROR(EAI_BADFLAGS); 416#else 417 pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); 418 break; 419#endif 420 } 421 422 /* 423 * check for special cases. (1) numeric servname is disallowed if 424 * socktype/protocol are left unspecified. (2) servname is disallowed 425 * for raw and other inet{,6} sockets. 426 */ 427 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 428#ifdef PF_INET6 429 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 430#endif 431 ) { 432 ai0 = *pai; /* backup *pai */ 433 434 if (pai->ai_family == PF_UNSPEC) { 435#ifdef PF_INET6 436 pai->ai_family = PF_INET6; 437#else 438 pai->ai_family = PF_INET; 439#endif 440 } 441 error = get_portmatch(pai, servname); 442 if (error) 443 SETERROR(error); 444 445 *pai = ai0; 446 } 447 448 ai0 = *pai; 449 450 /* NULL hostname, or numeric hostname */ 451 for (ex = explore; ex->e_af >= 0; ex++) { 452 *pai = ai0; 453 454 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 455 continue; 456 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 457 continue; 458 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 459 continue; 460 461 if (pai->ai_family == PF_UNSPEC) 462 pai->ai_family = ex->e_af; 463 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 464 pai->ai_socktype = ex->e_socktype; 465 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 466 pai->ai_protocol = ex->e_protocol; 467 468 /* 469 * if the servname does not match socktype/protocol, ignore it. 470 */ 471 if (get_portmatch(pai, servname) != 0) 472 continue; 473 474 if (hostname == NULL) { 475 /* 476 * filter out AFs that are not supported by the kernel 477 * XXX errno? 478 */ 479 if (!addrconfig(pai->ai_family)) 480 continue; 481 error = explore_null(pai, servname, &cur->ai_next); 482 } else 483 error = explore_numeric_scope(pai, hostname, servname, 484 &cur->ai_next); 485 486 if (error) 487 goto free; 488 489 while (cur && cur->ai_next) 490 cur = cur->ai_next; 491 } 492 493 /* 494 * XXX 495 * If numreic representation of AF1 can be interpreted as FQDN 496 * representation of AF2, we need to think again about the code below. 497 */ 498 if (sentinel.ai_next) 499 goto good; 500 501 if (pai->ai_flags & AI_NUMERICHOST) 502 SETERROR(EAI_NONAME); 503 if (hostname == NULL) 504 SETERROR(EAI_NONAME); 505 506 /* 507 * hostname as alphabetical name. 508 * We'll make sure that 509 * - if returning addrinfo list is empty, return non-zero error 510 * value (already known one or EAI_NONAME). 511 * - otherwise, 512 * + if we haven't had any errors, return 0 (i.e. success). 513 * + if we've had an error, free the list and return the error. 514 * without any assumption on the behavior of explore_fqdn(). 515 */ 516 517 /* first, try to query DNS for all possible address families. */ 518 *pai = ai0; 519 error = explore_fqdn(pai, hostname, servname, &afai); 520 if (error) { 521 if (afai != NULL) 522 freeaddrinfo(afai); 523 goto free; 524 } 525 if (afai == NULL) { 526 error = EAI_NONAME; /*%< we've had no errors. */ 527 goto free; 528 } 529 530 /* 531 * we would like to prefer AF_INET6 than AF_INET, so we'll make an 532 * outer loop by AFs. 533 */ 534 for (ex = explore; ex->e_af >= 0; ex++) { 535 *pai = ai0; 536 537 if (pai->ai_family == PF_UNSPEC) 538 pai->ai_family = ex->e_af; 539 540 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 541 continue; 542 if (!MATCH(pai->ai_socktype, ex->e_socktype, 543 WILD_SOCKTYPE(ex))) { 544 continue; 545 } 546 if (!MATCH(pai->ai_protocol, ex->e_protocol, 547 WILD_PROTOCOL(ex))) { 548 continue; 549 } 550 551#ifdef AI_ADDRCONFIG 552 /* 553 * If AI_ADDRCONFIG is specified, check if we are 554 * expected to return the address family or not. 555 */ 556 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && 557 !addrconfig(pai->ai_family)) 558 continue; 559#endif 560 561 if (pai->ai_family == PF_UNSPEC) 562 pai->ai_family = ex->e_af; 563 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 564 pai->ai_socktype = ex->e_socktype; 565 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 566 pai->ai_protocol = ex->e_protocol; 567 568 /* 569 * if the servname does not match socktype/protocol, ignore it. 570 */ 571 if (get_portmatch(pai, servname) != 0) 572 continue; 573 574 if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) { 575 freeaddrinfo(afai); 576 goto free; 577 } 578 579 while (cur && cur->ai_next) 580 cur = cur->ai_next; 581 } 582 583 freeaddrinfo(afai); /*%< afai must not be NULL at this point. */ 584 585 if (sentinel.ai_next) { 586good: 587 *res = sentinel.ai_next; 588 return(SUCCESS); 589 } else { 590 /* 591 * All the process succeeded, but we've had an empty list. 592 * This can happen if the given hints do not match our 593 * candidates. 594 */ 595 error = EAI_NONAME; 596 } 597 598free: 599bad: 600 if (sentinel.ai_next) 601 freeaddrinfo(sentinel.ai_next); 602 *res = NULL; 603 return(error); 604} 605 606/*% 607 * FQDN hostname, DNS lookup 608 */ 609static int 610explore_fqdn(pai, hostname, servname, res) 611 const struct addrinfo *pai; 612 const char *hostname; 613 const char *servname; 614 struct addrinfo **res; 615{ 616 struct addrinfo *result; 617 struct addrinfo *cur; 618 struct net_data *net_data = init(); 619 struct irs_ho *ho; 620 int error = 0; 621 char tmp[NS_MAXDNAME]; 622 const char *cp; 623 624 INSIST(res != NULL && *res == NULL); 625 626 /* 627 * if the servname does not match socktype/protocol, ignore it. 628 */ 629 if (get_portmatch(pai, servname) != 0) 630 return(0); 631 632 if (!net_data || !(ho = net_data->ho)) 633 return(0); 634#if 0 /*%< XXX (notyet) */ 635 if (net_data->ho_stayopen && net_data->ho_last && 636 net_data->ho_last->h_addrtype == af) { 637 if (ns_samename(name, net_data->ho_last->h_name) == 1) 638 return (net_data->ho_last); 639 for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) 640 if (ns_samename(name, *hap) == 1) 641 return (net_data->ho_last); 642 } 643#endif 644 if (!strchr(hostname, '.') && 645 (cp = res_hostalias(net_data->res, hostname, 646 tmp, sizeof(tmp)))) 647 hostname = cp; 648 result = (*ho->addrinfo)(ho, hostname, pai); 649 if (!net_data->ho_stayopen) { 650 (*ho->minimize)(ho); 651 } 652 if (result == NULL) { 653 int e = h_errno; 654 655 switch(e) { 656 case NETDB_INTERNAL: 657 error = EAI_SYSTEM; 658 break; 659 case TRY_AGAIN: 660 error = EAI_AGAIN; 661 break; 662 case NO_RECOVERY: 663 error = EAI_FAIL; 664 break; 665 case HOST_NOT_FOUND: 666 case NO_DATA: 667 error = EAI_NONAME; 668 break; 669 default: 670 case NETDB_SUCCESS: /*%< should be impossible... */ 671 error = EAI_NONAME; 672 break; 673 } 674 goto free; 675 } 676 677 for (cur = result; cur; cur = cur->ai_next) { 678 GET_PORT(cur, servname); /*%< XXX: redundant lookups... */ 679 /* canonname should already be filled. */ 680 } 681 682 *res = result; 683 684 return(0); 685 686free: 687 if (result) 688 freeaddrinfo(result); 689 return error; 690} 691 692static int 693explore_copy(pai, src0, res) 694 const struct addrinfo *pai; /*%< seed */ 695 const struct addrinfo *src0; /*%< source */ 696 struct addrinfo **res; 697{ 698 int error; 699 struct addrinfo sentinel, *cur; 700 const struct addrinfo *src; 701 702 error = 0; 703 sentinel.ai_next = NULL; 704 cur = &sentinel; 705 706 for (src = src0; src != NULL; src = src->ai_next) { 707 if (src->ai_family != pai->ai_family) 708 continue; 709 710 cur->ai_next = copy_ai(src); 711 if (!cur->ai_next) { 712 error = EAI_MEMORY; 713 goto fail; 714 } 715 716 cur->ai_next->ai_socktype = pai->ai_socktype; 717 cur->ai_next->ai_protocol = pai->ai_protocol; 718 cur = cur->ai_next; 719 } 720 721 *res = sentinel.ai_next; 722 return 0; 723 724fail: 725 freeaddrinfo(sentinel.ai_next); 726 return error; 727} 728 729/*% 730 * hostname == NULL. 731 * passive socket -> anyaddr (0.0.0.0 or ::) 732 * non-passive socket -> localhost (127.0.0.1 or ::1) 733 */ 734static int 735explore_null(pai, servname, res) 736 const struct addrinfo *pai; 737 const char *servname; 738 struct addrinfo **res; 739{ 740 const struct afd *afd; 741 struct addrinfo *cur; 742 struct addrinfo sentinel; 743 int error; 744 745 *res = NULL; 746 sentinel.ai_next = NULL; 747 cur = &sentinel; 748 749 afd = find_afd(pai->ai_family); 750 if (afd == NULL) 751 return 0; 752 753 if (pai->ai_flags & AI_PASSIVE) { 754 GET_AI(cur->ai_next, afd, afd->a_addrany); 755 /* xxx meaningless? 756 * GET_CANONNAME(cur->ai_next, "anyaddr"); 757 */ 758 GET_PORT(cur->ai_next, servname); 759 } else { 760 GET_AI(cur->ai_next, afd, afd->a_loopback); 761 /* xxx meaningless? 762 * GET_CANONNAME(cur->ai_next, "localhost"); 763 */ 764 GET_PORT(cur->ai_next, servname); 765 } 766 cur = cur->ai_next; 767 768 *res = sentinel.ai_next; 769 return 0; 770 771free: 772 if (sentinel.ai_next) 773 freeaddrinfo(sentinel.ai_next); 774 return error; 775} 776 777/*% 778 * numeric hostname 779 */ 780static int 781explore_numeric(pai, hostname, servname, res) 782 const struct addrinfo *pai; 783 const char *hostname; 784 const char *servname; 785 struct addrinfo **res; 786{ 787 const struct afd *afd; 788 struct addrinfo *cur; 789 struct addrinfo sentinel; 790 int error; 791 char pton[PTON_MAX]; 792 793 *res = NULL; 794 sentinel.ai_next = NULL; 795 cur = &sentinel; 796 797 afd = find_afd(pai->ai_family); 798 if (afd == NULL) 799 return 0; 800 801 switch (afd->a_af) { 802#if 0 /*X/Open spec*/ 803 case AF_INET: 804 if (inet_aton(hostname, (struct in_addr *)pton) == 1) { 805 if (pai->ai_family == afd->a_af || 806 pai->ai_family == PF_UNSPEC /*?*/) { 807 GET_AI(cur->ai_next, afd, pton); 808 GET_PORT(cur->ai_next, servname); 809 while (cur->ai_next) 810 cur = cur->ai_next; 811 } else 812 SETERROR(EAI_FAMILY); /*xxx*/ 813 } 814 break; 815#endif 816 default: 817 if (inet_pton(afd->a_af, hostname, pton) == 1) { 818 if (pai->ai_family == afd->a_af || 819 pai->ai_family == PF_UNSPEC /*?*/) { 820 GET_AI(cur->ai_next, afd, pton); 821 GET_PORT(cur->ai_next, servname); 822 while (cur->ai_next) 823 cur = cur->ai_next; 824 } else 825 SETERROR(EAI_FAMILY); /*xxx*/ 826 } 827 break; 828 } 829 830 *res = sentinel.ai_next; 831 return 0; 832 833free: 834bad: 835 if (sentinel.ai_next) 836 freeaddrinfo(sentinel.ai_next); 837 return error; 838} 839 840/*% 841 * numeric hostname with scope 842 */ 843static int 844explore_numeric_scope(pai, hostname, servname, res) 845 const struct addrinfo *pai; 846 const char *hostname; 847 const char *servname; 848 struct addrinfo **res; 849{ 850#ifndef SCOPE_DELIMITER 851 return explore_numeric(pai, hostname, servname, res); 852#else 853 const struct afd *afd; 854 struct addrinfo *cur; 855 int error; 856 char *cp, *hostname2 = NULL, *scope, *addr; 857 struct sockaddr_in6 *sin6; 858 859 afd = find_afd(pai->ai_family); 860 if (afd == NULL) 861 return 0; 862 863 if (!afd->a_scoped) 864 return explore_numeric(pai, hostname, servname, res); 865 866 cp = strchr(hostname, SCOPE_DELIMITER); 867 if (cp == NULL) 868 return explore_numeric(pai, hostname, servname, res); 869 870 /* 871 * Handle special case of <scoped_address><delimiter><scope id> 872 */ 873 hostname2 = strdup(hostname); 874 if (hostname2 == NULL) 875 return EAI_MEMORY; 876 /* terminate at the delimiter */ 877 hostname2[cp - hostname] = '\0'; 878 addr = hostname2; 879 scope = cp + 1; 880 881 error = explore_numeric(pai, addr, servname, res); 882 if (error == 0) { 883 u_int32_t scopeid = 0; 884 885 for (cur = *res; cur; cur = cur->ai_next) { 886 if (cur->ai_family != AF_INET6) 887 continue; 888 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 889 if (!ip6_str2scopeid(scope, sin6, &scopeid)) { 890 free(hostname2); 891 return(EAI_NONAME); /*%< XXX: is return OK? */ 892 } 893#ifdef HAVE_SIN6_SCOPE_ID 894 sin6->sin6_scope_id = scopeid; 895#endif 896 } 897 } 898 899 free(hostname2); 900 901 return error; 902#endif 903} 904 905static int 906get_canonname(pai, ai, str) 907 const struct addrinfo *pai; 908 struct addrinfo *ai; 909 const char *str; 910{ 911 if ((pai->ai_flags & AI_CANONNAME) != 0) { 912 ai->ai_canonname = (char *)malloc(strlen(str) + 1); 913 if (ai->ai_canonname == NULL) 914 return EAI_MEMORY; 915 strcpy(ai->ai_canonname, str); 916 } 917 return 0; 918} 919 920static struct addrinfo * 921get_ai(pai, afd, addr) 922 const struct addrinfo *pai; 923 const struct afd *afd; 924 const char *addr; 925{ 926 char *p; 927 struct addrinfo *ai; 928 929 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 930 + (afd->a_socklen)); 931 if (ai == NULL) 932 return NULL; 933 934 memcpy(ai, pai, sizeof(struct addrinfo)); 935 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); 936 memset(ai->ai_addr, 0, (size_t)afd->a_socklen); 937#ifdef HAVE_SA_LEN 938 ai->ai_addr->sa_len = afd->a_socklen; 939#endif 940 ai->ai_addrlen = afd->a_socklen; 941 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 942 p = (char *)(void *)(ai->ai_addr); 943 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 944 return ai; 945} 946 947/* XXX need to malloc() the same way we do from other functions! */ 948static struct addrinfo * 949copy_ai(pai) 950 const struct addrinfo *pai; 951{ 952 struct addrinfo *ai; 953 size_t l; 954 955 l = sizeof(*ai) + pai->ai_addrlen; 956 if ((ai = (struct addrinfo *)malloc(l)) == NULL) 957 return NULL; 958 memset(ai, 0, l); 959 memcpy(ai, pai, sizeof(*ai)); 960 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); 961 memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen); 962 963 if (pai->ai_canonname) { 964 l = strlen(pai->ai_canonname) + 1; 965 if ((ai->ai_canonname = malloc(l)) == NULL) { 966 free(ai); 967 return NULL; 968 } 969 strcpy(ai->ai_canonname, pai->ai_canonname); /* (checked) */ 970 } else { 971 /* just to make sure */ 972 ai->ai_canonname = NULL; 973 } 974 975 ai->ai_next = NULL; 976 977 return ai; 978} 979 980static int 981get_portmatch(const struct addrinfo *ai, const char *servname) { 982 983 /* get_port does not touch first argument. when matchonly == 1. */ 984 /* LINTED const cast */ 985 return get_port((const struct addrinfo *)ai, servname, 1); 986} 987 988static int 989get_port(const struct addrinfo *ai, const char *servname, int matchonly) { 990 const char *proto; 991 struct servent *sp; 992 int port; 993 int allownumeric; 994 995 if (servname == NULL) 996 return 0; 997 switch (ai->ai_family) { 998 case AF_INET: 999#ifdef AF_INET6 1000 case AF_INET6: 1001#endif 1002 break; 1003 default: 1004 return 0; 1005 } 1006 1007 switch (ai->ai_socktype) { 1008 case SOCK_RAW: 1009 return EAI_SERVICE; 1010 case SOCK_DGRAM: 1011 case SOCK_STREAM: 1012 allownumeric = 1; 1013 break; 1014 case ANY: 1015 switch (ai->ai_family) { 1016 case AF_INET: 1017#ifdef AF_INET6 1018 case AF_INET6: 1019#endif 1020 allownumeric = 1; 1021 break; 1022 default: 1023 allownumeric = 0; 1024 break; 1025 } 1026 break; 1027 default: 1028 return EAI_SOCKTYPE; 1029 } 1030 1031 if (str_isnumber(servname)) { 1032 if (!allownumeric) 1033 return EAI_SERVICE; 1034 port = atoi(servname); 1035 if (port < 0 || port > 65535) 1036 return EAI_SERVICE; 1037 port = htons(port); 1038 } else { 1039 switch (ai->ai_socktype) { 1040 case SOCK_DGRAM: 1041 proto = "udp"; 1042 break; 1043 case SOCK_STREAM: 1044 proto = "tcp"; 1045 break; 1046 default: 1047 proto = NULL; 1048 break; 1049 } 1050 1051 if ((sp = getservbyname(servname, proto)) == NULL) 1052 return EAI_SERVICE; 1053 port = sp->s_port; 1054 } 1055 1056 if (!matchonly) { 1057 switch (ai->ai_family) { 1058 case AF_INET: 1059 ((struct sockaddr_in *)(void *) 1060 ai->ai_addr)->sin_port = port; 1061 break; 1062 case AF_INET6: 1063 ((struct sockaddr_in6 *)(void *) 1064 ai->ai_addr)->sin6_port = port; 1065 break; 1066 } 1067 } 1068 1069 return 0; 1070} 1071 1072static const struct afd * 1073find_afd(af) 1074 int af; 1075{ 1076 const struct afd *afd; 1077 1078 if (af == PF_UNSPEC) 1079 return NULL; 1080 for (afd = afdl; afd->a_af; afd++) { 1081 if (afd->a_af == af) 1082 return afd; 1083 } 1084 return NULL; 1085} 1086 1087/*% 1088 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend 1089 * will take care of it. 1090 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure 1091 * if the code is right or not. 1092 */ 1093static int 1094addrconfig(af) 1095 int af; 1096{ 1097 int s; 1098 1099 /* XXX errno */ 1100 s = socket(af, SOCK_DGRAM, 0); 1101 if (s < 0) { 1102 if (errno != EMFILE) 1103 return 0; 1104 } else 1105 close(s); 1106 return 1; 1107} 1108 1109/* convert a string to a scope identifier. XXX: IPv6 specific */ 1110static int 1111ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, 1112 u_int32_t *scopeidp) 1113{ 1114 u_int32_t scopeid; 1115 u_long lscopeid; 1116 struct in6_addr *a6 = &sin6->sin6_addr; 1117 char *ep; 1118 1119 /* empty scopeid portion is invalid */ 1120 if (*scope == '\0') 1121 return (0); 1122 1123#ifdef USE_IFNAMELINKID 1124 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) || 1125 IN6_IS_ADDR_MC_NODELOCAL(a6)) { 1126 /* 1127 * Using interface names as link indices can be allowed 1128 * only when we can assume a one-to-one mappings between 1129 * links and interfaces. See comments in getnameinfo.c. 1130 */ 1131 scopeid = if_nametoindex(scope); 1132 if (scopeid == 0) 1133 goto trynumeric; 1134 *scopeidp = scopeid; 1135 return (1); 1136 } 1137#endif 1138 1139 /* still unclear about literal, allow numeric only - placeholder */ 1140 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 1141 goto trynumeric; 1142 if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 1143 goto trynumeric; 1144 else 1145 goto trynumeric; /*%< global */ 1146 /* try to convert to a numeric id as a last resort */ 1147trynumeric: 1148 errno = 0; 1149 lscopeid = strtoul(scope, &ep, 10); 1150 scopeid = lscopeid & 0xffffffff; 1151 if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) { 1152 *scopeidp = scopeid; 1153 return (1); 1154 } else 1155 return (0); 1156} 1157 1158struct addrinfo * 1159hostent2addrinfo(hp, pai) 1160 struct hostent *hp; 1161 const struct addrinfo *pai; 1162{ 1163 int i, af, error = 0; 1164 char **aplist = NULL, *ap; 1165 struct addrinfo sentinel, *cur; 1166 const struct afd *afd; 1167 1168 af = hp->h_addrtype; 1169 if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) 1170 return(NULL); 1171 1172 afd = find_afd(af); 1173 if (afd == NULL) 1174 return(NULL); 1175 1176 aplist = hp->h_addr_list; 1177 1178 memset(&sentinel, 0, sizeof(sentinel)); 1179 cur = &sentinel; 1180 1181 for (i = 0; (ap = aplist[i]) != NULL; i++) { 1182#if 0 /*%< the trick seems too much */ 1183 af = hp->h_addr_list; 1184 if (af == AF_INET6 && 1185 IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { 1186 af = AF_INET; 1187 ap = ap + sizeof(struct in6_addr) 1188 - sizeof(struct in_addr); 1189 } 1190 afd = find_afd(af); 1191 if (afd == NULL) 1192 continue; 1193#endif /* 0 */ 1194 1195 GET_AI(cur->ai_next, afd, ap); 1196 1197 /* GET_PORT(cur->ai_next, servname); */ 1198 if ((pai->ai_flags & AI_CANONNAME) != 0) { 1199 /* 1200 * RFC2553 says that ai_canonname will be set only for 1201 * the first element. we do it for all the elements, 1202 * just for convenience. 1203 */ 1204 GET_CANONNAME(cur->ai_next, hp->h_name); 1205 } 1206 while (cur->ai_next) /*%< no need to loop, actually. */ 1207 cur = cur->ai_next; 1208 continue; 1209 1210 free: 1211 if (cur->ai_next) 1212 freeaddrinfo(cur->ai_next); 1213 cur->ai_next = NULL; 1214 /* continue, without tht pointer CUR advanced. */ 1215 } 1216 1217 return(sentinel.ai_next); 1218} 1219 1220struct addrinfo * 1221addr2addrinfo(pai, cp) 1222 const struct addrinfo *pai; 1223 const char *cp; 1224{ 1225 const struct afd *afd; 1226 1227 afd = find_afd(pai->ai_family); 1228 if (afd == NULL) 1229 return(NULL); 1230 1231 return(get_ai(pai, afd, cp)); 1232} 1233 1234static struct net_data * 1235init() 1236{ 1237 struct net_data *net_data; 1238 1239 if (!(net_data = net_data_init(NULL))) 1240 goto error; 1241 if (!net_data->ho) { 1242 net_data->ho = (*net_data->irs->ho_map)(net_data->irs); 1243 if (!net_data->ho || !net_data->res) { 1244error: 1245 errno = EIO; 1246 if (net_data && net_data->res) 1247 RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); 1248 return (NULL); 1249 } 1250 1251 (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); 1252 } 1253 1254 return (net_data); 1255} 1256