1 /* $NetBSD: getaddrinfo.c,v 1.113 2015/12/14 22:07:37 christos Exp $ */ 2 /* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Issues to be discussed: 35 * - Return values. There are nonstandard return values defined and used 36 * in the source code. This is because RFC2553 is silent about which error 37 * code must be returned for which situation. 38 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 39 * says to use inet_aton() to convert IPv4 numeric to binary (alows 40 * classful form as a result). 41 * current code - disallow classful form for IPv4 (due to use of inet_pton). 42 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is 43 * invalid. 44 * current code - SEGV on freeaddrinfo(NULL) 45 * Note: 46 * - The code filters out AFs that are not supported by the kernel, 47 * when globbing NULL hostname (to loopback, or wildcard). Is it the right 48 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 49 * in ai_flags? 50 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. 51 * (1) what should we do against numeric hostname (2) what should we do 52 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? 53 * non-loopback address configured? global address configured? 54 */ 55 56 #include <sys/cdefs.h> 57 #if defined(LIBC_SCCS) && !defined(lint) 58 __RCSID("$NetBSD: getaddrinfo.c,v 1.113 2015/12/14 22:07:37 christos Exp $"); 59 #endif /* LIBC_SCCS and not lint */ 60 61 #ifndef RUMP_ACTION 62 #include "namespace.h" 63 #endif 64 #include <sys/types.h> 65 #include <sys/param.h> 66 #include <sys/socket.h> 67 #include <sys/ioctl.h> 68 #include <sys/sysctl.h> 69 #include <net/if.h> 70 #include <netinet/in.h> 71 #include <netinet6/in6_var.h> 72 #include <arpa/inet.h> 73 #include <arpa/nameser.h> 74 #include <assert.h> 75 #include <ctype.h> 76 #include <errno.h> 77 #include <netdb.h> 78 #include <resolv.h> 79 #include <stddef.h> 80 #include <stdio.h> 81 #include <stdlib.h> 82 #include <string.h> 83 #include <unistd.h> 84 #include <ifaddrs.h> 85 86 #include <syslog.h> 87 #include <stdarg.h> 88 #include <nsswitch.h> 89 90 #ifdef YP 91 #include <rpc/rpc.h> 92 #include <rpcsvc/yp_prot.h> 93 #include <rpcsvc/ypclnt.h> 94 #endif 95 96 #include "servent.h" 97 98 #ifndef RUMP_ACTION 99 #ifdef __weak_alias 100 __weak_alias(getaddrinfo,_getaddrinfo) 101 __weak_alias(allocaddrinfo,_allocaddrinfo) 102 __weak_alias(freeaddrinfo,_freeaddrinfo) 103 __weak_alias(gai_strerror,_gai_strerror) 104 #endif 105 #endif 106 107 #define SUCCESS 0 108 #define ANY 0 109 #define YES 1 110 #define NO 0 111 112 static const char in_addrany[] = { 0, 0, 0, 0 }; 113 static const char in_loopback[] = { 127, 0, 0, 1 }; 114 #ifdef INET6 115 static const char in6_addrany[] = { 116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 117 }; 118 static const char in6_loopback[] = { 119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 120 }; 121 #endif 122 123 struct policyqueue { 124 TAILQ_ENTRY(policyqueue) pc_entry; 125 #ifdef INET6 126 struct in6_addrpolicy pc_policy; 127 #endif 128 }; 129 TAILQ_HEAD(policyhead, policyqueue); 130 131 static const struct afd { 132 int a_af; 133 int a_addrlen; 134 int a_socklen; 135 int a_off; 136 const char *a_addrany; 137 const char *a_loopback; 138 int a_scoped; 139 } afdl [] = { 140 #ifdef INET6 141 {PF_INET6, sizeof(struct in6_addr), 142 sizeof(struct sockaddr_in6), 143 offsetof(struct sockaddr_in6, sin6_addr), 144 in6_addrany, in6_loopback, 1}, 145 #endif 146 {PF_INET, sizeof(struct in_addr), 147 sizeof(struct sockaddr_in), 148 offsetof(struct sockaddr_in, sin_addr), 149 in_addrany, in_loopback, 0}, 150 {0, 0, 0, 0, NULL, NULL, 0}, 151 }; 152 153 struct explore { 154 int e_af; 155 int e_socktype; 156 int e_protocol; 157 const char *e_protostr; 158 int e_wild; 159 #define WILD_AF(ex) ((ex)->e_wild & 0x01) 160 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 161 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 162 }; 163 164 static const struct explore explore[] = { 165 #if 0 166 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, 167 #endif 168 #ifdef INET6 169 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 170 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 171 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 172 #endif 173 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 174 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 175 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 176 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 177 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 178 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, 179 { -1, 0, 0, NULL, 0 }, 180 }; 181 182 #ifdef INET6 183 #define PTON_MAX 16 184 #else 185 #define PTON_MAX 4 186 #endif 187 188 #define AIO_SRCFLAG_DEPRECATED 0x1 189 190 struct ai_order { 191 union { 192 struct sockaddr_storage aiou_ss; 193 struct sockaddr aiou_sa; 194 } aio_src_un; 195 #define aio_srcsa aio_src_un.aiou_sa 196 u_int32_t aio_srcflag; 197 int aio_srcscope; 198 int aio_dstscope; 199 struct policyqueue *aio_srcpolicy; 200 struct policyqueue *aio_dstpolicy; 201 struct addrinfo *aio_ai; 202 int aio_matchlen; 203 }; 204 205 static const ns_src default_dns_files[] = { 206 { NSSRC_FILES, NS_SUCCESS }, 207 { NSSRC_DNS, NS_SUCCESS }, 208 { 0, 0 } 209 }; 210 211 #define MAXPACKET (64*1024) 212 213 typedef union { 214 HEADER hdr; 215 u_char buf[MAXPACKET]; 216 } querybuf; 217 218 struct res_target { 219 struct res_target *next; 220 const char *name; /* domain name */ 221 int qclass, qtype; /* class and type of query */ 222 u_char *answer; /* buffer to put answer */ 223 int anslen; /* size of answer buffer */ 224 int n; /* result length */ 225 }; 226 227 struct srvinfo { 228 struct srvinfo *next; 229 char name[MAXDNAME]; 230 int port, pri, weight; 231 }; 232 233 static int gai_srvok(const char *); 234 static int str2number(const char *); 235 static int explore_fqdn(const struct addrinfo *, const char *, 236 const char *, struct addrinfo **, struct servent_data *); 237 static int explore_null(const struct addrinfo *, 238 const char *, struct addrinfo **, struct servent_data *); 239 static int explore_numeric(const struct addrinfo *, const char *, 240 const char *, struct addrinfo **, const char *, struct servent_data *); 241 static int explore_numeric_scope(const struct addrinfo *, const char *, 242 const char *, struct addrinfo **, struct servent_data *); 243 static int get_canonname(const struct addrinfo *, 244 struct addrinfo *, const char *); 245 static struct addrinfo *get_ai(const struct addrinfo *, 246 const struct afd *, const char *); 247 static int get_portmatch(const struct addrinfo *, const char *, 248 struct servent_data *); 249 static int get_port(const struct addrinfo *, const char *, int, 250 struct servent_data *); 251 static const struct afd *find_afd(int); 252 static int addrconfig(uint64_t *); 253 static void set_source(struct ai_order *, struct policyhead *, 254 struct servent_data *); 255 static int comp_dst(const void *, const void *); 256 #ifdef INET6 257 static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); 258 #endif 259 static int gai_addr2scopetype(struct sockaddr *); 260 261 static int reorder(struct addrinfo *, struct servent_data *); 262 static int get_addrselectpolicy(struct policyhead *); 263 static void free_addrselectpolicy(struct policyhead *); 264 static struct policyqueue *match_addrselectpolicy(struct sockaddr *, 265 struct policyhead *); 266 static int matchlen(struct sockaddr *, struct sockaddr *); 267 268 static struct addrinfo *getanswer(res_state, const querybuf *, int, 269 const char *, int, const struct addrinfo *); 270 static void aisort(struct addrinfo *s, res_state res); 271 static struct addrinfo * _dns_query(struct res_target *, 272 const struct addrinfo *, res_state, int); 273 static struct addrinfo * _dns_srv_lookup(const char *, const char *, 274 const struct addrinfo *); 275 static struct addrinfo * _dns_host_lookup(const char *, 276 const struct addrinfo *); 277 static int _dns_getaddrinfo(void *, void *, va_list); 278 static void _sethtent(FILE **); 279 static void _endhtent(FILE **); 280 static struct addrinfo *_gethtent(FILE **, const char *, 281 const struct addrinfo *); 282 static int _files_getaddrinfo(void *, void *, va_list); 283 #ifdef YP 284 static struct addrinfo *_yphostent(char *, const struct addrinfo *); 285 static int _yp_getaddrinfo(void *, void *, va_list); 286 #endif 287 288 static int res_queryN(const char *, struct res_target *, res_state); 289 static int res_searchN(const char *, struct res_target *, res_state); 290 static int res_querydomainN(const char *, const char *, 291 struct res_target *, res_state); 292 293 static const char * const ai_errlist[] = { 294 "Success", 295 "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 296 "Temporary failure in name resolution", /* EAI_AGAIN */ 297 "Invalid value for ai_flags", /* EAI_BADFLAGS */ 298 "Non-recoverable failure in name resolution", /* EAI_FAIL */ 299 "ai_family not supported", /* EAI_FAMILY */ 300 "Memory allocation failure", /* EAI_MEMORY */ 301 "No address associated with hostname", /* EAI_NODATA */ 302 "hostname nor servname provided, or not known", /* EAI_NONAME */ 303 "servname not supported for ai_socktype", /* EAI_SERVICE */ 304 "ai_socktype not supported", /* EAI_SOCKTYPE */ 305 "System error returned in errno", /* EAI_SYSTEM */ 306 "Invalid value for hints", /* EAI_BADHINTS */ 307 "Resolved protocol is unknown", /* EAI_PROTOCOL */ 308 "Argument buffer overflow", /* EAI_OVERFLOW */ 309 "Unknown error", /* EAI_MAX */ 310 }; 311 312 /* XXX macros that make external reference is BAD. */ 313 314 #define GET_AI(ai, afd, addr) \ 315 do { \ 316 /* external reference: pai, error, and label free */ \ 317 (ai) = get_ai(pai, (afd), (addr)); \ 318 if ((ai) == NULL) { \ 319 error = EAI_MEMORY; \ 320 goto free; \ 321 } \ 322 } while (/*CONSTCOND*/0) 323 324 #define GET_PORT(ai, serv, svd) \ 325 do { \ 326 /* external reference: error and label free */ \ 327 error = get_port((ai), (serv), 0, (svd)); \ 328 if (error != 0) \ 329 goto free; \ 330 } while (/*CONSTCOND*/0) 331 332 #define GET_CANONNAME(ai, str) \ 333 do { \ 334 /* external reference: pai, error and label free */ \ 335 error = get_canonname(pai, (ai), (str)); \ 336 if (error != 0) \ 337 goto free; \ 338 } while (/*CONSTCOND*/0) 339 340 #define ERR(err) \ 341 do { \ 342 /* external reference: error, and label bad */ \ 343 error = (err); \ 344 goto bad; \ 345 /*NOTREACHED*/ \ 346 } while (/*CONSTCOND*/0) 347 348 #define MATCH_FAMILY(x, y, w) \ 349 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \ 350 (y) == PF_UNSPEC))) 351 #define MATCH(x, y, w) \ 352 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) 353 354 const char * 355 gai_strerror(int ecode) 356 { 357 if (ecode < 0 || ecode > EAI_MAX) 358 ecode = EAI_MAX; 359 return ai_errlist[ecode]; 360 } 361 362 void 363 freeaddrinfo(struct addrinfo *ai) 364 { 365 struct addrinfo *next; 366 367 _DIAGASSERT(ai != NULL); 368 369 do { 370 next = ai->ai_next; 371 if (ai->ai_canonname) 372 free(ai->ai_canonname); 373 /* no need to free(ai->ai_addr) */ 374 free(ai); 375 ai = next; 376 } while (ai); 377 } 378 379 /* 380 * We don't want localization to affect us 381 */ 382 #define PERIOD '.' 383 #define hyphenchar(c) ((c) == '-') 384 #define periodchar(c) ((c) == PERIOD) 385 #define underschar(c) ((c) == '_') 386 #define alphachar(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) 387 #define digitchar(c) ((c) >= '0' && (c) <= '9') 388 389 #define firstchar(c) (alphachar(c) || digitchar(c) || underschar(c)) 390 #define lastchar(c) (alphachar(c) || digitchar(c)) 391 #define middlechar(c) (lastchar(c) || hyphenchar(c)) 392 393 static int 394 gai_srvok(const char *dn) 395 { 396 int nch, pch, ch; 397 398 for (pch = PERIOD, nch = ch = *dn++; ch != '\0'; pch = ch, ch = nch) { 399 if (periodchar(ch)) 400 continue; 401 if (periodchar(pch)) { 402 if (!firstchar(ch)) 403 return 0; 404 } else if (periodchar(nch) || nch == '\0') { 405 if (!lastchar(ch)) 406 return 0; 407 } else if (!middlechar(ch)) 408 return 0; 409 } 410 return 1; 411 } 412 413 static in_port_t * 414 getport(struct addrinfo *ai) { 415 static in_port_t p; 416 417 switch (ai->ai_family) { 418 case AF_INET: 419 return &((struct sockaddr_in *)(void *)ai->ai_addr)->sin_port; 420 #ifdef INET6 421 case AF_INET6: 422 return &((struct sockaddr_in6 *)(void *)ai->ai_addr)->sin6_port; 423 #endif 424 default: 425 p = 0; 426 /* XXX: abort()? */ 427 return &p; 428 } 429 } 430 431 static int 432 str2number(const char *p) 433 { 434 char *ep; 435 unsigned long v; 436 437 _DIAGASSERT(p != NULL); 438 439 if (*p == '\0') 440 return -1; 441 ep = NULL; 442 errno = 0; 443 v = strtoul(p, &ep, 10); 444 if (errno == 0 && ep && *ep == '\0' && v <= INT_MAX) 445 return (int)v; 446 else 447 return -1; 448 } 449 450 int 451 getaddrinfo(const char *hostname, const char *servname, 452 const struct addrinfo *hints, struct addrinfo **res) 453 { 454 struct addrinfo sentinel; 455 struct addrinfo *cur; 456 int error = 0; 457 struct addrinfo ai; 458 struct addrinfo ai0; 459 struct addrinfo *pai; 460 const struct explore *ex; 461 struct servent_data svd; 462 uint64_t mask = (uint64_t)~0ULL; 463 int numeric = 0; 464 465 /* hostname is allowed to be NULL */ 466 /* servname is allowed to be NULL */ 467 /* hints is allowed to be NULL */ 468 _DIAGASSERT(res != NULL); 469 470 (void)memset(&svd, 0, sizeof(svd)); 471 memset(&sentinel, 0, sizeof(sentinel)); 472 cur = &sentinel; 473 memset(&ai, 0, sizeof(ai)); 474 pai = &ai; 475 pai->ai_flags = 0; 476 pai->ai_family = PF_UNSPEC; 477 pai->ai_socktype = ANY; 478 pai->ai_protocol = ANY; 479 pai->ai_addrlen = 0; 480 pai->ai_canonname = NULL; 481 pai->ai_addr = NULL; 482 pai->ai_next = NULL; 483 484 if (hostname == NULL && servname == NULL) 485 return EAI_NONAME; 486 if (hints) { 487 /* error check for hints */ 488 if (hints->ai_addrlen || hints->ai_canonname || 489 hints->ai_addr || hints->ai_next) 490 ERR(EAI_BADHINTS); /* xxx */ 491 if (hints->ai_flags & ~AI_MASK) 492 ERR(EAI_BADFLAGS); 493 switch (hints->ai_family) { 494 case PF_UNSPEC: 495 case PF_INET: 496 #ifdef INET6 497 case PF_INET6: 498 #endif 499 break; 500 default: 501 ERR(EAI_FAMILY); 502 } 503 memcpy(pai, hints, sizeof(*pai)); 504 505 /* 506 * if both socktype/protocol are specified, check if they 507 * are meaningful combination. 508 */ 509 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 510 for (ex = explore; ex->e_af >= 0; ex++) { 511 if (pai->ai_family != ex->e_af) 512 continue; 513 if (ex->e_socktype == ANY) 514 continue; 515 if (ex->e_protocol == ANY) 516 continue; 517 if (pai->ai_socktype == ex->e_socktype 518 && pai->ai_protocol != ex->e_protocol) { 519 ERR(EAI_BADHINTS); 520 } 521 } 522 } 523 } 524 525 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && addrconfig(&mask) == -1) 526 ERR(EAI_FAIL); 527 528 /* 529 * check for special cases. (1) numeric servname is disallowed if 530 * socktype/protocol are left unspecified. (2) servname is disallowed 531 * for raw and other inet{,6} sockets. 532 */ 533 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 534 #ifdef PF_INET6 535 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 536 #endif 537 ) { 538 ai0 = *pai; /* backup *pai */ 539 540 if (pai->ai_family == PF_UNSPEC) { 541 #ifdef PF_INET6 542 pai->ai_family = PF_INET6; 543 #else 544 pai->ai_family = PF_INET; 545 #endif 546 } 547 error = get_portmatch(pai, servname, &svd); 548 if (error) 549 goto bad; 550 551 *pai = ai0; 552 } 553 554 ai0 = *pai; 555 556 /* NULL hostname, or numeric hostname */ 557 for (ex = explore; ex->e_af >= 0; ex++) { 558 *pai = ai0; 559 560 /* ADDRCONFIG check */ 561 if ((((uint64_t)1 << ex->e_af) & mask) == 0) 562 continue; 563 564 /* PF_UNSPEC entries are prepared for DNS queries only */ 565 if (ex->e_af == PF_UNSPEC) 566 continue; 567 568 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 569 continue; 570 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 571 continue; 572 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 573 continue; 574 if (pai->ai_family == PF_UNSPEC) 575 pai->ai_family = ex->e_af; 576 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 577 pai->ai_socktype = ex->e_socktype; 578 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 579 pai->ai_protocol = ex->e_protocol; 580 581 if (hostname == NULL) 582 error = explore_null(pai, servname, &cur->ai_next, 583 &svd); 584 else 585 error = explore_numeric_scope(pai, hostname, servname, 586 &cur->ai_next, &svd); 587 588 if (error) 589 goto free; 590 591 while (cur->ai_next) 592 cur = cur->ai_next; 593 } 594 595 /* 596 * XXX 597 * If numeric representation of AF1 can be interpreted as FQDN 598 * representation of AF2, we need to think again about the code below. 599 */ 600 if (sentinel.ai_next) { 601 numeric = 1; 602 goto good; 603 } 604 605 if (hostname == NULL) 606 ERR(EAI_NODATA); 607 if (pai->ai_flags & AI_NUMERICHOST) 608 ERR(EAI_NONAME); 609 610 /* 611 * hostname as alphabetical name. 612 * we would like to prefer AF_INET6 than AF_INET, so we'll make a 613 * outer loop by AFs. 614 */ 615 for (ex = explore; ex->e_af >= 0; ex++) { 616 *pai = ai0; 617 618 619 /* ADDRCONFIG check */ 620 /* PF_UNSPEC entries are prepared for DNS queries only */ 621 if (ex->e_af != PF_UNSPEC && 622 (((uint64_t)1 << ex->e_af) & mask) == 0) 623 continue; 624 625 /* require exact match for family field */ 626 if (pai->ai_family != ex->e_af) 627 continue; 628 629 if (!MATCH(pai->ai_socktype, ex->e_socktype, 630 WILD_SOCKTYPE(ex))) { 631 continue; 632 } 633 if (!MATCH(pai->ai_protocol, ex->e_protocol, 634 WILD_PROTOCOL(ex))) { 635 continue; 636 } 637 638 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 639 pai->ai_socktype = ex->e_socktype; 640 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 641 pai->ai_protocol = ex->e_protocol; 642 643 error = explore_fqdn(pai, hostname, servname, &cur->ai_next, 644 &svd); 645 646 while (cur && cur->ai_next) 647 cur = cur->ai_next; 648 } 649 650 /* XXX */ 651 if (sentinel.ai_next) 652 error = 0; 653 654 if (error) 655 goto free; 656 657 if (sentinel.ai_next) { 658 good: 659 /* 660 * If the returned entry is for an active connection, 661 * and the given name is not numeric, reorder the 662 * list, so that the application would try the list 663 * in the most efficient order. Since the head entry 664 * of the original list may contain ai_canonname and 665 * that entry may be moved elsewhere in the new list, 666 * we keep the pointer and will restore it in the new 667 * head entry. (Note that RFC3493 requires the head 668 * entry store it when requested by the caller). 669 */ 670 if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) { 671 if (!numeric) { 672 char *canonname; 673 674 canonname = sentinel.ai_next->ai_canonname; 675 sentinel.ai_next->ai_canonname = NULL; 676 (void)reorder(&sentinel, &svd); 677 if (sentinel.ai_next->ai_canonname == NULL) { 678 sentinel.ai_next->ai_canonname 679 = canonname; 680 } else if (canonname != NULL) 681 free(canonname); 682 } 683 } 684 endservent_r(&svd); 685 *res = sentinel.ai_next; 686 return SUCCESS; 687 } else 688 error = EAI_FAIL; 689 free: 690 bad: 691 endservent_r(&svd); 692 if (sentinel.ai_next) 693 freeaddrinfo(sentinel.ai_next); 694 *res = NULL; 695 return error; 696 } 697 698 static int 699 reorder(struct addrinfo *sentinel, struct servent_data *svd) 700 { 701 struct addrinfo *ai, **aip; 702 struct ai_order *aio; 703 int i, n; 704 struct policyhead policyhead; 705 706 /* count the number of addrinfo elements for sorting. */ 707 for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++) 708 ; 709 710 /* 711 * If the number is small enough, we can skip the reordering process. 712 */ 713 if (n <= 1) 714 return(n); 715 716 /* allocate a temporary array for sort and initialization of it. */ 717 if ((aio = malloc(sizeof(*aio) * n)) == NULL) 718 return(n); /* give up reordering */ 719 memset(aio, 0, sizeof(*aio) * n); 720 721 /* retrieve address selection policy from the kernel */ 722 TAILQ_INIT(&policyhead); 723 if (!get_addrselectpolicy(&policyhead)) { 724 /* no policy is installed into kernel, we don't sort. */ 725 free(aio); 726 return (n); 727 } 728 729 for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) { 730 aio[i].aio_ai = ai; 731 aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr); 732 aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr, 733 &policyhead); 734 set_source(&aio[i], &policyhead, svd); 735 } 736 737 /* perform sorting. */ 738 qsort(aio, n, sizeof(*aio), comp_dst); 739 740 /* reorder the addrinfo chain. */ 741 for (i = 0, aip = &sentinel->ai_next; i < n; i++) { 742 *aip = aio[i].aio_ai; 743 aip = &aio[i].aio_ai->ai_next; 744 } 745 *aip = NULL; 746 747 /* cleanup and return */ 748 free(aio); 749 free_addrselectpolicy(&policyhead); 750 return(n); 751 } 752 753 static int 754 get_addrselectpolicy(struct policyhead *head) 755 { 756 #ifdef INET6 757 int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY }; 758 size_t l; 759 char *buf; 760 struct in6_addrpolicy *pol, *ep; 761 762 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) 763 return (0); 764 if (l == 0) 765 return (0); 766 if ((buf = malloc(l)) == NULL) 767 return (0); 768 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { 769 free(buf); 770 return (0); 771 } 772 773 ep = (struct in6_addrpolicy *)(buf + l); 774 for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) { 775 struct policyqueue *new; 776 777 if ((new = malloc(sizeof(*new))) == NULL) { 778 free_addrselectpolicy(head); /* make the list empty */ 779 break; 780 } 781 new->pc_policy = *pol; 782 TAILQ_INSERT_TAIL(head, new, pc_entry); 783 } 784 785 free(buf); 786 return (1); 787 #else 788 return (0); 789 #endif 790 } 791 792 static void 793 free_addrselectpolicy(struct policyhead *head) 794 { 795 struct policyqueue *ent, *nent; 796 797 for (ent = TAILQ_FIRST(head); ent; ent = nent) { 798 nent = TAILQ_NEXT(ent, pc_entry); 799 TAILQ_REMOVE(head, ent, pc_entry); 800 free(ent); 801 } 802 } 803 804 static struct policyqueue * 805 match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head) 806 { 807 #ifdef INET6 808 struct policyqueue *ent, *bestent = NULL; 809 struct in6_addrpolicy *pol; 810 int matchlen, bestmatchlen = -1; 811 u_char *mp, *ep, *k, *p, m; 812 struct sockaddr_in6 key; 813 814 switch(addr->sa_family) { 815 case AF_INET6: 816 key = *(struct sockaddr_in6 *)addr; 817 break; 818 case AF_INET: 819 /* convert the address into IPv4-mapped IPv6 address. */ 820 memset(&key, 0, sizeof(key)); 821 key.sin6_family = AF_INET6; 822 key.sin6_len = sizeof(key); 823 key.sin6_addr.s6_addr[10] = 0xff; 824 key.sin6_addr.s6_addr[11] = 0xff; 825 memcpy(&key.sin6_addr.s6_addr[12], 826 &((struct sockaddr_in *)addr)->sin_addr, 4); 827 break; 828 default: 829 return(NULL); 830 } 831 832 for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) { 833 pol = &ent->pc_policy; 834 matchlen = 0; 835 836 mp = (u_char *)&pol->addrmask.sin6_addr; 837 ep = mp + 16; /* XXX: scope field? */ 838 k = (u_char *)&key.sin6_addr; 839 p = (u_char *)&pol->addr.sin6_addr; 840 for (; mp < ep && *mp; mp++, k++, p++) { 841 m = *mp; 842 if ((*k & m) != *p) 843 goto next; /* not match */ 844 if (m == 0xff) /* short cut for a typical case */ 845 matchlen += 8; 846 else { 847 while (m >= 0x80) { 848 matchlen++; 849 m <<= 1; 850 } 851 } 852 } 853 854 /* matched. check if this is better than the current best. */ 855 if (matchlen > bestmatchlen) { 856 bestent = ent; 857 bestmatchlen = matchlen; 858 } 859 860 next: 861 continue; 862 } 863 864 return(bestent); 865 #else 866 return(NULL); 867 #endif 868 869 } 870 871 static void 872 set_source(struct ai_order *aio, struct policyhead *ph, 873 struct servent_data *svd) 874 { 875 struct addrinfo ai = *aio->aio_ai; 876 struct sockaddr_storage ss; 877 socklen_t srclen; 878 int s; 879 880 /* set unspec ("no source is available"), just in case */ 881 aio->aio_srcsa.sa_family = AF_UNSPEC; 882 aio->aio_srcscope = -1; 883 884 switch(ai.ai_family) { 885 case AF_INET: 886 #ifdef INET6 887 case AF_INET6: 888 #endif 889 break; 890 default: /* ignore unsupported AFs explicitly */ 891 return; 892 } 893 894 /* XXX: make a dummy addrinfo to call connect() */ 895 ai.ai_socktype = SOCK_DGRAM; 896 ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */ 897 ai.ai_next = NULL; 898 memset(&ss, 0, sizeof(ss)); 899 memcpy(&ss, ai.ai_addr, ai.ai_addrlen); 900 ai.ai_addr = (struct sockaddr *)&ss; 901 get_port(&ai, "1", 0, svd); 902 903 /* open a socket to get the source address for the given dst */ 904 if ((s = socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC, 905 ai.ai_protocol)) < 0) 906 return; /* give up */ 907 if (connect(s, ai.ai_addr, ai.ai_addrlen) < 0) 908 goto cleanup; 909 srclen = ai.ai_addrlen; 910 if (getsockname(s, &aio->aio_srcsa, &srclen) < 0) { 911 aio->aio_srcsa.sa_family = AF_UNSPEC; 912 goto cleanup; 913 } 914 aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa); 915 aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph); 916 aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr); 917 #ifdef INET6 918 if (ai.ai_family == AF_INET6) { 919 struct in6_ifreq ifr6; 920 u_int32_t flags6; 921 922 memset(&ifr6, 0, sizeof(ifr6)); 923 memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen); 924 if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) { 925 flags6 = ifr6.ifr_ifru.ifru_flags6; 926 if ((flags6 & IN6_IFF_DEPRECATED)) 927 aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED; 928 } 929 } 930 #endif 931 932 cleanup: 933 close(s); 934 return; 935 } 936 937 static int 938 matchlen(struct sockaddr *src, struct sockaddr *dst) 939 { 940 int match = 0; 941 u_char *s, *d; 942 u_char *lim, r; 943 int addrlen; 944 945 switch (src->sa_family) { 946 #ifdef INET6 947 case AF_INET6: 948 s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr; 949 d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr; 950 addrlen = sizeof(struct in6_addr); 951 lim = s + addrlen; 952 break; 953 #endif 954 case AF_INET: 955 s = (u_char *)&((struct sockaddr_in *)src)->sin_addr; 956 d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr; 957 addrlen = sizeof(struct in_addr); 958 lim = s + addrlen; 959 break; 960 default: 961 return(0); 962 } 963 964 while (s < lim) 965 if ((r = (*d++ ^ *s++)) != 0) { 966 while (r < addrlen * 8) { 967 match++; 968 r <<= 1; 969 } 970 break; 971 } else 972 match += 8; 973 return(match); 974 } 975 976 static int 977 comp_dst(const void *arg1, const void *arg2) 978 { 979 const struct ai_order *dst1 = arg1, *dst2 = arg2; 980 981 /* 982 * Rule 1: Avoid unusable destinations. 983 * XXX: we currently do not consider if an appropriate route exists. 984 */ 985 if (dst1->aio_srcsa.sa_family != AF_UNSPEC && 986 dst2->aio_srcsa.sa_family == AF_UNSPEC) { 987 return(-1); 988 } 989 if (dst1->aio_srcsa.sa_family == AF_UNSPEC && 990 dst2->aio_srcsa.sa_family != AF_UNSPEC) { 991 return(1); 992 } 993 994 /* Rule 2: Prefer matching scope. */ 995 if (dst1->aio_dstscope == dst1->aio_srcscope && 996 dst2->aio_dstscope != dst2->aio_srcscope) { 997 return(-1); 998 } 999 if (dst1->aio_dstscope != dst1->aio_srcscope && 1000 dst2->aio_dstscope == dst2->aio_srcscope) { 1001 return(1); 1002 } 1003 1004 /* Rule 3: Avoid deprecated addresses. */ 1005 if (dst1->aio_srcsa.sa_family != AF_UNSPEC && 1006 dst2->aio_srcsa.sa_family != AF_UNSPEC) { 1007 if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && 1008 (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { 1009 return(-1); 1010 } 1011 if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && 1012 !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { 1013 return(1); 1014 } 1015 } 1016 1017 /* Rule 4: Prefer home addresses. */ 1018 /* XXX: not implemented yet */ 1019 1020 /* Rule 5: Prefer matching label. */ 1021 #ifdef INET6 1022 if (dst1->aio_srcpolicy && dst1->aio_dstpolicy && 1023 dst1->aio_srcpolicy->pc_policy.label == 1024 dst1->aio_dstpolicy->pc_policy.label && 1025 (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL || 1026 dst2->aio_srcpolicy->pc_policy.label != 1027 dst2->aio_dstpolicy->pc_policy.label)) { 1028 return(-1); 1029 } 1030 if (dst2->aio_srcpolicy && dst2->aio_dstpolicy && 1031 dst2->aio_srcpolicy->pc_policy.label == 1032 dst2->aio_dstpolicy->pc_policy.label && 1033 (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL || 1034 dst1->aio_srcpolicy->pc_policy.label != 1035 dst1->aio_dstpolicy->pc_policy.label)) { 1036 return(1); 1037 } 1038 #endif 1039 1040 /* Rule 6: Prefer higher precedence. */ 1041 #ifdef INET6 1042 if (dst1->aio_dstpolicy && 1043 (dst2->aio_dstpolicy == NULL || 1044 dst1->aio_dstpolicy->pc_policy.preced > 1045 dst2->aio_dstpolicy->pc_policy.preced)) { 1046 return(-1); 1047 } 1048 if (dst2->aio_dstpolicy && 1049 (dst1->aio_dstpolicy == NULL || 1050 dst2->aio_dstpolicy->pc_policy.preced > 1051 dst1->aio_dstpolicy->pc_policy.preced)) { 1052 return(1); 1053 } 1054 #endif 1055 1056 /* Rule 7: Prefer native transport. */ 1057 /* XXX: not implemented yet */ 1058 1059 /* Rule 8: Prefer smaller scope. */ 1060 if (dst1->aio_dstscope >= 0 && 1061 dst1->aio_dstscope < dst2->aio_dstscope) { 1062 return(-1); 1063 } 1064 if (dst2->aio_dstscope >= 0 && 1065 dst2->aio_dstscope < dst1->aio_dstscope) { 1066 return(1); 1067 } 1068 1069 /* 1070 * Rule 9: Use longest matching prefix. 1071 * We compare the match length in a same AF only. 1072 */ 1073 if (dst1->aio_ai->ai_addr->sa_family == 1074 dst2->aio_ai->ai_addr->sa_family && 1075 dst1->aio_ai->ai_addr->sa_family != AF_INET) { 1076 if (dst1->aio_matchlen > dst2->aio_matchlen) { 1077 return(-1); 1078 } 1079 if (dst1->aio_matchlen < dst2->aio_matchlen) { 1080 return(1); 1081 } 1082 } 1083 1084 /* Rule 10: Otherwise, leave the order unchanged. */ 1085 return(-1); 1086 } 1087 1088 /* 1089 * Copy from scope.c. 1090 * XXX: we should standardize the functions and link them as standard 1091 * library. 1092 */ 1093 static int 1094 gai_addr2scopetype(struct sockaddr *sa) 1095 { 1096 #ifdef INET6 1097 struct sockaddr_in6 *sa6; 1098 #endif 1099 struct sockaddr_in *sa4; 1100 1101 switch(sa->sa_family) { 1102 #ifdef INET6 1103 case AF_INET6: 1104 sa6 = (struct sockaddr_in6 *)sa; 1105 if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) { 1106 /* just use the scope field of the multicast address */ 1107 return(sa6->sin6_addr.s6_addr[2] & 0x0f); 1108 } 1109 /* 1110 * Unicast addresses: map scope type to corresponding scope 1111 * value defined for multcast addresses. 1112 * XXX: hardcoded scope type values are bad... 1113 */ 1114 if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) 1115 return(1); /* node local scope */ 1116 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) 1117 return(2); /* link-local scope */ 1118 if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr)) 1119 return(5); /* site-local scope */ 1120 return(14); /* global scope */ 1121 break; 1122 #endif 1123 case AF_INET: 1124 /* 1125 * IPv4 pseudo scoping according to RFC 3484. 1126 */ 1127 sa4 = (struct sockaddr_in *)sa; 1128 /* IPv4 autoconfiguration addresses have link-local scope. */ 1129 if (((u_char *)&sa4->sin_addr)[0] == 169 && 1130 ((u_char *)&sa4->sin_addr)[1] == 254) 1131 return(2); 1132 /* Private addresses have site-local scope. */ 1133 if (((u_char *)&sa4->sin_addr)[0] == 10 || 1134 (((u_char *)&sa4->sin_addr)[0] == 172 && 1135 (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) || 1136 (((u_char *)&sa4->sin_addr)[0] == 192 && 1137 ((u_char *)&sa4->sin_addr)[1] == 168)) 1138 return(14); /* XXX: It should be 5 unless NAT */ 1139 /* Loopback addresses have link-local scope. */ 1140 if (((u_char *)&sa4->sin_addr)[0] == 127) 1141 return(2); 1142 return(14); 1143 break; 1144 default: 1145 errno = EAFNOSUPPORT; /* is this a good error? */ 1146 return(-1); 1147 } 1148 } 1149 1150 /* 1151 * FQDN hostname, DNS lookup 1152 */ 1153 static int 1154 explore_fqdn(const struct addrinfo *pai, const char *hostname, 1155 const char *servname, struct addrinfo **res, struct servent_data *svd) 1156 { 1157 struct addrinfo *result; 1158 struct addrinfo *cur; 1159 int error = 0; 1160 static const ns_dtab dtab[] = { 1161 NS_FILES_CB(_files_getaddrinfo, NULL) 1162 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ 1163 NS_NIS_CB(_yp_getaddrinfo, NULL) 1164 NS_NULL_CB 1165 }; 1166 1167 _DIAGASSERT(pai != NULL); 1168 /* hostname may be NULL */ 1169 /* servname may be NULL */ 1170 _DIAGASSERT(res != NULL); 1171 1172 result = NULL; 1173 1174 /* 1175 * if the servname does not match socktype/protocol, ignore it. 1176 */ 1177 if (get_portmatch(pai, servname, svd) != 0) 1178 return 0; 1179 1180 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", 1181 default_dns_files, hostname, pai, servname)) { 1182 case NS_TRYAGAIN: 1183 error = EAI_AGAIN; 1184 goto free; 1185 case NS_UNAVAIL: 1186 error = EAI_FAIL; 1187 goto free; 1188 case NS_NOTFOUND: 1189 error = EAI_NONAME; 1190 goto free; 1191 case NS_SUCCESS: 1192 error = 0; 1193 for (cur = result; cur; cur = cur->ai_next) { 1194 /* Check for already filled port. */ 1195 if (*getport(cur)) 1196 continue; 1197 GET_PORT(cur, servname, svd); 1198 /* canonname should be filled already */ 1199 } 1200 break; 1201 } 1202 1203 *res = result; 1204 1205 return 0; 1206 1207 free: 1208 if (result) 1209 freeaddrinfo(result); 1210 return error; 1211 } 1212 1213 /* 1214 * hostname == NULL. 1215 * passive socket -> anyaddr (0.0.0.0 or ::) 1216 * non-passive socket -> localhost (127.0.0.1 or ::1) 1217 */ 1218 static int 1219 explore_null(const struct addrinfo *pai, const char *servname, 1220 struct addrinfo **res, struct servent_data *svd) 1221 { 1222 int s; 1223 const struct afd *afd; 1224 struct addrinfo *cur; 1225 struct addrinfo sentinel; 1226 int error; 1227 1228 _DIAGASSERT(pai != NULL); 1229 /* servname may be NULL */ 1230 _DIAGASSERT(res != NULL); 1231 1232 *res = NULL; 1233 sentinel.ai_next = NULL; 1234 cur = &sentinel; 1235 1236 /* 1237 * filter out AFs that are not supported by the kernel 1238 * XXX errno? 1239 */ 1240 s = socket(pai->ai_family, SOCK_DGRAM, 0); 1241 if (s < 0) { 1242 if (errno != EMFILE) 1243 return 0; 1244 } else 1245 close(s); 1246 1247 /* 1248 * if the servname does not match socktype/protocol, ignore it. 1249 */ 1250 if (get_portmatch(pai, servname, svd) != 0) 1251 return 0; 1252 1253 afd = find_afd(pai->ai_family); 1254 if (afd == NULL) 1255 return 0; 1256 1257 if (pai->ai_flags & AI_PASSIVE) { 1258 GET_AI(cur->ai_next, afd, afd->a_addrany); 1259 /* xxx meaningless? 1260 * GET_CANONNAME(cur->ai_next, "anyaddr"); 1261 */ 1262 GET_PORT(cur->ai_next, servname, svd); 1263 } else { 1264 GET_AI(cur->ai_next, afd, afd->a_loopback); 1265 /* xxx meaningless? 1266 * GET_CANONNAME(cur->ai_next, "localhost"); 1267 */ 1268 GET_PORT(cur->ai_next, servname, svd); 1269 } 1270 cur = cur->ai_next; 1271 1272 *res = sentinel.ai_next; 1273 return 0; 1274 1275 free: 1276 if (sentinel.ai_next) 1277 freeaddrinfo(sentinel.ai_next); 1278 return error; 1279 } 1280 1281 /* 1282 * numeric hostname 1283 */ 1284 static int 1285 explore_numeric(const struct addrinfo *pai, const char *hostname, 1286 const char *servname, struct addrinfo **res, const char *canonname, 1287 struct servent_data *svd) 1288 { 1289 const struct afd *afd; 1290 struct addrinfo *cur; 1291 struct addrinfo sentinel; 1292 int error; 1293 char pton[PTON_MAX]; 1294 1295 _DIAGASSERT(pai != NULL); 1296 /* hostname may be NULL */ 1297 /* servname may be NULL */ 1298 _DIAGASSERT(res != NULL); 1299 1300 *res = NULL; 1301 sentinel.ai_next = NULL; 1302 cur = &sentinel; 1303 1304 /* 1305 * if the servname does not match socktype/protocol, ignore it. 1306 */ 1307 if (get_portmatch(pai, servname, svd) != 0) 1308 return 0; 1309 1310 afd = find_afd(pai->ai_family); 1311 if (afd == NULL) 1312 return 0; 1313 1314 switch (afd->a_af) { 1315 case AF_INET: 1316 /* 1317 * RFC3493 section 6.1, requires getaddrinfo() to accept 1318 * AF_INET formats that are accepted by inet_addr(); here 1319 * we use the equivalent inet_aton() function so we can 1320 * check for errors. inet_pton() only accepts addresses 1321 * in the dotted quad format and only in base 10, so we 1322 * need to treat AF_INET specially. 1323 */ 1324 if (inet_aton(hostname, (struct in_addr *)pton) == 1) { 1325 if (pai->ai_family == afd->a_af || 1326 pai->ai_family == PF_UNSPEC /*?*/) { 1327 GET_AI(cur->ai_next, afd, pton); 1328 GET_PORT(cur->ai_next, servname, svd); 1329 if ((pai->ai_flags & AI_CANONNAME)) { 1330 /* 1331 * Set the numeric address itself as 1332 * the canonical name, based on a 1333 * clarification in rfc2553bis-03. 1334 */ 1335 GET_CANONNAME(cur->ai_next, canonname); 1336 } 1337 while (cur && cur->ai_next) 1338 cur = cur->ai_next; 1339 } else 1340 ERR(EAI_FAMILY); /*xxx*/ 1341 } 1342 break; 1343 default: 1344 if (inet_pton(afd->a_af, hostname, pton) == 1) { 1345 if (pai->ai_family == afd->a_af || 1346 pai->ai_family == PF_UNSPEC /*?*/) { 1347 GET_AI(cur->ai_next, afd, pton); 1348 GET_PORT(cur->ai_next, servname, svd); 1349 if ((pai->ai_flags & AI_CANONNAME)) { 1350 /* 1351 * Set the numeric address itself as 1352 * the canonical name, based on a 1353 * clarification in rfc2553bis-03. 1354 */ 1355 GET_CANONNAME(cur->ai_next, canonname); 1356 } 1357 while (cur->ai_next) 1358 cur = cur->ai_next; 1359 } else 1360 ERR(EAI_FAMILY); /*xxx*/ 1361 } 1362 break; 1363 } 1364 1365 *res = sentinel.ai_next; 1366 return 0; 1367 1368 free: 1369 bad: 1370 if (sentinel.ai_next) 1371 freeaddrinfo(sentinel.ai_next); 1372 return error; 1373 } 1374 1375 /* 1376 * numeric hostname with scope 1377 */ 1378 static int 1379 explore_numeric_scope(const struct addrinfo *pai, const char *hostname, 1380 const char *servname, struct addrinfo **res, struct servent_data *svd) 1381 { 1382 #if !defined(SCOPE_DELIMITER) || !defined(INET6) 1383 return explore_numeric(pai, hostname, servname, res, hostname, svd); 1384 #else 1385 const struct afd *afd; 1386 struct addrinfo *cur; 1387 int error; 1388 char *cp, *hostname2 = NULL, *scope, *addr; 1389 struct sockaddr_in6 *sin6; 1390 1391 _DIAGASSERT(pai != NULL); 1392 /* hostname may be NULL */ 1393 /* servname may be NULL */ 1394 _DIAGASSERT(res != NULL); 1395 1396 /* 1397 * if the servname does not match socktype/protocol, ignore it. 1398 */ 1399 if (get_portmatch(pai, servname, svd) != 0) 1400 return 0; 1401 1402 afd = find_afd(pai->ai_family); 1403 if (afd == NULL) 1404 return 0; 1405 1406 if (!afd->a_scoped) 1407 return explore_numeric(pai, hostname, servname, res, hostname, 1408 svd); 1409 1410 cp = strchr(hostname, SCOPE_DELIMITER); 1411 if (cp == NULL) 1412 return explore_numeric(pai, hostname, servname, res, hostname, 1413 svd); 1414 1415 /* 1416 * Handle special case of <scoped_address><delimiter><scope id> 1417 */ 1418 hostname2 = strdup(hostname); 1419 if (hostname2 == NULL) 1420 return EAI_MEMORY; 1421 /* terminate at the delimiter */ 1422 hostname2[cp - hostname] = '\0'; 1423 addr = hostname2; 1424 scope = cp + 1; 1425 1426 error = explore_numeric(pai, addr, servname, res, hostname, svd); 1427 if (error == 0) { 1428 u_int32_t scopeid; 1429 1430 for (cur = *res; cur; cur = cur->ai_next) { 1431 if (cur->ai_family != AF_INET6) 1432 continue; 1433 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 1434 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { 1435 free(hostname2); 1436 return(EAI_NODATA); /* XXX: is return OK? */ 1437 } 1438 sin6->sin6_scope_id = scopeid; 1439 } 1440 } 1441 1442 free(hostname2); 1443 1444 return error; 1445 #endif 1446 } 1447 1448 static int 1449 get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) 1450 { 1451 1452 _DIAGASSERT(pai != NULL); 1453 _DIAGASSERT(ai != NULL); 1454 _DIAGASSERT(str != NULL); 1455 1456 if ((pai->ai_flags & AI_CANONNAME) != 0) { 1457 ai->ai_canonname = strdup(str); 1458 if (ai->ai_canonname == NULL) 1459 return EAI_MEMORY; 1460 } 1461 return 0; 1462 } 1463 1464 struct addrinfo * 1465 allocaddrinfo(socklen_t addrlen) 1466 { 1467 struct addrinfo *ai; 1468 1469 ai = calloc(sizeof(struct addrinfo) + addrlen, 1); 1470 if (ai) { 1471 ai->ai_addr = (void *)(ai+1); 1472 ai->ai_addrlen = ai->ai_addr->sa_len = addrlen; 1473 } 1474 1475 return ai; 1476 } 1477 1478 static struct addrinfo * 1479 get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 1480 { 1481 char *p; 1482 struct addrinfo *ai; 1483 struct sockaddr *save; 1484 1485 _DIAGASSERT(pai != NULL); 1486 _DIAGASSERT(afd != NULL); 1487 _DIAGASSERT(addr != NULL); 1488 1489 ai = allocaddrinfo((socklen_t)afd->a_socklen); 1490 if (ai == NULL) 1491 return NULL; 1492 1493 save = ai->ai_addr; 1494 memcpy(ai, pai, sizeof(struct addrinfo)); 1495 1496 /* since we just overwrote all of ai, we have 1497 to restore ai_addr and ai_addrlen */ 1498 ai->ai_addr = save; 1499 ai->ai_addrlen = (socklen_t)afd->a_socklen; 1500 1501 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 1502 p = (char *)(void *)(ai->ai_addr); 1503 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 1504 return ai; 1505 } 1506 1507 static int 1508 get_portmatch(const struct addrinfo *ai, const char *servname, 1509 struct servent_data *svd) 1510 { 1511 1512 _DIAGASSERT(ai != NULL); 1513 /* servname may be NULL */ 1514 1515 return get_port(ai, servname, 1, svd); 1516 } 1517 1518 static int 1519 get_port(const struct addrinfo *ai, const char *servname, int matchonly, 1520 struct servent_data *svd) 1521 { 1522 const char *proto; 1523 struct servent *sp; 1524 int port; 1525 int allownumeric; 1526 1527 _DIAGASSERT(ai != NULL); 1528 /* servname may be NULL */ 1529 1530 if (servname == NULL) 1531 return 0; 1532 switch (ai->ai_family) { 1533 case AF_INET: 1534 #ifdef AF_INET6 1535 case AF_INET6: 1536 #endif 1537 break; 1538 default: 1539 return 0; 1540 } 1541 1542 switch (ai->ai_socktype) { 1543 case SOCK_RAW: 1544 return EAI_SERVICE; 1545 case SOCK_DGRAM: 1546 case SOCK_STREAM: 1547 allownumeric = 1; 1548 break; 1549 case ANY: 1550 /* 1551 * This was 0. It is now 1 so that queries specifying 1552 * a NULL hint, or hint without socktype (but, hopefully, 1553 * with protocol) and numeric address actually work. 1554 */ 1555 allownumeric = 1; 1556 break; 1557 default: 1558 return EAI_SOCKTYPE; 1559 } 1560 1561 port = str2number(servname); 1562 if (port >= 0) { 1563 if (!allownumeric) 1564 return EAI_SERVICE; 1565 if (port < 0 || port > 65535) 1566 return EAI_SERVICE; 1567 port = htons(port); 1568 } else { 1569 struct servent sv; 1570 if (ai->ai_flags & AI_NUMERICSERV) 1571 return EAI_NONAME; 1572 1573 switch (ai->ai_socktype) { 1574 case SOCK_DGRAM: 1575 proto = "udp"; 1576 break; 1577 case SOCK_STREAM: 1578 proto = "tcp"; 1579 break; 1580 default: 1581 proto = NULL; 1582 break; 1583 } 1584 1585 sp = getservbyname_r(servname, proto, &sv, svd); 1586 if (sp == NULL) 1587 return EAI_SERVICE; 1588 port = sp->s_port; 1589 } 1590 1591 if (!matchonly) 1592 *getport(__UNCONST(ai)) = port; 1593 return 0; 1594 } 1595 1596 static const struct afd * 1597 find_afd(int af) 1598 { 1599 const struct afd *afd; 1600 1601 if (af == PF_UNSPEC) 1602 return NULL; 1603 for (afd = afdl; afd->a_af; afd++) { 1604 if (afd->a_af == af) 1605 return afd; 1606 } 1607 return NULL; 1608 } 1609 1610 /* 1611 * AI_ADDRCONFIG check: Build a mask containing a bit set for each address 1612 * family configured in the system. 1613 * 1614 */ 1615 static int 1616 addrconfig(uint64_t *mask) 1617 { 1618 struct ifaddrs *ifaddrs, *ifa; 1619 1620 if (getifaddrs(&ifaddrs) == -1) 1621 return -1; 1622 1623 *mask = 0; 1624 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) 1625 if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP)) { 1626 _DIAGASSERT(ifa->ifa_addr->sa_family < 64); 1627 *mask |= (uint64_t)1 << ifa->ifa_addr->sa_family; 1628 } 1629 1630 freeifaddrs(ifaddrs); 1631 return 0; 1632 } 1633 1634 #ifdef INET6 1635 /* convert a string to a scope identifier. XXX: IPv6 specific */ 1636 static int 1637 ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 1638 { 1639 u_long lscopeid; 1640 struct in6_addr *a6; 1641 char *ep; 1642 1643 _DIAGASSERT(scope != NULL); 1644 _DIAGASSERT(sin6 != NULL); 1645 _DIAGASSERT(scopeid != NULL); 1646 1647 a6 = &sin6->sin6_addr; 1648 1649 /* empty scopeid portion is invalid */ 1650 if (*scope == '\0') 1651 return -1; 1652 1653 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 1654 /* 1655 * We currently assume a one-to-one mapping between links 1656 * and interfaces, so we simply use interface indices for 1657 * like-local scopes. 1658 */ 1659 *scopeid = if_nametoindex(scope); 1660 if (*scopeid == 0) 1661 goto trynumeric; 1662 return 0; 1663 } 1664 1665 /* still unclear about literal, allow numeric only - placeholder */ 1666 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 1667 goto trynumeric; 1668 if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 1669 goto trynumeric; 1670 else 1671 goto trynumeric; /* global */ 1672 1673 /* try to convert to a numeric id as a last resort */ 1674 trynumeric: 1675 errno = 0; 1676 lscopeid = strtoul(scope, &ep, 10); 1677 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 1678 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 1679 return 0; 1680 else 1681 return -1; 1682 } 1683 #endif 1684 1685 /* code duplicate with gethnamaddr.c */ 1686 1687 static const char AskedForGot[] = 1688 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 1689 1690 #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \ 1691 (ok)(nm) != 0) 1692 static struct addrinfo * 1693 getanswer(res_state res, const querybuf *answer, int anslen, const char *qname, 1694 int qtype, const struct addrinfo *pai) 1695 { 1696 struct addrinfo sentinel, *cur; 1697 struct addrinfo ai, *aip; 1698 const struct afd *afd; 1699 char *canonname; 1700 const HEADER *hp; 1701 const u_char *cp; 1702 int n; 1703 const u_char *eom; 1704 char *bp, *ep; 1705 int type, class, ancount, qdcount; 1706 int haveanswer, had_error; 1707 char tbuf[MAXDNAME]; 1708 int (*name_ok) (const char *); 1709 char hostbuf[8*1024]; 1710 int port, pri, weight; 1711 struct srvinfo *srvlist, *srv, *csrv; 1712 1713 _DIAGASSERT(answer != NULL); 1714 _DIAGASSERT(qname != NULL); 1715 _DIAGASSERT(pai != NULL); 1716 _DIAGASSERT(res != NULL); 1717 1718 memset(&sentinel, 0, sizeof(sentinel)); 1719 cur = &sentinel; 1720 1721 canonname = NULL; 1722 eom = answer->buf + anslen; 1723 switch (qtype) { 1724 case T_A: 1725 case T_AAAA: 1726 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 1727 name_ok = res_hnok; 1728 break; 1729 case T_SRV: 1730 name_ok = gai_srvok; 1731 break; 1732 default: 1733 return NULL; /* XXX should be abort(); */ 1734 } 1735 /* 1736 * find first satisfactory answer 1737 */ 1738 hp = &answer->hdr; 1739 ancount = ntohs(hp->ancount); 1740 qdcount = ntohs(hp->qdcount); 1741 bp = hostbuf; 1742 ep = hostbuf + sizeof hostbuf; 1743 cp = answer->buf + HFIXEDSZ; 1744 if (qdcount != 1) { 1745 h_errno = NO_RECOVERY; 1746 return (NULL); 1747 } 1748 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1749 if ((n < 0) || !maybe_ok(res, bp, name_ok)) { 1750 h_errno = NO_RECOVERY; 1751 return (NULL); 1752 } 1753 cp += n + QFIXEDSZ; 1754 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 1755 /* res_send() has already verified that the query name is the 1756 * same as the one we sent; this just gets the expanded name 1757 * (i.e., with the succeeding search-domain tacked on). 1758 */ 1759 n = (int)strlen(bp) + 1; /* for the \0 */ 1760 if (n >= MAXHOSTNAMELEN) { 1761 h_errno = NO_RECOVERY; 1762 return (NULL); 1763 } 1764 canonname = bp; 1765 bp += n; 1766 /* The qname can be abbreviated, but h_name is now absolute. */ 1767 qname = canonname; 1768 } 1769 haveanswer = 0; 1770 had_error = 0; 1771 srvlist = NULL; 1772 while (ancount-- > 0 && cp < eom && !had_error) { 1773 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1774 if ((n < 0) || !maybe_ok(res, bp, name_ok)) { 1775 had_error++; 1776 continue; 1777 } 1778 cp += n; /* name */ 1779 type = _getshort(cp); 1780 cp += INT16SZ; /* type */ 1781 class = _getshort(cp); 1782 cp += INT16SZ + INT32SZ; /* class, TTL */ 1783 n = _getshort(cp); 1784 cp += INT16SZ; /* len */ 1785 if (class != C_IN) { 1786 /* XXX - debug? syslog? */ 1787 cp += n; 1788 continue; /* XXX - had_error++ ? */ 1789 } 1790 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 1791 type == T_CNAME) { 1792 n = dn_expand(answer->buf, eom, cp, tbuf, (int)sizeof tbuf); 1793 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) { 1794 had_error++; 1795 continue; 1796 } 1797 cp += n; 1798 /* Get canonical name. */ 1799 n = (int)strlen(tbuf) + 1; /* for the \0 */ 1800 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 1801 had_error++; 1802 continue; 1803 } 1804 strlcpy(bp, tbuf, (size_t)(ep - bp)); 1805 canonname = bp; 1806 bp += n; 1807 continue; 1808 } 1809 if (qtype == T_ANY) { 1810 if (!(type == T_A || type == T_AAAA)) { 1811 cp += n; 1812 continue; 1813 } 1814 } else if (type != qtype) { 1815 if (type != T_KEY && type != T_SIG) { 1816 struct syslog_data sd = SYSLOG_DATA_INIT; 1817 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1818 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 1819 qname, p_class(C_IN), p_type(qtype), 1820 p_type(type)); 1821 } 1822 cp += n; 1823 continue; /* XXX - had_error++ ? */ 1824 } 1825 switch (type) { 1826 case T_A: 1827 case T_AAAA: 1828 if (strcasecmp(canonname, bp) != 0) { 1829 struct syslog_data sd = SYSLOG_DATA_INIT; 1830 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1831 AskedForGot, canonname, bp); 1832 cp += n; 1833 continue; /* XXX - had_error++ ? */ 1834 } 1835 if (type == T_A && n != INADDRSZ) { 1836 cp += n; 1837 continue; 1838 } 1839 if (type == T_AAAA && n != IN6ADDRSZ) { 1840 cp += n; 1841 continue; 1842 } 1843 if (type == T_AAAA) { 1844 struct in6_addr in6; 1845 memcpy(&in6, cp, IN6ADDRSZ); 1846 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 1847 cp += n; 1848 continue; 1849 } 1850 } 1851 if (!haveanswer) { 1852 int nn; 1853 1854 canonname = bp; 1855 nn = (int)strlen(bp) + 1; /* for the \0 */ 1856 bp += nn; 1857 } 1858 1859 /* don't overwrite pai */ 1860 ai = *pai; 1861 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 1862 afd = find_afd(ai.ai_family); 1863 if (afd == NULL) { 1864 cp += n; 1865 continue; 1866 } 1867 cur->ai_next = get_ai(&ai, afd, (const char *)cp); 1868 if (cur->ai_next == NULL) 1869 had_error++; 1870 while (cur && cur->ai_next) 1871 cur = cur->ai_next; 1872 cp += n; 1873 break; 1874 case T_SRV: 1875 /* Add to SRV list. Insertion sort on priority. */ 1876 pri = _getshort(cp); 1877 cp += INT16SZ; 1878 weight = _getshort(cp); 1879 cp += INT16SZ; 1880 port = _getshort(cp); 1881 cp += INT16SZ; 1882 n = dn_expand(answer->buf, eom, cp, tbuf, 1883 (int)sizeof(tbuf)); 1884 if ((n < 0) || !maybe_ok(res, tbuf, res_hnok)) { 1885 had_error++; 1886 continue; 1887 } 1888 cp += n; 1889 if (strlen(tbuf) + 1 >= MAXDNAME) { 1890 had_error++; 1891 continue; 1892 } 1893 srv = malloc(sizeof(*srv)); 1894 if (!srv) { 1895 had_error++; 1896 continue; 1897 } 1898 strlcpy(srv->name, tbuf, sizeof(srv->name)); 1899 srv->pri = pri; 1900 srv->weight = weight; 1901 srv->port = port; 1902 /* Weight 0 is sorted before other weights. */ 1903 if (!srvlist 1904 || srv->pri < srvlist->pri 1905 || (srv->pri == srvlist->pri && 1906 (!srv->weight || srvlist->weight))) { 1907 srv->next = srvlist; 1908 srvlist = srv; 1909 } else { 1910 for (csrv = srvlist; 1911 csrv->next && csrv->next->pri <= srv->pri; 1912 csrv = csrv->next) { 1913 if (csrv->next->pri == srv->pri 1914 && (!srv->weight || 1915 csrv->next->weight)) 1916 break; 1917 } 1918 srv->next = csrv->next; 1919 csrv->next = srv; 1920 } 1921 continue; /* Don't add to haveanswer yet. */ 1922 default: 1923 abort(); 1924 } 1925 if (!had_error) 1926 haveanswer++; 1927 } 1928 1929 if (srvlist) { 1930 /* 1931 * Check for explicit rejection. 1932 */ 1933 if (!srvlist->next && !srvlist->name[0]) { 1934 free(srvlist); 1935 h_errno = HOST_NOT_FOUND; 1936 return NULL; 1937 } 1938 1939 while (srvlist) { 1940 struct res_target q, q2; 1941 1942 srv = srvlist; 1943 srvlist = srvlist->next; 1944 1945 /* 1946 * Since res_* doesn't give the additional 1947 * section, we always look up. 1948 */ 1949 memset(&q, 0, sizeof(q)); 1950 memset(&q2, 0, sizeof(q2)); 1951 1952 q.name = srv->name; 1953 q.qclass = C_IN; 1954 q.qtype = T_AAAA; 1955 q.next = &q2; 1956 q2.name = srv->name; 1957 q2.qclass = C_IN; 1958 q2.qtype = T_A; 1959 1960 aip = _dns_query(&q, pai, res, 0); 1961 1962 if (aip != NULL) { 1963 cur->ai_next = aip; 1964 while (cur && cur->ai_next) { 1965 cur = cur->ai_next; 1966 *getport(cur) = htons(srv->port); 1967 haveanswer++; 1968 } 1969 } 1970 free(srv); 1971 } 1972 } 1973 if (haveanswer) { 1974 if (!sentinel.ai_next->ai_canonname) 1975 (void)get_canonname(pai, sentinel.ai_next, 1976 canonname ? canonname : qname); 1977 h_errno = NETDB_SUCCESS; 1978 return sentinel.ai_next; 1979 } 1980 1981 /* We could have walked a CNAME chain, */ 1982 /* but the ultimate target may not have what we looked for */ 1983 h_errno = ntohs(hp->ancount) > 0? NO_DATA : NO_RECOVERY; 1984 return NULL; 1985 } 1986 1987 #define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr) 1988 #define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr) 1989 1990 static void 1991 aisort(struct addrinfo *s, res_state res) 1992 { 1993 struct addrinfo head, *t, *p; 1994 int i; 1995 1996 head.ai_next = NULL; 1997 t = &head; 1998 1999 for (i = 0; i < res->nsort; i++) { 2000 p = s; 2001 while (p->ai_next) { 2002 if ((p->ai_next->ai_family != AF_INET) 2003 || SORTMATCH(p, res->sort_list[i])) { 2004 t->ai_next = p->ai_next; 2005 t = t->ai_next; 2006 p->ai_next = p->ai_next->ai_next; 2007 } else { 2008 p = p->ai_next; 2009 } 2010 } 2011 } 2012 2013 /* add rest of list and reset s to the new list*/ 2014 t->ai_next = s->ai_next; 2015 s->ai_next = head.ai_next; 2016 } 2017 2018 static struct addrinfo * 2019 _dns_query(struct res_target *q, const struct addrinfo *pai, 2020 res_state res, int dosearch) 2021 { 2022 struct res_target *q2 = q->next; 2023 querybuf *buf, *buf2; 2024 struct addrinfo sentinel, *cur, *ai; 2025 2026 #ifdef DNS_DEBUG 2027 struct res_target *iter; 2028 for (iter = q; iter; iter = iter->next) 2029 printf("Query type %d for %s\n", iter->qtype, iter->name); 2030 #endif 2031 2032 buf = malloc(sizeof(*buf)); 2033 if (buf == NULL) { 2034 h_errno = NETDB_INTERNAL; 2035 return NULL; 2036 } 2037 buf2 = malloc(sizeof(*buf2)); 2038 if (buf2 == NULL) { 2039 free(buf); 2040 h_errno = NETDB_INTERNAL; 2041 return NULL; 2042 } 2043 2044 memset(&sentinel, 0, sizeof(sentinel)); 2045 cur = &sentinel; 2046 2047 q->answer = buf->buf; 2048 q->anslen = sizeof(buf->buf); 2049 if (q2) { 2050 q2->answer = buf2->buf; 2051 q2->anslen = sizeof(buf2->buf); 2052 } 2053 2054 if (dosearch) { 2055 if (res_searchN(q->name, q, res) < 0) 2056 goto out; 2057 } else { 2058 if (res_queryN(q->name, q, res) < 0) 2059 goto out; 2060 } 2061 2062 ai = getanswer(res, buf, q->n, q->name, q->qtype, pai); 2063 if (ai) { 2064 cur->ai_next = ai; 2065 while (cur && cur->ai_next) 2066 cur = cur->ai_next; 2067 } 2068 if (q2) { 2069 ai = getanswer(res, buf2, q2->n, q2->name, q2->qtype, pai); 2070 if (ai) 2071 cur->ai_next = ai; 2072 } 2073 free(buf); 2074 free(buf2); 2075 return sentinel.ai_next; 2076 out: 2077 free(buf); 2078 free(buf2); 2079 return NULL; 2080 } 2081 2082 /*ARGSUSED*/ 2083 static struct addrinfo * 2084 _dns_srv_lookup(const char *name, const char *servname, 2085 const struct addrinfo *pai) 2086 { 2087 static const char * const srvprotos[] = { "tcp", "udp" }; 2088 static const int srvnottype[] = { SOCK_DGRAM, SOCK_STREAM }; 2089 static const int nsrvprotos = 2; 2090 struct addrinfo sentinel, *cur, *ai; 2091 struct servent *serv, sv; 2092 struct servent_data svd; 2093 struct res_target q; 2094 res_state res; 2095 char *tname; 2096 int i; 2097 2098 res = __res_get_state(); 2099 if (res == NULL) 2100 return NULL; 2101 2102 memset(&svd, 0, sizeof(svd)); 2103 memset(&sentinel, 0, sizeof(sentinel)); 2104 cur = &sentinel; 2105 2106 /* 2107 * Iterate over supported SRV protocols. 2108 * (currently UDP and TCP only) 2109 */ 2110 for (i = 0; i < nsrvprotos; i++) { 2111 /* 2112 * Check that the caller didn't specify a hint 2113 * which precludes this protocol. 2114 */ 2115 if (pai->ai_socktype == srvnottype[i]) 2116 continue; 2117 /* 2118 * If the caller specified a port, 2119 * then lookup the database for the 2120 * official service name. 2121 */ 2122 serv = getservbyname_r(servname, srvprotos[i], &sv, &svd); 2123 if (serv == NULL) 2124 continue; 2125 2126 /* 2127 * Construct service DNS name. 2128 */ 2129 if (asprintf(&tname, "_%s._%s.%s", serv->s_name, serv->s_proto, 2130 name) < 0) 2131 continue; 2132 2133 memset(&q, 0, sizeof(q)); 2134 q.name = tname; 2135 q.qclass = C_IN; 2136 q.qtype = T_SRV; 2137 2138 /* 2139 * Do SRV query. 2140 */ 2141 ai = _dns_query(&q, pai, res, 1); 2142 if (ai) { 2143 cur->ai_next = ai; 2144 while (cur && cur->ai_next) 2145 cur = cur->ai_next; 2146 } 2147 free(tname); 2148 } 2149 2150 if (res->nsort) 2151 aisort(&sentinel, res); 2152 2153 __res_put_state(res); 2154 2155 return sentinel.ai_next; 2156 } 2157 2158 /*ARGSUSED*/ 2159 static struct addrinfo * 2160 _dns_host_lookup(const char *name, const struct addrinfo *pai) 2161 { 2162 struct res_target q, q2; 2163 struct addrinfo sentinel, *ai; 2164 res_state res; 2165 2166 res = __res_get_state(); 2167 if (res == NULL) 2168 return NULL; 2169 2170 memset(&q, 0, sizeof(q2)); 2171 memset(&q2, 0, sizeof(q2)); 2172 2173 switch (pai->ai_family) { 2174 case AF_UNSPEC: 2175 /* prefer IPv6 */ 2176 q.name = name; 2177 q.qclass = C_IN; 2178 q.qtype = T_AAAA; 2179 q.next = &q2; 2180 q2.name = name; 2181 q2.qclass = C_IN; 2182 q2.qtype = T_A; 2183 break; 2184 case AF_INET: 2185 q.name = name; 2186 q.qclass = C_IN; 2187 q.qtype = T_A; 2188 break; 2189 case AF_INET6: 2190 q.name = name; 2191 q.qclass = C_IN; 2192 q.qtype = T_AAAA; 2193 break; 2194 default: 2195 __res_put_state(res); 2196 h_errno = NETDB_INTERNAL; 2197 return NULL; 2198 } 2199 2200 ai = _dns_query(&q, pai, res, 1); 2201 2202 memset(&sentinel, 0, sizeof(sentinel)); 2203 sentinel.ai_next = ai; 2204 2205 if (ai != NULL && res->nsort) 2206 aisort(&sentinel, res); 2207 2208 __res_put_state(res); 2209 2210 return sentinel.ai_next; 2211 } 2212 2213 /*ARGSUSED*/ 2214 static int 2215 _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 2216 { 2217 struct addrinfo *ai = NULL; 2218 const char *name, *servname; 2219 const struct addrinfo *pai; 2220 2221 name = va_arg(ap, char *); 2222 pai = va_arg(ap, const struct addrinfo *); 2223 servname = va_arg(ap, char *); 2224 2225 /* 2226 * Try doing SRV lookup on service first. 2227 */ 2228 if (servname 2229 #ifdef AI_SRV 2230 && (pai->ai_flags & AI_SRV) 2231 #endif 2232 && !(pai->ai_flags & AI_NUMERICSERV) 2233 && str2number(servname) == -1) { 2234 2235 #ifdef DNS_DEBUG 2236 printf("%s: try SRV lookup\n", __func__); 2237 #endif 2238 ai = _dns_srv_lookup(name, servname, pai); 2239 } 2240 2241 /* 2242 * Do lookup on name. 2243 */ 2244 if (ai == NULL) { 2245 2246 #ifdef DNS_DEBUG 2247 printf("%s: try HOST lookup\n", __func__); 2248 #endif 2249 ai = _dns_host_lookup(name, pai); 2250 2251 if (ai == NULL) { 2252 switch (h_errno) { 2253 case HOST_NOT_FOUND: 2254 case NO_DATA: // XXX: Perhaps we could differentiate 2255 // So that we could return EAI_NODATA? 2256 return NS_NOTFOUND; 2257 case TRY_AGAIN: 2258 return NS_TRYAGAIN; 2259 default: 2260 return NS_UNAVAIL; 2261 } 2262 } 2263 } 2264 2265 *((struct addrinfo **)rv) = ai; 2266 return NS_SUCCESS; 2267 } 2268 2269 static void 2270 _sethtent(FILE **hostf) 2271 { 2272 2273 if (!*hostf) 2274 *hostf = fopen(_PATH_HOSTS, "re"); 2275 else 2276 rewind(*hostf); 2277 } 2278 2279 static void 2280 _endhtent(FILE **hostf) 2281 { 2282 2283 if (*hostf) { 2284 (void) fclose(*hostf); 2285 *hostf = NULL; 2286 } 2287 } 2288 2289 static struct addrinfo * 2290 _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 2291 { 2292 char *p; 2293 char *cp, *tname, *cname; 2294 struct addrinfo hints, *res0, *res; 2295 int error; 2296 const char *addr; 2297 char hostbuf[8*1024]; 2298 2299 _DIAGASSERT(name != NULL); 2300 _DIAGASSERT(pai != NULL); 2301 2302 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re"))) 2303 return (NULL); 2304 again: 2305 if (!(p = fgets(hostbuf, (int)sizeof hostbuf, *hostf))) 2306 return (NULL); 2307 if (*p == '#') 2308 goto again; 2309 if (!(cp = strpbrk(p, "#\n"))) 2310 goto again; 2311 *cp = '\0'; 2312 if (!(cp = strpbrk(p, " \t"))) 2313 goto again; 2314 *cp++ = '\0'; 2315 addr = p; 2316 /* if this is not something we're looking for, skip it. */ 2317 cname = NULL; 2318 while (cp && *cp) { 2319 if (*cp == ' ' || *cp == '\t') { 2320 cp++; 2321 continue; 2322 } 2323 if (!cname) 2324 cname = cp; 2325 tname = cp; 2326 if ((cp = strpbrk(cp, " \t")) != NULL) 2327 *cp++ = '\0'; 2328 if (strcasecmp(name, tname) == 0) 2329 goto found; 2330 } 2331 goto again; 2332 2333 found: 2334 hints = *pai; 2335 hints.ai_flags = AI_NUMERICHOST; 2336 error = getaddrinfo(addr, NULL, &hints, &res0); 2337 if (error) 2338 goto again; 2339 for (res = res0; res; res = res->ai_next) { 2340 /* cover it up */ 2341 res->ai_flags = pai->ai_flags; 2342 2343 if (pai->ai_flags & AI_CANONNAME) { 2344 if (get_canonname(pai, res, cname) != 0) { 2345 freeaddrinfo(res0); 2346 goto again; 2347 } 2348 } 2349 } 2350 return res0; 2351 } 2352 2353 /*ARGSUSED*/ 2354 static int 2355 _files_getaddrinfo(void *rv, void *cb_data, va_list ap) 2356 { 2357 const char *name; 2358 const struct addrinfo *pai; 2359 struct addrinfo sentinel, *cur; 2360 struct addrinfo *p; 2361 #ifndef _REENTRANT 2362 static 2363 #endif 2364 FILE *hostf = NULL; 2365 2366 name = va_arg(ap, char *); 2367 pai = va_arg(ap, const struct addrinfo *); 2368 2369 memset(&sentinel, 0, sizeof(sentinel)); 2370 cur = &sentinel; 2371 2372 _sethtent(&hostf); 2373 while ((p = _gethtent(&hostf, name, pai)) != NULL) { 2374 cur->ai_next = p; 2375 while (cur && cur->ai_next) 2376 cur = cur->ai_next; 2377 } 2378 _endhtent(&hostf); 2379 2380 *((struct addrinfo **)rv) = sentinel.ai_next; 2381 if (sentinel.ai_next == NULL) 2382 return NS_NOTFOUND; 2383 return NS_SUCCESS; 2384 } 2385 2386 #ifdef YP 2387 /*ARGSUSED*/ 2388 static struct addrinfo * 2389 _yphostent(char *line, const struct addrinfo *pai) 2390 { 2391 struct addrinfo sentinel, *cur; 2392 struct addrinfo hints, *res, *res0; 2393 int error; 2394 char *p; 2395 const char *addr, *canonname; 2396 char *nextline; 2397 char *cp; 2398 2399 _DIAGASSERT(line != NULL); 2400 _DIAGASSERT(pai != NULL); 2401 2402 p = line; 2403 addr = canonname = NULL; 2404 2405 memset(&sentinel, 0, sizeof(sentinel)); 2406 cur = &sentinel; 2407 2408 nextline: 2409 /* terminate line */ 2410 cp = strchr(p, '\n'); 2411 if (cp) { 2412 *cp++ = '\0'; 2413 nextline = cp; 2414 } else 2415 nextline = NULL; 2416 2417 cp = strpbrk(p, " \t"); 2418 if (cp == NULL) { 2419 if (canonname == NULL) 2420 return (NULL); 2421 else 2422 goto done; 2423 } 2424 *cp++ = '\0'; 2425 2426 addr = p; 2427 2428 while (cp && *cp) { 2429 if (*cp == ' ' || *cp == '\t') { 2430 cp++; 2431 continue; 2432 } 2433 if (!canonname) 2434 canonname = cp; 2435 if ((cp = strpbrk(cp, " \t")) != NULL) 2436 *cp++ = '\0'; 2437 } 2438 2439 hints = *pai; 2440 hints.ai_flags = AI_NUMERICHOST; 2441 error = getaddrinfo(addr, NULL, &hints, &res0); 2442 if (error == 0) { 2443 for (res = res0; res; res = res->ai_next) { 2444 /* cover it up */ 2445 res->ai_flags = pai->ai_flags; 2446 2447 if (pai->ai_flags & AI_CANONNAME) 2448 (void)get_canonname(pai, res, canonname); 2449 } 2450 } else 2451 res0 = NULL; 2452 if (res0) { 2453 cur->ai_next = res0; 2454 while (cur->ai_next) 2455 cur = cur->ai_next; 2456 } 2457 2458 if (nextline) { 2459 p = nextline; 2460 goto nextline; 2461 } 2462 2463 done: 2464 return sentinel.ai_next; 2465 } 2466 2467 /*ARGSUSED*/ 2468 static int 2469 _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) 2470 { 2471 struct addrinfo sentinel, *cur; 2472 struct addrinfo *ai = NULL; 2473 char *ypbuf; 2474 int ypbuflen, r; 2475 const char *name; 2476 const struct addrinfo *pai; 2477 char *ypdomain; 2478 2479 if (_yp_check(&ypdomain) == 0) 2480 return NS_UNAVAIL; 2481 2482 name = va_arg(ap, char *); 2483 pai = va_arg(ap, const struct addrinfo *); 2484 2485 memset(&sentinel, 0, sizeof(sentinel)); 2486 cur = &sentinel; 2487 2488 /* hosts.byname is only for IPv4 (Solaris8) */ 2489 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { 2490 r = yp_match(ypdomain, "hosts.byname", name, 2491 (int)strlen(name), &ypbuf, &ypbuflen); 2492 if (r == 0) { 2493 struct addrinfo ai4; 2494 2495 ai4 = *pai; 2496 ai4.ai_family = AF_INET; 2497 ai = _yphostent(ypbuf, &ai4); 2498 if (ai) { 2499 cur->ai_next = ai; 2500 while (cur && cur->ai_next) 2501 cur = cur->ai_next; 2502 } 2503 } 2504 free(ypbuf); 2505 } 2506 2507 /* ipnodes.byname can hold both IPv4/v6 */ 2508 r = yp_match(ypdomain, "ipnodes.byname", name, 2509 (int)strlen(name), &ypbuf, &ypbuflen); 2510 if (r == 0) { 2511 ai = _yphostent(ypbuf, pai); 2512 if (ai) 2513 cur->ai_next = ai; 2514 free(ypbuf); 2515 } 2516 2517 if (sentinel.ai_next == NULL) { 2518 h_errno = HOST_NOT_FOUND; 2519 return NS_NOTFOUND; 2520 } 2521 *((struct addrinfo **)rv) = sentinel.ai_next; 2522 return NS_SUCCESS; 2523 } 2524 #endif 2525 2526 /* resolver logic */ 2527 2528 /* 2529 * Formulate a normal query, send, and await answer. 2530 * Returned answer is placed in supplied buffer "answer". 2531 * Perform preliminary check of answer, returning success only 2532 * if no error is indicated and the answer count is nonzero. 2533 * Return the size of the response on success, -1 on error. 2534 * Error number is left in h_errno. 2535 * 2536 * Caller must parse answer and determine whether it answers the question. 2537 */ 2538 static int 2539 res_queryN(const char *name, /* domain name */ struct res_target *target, 2540 res_state res) 2541 { 2542 u_char buf[MAXPACKET]; 2543 HEADER *hp; 2544 int n; 2545 struct res_target *t; 2546 int rcode; 2547 int ancount; 2548 2549 _DIAGASSERT(name != NULL); 2550 /* XXX: target may be NULL??? */ 2551 2552 rcode = NOERROR; 2553 ancount = 0; 2554 2555 for (t = target; t; t = t->next) { 2556 int class, type; 2557 u_char *answer; 2558 int anslen; 2559 2560 hp = (HEADER *)(void *)t->answer; 2561 hp->rcode = NOERROR; /* default */ 2562 2563 /* make it easier... */ 2564 class = t->qclass; 2565 type = t->qtype; 2566 answer = t->answer; 2567 anslen = t->anslen; 2568 #ifdef DEBUG 2569 if (res->options & RES_DEBUG) 2570 printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 2571 #endif 2572 2573 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, 2574 buf, (int)sizeof(buf)); 2575 #ifdef RES_USE_EDNS0 2576 if (n > 0 && (res->options & RES_USE_EDNS0) != 0) 2577 n = res_nopt(res, n, buf, (int)sizeof(buf), anslen); 2578 #endif 2579 if (n <= 0) { 2580 #ifdef DEBUG 2581 if (res->options & RES_DEBUG) 2582 printf(";; res_nquery: mkquery failed\n"); 2583 #endif 2584 h_errno = NO_RECOVERY; 2585 return n; 2586 } 2587 n = res_nsend(res, buf, n, answer, anslen); 2588 #if 0 2589 if (n < 0) { 2590 #ifdef DEBUG 2591 if (res->options & RES_DEBUG) 2592 printf(";; res_query: send error\n"); 2593 #endif 2594 h_errno = TRY_AGAIN; 2595 return n; 2596 } 2597 #endif 2598 2599 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 2600 rcode = hp->rcode; /* record most recent error */ 2601 #ifdef DEBUG 2602 if (res->options & RES_DEBUG) 2603 printf(";; rcode = %u, ancount=%u\n", hp->rcode, 2604 ntohs(hp->ancount)); 2605 #endif 2606 continue; 2607 } 2608 2609 ancount += ntohs(hp->ancount); 2610 2611 t->n = n; 2612 } 2613 2614 if (ancount == 0) { 2615 switch (rcode) { 2616 case NXDOMAIN: 2617 h_errno = HOST_NOT_FOUND; 2618 break; 2619 case SERVFAIL: 2620 h_errno = TRY_AGAIN; 2621 break; 2622 case NOERROR: 2623 h_errno = NO_DATA; 2624 break; 2625 case FORMERR: 2626 case NOTIMP: 2627 case REFUSED: 2628 default: 2629 h_errno = NO_RECOVERY; 2630 break; 2631 } 2632 return -1; 2633 } 2634 return ancount; 2635 } 2636 2637 /* 2638 * Formulate a normal query, send, and retrieve answer in supplied buffer. 2639 * Return the size of the response on success, -1 on error. 2640 * If enabled, implement search rules until answer or unrecoverable failure 2641 * is detected. Error code, if any, is left in h_errno. 2642 */ 2643 static int 2644 res_searchN(const char *name, struct res_target *target, res_state res) 2645 { 2646 const char *cp, * const *domain; 2647 HEADER *hp; 2648 u_int dots; 2649 char buf[MAXHOSTNAMELEN]; 2650 int trailing_dot, ret, saved_herrno; 2651 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 2652 2653 _DIAGASSERT(name != NULL); 2654 _DIAGASSERT(target != NULL); 2655 2656 hp = (HEADER *)(void *)target->answer; /*XXX*/ 2657 2658 errno = 0; 2659 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 2660 dots = 0; 2661 for (cp = name; *cp; cp++) 2662 dots += (*cp == '.'); 2663 trailing_dot = 0; 2664 if (cp > name && *--cp == '.') 2665 trailing_dot++; 2666 2667 /* 2668 * if there aren't any dots, it could be a user-level alias 2669 */ 2670 if (!dots && (cp = res_hostalias(res, name, buf, sizeof(buf))) != NULL) { 2671 ret = res_queryN(cp, target, res); 2672 return ret; 2673 } 2674 2675 /* 2676 * If there are dots in the name already, let's just give it a try 2677 * 'as is'. The threshold can be set with the "ndots" option. 2678 */ 2679 saved_herrno = -1; 2680 if (dots >= res->ndots) { 2681 ret = res_querydomainN(name, NULL, target, res); 2682 if (ret > 0) 2683 return (ret); 2684 saved_herrno = h_errno; 2685 tried_as_is++; 2686 } 2687 2688 /* 2689 * We do at least one level of search if 2690 * - there is no dot and RES_DEFNAME is set, or 2691 * - there is at least one dot, there is no trailing dot, 2692 * and RES_DNSRCH is set. 2693 */ 2694 if ((!dots && (res->options & RES_DEFNAMES)) || 2695 (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 2696 int done = 0; 2697 2698 for (domain = (const char * const *)res->dnsrch; 2699 *domain && !done; 2700 domain++) { 2701 2702 ret = res_querydomainN(name, *domain, target, res); 2703 if (ret > 0) 2704 return ret; 2705 2706 /* 2707 * If no server present, give up. 2708 * If name isn't found in this domain, 2709 * keep trying higher domains in the search list 2710 * (if that's enabled). 2711 * On a NO_DATA error, keep trying, otherwise 2712 * a wildcard entry of another type could keep us 2713 * from finding this entry higher in the domain. 2714 * If we get some other error (negative answer or 2715 * server failure), then stop searching up, 2716 * but try the input name below in case it's 2717 * fully-qualified. 2718 */ 2719 if (errno == ECONNREFUSED) { 2720 h_errno = TRY_AGAIN; 2721 return -1; 2722 } 2723 2724 switch (h_errno) { 2725 case NO_DATA: 2726 got_nodata++; 2727 /* FALLTHROUGH */ 2728 case HOST_NOT_FOUND: 2729 /* keep trying */ 2730 break; 2731 case TRY_AGAIN: 2732 if (hp->rcode == SERVFAIL) { 2733 /* try next search element, if any */ 2734 got_servfail++; 2735 break; 2736 } 2737 /* FALLTHROUGH */ 2738 default: 2739 /* anything else implies that we're done */ 2740 done++; 2741 } 2742 /* 2743 * if we got here for some reason other than DNSRCH, 2744 * we only wanted one iteration of the loop, so stop. 2745 */ 2746 if (!(res->options & RES_DNSRCH)) 2747 done++; 2748 } 2749 } 2750 2751 /* 2752 * if we have not already tried the name "as is", do that now. 2753 * note that we do this regardless of how many dots were in the 2754 * name or whether it ends with a dot. 2755 */ 2756 if (!tried_as_is) { 2757 ret = res_querydomainN(name, NULL, target, res); 2758 if (ret > 0) 2759 return ret; 2760 } 2761 2762 /* 2763 * if we got here, we didn't satisfy the search. 2764 * if we did an initial full query, return that query's h_errno 2765 * (note that we wouldn't be here if that query had succeeded). 2766 * else if we ever got a nodata, send that back as the reason. 2767 * else send back meaningless h_errno, that being the one from 2768 * the last DNSRCH we did. 2769 */ 2770 if (saved_herrno != -1) 2771 h_errno = saved_herrno; 2772 else if (got_nodata) 2773 h_errno = NO_DATA; 2774 else if (got_servfail) 2775 h_errno = TRY_AGAIN; 2776 return -1; 2777 } 2778 2779 /* 2780 * Perform a call on res_query on the concatenation of name and domain, 2781 * removing a trailing dot from name if domain is NULL. 2782 */ 2783 static int 2784 res_querydomainN(const char *name, const char *domain, 2785 struct res_target *target, res_state res) 2786 { 2787 char nbuf[MAXDNAME]; 2788 const char *longname = nbuf; 2789 size_t n, d; 2790 2791 _DIAGASSERT(name != NULL); 2792 /* XXX: target may be NULL??? */ 2793 2794 #ifdef DEBUG 2795 if (res->options & RES_DEBUG) 2796 printf(";; res_querydomain(%s, %s)\n", 2797 name, domain?domain:"<Nil>"); 2798 #endif 2799 if (domain == NULL) { 2800 /* 2801 * Check for trailing '.'; 2802 * copy without '.' if present. 2803 */ 2804 n = strlen(name); 2805 if (n + 1 > sizeof(nbuf)) { 2806 h_errno = NO_RECOVERY; 2807 return -1; 2808 } 2809 if (n > 0 && name[--n] == '.') { 2810 strncpy(nbuf, name, n); 2811 nbuf[n] = '\0'; 2812 } else 2813 longname = name; 2814 } else { 2815 n = strlen(name); 2816 d = strlen(domain); 2817 if (n + 1 + d + 1 > sizeof(nbuf)) { 2818 h_errno = NO_RECOVERY; 2819 return -1; 2820 } 2821 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 2822 } 2823 return res_queryN(longname, target, res); 2824 } 2825 2826 #ifdef TEST 2827 int 2828 main(int argc, char *argv[]) { 2829 struct addrinfo *ai, *sai; 2830 int i, e; 2831 char buf[1024]; 2832 2833 for (i = 1; i < argc; i++) { 2834 if ((e = getaddrinfo(argv[i], NULL, NULL, &sai)) != 0) 2835 warnx("%s: %s", argv[i], gai_strerror(e)); 2836 for (ai = sai; ai; ai = ai->ai_next) { 2837 sockaddr_snprintf(buf, sizeof(buf), "%a", ai->ai_addr); 2838 printf("flags=0x%x family=%d socktype=%d protocol=%d " 2839 "addrlen=%zu addr=%s canonname=%s next=%p\n", 2840 ai->ai_flags, 2841 ai->ai_family, 2842 ai->ai_socktype, 2843 ai->ai_protocol, 2844 (size_t)ai->ai_addrlen, 2845 buf, 2846 ai->ai_canonname, 2847 ai->ai_next); 2848 } 2849 if (sai) 2850 freeaddrinfo(sai); 2851 } 2852 return 0; 2853 } 2854 #endif 2855