getaddrinfo.c revision 55837
1/* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: head/lib/libc/net/getaddrinfo.c 55837 2000-01-12 09:23:48Z jasone $ 30 */ 31 32/* 33 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. 34 * 35 * Issues to be discussed: 36 * - Thread safe-ness must be checked. 37 * - Return values. There are nonstandard return values defined and used 38 * in the source code. This is because RFC2553 is silent about which error 39 * code must be returned for which situation. 40 * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag. 41 */ 42 43#include <sys/types.h> 44#include <sys/param.h> 45#include <sys/socket.h> 46#include <net/if.h> 47#include <netinet/in.h> 48#include <arpa/inet.h> 49#include <arpa/nameser.h> 50#include <netdb.h> 51#include <resolv.h> 52#include <string.h> 53#include <stdlib.h> 54#include <stddef.h> 55#include <ctype.h> 56#include <unistd.h> 57#include <stdio.h> 58 59#if defined(__KAME__) && defined(INET6) 60# define FAITH 61#endif 62 63#define SUCCESS 0 64#define ANY 0 65#define YES 1 66#define NO 0 67 68static const char in_addrany[] = { 0, 0, 0, 0 }; 69static const char in6_addrany[] = { 70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 71}; 72static const char in_loopback[] = { 127, 0, 0, 1 }; 73static const char in6_loopback[] = { 74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 75}; 76 77static const struct afd { 78 int a_af; 79 int a_addrlen; 80 int a_socklen; 81 int a_off; 82 const char *a_addrany; 83 const char *a_loopback; 84 int a_scoped; 85} afdl [] = { 86#ifdef INET6 87#define N_INET6 0 88 {PF_INET6, sizeof(struct in6_addr), 89 sizeof(struct sockaddr_in6), 90 offsetof(struct sockaddr_in6, sin6_addr), 91 in6_addrany, in6_loopback, 1}, 92#define N_INET 1 93#else 94#define N_INET 0 95#endif 96 {PF_INET, sizeof(struct in_addr), 97 sizeof(struct sockaddr_in), 98 offsetof(struct sockaddr_in, sin_addr), 99 in_addrany, in_loopback, 0}, 100 {0, 0, 0, 0, NULL, NULL, 0}, 101}; 102 103struct explore { 104 int e_af; 105 int e_socktype; 106 int e_protocol; 107 const char *e_protostr; 108 int e_wild; 109#define WILD_AF(ex) ((ex)->e_wild & 0x01) 110#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 111#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 112}; 113 114static const struct explore explore[] = { 115#ifdef INET6 116 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 117 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 118 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 119#endif 120 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 121 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 122 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 123 { -1, 0, 0, NULL, 0 }, 124}; 125 126#ifdef INET6 127#define PTON_MAX 16 128#else 129#define PTON_MAX 4 130#endif 131 132 133static int str_isnumber __P((const char *)); 134static int explore_fqdn __P((const struct addrinfo *, const char *, 135 const char *, struct addrinfo **)); 136static int explore_null __P((const struct addrinfo *, const char *, 137 const char *, struct addrinfo **)); 138static int explore_numeric __P((const struct addrinfo *, const char *, 139 const char *, struct addrinfo **)); 140static int explore_numeric_scope __P((const struct addrinfo *, const char *, 141 const char *, struct addrinfo **)); 142static int get_name __P((const char *, const struct afd *, struct addrinfo **, 143 char *, const struct addrinfo *, const char *)); 144static int get_canonname __P((const struct addrinfo *, 145 struct addrinfo *, const char *)); 146static struct addrinfo *get_ai __P((const struct addrinfo *, 147 const struct afd *, const char *)); 148static int get_portmatch __P((const struct addrinfo *, const char *)); 149static int get_port __P((struct addrinfo *, const char *, int)); 150static const struct afd *find_afd __P((int)); 151 152static char *ai_errlist[] = { 153 "Success", 154 "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 155 "Temporary failure in name resolution", /* EAI_AGAIN */ 156 "Invalid value for ai_flags", /* EAI_BADFLAGS */ 157 "Non-recoverable failure in name resolution", /* EAI_FAIL */ 158 "ai_family not supported", /* EAI_FAMILY */ 159 "Memory allocation failure", /* EAI_MEMORY */ 160 "No address associated with hostname", /* EAI_NODATA */ 161 "hostname nor servname provided, or not known", /* EAI_NONAME */ 162 "servname not supported for ai_socktype", /* EAI_SERVICE */ 163 "ai_socktype not supported", /* EAI_SOCKTYPE */ 164 "System error returned in errno", /* EAI_SYSTEM */ 165 "Invalid value for hints", /* EAI_BADHINTS */ 166 "Resolved protocol is unknown", /* EAI_PROTOCOL */ 167 "Argument res is NULL", /* EAI_RESNULL */ 168 "Unknown error", /* EAI_MAX */ 169}; 170 171/* XXX macros that make external reference is BAD. */ 172 173#define GET_AI(ai, afd, addr) \ 174do { \ 175 /* external reference: pai, error, and label free */ \ 176 (ai) = get_ai(pai, (afd), (addr)); \ 177 if ((ai) == NULL) { \ 178 error = EAI_MEMORY; \ 179 goto free; \ 180 } \ 181} while (0) 182 183#define GET_PORT(ai, serv) \ 184do { \ 185 /* external reference: error and label free */ \ 186 error = get_port((ai), (serv), 0); \ 187 if (error != 0) \ 188 goto free; \ 189} while (0) 190 191#define GET_CANONNAME(ai, str) \ 192do { \ 193 /* external reference: pai, error and label free */ \ 194 error = get_canonname(pai, (ai), (str)); \ 195 if (error != 0) \ 196 goto free; \ 197} while (0) 198 199#define ERR(err) \ 200do { \ 201 /* external reference: error, and label bad */ \ 202 error = (err); \ 203 goto bad; \ 204} while (0) 205 206#define MATCH_FAMILY(x, y, w) \ 207 ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) 208#define MATCH(x, y, w) \ 209 ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY))) 210 211char * 212gai_strerror(ecode) 213 int ecode; 214{ 215 if (ecode < 0 || ecode > EAI_MAX) 216 ecode = EAI_MAX; 217 return ai_errlist[ecode]; 218} 219 220void 221freeaddrinfo(ai) 222 struct addrinfo *ai; 223{ 224 struct addrinfo *next; 225 226 do { 227 next = ai->ai_next; 228 if (ai->ai_canonname) 229 free(ai->ai_canonname); 230 /* no need to free(ai->ai_addr) */ 231 free(ai); 232 } while ((ai = next) != NULL); 233} 234 235static int 236str_isnumber(p) 237 const char *p; 238{ 239 char *q = (char *)p; 240 while (*q) { 241 if (! isdigit(*q)) 242 return NO; 243 q++; 244 } 245 return YES; 246} 247 248int 249getaddrinfo(hostname, servname, hints, res) 250 const char *hostname, *servname; 251 const struct addrinfo *hints; 252 struct addrinfo **res; 253{ 254 struct addrinfo sentinel; 255 struct addrinfo *cur; 256 int error = 0; 257 struct addrinfo ai; 258 struct addrinfo ai0; 259 struct addrinfo *pai; 260 const struct afd *afd; 261 const struct explore *ex; 262 263 sentinel.ai_next = NULL; 264 cur = &sentinel; 265 pai = &ai; 266 pai->ai_flags = 0; 267 pai->ai_family = PF_UNSPEC; 268 pai->ai_socktype = ANY; 269 pai->ai_protocol = ANY; 270 pai->ai_addrlen = 0; 271 pai->ai_canonname = NULL; 272 pai->ai_addr = NULL; 273 pai->ai_next = NULL; 274 275 if (hostname == NULL && servname == NULL) 276 return EAI_NONAME; 277 if (res == NULL) 278 return EAI_RESNULL; /* xxx */ 279 if (hints) { 280 /* error check for hints */ 281 if (hints->ai_addrlen || hints->ai_canonname || 282 hints->ai_addr || hints->ai_next) 283 ERR(EAI_BADHINTS); /* xxx */ 284 if (hints->ai_flags & ~AI_MASK) 285 ERR(EAI_BADFLAGS); 286 switch (hints->ai_family) { 287 case PF_UNSPEC: 288 case PF_INET: 289#ifdef INET6 290 case PF_INET6: 291#endif 292 break; 293 default: 294 ERR(EAI_FAMILY); 295 } 296 memcpy(pai, hints, sizeof(*pai)); 297 298 /* 299 * if both socktype/protocol are specified, check if they 300 * are meaningful combination. 301 */ 302 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 303 int matched = 0; 304 305 for (ex = explore; ex->e_af >= 0; ex++) { 306 if (pai->ai_family != ex->e_af) 307 continue; 308 if (ex->e_socktype == ANY) 309 continue; 310 if (ex->e_protocol == ANY) 311 continue; 312 if (pai->ai_socktype == ex->e_socktype 313 && pai->ai_protocol == ex->e_protocol) 314 matched = 1; 315 else 316 continue; 317 if (matched == 0) 318 ERR(EAI_BADHINTS); 319 } 320 } 321 } 322 323 /* backup original pai contents */ 324 ai0 = *pai; 325 326 /* 327 * special cases check for inet and inet6 sockets. 328 * (1) servname is disallowed for raw sockets. 329 * (2) numeric servname is disallowed if socktype/protocol is left 330 * unspecified. 331 */ 332 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 333#ifdef INET6 334 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 335#endif 336 ) { 337 *pai = ai0; 338 339 if (pai->ai_family == PF_UNSPEC) 340#ifdef INET6 341 pai->ai_family = PF_INET6; 342#else 343 pai->ai_family = PF_INET; 344#endif 345 error = get_portmatch(pai, servname); 346 if (error) 347 ERR(error); 348 } 349 350 /* NULL hostname, or numeric hostname */ 351 for (ex = explore; ex->e_af >= 0; ex++) { 352 *pai = ai0; 353 354 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 355 continue; 356 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 357 continue; 358 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 359 continue; 360 361 if (pai->ai_family == PF_UNSPEC) 362 pai->ai_family = ex->e_af; 363 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 364 pai->ai_socktype = ex->e_socktype; 365 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 366 pai->ai_protocol = ex->e_protocol; 367 368 if (hostname == NULL) 369 error = explore_null(pai, hostname, servname, &cur->ai_next); 370 else 371 error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next); 372 373 if (error) 374 goto free; 375 376 while (cur && cur->ai_next) 377 cur = cur->ai_next; 378 } 379 380 /* 381 * XXX 382 * If numreic representation of AF1 can be interpreted as FQDN 383 * representation of AF2, we need to think again about the code below. 384 */ 385 if (sentinel.ai_next) 386 goto good; 387 388 if (pai->ai_flags & AI_NUMERICHOST) 389 ERR(EAI_NONAME); 390 if (hostname == NULL) 391 ERR(EAI_NONAME); 392 393 /* 394 * hostname as alphabetical name. 395 * we would like to prefer AF_INET6 than AF_INET, so we'll make a 396 * outer loop by AFs. 397 */ 398 for (afd = afdl; afd->a_af; afd++) { 399 *pai = ai0; 400 401 if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1)) 402 continue; 403 404 for (ex = explore; ex->e_af >= 0; ex++) { 405 *pai = ai0; 406 407 if (pai->ai_family == PF_UNSPEC) 408 pai->ai_family = afd->a_af; 409 410 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, 411 WILD_AF(ex))) 412 continue; 413 if (!MATCH(pai->ai_socktype, ex->e_socktype, 414 WILD_SOCKTYPE(ex))) { 415 continue; 416 } 417 if (!MATCH(pai->ai_protocol, ex->e_protocol, 418 WILD_PROTOCOL(ex))) { 419 continue; 420 } 421 422 if (pai->ai_family == PF_UNSPEC) 423 pai->ai_family = ex->e_af; 424 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 425 pai->ai_socktype = ex->e_socktype; 426 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 427 pai->ai_protocol = ex->e_protocol; 428 429 error = explore_fqdn(pai, hostname, servname, 430 &cur->ai_next); 431 432 while (cur && cur->ai_next) 433 cur = cur->ai_next; 434 } 435 } 436 437 /* XXX: if any addrinfo found, SUCCESS return even if (error != 0) */ 438 if (sentinel.ai_next) { 439 good: 440 *res = sentinel.ai_next; 441 return SUCCESS; 442 } 443 /* else, failed */ 444 free: 445 bad: 446 if (error == 0) 447 error = EAI_FAIL; 448 if (sentinel.ai_next) 449 freeaddrinfo(sentinel.ai_next); 450 *res = NULL; 451 return error; 452} 453 454/* 455 * FQDN hostname, DNS lookup 456 */ 457static int 458explore_fqdn(pai, hostname, servname, res) 459 const struct addrinfo *pai; 460 const char *hostname; 461 const char *servname; 462 struct addrinfo **res; 463{ 464 int s; 465 struct hostent *hp; 466 int h_error; 467 int af; 468 char *ap; 469 struct addrinfo sentinel, *cur; 470 int i; 471 const struct afd *afd; 472 int error; 473 474 *res = NULL; 475 sentinel.ai_next = NULL; 476 cur = &sentinel; 477 478 /* 479 * filter out AFs that are not supported by the kernel 480 * XXX errno? 481 */ 482 s = socket(pai->ai_family, SOCK_DGRAM, 0); 483 if (s < 0) 484 return 0; 485 _libc_close(s); 486 487 /* 488 * if the servname does not match socktype/protocol, ignore it. 489 */ 490 if (get_portmatch(pai, servname) != 0) 491 return 0; 492 493 afd = find_afd(pai->ai_family); 494 if (afd == NULL) 495 return 0; 496 497 hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, 498 &h_error); 499 if (hp == NULL) { 500 switch (h_error) { 501 case HOST_NOT_FOUND: 502 case NO_DATA: 503 error = EAI_NODATA; 504 break; 505 case TRY_AGAIN: 506 error = EAI_AGAIN; 507 break; 508 case NO_RECOVERY: 509 case NETDB_INTERNAL: 510 default: 511 error = EAI_FAIL; 512 break; 513 } 514 } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0) 515 || (hp->h_addr_list[0] == NULL)) { 516 freehostent(hp); 517 hp = NULL; 518 error = EAI_FAIL; 519 } 520 521 if (hp == NULL) 522 goto free; 523 524 for (i = 0; hp->h_addr_list[i] != NULL; i++) { 525 af = hp->h_addrtype; 526 ap = hp->h_addr_list[i]; 527 528 if (af != pai->ai_family) 529 continue; 530 531 if ((pai->ai_flags & AI_CANONNAME) == 0) { 532 GET_AI(cur->ai_next, afd, ap); 533 GET_PORT(cur->ai_next, servname); 534 } else { 535 /* 536 * if AI_CANONNAME and if reverse lookup 537 * fail, return ai anyway to pacify 538 * calling application. 539 * 540 * XXX getaddrinfo() is a name->address 541 * translation function, and it looks 542 * strange that we do addr->name 543 * translation here. 544 */ 545 get_name(ap, afd, &cur->ai_next, 546 ap, pai, servname); 547 } 548 549 while (cur && cur->ai_next) 550 cur = cur->ai_next; 551 } 552 553 *res = sentinel.ai_next; 554 return 0; 555 556free: 557 if (hp) 558 freehostent(hp); 559 if (sentinel.ai_next) 560 freeaddrinfo(sentinel.ai_next); 561 return error; 562} 563 564/* 565 * hostname == NULL. 566 * passive socket -> anyaddr (0.0.0.0 or ::) 567 * non-passive socket -> localhost (127.0.0.1 or ::1) 568 */ 569static int 570explore_null(pai, hostname, servname, res) 571 const struct addrinfo *pai; 572 const char *hostname; 573 const char *servname; 574 struct addrinfo **res; 575{ 576 int s; 577 const struct afd *afd; 578 struct addrinfo *cur; 579 struct addrinfo sentinel; 580 int error; 581 582 *res = NULL; 583 sentinel.ai_next = NULL; 584 cur = &sentinel; 585 586 /* 587 * filter out AFs that are not supported by the kernel 588 * XXX errno? 589 */ 590 s = socket(pai->ai_family, SOCK_DGRAM, 0); 591 if (s < 0) 592 return 0; 593 _libc_close(s); 594 afd = find_afd(pai->ai_family); 595 if (afd == NULL) 596 return 0; 597 598 GET_AI(cur->ai_next, afd, 599 (pai->ai_flags & AI_PASSIVE) ? afd->a_addrany : afd->a_loopback 600 ); 601 /* xxx meaningless? 602 * GET_CANONNAME(cur->ai_next, "anyaddr"); 603 * or 604 * GET_CANONNAME(cur->ai_next, "localhost"); 605 */ 606 /* if the servname does not match socktype/protocol, ignored */ 607 GET_PORT(cur->ai_next, servname); 608 609 *res = sentinel.ai_next; 610 return 0; 611 612free: 613 if (sentinel.ai_next) 614 freeaddrinfo(sentinel.ai_next); 615 return error; 616} 617 618/* 619 * numeric hostname 620 */ 621static int 622explore_numeric(pai, hostname, servname, res) 623 const struct addrinfo *pai; 624 const char *hostname; 625 const char *servname; 626 struct addrinfo **res; 627{ 628 const struct afd *afd; 629 struct addrinfo *cur; 630 struct addrinfo sentinel; 631 int error; 632 char pton[PTON_MAX]; 633 int flags; 634 635 *res = NULL; 636 sentinel.ai_next = NULL; 637 cur = &sentinel; 638 639 /* 640 * if the servname does not match socktype/protocol, ignore it. 641 */ 642 if (get_portmatch(pai, servname) != 0) 643 return 0; 644 645 afd = find_afd(pai->ai_family); 646 if (afd == NULL) 647 return 0; 648 flags = pai->ai_flags; 649 650 if (inet_pton(afd->a_af, hostname, pton) == 1) { 651 u_int32_t v4a; 652#ifdef INET6 653 struct in6_addr * v6a; 654#endif 655 656 switch (afd->a_af) { 657 case AF_INET: 658 v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr); 659 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) 660 flags &= ~AI_CANONNAME; 661 v4a >>= IN_CLASSA_NSHIFT; 662 if (v4a == 0 || v4a == IN_LOOPBACKNET) 663 flags &= ~AI_CANONNAME; 664 break; 665#ifdef INET6 666 case AF_INET6: 667 v6a = (struct in6_addr *)pton; 668 if (IN6_IS_ADDR_MULTICAST(v6a)) 669 flags &= ~AI_CANONNAME; 670 if (IN6_IS_ADDR_UNSPECIFIED(v6a) || 671 IN6_IS_ADDR_LOOPBACK(v6a)) 672 flags &= ~AI_CANONNAME; 673 if (IN6_IS_ADDR_LINKLOCAL(v6a)) 674 flags &= ~AI_CANONNAME; 675 676 /* should also do this for SITELOCAL ?? */ 677 678 break; 679#endif 680 } 681 682 if (pai->ai_family == afd->a_af || 683 pai->ai_family == PF_UNSPEC /*?*/) { 684 if ((flags & AI_CANONNAME) == 0) { 685 GET_AI(cur->ai_next, afd, pton); 686 GET_PORT(cur->ai_next, servname); 687 } else { 688 /* 689 * if AI_CANONNAME and if reverse lookup 690 * fail, return ai anyway to pacify 691 * calling application. 692 * 693 * XXX getaddrinfo() is a name->address 694 * translation function, and it looks 695 * strange that we do addr->name 696 * translation here. 697 */ 698 get_name(pton, afd, &cur->ai_next, 699 pton, pai, servname); 700 } 701 while (cur && cur->ai_next) 702 cur = cur->ai_next; 703 } else 704 ERR(EAI_FAMILY); /*xxx*/ 705 } 706 707 *res = sentinel.ai_next; 708 return 0; 709 710free: 711bad: 712 if (sentinel.ai_next) 713 freeaddrinfo(sentinel.ai_next); 714 return error; 715} 716 717/* 718 * numeric hostname with scope 719 */ 720static int 721explore_numeric_scope(pai, hostname, servname, res) 722 const struct addrinfo *pai; 723 const char *hostname; 724 const char *servname; 725 struct addrinfo **res; 726{ 727#ifndef SCOPE_DELIMITER 728 return explore_numeric(pai, hostname, servname, res); 729#else 730 const struct afd *afd; 731 struct addrinfo *cur; 732 int error; 733 char *cp, *hostname2 = NULL; 734 int scope; 735#ifdef INET6 736 struct sockaddr_in6 *sin6; 737#endif 738 739 /* 740 * if the servname does not match socktype/protocol, ignore it. 741 */ 742 if (get_portmatch(pai, servname) != 0) 743 return 0; 744 745 afd = find_afd(pai->ai_family); 746 if (afd == NULL) 747 return 0; 748 if (!afd->a_scoped) 749 return explore_numeric(pai, hostname, servname, res); 750 751 cp = strchr(hostname, SCOPE_DELIMITER); 752 if (cp == NULL) 753 return explore_numeric(pai, hostname, servname, res); 754 755 /* 756 * Handle special case of <scoped_address><delimiter><scope id> 757 */ 758 hostname2 = strdup(hostname); 759 if (hostname2 == NULL) 760 return EAI_MEMORY; 761 /* terminate at the delimiter */ 762 hostname2[cp - hostname] = '\0'; 763 764 cp++; 765 switch (pai->ai_family) { 766#ifdef INET6 767 case AF_INET6: 768 scope = if_nametoindex(cp); 769 if (scope == 0) { 770 error = EAI_SYSTEM; 771 goto free; 772 } 773 break; 774#endif 775 } 776 777 error = explore_numeric(pai, hostname2, servname, res); 778 if (error == 0) { 779 for (cur = *res; cur; cur = cur->ai_next) { 780#ifdef INET6 781 if (cur->ai_family != AF_INET6) 782 continue; 783 sin6 = (struct sockaddr_in6 *)cur->ai_addr; 784 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 785 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) 786 sin6->sin6_scope_id = scope; 787#endif 788 } 789 } 790 791#ifdef INET6 792free: 793#endif 794 free(hostname2); 795 796 return error; 797#endif 798} 799 800static int 801get_name(addr, afd, res, numaddr, pai, servname) 802 const char *addr; 803 const struct afd *afd; 804 struct addrinfo **res; 805 char *numaddr; 806 const struct addrinfo *pai; 807 const char *servname; 808{ 809 struct hostent *hp; 810 struct addrinfo *cur; 811 int error = 0; 812 int h_error; 813 814 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); 815 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { 816 GET_AI(cur, afd, hp->h_addr_list[0]); 817 GET_PORT(cur, servname); 818 GET_CANONNAME(cur, hp->h_name); 819 } else { 820 GET_AI(cur, afd, numaddr); 821 GET_PORT(cur, servname); 822 } 823 824 if (hp) 825 freehostent(hp); 826 *res = cur; 827 return SUCCESS; 828 free: 829 if (cur) 830 freeaddrinfo(cur); 831 if (hp) 832 freehostent(hp); 833 /* bad: */ 834 *res = NULL; 835 return error; 836} 837 838static int 839get_canonname(pai, ai, str) 840 const struct addrinfo *pai; 841 struct addrinfo *ai; 842 const char *str; 843{ 844 if ((pai->ai_flags & AI_CANONNAME) != 0) { 845 ai->ai_canonname = (char *)malloc(strlen(str) + 1); 846 if (ai->ai_canonname == NULL) 847 return EAI_MEMORY; 848 strcpy(ai->ai_canonname, str); 849 } 850 return 0; 851} 852 853static struct addrinfo * 854get_ai(pai, afd, addr) 855 const struct addrinfo *pai; 856 const struct afd *afd; 857 const char *addr; 858{ 859 char *p; 860 struct addrinfo *ai; 861#ifdef FAITH 862 struct in6_addr faith_prefix; 863 char *fp_str; 864 int translate = 0; 865#endif 866 867#ifdef FAITH 868 /* 869 * Transfrom an IPv4 addr into a special IPv6 addr format for 870 * IPv6->IPv4 translation gateway. (only TCP is supported now) 871 * 872 * +-----------------------------------+------------+ 873 * | faith prefix part (12 bytes) | embedded | 874 * | | IPv4 addr part (4 bytes) 875 * +-----------------------------------+------------+ 876 * 877 * faith prefix part is specified as ascii IPv6 addr format 878 * in environmental variable GAI. 879 * For FAITH to work correctly, routing to faith prefix must be 880 * setup toward a machine where a FAITH daemon operates. 881 * Also, the machine must enable some mechanizm 882 * (e.g. faith interface hack) to divert those packet with 883 * faith prefixed destination addr to user-land FAITH daemon. 884 */ 885 fp_str = getenv("GAI"); 886 if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 && 887 afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) { 888 u_int32_t v4a; 889 u_int8_t v4a_top; 890 891 memcpy(&v4a, addr, sizeof v4a); 892 v4a_top = v4a >> IN_CLASSA_NSHIFT; 893 if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) && 894 v4a_top != 0 && v4a != IN_LOOPBACKNET) { 895 afd = &afdl[N_INET6]; 896 memcpy(&faith_prefix.s6_addr[12], addr, 897 sizeof(struct in_addr)); 898 translate = 1; 899 } 900 } 901#endif 902 903 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 904 + (afd->a_socklen)); 905 if (ai == NULL) 906 return NULL; 907 908 memcpy(ai, pai, sizeof(struct addrinfo)); 909 ai->ai_addr = (struct sockaddr *)(ai + 1); 910 memset(ai->ai_addr, 0, afd->a_socklen); 911 ai->ai_addr->sa_len = afd->a_socklen; 912 ai->ai_addrlen = afd->a_socklen; 913 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 914 p = (char *)(ai->ai_addr); 915#ifdef FAITH 916 if (translate == 1) 917 memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen); 918 else 919#endif 920 memcpy(p + afd->a_off, addr, afd->a_addrlen); 921 922 return ai; 923} 924 925static int 926get_portmatch(ai, servname) 927 const struct addrinfo *ai; 928 const char *servname; 929{ 930 /* get_port does not touch first argument. when matchonly == 1. */ 931 return get_port((struct addrinfo *)ai, servname, 1); 932} 933 934static int 935get_port(ai, servname, matchonly) 936 struct addrinfo *ai; 937 const char *servname; 938 int matchonly; 939{ 940 const char *proto; 941 struct servent *sp; 942 int port; 943 int allownumeric; 944 945 if (servname == NULL) 946 return 0; 947 if (ai->ai_family != AF_INET 948#ifdef INET6 949 && ai->ai_family != AF_INET6 950#endif 951 ) 952 return 0; 953 954 switch (ai->ai_socktype) { 955 case SOCK_RAW: 956 return EAI_SERVICE; 957 case SOCK_DGRAM: 958 case SOCK_STREAM: 959 allownumeric = 1; 960 break; 961 case ANY: 962 allownumeric = 0; 963 break; 964 default: 965 return EAI_SOCKTYPE; 966 } 967 968 if (str_isnumber(servname)) { 969 if (!allownumeric) 970 return EAI_SERVICE; 971 port = htons(atoi(servname)); 972 if (port < 0 || port > 65535) 973 return EAI_SERVICE; 974 } else { 975 switch (ai->ai_socktype) { 976 case SOCK_DGRAM: 977 proto = "udp"; 978 break; 979 case SOCK_STREAM: 980 proto = "tcp"; 981 break; 982 default: 983 proto = NULL; 984 break; 985 } 986 987 if ((sp = getservbyname(servname, proto)) == NULL) 988 return EAI_SERVICE; 989 port = sp->s_port; 990 } 991 992 if (!matchonly) { 993 switch (ai->ai_family) { 994 case AF_INET: 995 ((struct sockaddr_in *)ai->ai_addr)->sin_port = port; 996 break; 997#ifdef INET6 998 case AF_INET6: 999 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port; 1000 break; 1001#endif 1002 } 1003 } 1004 1005 return 0; 1006} 1007 1008static const struct afd * 1009find_afd(af) 1010 int af; 1011{ 1012 const struct afd *afd; 1013 1014 if (af == PF_UNSPEC) 1015 return NULL; 1016 for (afd = afdl; afd->a_af; afd++) { 1017 if (afd->a_af == af) 1018 return afd; 1019 } 1020 return NULL; 1021} 1022