getaddrinfo.c revision 57069
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 57069 2000-02-09 00:38:06Z shin $ 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 75static const char in_addrany[] = { 0, 0, 0, 0 }; 76static const char in6_addrany[] = { 77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 78}; 79static const char in_loopback[] = { 127, 0, 0, 1 }; 80static const char in6_loopback[] = { 81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 82}; 83 84static 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 110struct explore { 111 int e_af; 112 int e_socktype; 113 int e_protocol; 114 const char *e_protostr; 115 int e_wild; 116#define WILD_AF(ex) ((ex)->e_wild & 0x01) 117#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 118#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 119}; 120 121static const struct explore explore[] = { 122#ifdef INET6 123 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 124 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 125 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 126#endif 127 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 128 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 129 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 130 { -1, 0, 0, NULL, 0 }, 131}; 132 133#ifdef INET6 134#define PTON_MAX 16 135#else 136#define PTON_MAX 4 137#endif 138 139 140static int str_isnumber __P((const char *)); 141static int explore_fqdn __P((const struct addrinfo *, const char *, 142 const char *, struct addrinfo **)); 143static int explore_null __P((const struct addrinfo *, const char *, 144 const char *, struct addrinfo **)); 145static int explore_numeric __P((const struct addrinfo *, const char *, 146 const char *, struct addrinfo **)); 147static int explore_numeric_scope __P((const struct addrinfo *, const char *, 148 const char *, struct addrinfo **)); 149static int get_canonname __P((const struct addrinfo *, 150 struct addrinfo *, const char *)); 151static struct addrinfo *get_ai __P((const struct addrinfo *, 152 const struct afd *, const char *)); 153static int get_portmatch __P((const struct addrinfo *, const char *)); 154static int get_port __P((struct addrinfo *, const char *, int)); 155static const struct afd *find_afd __P((int)); 156 157static char *ai_errlist[] = { 158 "Success", 159 "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 160 "Temporary failure in name resolution", /* EAI_AGAIN */ 161 "Invalid value for ai_flags", /* EAI_BADFLAGS */ 162 "Non-recoverable failure in name resolution", /* EAI_FAIL */ 163 "ai_family not supported", /* EAI_FAMILY */ 164 "Memory allocation failure", /* EAI_MEMORY */ 165 "No address associated with hostname", /* EAI_NODATA */ 166 "hostname nor servname provided, or not known", /* EAI_NONAME */ 167 "servname not supported for ai_socktype", /* EAI_SERVICE */ 168 "ai_socktype not supported", /* EAI_SOCKTYPE */ 169 "System error returned in errno", /* EAI_SYSTEM */ 170 "Invalid value for hints", /* EAI_BADHINTS */ 171 "Resolved protocol is unknown", /* EAI_PROTOCOL */ 172 "Argument res is NULL", /* EAI_RESNULL */ 173 "Unknown error", /* EAI_MAX */ 174}; 175 176/* XXX macros that make external reference is BAD. */ 177 178#define GET_AI(ai, afd, addr) \ 179do { \ 180 /* external reference: pai, error, and label free */ \ 181 (ai) = get_ai(pai, (afd), (addr)); \ 182 if ((ai) == NULL) { \ 183 error = EAI_MEMORY; \ 184 goto free; \ 185 } \ 186} while (0) 187 188#define GET_PORT(ai, serv) \ 189do { \ 190 /* external reference: error and label free */ \ 191 error = get_port((ai), (serv), 0); \ 192 if (error != 0) \ 193 goto free; \ 194} while (0) 195 196#define GET_CANONNAME(ai, str) \ 197do { \ 198 /* external reference: pai, error and label free */ \ 199 error = get_canonname(pai, (ai), (str)); \ 200 if (error != 0) \ 201 goto free; \ 202} while (0) 203 204#define ERR(err) \ 205do { \ 206 /* external reference: error, and label bad */ \ 207 error = (err); \ 208 goto bad; \ 209} while (0) 210 211#define MATCH_FAMILY(x, y, w) \ 212 ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) 213#define MATCH(x, y, w) \ 214 ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY))) 215 216char * 217gai_strerror(ecode) 218 int ecode; 219{ 220 if (ecode < 0 || ecode > EAI_MAX) 221 ecode = EAI_MAX; 222 return ai_errlist[ecode]; 223} 224 225void 226freeaddrinfo(ai) 227 struct addrinfo *ai; 228{ 229 struct addrinfo *next; 230 231 do { 232 next = ai->ai_next; 233 if (ai->ai_canonname) 234 free(ai->ai_canonname); 235 /* no need to free(ai->ai_addr) */ 236 free(ai); 237 } while ((ai = next) != NULL); 238} 239 240static int 241str_isnumber(p) 242 const char *p; 243{ 244 char *q = (char *)p; 245 while (*q) { 246 if (! isdigit(*q)) 247 return NO; 248 q++; 249 } 250 return YES; 251} 252 253int 254getaddrinfo(hostname, servname, hints, res) 255 const char *hostname, *servname; 256 const struct addrinfo *hints; 257 struct addrinfo **res; 258{ 259 struct addrinfo sentinel; 260 struct addrinfo *cur; 261 int error = 0; 262 struct addrinfo ai; 263 struct addrinfo ai0; 264 struct addrinfo *pai; 265 const struct afd *afd; 266 const struct explore *ex; 267 268 sentinel.ai_next = NULL; 269 cur = &sentinel; 270 pai = &ai; 271 pai->ai_flags = 0; 272 pai->ai_family = PF_UNSPEC; 273 pai->ai_socktype = ANY; 274 pai->ai_protocol = ANY; 275 pai->ai_addrlen = 0; 276 pai->ai_canonname = NULL; 277 pai->ai_addr = NULL; 278 pai->ai_next = NULL; 279 280 if (hostname == NULL && servname == NULL) 281 return EAI_NONAME; 282 if (res == NULL) 283 return EAI_RESNULL; /* xxx */ 284 if (hints) { 285 /* error check for hints */ 286 if (hints->ai_addrlen || hints->ai_canonname || 287 hints->ai_addr || hints->ai_next) 288 ERR(EAI_BADHINTS); /* xxx */ 289 if (hints->ai_flags & ~AI_MASK) 290 ERR(EAI_BADFLAGS); 291 switch (hints->ai_family) { 292 case PF_UNSPEC: 293 case PF_INET: 294#ifdef INET6 295 case PF_INET6: 296#endif 297 break; 298 default: 299 ERR(EAI_FAMILY); 300 } 301 memcpy(pai, hints, sizeof(*pai)); 302 303 /* 304 * if both socktype/protocol are specified, check if they 305 * are meaningful combination. 306 */ 307 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 308 int matched = 0; 309 310 for (ex = explore; ex->e_af >= 0; ex++) { 311 if (pai->ai_family != ex->e_af) 312 continue; 313 if (ex->e_socktype == ANY) 314 continue; 315 if (ex->e_protocol == ANY) 316 continue; 317 if (pai->ai_socktype == ex->e_socktype 318 && pai->ai_protocol == ex->e_protocol) 319 matched = 1; 320 else 321 continue; 322 if (matched == 0) 323 ERR(EAI_BADHINTS); 324 } 325 } 326 } 327 328 /* backup original pai contents */ 329 ai0 = *pai; 330 331 /* 332 * special cases check for inet and inet6 sockets. 333 * (1) servname is disallowed for raw sockets. 334 * (2) numeric servname is disallowed if socktype/protocol is left 335 * unspecified. 336 */ 337 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 338#ifdef INET6 339 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 340#endif 341 ) { 342 *pai = ai0; 343 344 if (pai->ai_family == PF_UNSPEC) 345#ifdef INET6 346 pai->ai_family = PF_INET6; 347#else 348 pai->ai_family = PF_INET; 349#endif 350 error = get_portmatch(pai, servname); 351 if (error) 352 ERR(error); 353 } 354 355 /* NULL hostname, or numeric hostname */ 356 for (ex = explore; ex->e_af >= 0; ex++) { 357 *pai = ai0; 358 359 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 360 continue; 361 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 362 continue; 363 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 364 continue; 365 366 if (pai->ai_family == PF_UNSPEC) 367 pai->ai_family = ex->e_af; 368 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 369 pai->ai_socktype = ex->e_socktype; 370 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 371 pai->ai_protocol = ex->e_protocol; 372 373 if (hostname == NULL) 374 error = explore_null(pai, hostname, servname, &cur->ai_next); 375 else 376 error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next); 377 378 if (error) 379 goto free; 380 381 while (cur && cur->ai_next) 382 cur = cur->ai_next; 383 } 384 385 /* 386 * XXX 387 * If numreic representation of AF1 can be interpreted as FQDN 388 * representation of AF2, we need to think again about the code below. 389 */ 390 if (sentinel.ai_next) 391 goto good; 392 393 if (pai->ai_flags & AI_NUMERICHOST) 394 ERR(EAI_NONAME); 395 if (hostname == NULL) 396 ERR(EAI_NONAME); 397 398 /* 399 * hostname as alphabetical name. 400 * we would like to prefer AF_INET6 than AF_INET, so we'll make a 401 * outer loop by AFs. 402 */ 403 for (afd = afdl; afd->a_af; afd++) { 404 *pai = ai0; 405 406 if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1)) 407 continue; 408 409 for (ex = explore; ex->e_af >= 0; ex++) { 410 *pai = ai0; 411 412 if (pai->ai_family == PF_UNSPEC) 413 pai->ai_family = afd->a_af; 414 415 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, 416 WILD_AF(ex))) 417 continue; 418 if (!MATCH(pai->ai_socktype, ex->e_socktype, 419 WILD_SOCKTYPE(ex))) { 420 continue; 421 } 422 if (!MATCH(pai->ai_protocol, ex->e_protocol, 423 WILD_PROTOCOL(ex))) { 424 continue; 425 } 426 427 if (pai->ai_family == PF_UNSPEC) 428 pai->ai_family = ex->e_af; 429 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 430 pai->ai_socktype = ex->e_socktype; 431 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 432 pai->ai_protocol = ex->e_protocol; 433 434 error = explore_fqdn(pai, hostname, servname, 435 &cur->ai_next); 436 437 while (cur && cur->ai_next) 438 cur = cur->ai_next; 439 } 440 } 441 442 /* XXX: if any addrinfo found, SUCCESS return even if (error != 0) */ 443 if (sentinel.ai_next) { 444 good: 445 *res = sentinel.ai_next; 446 return SUCCESS; 447 } 448 /* else, failed */ 449 free: 450 bad: 451 if (error == 0) 452 error = EAI_FAIL; 453 if (sentinel.ai_next) 454 freeaddrinfo(sentinel.ai_next); 455 *res = NULL; 456 return error; 457} 458 459/* 460 * FQDN hostname, DNS lookup 461 */ 462static int 463explore_fqdn(pai, hostname, servname, res) 464 const struct addrinfo *pai; 465 const char *hostname; 466 const char *servname; 467 struct addrinfo **res; 468{ 469 struct hostent *hp; 470 int h_error; 471 int af; 472 char *ap; 473 struct addrinfo sentinel, *cur; 474 int i; 475 const struct afd *afd; 476 int error; 477 478 *res = NULL; 479 sentinel.ai_next = NULL; 480 cur = &sentinel; 481 482 /* 483 * if the servname does not match socktype/protocol, ignore it. 484 */ 485 if (get_portmatch(pai, servname) != 0) 486 return 0; 487 488 afd = find_afd(pai->ai_family); 489 if (afd == NULL) 490 return 0; 491 492 hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, 493 &h_error); 494 if (hp == NULL) { 495 switch (h_error) { 496 case HOST_NOT_FOUND: 497 case NO_DATA: 498 error = EAI_NODATA; 499 break; 500 case TRY_AGAIN: 501 error = EAI_AGAIN; 502 break; 503 case NO_RECOVERY: 504 case NETDB_INTERNAL: 505 default: 506 error = EAI_FAIL; 507 break; 508 } 509 } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0) 510 || (hp->h_addr_list[0] == NULL)) { 511 freehostent(hp); 512 hp = NULL; 513 error = EAI_FAIL; 514 } 515 516 if (hp == NULL) 517 goto free; 518 519 for (i = 0; hp->h_addr_list[i] != NULL; i++) { 520 af = hp->h_addrtype; 521 ap = hp->h_addr_list[i]; 522 523 if (af != pai->ai_family) 524 continue; 525 526 GET_AI(cur->ai_next, afd, ap); 527 GET_PORT(cur->ai_next, servname); 528 if ((pai->ai_flags & AI_CANONNAME) != 0) { 529 /* 530 * RFC2553 says that ai_canonname will be set only for 531 * the first element. we do it for all the elements, 532 * just for convenience. 533 */ 534 GET_CANONNAME(cur->ai_next, hp->h_name); 535 } 536 537 while (cur && cur->ai_next) 538 cur = cur->ai_next; 539 } 540 541 *res = sentinel.ai_next; 542 return 0; 543 544free: 545 if (hp) 546 freehostent(hp); 547 if (sentinel.ai_next) 548 freeaddrinfo(sentinel.ai_next); 549 return error; 550} 551 552/* 553 * hostname == NULL. 554 * passive socket -> anyaddr (0.0.0.0 or ::) 555 * non-passive socket -> localhost (127.0.0.1 or ::1) 556 */ 557static int 558explore_null(pai, hostname, servname, res) 559 const struct addrinfo *pai; 560 const char *hostname; 561 const char *servname; 562 struct addrinfo **res; 563{ 564 int s; 565 const struct afd *afd; 566 struct addrinfo *cur; 567 struct addrinfo sentinel; 568 int error; 569 570 *res = NULL; 571 sentinel.ai_next = NULL; 572 cur = &sentinel; 573 574 /* 575 * filter out AFs that are not supported by the kernel 576 * XXX errno? 577 */ 578 s = socket(pai->ai_family, SOCK_DGRAM, 0); 579 if (s < 0) 580 return 0; 581 _close(s); 582 afd = find_afd(pai->ai_family); 583 if (afd == NULL) 584 return 0; 585 586 GET_AI(cur->ai_next, afd, 587 (pai->ai_flags & AI_PASSIVE) ? afd->a_addrany : afd->a_loopback 588 ); 589 /* xxx meaningless? 590 * GET_CANONNAME(cur->ai_next, "anyaddr"); 591 * or 592 * GET_CANONNAME(cur->ai_next, "localhost"); 593 */ 594 /* if the servname does not match socktype/protocol, ignored */ 595 GET_PORT(cur->ai_next, servname); 596 597 *res = sentinel.ai_next; 598 return 0; 599 600free: 601 if (sentinel.ai_next) 602 freeaddrinfo(sentinel.ai_next); 603 return error; 604} 605 606/* 607 * numeric hostname 608 */ 609static int 610explore_numeric(pai, hostname, servname, res) 611 const struct addrinfo *pai; 612 const char *hostname; 613 const char *servname; 614 struct addrinfo **res; 615{ 616 const struct afd *afd; 617 struct addrinfo *cur; 618 struct addrinfo sentinel; 619 int error; 620 char pton[PTON_MAX]; 621 int flags; 622 623 *res = NULL; 624 sentinel.ai_next = NULL; 625 cur = &sentinel; 626 627 /* 628 * if the servname does not match socktype/protocol, ignore it. 629 */ 630 if (get_portmatch(pai, servname) != 0) 631 return 0; 632 633 afd = find_afd(pai->ai_family); 634 if (afd == NULL) 635 return 0; 636 flags = pai->ai_flags; 637 638 if (inet_pton(afd->a_af, hostname, pton) == 1) { 639 if (pai->ai_family == afd->a_af || 640 pai->ai_family == PF_UNSPEC /*?*/) { 641 GET_AI(cur->ai_next, afd, pton); 642 GET_PORT(cur->ai_next, servname); 643 while (cur && cur->ai_next) 644 cur = cur->ai_next; 645 } else 646 ERR(EAI_FAMILY); /*xxx*/ 647 } 648 649 *res = sentinel.ai_next; 650 return 0; 651 652free: 653bad: 654 if (sentinel.ai_next) 655 freeaddrinfo(sentinel.ai_next); 656 return error; 657} 658 659/* 660 * numeric hostname with scope 661 */ 662static int 663explore_numeric_scope(pai, hostname, servname, res) 664 const struct addrinfo *pai; 665 const char *hostname; 666 const char *servname; 667 struct addrinfo **res; 668{ 669#ifndef SCOPE_DELIMITER 670 return explore_numeric(pai, hostname, servname, res); 671#else 672 const struct afd *afd; 673 struct addrinfo *cur; 674 int error; 675 char *cp, *hostname2 = NULL; 676 int scope; 677#ifdef INET6 678 struct sockaddr_in6 *sin6; 679#endif 680 681 /* 682 * if the servname does not match socktype/protocol, ignore it. 683 */ 684 if (get_portmatch(pai, servname) != 0) 685 return 0; 686 687 afd = find_afd(pai->ai_family); 688 if (afd == NULL) 689 return 0; 690 if (!afd->a_scoped) 691 return explore_numeric(pai, hostname, servname, res); 692 693 cp = strchr(hostname, SCOPE_DELIMITER); 694 if (cp == NULL) 695 return explore_numeric(pai, hostname, servname, res); 696 697 /* 698 * Handle special case of <scoped_address><delimiter><scope id> 699 */ 700 hostname2 = strdup(hostname); 701 if (hostname2 == NULL) 702 return EAI_MEMORY; 703 /* terminate at the delimiter */ 704 hostname2[cp - hostname] = '\0'; 705 706 cp++; 707 switch (pai->ai_family) { 708#ifdef INET6 709 case AF_INET6: 710 scope = if_nametoindex(hostname2); 711 if (scope == 0) { 712 error = EAI_SYSTEM; 713 goto free; 714 } 715 break; 716#endif 717 } 718 719 error = explore_numeric(pai, cp, servname, res); 720 if (error == 0) { 721 for (cur = *res; cur; cur = cur->ai_next) { 722#ifdef INET6 723 if (cur->ai_family != AF_INET6) 724 continue; 725 sin6 = (struct sockaddr_in6 *)cur->ai_addr; 726 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 727 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) 728 sin6->sin6_scope_id = scope; 729#endif 730 } 731 } 732 733#ifdef INET6 734free: 735#endif 736 free(hostname2); 737 738 return error; 739#endif 740} 741 742static int 743get_canonname(pai, ai, str) 744 const struct addrinfo *pai; 745 struct addrinfo *ai; 746 const char *str; 747{ 748 if ((pai->ai_flags & AI_CANONNAME) != 0) { 749 ai->ai_canonname = (char *)malloc(strlen(str) + 1); 750 if (ai->ai_canonname == NULL) 751 return EAI_MEMORY; 752 strcpy(ai->ai_canonname, str); 753 } 754 return 0; 755} 756 757static struct addrinfo * 758get_ai(pai, afd, addr) 759 const struct addrinfo *pai; 760 const struct afd *afd; 761 const char *addr; 762{ 763 char *p; 764 struct addrinfo *ai; 765#ifdef FAITH 766 struct in6_addr faith_prefix; 767 char *fp_str; 768 int translate = 0; 769#endif 770 771#ifdef FAITH 772 /* 773 * Transfrom an IPv4 addr into a special IPv6 addr format for 774 * IPv6->IPv4 translation gateway. (only TCP is supported now) 775 * 776 * +-----------------------------------+------------+ 777 * | faith prefix part (12 bytes) | embedded | 778 * | | IPv4 addr part (4 bytes) 779 * +-----------------------------------+------------+ 780 * 781 * faith prefix part is specified as ascii IPv6 addr format 782 * in environmental variable GAI. 783 * For FAITH to work correctly, routing to faith prefix must be 784 * setup toward a machine where a FAITH daemon operates. 785 * Also, the machine must enable some mechanizm 786 * (e.g. faith interface hack) to divert those packet with 787 * faith prefixed destination addr to user-land FAITH daemon. 788 */ 789 fp_str = getenv("GAI"); 790 if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 && 791 afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) { 792 u_int32_t v4a; 793 u_int8_t v4a_top; 794 795 memcpy(&v4a, addr, sizeof v4a); 796 v4a_top = v4a >> IN_CLASSA_NSHIFT; 797 if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) && 798 v4a_top != 0 && v4a != IN_LOOPBACKNET) { 799 afd = &afdl[N_INET6]; 800 memcpy(&faith_prefix.s6_addr[12], addr, 801 sizeof(struct in_addr)); 802 translate = 1; 803 } 804 } 805#endif 806 807 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 808 + (afd->a_socklen)); 809 if (ai == NULL) 810 return NULL; 811 812 memcpy(ai, pai, sizeof(struct addrinfo)); 813 ai->ai_addr = (struct sockaddr *)(ai + 1); 814 memset(ai->ai_addr, 0, afd->a_socklen); 815 ai->ai_addr->sa_len = afd->a_socklen; 816 ai->ai_addrlen = afd->a_socklen; 817 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 818 p = (char *)(ai->ai_addr); 819#ifdef FAITH 820 if (translate == 1) 821 memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen); 822 else 823#endif 824 memcpy(p + afd->a_off, addr, afd->a_addrlen); 825 826 return ai; 827} 828 829static int 830get_portmatch(ai, servname) 831 const struct addrinfo *ai; 832 const char *servname; 833{ 834 /* get_port does not touch first argument. when matchonly == 1. */ 835 return get_port((struct addrinfo *)ai, servname, 1); 836} 837 838static int 839get_port(ai, servname, matchonly) 840 struct addrinfo *ai; 841 const char *servname; 842 int matchonly; 843{ 844 const char *proto; 845 struct servent *sp; 846 int port; 847 int allownumeric; 848 849 if (servname == NULL) 850 return 0; 851 if (ai->ai_family != AF_INET 852#ifdef INET6 853 && ai->ai_family != AF_INET6 854#endif 855 ) 856 return 0; 857 858 switch (ai->ai_socktype) { 859 case SOCK_RAW: 860 return EAI_SERVICE; 861 case SOCK_DGRAM: 862 case SOCK_STREAM: 863 allownumeric = 1; 864 break; 865 case ANY: 866 allownumeric = 0; 867 break; 868 default: 869 return EAI_SOCKTYPE; 870 } 871 872 if (str_isnumber(servname)) { 873 if (!allownumeric) 874 return EAI_SERVICE; 875 port = htons(atoi(servname)); 876 if (port < 0 || port > 65535) 877 return EAI_SERVICE; 878 } else { 879 switch (ai->ai_socktype) { 880 case SOCK_DGRAM: 881 proto = "udp"; 882 break; 883 case SOCK_STREAM: 884 proto = "tcp"; 885 break; 886 default: 887 proto = NULL; 888 break; 889 } 890 891 if ((sp = getservbyname(servname, proto)) == NULL) 892 return EAI_SERVICE; 893 port = sp->s_port; 894 } 895 896 if (!matchonly) { 897 switch (ai->ai_family) { 898 case AF_INET: 899 ((struct sockaddr_in *)ai->ai_addr)->sin_port = port; 900 break; 901#ifdef INET6 902 case AF_INET6: 903 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port; 904 break; 905#endif 906 } 907 } 908 909 return 0; 910} 911 912static const struct afd * 913find_afd(af) 914 int af; 915{ 916 const struct afd *afd; 917 918 if (af == PF_UNSPEC) 919 return NULL; 920 for (afd = afdl; afd->a_af; afd++) { 921 if (afd->a_af == af) 922 return afd; 923 } 924 return NULL; 925} 926