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 30 /* 31 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. 32 * 33 * Issues to be discussed: 34 * - Thread safe-ness must be checked. 35 * - Return values. There are nonstandard return values defined and used 36 * in the source code. This is because RFC2133 is silent about which error 37 * code must be returned for which situation. 38 * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag. 39 */ 40 41 #if 0 42 #include <sys/types.h> 43 #include <sys/param.h> 44 #include <sys/sysctl.h> 45 #include <sys/socket.h> 46 #include <netinet/in.h> 47 #include <arpa/inet.h> 48 #include <arpa/nameser.h> 49 #include <netdb.h> 50 #include <resolv.h> 51 #include <string.h> 52 #include <stdlib.h> 53 #include <stddef.h> 54 #include <ctype.h> 55 #include <unistd.h> 56 57 #include "addrinfo.h" 58 #endif 59 60 #if defined(__KAME__) && defined(ENABLE_IPV6) 61 # define FAITH 62 #endif 63 64 #define SUCCESS 0 65 #define GAI_ANY 0 66 #define YES 1 67 #define NO 0 68 69 #ifdef FAITH 70 static int translate = NO; 71 static struct in6_addr faith_prefix = IN6ADDR_GAI_ANY_INIT; 72 #endif 73 74 static const char in_addrany[] = { 0, 0, 0, 0 }; 75 static const char in6_addrany[] = { 76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 77 }; 78 static const char in_loopback[] = { 127, 0, 0, 1 }; 79 static const char in6_loopback[] = { 80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 81 }; 82 83 struct sockinet { 84 u_char si_len; 85 u_char si_family; 86 u_short si_port; 87 }; 88 89 static struct gai_afd { 90 int a_af; 91 int a_addrlen; 92 int a_socklen; 93 int a_off; 94 const char *a_addrany; 95 const char *a_loopback; 96 } gai_afdl [] = { 97 #ifdef ENABLE_IPV6 98 #define N_INET6 0 99 {PF_INET6, sizeof(struct in6_addr), 100 sizeof(struct sockaddr_in6), 101 offsetof(struct sockaddr_in6, sin6_addr), 102 in6_addrany, in6_loopback}, 103 #define N_INET 1 104 #else 105 #define N_INET 0 106 #endif 107 {PF_INET, sizeof(struct in_addr), 108 sizeof(struct sockaddr_in), 109 offsetof(struct sockaddr_in, sin_addr), 110 in_addrany, in_loopback}, 111 {0, 0, 0, 0, NULL, NULL}, 112 }; 113 114 #ifdef ENABLE_IPV6 115 #define PTON_MAX 16 116 #else 117 #define PTON_MAX 4 118 #endif 119 120 #ifndef IN_MULTICAST 121 #define IN_MULTICAST(i) (((i) & 0xf0000000U) == 0xe0000000U) 122 #endif 123 124 #ifndef IN_EXPERIMENTAL 125 #define IN_EXPERIMENTAL(i) (((i) & 0xe0000000U) == 0xe0000000U) 126 #endif 127 128 #ifndef IN_LOOPBACKNET 129 #define IN_LOOPBACKNET 127 130 #endif 131 132 static int get_name(const char *, struct gai_afd *, 133 struct addrinfo **, char *, struct addrinfo *, 134 int); 135 static int get_addr(const char *, int, struct addrinfo **, 136 struct addrinfo *, int); 137 static int str_isnumber(const char *); 138 139 static const char * const ai_errlist[] = { 140 "success.", 141 "address family for hostname not supported.", /* EAI_ADDRFAMILY */ 142 "temporary failure in name resolution.", /* EAI_AGAIN */ 143 "invalid value for ai_flags.", /* EAI_BADFLAGS */ 144 "non-recoverable failure in name resolution.", /* EAI_FAIL */ 145 "ai_family not supported.", /* EAI_FAMILY */ 146 "memory allocation failure.", /* EAI_MEMORY */ 147 "no address associated with hostname.", /* EAI_NODATA */ 148 "hostname nor servname provided, or not known.",/* EAI_NONAME */ 149 "servname not supported for ai_socktype.", /* EAI_SERVICE */ 150 "ai_socktype not supported.", /* EAI_SOCKTYPE */ 151 "system error returned in errno.", /* EAI_SYSTEM */ 152 "invalid value for hints.", /* EAI_BADHINTS */ 153 "resolved protocol is unknown.", /* EAI_PROTOCOL */ 154 "unknown error.", /* EAI_MAX */ 155 }; 156 157 #define GET_CANONNAME(ai, str) \ 158 if (pai->ai_flags & AI_CANONNAME) {\ 159 if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\ 160 strcpy((ai)->ai_canonname, (str));\ 161 } else {\ 162 error = EAI_MEMORY;\ 163 goto free;\ 164 }\ 165 } 166 167 #ifdef HAVE_SOCKADDR_SA_LEN 168 #define GET_AI(ai, gai_afd, addr, port) {\ 169 char *p;\ 170 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ 171 ((gai_afd)->a_socklen)))\ 172 == NULL) goto free;\ 173 memcpy(ai, pai, sizeof(struct addrinfo));\ 174 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ 175 memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\ 176 (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\ 177 (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\ 178 ((struct sockinet *)(ai)->ai_addr)->si_port = port;\ 179 p = (char *)((ai)->ai_addr);\ 180 memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\ 181 } 182 #else 183 #define GET_AI(ai, gai_afd, addr, port) {\ 184 char *p;\ 185 if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ 186 ((gai_afd)->a_socklen)))\ 187 == NULL) goto free;\ 188 memcpy(ai, pai, sizeof(struct addrinfo));\ 189 (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ 190 memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\ 191 (ai)->ai_addrlen = (gai_afd)->a_socklen;\ 192 (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\ 193 ((struct sockinet *)(ai)->ai_addr)->si_port = port;\ 194 p = (char *)((ai)->ai_addr);\ 195 memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\ 196 } 197 #endif 198 199 #define ERR(err) { error = (err); goto bad; } 200 201 const char * 202 gai_strerror(int ecode) 203 { 204 if (ecode < 0 || ecode > EAI_MAX) 205 ecode = EAI_MAX; 206 return ai_errlist[ecode]; 207 } 208 209 void 210 freeaddrinfo(struct addrinfo *ai) 211 { 212 struct addrinfo *next; 213 214 do { 215 next = ai->ai_next; 216 if (ai->ai_canonname) 217 free(ai->ai_canonname); 218 /* no need to free(ai->ai_addr) */ 219 free(ai); 220 } while ((ai = next) != NULL); 221 } 222 223 static int 224 str_isnumber(const char *p) 225 { 226 unsigned char *q = (unsigned char *)p; 227 while (*q) { 228 if (! isdigit(*q)) 229 return NO; 230 q++; 231 } 232 return YES; 233 } 234 235 int 236 getaddrinfo(const char*hostname, const char*servname, 237 const struct addrinfo *hints, struct addrinfo **res) 238 { 239 struct addrinfo sentinel; 240 struct addrinfo *top = NULL; 241 struct addrinfo *cur; 242 int i, error = 0; 243 char pton[PTON_MAX]; 244 struct addrinfo ai; 245 struct addrinfo *pai; 246 u_short port; 247 248 #ifdef FAITH 249 static int firsttime = 1; 250 251 if (firsttime) { 252 /* translator hack */ 253 { 254 char *q = getenv("GAI"); 255 if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) 256 translate = YES; 257 } 258 firsttime = 0; 259 } 260 #endif 261 262 /* initialize file static vars */ 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 = GAI_ANY; 269 pai->ai_protocol = GAI_ANY; 270 pai->ai_addrlen = 0; 271 pai->ai_canonname = NULL; 272 pai->ai_addr = NULL; 273 pai->ai_next = NULL; 274 port = GAI_ANY; 275 276 if (hostname == NULL && servname == NULL) 277 return EAI_NONAME; 278 if (hints) { 279 /* error check for hints */ 280 if (hints->ai_addrlen || hints->ai_canonname || 281 hints->ai_addr || hints->ai_next) 282 ERR(EAI_BADHINTS); /* xxx */ 283 if (hints->ai_flags & ~AI_MASK) 284 ERR(EAI_BADFLAGS); 285 switch (hints->ai_family) { 286 case PF_UNSPEC: 287 case PF_INET: 288 #ifdef ENABLE_IPV6 289 case PF_INET6: 290 #endif 291 break; 292 default: 293 ERR(EAI_FAMILY); 294 } 295 memcpy(pai, hints, sizeof(*pai)); 296 switch (pai->ai_socktype) { 297 case GAI_ANY: 298 switch (pai->ai_protocol) { 299 case GAI_ANY: 300 break; 301 case IPPROTO_UDP: 302 pai->ai_socktype = SOCK_DGRAM; 303 break; 304 case IPPROTO_TCP: 305 pai->ai_socktype = SOCK_STREAM; 306 break; 307 default: 308 pai->ai_socktype = SOCK_RAW; 309 break; 310 } 311 break; 312 case SOCK_RAW: 313 break; 314 case SOCK_DGRAM: 315 if (pai->ai_protocol != IPPROTO_UDP && 316 pai->ai_protocol != GAI_ANY) 317 ERR(EAI_BADHINTS); /*xxx*/ 318 pai->ai_protocol = IPPROTO_UDP; 319 break; 320 case SOCK_STREAM: 321 if (pai->ai_protocol != IPPROTO_TCP && 322 pai->ai_protocol != GAI_ANY) 323 ERR(EAI_BADHINTS); /*xxx*/ 324 pai->ai_protocol = IPPROTO_TCP; 325 break; 326 default: 327 ERR(EAI_SOCKTYPE); 328 /* unreachable */ 329 } 330 } 331 332 /* 333 * service port 334 */ 335 if (servname) { 336 if (str_isnumber(servname)) { 337 if (pai->ai_socktype == GAI_ANY) { 338 /* caller accept *GAI_ANY* socktype */ 339 pai->ai_socktype = SOCK_DGRAM; 340 pai->ai_protocol = IPPROTO_UDP; 341 } 342 port = htons((u_short)atoi(servname)); 343 } else { 344 struct servent *sp; 345 char *proto; 346 347 proto = NULL; 348 switch (pai->ai_socktype) { 349 case GAI_ANY: 350 proto = NULL; 351 break; 352 case SOCK_DGRAM: 353 proto = "udp"; 354 break; 355 case SOCK_STREAM: 356 proto = "tcp"; 357 break; 358 default: 359 fprintf(stderr, "panic!\n"); 360 break; 361 } 362 if ((sp = getservbyname(servname, proto)) == NULL) 363 ERR(EAI_SERVICE); 364 port = sp->s_port; 365 if (pai->ai_socktype == GAI_ANY) { 366 if (strcmp(sp->s_proto, "udp") == 0) { 367 pai->ai_socktype = SOCK_DGRAM; 368 pai->ai_protocol = IPPROTO_UDP; 369 } else if (strcmp(sp->s_proto, "tcp") == 0) { 370 pai->ai_socktype = SOCK_STREAM; 371 pai->ai_protocol = IPPROTO_TCP; 372 } else 373 ERR(EAI_PROTOCOL); /*xxx*/ 374 } 375 } 376 } 377 378 /* 379 * hostname == NULL. 380 * passive socket -> anyaddr (0.0.0.0 or ::) 381 * non-passive socket -> localhost (127.0.0.1 or ::1) 382 */ 383 if (hostname == NULL) { 384 struct gai_afd *gai_afd; 385 386 for (gai_afd = &gai_afdl[0]; gai_afd->a_af; gai_afd++) { 387 if (!(pai->ai_family == PF_UNSPEC 388 || pai->ai_family == gai_afd->a_af)) { 389 continue; 390 } 391 392 if (pai->ai_flags & AI_PASSIVE) { 393 GET_AI(cur->ai_next, gai_afd, gai_afd->a_addrany, port); 394 /* xxx meaningless? 395 * GET_CANONNAME(cur->ai_next, "anyaddr"); 396 */ 397 } else { 398 GET_AI(cur->ai_next, gai_afd, gai_afd->a_loopback, 399 port); 400 /* xxx meaningless? 401 * GET_CANONNAME(cur->ai_next, "localhost"); 402 */ 403 } 404 cur = cur->ai_next; 405 } 406 top = sentinel.ai_next; 407 if (top) 408 goto good; 409 else 410 ERR(EAI_FAMILY); 411 } 412 413 /* hostname as numeric name */ 414 for (i = 0; gai_afdl[i].a_af; i++) { 415 if (inet_pton(gai_afdl[i].a_af, hostname, pton)) { 416 u_long v4a; 417 #ifdef ENABLE_IPV6 418 u_char pfx; 419 #endif 420 421 switch (gai_afdl[i].a_af) { 422 case AF_INET: 423 v4a = ((struct in_addr *)pton)->s_addr; 424 v4a = ntohl(v4a); 425 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) 426 pai->ai_flags &= ~AI_CANONNAME; 427 v4a >>= IN_CLASSA_NSHIFT; 428 if (v4a == 0 || v4a == IN_LOOPBACKNET) 429 pai->ai_flags &= ~AI_CANONNAME; 430 break; 431 #ifdef ENABLE_IPV6 432 case AF_INET6: 433 pfx = ((struct in6_addr *)pton)->s6_addr[0]; 434 if (pfx == 0 || pfx == 0xfe || pfx == 0xff) 435 pai->ai_flags &= ~AI_CANONNAME; 436 break; 437 #endif 438 } 439 440 if (pai->ai_family == gai_afdl[i].a_af || 441 pai->ai_family == PF_UNSPEC) { 442 if (! (pai->ai_flags & AI_CANONNAME)) { 443 GET_AI(top, &gai_afdl[i], pton, port); 444 goto good; 445 } 446 /* 447 * if AI_CANONNAME and if reverse lookup 448 * fail, return ai anyway to pacify 449 * calling application. 450 * 451 * XXX getaddrinfo() is a name->address 452 * translation function, and it looks strange 453 * that we do addr->name translation here. 454 */ 455 get_name(pton, &gai_afdl[i], &top, pton, pai, port); 456 goto good; 457 } else 458 ERR(EAI_FAMILY); /*xxx*/ 459 } 460 } 461 462 if (pai->ai_flags & AI_NUMERICHOST) 463 ERR(EAI_NONAME); 464 465 /* hostname as alphabetical name */ 466 error = get_addr(hostname, pai->ai_family, &top, pai, port); 467 if (error == 0) { 468 if (top) { 469 good: 470 *res = top; 471 return SUCCESS; 472 } else 473 error = EAI_FAIL; 474 } 475 free: 476 if (top) 477 freeaddrinfo(top); 478 bad: 479 *res = NULL; 480 return error; 481 } 482 483 static int 484 get_name(addr, gai_afd, res, numaddr, pai, port0) 485 const char *addr; 486 struct gai_afd *gai_afd; 487 struct addrinfo **res; 488 char *numaddr; 489 struct addrinfo *pai; 490 int port0; 491 { 492 u_short port = port0 & 0xffff; 493 struct hostent *hp; 494 struct addrinfo *cur; 495 int error = 0; 496 #ifdef ENABLE_IPV6 497 int h_error; 498 #endif 499 500 #ifdef ENABLE_IPV6 501 hp = getipnodebyaddr(addr, gai_afd->a_addrlen, gai_afd->a_af, &h_error); 502 #else 503 hp = gethostbyaddr(addr, gai_afd->a_addrlen, AF_INET); 504 #endif 505 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { 506 GET_AI(cur, gai_afd, hp->h_addr_list[0], port); 507 GET_CANONNAME(cur, hp->h_name); 508 } else 509 GET_AI(cur, gai_afd, numaddr, port); 510 511 #ifdef ENABLE_IPV6 512 if (hp) 513 freehostent(hp); 514 #endif 515 *res = cur; 516 return SUCCESS; 517 free: 518 if (cur) 519 freeaddrinfo(cur); 520 #ifdef ENABLE_IPV6 521 if (hp) 522 freehostent(hp); 523 #endif 524 /* bad: */ 525 *res = NULL; 526 return error; 527 } 528 529 static int 530 get_addr(hostname, af, res, pai, port0) 531 const char *hostname; 532 int af; 533 struct addrinfo **res; 534 struct addrinfo *pai; 535 int port0; 536 { 537 u_short port = port0 & 0xffff; 538 struct addrinfo sentinel; 539 struct hostent *hp; 540 struct addrinfo *top, *cur; 541 struct gai_afd *gai_afd; 542 int i, error = 0, h_error; 543 char *ap; 544 545 top = NULL; 546 sentinel.ai_next = NULL; 547 cur = &sentinel; 548 #ifdef ENABLE_IPV6 549 if (af == AF_UNSPEC) { 550 hp = getipnodebyname(hostname, AF_INET6, 551 AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error); 552 } else 553 hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error); 554 #else 555 hp = gethostbyname(hostname); 556 h_error = h_errno; 557 #endif 558 if (hp == NULL) { 559 switch (h_error) { 560 case HOST_NOT_FOUND: 561 case NO_DATA: 562 error = EAI_NODATA; 563 break; 564 case TRY_AGAIN: 565 error = EAI_AGAIN; 566 break; 567 case NO_RECOVERY: 568 default: 569 error = EAI_FAIL; 570 break; 571 } 572 goto free; 573 } 574 575 if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || 576 (hp->h_addr_list[0] == NULL)) { 577 error = EAI_FAIL; 578 goto free; 579 } 580 581 for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) { 582 switch (af) { 583 #ifdef ENABLE_IPV6 584 case AF_INET6: 585 gai_afd = &gai_afdl[N_INET6]; 586 break; 587 #endif 588 #ifndef ENABLE_IPV6 589 default: /* AF_UNSPEC */ 590 #endif 591 case AF_INET: 592 gai_afd = &gai_afdl[N_INET]; 593 break; 594 #ifdef ENABLE_IPV6 595 default: /* AF_UNSPEC */ 596 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { 597 ap += sizeof(struct in6_addr) - 598 sizeof(struct in_addr); 599 gai_afd = &gai_afdl[N_INET]; 600 } else 601 gai_afd = &gai_afdl[N_INET6]; 602 break; 603 #endif 604 } 605 #ifdef FAITH 606 if (translate && gai_afd->a_af == AF_INET) { 607 struct in6_addr *in6; 608 609 GET_AI(cur->ai_next, &gai_afdl[N_INET6], ap, port); 610 in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr; 611 memcpy(&in6->s6_addr32[0], &faith_prefix, 612 sizeof(struct in6_addr) - sizeof(struct in_addr)); 613 memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr)); 614 } else 615 #endif /* FAITH */ 616 GET_AI(cur->ai_next, gai_afd, ap, port); 617 if (cur == &sentinel) { 618 top = cur->ai_next; 619 GET_CANONNAME(top, hp->h_name); 620 } 621 cur = cur->ai_next; 622 } 623 #ifdef ENABLE_IPV6 624 freehostent(hp); 625 #endif 626 *res = top; 627 return SUCCESS; 628 free: 629 if (top) 630 freeaddrinfo(top); 631 #ifdef ENABLE_IPV6 632 if (hp) 633 freehostent(hp); 634 #endif 635 /* bad: */ 636 *res = NULL; 637 return error; 638 } 639