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