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