1 /* $NetBSD: getaddrinfo.c,v 1.119.2.1 2020/11/29 11:25:31 martin 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.119.2.1 2020/11/29 11:25:31 martin Exp $"); 59 #endif /* LIBC_SCCS and not lint */ 60 #include "namespace.h" 61 #include <sys/types.h> 62 #include <sys/param.h> 63 #include <sys/socket.h> 64 #include <net/if.h> 65 #include <netinet/in.h> 66 #include <arpa/inet.h> 67 #include <arpa/nameser.h> 68 #include <assert.h> 69 #include <ctype.h> 70 #include <errno.h> 71 #include <netdb.h> 72 #include <resolv.h> 73 #include <stddef.h> 74 #include <stdio.h> 75 #include <stdlib.h> 76 #include <string.h> 77 #include <unistd.h> 78 #include <ifaddrs.h> 79 80 #include <syslog.h> 81 #include <stdarg.h> 82 83 #ifdef YP 84 #include <rpc/rpc.h> 85 #include <rpcsvc/yp_prot.h> 86 #include <rpcsvc/ypclnt.h> 87 #endif 88 89 #include <FindDirectory.h> 90 91 #include <libutil.h> 92 #include "nsswitch.h" 93 #include "servent.h" 94 95 #ifndef RUMP_ACTION 96 #ifdef __weak_alias 97 __weak_alias(getaddrinfo,_getaddrinfo) 98 __weak_alias(allocaddrinfo,_allocaddrinfo) 99 __weak_alias(freeaddrinfo,_freeaddrinfo) 100 __weak_alias(gai_strerror,_gai_strerror) 101 #endif 102 #endif 103 104 #define SUCCESS 0 105 #define ANY 0 106 #define YES 1 107 #define NO 0 108 109 #define sa4addr(sa) ((void *)&((struct sockaddr_in *)(void *)sa)->sin_addr) 110 #define sa6addr(sa) ((void *)&((struct sockaddr_in6 *)(void *)sa)->sin6_addr) 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 #if defined(INET6) && !defined(__HAIKU__) 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 or servname not 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 #ifndef __HAIKU__ 647 while (cur && cur->ai_next) 648 cur = cur->ai_next; 649 #else 650 while (cur && cur->ai_next) { 651 if ((((uint64_t)1 << cur->ai_next->ai_family) & mask) == 0) { 652 /* entry does not match addrconfig mask, remove from list */ 653 struct addrinfo* removed = cur->ai_next; 654 cur->ai_next = removed->ai_next; 655 removed->ai_next = NULL; 656 freeaddrinfo(removed); 657 } else { 658 /* entry does match, keep it in list and move to next one */ 659 cur = cur->ai_next; 660 } 661 } 662 #endif 663 } 664 665 /* XXX */ 666 if (sentinel.ai_next) 667 error = 0; 668 669 if (error) 670 goto free; 671 672 if (sentinel.ai_next) { 673 good: 674 /* 675 * If the returned entry is for an active connection, 676 * and the given name is not numeric, reorder the 677 * list, so that the application would try the list 678 * in the most efficient order. Since the head entry 679 * of the original list may contain ai_canonname and 680 * that entry may be moved elsewhere in the new list, 681 * we keep the pointer and will restore it in the new 682 * head entry. (Note that RFC3493 requires the head 683 * entry store it when requested by the caller). 684 */ 685 if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) { 686 if (!numeric) { 687 char *canonname; 688 689 canonname = sentinel.ai_next->ai_canonname; 690 sentinel.ai_next->ai_canonname = NULL; 691 (void)reorder(&sentinel, &svd); 692 if (sentinel.ai_next->ai_canonname == NULL) { 693 sentinel.ai_next->ai_canonname 694 = canonname; 695 } else if (canonname != NULL) 696 free(canonname); 697 } 698 } 699 endservent_r(&svd); 700 *res = sentinel.ai_next; 701 return SUCCESS; 702 } else 703 error = EAI_FAIL; 704 free: 705 bad: 706 endservent_r(&svd); 707 if (sentinel.ai_next) 708 freeaddrinfo(sentinel.ai_next); 709 *res = NULL; 710 return error; 711 } 712 713 static int 714 reorder(struct addrinfo *sentinel, struct servent_data *svd) 715 { 716 struct addrinfo *ai, **aip; 717 struct ai_order *aio; 718 int i, n; 719 struct policyhead policyhead; 720 721 /* count the number of addrinfo elements for sorting. */ 722 for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++) 723 ; 724 725 /* 726 * If the number is small enough, we can skip the reordering process. 727 */ 728 if (n <= 1) 729 return n; 730 731 /* allocate a temporary array for sort and initialization of it. */ 732 if ((aio = malloc(sizeof(*aio) * n)) == NULL) 733 return n; /* give up reordering */ 734 memset(aio, 0, sizeof(*aio) * n); 735 736 /* retrieve address selection policy from the kernel */ 737 TAILQ_INIT(&policyhead); 738 if (!get_addrselectpolicy(&policyhead)) { 739 /* no policy is installed into kernel, we don't sort. */ 740 free(aio); 741 return n; 742 } 743 744 for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) { 745 aio[i].aio_ai = ai; 746 aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr); 747 aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr, 748 &policyhead); 749 set_source(&aio[i], &policyhead, svd); 750 } 751 752 /* perform sorting. */ 753 qsort(aio, n, sizeof(*aio), comp_dst); 754 755 /* reorder the addrinfo chain. */ 756 for (i = 0, aip = &sentinel->ai_next; i < n; i++) { 757 *aip = aio[i].aio_ai; 758 aip = &aio[i].aio_ai->ai_next; 759 } 760 *aip = NULL; 761 762 /* cleanup and return */ 763 free(aio); 764 free_addrselectpolicy(&policyhead); 765 return n; 766 } 767 768 static int 769 get_addrselectpolicy(struct policyhead *head) 770 { 771 #if defined(INET6) && !defined(__HAIKU__) 772 static const int mib[] = { 773 CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY }; 774 static const u_int miblen = (u_int)__arraycount(mib); 775 size_t l; 776 char *buf; 777 struct in6_addrpolicy *pol, *ep; 778 779 if (sysctl(mib, miblen, NULL, &l, NULL, 0) < 0) 780 return 0; 781 if (l == 0) 782 return 0; 783 if ((buf = malloc(l)) == NULL) 784 return 0; 785 if (sysctl(mib, miblen, buf, &l, NULL, 0) < 0) { 786 free(buf); 787 return 0; 788 } 789 790 ep = (void *)(buf + l); 791 for (pol = (void *)buf; pol + 1 <= ep; pol++) { 792 struct policyqueue *new; 793 794 if ((new = malloc(sizeof(*new))) == NULL) { 795 free_addrselectpolicy(head); /* make the list empty */ 796 break; 797 } 798 new->pc_policy = *pol; 799 TAILQ_INSERT_TAIL(head, new, pc_entry); 800 } 801 802 free(buf); 803 return 1; 804 #else 805 return 0; 806 #endif 807 } 808 809 static void 810 free_addrselectpolicy(struct policyhead *head) 811 { 812 struct policyqueue *ent, *nent; 813 814 for (ent = TAILQ_FIRST(head); ent; ent = nent) { 815 nent = TAILQ_NEXT(ent, pc_entry); 816 TAILQ_REMOVE(head, ent, pc_entry); 817 free(ent); 818 } 819 } 820 821 static struct policyqueue * 822 match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head) 823 { 824 #if defined(INET6) && !defined(__HAIKU__) 825 struct policyqueue *ent, *bestent = NULL; 826 struct in6_addrpolicy *pol; 827 int curmatchlen, bestmatchlen = -1; 828 u_char *mp, *ep, *k, *p; 829 u_int m; 830 struct sockaddr_in6 key; 831 832 switch(addr->sa_family) { 833 case AF_INET6: 834 memcpy(&key, addr, sizeof(key)); 835 break; 836 case AF_INET: 837 /* convert the address into IPv4-mapped IPv6 address. */ 838 memset(&key, 0, sizeof(key)); 839 key.sin6_family = AF_INET6; 840 key.sin6_len = sizeof(key); 841 key.sin6_addr.s6_addr[10] = 0xff; 842 key.sin6_addr.s6_addr[11] = 0xff; 843 memcpy(&key.sin6_addr.s6_addr[12], sa4addr(addr), 4); 844 break; 845 default: 846 return NULL; 847 } 848 849 for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) { 850 pol = &ent->pc_policy; 851 curmatchlen = 0; 852 853 mp = (void *)&pol->addrmask.sin6_addr; 854 ep = mp + 16; /* XXX: scope field? */ 855 k = (void *)&key.sin6_addr; 856 p = (void *)&pol->addr.sin6_addr; 857 for (; mp < ep && *mp; mp++, k++, p++) { 858 m = *mp; 859 if ((*k & m) != *p) 860 goto next; /* not match */ 861 if (m == 0xff) /* short cut for a typical case */ 862 curmatchlen += 8; 863 else { 864 while (m >= 0x80) { 865 curmatchlen++; 866 m <<= 1; 867 } 868 } 869 } 870 871 /* matched. check if this is better than the current best. */ 872 if (curmatchlen > bestmatchlen) { 873 bestent = ent; 874 bestmatchlen = curmatchlen; 875 } 876 877 next: 878 continue; 879 } 880 881 return bestent; 882 #else 883 return NULL; 884 #endif 885 886 } 887 888 static void 889 set_source(struct ai_order *aio, struct policyhead *ph, 890 struct servent_data *svd) 891 { 892 struct addrinfo ai = *aio->aio_ai; 893 struct sockaddr_storage ss; 894 socklen_t srclen; 895 int s; 896 897 /* set unspec ("no source is available"), just in case */ 898 aio->aio_srcsa.sa_family = AF_UNSPEC; 899 aio->aio_srcscope = -1; 900 901 switch(ai.ai_family) { 902 case AF_INET: 903 #ifdef INET6 904 case AF_INET6: 905 #endif 906 break; 907 default: /* ignore unsupported AFs explicitly */ 908 return; 909 } 910 911 /* XXX: make a dummy addrinfo to call connect() */ 912 ai.ai_socktype = SOCK_DGRAM; 913 ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */ 914 ai.ai_next = NULL; 915 memset(&ss, 0, sizeof(ss)); 916 memcpy(&ss, ai.ai_addr, ai.ai_addrlen); 917 ai.ai_addr = (void *)&ss; 918 get_port(&ai, "1", 0, svd); 919 920 #ifndef SOCK_CLOEXEC 921 #define SOCK_CLOEXEC 0 922 #endif 923 924 /* open a socket to get the source address for the given dst */ 925 if ((s = socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC, 926 ai.ai_protocol)) < 0) 927 return; /* give up */ 928 #if SOCK_CLOEXEC == 0 929 fcntl(s, F_SETFD, FD_CLOEXEC); 930 #endif 931 if (connect(s, ai.ai_addr, ai.ai_addrlen) < 0) 932 goto cleanup; 933 srclen = ai.ai_addrlen; 934 if (getsockname(s, &aio->aio_srcsa, &srclen) < 0) { 935 aio->aio_srcsa.sa_family = AF_UNSPEC; 936 goto cleanup; 937 } 938 aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa); 939 aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph); 940 aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr); 941 #if defined(INET6) && !defined(__HAIKU__) 942 if (ai.ai_family == AF_INET6) { 943 struct in6_ifreq ifr6; 944 u_int32_t flags6; 945 946 memset(&ifr6, 0, sizeof(ifr6)); 947 memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen); 948 if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) { 949 flags6 = ifr6.ifr_ifru.ifru_flags6; 950 if ((flags6 & IN6_IFF_DEPRECATED)) 951 aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED; 952 } 953 } 954 #endif 955 956 cleanup: 957 close(s); 958 return; 959 } 960 961 static int 962 matchlen(struct sockaddr *src, struct sockaddr *dst) 963 { 964 int match = 0; 965 u_char *s, *d; 966 u_char *lim; 967 u_int r, addrlen; 968 969 switch (src->sa_family) { 970 #ifdef INET6 971 case AF_INET6: 972 s = sa6addr(src); 973 d = sa6addr(dst); 974 addrlen = sizeof(struct in6_addr); 975 lim = s + addrlen; 976 break; 977 #endif 978 case AF_INET: 979 s = sa4addr(src); 980 d = sa4addr(dst); 981 addrlen = sizeof(struct in_addr); 982 lim = s + addrlen; 983 break; 984 default: 985 return 0; 986 } 987 988 while (s < lim) 989 if ((r = (*d++ ^ *s++)) != 0) { 990 while (r < addrlen * 8) { 991 match++; 992 r <<= 1; 993 } 994 break; 995 } else 996 match += 8; 997 return match; 998 } 999 1000 static int 1001 comp_dst(const void *arg1, const void *arg2) 1002 { 1003 const struct ai_order *dst1 = arg1, *dst2 = arg2; 1004 1005 /* 1006 * Rule 1: Avoid unusable destinations. 1007 * XXX: we currently do not consider if an appropriate route exists. 1008 */ 1009 if (dst1->aio_srcsa.sa_family != AF_UNSPEC && 1010 dst2->aio_srcsa.sa_family == AF_UNSPEC) { 1011 return -1; 1012 } 1013 if (dst1->aio_srcsa.sa_family == AF_UNSPEC && 1014 dst2->aio_srcsa.sa_family != AF_UNSPEC) { 1015 return 1; 1016 } 1017 1018 /* Rule 2: Prefer matching scope. */ 1019 if (dst1->aio_dstscope == dst1->aio_srcscope && 1020 dst2->aio_dstscope != dst2->aio_srcscope) { 1021 return -1; 1022 } 1023 if (dst1->aio_dstscope != dst1->aio_srcscope && 1024 dst2->aio_dstscope == dst2->aio_srcscope) { 1025 return 1; 1026 } 1027 1028 /* Rule 3: Avoid deprecated addresses. */ 1029 if (dst1->aio_srcsa.sa_family != AF_UNSPEC && 1030 dst2->aio_srcsa.sa_family != AF_UNSPEC) { 1031 if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && 1032 (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { 1033 return -1; 1034 } 1035 if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && 1036 !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { 1037 return 1; 1038 } 1039 } 1040 1041 /* Rule 4: Prefer home addresses. */ 1042 /* XXX: not implemented yet */ 1043 1044 /* Rule 5: Prefer matching label. */ 1045 #if defined(INET6) && !defined(__HAIKU__) 1046 if (dst1->aio_srcpolicy && dst1->aio_dstpolicy && 1047 dst1->aio_srcpolicy->pc_policy.label == 1048 dst1->aio_dstpolicy->pc_policy.label && 1049 (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL || 1050 dst2->aio_srcpolicy->pc_policy.label != 1051 dst2->aio_dstpolicy->pc_policy.label)) { 1052 return -1; 1053 } 1054 if (dst2->aio_srcpolicy && dst2->aio_dstpolicy && 1055 dst2->aio_srcpolicy->pc_policy.label == 1056 dst2->aio_dstpolicy->pc_policy.label && 1057 (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL || 1058 dst1->aio_srcpolicy->pc_policy.label != 1059 dst1->aio_dstpolicy->pc_policy.label)) { 1060 return 1; 1061 } 1062 #endif 1063 1064 /* Rule 6: Prefer higher precedence. */ 1065 #if defined(INET6) && !defined(__HAIKU__) 1066 if (dst1->aio_dstpolicy && 1067 (dst2->aio_dstpolicy == NULL || 1068 dst1->aio_dstpolicy->pc_policy.preced > 1069 dst2->aio_dstpolicy->pc_policy.preced)) { 1070 return -1; 1071 } 1072 if (dst2->aio_dstpolicy && 1073 (dst1->aio_dstpolicy == NULL || 1074 dst2->aio_dstpolicy->pc_policy.preced > 1075 dst1->aio_dstpolicy->pc_policy.preced)) { 1076 return 1; 1077 } 1078 #endif 1079 1080 /* Rule 7: Prefer native transport. */ 1081 /* XXX: not implemented yet */ 1082 1083 /* Rule 8: Prefer smaller scope. */ 1084 if (dst1->aio_dstscope >= 0 && 1085 dst1->aio_dstscope < dst2->aio_dstscope) { 1086 return -1; 1087 } 1088 if (dst2->aio_dstscope >= 0 && 1089 dst2->aio_dstscope < dst1->aio_dstscope) { 1090 return 1; 1091 } 1092 1093 /* 1094 * Rule 9: Use longest matching prefix. 1095 * We compare the match length in a same AF only. 1096 */ 1097 if (dst1->aio_ai->ai_addr->sa_family == 1098 dst2->aio_ai->ai_addr->sa_family && 1099 dst1->aio_ai->ai_addr->sa_family != AF_INET) { 1100 if (dst1->aio_matchlen > dst2->aio_matchlen) { 1101 return -1; 1102 } 1103 if (dst1->aio_matchlen < dst2->aio_matchlen) { 1104 return 1; 1105 } 1106 } 1107 1108 /* Rule 10: Otherwise, leave the order unchanged. */ 1109 return -1; 1110 } 1111 1112 /* 1113 * Copy from scope.c. 1114 * XXX: we should standardize the functions and link them as standard 1115 * library. 1116 */ 1117 static int 1118 gai_addr2scopetype(struct sockaddr *sa) 1119 { 1120 #ifdef INET6 1121 struct sockaddr_in6 *sa6; 1122 #endif 1123 struct sockaddr_in *sa4; 1124 u_char *p; 1125 1126 switch(sa->sa_family) { 1127 #ifdef INET6 1128 case AF_INET6: 1129 sa6 = (void *)sa; 1130 if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) { 1131 /* just use the scope field of the multicast address */ 1132 return sa6->sin6_addr.s6_addr[2] & 0x0f; 1133 } 1134 /* 1135 * Unicast addresses: map scope type to corresponding scope 1136 * value defined for multcast addresses. 1137 * XXX: hardcoded scope type values are bad... 1138 */ 1139 if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) 1140 return 1; /* node local scope */ 1141 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) 1142 return 2; /* link-local scope */ 1143 if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr)) 1144 return 5; /* site-local scope */ 1145 return 14; /* global scope */ 1146 #endif 1147 case AF_INET: 1148 /* 1149 * IPv4 pseudo scoping according to RFC 3484. 1150 */ 1151 sa4 = (void *)sa; 1152 p = (u_char *)(void *)&sa4->sin_addr; 1153 /* IPv4 autoconfiguration addresses have link-local scope. */ 1154 if (p[0] == 169 && p[1] == 254) 1155 return 2; 1156 /* Private addresses have site-local scope. */ 1157 if (p[0] == 10 || 1158 (p[0] == 172 && (p[1] & 0xf0) == 16) || 1159 (p[0] == 192 && p[1] == 168)) 1160 return 14; /* XXX: It should be 5 unless NAT */ 1161 /* Loopback addresses have link-local scope. */ 1162 if (p[0] == 127) 1163 return 2; 1164 return 14; 1165 default: 1166 errno = EAFNOSUPPORT; /* is this a good error? */ 1167 return -1; 1168 } 1169 } 1170 1171 /* 1172 * FQDN hostname, DNS lookup 1173 */ 1174 static int 1175 explore_fqdn(const struct addrinfo *pai, const char *hostname, 1176 const char *servname, struct addrinfo **res, struct servent_data *svd) 1177 { 1178 struct addrinfo *result; 1179 struct addrinfo *cur; 1180 int error = 0; 1181 static const ns_dtab dtab[] = { 1182 NS_FILES_CB(_files_getaddrinfo, NULL) 1183 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ 1184 NS_NIS_CB(_yp_getaddrinfo, NULL) 1185 NS_NULL_CB 1186 }; 1187 1188 _DIAGASSERT(pai != NULL); 1189 /* hostname may be NULL */ 1190 /* servname may be NULL */ 1191 _DIAGASSERT(res != NULL); 1192 1193 result = NULL; 1194 1195 /* 1196 * if the servname does not match socktype/protocol, ignore it. 1197 */ 1198 if (get_portmatch(pai, servname, svd) != 0) 1199 return 0; 1200 1201 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", 1202 default_dns_files, hostname, pai, servname)) { 1203 case NS_TRYAGAIN: 1204 error = EAI_AGAIN; 1205 goto free; 1206 case NS_UNAVAIL: 1207 error = EAI_FAIL; 1208 goto free; 1209 case NS_NOTFOUND: 1210 error = EAI_NODATA; 1211 goto free; 1212 case NS_SUCCESS: 1213 error = 0; 1214 for (cur = result; cur; cur = cur->ai_next) { 1215 /* Check for already filled port. */ 1216 if (*getport(cur)) 1217 continue; 1218 GET_PORT(cur, servname, svd); 1219 /* canonname should be filled already */ 1220 } 1221 break; 1222 } 1223 1224 *res = result; 1225 1226 return 0; 1227 1228 free: 1229 if (result) 1230 freeaddrinfo(result); 1231 return error; 1232 } 1233 1234 /* 1235 * hostname == NULL. 1236 * passive socket -> anyaddr (0.0.0.0 or ::) 1237 * non-passive socket -> localhost (127.0.0.1 or ::1) 1238 */ 1239 static int 1240 explore_null(const struct addrinfo *pai, const char *servname, 1241 struct addrinfo **res, struct servent_data *svd) 1242 { 1243 int s; 1244 const struct afd *afd; 1245 struct addrinfo *cur; 1246 struct addrinfo sentinel; 1247 int error; 1248 1249 _DIAGASSERT(pai != NULL); 1250 /* servname may be NULL */ 1251 _DIAGASSERT(res != NULL); 1252 1253 *res = NULL; 1254 sentinel.ai_next = NULL; 1255 cur = &sentinel; 1256 1257 /* 1258 * filter out AFs that are not supported by the kernel 1259 * XXX errno? 1260 */ 1261 s = socket(pai->ai_family, SOCK_DGRAM, 0); 1262 if (s < 0) { 1263 if (errno != EMFILE) 1264 return 0; 1265 } else 1266 close(s); 1267 1268 /* 1269 * if the servname does not match socktype/protocol, ignore it. 1270 */ 1271 if (get_portmatch(pai, servname, svd) != 0) 1272 return 0; 1273 1274 afd = find_afd(pai->ai_family); 1275 if (afd == NULL) 1276 return 0; 1277 1278 if (pai->ai_flags & AI_PASSIVE) { 1279 GET_AI(cur->ai_next, afd, afd->a_addrany); 1280 /* xxx meaningless? 1281 * GET_CANONNAME(cur->ai_next, "anyaddr"); 1282 */ 1283 GET_PORT(cur->ai_next, servname, svd); 1284 } else { 1285 GET_AI(cur->ai_next, afd, afd->a_loopback); 1286 /* xxx meaningless? 1287 * GET_CANONNAME(cur->ai_next, "localhost"); 1288 */ 1289 GET_PORT(cur->ai_next, servname, svd); 1290 } 1291 cur = cur->ai_next; 1292 1293 *res = sentinel.ai_next; 1294 return 0; 1295 1296 free: 1297 if (sentinel.ai_next) 1298 freeaddrinfo(sentinel.ai_next); 1299 return error; 1300 } 1301 1302 /* 1303 * numeric hostname 1304 */ 1305 static int 1306 explore_numeric(const struct addrinfo *pai, const char *hostname, 1307 const char *servname, struct addrinfo **res, const char *canonname, 1308 struct servent_data *svd) 1309 { 1310 const struct afd *afd; 1311 struct addrinfo *cur; 1312 struct addrinfo sentinel; 1313 int error; 1314 char pton[PTON_MAX]; 1315 1316 _DIAGASSERT(pai != NULL); 1317 /* hostname may be NULL */ 1318 /* servname may be NULL */ 1319 _DIAGASSERT(res != NULL); 1320 1321 *res = NULL; 1322 sentinel.ai_next = NULL; 1323 cur = &sentinel; 1324 1325 /* 1326 * if the servname does not match socktype/protocol, ignore it. 1327 */ 1328 if (get_portmatch(pai, servname, svd) != 0) 1329 return 0; 1330 1331 afd = find_afd(pai->ai_family); 1332 if (afd == NULL) 1333 return 0; 1334 1335 switch (afd->a_af) { 1336 case AF_INET: 1337 /* 1338 * RFC3493 section 6.1, requires getaddrinfo() to accept 1339 * AF_INET formats that are accepted by inet_addr(); here 1340 * we use the equivalent inet_aton() function so we can 1341 * check for errors. inet_pton() only accepts addresses 1342 * in the dotted quad format and only in base 10, so we 1343 * need to treat AF_INET specially. 1344 * 1345 * We also check for trailing characters and fail if there 1346 * are any. This matches the inet_pton6(), but not the 1347 * inet_pton4() behavior. We choose to make the protocol 1348 * behavior consistent. 1349 */ 1350 if (inet_aton(hostname, (void *)pton) == 1 && 1351 hostname[strspn(hostname, "0123456789.xabcdefXABCDEF")] 1352 == '\0') { 1353 if (pai->ai_family == afd->a_af || 1354 pai->ai_family == PF_UNSPEC /*?*/) { 1355 GET_AI(cur->ai_next, afd, pton); 1356 GET_PORT(cur->ai_next, servname, svd); 1357 if ((pai->ai_flags & AI_CANONNAME)) { 1358 /* 1359 * Set the numeric address itself as 1360 * the canonical name, based on a 1361 * clarification in rfc2553bis-03. 1362 */ 1363 GET_CANONNAME(cur->ai_next, canonname); 1364 } 1365 while (cur && cur->ai_next) 1366 cur = cur->ai_next; 1367 } else 1368 ERR(EAI_FAMILY); /*xxx*/ 1369 } 1370 break; 1371 default: 1372 if (inet_pton(afd->a_af, hostname, pton) == 1) { 1373 if (pai->ai_family == afd->a_af || 1374 pai->ai_family == PF_UNSPEC /*?*/) { 1375 GET_AI(cur->ai_next, afd, pton); 1376 GET_PORT(cur->ai_next, servname, svd); 1377 if ((pai->ai_flags & AI_CANONNAME)) { 1378 /* 1379 * Set the numeric address itself as 1380 * the canonical name, based on a 1381 * clarification in rfc2553bis-03. 1382 */ 1383 GET_CANONNAME(cur->ai_next, canonname); 1384 } 1385 while (cur->ai_next) 1386 cur = cur->ai_next; 1387 } else 1388 ERR(EAI_FAMILY); /*xxx*/ 1389 } 1390 break; 1391 } 1392 1393 *res = sentinel.ai_next; 1394 return 0; 1395 1396 free: 1397 bad: 1398 if (sentinel.ai_next) 1399 freeaddrinfo(sentinel.ai_next); 1400 return error; 1401 } 1402 1403 /* 1404 * numeric hostname with scope 1405 */ 1406 static int 1407 explore_numeric_scope(const struct addrinfo *pai, const char *hostname, 1408 const char *servname, struct addrinfo **res, struct servent_data *svd) 1409 { 1410 #if !defined(SCOPE_DELIMITER) || !defined(INET6) 1411 return explore_numeric(pai, hostname, servname, res, hostname, svd); 1412 #else 1413 const struct afd *afd; 1414 struct addrinfo *cur; 1415 int error; 1416 char *cp, *hostname2 = NULL, *scope, *addr; 1417 struct sockaddr_in6 *sin6; 1418 1419 _DIAGASSERT(pai != NULL); 1420 /* hostname may be NULL */ 1421 /* servname may be NULL */ 1422 _DIAGASSERT(res != NULL); 1423 1424 /* 1425 * if the servname does not match socktype/protocol, ignore it. 1426 */ 1427 if (get_portmatch(pai, servname, svd) != 0) 1428 return 0; 1429 1430 afd = find_afd(pai->ai_family); 1431 if (afd == NULL) 1432 return 0; 1433 1434 if (!afd->a_scoped) 1435 return explore_numeric(pai, hostname, servname, res, hostname, 1436 svd); 1437 1438 cp = strchr(hostname, SCOPE_DELIMITER); 1439 if (cp == NULL) 1440 return explore_numeric(pai, hostname, servname, res, hostname, 1441 svd); 1442 1443 /* 1444 * Handle special case of <scoped_address><delimiter><scope id> 1445 */ 1446 hostname2 = strdup(hostname); 1447 if (hostname2 == NULL) 1448 return EAI_MEMORY; 1449 /* terminate at the delimiter */ 1450 hostname2[cp - hostname] = '\0'; 1451 addr = hostname2; 1452 scope = cp + 1; 1453 1454 error = explore_numeric(pai, addr, servname, res, hostname, svd); 1455 if (error == 0) { 1456 u_int32_t scopeid; 1457 1458 for (cur = *res; cur; cur = cur->ai_next) { 1459 if (cur->ai_family != AF_INET6) 1460 continue; 1461 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 1462 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { 1463 free(hostname2); 1464 return EAI_NODATA; /* XXX: is return OK? */ 1465 } 1466 sin6->sin6_scope_id = scopeid; 1467 } 1468 } 1469 1470 free(hostname2); 1471 1472 return error; 1473 #endif 1474 } 1475 1476 static int 1477 get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) 1478 { 1479 1480 _DIAGASSERT(pai != NULL); 1481 _DIAGASSERT(ai != NULL); 1482 _DIAGASSERT(str != NULL); 1483 1484 if ((pai->ai_flags & AI_CANONNAME) != 0) { 1485 ai->ai_canonname = strdup(str); 1486 if (ai->ai_canonname == NULL) 1487 return EAI_MEMORY; 1488 } 1489 return 0; 1490 } 1491 1492 struct addrinfo * 1493 allocaddrinfo(socklen_t addrlen) 1494 { 1495 struct addrinfo *ai; 1496 1497 ai = calloc(sizeof(struct addrinfo) + addrlen, 1); 1498 if (ai) { 1499 ai->ai_addr = (void *)(ai+1); 1500 ai->ai_addrlen = ai->ai_addr->sa_len = addrlen; 1501 } 1502 1503 return ai; 1504 } 1505 1506 static struct addrinfo * 1507 get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 1508 { 1509 char *p; 1510 struct addrinfo *ai; 1511 struct sockaddr *save; 1512 1513 _DIAGASSERT(pai != NULL); 1514 _DIAGASSERT(afd != NULL); 1515 _DIAGASSERT(addr != NULL); 1516 1517 ai = allocaddrinfo((socklen_t)afd->a_socklen); 1518 if (ai == NULL) 1519 return NULL; 1520 1521 save = ai->ai_addr; 1522 memcpy(ai, pai, sizeof(struct addrinfo)); 1523 1524 /* since we just overwrote all of ai, we have 1525 to restore ai_addr and ai_addrlen */ 1526 ai->ai_addr = save; 1527 ai->ai_addrlen = (socklen_t)afd->a_socklen; 1528 1529 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 1530 p = (char *)(void *)(ai->ai_addr); 1531 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 1532 return ai; 1533 } 1534 1535 static int 1536 get_portmatch(const struct addrinfo *ai, const char *servname, 1537 struct servent_data *svd) 1538 { 1539 1540 _DIAGASSERT(ai != NULL); 1541 /* servname may be NULL */ 1542 1543 return get_port(ai, servname, 1, svd); 1544 } 1545 1546 static int 1547 get_port(const struct addrinfo *ai, const char *servname, int matchonly, 1548 struct servent_data *svd) 1549 { 1550 const char *proto; 1551 struct servent *sp; 1552 int port; 1553 int allownumeric; 1554 1555 _DIAGASSERT(ai != NULL); 1556 /* servname may be NULL */ 1557 1558 if (servname == NULL) 1559 return 0; 1560 switch (ai->ai_family) { 1561 case AF_INET: 1562 #ifdef AF_INET6 1563 case AF_INET6: 1564 #endif 1565 break; 1566 default: 1567 return 0; 1568 } 1569 1570 switch (ai->ai_socktype) { 1571 case SOCK_RAW: 1572 return EAI_SERVICE; 1573 case SOCK_DGRAM: 1574 case SOCK_STREAM: 1575 allownumeric = 1; 1576 break; 1577 case ANY: 1578 /* 1579 * This was 0. It is now 1 so that queries specifying 1580 * a NULL hint, or hint without socktype (but, hopefully, 1581 * with protocol) and numeric address actually work. 1582 */ 1583 allownumeric = 1; 1584 break; 1585 default: 1586 return EAI_SOCKTYPE; 1587 } 1588 1589 port = str2number(servname); 1590 if (port >= 0) { 1591 if (!allownumeric) 1592 return EAI_SERVICE; 1593 if (port < 0 || port > 65535) 1594 return EAI_SERVICE; 1595 port = htons(port); 1596 } else { 1597 struct servent sv; 1598 if (ai->ai_flags & AI_NUMERICSERV) 1599 return EAI_NONAME; 1600 1601 switch (ai->ai_socktype) { 1602 case SOCK_DGRAM: 1603 proto = "udp"; 1604 break; 1605 case SOCK_STREAM: 1606 proto = "tcp"; 1607 break; 1608 default: 1609 proto = NULL; 1610 break; 1611 } 1612 1613 sp = getservbyname_r(servname, proto, &sv, svd); 1614 if (sp == NULL) 1615 return EAI_SERVICE; 1616 port = sp->s_port; 1617 } 1618 1619 if (!matchonly) 1620 *getport(__DECONST(struct addrinfo*, ai)) = port; 1621 return 0; 1622 } 1623 1624 static const struct afd * 1625 find_afd(int af) 1626 { 1627 const struct afd *afd; 1628 1629 if (af == PF_UNSPEC) 1630 return NULL; 1631 for (afd = afdl; afd->a_af; afd++) { 1632 if (afd->a_af == af) 1633 return afd; 1634 } 1635 return NULL; 1636 } 1637 1638 /* 1639 * AI_ADDRCONFIG check: Build a mask containing a bit set for each address 1640 * family configured in the system. 1641 * 1642 */ 1643 static int 1644 addrconfig(uint64_t *mask) 1645 { 1646 struct ifaddrs *ifaddrs, *ifa; 1647 1648 if (getifaddrs(&ifaddrs) == -1) 1649 return -1; 1650 1651 *mask = 0; 1652 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) 1653 #ifndef __HAIKU__ 1654 if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP)) { 1655 #else 1656 if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP) 1657 && !(ifa->ifa_flags & IFF_LOOPBACK)) { 1658 assert(ifa->ifa_addr->sa_family < 64); 1659 #endif 1660 *mask |= (uint64_t)1 << ifa->ifa_addr->sa_family; 1661 } 1662 1663 freeifaddrs(ifaddrs); 1664 return 0; 1665 } 1666 1667 #ifdef INET6 1668 /* convert a string to a scope identifier. XXX: IPv6 specific */ 1669 static int 1670 ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 1671 { 1672 u_long lscopeid; 1673 struct in6_addr *a6; 1674 char *ep; 1675 1676 _DIAGASSERT(scope != NULL); 1677 _DIAGASSERT(sin6 != NULL); 1678 _DIAGASSERT(scopeid != NULL); 1679 1680 a6 = &sin6->sin6_addr; 1681 1682 /* empty scopeid portion is invalid */ 1683 if (*scope == '\0') 1684 return -1; 1685 1686 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 1687 /* 1688 * We currently assume a one-to-one mapping between links 1689 * and interfaces, so we simply use interface indices for 1690 * like-local scopes. 1691 */ 1692 *scopeid = if_nametoindex(scope); 1693 if (*scopeid == 0) 1694 goto trynumeric; 1695 return 0; 1696 } 1697 1698 /* still unclear about literal, allow numeric only - placeholder */ 1699 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 1700 goto trynumeric; 1701 if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 1702 goto trynumeric; 1703 else 1704 goto trynumeric; /* global */ 1705 1706 /* try to convert to a numeric id as a last resort */ 1707 trynumeric: 1708 errno = 0; 1709 lscopeid = strtoul(scope, &ep, 10); 1710 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 1711 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 1712 return 0; 1713 else 1714 return -1; 1715 } 1716 #endif 1717 1718 /* code duplicate with gethnamaddr.c */ 1719 1720 static const char AskedForGot[] = 1721 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 1722 1723 #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \ 1724 (ok)(nm) != 0) 1725 static struct addrinfo * 1726 getanswer(res_state res, const querybuf *answer, int anslen, const char *qname, 1727 int qtype, const struct addrinfo *pai) 1728 { 1729 struct addrinfo sentinel, *cur; 1730 struct addrinfo ai, *aip; 1731 const struct afd *afd; 1732 char *canonname; 1733 const HEADER *hp; 1734 const u_char *cp; 1735 int n; 1736 const u_char *eom; 1737 char *bp, *ep; 1738 int type, class, ancount, qdcount; 1739 int haveanswer, had_error; 1740 char tbuf[MAXDNAME]; 1741 int (*name_ok) (const char *); 1742 char hostbuf[8*1024]; 1743 int port, pri, weight; 1744 struct srvinfo *srvlist, *srv, *csrv; 1745 1746 _DIAGASSERT(answer != NULL); 1747 _DIAGASSERT(qname != NULL); 1748 _DIAGASSERT(pai != NULL); 1749 _DIAGASSERT(res != NULL); 1750 1751 memset(&sentinel, 0, sizeof(sentinel)); 1752 cur = &sentinel; 1753 1754 canonname = NULL; 1755 eom = answer->buf + anslen; 1756 switch (qtype) { 1757 case T_A: 1758 case T_AAAA: 1759 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 1760 name_ok = res_hnok; 1761 break; 1762 case T_SRV: 1763 name_ok = gai_srvok; 1764 break; 1765 default: 1766 return NULL; /* XXX should be abort(); */ 1767 } 1768 /* 1769 * find first satisfactory answer 1770 */ 1771 hp = &answer->hdr; 1772 ancount = ntohs(hp->ancount); 1773 qdcount = ntohs(hp->qdcount); 1774 bp = hostbuf; 1775 ep = hostbuf + sizeof hostbuf; 1776 cp = answer->buf + HFIXEDSZ; 1777 if (qdcount != 1) { 1778 h_errno = NO_RECOVERY; 1779 return NULL; 1780 } 1781 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1782 if ((n < 0) || !maybe_ok(res, bp, name_ok)) { 1783 h_errno = NO_RECOVERY; 1784 return NULL; 1785 } 1786 cp += n + QFIXEDSZ; 1787 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 1788 /* res_send() has already verified that the query name is the 1789 * same as the one we sent; this just gets the expanded name 1790 * (i.e., with the succeeding search-domain tacked on). 1791 */ 1792 n = (int)strlen(bp) + 1; /* for the \0 */ 1793 if (n >= MAXHOSTNAMELEN) { 1794 h_errno = NO_RECOVERY; 1795 return NULL; 1796 } 1797 canonname = bp; 1798 bp += n; 1799 /* The qname can be abbreviated, but h_name is now absolute. */ 1800 qname = canonname; 1801 } 1802 haveanswer = 0; 1803 had_error = 0; 1804 srvlist = NULL; 1805 while (ancount-- > 0 && cp < eom && !had_error) { 1806 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp)); 1807 if ((n < 0) || !maybe_ok(res, bp, name_ok)) { 1808 had_error++; 1809 continue; 1810 } 1811 cp += n; /* name */ 1812 type = _getshort(cp); 1813 cp += INT16SZ; /* type */ 1814 class = _getshort(cp); 1815 cp += INT16SZ + INT32SZ; /* class, TTL */ 1816 n = _getshort(cp); 1817 cp += INT16SZ; /* len */ 1818 if (class != C_IN) { 1819 /* XXX - debug? syslog? */ 1820 cp += n; 1821 continue; /* XXX - had_error++ ? */ 1822 } 1823 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 1824 type == T_CNAME) { 1825 n = dn_expand(answer->buf, eom, cp, tbuf, (int)sizeof tbuf); 1826 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) { 1827 had_error++; 1828 continue; 1829 } 1830 cp += n; 1831 /* Get canonical name. */ 1832 n = (int)strlen(tbuf) + 1; /* for the \0 */ 1833 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 1834 had_error++; 1835 continue; 1836 } 1837 strlcpy(bp, tbuf, (size_t)(ep - bp)); 1838 canonname = bp; 1839 bp += n; 1840 continue; 1841 } 1842 if (qtype == T_ANY) { 1843 if (!(type == T_A || type == T_AAAA)) { 1844 cp += n; 1845 continue; 1846 } 1847 } else if (type != qtype) { 1848 if (type != T_KEY && type != T_SIG) { 1849 syslog(LOG_NOTICE|LOG_AUTH, 1850 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 1851 qname, p_class(C_IN), p_type(qtype), 1852 p_type(type)); 1853 } 1854 cp += n; 1855 continue; /* XXX - had_error++ ? */ 1856 } 1857 switch (type) { 1858 case T_A: 1859 case T_AAAA: 1860 if (strcasecmp(canonname, bp) != 0) { 1861 syslog(LOG_NOTICE|LOG_AUTH, 1862 AskedForGot, canonname, bp); 1863 cp += n; 1864 continue; /* XXX - had_error++ ? */ 1865 } 1866 if (type == T_A && n != INADDRSZ) { 1867 cp += n; 1868 continue; 1869 } 1870 if (type == T_AAAA && n != IN6ADDRSZ) { 1871 cp += n; 1872 continue; 1873 } 1874 if (type == T_AAAA) { 1875 struct in6_addr in6; 1876 memcpy(&in6, cp, IN6ADDRSZ); 1877 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 1878 cp += n; 1879 continue; 1880 } 1881 } 1882 if (!haveanswer) { 1883 int nn; 1884 1885 canonname = bp; 1886 nn = (int)strlen(bp) + 1; /* for the \0 */ 1887 bp += nn; 1888 } 1889 1890 /* don't overwrite pai */ 1891 ai = *pai; 1892 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 1893 afd = find_afd(ai.ai_family); 1894 if (afd == NULL) { 1895 cp += n; 1896 continue; 1897 } 1898 cur->ai_next = get_ai(&ai, afd, (const char *)cp); 1899 if (cur->ai_next == NULL) 1900 had_error++; 1901 while (cur && cur->ai_next) 1902 cur = cur->ai_next; 1903 cp += n; 1904 break; 1905 case T_SRV: 1906 /* Add to SRV list. Insertion sort on priority. */ 1907 pri = _getshort(cp); 1908 cp += INT16SZ; 1909 weight = _getshort(cp); 1910 cp += INT16SZ; 1911 port = _getshort(cp); 1912 cp += INT16SZ; 1913 n = dn_expand(answer->buf, eom, cp, tbuf, 1914 (int)sizeof(tbuf)); 1915 if ((n < 0) || !maybe_ok(res, tbuf, res_hnok)) { 1916 had_error++; 1917 continue; 1918 } 1919 cp += n; 1920 if (strlen(tbuf) + 1 >= MAXDNAME) { 1921 had_error++; 1922 continue; 1923 } 1924 srv = malloc(sizeof(*srv)); 1925 if (!srv) { 1926 had_error++; 1927 continue; 1928 } 1929 strlcpy(srv->name, tbuf, sizeof(srv->name)); 1930 srv->pri = pri; 1931 srv->weight = weight; 1932 srv->port = port; 1933 /* Weight 0 is sorted before other weights. */ 1934 if (!srvlist 1935 || srv->pri < srvlist->pri 1936 || (srv->pri == srvlist->pri && 1937 (!srv->weight || srvlist->weight))) { 1938 srv->next = srvlist; 1939 srvlist = srv; 1940 } else { 1941 for (csrv = srvlist; 1942 csrv->next && csrv->next->pri <= srv->pri; 1943 csrv = csrv->next) { 1944 if (csrv->next->pri == srv->pri 1945 && (!srv->weight || 1946 csrv->next->weight)) 1947 break; 1948 } 1949 srv->next = csrv->next; 1950 csrv->next = srv; 1951 } 1952 continue; /* Don't add to haveanswer yet. */ 1953 default: 1954 abort(); 1955 } 1956 if (!had_error) 1957 haveanswer++; 1958 } 1959 1960 if (srvlist) { 1961 /* 1962 * Check for explicit rejection. 1963 */ 1964 if (!srvlist->next && !srvlist->name[0]) { 1965 free(srvlist); 1966 h_errno = HOST_NOT_FOUND; 1967 return NULL; 1968 } 1969 1970 while (srvlist) { 1971 struct res_target q, q2; 1972 1973 srv = srvlist; 1974 srvlist = srvlist->next; 1975 1976 /* 1977 * Since res_* doesn't give the additional 1978 * section, we always look up. 1979 */ 1980 memset(&q, 0, sizeof(q)); 1981 memset(&q2, 0, sizeof(q2)); 1982 1983 q.name = srv->name; 1984 q.qclass = C_IN; 1985 q.qtype = T_AAAA; 1986 q.next = &q2; 1987 q2.name = srv->name; 1988 q2.qclass = C_IN; 1989 q2.qtype = T_A; 1990 1991 aip = _dns_query(&q, pai, res, 0); 1992 1993 if (aip != NULL) { 1994 cur->ai_next = aip; 1995 while (cur && cur->ai_next) { 1996 cur = cur->ai_next; 1997 *getport(cur) = htons(srv->port); 1998 haveanswer++; 1999 } 2000 } 2001 free(srv); 2002 } 2003 } 2004 if (haveanswer) { 2005 if (!sentinel.ai_next->ai_canonname) 2006 (void)get_canonname(pai, sentinel.ai_next, 2007 canonname ? canonname : qname); 2008 h_errno = NETDB_SUCCESS; 2009 return sentinel.ai_next; 2010 } 2011 2012 /* We could have walked a CNAME chain, */ 2013 /* but the ultimate target may not have what we looked for */ 2014 h_errno = ntohs(hp->ancount) > 0? NO_DATA : NO_RECOVERY; 2015 return NULL; 2016 } 2017 2018 #define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr) 2019 #define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr) 2020 2021 static void 2022 aisort(struct addrinfo *s, res_state res) 2023 { 2024 struct addrinfo head, *t, *p; 2025 int i; 2026 2027 head.ai_next = NULL; 2028 t = &head; 2029 2030 for (i = 0; i < res->nsort; i++) { 2031 p = s; 2032 while (p->ai_next) { 2033 if ((p->ai_next->ai_family != AF_INET) 2034 || SORTMATCH(p, res->sort_list[i])) { 2035 t->ai_next = p->ai_next; 2036 t = t->ai_next; 2037 p->ai_next = p->ai_next->ai_next; 2038 } else { 2039 p = p->ai_next; 2040 } 2041 } 2042 } 2043 2044 /* add rest of list and reset s to the new list*/ 2045 t->ai_next = s->ai_next; 2046 s->ai_next = head.ai_next; 2047 } 2048 2049 static struct addrinfo * 2050 _dns_query(struct res_target *q, const struct addrinfo *pai, 2051 res_state res, int dosearch) 2052 { 2053 struct res_target *q2 = q->next; 2054 querybuf *buf, *buf2; 2055 struct addrinfo sentinel, *cur, *ai; 2056 2057 #ifdef DNS_DEBUG 2058 struct res_target *iter; 2059 for (iter = q; iter; iter = iter->next) 2060 printf("Query type %d for %s\n", iter->qtype, iter->name); 2061 #endif 2062 2063 buf = malloc(sizeof(*buf)); 2064 if (buf == NULL) { 2065 h_errno = NETDB_INTERNAL; 2066 return NULL; 2067 } 2068 buf2 = malloc(sizeof(*buf2)); 2069 if (buf2 == NULL) { 2070 free(buf); 2071 h_errno = NETDB_INTERNAL; 2072 return NULL; 2073 } 2074 2075 memset(&sentinel, 0, sizeof(sentinel)); 2076 cur = &sentinel; 2077 2078 q->answer = buf->buf; 2079 q->anslen = sizeof(buf->buf); 2080 if (q2) { 2081 q2->answer = buf2->buf; 2082 q2->anslen = sizeof(buf2->buf); 2083 } 2084 2085 if (dosearch) { 2086 if (res_searchN(q->name, q, res) < 0) 2087 goto out; 2088 } else { 2089 if (res_queryN(q->name, q, res) < 0) 2090 goto out; 2091 } 2092 2093 ai = getanswer(res, buf, q->n, q->name, q->qtype, pai); 2094 if (ai) { 2095 cur->ai_next = ai; 2096 while (cur && cur->ai_next) 2097 cur = cur->ai_next; 2098 } 2099 if (q2) { 2100 ai = getanswer(res, buf2, q2->n, q2->name, q2->qtype, pai); 2101 if (ai) 2102 cur->ai_next = ai; 2103 } 2104 free(buf); 2105 free(buf2); 2106 return sentinel.ai_next; 2107 out: 2108 free(buf); 2109 free(buf2); 2110 return NULL; 2111 } 2112 2113 /*ARGSUSED*/ 2114 static struct addrinfo * 2115 _dns_srv_lookup(const char *name, const char *servname, 2116 const struct addrinfo *pai) 2117 { 2118 static const char * const srvprotos[] = { "tcp", "udp" }; 2119 static const int srvnottype[] = { SOCK_DGRAM, SOCK_STREAM }; 2120 static const int nsrvprotos = 2; 2121 struct addrinfo sentinel, *cur, *ai; 2122 struct servent *serv, sv; 2123 struct servent_data svd; 2124 struct res_target q; 2125 res_state res; 2126 char *tname; 2127 int i; 2128 2129 res = __res_get_state(); 2130 if (res == NULL) 2131 return NULL; 2132 2133 memset(&svd, 0, sizeof(svd)); 2134 memset(&sentinel, 0, sizeof(sentinel)); 2135 cur = &sentinel; 2136 2137 /* 2138 * Iterate over supported SRV protocols. 2139 * (currently UDP and TCP only) 2140 */ 2141 for (i = 0; i < nsrvprotos; i++) { 2142 /* 2143 * Check that the caller didn't specify a hint 2144 * which precludes this protocol. 2145 */ 2146 if (pai->ai_socktype == srvnottype[i]) 2147 continue; 2148 /* 2149 * If the caller specified a port, 2150 * then lookup the database for the 2151 * official service name. 2152 */ 2153 serv = getservbyname_r(servname, srvprotos[i], &sv, &svd); 2154 if (serv == NULL) 2155 continue; 2156 2157 /* 2158 * Construct service DNS name. 2159 */ 2160 if (asprintf(&tname, "_%s._%s.%s", serv->s_name, serv->s_proto, 2161 name) < 0) 2162 continue; 2163 2164 memset(&q, 0, sizeof(q)); 2165 q.name = tname; 2166 q.qclass = C_IN; 2167 q.qtype = T_SRV; 2168 2169 /* 2170 * Do SRV query. 2171 */ 2172 ai = _dns_query(&q, pai, res, 1); 2173 if (ai) { 2174 cur->ai_next = ai; 2175 while (cur && cur->ai_next) 2176 cur = cur->ai_next; 2177 } 2178 free(tname); 2179 } 2180 2181 if (res->nsort) 2182 aisort(&sentinel, res); 2183 2184 __res_put_state(res); 2185 2186 return sentinel.ai_next; 2187 } 2188 2189 /*ARGSUSED*/ 2190 static struct addrinfo * 2191 _dns_host_lookup(const char *name, const struct addrinfo *pai) 2192 { 2193 struct res_target q, q2; 2194 struct addrinfo sentinel, *ai; 2195 res_state res; 2196 2197 res = __res_get_state(); 2198 if (res == NULL) 2199 return NULL; 2200 2201 memset(&q, 0, sizeof(q2)); 2202 memset(&q2, 0, sizeof(q2)); 2203 2204 switch (pai->ai_family) { 2205 case AF_UNSPEC: 2206 /* prefer IPv6 */ 2207 q.name = name; 2208 q.qclass = C_IN; 2209 q.qtype = T_AAAA; 2210 q.next = &q2; 2211 q2.name = name; 2212 q2.qclass = C_IN; 2213 q2.qtype = T_A; 2214 break; 2215 case AF_INET: 2216 q.name = name; 2217 q.qclass = C_IN; 2218 q.qtype = T_A; 2219 break; 2220 case AF_INET6: 2221 q.name = name; 2222 q.qclass = C_IN; 2223 q.qtype = T_AAAA; 2224 break; 2225 default: 2226 __res_put_state(res); 2227 h_errno = NETDB_INTERNAL; 2228 return NULL; 2229 } 2230 2231 ai = _dns_query(&q, pai, res, 1); 2232 2233 memset(&sentinel, 0, sizeof(sentinel)); 2234 sentinel.ai_next = ai; 2235 2236 if (ai != NULL && res->nsort) 2237 aisort(&sentinel, res); 2238 2239 __res_put_state(res); 2240 2241 return sentinel.ai_next; 2242 } 2243 2244 /*ARGSUSED*/ 2245 static int 2246 _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 2247 { 2248 struct addrinfo *ai = NULL; 2249 const char *name, *servname; 2250 const struct addrinfo *pai; 2251 2252 name = va_arg(ap, char *); 2253 pai = va_arg(ap, const struct addrinfo *); 2254 servname = va_arg(ap, char *); 2255 2256 /* 2257 * Try doing SRV lookup on service first. 2258 */ 2259 if (servname 2260 #ifdef AI_SRV 2261 && (pai->ai_flags & AI_SRV) 2262 #endif 2263 && !(pai->ai_flags & AI_NUMERICSERV) 2264 && str2number(servname) == -1) { 2265 2266 #ifdef DNS_DEBUG 2267 printf("%s: try SRV lookup\n", __func__); 2268 #endif 2269 ai = _dns_srv_lookup(name, servname, pai); 2270 } 2271 2272 /* 2273 * Do lookup on name. 2274 */ 2275 if (ai == NULL) { 2276 2277 #ifdef DNS_DEBUG 2278 printf("%s: try HOST lookup\n", __func__); 2279 #endif 2280 ai = _dns_host_lookup(name, pai); 2281 2282 if (ai == NULL) { 2283 switch (h_errno) { 2284 case HOST_NOT_FOUND: 2285 case NO_DATA: // XXX: Perhaps we could differentiate 2286 // So that we could return EAI_NODATA? 2287 return NS_NOTFOUND; 2288 case TRY_AGAIN: 2289 return NS_TRYAGAIN; 2290 default: 2291 return NS_UNAVAIL; 2292 } 2293 } 2294 } 2295 2296 *((struct addrinfo **)rv) = ai; 2297 return NS_SUCCESS; 2298 } 2299 2300 static void 2301 _sethtent(FILE **hostf) 2302 { 2303 2304 if (!*hostf) { 2305 char buffer[256]; 2306 find_directory(B_SYSTEM_SETTINGS_DIRECTORY, 0, false, buffer, sizeof(buffer)); 2307 strlcat(buffer, "/network/hosts", sizeof(buffer)); 2308 2309 *hostf = fopen(buffer, "re"); 2310 } else 2311 rewind(*hostf); 2312 } 2313 2314 static void 2315 _endhtent(FILE **hostf) 2316 { 2317 2318 if (*hostf) { 2319 (void) fclose(*hostf); 2320 *hostf = NULL; 2321 } 2322 } 2323 2324 static struct addrinfo * 2325 _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 2326 { 2327 char *p; 2328 char *cp, *tname, *cname; 2329 struct addrinfo hints, *res0, *res; 2330 int error; 2331 const char *addr; 2332 char hostbuf[8*1024]; 2333 2334 assert(name != NULL); 2335 assert(pai != NULL); 2336 2337 if (!*hostf) 2338 _sethtent(hostf); 2339 if (!*hostf) 2340 return (NULL); 2341 again: 2342 if (!(p = fgets(hostbuf, (int)sizeof hostbuf, *hostf))) 2343 return NULL; 2344 if (*p == '#') 2345 goto again; 2346 if (!(cp = strpbrk(p, "#\n"))) 2347 goto again; 2348 *cp = '\0'; 2349 if (!(cp = strpbrk(p, " \t"))) 2350 goto again; 2351 *cp++ = '\0'; 2352 addr = p; 2353 /* if this is not something we're looking for, skip it. */ 2354 cname = NULL; 2355 while (cp && *cp) { 2356 if (*cp == ' ' || *cp == '\t') { 2357 cp++; 2358 continue; 2359 } 2360 if (!cname) 2361 cname = cp; 2362 tname = cp; 2363 if ((cp = strpbrk(cp, " \t")) != NULL) 2364 *cp++ = '\0'; 2365 if (strcasecmp(name, tname) == 0) 2366 goto found; 2367 } 2368 goto again; 2369 2370 found: 2371 hints = *pai; 2372 hints.ai_flags = AI_NUMERICHOST; 2373 error = getaddrinfo(addr, NULL, &hints, &res0); 2374 if (error) 2375 goto again; 2376 for (res = res0; res; res = res->ai_next) { 2377 /* cover it up */ 2378 res->ai_flags = pai->ai_flags; 2379 2380 if (pai->ai_flags & AI_CANONNAME) { 2381 if (get_canonname(pai, res, cname) != 0) { 2382 freeaddrinfo(res0); 2383 goto again; 2384 } 2385 } 2386 } 2387 return res0; 2388 } 2389 2390 /*ARGSUSED*/ 2391 static int 2392 _files_getaddrinfo(void *rv, void *cb_data, va_list ap) 2393 { 2394 const char *name; 2395 const struct addrinfo *pai; 2396 struct addrinfo sentinel, *cur; 2397 struct addrinfo *p; 2398 #ifndef _REENTRANT 2399 static 2400 #endif 2401 FILE *hostf = NULL; 2402 2403 name = va_arg(ap, char *); 2404 pai = va_arg(ap, const struct addrinfo *); 2405 2406 memset(&sentinel, 0, sizeof(sentinel)); 2407 cur = &sentinel; 2408 2409 _sethtent(&hostf); 2410 while ((p = _gethtent(&hostf, name, pai)) != NULL) { 2411 cur->ai_next = p; 2412 while (cur && cur->ai_next) 2413 cur = cur->ai_next; 2414 } 2415 _endhtent(&hostf); 2416 2417 *((struct addrinfo **)rv) = sentinel.ai_next; 2418 if (sentinel.ai_next == NULL) 2419 return NS_NOTFOUND; 2420 return NS_SUCCESS; 2421 } 2422 2423 #ifdef YP 2424 /*ARGSUSED*/ 2425 static struct addrinfo * 2426 _yphostent(char *line, const struct addrinfo *pai) 2427 { 2428 struct addrinfo sentinel, *cur; 2429 struct addrinfo hints, *res, *res0; 2430 int error; 2431 char *p; 2432 const char *addr, *canonname; 2433 char *nextline; 2434 char *cp; 2435 2436 _DIAGASSERT(line != NULL); 2437 _DIAGASSERT(pai != NULL); 2438 2439 p = line; 2440 addr = canonname = NULL; 2441 2442 memset(&sentinel, 0, sizeof(sentinel)); 2443 cur = &sentinel; 2444 2445 nextline: 2446 /* terminate line */ 2447 cp = strchr(p, '\n'); 2448 if (cp) { 2449 *cp++ = '\0'; 2450 nextline = cp; 2451 } else 2452 nextline = NULL; 2453 2454 cp = strpbrk(p, " \t"); 2455 if (cp == NULL) { 2456 if (canonname == NULL) 2457 return NULL; 2458 else 2459 goto done; 2460 } 2461 *cp++ = '\0'; 2462 2463 addr = p; 2464 2465 while (cp && *cp) { 2466 if (*cp == ' ' || *cp == '\t') { 2467 cp++; 2468 continue; 2469 } 2470 if (!canonname) 2471 canonname = cp; 2472 if ((cp = strpbrk(cp, " \t")) != NULL) 2473 *cp++ = '\0'; 2474 } 2475 2476 hints = *pai; 2477 hints.ai_flags = AI_NUMERICHOST; 2478 error = getaddrinfo(addr, NULL, &hints, &res0); 2479 if (error == 0) { 2480 for (res = res0; res; res = res->ai_next) { 2481 /* cover it up */ 2482 res->ai_flags = pai->ai_flags; 2483 2484 if (pai->ai_flags & AI_CANONNAME) 2485 (void)get_canonname(pai, res, canonname); 2486 } 2487 } else 2488 res0 = NULL; 2489 if (res0) { 2490 cur->ai_next = res0; 2491 while (cur->ai_next) 2492 cur = cur->ai_next; 2493 } 2494 2495 if (nextline) { 2496 p = nextline; 2497 goto nextline; 2498 } 2499 2500 done: 2501 return sentinel.ai_next; 2502 } 2503 2504 /*ARGSUSED*/ 2505 static int 2506 _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) 2507 { 2508 struct addrinfo sentinel, *cur; 2509 struct addrinfo *ai = NULL; 2510 char *ypbuf; 2511 int ypbuflen, r; 2512 const char *name; 2513 const struct addrinfo *pai; 2514 char *ypdomain; 2515 2516 if (_yp_check(&ypdomain) == 0) 2517 return NS_UNAVAIL; 2518 2519 name = va_arg(ap, char *); 2520 pai = va_arg(ap, const struct addrinfo *); 2521 2522 memset(&sentinel, 0, sizeof(sentinel)); 2523 cur = &sentinel; 2524 2525 /* hosts.byname is only for IPv4 (Solaris8) */ 2526 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { 2527 r = yp_match(ypdomain, "hosts.byname", name, 2528 (int)strlen(name), &ypbuf, &ypbuflen); 2529 if (r == 0) { 2530 struct addrinfo ai4; 2531 2532 ai4 = *pai; 2533 ai4.ai_family = AF_INET; 2534 ai = _yphostent(ypbuf, &ai4); 2535 if (ai) { 2536 cur->ai_next = ai; 2537 while (cur && cur->ai_next) 2538 cur = cur->ai_next; 2539 } 2540 } 2541 free(ypbuf); 2542 } 2543 2544 /* ipnodes.byname can hold both IPv4/v6 */ 2545 r = yp_match(ypdomain, "ipnodes.byname", name, 2546 (int)strlen(name), &ypbuf, &ypbuflen); 2547 if (r == 0) { 2548 ai = _yphostent(ypbuf, pai); 2549 if (ai) 2550 cur->ai_next = ai; 2551 free(ypbuf); 2552 } 2553 2554 if (sentinel.ai_next == NULL) { 2555 h_errno = HOST_NOT_FOUND; 2556 return NS_NOTFOUND; 2557 } 2558 *((struct addrinfo **)rv) = sentinel.ai_next; 2559 return NS_SUCCESS; 2560 } 2561 #endif 2562 2563 /* resolver logic */ 2564 2565 /* 2566 * Formulate a normal query, send, and await answer. 2567 * Returned answer is placed in supplied buffer "answer". 2568 * Perform preliminary check of answer, returning success only 2569 * if no error is indicated and the answer count is nonzero. 2570 * Return the size of the response on success, -1 on error. 2571 * Error number is left in h_errno. 2572 * 2573 * Caller must parse answer and determine whether it answers the question. 2574 */ 2575 static int 2576 res_queryN(const char *name, /* domain name */ struct res_target *target, 2577 res_state statp) 2578 { 2579 u_char buf[MAXPACKET]; 2580 HEADER *hp; 2581 int n; 2582 struct res_target *t; 2583 int rcode; 2584 u_char *rdata; 2585 int ancount; 2586 2587 _DIAGASSERT(name != NULL); 2588 /* XXX: target may be NULL??? */ 2589 2590 rcode = NOERROR; 2591 ancount = 0; 2592 2593 for (t = target; t; t = t->next) { 2594 int class, type; 2595 u_char *answer; 2596 int anslen; 2597 u_int oflags; 2598 2599 hp = (HEADER *)(void *)t->answer; 2600 oflags = statp->_flags; 2601 2602 again: 2603 hp->rcode = NOERROR; /* default */ 2604 2605 /* make it easier... */ 2606 class = t->qclass; 2607 type = t->qtype; 2608 answer = t->answer; 2609 anslen = t->anslen; 2610 #ifdef DEBUG 2611 if (statp->options & RES_DEBUG) 2612 printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 2613 #endif 2614 2615 n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, 2616 buf, (int)sizeof(buf)); 2617 #ifdef RES_USE_EDNS0 2618 if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && 2619 (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) { 2620 n = res_nopt(statp, n, buf, (int)sizeof(buf), anslen); 2621 rdata = &buf[n]; 2622 if (n > 0 && (statp->options & RES_NSID) != 0U) { 2623 n = res_nopt_rdata(statp, n, buf, 2624 (int)sizeof(buf), 2625 rdata, NS_OPT_NSID, 0, NULL); 2626 } 2627 } 2628 #endif 2629 if (n <= 0) { 2630 #ifdef DEBUG 2631 if (statp->options & RES_DEBUG) 2632 printf(";; res_nquery: mkquery failed\n"); 2633 #endif 2634 h_errno = NO_RECOVERY; 2635 return n; 2636 } 2637 n = res_nsend(statp, buf, n, answer, anslen); 2638 if (n < 0) { 2639 #ifdef RES_USE_EDNS0 2640 /* if the query choked with EDNS0, retry without EDNS0 */ 2641 if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U && 2642 ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { 2643 statp->_flags |= RES_F_EDNS0ERR; 2644 if (statp->options & RES_DEBUG) 2645 printf(";; res_nquery: retry without EDNS0\n"); 2646 goto again; 2647 } 2648 #endif 2649 #if 0 2650 #ifdef DEBUG 2651 if (statp->options & RES_DEBUG) 2652 printf(";; res_query: send error\n"); 2653 #endif 2654 h_errno = TRY_AGAIN; 2655 return n; 2656 #endif 2657 } 2658 2659 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 2660 rcode = hp->rcode; /* record most recent error */ 2661 #ifdef DEBUG 2662 if (statp->options & RES_DEBUG) 2663 printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n", 2664 p_rcode(hp->rcode), 2665 ntohs(hp->ancount), 2666 ntohs(hp->nscount), 2667 ntohs(hp->arcount)); 2668 #endif 2669 continue; 2670 } 2671 2672 ancount += ntohs(hp->ancount); 2673 2674 t->n = n; 2675 } 2676 2677 if (ancount == 0) { 2678 switch (rcode) { 2679 case NXDOMAIN: 2680 h_errno = HOST_NOT_FOUND; 2681 break; 2682 case SERVFAIL: 2683 h_errno = TRY_AGAIN; 2684 break; 2685 case NOERROR: 2686 h_errno = NO_DATA; 2687 break; 2688 case FORMERR: 2689 case NOTIMP: 2690 case REFUSED: 2691 default: 2692 h_errno = NO_RECOVERY; 2693 break; 2694 } 2695 return -1; 2696 } 2697 return ancount; 2698 } 2699 2700 /* 2701 * Formulate a normal query, send, and retrieve answer in supplied buffer. 2702 * Return the size of the response on success, -1 on error. 2703 * If enabled, implement search rules until answer or unrecoverable failure 2704 * is detected. Error code, if any, is left in h_errno. 2705 */ 2706 static int 2707 res_searchN(const char *name, struct res_target *target, res_state res) 2708 { 2709 const char *cp, * const *domain; 2710 HEADER *hp; 2711 u_int dots; 2712 char buf[MAXHOSTNAMELEN]; 2713 int trailing_dot, ret, saved_herrno; 2714 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 2715 2716 _DIAGASSERT(name != NULL); 2717 _DIAGASSERT(target != NULL); 2718 2719 hp = (HEADER *)(void *)target->answer; /*XXX*/ 2720 2721 errno = 0; 2722 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 2723 dots = 0; 2724 for (cp = name; *cp; cp++) 2725 dots += (*cp == '.'); 2726 trailing_dot = 0; 2727 if (cp > name && *--cp == '.') 2728 trailing_dot++; 2729 2730 /* 2731 * if there aren't any dots, it could be a user-level alias 2732 */ 2733 if (!dots && (cp = res_hostalias(res, name, buf, sizeof(buf))) != NULL) { 2734 ret = res_queryN(cp, target, res); 2735 return ret; 2736 } 2737 2738 /* 2739 * If there are dots in the name already, let's just give it a try 2740 * 'as is'. The threshold can be set with the "ndots" option. 2741 */ 2742 saved_herrno = -1; 2743 if (dots >= res->ndots) { 2744 ret = res_querydomainN(name, NULL, target, res); 2745 if (ret > 0) 2746 return ret; 2747 saved_herrno = h_errno; 2748 tried_as_is++; 2749 } 2750 2751 /* 2752 * We do at least one level of search if 2753 * - there is no dot and RES_DEFNAME is set, or 2754 * - there is at least one dot, there is no trailing dot, 2755 * and RES_DNSRCH is set. 2756 */ 2757 if ((!dots && (res->options & RES_DEFNAMES)) || 2758 (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 2759 int done = 0; 2760 2761 for (domain = (const char * const *)res->dnsrch; 2762 *domain && !done; 2763 domain++) { 2764 2765 ret = res_querydomainN(name, *domain, target, res); 2766 if (ret > 0) 2767 return ret; 2768 2769 /* 2770 * If no server present, give up. 2771 * If name isn't found in this domain, 2772 * keep trying higher domains in the search list 2773 * (if that's enabled). 2774 * On a NO_DATA error, keep trying, otherwise 2775 * a wildcard entry of another type could keep us 2776 * from finding this entry higher in the domain. 2777 * If we get some other error (negative answer or 2778 * server failure), then stop searching up, 2779 * but try the input name below in case it's 2780 * fully-qualified. 2781 */ 2782 if (errno == ECONNREFUSED) { 2783 h_errno = TRY_AGAIN; 2784 return -1; 2785 } 2786 2787 switch (h_errno) { 2788 case NO_DATA: 2789 got_nodata++; 2790 /* FALLTHROUGH */ 2791 case HOST_NOT_FOUND: 2792 /* keep trying */ 2793 break; 2794 case TRY_AGAIN: 2795 if (hp->rcode == SERVFAIL) { 2796 /* try next search element, if any */ 2797 got_servfail++; 2798 break; 2799 } 2800 /* FALLTHROUGH */ 2801 default: 2802 /* anything else implies that we're done */ 2803 done++; 2804 } 2805 /* 2806 * if we got here for some reason other than DNSRCH, 2807 * we only wanted one iteration of the loop, so stop. 2808 */ 2809 if (!(res->options & RES_DNSRCH)) 2810 done++; 2811 } 2812 } 2813 2814 /* 2815 * if we have not already tried the name "as is", do that now. 2816 * note that we do this regardless of how many dots were in the 2817 * name or whether it ends with a dot. 2818 */ 2819 if (!tried_as_is) { 2820 ret = res_querydomainN(name, NULL, target, res); 2821 if (ret > 0) 2822 return ret; 2823 } 2824 2825 /* 2826 * if we got here, we didn't satisfy the search. 2827 * if we did an initial full query, return that query's h_errno 2828 * (note that we wouldn't be here if that query had succeeded). 2829 * else if we ever got a nodata, send that back as the reason. 2830 * else send back meaningless h_errno, that being the one from 2831 * the last DNSRCH we did. 2832 */ 2833 if (saved_herrno != -1) 2834 h_errno = saved_herrno; 2835 else if (got_nodata) 2836 h_errno = NO_DATA; 2837 else if (got_servfail) 2838 h_errno = TRY_AGAIN; 2839 return -1; 2840 } 2841 2842 /* 2843 * Perform a call on res_query on the concatenation of name and domain, 2844 * removing a trailing dot from name if domain is NULL. 2845 */ 2846 static int 2847 res_querydomainN(const char *name, const char *domain, 2848 struct res_target *target, res_state res) 2849 { 2850 char nbuf[MAXDNAME]; 2851 const char *longname = nbuf; 2852 size_t n, d; 2853 2854 _DIAGASSERT(name != NULL); 2855 /* XXX: target may be NULL??? */ 2856 2857 #ifdef DEBUG 2858 if (res->options & RES_DEBUG) 2859 printf(";; res_querydomain(%s, %s)\n", 2860 name, domain?domain:"<Nil>"); 2861 #endif 2862 if (domain == NULL) { 2863 /* 2864 * Check for trailing '.'; 2865 * copy without '.' if present. 2866 */ 2867 n = strlen(name); 2868 if (n + 1 > sizeof(nbuf)) { 2869 h_errno = NO_RECOVERY; 2870 return -1; 2871 } 2872 if (n > 0 && name[--n] == '.') { 2873 strncpy(nbuf, name, n); 2874 nbuf[n] = '\0'; 2875 } else 2876 longname = name; 2877 } else { 2878 n = strlen(name); 2879 d = strlen(domain); 2880 if (n + 1 + d + 1 > sizeof(nbuf)) { 2881 h_errno = NO_RECOVERY; 2882 return -1; 2883 } 2884 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 2885 } 2886 return res_queryN(longname, target, res); 2887 } 2888 2889 #ifdef TEST 2890 int 2891 main(int argc, char *argv[]) { 2892 struct addrinfo *ai, *sai; 2893 int i, e; 2894 char buf[1024]; 2895 2896 for (i = 1; i < argc; i++) { 2897 if ((e = getaddrinfo(argv[i], NULL, NULL, &sai)) != 0) 2898 warnx("%s: %s", argv[i], gai_strerror(e)); 2899 for (ai = sai; ai; ai = ai->ai_next) { 2900 sockaddr_snprintf(buf, sizeof(buf), "%a", ai->ai_addr); 2901 printf("flags=0x%x family=%d socktype=%d protocol=%d " 2902 "addrlen=%zu addr=%s canonname=%s next=%p\n", 2903 ai->ai_flags, 2904 ai->ai_family, 2905 ai->ai_socktype, 2906 ai->ai_protocol, 2907 (size_t)ai->ai_addrlen, 2908 buf, 2909 ai->ai_canonname, 2910 ai->ai_next); 2911 } 2912 if (sai) 2913 freeaddrinfo(sai); 2914 } 2915 return 0; 2916 } 2917 #endif 2918