1 /* $NetBSD: getaddrinfo.c,v 1.7 2014/12/10 04:37:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* Id: getaddrinfo.c,v 1.3 2009/09/02 23:48:02 tbox Exp */ 20 21 /*! \file */ 22 23 /** 24 * getaddrinfo() is used to get a list of IP addresses and port 25 * numbers for host hostname and service servname as defined in RFC3493. 26 * hostname and servname are pointers to null-terminated strings 27 * or NULL. hostname is either a host name or a numeric host address 28 * string: a dotted decimal IPv4 address or an IPv6 address. servname is 29 * either a decimal port number or a service name as listed in 30 * /etc/services. 31 * 32 * If the operating system does not provide a struct addrinfo, the 33 * following structure is used: 34 * 35 * \code 36 * struct addrinfo { 37 * int ai_flags; // AI_PASSIVE, AI_CANONNAME 38 * int ai_family; // PF_xxx 39 * int ai_socktype; // SOCK_xxx 40 * int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6 41 * size_t ai_addrlen; // length of ai_addr 42 * char *ai_canonname; // canonical name for hostname 43 * struct sockaddr *ai_addr; // binary address 44 * struct addrinfo *ai_next; // next structure in linked list 45 * }; 46 * \endcode 47 * 48 * 49 * hints is an optional pointer to a struct addrinfo. This structure can 50 * be used to provide hints concerning the type of socket that the caller 51 * supports or wishes to use. The caller can supply the following 52 * structure elements in *hints: 53 * 54 * <ul> 55 * <li>ai_family: 56 * The protocol family that should be used. When ai_family is set 57 * to PF_UNSPEC, it means the caller will accept any protocol 58 * family supported by the operating system.</li> 59 * 60 * <li>ai_socktype: 61 * denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or 62 * SOCK_RAW -- that is wanted. When ai_socktype is zero the caller 63 * will accept any socket type.</li> 64 * 65 * <li>ai_protocol: 66 * indicates which transport protocol is wanted: IPPROTO_UDP or 67 * IPPROTO_TCP. If ai_protocol is zero the caller will accept any 68 * protocol.</li> 69 * 70 * <li>ai_flags: 71 * Flag bits. If the AI_CANONNAME bit is set, a successful call to 72 * getaddrinfo() will return a null-terminated string 73 * containing the canonical name of the specified hostname in 74 * ai_canonname of the first addrinfo structure returned. Setting 75 * the AI_PASSIVE bit indicates that the returned socket address 76 * structure is intended for used in a call to bind(2). In this 77 * case, if the hostname argument is a NULL pointer, then the IP 78 * address portion of the socket address structure will be set to 79 * INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 80 * address.<br /><br /> 81 * 82 * When ai_flags does not set the AI_PASSIVE bit, the returned 83 * socket address structure will be ready for use in a call to 84 * connect(2) for a connection-oriented protocol or connect(2), 85 * sendto(2), or sendmsg(2) if a connectionless protocol was 86 * chosen. The IP address portion of the socket address structure 87 * will be set to the loopback address if hostname is a NULL 88 * pointer and AI_PASSIVE is not set in ai_flags.<br /><br /> 89 * 90 * If ai_flags is set to AI_NUMERICHOST it indicates that hostname 91 * should be treated as a numeric string defining an IPv4 or IPv6 92 * address and no name resolution should be attempted. 93 * </li></ul> 94 * 95 * All other elements of the struct addrinfo passed via hints must be 96 * zero. 97 * 98 * A hints of NULL is treated as if the caller provided a struct addrinfo 99 * initialized to zero with ai_familyset to PF_UNSPEC. 100 * 101 * After a successful call to getaddrinfo(), *res is a pointer to a 102 * linked list of one or more addrinfo structures. Each struct addrinfo 103 * in this list cn be processed by following the ai_next pointer, until a 104 * NULL pointer is encountered. The three members ai_family, ai_socktype, 105 * and ai_protocol in each returned addrinfo structure contain the 106 * corresponding arguments for a call to socket(2). For each addrinfo 107 * structure in the list, the ai_addr member points to a filled-in socket 108 * address structure of length ai_addrlen. 109 * 110 * All of the information returned by getaddrinfo() is dynamically 111 * allocated: the addrinfo structures, and the socket address structures 112 * and canonical host name strings pointed to by the addrinfostructures. 113 * Memory allocated for the dynamically allocated structures created by a 114 * successful call to getaddrinfo() is released by freeaddrinfo(). 115 * ai is a pointer to a struct addrinfo created by a call to getaddrinfo(). 116 * 117 * \section irsreturn RETURN VALUES 118 * 119 * getaddrinfo() returns zero on success or one of the error codes 120 * listed in gai_strerror() if an error occurs. If both hostname and 121 * servname are NULL getaddrinfo() returns #EAI_NONAME. 122 * 123 * \section irssee SEE ALSO 124 * 125 * getaddrinfo(), freeaddrinfo(), 126 * gai_strerror(), RFC3493, getservbyname(3), connect(2), 127 * sendto(2), sendmsg(2), socket(2). 128 */ 129 130 #include <config.h> 131 132 #include <stdlib.h> 133 #include <string.h> 134 #include <errno.h> 135 136 #include <isc/app.h> 137 #include <isc/buffer.h> 138 #include <isc/lib.h> 139 #include <isc/mem.h> 140 #include <isc/sockaddr.h> 141 #include <isc/string.h> 142 #include <isc/util.h> 143 144 #include <dns/client.h> 145 #include <dns/fixedname.h> 146 #include <dns/name.h> 147 #include <dns/rdata.h> 148 #include <dns/rdataset.h> 149 #include <dns/rdatastruct.h> 150 #include <dns/rdatatype.h> 151 #include <dns/result.h> 152 153 #include <irs/context.h> 154 #include <irs/netdb.h> 155 #include <irs/resconf.h> 156 157 #define SA(addr) ((struct sockaddr *)(addr)) 158 #define SIN(addr) ((struct sockaddr_in *)(addr)) 159 #define SIN6(addr) ((struct sockaddr_in6 *)(addr)) 160 #define SLOCAL(addr) ((struct sockaddr_un *)(addr)) 161 162 /*! \struct addrinfo 163 */ 164 static struct addrinfo 165 *ai_concat(struct addrinfo *ai1, struct addrinfo *ai2), 166 *ai_reverse(struct addrinfo *oai), 167 *ai_clone(struct addrinfo *oai, int family), 168 *ai_alloc(int family, int addrlen); 169 #ifdef AF_LOCAL 170 static int get_local(const char *name, int socktype, struct addrinfo **res); 171 #endif 172 173 static int 174 resolve_name(int family, const char *hostname, int flags, 175 struct addrinfo **aip, int socktype, int port); 176 177 static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip, 178 int socktype, int port); 179 static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip, 180 int socktype, int port); 181 static void set_order(int, int (**)(const char *, int, struct addrinfo **, 182 int, int)); 183 static void _freeaddrinfo(struct addrinfo *ai); 184 185 #define FOUND_IPV4 0x1 186 #define FOUND_IPV6 0x2 187 #define FOUND_MAX 2 188 189 #define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) 190 /*% 191 * Get a list of IP addresses and port numbers for host hostname and 192 * service servname. 193 */ 194 int 195 getaddrinfo(const char *hostname, const char *servname, 196 const struct addrinfo *hints, struct addrinfo **res) 197 { 198 struct servent *sp; 199 const char *proto; 200 int family, socktype, flags, protocol; 201 struct addrinfo *ai, *ai_list; 202 int err = 0; 203 int port, i; 204 int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **, 205 int, int); 206 207 if (hostname == NULL && servname == NULL) 208 return (EAI_NONAME); 209 210 proto = NULL; 211 if (hints != NULL) { 212 if ((hints->ai_flags & ~(ISC_AI_MASK)) != 0) 213 return (EAI_BADFLAGS); 214 if (hints->ai_addrlen || hints->ai_canonname || 215 hints->ai_addr || hints->ai_next) { 216 errno = EINVAL; 217 return (EAI_SYSTEM); 218 } 219 family = hints->ai_family; 220 socktype = hints->ai_socktype; 221 protocol = hints->ai_protocol; 222 flags = hints->ai_flags; 223 switch (family) { 224 case AF_UNSPEC: 225 switch (hints->ai_socktype) { 226 case SOCK_STREAM: 227 proto = "tcp"; 228 break; 229 case SOCK_DGRAM: 230 proto = "udp"; 231 break; 232 } 233 break; 234 case AF_INET: 235 case AF_INET6: 236 switch (hints->ai_socktype) { 237 case 0: 238 break; 239 case SOCK_STREAM: 240 proto = "tcp"; 241 break; 242 case SOCK_DGRAM: 243 proto = "udp"; 244 break; 245 case SOCK_RAW: 246 break; 247 default: 248 return (EAI_SOCKTYPE); 249 } 250 break; 251 #ifdef AF_LOCAL 252 case AF_LOCAL: 253 switch (hints->ai_socktype) { 254 case 0: 255 break; 256 case SOCK_STREAM: 257 break; 258 case SOCK_DGRAM: 259 break; 260 default: 261 return (EAI_SOCKTYPE); 262 } 263 break; 264 #endif 265 default: 266 return (EAI_FAMILY); 267 } 268 } else { 269 protocol = 0; 270 family = 0; 271 socktype = 0; 272 flags = 0; 273 } 274 275 #ifdef AF_LOCAL 276 /*! 277 * First, deal with AF_LOCAL. If the family was not set, 278 * then assume AF_LOCAL if the first character of the 279 * hostname/servname is '/'. 280 */ 281 282 if (hostname != NULL && 283 (family == AF_LOCAL || (family == 0 && *hostname == '/'))) 284 return (get_local(hostname, socktype, res)); 285 286 if (servname != NULL && 287 (family == AF_LOCAL || (family == 0 && *servname == '/'))) 288 return (get_local(servname, socktype, res)); 289 #endif 290 291 /* 292 * Ok, only AF_INET and AF_INET6 left. 293 */ 294 ai_list = NULL; 295 296 /* 297 * First, look up the service name (port) if it was 298 * requested. If the socket type wasn't specified, then 299 * try and figure it out. 300 */ 301 if (servname != NULL) { 302 char *e; 303 304 port = strtol(servname, &e, 10); 305 if (*e == '\0') { 306 if (socktype == 0) 307 return (EAI_SOCKTYPE); 308 if (port < 0 || port > 65535) 309 return (EAI_SERVICE); 310 port = htons((unsigned short) port); 311 } else { 312 sp = getservbyname(servname, proto); 313 if (sp == NULL) 314 return (EAI_SERVICE); 315 port = sp->s_port; 316 if (socktype == 0) { 317 if (strcmp(sp->s_proto, "tcp") == 0) 318 socktype = SOCK_STREAM; 319 else if (strcmp(sp->s_proto, "udp") == 0) 320 socktype = SOCK_DGRAM; 321 } 322 } 323 } else 324 port = 0; 325 326 /* 327 * Next, deal with just a service name, and no hostname. 328 * (we verified that one of them was non-null up above). 329 */ 330 if (hostname == NULL && (flags & AI_PASSIVE) != 0) { 331 if (family == AF_INET || family == 0) { 332 ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in)); 333 if (ai == NULL) 334 return (EAI_MEMORY); 335 ai->ai_socktype = socktype; 336 ai->ai_protocol = protocol; 337 SIN(ai->ai_addr)->sin_port = port; 338 ai->ai_next = ai_list; 339 ai_list = ai; 340 } 341 342 if (family == AF_INET6 || family == 0) { 343 ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6)); 344 if (ai == NULL) { 345 _freeaddrinfo(ai_list); 346 return (EAI_MEMORY); 347 } 348 ai->ai_socktype = socktype; 349 ai->ai_protocol = protocol; 350 SIN6(ai->ai_addr)->sin6_port = port; 351 ai->ai_next = ai_list; 352 ai_list = ai; 353 } 354 355 *res = ai_list; 356 return (0); 357 } 358 359 /* 360 * If the family isn't specified or AI_NUMERICHOST specified, check 361 * first to see if it is a numeric address. 362 * Though the gethostbyname2() routine will recognize numeric addresses, 363 * it will only recognize the format that it is being called for. Thus, 364 * a numeric AF_INET address will be treated by the AF_INET6 call as 365 * a domain name, and vice versa. Checking for both numerics here 366 * avoids that. 367 */ 368 if (hostname != NULL && 369 (family == 0 || (flags & AI_NUMERICHOST) != 0)) { 370 char abuf[sizeof(struct in6_addr)]; 371 char nbuf[NI_MAXHOST]; 372 int addrsize, addroff; 373 #ifdef IRS_HAVE_SIN6_SCOPE_ID 374 char *p, *ep; 375 char ntmp[NI_MAXHOST]; 376 isc_uint32_t scopeid; 377 #endif 378 379 #ifdef IRS_HAVE_SIN6_SCOPE_ID 380 /* 381 * Scope identifier portion. 382 */ 383 ntmp[0] = '\0'; 384 if (strchr(hostname, '%') != NULL) { 385 strncpy(ntmp, hostname, sizeof(ntmp) - 1); 386 ntmp[sizeof(ntmp) - 1] = '\0'; 387 p = strchr(ntmp, '%'); 388 ep = NULL; 389 390 /* 391 * Vendors may want to support non-numeric 392 * scopeid around here. 393 */ 394 395 if (p != NULL) 396 scopeid = (isc_uint32_t)strtoul(p + 1, 397 &ep, 10); 398 if (p != NULL && ep != NULL && ep[0] == '\0') 399 *p = '\0'; 400 else { 401 ntmp[0] = '\0'; 402 scopeid = 0; 403 } 404 } else 405 scopeid = 0; 406 #endif 407 408 if (inet_pton(AF_INET, hostname, (struct in_addr *)abuf) 409 == 1) { 410 if (family == AF_INET6) { 411 /* 412 * Convert to a V4 mapped address. 413 */ 414 struct in6_addr *a6 = (struct in6_addr *)abuf; 415 memmove(&a6->s6_addr[12], &a6->s6_addr[0], 4); 416 memset(&a6->s6_addr[10], 0xff, 2); 417 memset(&a6->s6_addr[0], 0, 10); 418 goto inet6_addr; 419 } 420 addrsize = sizeof(struct in_addr); 421 addroff = (char *)(&SIN(0)->sin_addr) - (char *)0; 422 family = AF_INET; 423 goto common; 424 #ifdef IRS_HAVE_SIN6_SCOPE_ID 425 } else if (ntmp[0] != '\0' && 426 inet_pton(AF_INET6, ntmp, abuf) == 1) { 427 if (family && family != AF_INET6) 428 return (EAI_NONAME); 429 addrsize = sizeof(struct in6_addr); 430 addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; 431 family = AF_INET6; 432 goto common; 433 #endif 434 } else if (inet_pton(AF_INET6, hostname, abuf) == 1) { 435 if (family != 0 && family != AF_INET6) 436 return (EAI_NONAME); 437 inet6_addr: 438 addrsize = sizeof(struct in6_addr); 439 addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; 440 family = AF_INET6; 441 442 common: 443 ai = ai_alloc(family, 444 ((family == AF_INET6) ? 445 sizeof(struct sockaddr_in6) : 446 sizeof(struct sockaddr_in))); 447 if (ai == NULL) 448 return (EAI_MEMORY); 449 ai_list = ai; 450 ai->ai_socktype = socktype; 451 SIN(ai->ai_addr)->sin_port = port; 452 memmove((char *)ai->ai_addr + addroff, abuf, addrsize); 453 if ((flags & AI_CANONNAME) != 0) { 454 #ifdef IRS_HAVE_SIN6_SCOPE_ID 455 if (ai->ai_family == AF_INET6) 456 SIN6(ai->ai_addr)->sin6_scope_id = 457 scopeid; 458 #endif 459 if (getnameinfo(ai->ai_addr, 460 (socklen_t)ai->ai_addrlen, 461 nbuf, sizeof(nbuf), NULL, 0, 462 NI_NUMERICHOST) == 0) { 463 ai->ai_canonname = strdup(nbuf); 464 if (ai->ai_canonname == NULL) { 465 _freeaddrinfo(ai); 466 return (EAI_MEMORY); 467 } 468 } else { 469 /* XXX raise error? */ 470 ai->ai_canonname = NULL; 471 } 472 } 473 goto done; 474 } else if ((flags & AI_NUMERICHOST) != 0) { 475 return (EAI_NONAME); 476 } 477 } 478 479 if (hostname == NULL && (flags & AI_PASSIVE) == 0) { 480 set_order(family, net_order); 481 for (i = 0; i < FOUND_MAX; i++) { 482 if (net_order[i] == NULL) 483 break; 484 err = (net_order[i])(hostname, flags, &ai_list, 485 socktype, port); 486 if (err != 0) { 487 if (ai_list != NULL) { 488 _freeaddrinfo(ai_list); 489 ai_list = NULL; 490 } 491 break; 492 } 493 } 494 } else 495 err = resolve_name(family, hostname, flags, &ai_list, 496 socktype, port); 497 498 if (ai_list == NULL) { 499 if (err == 0) 500 err = EAI_NONAME; 501 return (err); 502 } 503 504 done: 505 ai_list = ai_reverse(ai_list); 506 507 *res = ai_list; 508 return (0); 509 } 510 511 typedef struct gai_restrans { 512 dns_clientrestrans_t *xid; 513 isc_boolean_t is_inprogress; 514 int error; 515 struct addrinfo ai_sentinel; 516 struct gai_resstate *resstate; 517 } gai_restrans_t; 518 519 typedef struct gai_resstate { 520 isc_mem_t *mctx; 521 struct gai_statehead *head; 522 dns_fixedname_t fixedname; 523 dns_name_t *qname; 524 gai_restrans_t *trans4; 525 gai_restrans_t *trans6; 526 ISC_LINK(struct gai_resstate) link; 527 } gai_resstate_t; 528 529 typedef struct gai_statehead { 530 int ai_family; 531 int ai_flags; 532 int ai_socktype; 533 int ai_port; 534 isc_appctx_t *actx; 535 dns_client_t *dnsclient; 536 ISC_LIST(struct gai_resstate) resstates; 537 unsigned int activestates; 538 } gai_statehead_t; 539 540 static isc_result_t 541 make_resstate(isc_mem_t *mctx, gai_statehead_t *head, const char *hostname, 542 const char *domain, gai_resstate_t **statep) 543 { 544 isc_result_t result; 545 gai_resstate_t *state; 546 dns_fixedname_t fixeddomain; 547 dns_name_t *qdomain; 548 unsigned int namelen; 549 isc_buffer_t b; 550 isc_boolean_t need_v4 = ISC_FALSE; 551 isc_boolean_t need_v6 = ISC_FALSE; 552 553 state = isc_mem_get(mctx, sizeof(*state)); 554 if (state == NULL) 555 return (ISC_R_NOMEMORY); 556 557 /* Construct base domain name */ 558 namelen = strlen(domain); 559 isc_buffer_constinit(&b, domain, namelen); 560 isc_buffer_add(&b, namelen); 561 dns_fixedname_init(&fixeddomain); 562 qdomain = dns_fixedname_name(&fixeddomain); 563 result = dns_name_fromtext(qdomain, &b, dns_rootname, 0, NULL); 564 if (result != ISC_R_SUCCESS) { 565 isc_mem_put(mctx, state, sizeof(*state)); 566 return (result); 567 } 568 569 /* Construct query name */ 570 namelen = strlen(hostname); 571 isc_buffer_constinit(&b, hostname, namelen); 572 isc_buffer_add(&b, namelen); 573 dns_fixedname_init(&state->fixedname); 574 state->qname = dns_fixedname_name(&state->fixedname); 575 result = dns_name_fromtext(state->qname, &b, qdomain, 0, NULL); 576 if (result != ISC_R_SUCCESS) { 577 isc_mem_put(mctx, state, sizeof(*state)); 578 return (result); 579 } 580 581 if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET) 582 need_v4 = ISC_TRUE; 583 if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET6) 584 need_v6 = ISC_TRUE; 585 586 state->trans6 = NULL; 587 state->trans4 = NULL; 588 if (need_v4) { 589 state->trans4 = isc_mem_get(mctx, sizeof(gai_restrans_t)); 590 if (state->trans4 == NULL) { 591 isc_mem_put(mctx, state, sizeof(*state)); 592 return (ISC_R_NOMEMORY); 593 } 594 state->trans4->error = 0; 595 state->trans4->xid = NULL; 596 state->trans4->resstate = state; 597 state->trans4->is_inprogress = ISC_TRUE; 598 state->trans4->ai_sentinel.ai_next = NULL; 599 } 600 if (need_v6) { 601 state->trans6 = isc_mem_get(mctx, sizeof(gai_restrans_t)); 602 if (state->trans6 == NULL) { 603 if (state->trans4 != NULL) 604 isc_mem_put(mctx, state->trans4, 605 sizeof(*state->trans4)); 606 isc_mem_put(mctx, state, sizeof(*state)); 607 return (ISC_R_NOMEMORY); 608 } 609 state->trans6->error = 0; 610 state->trans6->xid = NULL; 611 state->trans6->resstate = state; 612 state->trans6->is_inprogress = ISC_TRUE; 613 state->trans6->ai_sentinel.ai_next = NULL; 614 } 615 616 state->mctx = mctx; 617 state->head = head; 618 ISC_LINK_INIT(state, link); 619 620 *statep = state; 621 622 return (ISC_R_SUCCESS); 623 } 624 625 static isc_result_t 626 make_resstates(isc_mem_t *mctx, const char *hostname, gai_statehead_t *head, 627 irs_resconf_t *resconf) 628 { 629 isc_result_t result; 630 irs_resconf_searchlist_t *searchlist; 631 irs_resconf_search_t *searchent; 632 gai_resstate_t *resstate, *resstate0; 633 634 resstate0 = NULL; 635 result = make_resstate(mctx, head, hostname, ".", &resstate0); 636 if (result != ISC_R_SUCCESS) 637 return (result); 638 639 searchlist = irs_resconf_getsearchlist(resconf); 640 for (searchent = ISC_LIST_HEAD(*searchlist); searchent != NULL; 641 searchent = ISC_LIST_NEXT(searchent, link)) { 642 resstate = NULL; 643 result = make_resstate(mctx, head, hostname, 644 (const char *)searchent->domain, 645 &resstate); 646 if (result != ISC_R_SUCCESS) 647 break; 648 649 ISC_LIST_APPEND(head->resstates, resstate, link); 650 head->activestates++; 651 } 652 653 /* 654 * Insert the original hostname either at the head or the tail of the 655 * state list, depending on the number of labels contained in the 656 * original name and the 'ndots' configuration parameter. 657 */ 658 if (dns_name_countlabels(resstate0->qname) > 659 irs_resconf_getndots(resconf) + 1) { 660 ISC_LIST_PREPEND(head->resstates, resstate0, link); 661 } else 662 ISC_LIST_APPEND(head->resstates, resstate0, link); 663 head->activestates++; 664 665 if (result != ISC_R_SUCCESS) { 666 while ((resstate = ISC_LIST_HEAD(head->resstates)) != NULL) { 667 ISC_LIST_UNLINK(head->resstates, resstate, link); 668 if (resstate->trans4 != NULL) { 669 isc_mem_put(mctx, resstate->trans4, 670 sizeof(*resstate->trans4)); 671 } 672 if (resstate->trans6 != NULL) { 673 isc_mem_put(mctx, resstate->trans6, 674 sizeof(*resstate->trans6)); 675 } 676 677 isc_mem_put(mctx, resstate, sizeof(*resstate)); 678 } 679 } 680 681 return (result); 682 } 683 684 static void 685 process_answer(isc_task_t *task, isc_event_t *event) { 686 int error = 0, family; 687 gai_restrans_t *trans = event->ev_arg; 688 gai_resstate_t *resstate; 689 dns_clientresevent_t *rev = (dns_clientresevent_t *)event; 690 dns_rdatatype_t qtype; 691 dns_name_t *name; 692 693 REQUIRE(trans != NULL); 694 resstate = trans->resstate; 695 REQUIRE(resstate != NULL); 696 REQUIRE(task != NULL); 697 698 if (trans == resstate->trans4) { 699 family = AF_INET; 700 qtype = dns_rdatatype_a; 701 } else { 702 INSIST(trans == resstate->trans6); 703 family = AF_INET6; 704 qtype = dns_rdatatype_aaaa; 705 } 706 707 INSIST(trans->is_inprogress); 708 trans->is_inprogress = ISC_FALSE; 709 710 switch (rev->result) { 711 case ISC_R_SUCCESS: 712 case DNS_R_NCACHENXDOMAIN: /* treat this as a fatal error? */ 713 case DNS_R_NCACHENXRRSET: 714 break; 715 default: 716 switch (rev->vresult) { 717 case DNS_R_SIGINVALID: 718 case DNS_R_SIGEXPIRED: 719 case DNS_R_SIGFUTURE: 720 case DNS_R_KEYUNAUTHORIZED: 721 case DNS_R_MUSTBESECURE: 722 case DNS_R_COVERINGNSEC: 723 case DNS_R_NOTAUTHORITATIVE: 724 case DNS_R_NOVALIDKEY: 725 case DNS_R_NOVALIDDS: 726 case DNS_R_NOVALIDSIG: 727 error = EAI_INSECUREDATA; 728 break; 729 default: 730 error = EAI_FAIL; 731 } 732 goto done; 733 } 734 735 /* Parse the response and construct the addrinfo chain */ 736 for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; 737 name = ISC_LIST_NEXT(name, link)) { 738 isc_result_t result; 739 dns_rdataset_t *rdataset; 740 isc_buffer_t b; 741 isc_region_t r; 742 char t[1024]; 743 744 for (rdataset = ISC_LIST_HEAD(name->list); 745 rdataset != NULL; 746 rdataset = ISC_LIST_NEXT(rdataset, link)) { 747 if (!dns_rdataset_isassociated(rdataset)) 748 continue; 749 if (rdataset->type != qtype) 750 continue; 751 752 if ((resstate->head->ai_flags & AI_CANONNAME) != 0) { 753 isc_buffer_init(&b, t, sizeof(t)); 754 result = dns_name_totext(name, ISC_TRUE, &b); 755 if (result != ISC_R_SUCCESS) { 756 error = EAI_FAIL; 757 goto done; 758 } 759 isc_buffer_putuint8(&b, '\0'); 760 isc_buffer_usedregion(&b, &r); 761 } 762 763 for (result = dns_rdataset_first(rdataset); 764 result == ISC_R_SUCCESS; 765 result = dns_rdataset_next(rdataset)) { 766 struct addrinfo *ai; 767 dns_rdata_t rdata; 768 dns_rdata_in_a_t rdata_a; 769 dns_rdata_in_aaaa_t rdata_aaaa; 770 771 ai = ai_alloc(family, 772 ((family == AF_INET6) ? 773 sizeof(struct sockaddr_in6) : 774 sizeof(struct sockaddr_in))); 775 if (ai == NULL) { 776 error = EAI_MEMORY; 777 goto done; 778 } 779 ai->ai_socktype = resstate->head->ai_socktype; 780 ai->ai_next = trans->ai_sentinel.ai_next; 781 trans->ai_sentinel.ai_next = ai; 782 783 /* 784 * Set AF-specific parameters 785 * (IPv4/v6 address/port) 786 */ 787 dns_rdata_init(&rdata); 788 switch (family) { 789 case AF_INET: 790 dns_rdataset_current(rdataset, &rdata); 791 result = dns_rdata_tostruct(&rdata, &rdata_a, 792 NULL); 793 RUNTIME_CHECK(result == ISC_R_SUCCESS); 794 SIN(ai->ai_addr)->sin_port = 795 resstate->head->ai_port; 796 memmove(&SIN(ai->ai_addr)->sin_addr, 797 &rdata_a.in_addr, 4); 798 dns_rdata_freestruct(&rdata_a); 799 break; 800 case AF_INET6: 801 dns_rdataset_current(rdataset, &rdata); 802 result = dns_rdata_tostruct(&rdata, &rdata_aaaa, 803 NULL); 804 RUNTIME_CHECK(result == ISC_R_SUCCESS); 805 SIN6(ai->ai_addr)->sin6_port = 806 resstate->head->ai_port; 807 memmove(&SIN6(ai->ai_addr)->sin6_addr, 808 &rdata_aaaa.in6_addr, 16); 809 dns_rdata_freestruct(&rdata_aaaa); 810 break; 811 } 812 813 if ((resstate->head->ai_flags & AI_CANONNAME) 814 != 0) { 815 ai->ai_canonname = 816 strdup((const char *)r.base); 817 if (ai->ai_canonname == NULL) { 818 error = EAI_MEMORY; 819 goto done; 820 } 821 } 822 } 823 } 824 } 825 826 done: 827 dns_client_freeresanswer(resstate->head->dnsclient, &rev->answerlist); 828 dns_client_destroyrestrans(&trans->xid); 829 830 isc_event_free(&event); 831 832 /* Make sure that error == 0 iff we have a non-empty list */ 833 if (error == 0) { 834 if (trans->ai_sentinel.ai_next == NULL) 835 error = EAI_NONAME; 836 } else { 837 if (trans->ai_sentinel.ai_next != NULL) { 838 _freeaddrinfo(trans->ai_sentinel.ai_next); 839 trans->ai_sentinel.ai_next = NULL; 840 } 841 } 842 trans->error = error; 843 844 /* Check whether we are done */ 845 if ((resstate->trans4 == NULL || !resstate->trans4->is_inprogress) && 846 (resstate->trans6 == NULL || !resstate->trans6->is_inprogress)) { 847 /* 848 * We're done for this state. If there is no other outstanding 849 * state, we can exit. 850 */ 851 resstate->head->activestates--; 852 if (resstate->head->activestates == 0) { 853 isc_app_ctxsuspend(resstate->head->actx); 854 return; 855 } 856 857 /* 858 * There are outstanding states, but if we are at the head 859 * of the state list (i.e., at the highest search priority) 860 * and have any answer, we can stop now by canceling the 861 * others. 862 */ 863 if (resstate == ISC_LIST_HEAD(resstate->head->resstates)) { 864 if ((resstate->trans4 != NULL && 865 resstate->trans4->ai_sentinel.ai_next != NULL) || 866 (resstate->trans6 != NULL && 867 resstate->trans6->ai_sentinel.ai_next != NULL)) { 868 gai_resstate_t *rest; 869 870 for (rest = ISC_LIST_NEXT(resstate, link); 871 rest != NULL; 872 rest = ISC_LIST_NEXT(rest, link)) { 873 if (rest->trans4 != NULL && 874 rest->trans4->xid != NULL) 875 dns_client_cancelresolve( 876 rest->trans4->xid); 877 if (rest->trans6 != NULL && 878 rest->trans6->xid != NULL) 879 dns_client_cancelresolve( 880 rest->trans6->xid); 881 } 882 } else { 883 /* 884 * This search fails, so we move to the tail 885 * of the list so that the next entry will 886 * have the highest priority. 887 */ 888 ISC_LIST_UNLINK(resstate->head->resstates, 889 resstate, link); 890 ISC_LIST_APPEND(resstate->head->resstates, 891 resstate, link); 892 } 893 } 894 } 895 } 896 897 static int 898 resolve_name(int family, const char *hostname, int flags, 899 struct addrinfo **aip, int socktype, int port) 900 { 901 isc_result_t result; 902 irs_context_t *irsctx; 903 irs_resconf_t *conf; 904 isc_mem_t *mctx; 905 isc_appctx_t *actx; 906 isc_task_t *task; 907 int terror = 0; 908 int error = 0; 909 dns_client_t *client; 910 gai_resstate_t *resstate; 911 gai_statehead_t head; 912 isc_boolean_t all_fail = ISC_TRUE; 913 914 /* get IRS context and the associated parameters */ 915 irsctx = NULL; 916 result = irs_context_get(&irsctx); 917 if (result != ISC_R_SUCCESS) 918 return (EAI_FAIL); 919 actx = irs_context_getappctx(irsctx); 920 921 mctx = irs_context_getmctx(irsctx); 922 task = irs_context_gettask(irsctx); 923 conf = irs_context_getresconf(irsctx); 924 client = irs_context_getdnsclient(irsctx); 925 926 /* construct resolution states */ 927 head.activestates = 0; 928 head.ai_family = family; 929 head.ai_socktype = socktype; 930 head.ai_flags = flags; 931 head.ai_port = port; 932 head.actx = actx; 933 head.dnsclient = client; 934 ISC_LIST_INIT(head.resstates); 935 result = make_resstates(mctx, hostname, &head, conf); 936 if (result != ISC_R_SUCCESS) 937 return (EAI_FAIL); 938 939 for (resstate = ISC_LIST_HEAD(head.resstates); 940 resstate != NULL; resstate = ISC_LIST_NEXT(resstate, link)) { 941 if (resstate->trans4 != NULL) { 942 result = dns_client_startresolve(client, 943 resstate->qname, 944 dns_rdataclass_in, 945 dns_rdatatype_a, 946 0, task, 947 process_answer, 948 resstate->trans4, 949 &resstate->trans4->xid); 950 if (result == ISC_R_SUCCESS) { 951 resstate->trans4->is_inprogress = ISC_TRUE; 952 all_fail = ISC_FALSE; 953 } else 954 resstate->trans4->is_inprogress = ISC_FALSE; 955 } 956 if (resstate->trans6 != NULL) { 957 result = dns_client_startresolve(client, 958 resstate->qname, 959 dns_rdataclass_in, 960 dns_rdatatype_aaaa, 961 0, task, 962 process_answer, 963 resstate->trans6, 964 &resstate->trans6->xid); 965 if (result == ISC_R_SUCCESS) { 966 resstate->trans6->is_inprogress = ISC_TRUE; 967 all_fail = ISC_FALSE; 968 } else 969 resstate->trans6->is_inprogress= ISC_FALSE; 970 } 971 } 972 if (!all_fail) { 973 /* Start all the events */ 974 isc_app_ctxrun(actx); 975 } else 976 error = EAI_FAIL; 977 978 /* Cleanup */ 979 while ((resstate = ISC_LIST_HEAD(head.resstates)) != NULL) { 980 int terror4 = 0, terror6 = 0; 981 982 ISC_LIST_UNLINK(head.resstates, resstate, link); 983 984 if (*aip == NULL) { 985 struct addrinfo *sentinel4 = NULL; 986 struct addrinfo *sentinel6 = NULL; 987 988 if (resstate->trans4 != NULL) { 989 sentinel4 = 990 resstate->trans4->ai_sentinel.ai_next; 991 resstate->trans4->ai_sentinel.ai_next = NULL; 992 } 993 if (resstate->trans6 != NULL) { 994 sentinel6 = 995 resstate->trans6->ai_sentinel.ai_next; 996 resstate->trans6->ai_sentinel.ai_next = NULL; 997 } 998 *aip = ai_concat(sentinel4, sentinel6); 999 } 1000 1001 if (resstate->trans4 != NULL) { 1002 INSIST(resstate->trans4->xid == NULL); 1003 terror4 = resstate->trans4->error; 1004 isc_mem_put(mctx, resstate->trans4, 1005 sizeof(*resstate->trans4)); 1006 } 1007 if (resstate->trans6 != NULL) { 1008 INSIST(resstate->trans6->xid == NULL); 1009 terror6 = resstate->trans6->error; 1010 isc_mem_put(mctx, resstate->trans6, 1011 sizeof(*resstate->trans6)); 1012 } 1013 1014 /* 1015 * If the entire lookup fails, we need to choose an appropriate 1016 * error code from individual codes. We'll try to provide as 1017 * specific a code as possible. In general, we are going to 1018 * find an error code other than EAI_NONAME (which is too 1019 * generic and may actually not be problematic in some cases). 1020 * EAI_NONAME will be set below if no better code is found. 1021 */ 1022 if (terror == 0 || terror == EAI_NONAME) { 1023 if (terror4 != 0 && terror4 != EAI_NONAME) 1024 terror = terror4; 1025 else if (terror6 != 0 && terror6 != EAI_NONAME) 1026 terror = terror6; 1027 } 1028 1029 isc_mem_put(mctx, resstate, sizeof(*resstate)); 1030 } 1031 1032 if (*aip == NULL) { 1033 error = terror; 1034 if (error == 0) 1035 error = EAI_NONAME; 1036 } 1037 1038 #if 1 /* XXX: enabled for finding leaks. should be cleaned up later. */ 1039 isc_app_ctxfinish(actx); 1040 irs_context_destroy(&irsctx); 1041 #endif 1042 1043 return (error); 1044 } 1045 1046 static char * 1047 irs_strsep(char **stringp, const char *delim) { 1048 char *string = *stringp; 1049 char *s; 1050 const char *d; 1051 char sc, dc; 1052 1053 if (string == NULL) 1054 return (NULL); 1055 1056 for (s = string; *s != '\0'; s++) { 1057 sc = *s; 1058 for (d = delim; (dc = *d) != '\0'; d++) 1059 if (sc == dc) { 1060 *s++ = '\0'; 1061 *stringp = s; 1062 return (string); 1063 } 1064 } 1065 *stringp = NULL; 1066 return (string); 1067 } 1068 1069 static void 1070 set_order(int family, int (**net_order)(const char *, int, struct addrinfo **, 1071 int, int)) 1072 { 1073 char *order, *tok; 1074 int found; 1075 1076 if (family) { 1077 switch (family) { 1078 case AF_INET: 1079 *net_order++ = add_ipv4; 1080 break; 1081 case AF_INET6: 1082 *net_order++ = add_ipv6; 1083 break; 1084 } 1085 } else { 1086 order = getenv("NET_ORDER"); 1087 found = 0; 1088 while (order != NULL) { 1089 /* 1090 * We ignore any unknown names. 1091 */ 1092 tok = irs_strsep(&order, ":"); 1093 if (strcasecmp(tok, "inet6") == 0) { 1094 if ((found & FOUND_IPV6) == 0) 1095 *net_order++ = add_ipv6; 1096 found |= FOUND_IPV6; 1097 } else if (strcasecmp(tok, "inet") == 0 || 1098 strcasecmp(tok, "inet4") == 0) { 1099 if ((found & FOUND_IPV4) == 0) 1100 *net_order++ = add_ipv4; 1101 found |= FOUND_IPV4; 1102 } 1103 } 1104 1105 /* 1106 * Add in anything that we didn't find. 1107 */ 1108 if ((found & FOUND_IPV4) == 0) 1109 *net_order++ = add_ipv4; 1110 if ((found & FOUND_IPV6) == 0) 1111 *net_order++ = add_ipv6; 1112 } 1113 *net_order = NULL; 1114 return; 1115 } 1116 1117 static char v4_loop[4] = { 127, 0, 0, 1 }; 1118 1119 static int 1120 add_ipv4(const char *hostname, int flags, struct addrinfo **aip, 1121 int socktype, int port) 1122 { 1123 struct addrinfo *ai; 1124 1125 UNUSED(hostname); 1126 UNUSED(flags); 1127 1128 ai = ai_clone(*aip, AF_INET); /* don't use ai_clone() */ 1129 if (ai == NULL) { 1130 _freeaddrinfo(*aip); 1131 return (EAI_MEMORY); 1132 } 1133 1134 *aip = ai; 1135 ai->ai_socktype = socktype; 1136 SIN(ai->ai_addr)->sin_port = port; 1137 memmove(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4); 1138 1139 return (0); 1140 } 1141 1142 static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 1143 1144 static int 1145 add_ipv6(const char *hostname, int flags, struct addrinfo **aip, 1146 int socktype, int port) 1147 { 1148 struct addrinfo *ai; 1149 1150 UNUSED(hostname); 1151 UNUSED(flags); 1152 1153 ai = ai_clone(*aip, AF_INET6); /* don't use ai_clone() */ 1154 if (ai == NULL) 1155 return (EAI_MEMORY); 1156 1157 *aip = ai; 1158 ai->ai_socktype = socktype; 1159 SIN6(ai->ai_addr)->sin6_port = port; 1160 memmove(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16); 1161 1162 return (0); 1163 } 1164 1165 /*% Free address info. */ 1166 void 1167 freeaddrinfo(struct addrinfo *ai) { 1168 _freeaddrinfo(ai); 1169 } 1170 1171 static void 1172 _freeaddrinfo(struct addrinfo *ai) { 1173 struct addrinfo *ai_next; 1174 1175 while (ai != NULL) { 1176 ai_next = ai->ai_next; 1177 if (ai->ai_addr != NULL) 1178 free(ai->ai_addr); 1179 if (ai->ai_canonname) 1180 free(ai->ai_canonname); 1181 free(ai); 1182 ai = ai_next; 1183 } 1184 } 1185 1186 #ifdef AF_LOCAL 1187 static int 1188 get_local(const char *name, int socktype, struct addrinfo **res) { 1189 struct addrinfo *ai; 1190 struct sockaddr_un *slocal; 1191 1192 if (socktype == 0) 1193 return (EAI_SOCKTYPE); 1194 1195 ai = ai_alloc(AF_LOCAL, sizeof(*slocal)); 1196 if (ai == NULL) 1197 return (EAI_MEMORY); 1198 1199 slocal = SLOCAL(ai->ai_addr); 1200 strlcpy(slocal->sun_path, name, sizeof(slocal->sun_path)); 1201 1202 ai->ai_socktype = socktype; 1203 /* 1204 * ai->ai_flags, ai->ai_protocol, ai->ai_canonname, 1205 * and ai->ai_next were initialized to zero. 1206 */ 1207 1208 *res = ai; 1209 return (0); 1210 } 1211 #endif 1212 1213 /*! 1214 * Allocate an addrinfo structure, and a sockaddr structure 1215 * of the specificed length. We initialize: 1216 * ai_addrlen 1217 * ai_family 1218 * ai_addr 1219 * ai_addr->sa_family 1220 * ai_addr->sa_len (IRS_PLATFORM_HAVESALEN) 1221 * and everything else is initialized to zero. 1222 */ 1223 static struct addrinfo * 1224 ai_alloc(int family, int addrlen) { 1225 struct addrinfo *ai; 1226 1227 ai = (struct addrinfo *)calloc(1, sizeof(*ai)); 1228 if (ai == NULL) 1229 return (NULL); 1230 1231 ai->ai_addr = SA(calloc(1, addrlen)); 1232 if (ai->ai_addr == NULL) { 1233 free(ai); 1234 return (NULL); 1235 } 1236 ai->ai_addrlen = addrlen; 1237 ai->ai_family = family; 1238 ai->ai_addr->sa_family = family; 1239 #ifdef IRS_PLATFORM_HAVESALEN 1240 ai->ai_addr->sa_len = addrlen; 1241 #endif 1242 return (ai); 1243 } 1244 1245 static struct addrinfo * 1246 ai_clone(struct addrinfo *oai, int family) { 1247 struct addrinfo *ai; 1248 1249 ai = ai_alloc(family, ((family == AF_INET6) ? 1250 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))); 1251 1252 if (ai == NULL) { 1253 if (oai != NULL) 1254 freeaddrinfo(oai); 1255 return (NULL); 1256 } 1257 if (oai == NULL) 1258 return (ai); 1259 1260 ai->ai_flags = oai->ai_flags; 1261 ai->ai_socktype = oai->ai_socktype; 1262 ai->ai_protocol = oai->ai_protocol; 1263 ai->ai_canonname = NULL; 1264 ai->ai_next = oai; 1265 return (ai); 1266 } 1267 1268 static struct addrinfo * 1269 ai_reverse(struct addrinfo *oai) { 1270 struct addrinfo *nai, *tai; 1271 1272 nai = NULL; 1273 1274 while (oai != NULL) { 1275 /* 1276 * Grab one off the old list. 1277 */ 1278 tai = oai; 1279 oai = oai->ai_next; 1280 /* 1281 * Put it on the front of the new list. 1282 */ 1283 tai->ai_next = nai; 1284 nai = tai; 1285 } 1286 return (nai); 1287 } 1288 1289 1290 static struct addrinfo * 1291 ai_concat(struct addrinfo *ai1, struct addrinfo *ai2) { 1292 struct addrinfo *ai_tmp; 1293 1294 if (ai1 == NULL) 1295 return (ai2); 1296 else if (ai2 == NULL) 1297 return (ai1); 1298 1299 for (ai_tmp = ai1; ai_tmp != NULL && ai_tmp->ai_next != NULL; 1300 ai_tmp = ai_tmp->ai_next) 1301 ; 1302 1303 ai_tmp->ai_next = ai2; 1304 1305 return (ai1); 1306 } 1307