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$ 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 * Note: 41 * - We use getipnodebyname() just for thread-safeness. There's no intent 42 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to 43 * getipnodebyname(). 44 * - The code filters out AFs that are not supported by the kernel, 45 * when globbing NULL hostname (to loopback, or wildcard). Is it the right 46 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 47 * in ai_flags? 48 */ 49 50 #include <sys/types.h> 51 #include <sys/param.h> 52 #include <sys/socket.h> 53 #include <net/if.h> 54 #include <netinet/in.h> 55 #include <arpa/inet.h> 56 #include <arpa/nameser.h> 57 #include <netdb.h> 58 #include <resolv.h> 59 #include <string.h> 60 #include <stdlib.h> 61 #include <stddef.h> 62 #include <ctype.h> 63 #include <unistd.h> 64 #include <stdio.h> 65 66 #if defined(__KAME__) && defined(INET6) 67 # define FAITH 68 #endif 69 70 #define SUCCESS 0 71 #define ANY 0 72 #define YES 1 73 #define NO 0 74 75 static const char in_addrany[] = { 0, 0, 0, 0 }; 76 static const char in6_addrany[] = { 77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 78 }; 79 static const char in_loopback[] = { 127, 0, 0, 1 }; 80 static const char in6_loopback[] = { 81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 82 }; 83 84 static const struct afd { 85 int a_af; 86 int a_addrlen; 87 int a_socklen; 88 int a_off; 89 const char *a_addrany; 90 const char *a_loopback; 91 int a_scoped; 92 } afdl [] = { 93 #ifdef INET6 94 #define N_INET6 0 95 {PF_INET6, sizeof(struct in6_addr), 96 sizeof(struct sockaddr_in6), 97 offsetof(struct sockaddr_in6, sin6_addr), 98 in6_addrany, in6_loopback, 1}, 99 #define N_INET 1 100 #else 101 #define N_INET 0 102 #endif 103 {PF_INET, sizeof(struct in_addr), 104 sizeof(struct sockaddr_in), 105 offsetof(struct sockaddr_in, sin_addr), 106 in_addrany, in_loopback, 0}, 107 {0, 0, 0, 0, NULL, NULL, 0}, 108 }; 109 110 struct explore { 111 int e_socktype; 112 int e_protocol; 113 const char *e_protostr; 114 int e_wild; 115 #define WILD_AF(ex) ((ex)->e_wild & 0x01) 116 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 117 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 118 }; 119 120 static const struct explore explore[] = { 121 { SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 122 { SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 123 { SOCK_RAW, ANY, NULL, 0x05 }, 124 { 0, 0, NULL, 0 }, 125 }; 126 127 #ifdef INET6 128 #define PTON_MAX 16 129 #else 130 #define PTON_MAX 4 131 #endif 132 133 extern struct hostent * _getipnodebyname_multi __P((const char *name, 134 int af, int flags, int *errp)); 135 static int str_isnumber __P((const char *)); 136 static int explore_fqdn __P((const struct addrinfo *, const char *, 137 const char *, struct addrinfo **)); 138 static int explore_null __P((const struct addrinfo *, const char *, 139 const char *, struct addrinfo **)); 140 static int explore_numeric __P((const struct addrinfo *, const char *, 141 const char *, struct addrinfo **)); 142 static int explore_numeric_scope __P((const struct addrinfo *, const char *, 143 const char *, struct addrinfo **)); 144 static int get_canonname __P((const struct addrinfo *, 145 struct addrinfo *, const char *)); 146 static struct addrinfo *get_ai __P((const struct addrinfo *, 147 const struct afd *, const char *)); 148 static int get_portmatch __P((const struct addrinfo *, const char *)); 149 static int get_port __P((struct addrinfo *, const char *, int)); 150 static const struct afd *find_afd __P((int)); 151 152 static 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) \ 174 do { \ 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) \ 184 do { \ 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) \ 192 do { \ 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) \ 200 do { \ 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 211 char * 212 gai_strerror(ecode) 213 int ecode; 214 { 215 if (ecode < 0 || ecode > EAI_MAX) 216 ecode = EAI_MAX; 217 return ai_errlist[ecode]; 218 } 219 220 void 221 freeaddrinfo(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 235 static int 236 str_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 248 int 249 getaddrinfo(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_socktype; ex++) { 306 if (ex->e_socktype == ANY) 307 continue; 308 if (ex->e_protocol == ANY) 309 continue; 310 if (pai->ai_socktype == ex->e_socktype 311 && pai->ai_protocol == ex->e_protocol) 312 matched = 1; 313 else 314 continue; 315 if (matched == 0) 316 ERR(EAI_BADHINTS); 317 } 318 } 319 } 320 321 /* backup original pai contents */ 322 ai0 = *pai; 323 324 /* 325 * special cases check for inet and inet6 sockets. 326 * (1) servname is disallowed for raw sockets. 327 * (2) numeric servname is disallowed if socktype/protocol is left 328 * unspecified. 329 */ 330 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 331 #ifdef INET6 332 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 333 #endif 334 ) { 335 *pai = ai0; 336 337 if (pai->ai_family == PF_UNSPEC) 338 #ifdef INET6 339 pai->ai_family = PF_INET6; 340 #else 341 pai->ai_family = PF_INET; 342 #endif 343 error = get_portmatch(pai, servname); 344 if (error) 345 ERR(error); 346 } 347 348 /* NULL hostname, or numeric hostname */ 349 for (afd = afdl; afd->a_af; afd++) 350 { 351 for (ex = explore; ex->e_socktype; ex++) { 352 *pai = ai0; 353 354 if (!MATCH_FAMILY(pai->ai_family, afd->a_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 = afd->a_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 /* 382 * XXX 383 * If numreic representation of AF1 can be interpreted as FQDN 384 * representation of AF2, we need to think again about the code below. 385 */ 386 if (sentinel.ai_next) 387 goto good; 388 389 if (pai->ai_flags & AI_NUMERICHOST) 390 ERR(EAI_NONAME); 391 if (hostname == NULL) 392 ERR(EAI_NONAME); 393 394 /* hostname as alphabetical name. */ 395 { 396 for (ex = explore; ex->e_socktype; ex++) { 397 *pai = ai0; 398 399 if (!MATCH(pai->ai_socktype, ex->e_socktype, 400 WILD_SOCKTYPE(ex))) { 401 continue; 402 } 403 if (!MATCH(pai->ai_protocol, ex->e_protocol, 404 WILD_PROTOCOL(ex))) { 405 continue; 406 } 407 408 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 409 pai->ai_socktype = ex->e_socktype; 410 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 411 pai->ai_protocol = ex->e_protocol; 412 413 error = explore_fqdn(pai, hostname, servname, 414 &cur->ai_next); 415 416 while (cur && cur->ai_next) 417 cur = cur->ai_next; 418 } 419 } 420 421 /* XXX: if any addrinfo found, SUCCESS return even if (error != 0) */ 422 if (sentinel.ai_next) { 423 good: 424 *res = sentinel.ai_next; 425 return SUCCESS; 426 } 427 /* else, failed */ 428 free: 429 bad: 430 if (error == 0) 431 error = EAI_FAIL; 432 if (sentinel.ai_next) 433 freeaddrinfo(sentinel.ai_next); 434 *res = NULL; 435 return error; 436 } 437 438 /* 439 * FQDN hostname, DNS lookup 440 */ 441 static int 442 explore_fqdn(pai, hostname, servname, res) 443 const struct addrinfo *pai; 444 const char *hostname; 445 const char *servname; 446 struct addrinfo **res; 447 { 448 struct hostent *hp; 449 int h_error; 450 int af; 451 char *ap; 452 struct addrinfo sentinel, *cur; 453 int i; 454 const struct afd *afd; 455 int error; 456 457 *res = NULL; 458 sentinel.ai_next = NULL; 459 cur = &sentinel; 460 461 /* 462 * if the servname does not match socktype/protocol, ignore it. 463 */ 464 if (get_portmatch(pai, servname) != 0) 465 return 0; 466 467 hp = _getipnodebyname_multi(hostname, pai->ai_family, AI_ADDRCONFIG, 468 &h_error); 469 if (hp == NULL) { 470 switch (h_error) { 471 case HOST_NOT_FOUND: 472 case NO_DATA: 473 error = EAI_NODATA; 474 break; 475 case TRY_AGAIN: 476 error = EAI_AGAIN; 477 break; 478 case NO_RECOVERY: 479 case NETDB_INTERNAL: 480 default: 481 error = EAI_FAIL; 482 break; 483 } 484 } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0) 485 || (hp->h_addr_list[0] == NULL)) { 486 freehostent(hp); 487 hp = NULL; 488 error = EAI_FAIL; 489 } 490 491 if (hp == NULL) 492 goto free; 493 494 for (i = 0; hp->h_addr_list[i] != NULL; i++) { 495 af = hp->h_addrtype; 496 ap = hp->h_addr_list[i]; 497 498 if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) 499 continue; 500 501 afd = find_afd(af); 502 if (afd == NULL) 503 continue; 504 505 GET_AI(cur->ai_next, afd, ap); 506 GET_PORT(cur->ai_next, servname); 507 if ((pai->ai_flags & AI_CANONNAME) != 0) { 508 /* 509 * RFC2553 says that ai_canonname will be set only for 510 * the first element. we do it for all the elements, 511 * just for convenience. 512 */ 513 GET_CANONNAME(cur->ai_next, hp->h_name); 514 } 515 516 while (cur && cur->ai_next) 517 cur = cur->ai_next; 518 } 519 520 *res = sentinel.ai_next; 521 return 0; 522 523 free: 524 if (hp) 525 freehostent(hp); 526 if (sentinel.ai_next) 527 freeaddrinfo(sentinel.ai_next); 528 return error; 529 } 530 531 /* 532 * hostname == NULL. 533 * passive socket -> anyaddr (0.0.0.0 or ::) 534 * non-passive socket -> localhost (127.0.0.1 or ::1) 535 */ 536 static int 537 explore_null(pai, hostname, servname, res) 538 const struct addrinfo *pai; 539 const char *hostname; 540 const char *servname; 541 struct addrinfo **res; 542 { 543 int s; 544 const struct afd *afd; 545 struct addrinfo *cur; 546 struct addrinfo sentinel; 547 int error; 548 549 *res = NULL; 550 sentinel.ai_next = NULL; 551 cur = &sentinel; 552 553 /* 554 * filter out AFs that are not supported by the kernel 555 * XXX errno? 556 */ 557 s = socket(pai->ai_family, SOCK_DGRAM, 0); 558 if (s < 0) 559 return 0; 560 _close(s); 561 afd = find_afd(pai->ai_family); 562 if (afd == NULL) 563 return 0; 564 565 GET_AI(cur->ai_next, afd, 566 (pai->ai_flags & AI_PASSIVE) ? afd->a_addrany : afd->a_loopback 567 ); 568 /* xxx meaningless? 569 * GET_CANONNAME(cur->ai_next, "anyaddr"); 570 * or 571 * GET_CANONNAME(cur->ai_next, "localhost"); 572 */ 573 /* if the servname does not match socktype/protocol, ignored */ 574 GET_PORT(cur->ai_next, servname); 575 576 *res = sentinel.ai_next; 577 return 0; 578 579 free: 580 if (sentinel.ai_next) 581 freeaddrinfo(sentinel.ai_next); 582 return error; 583 } 584 585 /* 586 * numeric hostname 587 */ 588 static int 589 explore_numeric(pai, hostname, servname, res) 590 const struct addrinfo *pai; 591 const char *hostname; 592 const char *servname; 593 struct addrinfo **res; 594 { 595 const struct afd *afd; 596 struct addrinfo *cur; 597 struct addrinfo sentinel; 598 int error; 599 char pton[PTON_MAX]; 600 int flags; 601 602 *res = NULL; 603 sentinel.ai_next = NULL; 604 cur = &sentinel; 605 606 /* 607 * if the servname does not match socktype/protocol, ignore it. 608 */ 609 if (get_portmatch(pai, servname) != 0) 610 return 0; 611 612 afd = find_afd(pai->ai_family); 613 if (afd == NULL) 614 return 0; 615 flags = pai->ai_flags; 616 617 if ((afd->a_af == AF_INET 618 ? inet_aton(hostname, (struct in_addr *)pton) 619 : inet_pton(afd->a_af, hostname, pton)) == 1) { 620 if (pai->ai_family == afd->a_af || 621 pai->ai_family == PF_UNSPEC /*?*/) { 622 GET_AI(cur->ai_next, afd, pton); 623 GET_PORT(cur->ai_next, servname); 624 while (cur && cur->ai_next) 625 cur = cur->ai_next; 626 } else 627 ERR(EAI_FAMILY); /*xxx*/ 628 } 629 630 *res = sentinel.ai_next; 631 return 0; 632 633 free: 634 bad: 635 if (sentinel.ai_next) 636 freeaddrinfo(sentinel.ai_next); 637 return error; 638 } 639 640 /* 641 * numeric hostname with scope 642 */ 643 static int 644 explore_numeric_scope(pai, hostname, servname, res) 645 const struct addrinfo *pai; 646 const char *hostname; 647 const char *servname; 648 struct addrinfo **res; 649 { 650 #ifndef SCOPE_DELIMITER 651 return explore_numeric(pai, hostname, servname, res); 652 #else 653 const struct afd *afd; 654 struct addrinfo *cur; 655 int error; 656 char *cp, *hostname2 = NULL; 657 int scope; 658 #ifdef INET6 659 struct sockaddr_in6 *sin6; 660 #endif 661 662 /* 663 * if the servname does not match socktype/protocol, ignore it. 664 */ 665 if (get_portmatch(pai, servname) != 0) 666 return 0; 667 668 afd = find_afd(pai->ai_family); 669 if (afd == NULL) 670 return 0; 671 if (!afd->a_scoped) 672 return explore_numeric(pai, hostname, servname, res); 673 674 cp = strchr(hostname, SCOPE_DELIMITER); 675 if (cp == NULL) 676 return explore_numeric(pai, hostname, servname, res); 677 678 /* 679 * Handle special case of <scoped_address><delimiter><scope id> 680 */ 681 hostname2 = strdup(hostname); 682 if (hostname2 == NULL) 683 return EAI_MEMORY; 684 /* terminate at the delimiter */ 685 hostname2[cp - hostname] = '\0'; 686 687 cp++; 688 switch (pai->ai_family) { 689 #ifdef INET6 690 case AF_INET6: 691 scope = if_nametoindex(cp); 692 if (scope == 0) { 693 error = EAI_SYSTEM; 694 goto free; 695 } 696 break; 697 #endif 698 } 699 700 error = explore_numeric(pai, hostname2, servname, res); 701 if (error == 0) { 702 for (cur = *res; cur; cur = cur->ai_next) { 703 #ifdef INET6 704 if (cur->ai_family != AF_INET6) 705 continue; 706 sin6 = (struct sockaddr_in6 *)cur->ai_addr; 707 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 708 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) 709 sin6->sin6_scope_id = scope; 710 #endif 711 } 712 } 713 714 #ifdef INET6 715 free: 716 #endif 717 free(hostname2); 718 719 return error; 720 #endif 721 } 722 723 static int 724 get_canonname(pai, ai, str) 725 const struct addrinfo *pai; 726 struct addrinfo *ai; 727 const char *str; 728 { 729 if ((pai->ai_flags & AI_CANONNAME) != 0) { 730 ai->ai_canonname = (char *)malloc(strlen(str) + 1); 731 if (ai->ai_canonname == NULL) 732 return EAI_MEMORY; 733 strcpy(ai->ai_canonname, str); 734 } 735 return 0; 736 } 737 738 static struct addrinfo * 739 get_ai(pai, afd, addr) 740 const struct addrinfo *pai; 741 const struct afd *afd; 742 const char *addr; 743 { 744 char *p; 745 struct addrinfo *ai; 746 #ifdef FAITH 747 struct in6_addr faith_prefix; 748 char *fp_str; 749 int translate = 0; 750 #endif 751 752 #ifdef FAITH 753 /* 754 * Transfrom an IPv4 addr into a special IPv6 addr format for 755 * IPv6->IPv4 translation gateway. (only TCP is supported now) 756 * 757 * +-----------------------------------+------------+ 758 * | faith prefix part (12 bytes) | embedded | 759 * | | IPv4 addr part (4 bytes) 760 * +-----------------------------------+------------+ 761 * 762 * faith prefix part is specified as ascii IPv6 addr format 763 * in environmental variable GAI. 764 * For FAITH to work correctly, routing to faith prefix must be 765 * setup toward a machine where a FAITH daemon operates. 766 * Also, the machine must enable some mechanizm 767 * (e.g. faith interface hack) to divert those packet with 768 * faith prefixed destination addr to user-land FAITH daemon. 769 */ 770 fp_str = getenv("GAI"); 771 if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 && 772 afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) { 773 u_int32_t v4a; 774 u_int8_t v4a_top; 775 776 memcpy(&v4a, addr, sizeof v4a); 777 v4a_top = v4a >> IN_CLASSA_NSHIFT; 778 if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) && 779 v4a_top != 0 && v4a != IN_LOOPBACKNET) { 780 afd = &afdl[N_INET6]; 781 memcpy(&faith_prefix.s6_addr[12], addr, 782 sizeof(struct in_addr)); 783 translate = 1; 784 } 785 } 786 #endif 787 788 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 789 + (afd->a_socklen)); 790 if (ai == NULL) 791 return NULL; 792 793 memcpy(ai, pai, sizeof(struct addrinfo)); 794 ai->ai_addr = (struct sockaddr *)(ai + 1); 795 memset(ai->ai_addr, 0, afd->a_socklen); 796 ai->ai_addr->sa_len = afd->a_socklen; 797 ai->ai_addrlen = afd->a_socklen; 798 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 799 p = (char *)(ai->ai_addr); 800 #ifdef FAITH 801 if (translate == 1) 802 memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen); 803 else 804 #endif 805 memcpy(p + afd->a_off, addr, afd->a_addrlen); 806 807 return ai; 808 } 809 810 static int 811 get_portmatch(ai, servname) 812 const struct addrinfo *ai; 813 const char *servname; 814 { 815 /* get_port does not touch first argument. when matchonly == 1. */ 816 return get_port((struct addrinfo *)ai, servname, 1); 817 } 818 819 static int 820 get_port(ai, servname, matchonly) 821 struct addrinfo *ai; 822 const char *servname; 823 int matchonly; 824 { 825 const char *proto; 826 struct servent *sp; 827 int port; 828 int allownumeric; 829 830 if (servname == NULL) 831 return 0; 832 if (ai->ai_family != AF_INET 833 #ifdef INET6 834 && ai->ai_family != AF_INET6 835 #endif 836 ) 837 return 0; 838 839 switch (ai->ai_socktype) { 840 case SOCK_RAW: 841 return EAI_SERVICE; 842 case SOCK_DGRAM: 843 case SOCK_STREAM: 844 allownumeric = 1; 845 break; 846 case ANY: 847 allownumeric = 0; 848 break; 849 default: 850 return EAI_SOCKTYPE; 851 } 852 853 if (str_isnumber(servname)) { 854 if (!allownumeric) 855 return EAI_SERVICE; 856 port = htons(atoi(servname)); 857 if (port < 0 || port > 65535) 858 return EAI_SERVICE; 859 } else { 860 switch (ai->ai_socktype) { 861 case SOCK_DGRAM: 862 proto = "udp"; 863 break; 864 case SOCK_STREAM: 865 proto = "tcp"; 866 break; 867 default: 868 proto = NULL; 869 break; 870 } 871 872 if ((sp = getservbyname(servname, proto)) == NULL) 873 return EAI_SERVICE; 874 port = sp->s_port; 875 } 876 877 if (!matchonly) { 878 switch (ai->ai_family) { 879 case AF_INET: 880 ((struct sockaddr_in *)ai->ai_addr)->sin_port = port; 881 break; 882 #ifdef INET6 883 case AF_INET6: 884 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port; 885 break; 886 #endif 887 } 888 } 889 890 return 0; 891 } 892 893 static const struct afd * 894 find_afd(af) 895 int af; 896 { 897 const struct afd *afd; 898 899 if (af == PF_UNSPEC) 900 return NULL; 901 for (afd = afdl; afd->a_af; afd++) { 902 if (afd->a_af == af) 903 return afd; 904 } 905 return NULL; 906 } 907