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