getaddrinfo.c revision 57107
1155324Simp/* 2155324Simp * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3155324Simp * All rights reserved. 4155324Simp * 5155324Simp * Redistribution and use in source and binary forms, with or without 6155324Simp * modification, are permitted provided that the following conditions 7155324Simp * are met: 8155324Simp * 1. Redistributions of source code must retain the above copyright 9155324Simp * notice, this list of conditions and the following disclaimer. 10155324Simp * 2. Redistributions in binary form must reproduce the above copyright 11155324Simp * notice, this list of conditions and the following disclaimer in the 12155324Simp * documentation and/or other materials provided with the distribution. 13155324Simp * 3. Neither the name of the project nor the names of its contributors 14155324Simp * may be used to endorse or promote products derived from this software 15155324Simp * without specific prior written permission. 16155324Simp * 17155324Simp * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18155324Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19155324Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20155324Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21155324Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22155324Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23155324Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24155324Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25155324Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26155324Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27155324Simp * SUCH DAMAGE. 28155324Simp * 29155324Simp * $FreeBSD: head/lib/libc/net/getaddrinfo.c 57107 2000-02-10 02:59:50Z shin $ 30155324Simp */ 31155324Simp 32155324Simp/* 33155324Simp * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. 34155324Simp * 35155324Simp * Issues to be discussed: 36155324Simp * - Thread safe-ness must be checked. 37155324Simp * - Return values. There are nonstandard return values defined and used 38155324Simp * in the source code. This is because RFC2553 is silent about which error 39155324Simp * code must be returned for which situation. 40155324Simp * Note: 41155324Simp * - We use getipnodebyname() just for thread-safeness. There's no intent 42155324Simp * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to 43155324Simp * getipnodebyname(). 44155324Simp * - The code filters out AFs that are not supported by the kernel, 45155324Simp * when globbing NULL hostname (to loopback, or wildcard). Is it the right 46155324Simp * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 47155324Simp * in ai_flags? 48155324Simp */ 49155324Simp 50155324Simp#include <sys/types.h> 51155324Simp#include <sys/param.h> 52155324Simp#include <sys/socket.h> 53155324Simp#include <net/if.h> 54155324Simp#include <netinet/in.h> 55155324Simp#include <arpa/inet.h> 56155324Simp#include <arpa/nameser.h> 57155324Simp#include <netdb.h> 58155324Simp#include <resolv.h> 59155324Simp#include <string.h> 60155324Simp#include <stdlib.h> 61155324Simp#include <stddef.h> 62155324Simp#include <ctype.h> 63155324Simp#include <unistd.h> 64155324Simp#include <stdio.h> 65155324Simp 66155324Simp#if defined(__KAME__) && defined(INET6) 67155324Simp# define FAITH 68155324Simp#endif 69155324Simp 70155324Simp#define SUCCESS 0 71155324Simp#define ANY 0 72155324Simp#define YES 1 73155324Simp#define NO 0 74155324Simp 75155324Simpstatic const char in_addrany[] = { 0, 0, 0, 0 }; 76155324Simpstatic const char in6_addrany[] = { 77155324Simp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 78155324Simp}; 79155324Simpstatic const char in_loopback[] = { 127, 0, 0, 1 }; 80155324Simpstatic const char in6_loopback[] = { 81155324Simp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 82155324Simp}; 83155324Simp 84155324Simpstatic const struct afd { 85155324Simp int a_af; 86155324Simp int a_addrlen; 87155324Simp int a_socklen; 88155324Simp int a_off; 89155324Simp const char *a_addrany; 90155324Simp const char *a_loopback; 91155324Simp int a_scoped; 92155324Simp} afdl [] = { 93155324Simp#ifdef INET6 94155324Simp#define N_INET6 0 95155324Simp {PF_INET6, sizeof(struct in6_addr), 96155324Simp sizeof(struct sockaddr_in6), 97155324Simp offsetof(struct sockaddr_in6, sin6_addr), 98155324Simp in6_addrany, in6_loopback, 1}, 99159556Scognet#define N_INET 1 100155324Simp#else 101155324Simp#define N_INET 0 102155324Simp#endif 103155324Simp {PF_INET, sizeof(struct in_addr), 104155324Simp sizeof(struct sockaddr_in), 105155324Simp offsetof(struct sockaddr_in, sin_addr), 106155324Simp in_addrany, in_loopback, 0}, 107155324Simp {0, 0, 0, 0, NULL, NULL, 0}, 108155324Simp}; 109155324Simp 110155324Simpstruct explore { 111155324Simp int e_af; 112155324Simp int e_socktype; 113155324Simp int e_protocol; 114155324Simp const char *e_protostr; 115155324Simp int e_wild; 116155324Simp#define WILD_AF(ex) ((ex)->e_wild & 0x01) 117155324Simp#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 118155324Simp#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 119155324Simp}; 120155324Simp 121155324Simpstatic const struct explore explore[] = { 122155324Simp#ifdef INET6 123155324Simp { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 124155324Simp { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 125155324Simp { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 126155324Simp#endif 127155324Simp { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 128155324Simp { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 129155324Simp { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 130155324Simp { -1, 0, 0, NULL, 0 }, 131155324Simp}; 132155324Simp 133155324Simp#ifdef INET6 134155324Simp#define PTON_MAX 16 135155324Simp#else 136155324Simp#define PTON_MAX 4 137155324Simp#endif 138155324Simp 139155324Simp 140155324Simpstatic int str_isnumber __P((const char *)); 141155324Simpstatic int explore_fqdn __P((const struct addrinfo *, const char *, 142155324Simp const char *, struct addrinfo **)); 143155324Simpstatic int explore_null __P((const struct addrinfo *, const char *, 144155324Simp const char *, struct addrinfo **)); 145155324Simpstatic int explore_numeric __P((const struct addrinfo *, const char *, 146155324Simp const char *, struct addrinfo **)); 147156832Simpstatic int explore_numeric_scope __P((const struct addrinfo *, const char *, 148156832Simp const char *, struct addrinfo **)); 149156832Simpstatic int get_canonname __P((const struct addrinfo *, 150156832Simp struct addrinfo *, const char *)); 151156832Simpstatic struct addrinfo *get_ai __P((const struct addrinfo *, 152156832Simp const struct afd *, const char *)); 153156832Simpstatic int get_portmatch __P((const struct addrinfo *, const char *)); 154156832Simpstatic int get_port __P((struct addrinfo *, const char *, int)); 155156832Simpstatic const struct afd *find_afd __P((int)); 156156832Simp 157156832Simpstatic char *ai_errlist[] = { 158156832Simp "Success", 159160282Scognet "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 160156832Simp "Temporary failure in name resolution", /* EAI_AGAIN */ 161156832Simp "Invalid value for ai_flags", /* EAI_BADFLAGS */ 162156832Simp "Non-recoverable failure in name resolution", /* EAI_FAIL */ 163156832Simp "ai_family not supported", /* EAI_FAMILY */ 164156832Simp "Memory allocation failure", /* EAI_MEMORY */ 165156832Simp "No address associated with hostname", /* EAI_NODATA */ 166156832Simp "hostname nor servname provided, or not known", /* EAI_NONAME */ 167156832Simp "servname not supported for ai_socktype", /* EAI_SERVICE */ 168156832Simp "ai_socktype not supported", /* EAI_SOCKTYPE */ 169156832Simp "System error returned in errno", /* EAI_SYSTEM */ 170156832Simp "Invalid value for hints", /* EAI_BADHINTS */ 171160282Scognet "Resolved protocol is unknown", /* EAI_PROTOCOL */ 172156832Simp "Argument res is NULL", /* EAI_RESNULL */ 173156832Simp "Unknown error", /* EAI_MAX */ 174156832Simp}; 175156832Simp 176156832Simp/* XXX macros that make external reference is BAD. */ 177156832Simp 178156832Simp#define GET_AI(ai, afd, addr) \ 179155324Simpdo { \ 180155324Simp /* external reference: pai, error, and label free */ \ 181155324Simp (ai) = get_ai(pai, (afd), (addr)); \ 182155324Simp if ((ai) == NULL) { \ 183155324Simp error = EAI_MEMORY; \ 184155324Simp goto free; \ 185155324Simp } \ 186155324Simp} while (0) 187159814Simp 188159795Simp#define GET_PORT(ai, serv) \ 189159795Simpdo { \ 190159795Simp /* external reference: error and label free */ \ 191159795Simp error = get_port((ai), (serv), 0); \ 192159795Simp if (error != 0) \ 193159795Simp goto free; \ 194159795Simp} while (0) 195159795Simp 196159795Simp#define GET_CANONNAME(ai, str) \ 197159795Simpdo { \ 198159795Simp /* external reference: pai, error and label free */ \ 199159795Simp error = get_canonname(pai, (ai), (str)); \ 200159814Simp if (error != 0) \ 201159795Simp goto free; \ 202159795Simp} while (0) 203155324Simp 204155324Simp#define ERR(err) \ 205155324Simpdo { \ 206155324Simp /* external reference: error, and label bad */ \ 207155324Simp error = (err); \ 208155324Simp goto bad; \ 209155324Simp} while (0) 210155324Simp 211155324Simp#define MATCH_FAMILY(x, y, w) \ 212155324Simp ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) 213159795Simp#define MATCH(x, y, w) \ 214157024Scognet ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY))) 215157024Scognet 216157024Scognetchar * 217157024Scognetgai_strerror(ecode) 218155324Simp int ecode; 219155324Simp{ 220155324Simp if (ecode < 0 || ecode > EAI_MAX) 221155324Simp ecode = EAI_MAX; 222155324Simp return ai_errlist[ecode]; 223155324Simp} 224155324Simp 225155324Simpvoid 226155324Simpfreeaddrinfo(ai) 227155324Simp struct addrinfo *ai; 228155324Simp{ 229155324Simp struct addrinfo *next; 230155324Simp 231155324Simp do { 232155324Simp next = ai->ai_next; 233155324Simp if (ai->ai_canonname) 234155324Simp free(ai->ai_canonname); 235155324Simp /* no need to free(ai->ai_addr) */ 236155324Simp free(ai); 237157024Scognet } while ((ai = next) != NULL); 238157024Scognet} 239157024Scognet 240157024Scognetstatic int 241157024Scognetstr_isnumber(p) 242157024Scognet const char *p; 243157024Scognet{ 244157024Scognet char *q = (char *)p; 245157024Scognet while (*q) { 246157024Scognet if (! isdigit(*q)) 247157024Scognet return NO; 248157024Scognet q++; 249157024Scognet } 250157024Scognet return YES; 251157024Scognet} 252157024Scognet 253157024Scognetint 254155324Simpgetaddrinfo(hostname, servname, hints, res) 255155324Simp const char *hostname, *servname; 256155324Simp const struct addrinfo *hints; 257155324Simp struct addrinfo **res; 258155324Simp{ 259155324Simp struct addrinfo sentinel; 260155324Simp struct addrinfo *cur; 261155324Simp int error = 0; 262155324Simp struct addrinfo ai; 263157024Scognet struct addrinfo ai0; 264155324Simp struct addrinfo *pai; 265155324Simp const struct afd *afd; 266155324Simp const struct explore *ex; 267155324Simp 268155324Simp sentinel.ai_next = NULL; 269155324Simp cur = &sentinel; 270155324Simp pai = &ai; 271155324Simp pai->ai_flags = 0; 272155324Simp pai->ai_family = PF_UNSPEC; 273155324Simp pai->ai_socktype = ANY; 274155324Simp pai->ai_protocol = ANY; 275155324Simp pai->ai_addrlen = 0; 276155324Simp pai->ai_canonname = NULL; 277155324Simp pai->ai_addr = NULL; 278155324Simp pai->ai_next = NULL; 279155324Simp 280155324Simp if (hostname == NULL && servname == NULL) 281155324Simp return EAI_NONAME; 282155324Simp if (res == NULL) 283155324Simp return EAI_RESNULL; /* xxx */ 284155324Simp if (hints) { 285155324Simp /* error check for hints */ 286155324Simp if (hints->ai_addrlen || hints->ai_canonname || 287155324Simp hints->ai_addr || hints->ai_next) 288155324Simp ERR(EAI_BADHINTS); /* xxx */ 289155324Simp if (hints->ai_flags & ~AI_MASK) 290155324Simp ERR(EAI_BADFLAGS); 291155324Simp switch (hints->ai_family) { 292155324Simp case PF_UNSPEC: 293155324Simp case PF_INET: 294155324Simp#ifdef INET6 295155324Simp case PF_INET6: 296155324Simp#endif 297155324Simp break; 298155324Simp default: 299155324Simp ERR(EAI_FAMILY); 300155324Simp } 301155324Simp memcpy(pai, hints, sizeof(*pai)); 302155324Simp 303155324Simp /* 304155324Simp * if both socktype/protocol are specified, check if they 305155324Simp * are meaningful combination. 306155324Simp */ 307155324Simp if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 308155324Simp int matched = 0; 309155324Simp 310155324Simp for (ex = explore; ex->e_af >= 0; ex++) { 311155324Simp if (pai->ai_family != ex->e_af) 312155324Simp continue; 313155324Simp if (ex->e_socktype == ANY) 314155324Simp continue; 315155324Simp if (ex->e_protocol == ANY) 316155324Simp continue; 317155324Simp if (pai->ai_socktype == ex->e_socktype 318155324Simp && pai->ai_protocol == ex->e_protocol) 319157024Scognet matched = 1; 320155324Simp else 321157024Scognet continue; 322155324Simp if (matched == 0) 323155324Simp ERR(EAI_BADHINTS); 324155324Simp } 325155324Simp } 326155324Simp } 327155324Simp 328155324Simp /* backup original pai contents */ 329155324Simp ai0 = *pai; 330155324Simp 331155324Simp /* 332155324Simp * special cases check for inet and inet6 sockets. 333155324Simp * (1) servname is disallowed for raw sockets. 334155324Simp * (2) numeric servname is disallowed if socktype/protocol is left 335155324Simp * unspecified. 336155324Simp */ 337155324Simp if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 338155324Simp#ifdef INET6 339155324Simp || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 340155324Simp#endif 341155324Simp ) { 342155324Simp *pai = ai0; 343155324Simp 344155324Simp if (pai->ai_family == PF_UNSPEC) 345155324Simp#ifdef INET6 346155324Simp pai->ai_family = PF_INET6; 347155324Simp#else 348155324Simp pai->ai_family = PF_INET; 349155324Simp#endif 350155324Simp error = get_portmatch(pai, servname); 351155324Simp if (error) 352155324Simp ERR(error); 353155324Simp } 354155324Simp 355155324Simp /* NULL hostname, or numeric hostname */ 356155324Simp for (ex = explore; ex->e_af >= 0; ex++) { 357155324Simp *pai = ai0; 358155324Simp 359155324Simp if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 360155324Simp continue; 361157029Scognet if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 362159795Simp continue; 363159814Simp if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 364159814Simp continue; 365155324Simp 366155324Simp if (pai->ai_family == PF_UNSPEC) 367155324Simp pai->ai_family = ex->e_af; 368155324Simp if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 369155324Simp pai->ai_socktype = ex->e_socktype; 370155324Simp if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 371155324Simp pai->ai_protocol = ex->e_protocol; 372155324Simp 373155324Simp if (hostname == NULL) 374155324Simp error = explore_null(pai, hostname, servname, &cur->ai_next); 375155324Simp else 376155324Simp error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next); 377155324Simp 378155324Simp if (error) 379155324Simp goto free; 380155324Simp 381155324Simp while (cur && cur->ai_next) 382155324Simp cur = cur->ai_next; 383155324Simp } 384155324Simp 385155324Simp /* 386155324Simp * XXX 387155324Simp * If numreic representation of AF1 can be interpreted as FQDN 388155324Simp * representation of AF2, we need to think again about the code below. 389155324Simp */ 390155324Simp if (sentinel.ai_next) 391155324Simp goto good; 392155324Simp 393155324Simp if (pai->ai_flags & AI_NUMERICHOST) 394155324Simp ERR(EAI_NONAME); 395155324Simp if (hostname == NULL) 396155324Simp ERR(EAI_NONAME); 397155324Simp 398155324Simp /* 399155324Simp * hostname as alphabetical name. 400155324Simp * we would like to prefer AF_INET6 than AF_INET, so we'll make a 401155324Simp * outer loop by AFs. 402155324Simp */ 403155324Simp for (afd = afdl; afd->a_af; afd++) { 404155324Simp *pai = ai0; 405155324Simp 406155324Simp if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1)) 407155324Simp continue; 408155324Simp 409155324Simp for (ex = explore; ex->e_af >= 0; ex++) { 410155324Simp *pai = ai0; 411155324Simp 412155324Simp if (pai->ai_family == PF_UNSPEC) 413155324Simp pai->ai_family = afd->a_af; 414155324Simp 415155324Simp if (!MATCH_FAMILY(pai->ai_family, ex->e_af, 416155324Simp WILD_AF(ex))) 417155324Simp continue; 418155324Simp if (!MATCH(pai->ai_socktype, ex->e_socktype, 419155324Simp WILD_SOCKTYPE(ex))) { 420155324Simp continue; 421155324Simp } 422155324Simp if (!MATCH(pai->ai_protocol, ex->e_protocol, 423155324Simp WILD_PROTOCOL(ex))) { 424155324Simp continue; 425155324Simp } 426155324Simp 427155324Simp if (pai->ai_family == PF_UNSPEC) 428155324Simp pai->ai_family = ex->e_af; 429155324Simp if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 430155324Simp pai->ai_socktype = ex->e_socktype; 431155324Simp if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 432155324Simp pai->ai_protocol = ex->e_protocol; 433159814Simp 434155324Simp error = explore_fqdn(pai, hostname, servname, 435155324Simp &cur->ai_next); 436155324Simp 437155324Simp while (cur && cur->ai_next) 438155324Simp 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 ((afd->a_af == AF_INET 639 ? inet_aton(hostname, (struct in_addr *)pton) 640 : inet_pton(afd->a_af, hostname, pton)) == 1) { 641 if (pai->ai_family == afd->a_af || 642 pai->ai_family == PF_UNSPEC /*?*/) { 643 GET_AI(cur->ai_next, afd, pton); 644 GET_PORT(cur->ai_next, servname); 645 while (cur && cur->ai_next) 646 cur = cur->ai_next; 647 } else 648 ERR(EAI_FAMILY); /*xxx*/ 649 } 650 651 *res = sentinel.ai_next; 652 return 0; 653 654free: 655bad: 656 if (sentinel.ai_next) 657 freeaddrinfo(sentinel.ai_next); 658 return error; 659} 660 661/* 662 * numeric hostname with scope 663 */ 664static int 665explore_numeric_scope(pai, hostname, servname, res) 666 const struct addrinfo *pai; 667 const char *hostname; 668 const char *servname; 669 struct addrinfo **res; 670{ 671#ifndef SCOPE_DELIMITER 672 return explore_numeric(pai, hostname, servname, res); 673#else 674 const struct afd *afd; 675 struct addrinfo *cur; 676 int error; 677 char *cp, *hostname2 = NULL; 678 int scope; 679#ifdef INET6 680 struct sockaddr_in6 *sin6; 681#endif 682 683 /* 684 * if the servname does not match socktype/protocol, ignore it. 685 */ 686 if (get_portmatch(pai, servname) != 0) 687 return 0; 688 689 afd = find_afd(pai->ai_family); 690 if (afd == NULL) 691 return 0; 692 if (!afd->a_scoped) 693 return explore_numeric(pai, hostname, servname, res); 694 695 cp = strchr(hostname, SCOPE_DELIMITER); 696 if (cp == NULL) 697 return explore_numeric(pai, hostname, servname, res); 698 699 /* 700 * Handle special case of <scoped_address><delimiter><scope id> 701 */ 702 hostname2 = strdup(hostname); 703 if (hostname2 == NULL) 704 return EAI_MEMORY; 705 /* terminate at the delimiter */ 706 hostname2[cp - hostname] = '\0'; 707 708 cp++; 709 switch (pai->ai_family) { 710#ifdef INET6 711 case AF_INET6: 712 scope = if_nametoindex(hostname2); 713 if (scope == 0) { 714 error = EAI_SYSTEM; 715 goto free; 716 } 717 break; 718#endif 719 } 720 721 error = explore_numeric(pai, cp, servname, res); 722 if (error == 0) { 723 for (cur = *res; cur; cur = cur->ai_next) { 724#ifdef INET6 725 if (cur->ai_family != AF_INET6) 726 continue; 727 sin6 = (struct sockaddr_in6 *)cur->ai_addr; 728 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 729 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) 730 sin6->sin6_scope_id = scope; 731#endif 732 } 733 } 734 735#ifdef INET6 736free: 737#endif 738 free(hostname2); 739 740 return error; 741#endif 742} 743 744static int 745get_canonname(pai, ai, str) 746 const struct addrinfo *pai; 747 struct addrinfo *ai; 748 const char *str; 749{ 750 if ((pai->ai_flags & AI_CANONNAME) != 0) { 751 ai->ai_canonname = (char *)malloc(strlen(str) + 1); 752 if (ai->ai_canonname == NULL) 753 return EAI_MEMORY; 754 strcpy(ai->ai_canonname, str); 755 } 756 return 0; 757} 758 759static struct addrinfo * 760get_ai(pai, afd, addr) 761 const struct addrinfo *pai; 762 const struct afd *afd; 763 const char *addr; 764{ 765 char *p; 766 struct addrinfo *ai; 767#ifdef FAITH 768 struct in6_addr faith_prefix; 769 char *fp_str; 770 int translate = 0; 771#endif 772 773#ifdef FAITH 774 /* 775 * Transfrom an IPv4 addr into a special IPv6 addr format for 776 * IPv6->IPv4 translation gateway. (only TCP is supported now) 777 * 778 * +-----------------------------------+------------+ 779 * | faith prefix part (12 bytes) | embedded | 780 * | | IPv4 addr part (4 bytes) 781 * +-----------------------------------+------------+ 782 * 783 * faith prefix part is specified as ascii IPv6 addr format 784 * in environmental variable GAI. 785 * For FAITH to work correctly, routing to faith prefix must be 786 * setup toward a machine where a FAITH daemon operates. 787 * Also, the machine must enable some mechanizm 788 * (e.g. faith interface hack) to divert those packet with 789 * faith prefixed destination addr to user-land FAITH daemon. 790 */ 791 fp_str = getenv("GAI"); 792 if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 && 793 afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) { 794 u_int32_t v4a; 795 u_int8_t v4a_top; 796 797 memcpy(&v4a, addr, sizeof v4a); 798 v4a_top = v4a >> IN_CLASSA_NSHIFT; 799 if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) && 800 v4a_top != 0 && v4a != IN_LOOPBACKNET) { 801 afd = &afdl[N_INET6]; 802 memcpy(&faith_prefix.s6_addr[12], addr, 803 sizeof(struct in_addr)); 804 translate = 1; 805 } 806 } 807#endif 808 809 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 810 + (afd->a_socklen)); 811 if (ai == NULL) 812 return NULL; 813 814 memcpy(ai, pai, sizeof(struct addrinfo)); 815 ai->ai_addr = (struct sockaddr *)(ai + 1); 816 memset(ai->ai_addr, 0, afd->a_socklen); 817 ai->ai_addr->sa_len = afd->a_socklen; 818 ai->ai_addrlen = afd->a_socklen; 819 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 820 p = (char *)(ai->ai_addr); 821#ifdef FAITH 822 if (translate == 1) 823 memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen); 824 else 825#endif 826 memcpy(p + afd->a_off, addr, afd->a_addrlen); 827 828 return ai; 829} 830 831static int 832get_portmatch(ai, servname) 833 const struct addrinfo *ai; 834 const char *servname; 835{ 836 /* get_port does not touch first argument. when matchonly == 1. */ 837 return get_port((struct addrinfo *)ai, servname, 1); 838} 839 840static int 841get_port(ai, servname, matchonly) 842 struct addrinfo *ai; 843 const char *servname; 844 int matchonly; 845{ 846 const char *proto; 847 struct servent *sp; 848 int port; 849 int allownumeric; 850 851 if (servname == NULL) 852 return 0; 853 if (ai->ai_family != AF_INET 854#ifdef INET6 855 && ai->ai_family != AF_INET6 856#endif 857 ) 858 return 0; 859 860 switch (ai->ai_socktype) { 861 case SOCK_RAW: 862 return EAI_SERVICE; 863 case SOCK_DGRAM: 864 case SOCK_STREAM: 865 allownumeric = 1; 866 break; 867 case ANY: 868 allownumeric = 0; 869 break; 870 default: 871 return EAI_SOCKTYPE; 872 } 873 874 if (str_isnumber(servname)) { 875 if (!allownumeric) 876 return EAI_SERVICE; 877 port = htons(atoi(servname)); 878 if (port < 0 || port > 65535) 879 return EAI_SERVICE; 880 } else { 881 switch (ai->ai_socktype) { 882 case SOCK_DGRAM: 883 proto = "udp"; 884 break; 885 case SOCK_STREAM: 886 proto = "tcp"; 887 break; 888 default: 889 proto = NULL; 890 break; 891 } 892 893 if ((sp = getservbyname(servname, proto)) == NULL) 894 return EAI_SERVICE; 895 port = sp->s_port; 896 } 897 898 if (!matchonly) { 899 switch (ai->ai_family) { 900 case AF_INET: 901 ((struct sockaddr_in *)ai->ai_addr)->sin_port = port; 902 break; 903#ifdef INET6 904 case AF_INET6: 905 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port; 906 break; 907#endif 908 } 909 } 910 911 return 0; 912} 913 914static const struct afd * 915find_afd(af) 916 int af; 917{ 918 const struct afd *afd; 919 920 if (af == PF_UNSPEC) 921 return NULL; 922 for (afd = afdl; afd->a_af; afd++) { 923 if (afd->a_af == af) 924 return afd; 925 } 926 return NULL; 927} 928