1 /* $NetBSD: dighost.c,v 1.21 2026/01/29 18:36:26 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file 17 * \note 18 * Notice to programmers: Do not use this code as an example of how to 19 * use the ISC library to perform DNS lookups. Dig and Host both operate 20 * on the request level, since they allow fine-tuning of output and are 21 * intended as debugging tools. As a result, they perform many of the 22 * functions which could be better handled using the dns_resolver 23 * functions in most applications. 24 */ 25 26 #include <errno.h> 27 #include <inttypes.h> 28 #include <limits.h> 29 #include <locale.h> 30 #include <netdb.h> 31 #include <stdbool.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 36 #ifdef HAVE_LIBIDN2 37 #include <idn2.h> 38 #endif /* HAVE_LIBIDN2 */ 39 40 #include <isc/base64.h> 41 #include <isc/file.h> 42 #include <isc/getaddresses.h> 43 #include <isc/hex.h> 44 #include <isc/lang.h> 45 #include <isc/log.h> 46 #include <isc/loop.h> 47 #include <isc/managers.h> 48 #include <isc/netaddr.h> 49 #include <isc/nonce.h> 50 #include <isc/parseint.h> 51 #include <isc/random.h> 52 #include <isc/result.h> 53 #include <isc/safe.h> 54 #include <isc/serial.h> 55 #include <isc/sockaddr.h> 56 #include <isc/string.h> 57 #include <isc/timer.h> 58 #include <isc/tls.h> 59 #include <isc/types.h> 60 #include <isc/util.h> 61 #include <isc/uv.h> 62 #include <isc/xml.h> 63 64 #include <dns/byaddr.h> 65 #include <dns/ede.h> 66 #include <dns/fixedname.h> 67 #include <dns/log.h> 68 #include <dns/message.h> 69 #include <dns/name.h> 70 #include <dns/opcode.h> 71 #include <dns/rcode.h> 72 #include <dns/rdata.h> 73 #include <dns/rdataclass.h> 74 #include <dns/rdatalist.h> 75 #include <dns/rdataset.h> 76 #include <dns/rdatastruct.h> 77 #include <dns/rdatatype.h> 78 #include <dns/tsig.h> 79 80 #include <dst/dst.h> 81 82 #include <isccfg/namedconf.h> 83 84 #include <irs/resconf.h> 85 86 #include "dighost.h" 87 88 #define systemlocale(l) (void)setlocale(l, "") 89 #define resetlocale(l) (void)setlocale(l, "C") 90 91 dig_lookuplist_t lookup_list; 92 dig_serverlist_t server_list; 93 dig_searchlistlist_t search_list; 94 95 static bool cancel_now = false; 96 97 bool check_ra = false, have_ipv4 = false, have_ipv6 = false, 98 specified_source = false, free_now = false, usesearch = false, 99 showsearch = false, is_dst_up = false, keep_open = false, verbose = false, 100 yaml = false; 101 in_port_t port = 53; 102 bool port_set = false; 103 unsigned int timeout = 0; 104 unsigned int extrabytes; 105 isc_mem_t *mctx = NULL; 106 isc_log_t *lctx = NULL; 107 isc_nm_t *netmgr = NULL; 108 isc_loopmgr_t *loopmgr = NULL; 109 isc_loop_t *mainloop = NULL; 110 isc_sockaddr_t localaddr; 111 isc_refcount_t sendcount = 0; 112 isc_refcount_t recvcount = 0; 113 int ndots = -1; 114 int tries = -1; 115 int lookup_counter = 0; 116 117 static char servercookie[256]; 118 119 #ifdef HAVE_LIBIDN2 120 static void 121 idn_input(const char *src, char *dst, size_t dstlen); 122 #endif /* HAVE_LIBIDN2 */ 123 124 isc_nmhandle_t *keep = NULL; 125 isc_sockaddr_t keepaddr; 126 127 /*% 128 * Exit Codes: 129 * 130 *\li 0 Everything went well, including things like NXDOMAIN 131 *\li 1 Usage error 132 *\li 7 Got too many RR's or Names 133 *\li 8 Couldn't open batch file 134 *\li 9 No reply from server 135 *\li 10 Internal error 136 */ 137 int exitcode = 0; 138 int fatalexit = 0; 139 char keynametext[MXNAME]; 140 char keyfile[MXNAME] = ""; 141 char keysecret[MXNAME] = ""; 142 unsigned char cookie_secret[33]; 143 unsigned char cookie[8]; 144 dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN; 145 unsigned int digestbits = 0; 146 isc_buffer_t *namebuf = NULL; 147 dns_tsigkey_t *tsigkey = NULL; 148 dst_key_t *sig0key = NULL; 149 bool validated = true; 150 bool debugging = false; 151 bool debugtiming = false; 152 bool memdebugging = false; 153 char *progname = NULL; 154 dig_lookup_t *current_lookup = NULL; 155 156 #define DIG_MAX_ADDRESSES 20 157 158 static void 159 default_warnerr(const char *format, ...) { 160 va_list args; 161 162 printf(";; "); 163 va_start(args, format); 164 vprintf(format, args); 165 va_end(args); 166 printf("\n"); 167 } 168 169 static void 170 default_comments(dig_lookup_t *lookup, const char *format, ...) { 171 va_list args; 172 173 if (lookup->comments) { 174 printf(";; "); 175 va_start(args, format); 176 vprintf(format, args); 177 va_end(args); 178 printf("\n"); 179 } 180 } 181 182 /* dynamic callbacks */ 183 184 isc_result_t (*dighost_printmessage)(dig_query_t *query, 185 const isc_buffer_t *msgbuf, 186 dns_message_t *msg, bool headers); 187 188 void (*dighost_error)(const char *format, ...) = default_warnerr; 189 190 void (*dighost_warning)(const char *format, ...) = default_warnerr; 191 192 void (*dighost_comments)(dig_lookup_t *lookup, const char *format, 193 ...) = default_comments; 194 195 void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from, 196 dig_query_t *query); 197 198 void (*dighost_trying)(char *frm, dig_lookup_t *lookup); 199 200 void (*dighost_shutdown)(void); 201 202 /* forward declarations */ 203 204 #define cancel_lookup(l) _cancel_lookup(l, __FILE__, __LINE__) 205 static void 206 _cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line); 207 208 static void 209 recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, 210 void *arg); 211 212 static void 213 start_udp(dig_query_t *query); 214 215 static void 216 start_tcp(dig_query_t *query); 217 218 static void 219 force_next(dig_query_t *query); 220 221 static void 222 launch_next_query(dig_query_t *query); 223 224 static void 225 clear_current_lookup(void); 226 227 static bool 228 next_origin(dig_lookup_t *oldlookup); 229 230 static int 231 count_dots(char *string) { 232 char *s; 233 int i = 0; 234 235 s = string; 236 while (*s != '\0') { 237 if (*s == '.') { 238 i++; 239 } 240 s++; 241 } 242 return i; 243 } 244 245 static void 246 hex_dump(isc_buffer_t *b) { 247 unsigned int len, i; 248 isc_region_t r; 249 250 isc_buffer_usedregion(b, &r); 251 252 printf("%u bytes\n", r.length); 253 for (len = 0; len < r.length; len++) { 254 printf("%02x ", r.base[len]); 255 if (len % 16 == 15) { 256 printf(" "); 257 for (i = len - 15; i <= len; i++) { 258 if (r.base[i] >= '!' && r.base[i] <= '}') { 259 putchar(r.base[i]); 260 } else { 261 putchar('.'); 262 } 263 } 264 printf("\n"); 265 } 266 } 267 if (len % 16 != 0) { 268 for (i = len; (i % 16) != 0; i++) { 269 printf(" "); 270 } 271 printf(" "); 272 for (i = ((len >> 4) << 4); i < len; i++) { 273 if (r.base[i] >= '!' && r.base[i] <= '}') { 274 putchar(r.base[i]); 275 } else { 276 putchar('.'); 277 } 278 } 279 printf("\n"); 280 } 281 } 282 283 /*% 284 * Append 'len' bytes of 'text' at '*p', failing with 285 * ISC_R_NOSPACE if that would advance p past 'end'. 286 */ 287 static isc_result_t 288 append(const char *text, size_t len, char **p, char *end) { 289 if (*p + len > end) { 290 return ISC_R_NOSPACE; 291 } 292 memmove(*p, text, len); 293 *p += len; 294 return ISC_R_SUCCESS; 295 } 296 297 static isc_result_t 298 reverse_octets(const char *in, char **p, char *end) { 299 const char *dot = strchr(in, '.'); 300 size_t len; 301 if (dot != NULL) { 302 isc_result_t result; 303 result = reverse_octets(dot + 1, p, end); 304 if (result != ISC_R_SUCCESS) { 305 return result; 306 } 307 result = append(".", 1, p, end); 308 if (result != ISC_R_SUCCESS) { 309 return result; 310 } 311 len = (int)(dot - in); 312 } else { 313 len = (int)strlen(in); 314 } 315 return append(in, len, p, end); 316 } 317 318 isc_result_t 319 get_reverse(char *reverse, size_t len, char *value, bool strict) { 320 int r; 321 isc_result_t result; 322 isc_netaddr_t addr; 323 324 addr.family = AF_INET6; 325 r = inet_pton(AF_INET6, value, &addr.type.in6); 326 if (r > 0) { 327 /* This is a valid IPv6 address. */ 328 dns_fixedname_t fname; 329 dns_name_t *name; 330 331 name = dns_fixedname_initname(&fname); 332 result = dns_byaddr_createptrname(&addr, name); 333 if (result != ISC_R_SUCCESS) { 334 return result; 335 } 336 dns_name_format(name, reverse, (unsigned int)len); 337 return ISC_R_SUCCESS; 338 } else { 339 /* 340 * Not a valid IPv6 address. Assume IPv4. 341 * If 'strict' is not set, construct the 342 * in-addr.arpa name by blindly reversing 343 * octets whether or not they look like integers, 344 * so that this can be used for RFC2317 names 345 * and such. 346 */ 347 char *p = reverse; 348 char *end = reverse + len; 349 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) { 350 return DNS_R_BADDOTTEDQUAD; 351 } 352 result = reverse_octets(value, &p, end); 353 if (result != ISC_R_SUCCESS) { 354 return result; 355 } 356 /* Append .in-addr.arpa. and a terminating NUL. */ 357 result = append(".in-addr.arpa.", 15, &p, end); 358 if (result != ISC_R_SUCCESS) { 359 return result; 360 } 361 return ISC_R_SUCCESS; 362 } 363 } 364 365 #if TARGET_OS_IPHONE 366 void 367 warn(const char *format, ...) { 368 va_list args; 369 370 fflush(stdout); 371 fprintf(stderr, ";; Warning: "); 372 va_start(args, format); 373 vfprintf(stderr, format, args); 374 va_end(args); 375 fprintf(stderr, "\n"); 376 } 377 #else /* if TARGET_OS_IPHONE */ 378 void 379 warn(const char *format, ...) { 380 va_list args; 381 382 fflush(stdout); 383 fprintf(stderr, "%s: ", progname); 384 va_start(args, format); 385 vfprintf(stderr, format, args); 386 va_end(args); 387 fprintf(stderr, "\n"); 388 } 389 #endif /* if TARGET_OS_IPHONE */ 390 391 void 392 digexit(void) { 393 if (exitcode < 10) { 394 exitcode = 10; 395 } 396 if (fatalexit != 0) { 397 _exit(fatalexit); 398 } 399 exit(exitcode); 400 } 401 402 void 403 fatal(const char *format, ...) { 404 va_list args; 405 406 fflush(stdout); 407 fprintf(stderr, "%s: ", progname); 408 va_start(args, format); 409 vfprintf(stderr, format, args); 410 va_end(args); 411 fprintf(stderr, "\n"); 412 if (fatalexit == 0 && exitcode != 0) { 413 fatalexit = exitcode; 414 } else if (fatalexit == 0) { 415 fatalexit = EXIT_FAILURE; 416 } 417 digexit(); 418 } 419 420 void 421 debug(const char *format, ...) { 422 va_list args; 423 isc_time_t t; 424 425 if (debugging) { 426 fflush(stdout); 427 if (debugtiming) { 428 t = isc_time_now(); 429 fprintf(stderr, "%u.%06u: ", isc_time_seconds(&t), 430 isc_time_nanoseconds(&t) / 1000); 431 } 432 va_start(args, format); 433 vfprintf(stderr, format, args); 434 va_end(args); 435 fprintf(stderr, "\n"); 436 } 437 } 438 439 void 440 check_result(isc_result_t result, const char *msg) { 441 if (result != ISC_R_SUCCESS) { 442 fatal("%s: %s", msg, isc_result_totext(result)); 443 } 444 } 445 446 /*% 447 * Create a server structure, which is part of the lookup structure. 448 * This is little more than a linked list of servers to query in hopes 449 * of finding the answer the user is looking for 450 */ 451 dig_server_t * 452 make_server(const char *servname, const char *userarg) { 453 dig_server_t *srv; 454 455 REQUIRE(servname != NULL); 456 457 debug("make_server(%s)", servname); 458 srv = isc_mem_allocate(mctx, sizeof(struct dig_server)); 459 strlcpy(srv->servername, servname, MXNAME); 460 strlcpy(srv->userarg, userarg, MXNAME); 461 ISC_LINK_INIT(srv, link); 462 return srv; 463 } 464 465 /*% 466 * Create a copy of the server list from the resolver configuration structure. 467 * The dest list must have already had ISC_LIST_INIT applied. 468 */ 469 static void 470 get_server_list(irs_resconf_t *resconf) { 471 isc_sockaddrlist_t *servers; 472 isc_sockaddr_t *sa; 473 dig_server_t *newsrv; 474 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + 475 sizeof("%4000000000")]; 476 debug("get_server_list()"); 477 servers = irs_resconf_getnameservers(resconf); 478 for (sa = ISC_LIST_HEAD(*servers); sa != NULL; 479 sa = ISC_LIST_NEXT(sa, link)) 480 { 481 int pf = isc_sockaddr_pf(sa); 482 isc_netaddr_t na; 483 isc_result_t result; 484 isc_buffer_t b; 485 486 if (pf == AF_INET && !have_ipv4) { 487 continue; 488 } 489 if (pf == AF_INET6 && !have_ipv6) { 490 continue; 491 } 492 493 isc_buffer_init(&b, tmp, sizeof(tmp)); 494 isc_netaddr_fromsockaddr(&na, sa); 495 result = isc_netaddr_totext(&na, &b); 496 if (result != ISC_R_SUCCESS) { 497 continue; 498 } 499 isc_buffer_putuint8(&b, 0); 500 if (pf == AF_INET6 && na.zone != 0) { 501 char buf[sizeof("%4000000000")]; 502 snprintf(buf, sizeof(buf), "%%%u", na.zone); 503 strlcat(tmp, buf, sizeof(tmp)); 504 } 505 newsrv = make_server(tmp, tmp); 506 ISC_LINK_INIT(newsrv, link); 507 ISC_LIST_APPEND(server_list, newsrv, link); 508 } 509 } 510 511 void 512 flush_server_list(void) { 513 dig_server_t *s, *ps; 514 515 debug("flush_server_list()"); 516 s = ISC_LIST_HEAD(server_list); 517 while (s != NULL) { 518 ps = s; 519 s = ISC_LIST_NEXT(s, link); 520 ISC_LIST_DEQUEUE(server_list, ps, link); 521 isc_mem_free(mctx, ps); 522 } 523 } 524 525 void 526 set_nameserver(char *opt) { 527 isc_result_t result; 528 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; 529 isc_netaddr_t netaddr; 530 int count, i; 531 dig_server_t *srv; 532 char tmp[ISC_NETADDR_FORMATSIZE]; 533 534 if (opt == NULL) { 535 return; 536 } 537 538 isc_loopmgr_blocking(loopmgr); 539 result = isc_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES, &count); 540 isc_loopmgr_nonblocking(loopmgr); 541 if (result != ISC_R_SUCCESS) { 542 fatal("couldn't get address for '%s': %s", opt, 543 isc_result_totext(result)); 544 } 545 546 flush_server_list(); 547 548 for (i = 0; i < count; i++) { 549 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); 550 isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); 551 srv = make_server(tmp, opt); 552 if (srv == NULL) { 553 fatal("memory allocation failure"); 554 } 555 ISC_LIST_APPEND(server_list, srv, link); 556 } 557 } 558 559 /*% 560 * Produce a cloned server list. The dest list must have already had 561 * ISC_LIST_INIT applied. 562 */ 563 void 564 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) { 565 dig_server_t *srv, *newsrv; 566 567 debug("clone_server_list()"); 568 srv = ISC_LIST_HEAD(src); 569 while (srv != NULL) { 570 newsrv = make_server(srv->servername, srv->userarg); 571 ISC_LINK_INIT(newsrv, link); 572 ISC_LIST_ENQUEUE(*dest, newsrv, link); 573 srv = ISC_LIST_NEXT(srv, link); 574 } 575 } 576 577 /*% 578 * Create an empty lookup structure, which holds all the information needed 579 * to get an answer to a user's question. This structure contains two 580 * linked lists: the server list (servers to query) and the query list 581 * (outstanding queries which have been made to the listed servers). 582 */ 583 dig_lookup_t * 584 make_empty_lookup(void) { 585 dig_lookup_t *looknew; 586 int idnin = false, idnout = false; 587 588 #ifdef HAVE_LIBIDN2 589 if (getenv("IDN_DISABLE") == NULL) { 590 idnin = true; 591 idnout = isatty(1); 592 } 593 #endif /* HAVE_LIBIDN2 */ 594 595 debug("make_empty_lookup()"); 596 597 INSIST(!free_now); 598 599 looknew = isc_mem_allocate(mctx, sizeof(*looknew)); 600 *looknew = (dig_lookup_t){ 601 .pending = true, 602 .rdtype = dns_rdatatype_a, 603 .qrdtype = dns_rdatatype_a, 604 .rdclass = dns_rdataclass_in, 605 .servfail_stops = true, 606 .besteffort = true, 607 .opcode = dns_opcode_query, 608 .badcookie = true, 609 .idnin = idnin, 610 .idnout = idnout, 611 .udpsize = -1, 612 .edns = -1, 613 .original_edns = -1, 614 .recurse = true, 615 .retries = tries, 616 .comments = true, 617 .stats = true, 618 .section_question = true, 619 .section_answer = true, 620 .section_authority = true, 621 .section_additional = true, 622 .ednsneg = true, 623 }; 624 625 dns_fixedname_init(&looknew->fdomain); 626 ISC_LINK_INIT(looknew, link); 627 ISC_LIST_INIT(looknew->q); 628 ISC_LIST_INIT(looknew->my_server_list); 629 630 isc_tlsctx_cache_create(mctx, &looknew->tls_ctx_cache); 631 632 isc_refcount_init(&looknew->references, 1); 633 634 looknew->magic = DIG_LOOKUP_MAGIC; 635 636 debug("make_empty_lookup() = %p->references = %" PRIuFAST32, looknew, 637 isc_refcount_current(&looknew->references)); 638 639 return looknew; 640 } 641 642 #define EDNSOPT_OPTIONS 100U 643 644 static void 645 cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) { 646 size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS; 647 size_t i; 648 looknew->ednsopts = isc_mem_allocate(mctx, len); 649 for (i = 0; i < EDNSOPT_OPTIONS; i++) { 650 looknew->ednsopts[i].code = 0; 651 looknew->ednsopts[i].length = 0; 652 looknew->ednsopts[i].value = NULL; 653 } 654 looknew->ednsoptscnt = 0; 655 if (lookold == NULL || lookold->ednsopts == NULL) { 656 return; 657 } 658 659 for (i = 0; i < lookold->ednsoptscnt; i++) { 660 len = lookold->ednsopts[i].length; 661 if (len != 0) { 662 INSIST(lookold->ednsopts[i].value != NULL); 663 looknew->ednsopts[i].value = isc_mem_allocate(mctx, 664 len); 665 memmove(looknew->ednsopts[i].value, 666 lookold->ednsopts[i].value, len); 667 } 668 looknew->ednsopts[i].code = lookold->ednsopts[i].code; 669 looknew->ednsopts[i].length = len; 670 } 671 looknew->ednsoptscnt = lookold->ednsoptscnt; 672 } 673 674 /*% 675 * Clone a lookup, perhaps copying the server list. This does not clone 676 * the query list, since it will be regenerated by the setup_lookup() 677 * function, nor does it queue up the new lookup for processing. 678 * Caution: If you don't clone the servers, you MUST clone the server 679 * list separately from somewhere else, or construct it by hand. 680 */ 681 dig_lookup_t * 682 clone_lookup(dig_lookup_t *lookold, bool servers) { 683 dig_lookup_t *looknew; 684 685 debug("clone_lookup()"); 686 687 INSIST(!free_now); 688 689 looknew = make_empty_lookup(); 690 strlcpy(looknew->textname, lookold->textname, MXNAME); 691 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME); 692 looknew->textname[MXNAME - 1] = 0; 693 looknew->rdtype = lookold->rdtype; 694 looknew->qrdtype = lookold->qrdtype; 695 looknew->rdclass = lookold->rdclass; 696 looknew->rdtypeset = lookold->rdtypeset; 697 looknew->rdclassset = lookold->rdclassset; 698 looknew->doing_xfr = lookold->doing_xfr; 699 looknew->ixfr_serial = lookold->ixfr_serial; 700 looknew->trace = lookold->trace; 701 looknew->trace_root = lookold->trace_root; 702 looknew->identify = lookold->identify; 703 looknew->identify_previous_line = lookold->identify_previous_line; 704 looknew->ignore = lookold->ignore; 705 looknew->servfail_stops = lookold->servfail_stops; 706 looknew->besteffort = lookold->besteffort; 707 looknew->dns64prefix = lookold->dns64prefix; 708 looknew->dnssec = lookold->dnssec; 709 looknew->ednsflags = lookold->ednsflags; 710 looknew->opcode = lookold->opcode; 711 looknew->expire = lookold->expire; 712 looknew->nsid = lookold->nsid; 713 looknew->tcp_keepalive = lookold->tcp_keepalive; 714 looknew->header_only = lookold->header_only; 715 looknew->https_mode = lookold->https_mode; 716 if (lookold->https_path != NULL) { 717 looknew->https_path = isc_mem_strdup(mctx, lookold->https_path); 718 } 719 looknew->https_get = lookold->https_get; 720 looknew->http_plain = lookold->http_plain; 721 722 looknew->tls_ca_set = lookold->tls_ca_set; 723 if (lookold->tls_ca_file != NULL) { 724 looknew->tls_ca_file = isc_mem_strdup(mctx, 725 lookold->tls_ca_file); 726 }; 727 728 looknew->tls_hostname_set = lookold->tls_hostname_set; 729 if (lookold->tls_hostname != NULL) { 730 looknew->tls_hostname = isc_mem_strdup(mctx, 731 lookold->tls_hostname); 732 } 733 734 looknew->tls_key_file_set = lookold->tls_key_file_set; 735 if (lookold->tls_key_file != NULL) { 736 looknew->tls_key_file = isc_mem_strdup(mctx, 737 lookold->tls_key_file); 738 } 739 740 looknew->tls_cert_file_set = lookold->tls_cert_file_set; 741 if (lookold->tls_cert_file != NULL) { 742 looknew->tls_cert_file = isc_mem_strdup(mctx, 743 lookold->tls_cert_file); 744 } 745 746 looknew->showbadcookie = lookold->showbadcookie; 747 looknew->showbadvers = lookold->showbadvers; 748 looknew->sendcookie = lookold->sendcookie; 749 looknew->seenbadcookie = lookold->seenbadcookie; 750 looknew->badcookie = lookold->badcookie; 751 looknew->cookie = lookold->cookie; 752 if (lookold->ednsopts != NULL) { 753 cloneopts(looknew, lookold); 754 } else { 755 looknew->ednsopts = NULL; 756 looknew->ednsoptscnt = 0; 757 } 758 looknew->ednsneg = lookold->ednsneg; 759 looknew->padding = lookold->padding; 760 looknew->multiline = lookold->multiline; 761 looknew->nottl = lookold->nottl; 762 looknew->noclass = lookold->noclass; 763 looknew->onesoa = lookold->onesoa; 764 looknew->use_usec = lookold->use_usec; 765 looknew->nocrypto = lookold->nocrypto; 766 looknew->ttlunits = lookold->ttlunits; 767 looknew->expandaaaa = lookold->expandaaaa; 768 looknew->qr = lookold->qr; 769 looknew->idnin = lookold->idnin; 770 looknew->idnout = lookold->idnout; 771 looknew->udpsize = lookold->udpsize; 772 looknew->edns = lookold->edns; 773 looknew->original_edns = lookold->original_edns; 774 looknew->recurse = lookold->recurse; 775 looknew->aaonly = lookold->aaonly; 776 looknew->adflag = lookold->adflag; 777 looknew->cdflag = lookold->cdflag; 778 looknew->coflag = lookold->coflag; 779 looknew->raflag = lookold->raflag; 780 looknew->tcflag = lookold->tcflag; 781 looknew->print_unknown_format = lookold->print_unknown_format; 782 looknew->zflag = lookold->zflag; 783 looknew->setqid = lookold->setqid; 784 looknew->qid = lookold->qid; 785 looknew->ns_search_only = lookold->ns_search_only; 786 looknew->tcp_mode = lookold->tcp_mode; 787 looknew->tcp_mode_set = lookold->tcp_mode_set; 788 looknew->tls_mode = lookold->tls_mode; 789 looknew->comments = lookold->comments; 790 looknew->stats = lookold->stats; 791 looknew->section_question = lookold->section_question; 792 looknew->section_answer = lookold->section_answer; 793 looknew->section_authority = lookold->section_authority; 794 looknew->section_additional = lookold->section_additional; 795 looknew->origin = lookold->origin; 796 looknew->retries = lookold->retries; 797 looknew->tsigctx = NULL; 798 looknew->need_search = lookold->need_search; 799 looknew->done_as_is = lookold->done_as_is; 800 looknew->rrcomments = lookold->rrcomments; 801 looknew->fuzzing = lookold->fuzzing; 802 looknew->fuzztime = lookold->fuzztime; 803 looknew->proxy_mode = lookold->proxy_mode; 804 looknew->proxy_plain = lookold->proxy_plain; 805 looknew->proxy_local = lookold->proxy_local; 806 looknew->proxy_src_addr = lookold->proxy_src_addr; 807 looknew->proxy_dst_addr = lookold->proxy_dst_addr; 808 809 if (lookold->ecs_addr != NULL) { 810 looknew->ecs_addr = isc_mem_get(mctx, 811 sizeof(*looknew->ecs_addr)); 812 memmove(looknew->ecs_addr, lookold->ecs_addr, 813 sizeof(*looknew->ecs_addr)); 814 } 815 816 dns_name_copy(dns_fixedname_name(&lookold->fdomain), 817 dns_fixedname_name(&looknew->fdomain)); 818 819 if (servers) { 820 if (lookold->tls_ctx_cache != NULL) { 821 isc_tlsctx_cache_detach(&looknew->tls_ctx_cache); 822 isc_tlsctx_cache_attach(lookold->tls_ctx_cache, 823 &looknew->tls_ctx_cache); 824 } 825 clone_server_list(lookold->my_server_list, 826 &looknew->my_server_list); 827 } 828 829 isc_refcount_init(&looknew->references, 1); 830 831 looknew->magic = DIG_LOOKUP_MAGIC; 832 833 return looknew; 834 } 835 836 /*% 837 * Requeue a lookup for further processing, perhaps copying the server 838 * list. The new lookup structure is returned to the caller, and is 839 * queued for processing. If servers are not cloned in the requeue, they 840 * must be added before allowing the current event to complete, since the 841 * completion of the event may result in the next entry on the lookup 842 * queue getting run. 843 */ 844 dig_lookup_t * 845 requeue_lookup(dig_lookup_t *lookold, bool servers) { 846 dig_lookup_t *looknew = NULL; 847 848 debug("requeue_lookup()"); 849 850 lookup_counter++; 851 if (lookup_counter > LOOKUP_LIMIT) { 852 fatal("too many lookups"); 853 } 854 855 looknew = clone_lookup(lookold, servers); 856 INSIST(looknew != NULL); 857 858 debug("before insertion, init@%p -> %p, new@%p -> %p", lookold, 859 lookold->link.next, looknew, looknew->link.next); 860 ISC_LIST_PREPEND(lookup_list, looknew, link); 861 debug("after insertion, init -> %p, new = %p, new -> %p", lookold, 862 looknew, looknew->link.next); 863 return looknew; 864 } 865 866 void 867 setup_text_key(void) { 868 isc_result_t result; 869 dns_name_t keyname; 870 isc_buffer_t secretbuf; 871 unsigned int secretsize; 872 unsigned char *secretstore; 873 874 debug("setup_text_key()"); 875 isc_buffer_allocate(mctx, &namebuf, MXNAME); 876 dns_name_init(&keyname, NULL); 877 isc_buffer_putstr(namebuf, keynametext); 878 secretsize = (unsigned int)strlen(keysecret) * 3 / 4; 879 secretstore = isc_mem_allocate(mctx, secretsize); 880 isc_buffer_init(&secretbuf, secretstore, secretsize); 881 result = isc_base64_decodestring(keysecret, &secretbuf); 882 if (result != ISC_R_SUCCESS) { 883 goto failure; 884 } 885 886 secretsize = isc_buffer_usedlength(&secretbuf); 887 888 if (hmac_alg == DST_ALG_UNKNOWN) { 889 result = DST_R_UNSUPPORTEDALG; 890 goto failure; 891 } 892 893 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf); 894 if (result != ISC_R_SUCCESS) { 895 goto failure; 896 } 897 898 result = dns_tsigkey_create(&keyname, hmac_alg, secretstore, 899 (int)secretsize, mctx, &tsigkey); 900 failure: 901 if (result != ISC_R_SUCCESS) { 902 printf(";; Couldn't create key %s: %s\n", keynametext, 903 isc_result_totext(result)); 904 } else { 905 dst_key_setbits(tsigkey->key, digestbits); 906 } 907 908 isc_mem_free(mctx, secretstore); 909 dns_name_invalidate(&keyname); 910 isc_buffer_free(&namebuf); 911 } 912 913 static isc_result_t 914 parse_uint_helper(uint32_t *uip, const char *value, uint32_t max, 915 const char *desc, int base) { 916 uint32_t n; 917 isc_result_t result = isc_parse_uint32(&n, value, base); 918 if (result == ISC_R_SUCCESS && n > max) { 919 result = ISC_R_RANGE; 920 } 921 if (result != ISC_R_SUCCESS) { 922 printf("invalid %s '%s': %s\n", desc, value, 923 isc_result_totext(result)); 924 return result; 925 } 926 *uip = n; 927 return ISC_R_SUCCESS; 928 } 929 930 isc_result_t 931 parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) { 932 return parse_uint_helper(uip, value, max, desc, 10); 933 } 934 935 isc_result_t 936 parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc) { 937 return parse_uint_helper(uip, value, max, desc, 0); 938 } 939 940 static uint32_t 941 parse_bits(char *arg, const char *desc, uint32_t max) { 942 isc_result_t result; 943 uint32_t tmp; 944 945 result = parse_uint(&tmp, arg, max, desc); 946 if (result != ISC_R_SUCCESS) { 947 fatal("couldn't parse digest bits"); 948 } 949 tmp = (tmp + 7) & ~0x7U; 950 return tmp; 951 } 952 953 isc_result_t 954 parse_netprefix(isc_sockaddr_t **sap, const char *value) { 955 isc_result_t result = ISC_R_SUCCESS; 956 isc_sockaddr_t *sa = NULL; 957 struct in_addr in4; 958 struct in6_addr in6; 959 uint32_t prefix_length = 0xffffffff; 960 char *slash = NULL; 961 bool parsed = false; 962 bool prefix_parsed = false; 963 char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")]; 964 965 REQUIRE(sap != NULL && *sap == NULL); 966 967 if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf)) { 968 fatal("invalid prefix '%s'\n", value); 969 } 970 971 sa = isc_mem_get(mctx, sizeof(*sa)); 972 *sa = (isc_sockaddr_t){ .length = 0 }; 973 974 if (strcmp(buf, "0") == 0) { 975 sa->type.sa.sa_family = AF_UNSPEC; 976 prefix_length = 0; 977 goto done; 978 } 979 980 slash = strchr(buf, '/'); 981 if (slash != NULL) { 982 *slash = '\0'; 983 result = isc_parse_uint32(&prefix_length, slash + 1, 10); 984 if (result != ISC_R_SUCCESS) { 985 fatal("invalid prefix length in '%s': %s\n", value, 986 isc_result_totext(result)); 987 } 988 prefix_parsed = true; 989 } 990 991 if (inet_pton(AF_INET6, buf, &in6) == 1) { 992 parsed = true; 993 isc_sockaddr_fromin6(sa, &in6, 0); 994 if (prefix_length > 128) { 995 prefix_length = 128; 996 } 997 } else if (inet_pton(AF_INET, buf, &in4) == 1) { 998 parsed = true; 999 isc_sockaddr_fromin(sa, &in4, 0); 1000 if (prefix_length > 32) { 1001 prefix_length = 32; 1002 } 1003 } else if (prefix_parsed) { 1004 int i; 1005 1006 for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) { 1007 strlcat(buf, ".0", sizeof(buf)); 1008 if (inet_pton(AF_INET, buf, &in4) == 1) { 1009 parsed = true; 1010 isc_sockaddr_fromin(sa, &in4, 0); 1011 break; 1012 } 1013 } 1014 1015 if (prefix_length > 32) { 1016 prefix_length = 32; 1017 } 1018 } 1019 1020 if (!parsed) { 1021 fatal("invalid address '%s'", value); 1022 } 1023 1024 done: 1025 sa->length = prefix_length; 1026 *sap = sa; 1027 1028 return ISC_R_SUCCESS; 1029 } 1030 1031 /* 1032 * Parse HMAC algorithm specification 1033 */ 1034 void 1035 parse_hmac(const char *algname) { 1036 char buf[20]; 1037 size_t len; 1038 1039 REQUIRE(algname != NULL); 1040 1041 len = strlen(algname); 1042 if (len >= sizeof(buf)) { 1043 fatal("unknown key type '%.*s'", (int)len, algname); 1044 } 1045 strlcpy(buf, algname, sizeof(buf)); 1046 1047 digestbits = 0; 1048 1049 if (strcasecmp(buf, "hmac-md5") == 0) { 1050 hmac_alg = DST_ALG_HMACMD5; 1051 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { 1052 hmac_alg = DST_ALG_HMACMD5; 1053 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); 1054 } else if (strcasecmp(buf, "hmac-sha1") == 0) { 1055 hmac_alg = DST_ALG_HMACSHA1; 1056 digestbits = 0; 1057 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { 1058 hmac_alg = DST_ALG_HMACSHA1; 1059 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160); 1060 } else if (strcasecmp(buf, "hmac-sha224") == 0) { 1061 hmac_alg = DST_ALG_HMACSHA224; 1062 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { 1063 hmac_alg = DST_ALG_HMACSHA224; 1064 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224); 1065 } else if (strcasecmp(buf, "hmac-sha256") == 0) { 1066 hmac_alg = DST_ALG_HMACSHA256; 1067 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { 1068 hmac_alg = DST_ALG_HMACSHA256; 1069 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256); 1070 } else if (strcasecmp(buf, "hmac-sha384") == 0) { 1071 hmac_alg = DST_ALG_HMACSHA384; 1072 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { 1073 hmac_alg = DST_ALG_HMACSHA384; 1074 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384); 1075 } else if (strcasecmp(buf, "hmac-sha512") == 0) { 1076 hmac_alg = DST_ALG_HMACSHA512; 1077 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { 1078 hmac_alg = DST_ALG_HMACSHA512; 1079 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512); 1080 } else { 1081 fprintf(stderr, 1082 ";; Warning, ignoring " 1083 "invalid TSIG algorithm %s\n", 1084 buf); 1085 } 1086 } 1087 1088 /* 1089 * Get a key from a named.conf format keyfile 1090 */ 1091 static isc_result_t 1092 read_confkey(void) { 1093 cfg_parser_t *pctx = NULL; 1094 cfg_obj_t *file = NULL; 1095 const cfg_obj_t *keyobj = NULL; 1096 const cfg_obj_t *secretobj = NULL; 1097 const cfg_obj_t *algorithmobj = NULL; 1098 const char *keyname; 1099 const char *secretstr; 1100 const char *algorithm; 1101 isc_result_t result; 1102 1103 if (!isc_file_exists(keyfile)) { 1104 return ISC_R_FILENOTFOUND; 1105 } 1106 1107 result = cfg_parser_create(mctx, NULL, &pctx); 1108 if (result != ISC_R_SUCCESS) { 1109 goto cleanup; 1110 } 1111 1112 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &file); 1113 if (result != ISC_R_SUCCESS) { 1114 goto cleanup; 1115 } 1116 1117 result = cfg_map_get(file, "key", &keyobj); 1118 if (result != ISC_R_SUCCESS) { 1119 goto cleanup; 1120 } 1121 1122 (void)cfg_map_get(keyobj, "secret", &secretobj); 1123 (void)cfg_map_get(keyobj, "algorithm", &algorithmobj); 1124 if (secretobj == NULL || algorithmobj == NULL) { 1125 fatal("key must have algorithm and secret"); 1126 } 1127 1128 keyname = cfg_obj_asstring(cfg_map_getname(keyobj)); 1129 secretstr = cfg_obj_asstring(secretobj); 1130 algorithm = cfg_obj_asstring(algorithmobj); 1131 1132 strlcpy(keynametext, keyname, sizeof(keynametext)); 1133 strlcpy(keysecret, secretstr, sizeof(keysecret)); 1134 parse_hmac(algorithm); 1135 setup_text_key(); 1136 1137 cleanup: 1138 if (pctx != NULL) { 1139 if (file != NULL) { 1140 cfg_obj_destroy(pctx, &file); 1141 } 1142 cfg_parser_destroy(&pctx); 1143 } 1144 1145 return result; 1146 } 1147 1148 void 1149 setup_file_key(void) { 1150 isc_result_t result; 1151 dst_key_t *dstkey = NULL; 1152 1153 debug("setup_file_key()"); 1154 1155 if (sig0key != NULL) { 1156 dst_key_free(&sig0key); 1157 } 1158 1159 /* Try reading the key from a K* pair */ 1160 result = dst_key_fromnamedfile( 1161 keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); 1162 1163 /* If that didn't work, try reading it as a session.key keyfile */ 1164 if (result != ISC_R_SUCCESS) { 1165 result = read_confkey(); 1166 if (result == ISC_R_SUCCESS) { 1167 return; 1168 } 1169 } 1170 1171 if (result != ISC_R_SUCCESS) { 1172 fprintf(stderr, "Couldn't read key from %s: %s\n", keyfile, 1173 isc_result_totext(result)); 1174 goto failure; 1175 } 1176 1177 switch (dst_key_alg(dstkey)) { 1178 case DST_ALG_HMACMD5: 1179 case DST_ALG_HMACSHA1: 1180 case DST_ALG_HMACSHA224: 1181 case DST_ALG_HMACSHA256: 1182 case DST_ALG_HMACSHA384: 1183 case DST_ALG_HMACSHA512: 1184 hmac_alg = dst_key_alg(dstkey); 1185 break; 1186 default: 1187 dst_key_attach(dstkey, &sig0key); 1188 dst_key_free(&dstkey); 1189 return; 1190 } 1191 1192 if (dstkey != NULL) { 1193 result = dns_tsigkey_createfromkey( 1194 dst_key_name(dstkey), hmac_alg, dstkey, false, false, 1195 NULL, 0, 0, mctx, &tsigkey); 1196 if (result != ISC_R_SUCCESS) { 1197 printf(";; Couldn't create key %s: %s\n", keynametext, 1198 isc_result_totext(result)); 1199 } 1200 } 1201 1202 failure: 1203 if (dstkey != NULL) { 1204 dst_key_free(&dstkey); 1205 } 1206 } 1207 1208 static dig_searchlist_t * 1209 make_searchlist_entry(char *domain) { 1210 dig_searchlist_t *search; 1211 search = isc_mem_allocate(mctx, sizeof(*search)); 1212 strlcpy(search->origin, domain, MXNAME); 1213 search->origin[MXNAME - 1] = 0; 1214 ISC_LINK_INIT(search, link); 1215 return search; 1216 } 1217 1218 static void 1219 clear_searchlist(void) { 1220 dig_searchlist_t *search; 1221 while ((search = ISC_LIST_HEAD(search_list)) != NULL) { 1222 ISC_LIST_UNLINK(search_list, search, link); 1223 isc_mem_free(mctx, search); 1224 } 1225 } 1226 1227 static void 1228 create_search_list(irs_resconf_t *resconf) { 1229 irs_resconf_searchlist_t *list; 1230 irs_resconf_search_t *entry; 1231 dig_searchlist_t *search; 1232 1233 debug("create_search_list()"); 1234 clear_searchlist(); 1235 1236 list = irs_resconf_getsearchlist(resconf); 1237 for (entry = ISC_LIST_HEAD(*list); entry != NULL; 1238 entry = ISC_LIST_NEXT(entry, link)) 1239 { 1240 search = make_searchlist_entry(entry->domain); 1241 ISC_LIST_APPEND(search_list, search, link); 1242 } 1243 } 1244 1245 /*% 1246 * Append 'addr' to the list of servers to be queried. This function is only 1247 * called when no server addresses are explicitly specified and either libirs 1248 * returns an empty list of servers to use or none of the addresses returned by 1249 * libirs are usable due to the specified address family restrictions. 1250 */ 1251 static void 1252 add_fallback_nameserver(const char *addr) { 1253 dig_server_t *server = make_server(addr, addr); 1254 ISC_LINK_INIT(server, link); 1255 ISC_LIST_APPEND(server_list, server, link); 1256 } 1257 1258 /*% 1259 * Setup the system as a whole, reading key information and resolv.conf 1260 * settings. 1261 */ 1262 void 1263 setup_system(bool ipv4only, bool ipv6only) { 1264 irs_resconf_t *resconf = NULL; 1265 isc_result_t result; 1266 1267 debug("setup_system()"); 1268 1269 if (ipv4only) { 1270 if (have_ipv4) { 1271 isc_net_disableipv6(); 1272 have_ipv6 = false; 1273 } else { 1274 fatal("can't find IPv4 networking"); 1275 } 1276 } 1277 1278 if (ipv6only) { 1279 if (have_ipv6) { 1280 isc_net_disableipv4(); 1281 have_ipv4 = false; 1282 } else { 1283 fatal("can't find IPv6 networking"); 1284 } 1285 } 1286 1287 result = irs_resconf_load(mctx, RESOLV_CONF, &resconf); 1288 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { 1289 fatal("parse of %s failed", RESOLV_CONF); 1290 } 1291 1292 create_search_list(resconf); 1293 if (ndots == -1) { 1294 ndots = irs_resconf_getndots(resconf); 1295 debug("ndots is %d.", ndots); 1296 } 1297 if (timeout == 0) { 1298 timeout = irs_resconf_gettimeout(resconf); 1299 debug("timeout is %d.", timeout); 1300 } 1301 if (tries == -1) { 1302 tries = irs_resconf_getattempts(resconf); 1303 if (tries == 0) { 1304 tries = 3; 1305 } 1306 debug("retries is %d.", tries); 1307 } 1308 1309 /* If user doesn't specify server use nameservers from resolv.conf. */ 1310 if (ISC_LIST_EMPTY(server_list)) { 1311 get_server_list(resconf); 1312 } 1313 1314 /* If we don't find a nameserver fall back to localhost */ 1315 if (ISC_LIST_EMPTY(server_list)) { 1316 if (have_ipv6) { 1317 add_fallback_nameserver("::1"); 1318 } 1319 if (have_ipv4) { 1320 add_fallback_nameserver("127.0.0.1"); 1321 } 1322 } 1323 1324 irs_resconf_destroy(&resconf); 1325 1326 if (keyfile[0] != 0) { 1327 setup_file_key(); 1328 } else if (keysecret[0] != 0) { 1329 setup_text_key(); 1330 } 1331 1332 isc_nonce_buf(cookie_secret, sizeof(cookie_secret)); 1333 } 1334 1335 /*% 1336 * Override the search list derived from resolv.conf by 'domain'. 1337 */ 1338 void 1339 set_search_domain(char *domain) { 1340 dig_searchlist_t *search; 1341 1342 clear_searchlist(); 1343 search = make_searchlist_entry(domain); 1344 ISC_LIST_APPEND(search_list, search, link); 1345 } 1346 1347 /*% 1348 * Setup the ISC and DNS libraries for use by the system. 1349 */ 1350 void 1351 setup_libs(void) { 1352 isc_result_t result; 1353 isc_logconfig_t *logconfig = NULL; 1354 1355 debug("setup_libs()"); 1356 1357 result = isc_net_probeipv4(); 1358 if (result == ISC_R_SUCCESS) { 1359 have_ipv4 = true; 1360 } 1361 1362 result = isc_net_probeipv6(); 1363 if (result == ISC_R_SUCCESS) { 1364 have_ipv6 = true; 1365 } 1366 if (!have_ipv6 && !have_ipv4) { 1367 fatal("can't find either v4 or v6 networking"); 1368 } 1369 1370 isc_managers_create(&mctx, 1, &loopmgr, &netmgr); 1371 1372 isc_log_create(mctx, &lctx, &logconfig); 1373 isc_log_setcontext(lctx); 1374 dns_log_init(lctx); 1375 dns_log_setcontext(lctx); 1376 1377 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); 1378 check_result(result, "isc_log_usechannel"); 1379 1380 isc_log_setdebuglevel(lctx, 0); 1381 1382 isc_mem_setname(mctx, "dig"); 1383 mainloop = isc_loop_main(loopmgr); 1384 1385 result = dst_lib_init(mctx, NULL); 1386 check_result(result, "dst_lib_init"); 1387 is_dst_up = true; 1388 } 1389 1390 typedef struct dig_ednsoptname { 1391 uint32_t code; 1392 const char *name; 1393 } dig_ednsoptname_t; 1394 1395 dig_ednsoptname_t optnames[] = { 1396 { 1, "LLQ" }, /* draft-sekar-dns-llq */ 1397 { 2, "UPDATE-LEASE" }, /* draft-ietf-dnssd-update-lease */ 1398 { 2, "UL" }, /* draft-ietf-dnssd-update-lease */ 1399 { 3, "NSID" }, /* RFC 5001 */ 1400 { 5, "DAU" }, /* RFC 6975 */ 1401 { 6, "DHU" }, /* RFC 6975 */ 1402 { 7, "N3U" }, /* RFC 6975 */ 1403 { 8, "ECS" }, /* RFC 7871 */ 1404 { 9, "EXPIRE" }, /* RFC 7314 */ 1405 { 10, "COOKIE" }, /* RFC 7873 */ 1406 { 11, "KEEPALIVE" }, /* RFC 7828 */ 1407 { 12, "PADDING" }, /* RFC 7830 */ 1408 { 12, "PAD" }, /* shorthand */ 1409 { 13, "CHAIN" }, /* RFC 7901 */ 1410 { 14, "KEY-TAG" }, /* RFC 8145 */ 1411 { 15, "EDE" }, /* ietf-dnsop-extended-error-16 */ 1412 { 16, "CLIENT-TAG" }, /* draft-bellis-dnsop-edns-tags */ 1413 { 17, "SERVER-TAG" }, /* draft-bellis-dnsop-edns-tags */ 1414 { 18, "REPORT-CHANNEL" }, /* RFC 9567 */ 1415 { 18, "RC" }, /* shorthand */ 1416 { 19, "ZONEVERSION" }, /* RFC 9660 */ 1417 { 26946, "DEVICEID" }, /* Brian Hartvigsen */ 1418 }; 1419 1420 #define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0])) 1421 1422 void 1423 save_opt(dig_lookup_t *lookup, char *code, char *value) { 1424 isc_result_t result; 1425 uint32_t num = 0; 1426 isc_buffer_t b; 1427 bool found = false; 1428 unsigned int i; 1429 1430 if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS) { 1431 fatal("too many ednsopts"); 1432 } 1433 1434 for (i = 0; i < N_EDNS_OPTNAMES; i++) { 1435 if (strcasecmp(code, optnames[i].name) == 0) { 1436 num = optnames[i].code; 1437 found = true; 1438 break; 1439 } 1440 } 1441 1442 if (!found) { 1443 result = parse_uint(&num, code, 65535, "ednsopt"); 1444 if (result != ISC_R_SUCCESS) { 1445 fatal("bad edns code point: %s", code); 1446 } 1447 } 1448 1449 if (lookup->ednsopts == NULL) { 1450 cloneopts(lookup, NULL); 1451 } 1452 INSIST(lookup->ednsopts != NULL); 1453 1454 if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL) { 1455 isc_mem_free(mctx, lookup->ednsopts[lookup->ednsoptscnt].value); 1456 } 1457 1458 lookup->ednsopts[lookup->ednsoptscnt].code = num; 1459 lookup->ednsopts[lookup->ednsoptscnt].length = 0; 1460 lookup->ednsopts[lookup->ednsoptscnt].value = NULL; 1461 1462 if (value != NULL) { 1463 char *buf; 1464 buf = isc_mem_allocate(mctx, strlen(value) / 2 + 1); 1465 isc_buffer_init(&b, buf, (unsigned int)strlen(value) / 2 + 1); 1466 result = isc_hex_decodestring(value, &b); 1467 check_result(result, "isc_hex_decodestring"); 1468 lookup->ednsopts[lookup->ednsoptscnt].value = 1469 isc_buffer_base(&b); 1470 lookup->ednsopts[lookup->ednsoptscnt].length = 1471 isc_buffer_usedlength(&b); 1472 } 1473 1474 lookup->ednsoptscnt++; 1475 } 1476 1477 /*% 1478 * Add EDNS0 option record to a message. Currently, the only supported 1479 * options are UDP buffer size, the DO bit, and EDNS options 1480 * (e.g., NSID, COOKIE, client-subnet) 1481 */ 1482 static void 1483 add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags, 1484 dns_ednsopt_t *opts, size_t count) { 1485 dns_rdataset_t *rdataset = NULL; 1486 isc_result_t result; 1487 1488 debug("add_opt()"); 1489 result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags, 1490 opts, count); 1491 check_result(result, "dns_message_buildopt"); 1492 result = dns_message_setopt(msg, rdataset); 1493 check_result(result, "dns_message_setopt"); 1494 } 1495 1496 /*% 1497 * Add a question section to a message, asking for the specified name, 1498 * type, and class. 1499 */ 1500 static void 1501 add_question(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, 1502 dns_rdatatype_t rdtype) { 1503 dns_rdataset_t *rdataset; 1504 1505 debug("add_question()"); 1506 rdataset = NULL; 1507 dns_message_gettemprdataset(message, &rdataset); 1508 dns_rdataset_makequestion(rdataset, rdclass, rdtype); 1509 ISC_LIST_APPEND(name->list, rdataset, link); 1510 } 1511 1512 /*% 1513 * Check if we're done with all the queued lookups, which is true iff 1514 * all sockets, sends, and recvs are accounted for (counters == 0), 1515 * and the lookup list is empty. 1516 * If we are done, pass control back out to dighost_shutdown() (which is 1517 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as 1518 * a whole or reseed the lookup list. 1519 */ 1520 static void 1521 check_if_done(void) { 1522 dig_lookup_t *lookup = NULL; 1523 1524 debug("check_if_done()"); 1525 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full"); 1526 1527 lookup = ISC_LIST_HEAD(lookup_list); 1528 while (lookup != NULL) { 1529 dig_lookup_t *next = NULL; 1530 debug("pending lookup %p", lookup); 1531 next = ISC_LIST_NEXT(lookup, link); 1532 lookup = next; 1533 } 1534 1535 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL && 1536 isc_refcount_current(&sendcount) == 0) 1537 { 1538 INSIST(isc_refcount_current(&recvcount) == 0); 1539 debug("shutting down"); 1540 dighost_shutdown(); 1541 1542 if (current_lookup == NULL && keep != NULL) { 1543 isc_nmhandle_detach(&keep); 1544 } 1545 } 1546 } 1547 1548 /*% 1549 * Check if we're done with all the queries in the lookup, except for 1550 * the `except_q` query (can be NULL if no exception is required). 1551 * Expects `l` to be a valid and locked lookup. 1552 */ 1553 static bool 1554 check_if_queries_done(dig_lookup_t *l, dig_query_t *except_q) { 1555 dig_query_t *q = ISC_LIST_HEAD(l->q); 1556 1557 debug("check_if_queries_done(%p)", l); 1558 1559 while (q != NULL) { 1560 if (!q->started || isc_refcount_current(&q->references) > 1) { 1561 if (!q->canceled && q != except_q) { 1562 debug("there is a pending query %p", q); 1563 return false; 1564 } 1565 } 1566 q = ISC_LIST_NEXT(q, link); 1567 } 1568 1569 return true; 1570 } 1571 1572 static void 1573 _destroy_lookup(dig_lookup_t *lookup) { 1574 dig_server_t *s; 1575 void *ptr; 1576 1577 REQUIRE(lookup != NULL); 1578 REQUIRE(ISC_LIST_EMPTY(lookup->q)); 1579 1580 debug("destroy_lookup"); 1581 1582 isc_refcount_destroy(&lookup->references); 1583 1584 s = ISC_LIST_HEAD(lookup->my_server_list); 1585 while (s != NULL) { 1586 debug("freeing server %p belonging to %p", s, lookup); 1587 ptr = s; 1588 s = ISC_LIST_NEXT(s, link); 1589 ISC_LIST_DEQUEUE(lookup->my_server_list, (dig_server_t *)ptr, 1590 link); 1591 isc_mem_free(mctx, ptr); 1592 } 1593 if (lookup->sendmsg != NULL) { 1594 dns_message_detach(&lookup->sendmsg); 1595 } 1596 if (lookup->querysig != NULL) { 1597 debug("freeing buffer %p", lookup->querysig); 1598 isc_buffer_free(&lookup->querysig); 1599 } 1600 if (lookup->sendspace != NULL) { 1601 isc_mem_put(mctx, lookup->sendspace, COMMSIZE); 1602 } 1603 1604 if (lookup->tsigctx != NULL) { 1605 dst_context_destroy(&lookup->tsigctx); 1606 } 1607 1608 if (lookup->ecs_addr != NULL) { 1609 isc_mem_put(mctx, lookup->ecs_addr, sizeof(*lookup->ecs_addr)); 1610 } 1611 1612 if (lookup->ednsopts != NULL) { 1613 size_t i; 1614 for (i = 0; i < EDNSOPT_OPTIONS; i++) { 1615 if (lookup->ednsopts[i].value != NULL) { 1616 isc_mem_free(mctx, lookup->ednsopts[i].value); 1617 } 1618 } 1619 isc_mem_free(mctx, lookup->ednsopts); 1620 } 1621 1622 if (lookup->https_path) { 1623 isc_mem_free(mctx, lookup->https_path); 1624 } 1625 1626 if (lookup->tls_ctx_cache != NULL) { 1627 isc_tlsctx_cache_detach(&lookup->tls_ctx_cache); 1628 } 1629 1630 if (lookup->tls_ca_file != NULL) { 1631 isc_mem_free(mctx, lookup->tls_ca_file); 1632 } 1633 1634 if (lookup->tls_hostname != NULL) { 1635 isc_mem_free(mctx, lookup->tls_hostname); 1636 } 1637 1638 if (lookup->tls_key_file != NULL) { 1639 isc_mem_free(mctx, lookup->tls_key_file); 1640 } 1641 1642 if (lookup->tls_cert_file != NULL) { 1643 isc_mem_free(mctx, lookup->tls_cert_file); 1644 } 1645 1646 isc_mem_free(mctx, lookup); 1647 } 1648 1649 #define lookup_attach(s, t) _lookup_attach(s, t, __FILE__, __LINE__) 1650 static void 1651 _lookup_attach(dig_lookup_t *lookup, dig_lookup_t **lookupp, const char *file, 1652 unsigned int line) { 1653 REQUIRE(DIG_VALID_LOOKUP(lookup)); 1654 REQUIRE(lookupp != NULL && *lookupp == NULL); 1655 1656 debug("%s:%u:lookup_attach(%p) = %" PRIuFAST32, file, line, lookup, 1657 isc_refcount_current(&lookup->references) + 1); 1658 1659 (void)isc_refcount_increment(&lookup->references); 1660 1661 *lookupp = lookup; 1662 } 1663 1664 #define lookup_detach(l) _lookup_detach(l, __FILE__, __LINE__) 1665 static void 1666 _lookup_detach(dig_lookup_t **lookupp, const char *file, unsigned int line) { 1667 REQUIRE(DIG_VALID_LOOKUP(*lookupp)); 1668 1669 dig_lookup_t *lookup = *lookupp; 1670 *lookupp = NULL; 1671 1672 debug("%s:%u:lookup_detach(%p) = %" PRIuFAST32, file, line, lookup, 1673 isc_refcount_current(&lookup->references) - 1); 1674 1675 if (isc_refcount_decrement(&lookup->references) == 1) { 1676 _destroy_lookup(lookup); 1677 if (lookup == current_lookup) { 1678 current_lookup = NULL; 1679 start_lookup(); 1680 } 1681 } 1682 } 1683 1684 void 1685 destroy_lookup(dig_lookup_t *lookup) { 1686 REQUIRE(DIG_VALID_LOOKUP(lookup)); 1687 1688 REQUIRE(isc_refcount_decrement(&lookup->references) == 1); 1689 _destroy_lookup(lookup); 1690 } 1691 1692 /*% 1693 * Destroy a query when we're done with it. WARNING: This routine 1694 * WILL invalidate the query pointer. 1695 */ 1696 static void 1697 destroy_query(dig_query_t *query, const char *file, unsigned int line) { 1698 debug("%s:%u:destroy_query(%p) = %" PRIuFAST32, file, line, query, 1699 isc_refcount_current(&query->references)); 1700 1701 isc_refcount_destroy(&query->references); 1702 1703 lookup_detach(&query->lookup); 1704 1705 INSIST(query->recvspace != NULL); 1706 1707 isc_mem_put(mctx, query->recvspace, COMMSIZE); 1708 isc_mem_put(mctx, query->tmpsendspace, COMMSIZE); 1709 1710 query->magic = 0; 1711 isc_mem_free(mctx, query); 1712 } 1713 1714 #define query_attach(s, t) _query_attach(s, t, __FILE__, __LINE__) 1715 1716 static void 1717 _query_attach(dig_query_t *source, dig_query_t **targetp, const char *file, 1718 unsigned int line) { 1719 REQUIRE(DIG_VALID_QUERY(source)); 1720 REQUIRE(targetp != NULL && *targetp == NULL); 1721 1722 debug("%s:%u:query_attach(%p) = %" PRIuFAST32, file, line, source, 1723 isc_refcount_current(&source->references) + 1); 1724 1725 (void)isc_refcount_increment(&source->references); 1726 1727 *targetp = source; 1728 } 1729 1730 #define query_detach(q) _query_detach(q, __FILE__, __LINE__) 1731 1732 static void 1733 _query_detach(dig_query_t **queryp, const char *file, unsigned int line) { 1734 dig_query_t *query = NULL; 1735 dig_lookup_t *lookup = NULL; 1736 1737 REQUIRE(DIG_VALID_QUERY(*queryp)); 1738 1739 query = *queryp; 1740 *queryp = NULL; 1741 1742 lookup = query->lookup; 1743 1744 if (lookup->current_query == query) { 1745 query_detach(&lookup->current_query); 1746 } 1747 1748 debug("%s:%u:query_detach(%p) = %" PRIuFAST32, file, line, query, 1749 isc_refcount_current(&query->references) - 1); 1750 1751 if (isc_refcount_decrement(&query->references) == 1) { 1752 INSIST(query->readhandle == NULL); 1753 INSIST(query->sendhandle == NULL); 1754 1755 if (ISC_LINK_LINKED(query, link)) { 1756 ISC_LIST_UNLINK(lookup->q, query, link); 1757 } 1758 destroy_query(query, file, line); 1759 } 1760 } 1761 1762 /*% 1763 * If we can, start the next lookup in the queue running. 1764 * This assumes that the lookup on the head of the queue hasn't been 1765 * started yet. It also removes the lookup from the head of the queue, 1766 * setting the current_lookup pointer pointing to it. 1767 */ 1768 void 1769 start_lookup(void) { 1770 debug("start_lookup()"); 1771 1772 if (cancel_now) { 1773 return; 1774 } 1775 1776 /* 1777 * If there's a current lookup running, we really shouldn't get 1778 * here. 1779 */ 1780 INSIST(current_lookup == NULL); 1781 1782 current_lookup = ISC_LIST_HEAD(lookup_list); 1783 1784 /* 1785 * Put the current lookup somewhere so cancel_all can find it 1786 */ 1787 if (current_lookup != NULL) { 1788 /* 1789 * Formally, we should attach the lookup to the current_lookup 1790 * and detach it from the lookup_list, but it would be one 1791 * attach and one detach. 1792 */ 1793 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link); 1794 if (setup_lookup(current_lookup)) { 1795 do_lookup(current_lookup); 1796 } else if (next_origin(current_lookup)) { 1797 lookup_detach(¤t_lookup); 1798 start_lookup(); 1799 } 1800 } else { 1801 check_if_done(); 1802 } 1803 } 1804 1805 /*% 1806 * If we can, clear the current lookup and start the next one running. 1807 * (Note that while the reference count of current_lookup may be 1808 * decremented, current_lookup will not be set to NULL.) 1809 */ 1810 static void 1811 clear_current_lookup(void) { 1812 dig_lookup_t *lookup = current_lookup; 1813 1814 INSIST(!free_now); 1815 1816 debug("clear_current_lookup()"); 1817 1818 if (lookup == NULL) { 1819 debug("current_lookup is already detached"); 1820 return; 1821 } 1822 1823 if (lookup->cleared) { 1824 debug("current_lookup is already cleared"); 1825 return; 1826 } 1827 1828 if (ISC_LIST_HEAD(lookup->q) != NULL) { 1829 debug("still have a worker"); 1830 return; 1831 } 1832 1833 lookup->cleared = true; 1834 debug("lookup cleared"); 1835 1836 lookup_detach(&lookup); 1837 } 1838 1839 /*% 1840 * Create and queue a new lookup as a followup to the current lookup, 1841 * based on the supplied message and section. This is used in trace and 1842 * name server search modes to start a new lookup using servers from 1843 * NS records in a reply. Returns the number of followup lookups made. 1844 */ 1845 static int 1846 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) { 1847 dig_lookup_t *lookup = NULL; 1848 dig_server_t *srv = NULL; 1849 dns_rdataset_t *rdataset = NULL; 1850 dns_rdata_t rdata = DNS_RDATA_INIT; 1851 dns_name_t *name = NULL; 1852 isc_result_t result; 1853 bool success = false; 1854 int numLookups = 0; 1855 int num; 1856 isc_result_t lresult, addresses_result; 1857 char bad_namestr[DNS_NAME_FORMATSIZE]; 1858 dns_name_t *domain; 1859 bool horizontal = false, bad = false; 1860 1861 INSIST(!free_now); 1862 1863 debug("following up %s", query->lookup->textname); 1864 1865 addresses_result = ISC_R_SUCCESS; 1866 bad_namestr[0] = '\0'; 1867 for (result = dns_message_firstname(msg, section); 1868 result == ISC_R_SUCCESS; 1869 result = dns_message_nextname(msg, section)) 1870 { 1871 name = NULL; 1872 dns_message_currentname(msg, section, &name); 1873 1874 if (section == DNS_SECTION_AUTHORITY) { 1875 rdataset = NULL; 1876 result = dns_message_findtype(name, dns_rdatatype_soa, 1877 0, &rdataset); 1878 if (result == ISC_R_SUCCESS) { 1879 return 0; 1880 } 1881 } 1882 rdataset = NULL; 1883 result = dns_message_findtype(name, dns_rdatatype_ns, 0, 1884 &rdataset); 1885 if (result != ISC_R_SUCCESS) { 1886 continue; 1887 } 1888 1889 debug("found NS set"); 1890 1891 if (query->lookup->trace && !query->lookup->trace_root) { 1892 dns_namereln_t namereln; 1893 unsigned int nlabels; 1894 int order; 1895 1896 domain = dns_fixedname_name(&query->lookup->fdomain); 1897 namereln = dns_name_fullcompare(name, domain, &order, 1898 &nlabels); 1899 if (namereln == dns_namereln_equal) { 1900 if (!horizontal) { 1901 dighost_warning("BAD (HORIZONTAL) " 1902 "REFERRAL"); 1903 } 1904 horizontal = true; 1905 } else if (namereln != dns_namereln_subdomain) { 1906 if (!bad) { 1907 dighost_warning("BAD REFERRAL"); 1908 } 1909 bad = true; 1910 continue; 1911 } 1912 } 1913 1914 for (result = dns_rdataset_first(rdataset); 1915 result == ISC_R_SUCCESS; 1916 result = dns_rdataset_next(rdataset)) 1917 { 1918 char namestr[DNS_NAME_FORMATSIZE]; 1919 dns_rdata_ns_t ns; 1920 1921 if (query->lookup->trace_root && 1922 query->lookup->nsfound >= MXSERV) 1923 { 1924 break; 1925 } 1926 1927 dns_rdataset_current(rdataset, &rdata); 1928 1929 query->lookup->nsfound++; 1930 result = dns_rdata_tostruct(&rdata, &ns, NULL); 1931 check_result(result, "dns_rdata_tostruct"); 1932 dns_name_format(&ns.name, namestr, sizeof(namestr)); 1933 dns_rdata_freestruct(&ns); 1934 1935 /* Initialize lookup if we've not yet */ 1936 debug("found NS %s", namestr); 1937 if (!success) { 1938 success = true; 1939 lookup_counter++; 1940 lookup = requeue_lookup(query->lookup, false); 1941 cancel_lookup(query->lookup); 1942 lookup->doing_xfr = false; 1943 if (!lookup->trace_root && 1944 section == DNS_SECTION_ANSWER) 1945 { 1946 lookup->trace = false; 1947 } else { 1948 lookup->trace = query->lookup->trace; 1949 } 1950 lookup->ns_search_only = 1951 query->lookup->ns_search_only; 1952 lookup->trace_root = false; 1953 if (lookup->ns_search_only) { 1954 lookup->recurse = false; 1955 } 1956 domain = dns_fixedname_name(&lookup->fdomain); 1957 dns_name_copy(name, domain); 1958 lookup->edns = lookup->original_edns; 1959 } 1960 debug("adding server %s", namestr); 1961 num = getaddresses(lookup, namestr, &lresult); 1962 if (lresult != ISC_R_SUCCESS) { 1963 printf("couldn't get address for '%s': %s\n", 1964 namestr, isc_result_totext(lresult)); 1965 if (addresses_result == ISC_R_SUCCESS) { 1966 addresses_result = lresult; 1967 strlcpy(bad_namestr, namestr, 1968 sizeof(bad_namestr)); 1969 } 1970 } 1971 numLookups += num; 1972 dns_rdata_reset(&rdata); 1973 } 1974 } 1975 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) { 1976 fatal("couldn't get address for '%s': %s", bad_namestr, 1977 isc_result_totext(result)); 1978 } 1979 1980 if (lookup == NULL && section == DNS_SECTION_ANSWER && 1981 (query->lookup->trace || query->lookup->ns_search_only)) 1982 { 1983 return followup_lookup(msg, query, DNS_SECTION_AUTHORITY); 1984 } 1985 1986 /* 1987 * Randomize the order the nameserver will be tried. 1988 */ 1989 if (numLookups > 1) { 1990 uint32_t i, j; 1991 dig_serverlist_t my_server_list; 1992 dig_server_t *next; 1993 1994 ISC_LIST_INIT(my_server_list); 1995 1996 i = numLookups; 1997 for (srv = ISC_LIST_HEAD(lookup->my_server_list); srv != NULL; 1998 srv = ISC_LIST_HEAD(lookup->my_server_list)) 1999 { 2000 INSIST(i > 0); 2001 j = isc_random_uniform(i); 2002 next = ISC_LIST_NEXT(srv, link); 2003 while (j-- > 0 && next != NULL) { 2004 srv = next; 2005 next = ISC_LIST_NEXT(srv, link); 2006 } 2007 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link); 2008 ISC_LIST_APPEND(my_server_list, srv, link); 2009 i--; 2010 } 2011 ISC_LIST_APPENDLIST(lookup->my_server_list, my_server_list, 2012 link); 2013 } 2014 2015 return numLookups; 2016 } 2017 2018 /*% 2019 * Create and queue a new lookup using the next origin from the search 2020 * list, read in setup_system(). 2021 * 2022 * Return true iff there was another searchlist entry. 2023 */ 2024 static bool 2025 next_origin(dig_lookup_t *oldlookup) { 2026 dig_lookup_t *newlookup; 2027 dig_searchlist_t *search; 2028 dns_fixedname_t fixed; 2029 dns_name_t *name; 2030 isc_result_t result; 2031 2032 INSIST(!free_now); 2033 2034 debug("next_origin()"); 2035 debug("following up %s", oldlookup->textname); 2036 2037 if (!usesearch) { 2038 /* 2039 * We're not using a search list, so don't even think 2040 * about finding the next entry. 2041 */ 2042 return false; 2043 } 2044 2045 /* 2046 * Check for a absolute name or ndots being met. 2047 */ 2048 name = dns_fixedname_initname(&fixed); 2049 result = dns_name_fromstring(name, oldlookup->textname, NULL, 0, NULL); 2050 if (result == ISC_R_SUCCESS && 2051 (dns_name_isabsolute(name) || 2052 (int)dns_name_countlabels(name) > ndots)) 2053 { 2054 return false; 2055 } 2056 2057 if (oldlookup->origin == NULL && !oldlookup->need_search) { 2058 /* 2059 * Then we just did rootorg; there's nothing left. 2060 */ 2061 return false; 2062 } 2063 if (oldlookup->origin == NULL && oldlookup->need_search) { 2064 newlookup = requeue_lookup(oldlookup, true); 2065 newlookup->origin = ISC_LIST_HEAD(search_list); 2066 newlookup->need_search = false; 2067 } else { 2068 search = ISC_LIST_NEXT(oldlookup->origin, link); 2069 if (search == NULL && oldlookup->done_as_is) { 2070 return false; 2071 } 2072 newlookup = requeue_lookup(oldlookup, true); 2073 newlookup->origin = search; 2074 } 2075 cancel_lookup(oldlookup); 2076 return true; 2077 } 2078 2079 /*% 2080 * Insert an SOA record into the sendmessage in a lookup. Used for 2081 * creating IXFR queries. 2082 */ 2083 static void 2084 insert_soa(dig_lookup_t *lookup) { 2085 isc_result_t result; 2086 dns_rdata_soa_t soa; 2087 dns_rdata_t *rdata = NULL; 2088 dns_rdatalist_t *rdatalist = NULL; 2089 dns_rdataset_t *rdataset = NULL; 2090 dns_name_t *soaname = NULL; 2091 2092 debug("insert_soa()"); 2093 soa.mctx = mctx; 2094 soa.serial = lookup->ixfr_serial; 2095 soa.refresh = 0; 2096 soa.retry = 0; 2097 soa.expire = 0; 2098 soa.minimum = 0; 2099 soa.common.rdclass = lookup->rdclass; 2100 soa.common.rdtype = dns_rdatatype_soa; 2101 2102 dns_name_init(&soa.origin, NULL); 2103 dns_name_init(&soa.contact, NULL); 2104 2105 dns_name_clone(dns_rootname, &soa.origin); 2106 dns_name_clone(dns_rootname, &soa.contact); 2107 2108 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore, 2109 sizeof(lookup->rdatastore)); 2110 2111 dns_message_gettemprdata(lookup->sendmsg, &rdata); 2112 2113 result = dns_rdata_fromstruct(rdata, lookup->rdclass, dns_rdatatype_soa, 2114 &soa, &lookup->rdatabuf); 2115 check_result(result, "isc_rdata_fromstruct"); 2116 2117 dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist); 2118 2119 dns_message_gettemprdataset(lookup->sendmsg, &rdataset); 2120 2121 dns_rdatalist_init(rdatalist); 2122 rdatalist->type = dns_rdatatype_soa; 2123 rdatalist->rdclass = lookup->rdclass; 2124 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 2125 2126 dns_rdatalist_tordataset(rdatalist, rdataset); 2127 2128 dns_message_gettempname(lookup->sendmsg, &soaname); 2129 dns_name_clone(lookup->name, soaname); 2130 ISC_LIST_INIT(soaname->list); 2131 ISC_LIST_APPEND(soaname->list, rdataset, link); 2132 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY); 2133 } 2134 2135 static void 2136 compute_cookie(unsigned char *clientcookie, size_t len) { 2137 /* XXXMPA need to fix, should be per server. */ 2138 INSIST(len >= 8U); 2139 memmove(clientcookie, cookie_secret, 8); 2140 } 2141 2142 #define new_query(l, s, u) _new_query(l, s, u, __FILE__, __LINE__) 2143 2144 static dig_query_t * 2145 _new_query(dig_lookup_t *lookup, char *servname, char *userarg, 2146 const char *file, unsigned int line) { 2147 dig_query_t *query = NULL; 2148 2149 query = isc_mem_allocate(mctx, sizeof(dig_query_t)); 2150 debug("create query %p linked to lookup %p", query, lookup); 2151 *query = (dig_query_t){ .sendbuf = lookup->renderbuf, 2152 .servname = servname, 2153 .userarg = userarg, 2154 .warn_id = true, 2155 .recvspace = isc_mem_get(mctx, COMMSIZE), 2156 .tmpsendspace = isc_mem_get(mctx, COMMSIZE) }; 2157 2158 lookup_attach(lookup, &query->lookup); 2159 2160 isc_refcount_init(&query->references, 1); 2161 2162 debug("%s:%u:new_query(%p) = %" PRIuFAST32, file, line, query, 2163 isc_refcount_current(&query->references)); 2164 2165 if (query->recvspace == NULL) { 2166 fatal("memory allocation failure"); 2167 } 2168 if (query->tmpsendspace == NULL) { 2169 fatal("memory allocation failure"); 2170 } 2171 2172 isc_time_settoepoch(&query->time_sent); 2173 isc_time_settoepoch(&query->time_recv); 2174 2175 ISC_LINK_INIT(query, clink); 2176 ISC_LINK_INIT(query, link); 2177 2178 query->magic = DIG_QUERY_MAGIC; 2179 return query; 2180 } 2181 2182 /*% 2183 * Setup the supplied lookup structure, making it ready to start sending 2184 * queries to servers. Create and initialize the message to be sent as 2185 * well as the query structures and buffer space for the replies. If the 2186 * server list is empty, clone it from the system default list. 2187 */ 2188 bool 2189 setup_lookup(dig_lookup_t *lookup) { 2190 isc_result_t result; 2191 unsigned int len; 2192 dig_server_t *serv; 2193 dig_query_t *query; 2194 isc_buffer_t b; 2195 dns_compress_t cctx; 2196 char store[MXNAME]; 2197 char ecsbuf[20]; 2198 char cookiebuf[256]; 2199 char *origin = NULL; 2200 char *textname = NULL; 2201 2202 REQUIRE(lookup != NULL); 2203 2204 #ifdef HAVE_LIBIDN2 2205 char idn_origin[MXNAME], idn_textname[MXNAME]; 2206 #endif /* HAVE_LIBIDN2 */ 2207 2208 INSIST(!free_now); 2209 2210 debug("setup_lookup(%p)", lookup); 2211 2212 dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, 2213 &lookup->sendmsg); 2214 2215 if (lookup->new_search) { 2216 debug("resetting lookup counter."); 2217 lookup_counter = 0; 2218 } 2219 2220 if (ISC_LIST_EMPTY(lookup->my_server_list)) { 2221 debug("cloning server list"); 2222 clone_server_list(server_list, &lookup->my_server_list); 2223 } 2224 dns_message_gettempname(lookup->sendmsg, &lookup->name); 2225 2226 isc_buffer_init(&lookup->namebuf, lookup->name_space, 2227 sizeof(lookup->name_space)); 2228 isc_buffer_init(&lookup->onamebuf, lookup->oname_space, 2229 sizeof(lookup->oname_space)); 2230 2231 /* 2232 * We cannot convert `textname' and `origin' separately. 2233 * `textname' doesn't contain TLD, but local mapping needs 2234 * TLD. 2235 */ 2236 textname = lookup->textname; 2237 #ifdef HAVE_LIBIDN2 2238 if (lookup->idnin) { 2239 idn_input(textname, idn_textname, sizeof(idn_textname)); 2240 debug("idn_textname: %s", idn_textname); 2241 textname = idn_textname; 2242 } 2243 #endif /* HAVE_LIBIDN2 */ 2244 2245 /* 2246 * If the name has too many dots, force the origin to be NULL 2247 * (which produces an absolute lookup). Otherwise, take the origin 2248 * we have if there's one in the struct already. If it's NULL, 2249 * take the first entry in the searchlist iff either usesearch 2250 * is TRUE or we got a domain line in the resolv.conf file. 2251 */ 2252 if (lookup->new_search) { 2253 if ((count_dots(textname) >= ndots) || !usesearch) { 2254 lookup->origin = NULL; /* Force abs lookup */ 2255 lookup->done_as_is = true; 2256 lookup->need_search = usesearch; 2257 } else if (lookup->origin == NULL && usesearch) { 2258 lookup->origin = ISC_LIST_HEAD(search_list); 2259 lookup->need_search = false; 2260 } 2261 } 2262 2263 if (lookup->origin != NULL) { 2264 debug("trying origin %s", lookup->origin->origin); 2265 dns_message_gettempname(lookup->sendmsg, &lookup->oname); 2266 /* XXX Helper funct to conv char* to name? */ 2267 origin = lookup->origin->origin; 2268 #ifdef HAVE_LIBIDN2 2269 if (lookup->idnin) { 2270 idn_input(origin, idn_origin, sizeof(idn_origin)); 2271 debug("trying idn origin %s", idn_origin); 2272 origin = idn_origin; 2273 } 2274 #endif /* HAVE_LIBIDN2 */ 2275 len = (unsigned int)strlen(origin); 2276 isc_buffer_init(&b, origin, len); 2277 isc_buffer_add(&b, len); 2278 result = dns_name_fromtext(lookup->oname, &b, dns_rootname, 0, 2279 &lookup->onamebuf); 2280 if (result != ISC_R_SUCCESS) { 2281 dns_message_puttempname(lookup->sendmsg, &lookup->name); 2282 dns_message_puttempname(lookup->sendmsg, 2283 &lookup->oname); 2284 fatal("'%s' is not in legal name syntax (%s)", origin, 2285 isc_result_totext(result)); 2286 } 2287 if (lookup->trace && lookup->trace_root) { 2288 dns_name_clone(dns_rootname, lookup->name); 2289 } else { 2290 dns_fixedname_t fixed; 2291 dns_name_t *name; 2292 2293 name = dns_fixedname_initname(&fixed); 2294 len = (unsigned int)strlen(textname); 2295 isc_buffer_init(&b, textname, len); 2296 isc_buffer_add(&b, len); 2297 result = dns_name_fromtext(name, &b, NULL, 0, NULL); 2298 if (result == ISC_R_SUCCESS) { 2299 if (!dns_name_isabsolute(name)) { 2300 result = dns_name_concatenate( 2301 name, lookup->oname, 2302 lookup->name, &lookup->namebuf); 2303 } else { 2304 dns_name_copy(name, lookup->name); 2305 } 2306 } 2307 if (result != ISC_R_SUCCESS) { 2308 dns_message_puttempname(lookup->sendmsg, 2309 &lookup->name); 2310 dns_message_puttempname(lookup->sendmsg, 2311 &lookup->oname); 2312 if (result == DNS_R_NAMETOOLONG) { 2313 return false; 2314 } 2315 fatal("'%s' is not in legal name syntax (%s)", 2316 lookup->textname, 2317 isc_result_totext(result)); 2318 } 2319 } 2320 dns_message_puttempname(lookup->sendmsg, &lookup->oname); 2321 } else { 2322 debug("using root origin"); 2323 if (lookup->trace && lookup->trace_root) { 2324 dns_name_clone(dns_rootname, lookup->name); 2325 } else { 2326 len = (unsigned int)strlen(textname); 2327 isc_buffer_init(&b, textname, len); 2328 isc_buffer_add(&b, len); 2329 result = dns_name_fromtext(lookup->name, &b, 2330 dns_rootname, 0, 2331 &lookup->namebuf); 2332 if (result != ISC_R_SUCCESS) { 2333 dns_message_puttempname(lookup->sendmsg, 2334 &lookup->name); 2335 warn("'%s' is not a legal name (%s)", 2336 lookup->textname, 2337 isc_result_totext(result)); 2338 #if TARGET_OS_IPHONE 2339 clear_current_lookup(); 2340 return false; 2341 #else /* if TARGET_OS_IPHONE */ 2342 cleanup_openssl_refs(); 2343 digexit(); 2344 #endif /* if TARGET_OS_IPHONE */ 2345 } 2346 } 2347 } 2348 dns_name_format(lookup->name, store, sizeof(store)); 2349 dighost_trying(store, lookup); 2350 INSIST(dns_name_isabsolute(lookup->name)); 2351 2352 lookup->sendmsg->id = (dns_messageid_t)isc_random16(); 2353 lookup->sendmsg->opcode = lookup->opcode; 2354 lookup->msgcounter = 0; 2355 2356 /* 2357 * If this is a trace request, completely disallow recursion after 2358 * looking up the root name servers, since it's meaningless for traces. 2359 */ 2360 if ((lookup->trace || lookup->ns_search_only) && !lookup->trace_root) { 2361 lookup->recurse = false; 2362 } 2363 2364 if (lookup->recurse && lookup->rdtype != dns_rdatatype_axfr && 2365 lookup->rdtype != dns_rdatatype_ixfr) 2366 { 2367 debug("recursive query"); 2368 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; 2369 } 2370 2371 /* XXX aaflag */ 2372 if (lookup->aaonly) { 2373 debug("AA query"); 2374 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA; 2375 } 2376 2377 if (lookup->adflag) { 2378 debug("AD query"); 2379 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD; 2380 } 2381 2382 if (lookup->cdflag) { 2383 debug("CD query"); 2384 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD; 2385 } 2386 2387 if (lookup->raflag) { 2388 debug("RA query"); 2389 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RA; 2390 } 2391 2392 if (lookup->tcflag) { 2393 debug("TC query"); 2394 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_TC; 2395 } 2396 2397 if (lookup->zflag) { 2398 debug("Z query"); 2399 lookup->sendmsg->flags |= 0x0040U; 2400 } 2401 2402 if (lookup->setqid) { 2403 debug("set QID"); 2404 lookup->sendmsg->id = lookup->qid; 2405 } 2406 2407 dns_message_addname(lookup->sendmsg, lookup->name, 2408 DNS_SECTION_QUESTION); 2409 2410 if (lookup->trace && lookup->trace_root) { 2411 lookup->qrdtype = lookup->rdtype; 2412 lookup->rdtype = dns_rdatatype_ns; 2413 } 2414 2415 if ((lookup->rdtype == dns_rdatatype_axfr) || 2416 (lookup->rdtype == dns_rdatatype_ixfr)) 2417 { 2418 /* 2419 * Force TCP mode if we're doing an axfr. 2420 */ 2421 if (lookup->rdtype == dns_rdatatype_axfr) { 2422 lookup->doing_xfr = true; 2423 lookup->tcp_mode = true; 2424 } else if (lookup->tcp_mode) { 2425 lookup->doing_xfr = true; 2426 } 2427 } 2428 2429 if (!lookup->header_only) { 2430 add_question(lookup->sendmsg, lookup->name, lookup->rdclass, 2431 lookup->rdtype); 2432 } 2433 2434 /* add_soa */ 2435 if (lookup->rdtype == dns_rdatatype_ixfr) { 2436 insert_soa(lookup); 2437 } 2438 2439 /* XXX Insist this? */ 2440 lookup->tsigctx = NULL; 2441 lookup->querysig = NULL; 2442 if (tsigkey != NULL) { 2443 debug("initializing keys"); 2444 result = dns_message_settsigkey(lookup->sendmsg, tsigkey); 2445 check_result(result, "dns_message_settsigkey"); 2446 } else if (sig0key != NULL) { 2447 debug("initializing keys"); 2448 result = dns_message_setsig0key(lookup->sendmsg, sig0key); 2449 check_result(result, "dns_message_setsig0key"); 2450 } 2451 2452 if (lookup->fuzzing) { 2453 lookup->sendmsg->fuzzing = true; 2454 lookup->sendmsg->fuzztime = lookup->fuzztime; 2455 } 2456 2457 lookup->sendspace = isc_mem_get(mctx, COMMSIZE); 2458 2459 dns_compress_init(&cctx, mctx, 0); 2460 2461 debug("starting to render the message"); 2462 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE); 2463 result = dns_message_renderbegin(lookup->sendmsg, &cctx, 2464 &lookup->renderbuf); 2465 check_result(result, "dns_message_renderbegin"); 2466 if (lookup->udpsize > -1 || lookup->dnssec || lookup->edns > -1 || 2467 lookup->ecs_addr != NULL) 2468 { 2469 #define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS) 2470 dns_ednsopt_t opts[MAXOPTS]; 2471 unsigned int flags; 2472 unsigned int i = 0; 2473 2474 /* 2475 * There can't be more than MAXOPTS options to send: 2476 * a maximum of EDNSOPT_OPTIONS set by +ednsopt 2477 * and DNS_EDNSOPTIONS set by other arguments 2478 * (+nsid, +cookie, etc). 2479 */ 2480 if (lookup->udpsize < 0) { 2481 lookup->udpsize = DEFAULT_EDNS_BUFSIZE; 2482 } 2483 if (lookup->edns < 0) { 2484 lookup->original_edns = lookup->edns = 2485 DEFAULT_EDNS_VERSION; 2486 } 2487 2488 if (lookup->nsid) { 2489 INSIST(i < MAXOPTS); 2490 opts[i].code = DNS_OPT_NSID; 2491 opts[i].length = 0; 2492 opts[i].value = NULL; 2493 i++; 2494 } 2495 2496 if (lookup->ecs_addr != NULL) { 2497 uint8_t addr[16]; 2498 uint16_t family = 0; 2499 uint32_t plen; 2500 struct sockaddr *sa; 2501 struct sockaddr_in *sin; 2502 struct sockaddr_in6 *sin6; 2503 size_t addrl; 2504 2505 sa = &lookup->ecs_addr->type.sa; 2506 plen = lookup->ecs_addr->length; 2507 2508 /* Round up prefix len to a multiple of 8 */ 2509 addrl = (plen + 7) / 8; 2510 2511 INSIST(i < MAXOPTS); 2512 opts[i].code = DNS_OPT_CLIENT_SUBNET; 2513 opts[i].length = (uint16_t)addrl + 4; 2514 check_result(result, "isc_buffer_allocate"); 2515 2516 /* 2517 * XXXMUKS: According to RFC7871, "If there is 2518 * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is 2519 * set to 0, then FAMILY SHOULD be set to the 2520 * transport over which the query is sent." 2521 * 2522 * However, at this point we don't know what 2523 * transport(s) we'll be using, so we can't 2524 * set the value now. For now, we're using 2525 * IPv4 as the default the +subnet option 2526 * used an IPv4 prefix, or for +subnet=0, 2527 * and IPv6 if the +subnet option used an 2528 * IPv6 prefix. 2529 * 2530 * (For future work: preserve the offset into 2531 * the buffer where the family field is; 2532 * that way we can update it in start_udp() 2533 * or start_tcp() once we know 2534 * what it outght to be.) 2535 */ 2536 switch (sa->sa_family) { 2537 case AF_UNSPEC: 2538 INSIST(plen == 0); 2539 family = 1; 2540 break; 2541 case AF_INET: 2542 INSIST(plen <= 32); 2543 family = 1; 2544 sin = (struct sockaddr_in *)sa; 2545 memmove(addr, &sin->sin_addr, addrl); 2546 break; 2547 case AF_INET6: 2548 INSIST(plen <= 128); 2549 family = 2; 2550 sin6 = (struct sockaddr_in6 *)sa; 2551 memmove(addr, &sin6->sin6_addr, addrl); 2552 break; 2553 default: 2554 UNREACHABLE(); 2555 } 2556 2557 isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf)); 2558 /* family */ 2559 isc_buffer_putuint16(&b, family); 2560 /* source prefix-length */ 2561 isc_buffer_putuint8(&b, plen); 2562 /* scope prefix-length */ 2563 isc_buffer_putuint8(&b, 0); 2564 2565 /* address */ 2566 if (addrl > 0) { 2567 /* Mask off last address byte */ 2568 if ((plen % 8) != 0) { 2569 addr[addrl - 1] &= ~0U 2570 << (8 - (plen % 8)); 2571 } 2572 isc_buffer_putmem(&b, addr, 2573 (unsigned int)addrl); 2574 } 2575 2576 opts[i].value = (uint8_t *)ecsbuf; 2577 i++; 2578 } 2579 2580 if (lookup->sendcookie) { 2581 INSIST(i < MAXOPTS); 2582 opts[i].code = DNS_OPT_COOKIE; 2583 if (lookup->cookie != NULL) { 2584 isc_buffer_init(&b, cookiebuf, 2585 sizeof(cookiebuf)); 2586 result = isc_hex_decodestring(lookup->cookie, 2587 &b); 2588 check_result(result, "isc_hex_decodestring"); 2589 opts[i].value = isc_buffer_base(&b); 2590 opts[i].length = isc_buffer_usedlength(&b); 2591 } else { 2592 compute_cookie(cookie, sizeof(cookie)); 2593 opts[i].length = 8; 2594 opts[i].value = cookie; 2595 } 2596 i++; 2597 } 2598 2599 if (lookup->expire) { 2600 INSIST(i < MAXOPTS); 2601 opts[i].code = DNS_OPT_EXPIRE; 2602 opts[i].length = 0; 2603 opts[i].value = NULL; 2604 i++; 2605 } 2606 2607 if (lookup->tcp_keepalive) { 2608 INSIST(i < MAXOPTS); 2609 opts[i].code = DNS_OPT_TCP_KEEPALIVE; 2610 opts[i].length = 0; 2611 opts[i].value = NULL; 2612 i++; 2613 } 2614 2615 if (lookup->ednsoptscnt != 0) { 2616 INSIST(i + lookup->ednsoptscnt <= MAXOPTS); 2617 memmove(&opts[i], lookup->ednsopts, 2618 sizeof(dns_ednsopt_t) * lookup->ednsoptscnt); 2619 i += lookup->ednsoptscnt; 2620 } 2621 2622 if (lookup->padding != 0 && (i >= MAXOPTS)) { 2623 debug("turned off padding because of EDNS overflow"); 2624 lookup->padding = 0; 2625 } 2626 2627 if (lookup->padding != 0) { 2628 INSIST(i < MAXOPTS); 2629 opts[i].code = DNS_OPT_PAD; 2630 opts[i].length = 0; 2631 opts[i].value = NULL; 2632 i++; 2633 dns_message_setpadding(lookup->sendmsg, 2634 lookup->padding); 2635 } 2636 2637 flags = lookup->ednsflags; 2638 flags &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO); 2639 if (lookup->dnssec) { 2640 flags |= DNS_MESSAGEEXTFLAG_DO; 2641 } 2642 if (lookup->coflag) { 2643 flags |= DNS_MESSAGEEXTFLAG_CO; 2644 } 2645 add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, flags, 2646 opts, i); 2647 } 2648 2649 result = dns_message_rendersection(lookup->sendmsg, 2650 DNS_SECTION_QUESTION, 0); 2651 check_result(result, "dns_message_rendersection"); 2652 result = dns_message_rendersection(lookup->sendmsg, 2653 DNS_SECTION_AUTHORITY, 0); 2654 check_result(result, "dns_message_rendersection"); 2655 result = dns_message_renderend(lookup->sendmsg); 2656 check_result(result, "dns_message_renderend"); 2657 debug("done rendering"); 2658 2659 dns_compress_invalidate(&cctx); 2660 2661 /* 2662 * Force TCP mode if the request is larger than 512 bytes. 2663 */ 2664 if (isc_buffer_usedlength(&lookup->renderbuf) > 512) { 2665 lookup->tcp_mode = true; 2666 } 2667 2668 lookup->pending = false; 2669 2670 for (serv = ISC_LIST_HEAD(lookup->my_server_list); serv != NULL; 2671 serv = ISC_LIST_NEXT(serv, link)) 2672 { 2673 query = new_query(lookup, serv->servername, serv->userarg); 2674 ISC_LIST_ENQUEUE(lookup->q, query, link); 2675 } 2676 2677 return true; 2678 } 2679 2680 /*% 2681 * NSSEARCH mode special mode handling function to start the next query in the 2682 * list. The lookup lock must be held by the caller. The function will detach 2683 * both the lookup and the query, and may cancel the lookup and clear the 2684 * current lookup. 2685 */ 2686 static void 2687 nssearch_next(dig_lookup_t *l, dig_query_t *q) { 2688 dig_query_t *next = ISC_LIST_NEXT(q, link); 2689 bool tcp_mode = l->tcp_mode; 2690 2691 INSIST(l->ns_search_only && !l->trace_root); 2692 INSIST(l == current_lookup); 2693 2694 if (next == NULL) { 2695 /* 2696 * If this is the last query, and if there was 2697 * not a single successful query in the whole 2698 * lookup, then treat the situation as an error, 2699 * cancel and clear the lookup. 2700 */ 2701 if (check_if_queries_done(l, q) && !l->ns_search_success) { 2702 dighost_error("NS servers could not be reached"); 2703 if (exitcode < 9) { 2704 exitcode = 9; 2705 } 2706 2707 cancel_lookup(l); 2708 query_detach(&q); 2709 lookup_detach(&l); 2710 clear_current_lookup(); 2711 } else { 2712 query_detach(&q); 2713 lookup_detach(&l); 2714 } 2715 } else { 2716 query_detach(&q); 2717 lookup_detach(&l); 2718 2719 debug("sending next, since searching"); 2720 if (tcp_mode) { 2721 start_tcp(next); 2722 } else { 2723 start_udp(next); 2724 } 2725 } 2726 } 2727 2728 /*% 2729 * Event handler for send completion. Track send counter, and clear out 2730 * the query if the send was canceled. 2731 */ 2732 static void 2733 send_done(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { 2734 dig_query_t *query = (dig_query_t *)arg; 2735 dig_lookup_t *l = NULL; 2736 2737 REQUIRE(DIG_VALID_QUERY(query)); 2738 INSIST(query->sendhandle != NULL); 2739 INSIST(handle == query->sendhandle); 2740 2741 debug("send_done(%p, %s, %p)", handle, isc_result_totext(eresult), arg); 2742 2743 isc_refcount_decrement0(&sendcount); 2744 debug("sendcount=%" PRIuFAST32, isc_refcount_current(&sendcount)); 2745 2746 INSIST(!free_now); 2747 2748 isc_nmhandle_detach(&query->sendhandle); 2749 2750 lookup_attach(query->lookup, &l); 2751 2752 if (eresult == ISC_R_CANCELED || query->canceled) { 2753 debug("send_done: cancel"); 2754 if (!query->canceled) { 2755 cancel_lookup(l); 2756 } 2757 query_detach(&query); 2758 lookup_detach(&l); 2759 check_if_done(); 2760 return; 2761 } else if (eresult != ISC_R_SUCCESS) { 2762 debug("send failed: %s", isc_result_totext(eresult)); 2763 } 2764 2765 if (l->ns_search_only && !l->trace_root) { 2766 nssearch_next(l, query); 2767 } else { 2768 query_detach(&query); 2769 lookup_detach(&l); 2770 } 2771 2772 check_if_done(); 2773 } 2774 2775 /*% 2776 * Cancel a lookup, sending canceling reads on all existing sockets. 2777 */ 2778 2779 static void 2780 _cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line) { 2781 dig_query_t *query, *next; 2782 2783 debug("%s:%u:%s()", file, line, __func__); 2784 query = ISC_LIST_HEAD(lookup->q); 2785 while (query != NULL) { 2786 REQUIRE(DIG_VALID_QUERY(query)); 2787 next = ISC_LIST_NEXT(query, link); 2788 ISC_LIST_DEQUEUE(lookup->q, query, link); 2789 debug("canceling pending query %p, belonging to %p", query, 2790 query->lookup); 2791 query->canceled = true; 2792 if (query->readhandle != NULL && 2793 !isc_nm_is_http_handle(query->readhandle)) 2794 { 2795 isc_nm_cancelread(query->readhandle); 2796 } 2797 query_detach(&query); 2798 query = next; 2799 } 2800 lookup->pending = false; 2801 lookup->retries = 0; 2802 check_if_done(); 2803 } 2804 2805 static inline const char * 2806 get_tls_sni_hostname(dig_query_t *query) { 2807 const char *hostname = query->lookup->tls_hostname_set 2808 ? query->lookup->tls_hostname 2809 : query->userarg; 2810 2811 if (query->lookup->tls_hostname_set) { 2812 return query->lookup->tls_hostname; 2813 } 2814 2815 if (isc_tls_valid_sni_hostname(hostname)) { 2816 return hostname; 2817 } 2818 2819 return NULL; 2820 } 2821 2822 static isc_tlsctx_t * 2823 get_create_tls_context(dig_query_t *query, const bool is_https, 2824 isc_tlsctx_client_session_cache_t **psess_cache) { 2825 isc_result_t result; 2826 isc_tlsctx_t *ctx = NULL, *found_ctx = NULL; 2827 isc_tls_cert_store_t *store = NULL, *found_store = NULL; 2828 char tlsctxname[ISC_SOCKADDR_FORMATSIZE]; 2829 const uint16_t family = isc_sockaddr_pf(&query->sockaddr) == PF_INET6 2830 ? AF_INET6 2831 : AF_INET; 2832 isc_tlsctx_cache_transport_t transport = 2833 is_https ? isc_tlsctx_cache_https : isc_tlsctx_cache_tls; 2834 const bool hostname_ignore_subject = !is_https; 2835 isc_tlsctx_client_session_cache_t *sess_cache = NULL, 2836 *found_sess_cache = NULL; 2837 2838 if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set) 2839 { 2840 return NULL; 2841 } 2842 2843 isc_sockaddr_format(&query->sockaddr, tlsctxname, sizeof(tlsctxname)); 2844 2845 result = isc_tlsctx_cache_find(query->lookup->tls_ctx_cache, tlsctxname, 2846 transport, family, &found_ctx, 2847 &found_store, &found_sess_cache); 2848 if (result != ISC_R_SUCCESS) { 2849 if (query->lookup->tls_ca_set) { 2850 if (found_store == NULL) { 2851 result = isc_tls_cert_store_create( 2852 query->lookup->tls_ca_file, &store); 2853 2854 if (result != ISC_R_SUCCESS) { 2855 goto failure; 2856 } 2857 } else { 2858 store = found_store; 2859 } 2860 } 2861 2862 result = isc_tlsctx_createclient(&ctx); 2863 if (result != ISC_R_SUCCESS) { 2864 goto failure; 2865 } 2866 2867 if (store != NULL) { 2868 const char *hostname = get_tls_sni_hostname(query); 2869 /* 2870 * According to RFC 8310, Subject field MUST NOT be 2871 * inspected when verifying hostname for DoT. Only 2872 * SubjectAltName must be checked. That is NOT the case 2873 * for HTTPS. 2874 */ 2875 result = isc_tlsctx_enable_peer_verification( 2876 ctx, false, store, hostname, 2877 hostname_ignore_subject); 2878 if (result != ISC_R_SUCCESS) { 2879 goto failure; 2880 } 2881 } 2882 2883 if (query->lookup->tls_key_file_set && 2884 query->lookup->tls_cert_file_set) 2885 { 2886 result = isc_tlsctx_load_certificate( 2887 ctx, query->lookup->tls_key_file, 2888 query->lookup->tls_cert_file); 2889 if (result != ISC_R_SUCCESS) { 2890 goto failure; 2891 } 2892 } 2893 2894 if (!is_https) { 2895 isc_tlsctx_enable_dot_client_alpn(ctx); 2896 } 2897 2898 #if HAVE_LIBNGHTTP2 2899 if (is_https) { 2900 isc_tlsctx_enable_http2client_alpn(ctx); 2901 } 2902 #endif /* HAVE_LIBNGHTTP2 */ 2903 2904 isc_tlsctx_client_session_cache_create( 2905 mctx, ctx, ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE, 2906 &sess_cache); 2907 2908 result = isc_tlsctx_cache_add( 2909 query->lookup->tls_ctx_cache, tlsctxname, transport, 2910 family, ctx, store, sess_cache, NULL, NULL, NULL); 2911 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2912 if (psess_cache != NULL) { 2913 INSIST(*psess_cache == NULL); 2914 *psess_cache = sess_cache; 2915 } 2916 return ctx; 2917 } 2918 2919 if (psess_cache != NULL) { 2920 INSIST(*psess_cache == NULL); 2921 *psess_cache = found_sess_cache; 2922 } 2923 2924 INSIST(!query->lookup->tls_ca_set || found_store != NULL); 2925 return found_ctx; 2926 failure: 2927 if (ctx != NULL) { 2928 isc_tlsctx_free(&ctx); 2929 } 2930 /* 2931 * The 'found_store' is being managed by the TLS context 2932 * cache. Thus, we should keep it as it is, as it will get 2933 * destroyed alongside the cache. As there is one store per 2934 * multiple TLS contexts, we need to handle store deletion in a 2935 * special way. 2936 */ 2937 if (store != NULL && store != found_store) { 2938 isc_tls_cert_store_free(&store); 2939 } 2940 return NULL; 2941 } 2942 2943 static void 2944 tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg); 2945 2946 /*% 2947 * Unlike start_udp, this can't be called multiple times with the same 2948 * query. When we retry TCP, we requeue the whole lookup, which should 2949 * start anew. 2950 */ 2951 static void 2952 start_tcp(dig_query_t *query) { 2953 isc_result_t result; 2954 dig_query_t *next = NULL; 2955 dig_query_t *connectquery = NULL; 2956 isc_tlsctx_t *tlsctx = NULL; 2957 bool tls_mode = false; 2958 isc_tlsctx_client_session_cache_t *sess_cache = NULL; 2959 int local_timeout; 2960 isc_nm_proxy_type_t proxy_type = ISC_NM_PROXY_NONE; 2961 isc_nm_proxyheader_info_t proxy_info = { 0 }; 2962 isc_nm_proxyheader_info_t *ppi = NULL; 2963 2964 REQUIRE(DIG_VALID_QUERY(query)); 2965 2966 debug("start_tcp(%p)", query); 2967 2968 query_attach(query, &query->lookup->current_query); 2969 2970 tls_mode = dig_lookup_is_tls(query->lookup); 2971 2972 /* 2973 * For TLS connections, we want to override the default 2974 * port number. 2975 */ 2976 if (!port_set) { 2977 if (tls_mode) { 2978 port = 853; 2979 } else if (query->lookup->https_mode && 2980 !query->lookup->http_plain) 2981 { 2982 port = 443; 2983 } else if (query->lookup->https_mode) { 2984 port = 80; 2985 } else { 2986 port = 53; 2987 } 2988 } 2989 2990 debug("query->servname = %s\n", query->servname); 2991 2992 result = get_address(query->servname, port, &query->sockaddr); 2993 if (result != ISC_R_SUCCESS) { 2994 /* 2995 * This servname doesn't have an address. Try the next server 2996 * by triggering an immediate 'timeout' (we lie, but the effect 2997 * is the same). 2998 */ 2999 force_next(query); 3000 return; 3001 } 3002 3003 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET6 && 3004 IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) 3005 { 3006 isc_netaddr_t netaddr; 3007 char buf[ISC_NETADDR_FORMATSIZE]; 3008 3009 isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); 3010 isc_netaddr_format(&netaddr, buf, sizeof(buf)); 3011 dighost_warning("Skipping mapped address '%s'", buf); 3012 3013 if (ISC_LINK_LINKED(query, link)) { 3014 next = ISC_LIST_NEXT(query, link); 3015 } else { 3016 next = NULL; 3017 } 3018 query_detach(&query); 3019 if (next == NULL) { 3020 dighost_warning("No acceptable nameservers"); 3021 clear_current_lookup(); 3022 } else { 3023 start_tcp(next); 3024 } 3025 return; 3026 } 3027 3028 INSIST(query->handle == NULL); 3029 3030 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) { 3031 query->handle = keep; 3032 launch_next_query(query); 3033 return; 3034 } else if (keep != NULL) { 3035 isc_nmhandle_detach(&keep); 3036 } 3037 3038 if (timeout != 0) { 3039 local_timeout = timeout * 1000; 3040 } else { 3041 local_timeout = TCP_TIMEOUT * 1000; 3042 } 3043 3044 if (!specified_source) { 3045 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4) 3046 { 3047 isc_sockaddr_any(&localaddr); 3048 } else { 3049 isc_sockaddr_any6(&localaddr); 3050 } 3051 } 3052 3053 if (query->lookup->proxy_mode) { 3054 proxy_type = ISC_NM_PROXY_PLAIN; 3055 if ((tls_mode || (query->lookup->https_mode && 3056 !query->lookup->http_plain)) && 3057 !query->lookup->proxy_plain) 3058 { 3059 proxy_type = ISC_NM_PROXY_ENCRYPTED; 3060 } 3061 if (!query->lookup->proxy_local) { 3062 isc_nm_proxyheader_info_init( 3063 &proxy_info, &query->lookup->proxy_src_addr, 3064 &query->lookup->proxy_dst_addr, NULL); 3065 ppi = &proxy_info; 3066 } 3067 } 3068 3069 REQUIRE(query != NULL); 3070 3071 query_attach(query, &connectquery); 3072 3073 if (tls_mode) { 3074 tlsctx = get_create_tls_context(connectquery, false, 3075 &sess_cache); 3076 if (tlsctx == NULL) { 3077 goto failure_tls; 3078 } 3079 isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr, 3080 tcp_connected, connectquery, 3081 local_timeout, tlsctx, 3082 get_tls_sni_hostname(query), sess_cache, 3083 proxy_type, ppi); 3084 #if HAVE_LIBNGHTTP2 3085 } else if (query->lookup->https_mode) { 3086 char uri[4096] = { 0 }; 3087 isc_nm_http_makeuri(!query->lookup->http_plain, 3088 &query->sockaddr, query->userarg, port, 3089 query->lookup->https_path, uri, 3090 sizeof(uri)); 3091 3092 if (!query->lookup->http_plain) { 3093 tlsctx = get_create_tls_context(connectquery, true, 3094 &sess_cache); 3095 if (tlsctx == NULL) { 3096 goto failure_tls; 3097 } 3098 } 3099 3100 isc_nm_httpconnect(netmgr, &localaddr, &query->sockaddr, uri, 3101 !query->lookup->https_get, tcp_connected, 3102 connectquery, tlsctx, 3103 get_tls_sni_hostname(query), sess_cache, 3104 local_timeout, proxy_type, ppi); 3105 #endif 3106 } else { 3107 isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr, 3108 tcp_connected, connectquery, 3109 local_timeout, NULL, NULL, NULL, 3110 proxy_type, ppi); 3111 } 3112 3113 return; 3114 3115 failure_tls: 3116 if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set) 3117 { 3118 dighost_warning( 3119 "both TLS client certificate and key file must be " 3120 "specified a the same time"); 3121 } else { 3122 dighost_warning("TLS context cannot be created"); 3123 } 3124 3125 if (ISC_LINK_LINKED(query, link)) { 3126 next = ISC_LIST_NEXT(query, link); 3127 } else { 3128 next = NULL; 3129 } 3130 query_detach(&connectquery); 3131 query_detach(&query); 3132 if (next == NULL) { 3133 clear_current_lookup(); 3134 } else { 3135 start_tcp(next); 3136 } 3137 } 3138 3139 static void 3140 print_query_size(dig_query_t *query) { 3141 if (!yaml) { 3142 printf(";; QUERY SIZE: %u\n\n", 3143 isc_buffer_usedlength(&query->lookup->renderbuf)); 3144 } 3145 } 3146 3147 static void 3148 send_udp(dig_query_t *query) { 3149 dig_query_t *sendquery = NULL; 3150 isc_region_t r; 3151 3152 query_attach(query, &sendquery); 3153 3154 isc_buffer_usedregion(&query->sendbuf, &r); 3155 debug("sending a request"); 3156 if (query->lookup->use_usec) { 3157 query->time_sent = isc_time_now_hires(); 3158 } else { 3159 query->time_sent = isc_time_now(); 3160 } 3161 3162 isc_nmhandle_attach(query->handle, &query->sendhandle); 3163 3164 isc_nm_send(query->handle, &r, send_done, sendquery); 3165 isc_refcount_increment0(&sendcount); 3166 debug("sendcount=%" PRIuFAST32, isc_refcount_current(&sendcount)); 3167 3168 /* XXX qrflag, print_query, etc... */ 3169 if (query->lookup->qr) { 3170 extrabytes = 0; 3171 dighost_printmessage(query, &query->lookup->renderbuf, 3172 query->lookup->sendmsg, true); 3173 if (query->lookup->stats) { 3174 print_query_size(query); 3175 } 3176 } 3177 } 3178 3179 static void 3180 udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { 3181 dig_query_t *query = (dig_query_t *)arg; 3182 dig_query_t *next = NULL; 3183 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 3184 dig_lookup_t *l = NULL; 3185 dig_query_t *readquery = NULL; 3186 int local_timeout = timeout * 1000; 3187 3188 REQUIRE(DIG_VALID_QUERY(query)); 3189 REQUIRE(query->handle == NULL); 3190 3191 debug("udp_ready()"); 3192 3193 query->started = true; 3194 3195 if (cancel_now) { 3196 query_detach(&query); 3197 return; 3198 } 3199 3200 INSIST(!free_now); 3201 3202 debug("udp_ready(%p, %s, %p)", handle, isc_result_totext(eresult), 3203 query); 3204 3205 lookup_attach(query->lookup, &l); 3206 3207 if (eresult == ISC_R_CANCELED || query->canceled) { 3208 debug("in cancel handler"); 3209 if (!query->canceled) { 3210 cancel_lookup(l); 3211 } 3212 query_detach(&query); 3213 lookup_detach(&l); 3214 clear_current_lookup(); 3215 return; 3216 } 3217 3218 if (eresult != ISC_R_SUCCESS) { 3219 debug("udp setup failed: %s", isc_result_totext(eresult)); 3220 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); 3221 dighost_warning("UDP setup with %s(%s) for %s failed: %s.", 3222 sockstr, query->servname, l->textname, 3223 isc_result_totext(eresult)); 3224 3225 /* 3226 * NSSEARCH mode: if the current query failed to start properly, 3227 * then send_done() will not be called, and we want to make sure 3228 * that the next query gets a chance to start in order to not 3229 * break the chain. 3230 */ 3231 if (l->ns_search_only && !l->trace_root) { 3232 nssearch_next(l, query); 3233 3234 check_if_done(); 3235 return; 3236 } 3237 3238 if (exitcode < 9) { 3239 exitcode = 9; 3240 } 3241 3242 if (l->retries > 1) { 3243 l->retries--; 3244 debug("making new UDP request, %d tries left", 3245 l->retries); 3246 requeue_lookup(l, true); 3247 next = NULL; 3248 } else if ((l->current_query != NULL) && 3249 (ISC_LINK_LINKED(l->current_query, link))) 3250 { 3251 next = ISC_LIST_NEXT(l->current_query, link); 3252 } else { 3253 next = NULL; 3254 } 3255 3256 query_detach(&query); 3257 if (next == NULL) { 3258 cancel_lookup(l); 3259 } 3260 lookup_detach(&l); 3261 3262 if (next != NULL) { 3263 start_udp(next); 3264 check_if_done(); 3265 } else { 3266 dighost_error("no servers could be reached"); 3267 clear_current_lookup(); 3268 } 3269 3270 return; 3271 } 3272 3273 exitcode = 0; 3274 3275 query_attach(query, &readquery); 3276 3277 debug("recving with lookup=%p, query=%p, handle=%p", query->lookup, 3278 query, handle); 3279 3280 query->handle = handle; 3281 isc_nmhandle_attach(handle, &query->readhandle); 3282 isc_refcount_increment0(&recvcount); 3283 debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount)); 3284 3285 if (local_timeout == 0) { 3286 local_timeout = UDP_TIMEOUT * 1000; 3287 } 3288 3289 debug("have local timeout of %d", local_timeout); 3290 isc_nmhandle_settimeout(handle, local_timeout); 3291 3292 isc_nm_read(handle, recv_done, readquery); 3293 send_udp(readquery); 3294 3295 query_detach(&query); 3296 lookup_detach(&l); 3297 } 3298 3299 /*% 3300 * Send a UDP packet to the remote nameserver, possible starting the 3301 * recv action as well. Also make sure that the timer is running and 3302 * is properly reset. 3303 */ 3304 static void 3305 start_udp(dig_query_t *query) { 3306 isc_result_t result; 3307 dig_query_t *next = NULL; 3308 dig_query_t *connectquery = NULL; 3309 3310 REQUIRE(DIG_VALID_QUERY(query)); 3311 3312 debug("start_udp(%p)", query); 3313 3314 query_attach(query, &query->lookup->current_query); 3315 debug("working on lookup %p, query %p", query->lookup, query); 3316 3317 if (query->handle != NULL) { 3318 launch_next_query(query); 3319 query_detach(&query); 3320 return; 3321 } 3322 3323 if (!port_set) { 3324 port = 53; 3325 } 3326 3327 result = get_address(query->servname, port, &query->sockaddr); 3328 if (result != ISC_R_SUCCESS) { 3329 /* This servname doesn't have an address. */ 3330 force_next(query); 3331 return; 3332 } 3333 3334 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET6 && 3335 IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) 3336 { 3337 isc_netaddr_t netaddr; 3338 char buf[ISC_NETADDR_FORMATSIZE]; 3339 3340 isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); 3341 isc_netaddr_format(&netaddr, buf, sizeof(buf)); 3342 dighost_warning("Skipping mapped address '%s'", buf); 3343 next = ISC_LIST_NEXT(query, link); 3344 query_detach(&query); 3345 if (next == NULL) { 3346 dighost_warning("No acceptable nameservers"); 3347 clear_current_lookup(); 3348 } else { 3349 start_udp(next); 3350 } 3351 return; 3352 } 3353 3354 if (!specified_source) { 3355 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4) 3356 { 3357 isc_sockaddr_any(&localaddr); 3358 } else { 3359 isc_sockaddr_any6(&localaddr); 3360 } 3361 } 3362 3363 query_attach(query, &connectquery); 3364 if (query->lookup->proxy_mode) { 3365 isc_nm_proxyheader_info_t proxy_info = { 0 }; 3366 isc_nm_proxyheader_info_t *ppi = NULL; 3367 if (!query->lookup->proxy_local) { 3368 isc_nm_proxyheader_info_init( 3369 &proxy_info, &query->lookup->proxy_src_addr, 3370 &query->lookup->proxy_dst_addr, NULL); 3371 ppi = &proxy_info; 3372 } 3373 isc_nm_proxyudpconnect(netmgr, &localaddr, &query->sockaddr, 3374 udp_ready, connectquery, 3375 (timeout ? timeout : UDP_TIMEOUT) * 1000, 3376 ppi); 3377 } else { 3378 isc_nm_udpconnect(netmgr, &localaddr, &query->sockaddr, 3379 udp_ready, connectquery, 3380 (timeout ? timeout : UDP_TIMEOUT) * 1000); 3381 } 3382 } 3383 3384 /*% 3385 * If there are more servers available for querying within 'lookup', initiate a 3386 * TCP or UDP query to the next available server and return true; otherwise, 3387 * return false. 3388 */ 3389 static bool 3390 try_next_server(dig_lookup_t *lookup) { 3391 dig_query_t *current_query, *next_query; 3392 3393 current_query = lookup->current_query; 3394 if (current_query == NULL || !ISC_LINK_LINKED(current_query, link)) { 3395 return false; 3396 } 3397 3398 next_query = ISC_LIST_NEXT(current_query, link); 3399 if (next_query == NULL) { 3400 return false; 3401 } 3402 3403 /* 3404 * We reach here only when either start_udp or start_tcp fails in 3405 * get_address(), at which point lookup's current_query must be attached 3406 * to the query that just failed. We need to detach it before trying 3407 * the next server similar to, e.g., recv_done(). 3408 */ 3409 query_detach(&lookup->current_query); 3410 3411 debug("trying next server..."); 3412 3413 if (lookup->tcp_mode) { 3414 start_tcp(next_query); 3415 } else { 3416 start_udp(next_query); 3417 } 3418 3419 return true; 3420 } 3421 3422 static void 3423 force_next(dig_query_t *query) { 3424 dig_lookup_t *l = NULL; 3425 3426 REQUIRE(DIG_VALID_QUERY(query)); 3427 3428 debug("force_next()"); 3429 3430 INSIST(!free_now); 3431 3432 if (cancel_now) { 3433 return; 3434 } 3435 3436 lookup_attach(query->lookup, &l); 3437 3438 if (try_next_server(l)) { 3439 lookup_detach(&l); 3440 return; 3441 } 3442 3443 /* 3444 * We don't retry this server unlike other similar cases such as 3445 * recv_done() because we're here due to get_address() failure, 3446 * which shouldn't be transient. 3447 */ 3448 3449 if (query->readhandle != NULL) { 3450 isc_refcount_decrement0(&recvcount); 3451 debug("recvcount=%" PRIuFAST32, 3452 isc_refcount_current(&recvcount)); 3453 } 3454 3455 if (l->ns_search_only) { 3456 isc_netaddr_t netaddr; 3457 char buf[ISC_NETADDR_FORMATSIZE]; 3458 3459 isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); 3460 isc_netaddr_format(&netaddr, buf, sizeof(buf)); 3461 3462 dighost_error("no response from %s", buf); 3463 } else { 3464 printf("%s", l->cmdline); 3465 dighost_error("no servers could be reached"); 3466 } 3467 3468 if (exitcode < 9) { 3469 exitcode = 9; 3470 } 3471 3472 query_detach(&query); 3473 cancel_lookup(l); 3474 lookup_detach(&l); 3475 clear_current_lookup(); 3476 } 3477 3478 /*% 3479 * For transfers that involve multiple recvs (XFR's in particular), 3480 * launch the next recv. 3481 */ 3482 static void 3483 launch_next_query(dig_query_t *query) { 3484 dig_query_t *readquery = NULL; 3485 int local_timeout = timeout * 1000; 3486 dig_lookup_t *l = NULL; 3487 isc_region_t r; 3488 bool xfr; 3489 3490 REQUIRE(DIG_VALID_QUERY(query)); 3491 INSIST(!free_now); 3492 3493 debug("launch_next_query()"); 3494 3495 lookup_attach(query->lookup, &l); 3496 3497 if (!l->pending) { 3498 debug("ignoring launch_next_query because !pending"); 3499 query_detach(&query); 3500 lookup_detach(&l); 3501 clear_current_lookup(); 3502 return; 3503 } 3504 3505 isc_nmhandle_attach(query->handle, &query->readhandle); 3506 isc_refcount_increment0(&recvcount); 3507 debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount)); 3508 3509 if (local_timeout == 0) { 3510 local_timeout = TCP_TIMEOUT * 1000; 3511 } 3512 3513 debug("have local timeout of %d", local_timeout); 3514 isc_nmhandle_settimeout(query->handle, local_timeout); 3515 3516 xfr = query->lookup->rdtype == dns_rdatatype_ixfr || 3517 query->lookup->rdtype == dns_rdatatype_axfr; 3518 if (xfr && 3519 isc_nm_socket_type(query->handle) == isc_nm_streamdnssocket && 3520 query->lookup->tls_mode) 3521 { 3522 isc_result_t result = isc_nm_xfr_checkperm(query->handle); 3523 if (result != ISC_R_SUCCESS) { 3524 dighost_error("zone transfers over the established TLS " 3525 "connection are not allowed: %s", 3526 isc_result_totext(result)); 3527 isc_refcount_decrement0(&recvcount); 3528 isc_nmhandle_detach(&query->readhandle); 3529 cancel_lookup(l); 3530 lookup_detach(&l); 3531 clear_current_lookup(); 3532 return; 3533 } 3534 } 3535 3536 query_attach(query, &readquery); 3537 3538 isc_nm_read(query->handle, recv_done, readquery); 3539 3540 if (!query->first_soa_rcvd) { 3541 dig_query_t *sendquery = NULL; 3542 debug("sending a request in launch_next_query"); 3543 if (query->lookup->use_usec) { 3544 query->time_sent = isc_time_now_hires(); 3545 } else { 3546 query->time_sent = isc_time_now(); 3547 } 3548 3549 query_attach(query, &sendquery); 3550 isc_buffer_usedregion(&query->sendbuf, &r); 3551 if (keep != NULL) { 3552 query->handle = keep; 3553 } 3554 3555 isc_nmhandle_attach(query->handle, &query->sendhandle); 3556 isc_nm_send(query->handle, &r, send_done, sendquery); 3557 isc_refcount_increment0(&sendcount); 3558 debug("sendcount=%" PRIuFAST32, 3559 isc_refcount_current(&sendcount)); 3560 3561 /* XXX qrflag, print_query, etc... */ 3562 if (l->qr) { 3563 extrabytes = 0; 3564 dighost_printmessage(query, &l->renderbuf, l->sendmsg, 3565 true); 3566 if (l->stats) { 3567 print_query_size(query); 3568 } 3569 } 3570 } 3571 3572 lookup_detach(&l); 3573 return; 3574 } 3575 3576 /*% 3577 * Event handler for TCP connect complete. Make sure the connection was 3578 * successful, then pass into launch_next_query to actually send the 3579 * question. 3580 */ 3581 static void 3582 tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { 3583 dig_query_t *query = (dig_query_t *)arg; 3584 dig_query_t *next = NULL; 3585 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 3586 dig_lookup_t *l = NULL; 3587 3588 REQUIRE(DIG_VALID_QUERY(query)); 3589 REQUIRE(query->handle == NULL); 3590 3591 debug("tcp_connected()"); 3592 3593 query->started = true; 3594 3595 if (cancel_now) { 3596 query_detach(&query); 3597 return; 3598 } 3599 3600 INSIST(!free_now); 3601 3602 debug("tcp_connected(%p, %s, %p)", handle, isc_result_totext(eresult), 3603 query); 3604 3605 if (eresult == ISC_R_SHUTTINGDOWN) { 3606 query_detach(&query); 3607 cancel_all(); 3608 return; 3609 } 3610 3611 lookup_attach(query->lookup, &l); 3612 3613 if (eresult == ISC_R_CANCELED || eresult == ISC_R_TLSBADPEERCERT || 3614 query->canceled) 3615 { 3616 debug("in cancel handler"); 3617 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); 3618 if (eresult == ISC_R_TLSBADPEERCERT) { 3619 dighost_warning( 3620 "TLS peer certificate verification for " 3621 "%s failed: %s", 3622 sockstr, 3623 isc_nm_verify_tls_peer_result_string(handle)); 3624 } else if (query->lookup->rdtype == dns_rdatatype_ixfr || 3625 query->lookup->rdtype == dns_rdatatype_axfr) 3626 { 3627 puts("; Transfer failed."); 3628 } 3629 3630 if (!query->canceled) { 3631 cancel_lookup(l); 3632 } 3633 3634 query_detach(&query); 3635 lookup_detach(&l); 3636 clear_current_lookup(); 3637 return; 3638 } 3639 3640 if (eresult != ISC_R_SUCCESS) { 3641 debug("unsuccessful connection: %s", 3642 isc_result_totext(eresult)); 3643 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); 3644 dighost_warning("Connection to %s(%s) for %s failed: %s.", 3645 sockstr, query->servname, l->textname, 3646 isc_result_totext(eresult)); 3647 3648 /* 3649 * NSSEARCH mode: if the current query failed to start properly, 3650 * then send_done() will not be called, and we want to make sure 3651 * that the next query gets a chance to start in order to not 3652 * break the chain. 3653 */ 3654 if (l->ns_search_only && !l->trace_root) { 3655 nssearch_next(l, query); 3656 check_if_done(); 3657 return; 3658 } 3659 3660 /* XXX Clean up exitcodes */ 3661 if (exitcode < 9) { 3662 exitcode = 9; 3663 } 3664 3665 if (l->retries > 1) { 3666 l->retries--; 3667 debug("making new TCP request, %d tries left", 3668 l->retries); 3669 requeue_lookup(l, true); 3670 next = NULL; 3671 } else if ((l->current_query != NULL) && 3672 (ISC_LINK_LINKED(l->current_query, link))) 3673 { 3674 next = ISC_LIST_NEXT(l->current_query, link); 3675 } else { 3676 next = NULL; 3677 } 3678 3679 query_detach(&query); 3680 if (next == NULL) { 3681 cancel_lookup(l); 3682 } 3683 lookup_detach(&l); 3684 3685 if (next != NULL) { 3686 start_tcp(next); 3687 check_if_done(); 3688 } else { 3689 dighost_error("no servers could be reached"); 3690 clear_current_lookup(); 3691 } 3692 3693 return; 3694 } 3695 3696 exitcode = 0; 3697 3698 query->handle = handle; 3699 if (keep_open) { 3700 keepaddr = query->sockaddr; 3701 if (keep != NULL) { 3702 isc_nmhandle_detach(&keep); 3703 } 3704 3705 isc_nmhandle_attach(handle, &keep); 3706 } 3707 3708 launch_next_query(query); 3709 query_detach(&query); 3710 lookup_detach(&l); 3711 } 3712 3713 /*% 3714 * Check if the ongoing XFR needs more data before it's complete, using 3715 * the semantics of IXFR and AXFR protocols. Much of the complexity of 3716 * this routine comes from determining when an IXFR is complete. 3717 * false means more data is on the way, and the recv has been issued. 3718 */ 3719 static bool 3720 check_for_more_data(dig_lookup_t *lookup, dig_query_t *query, 3721 dns_message_t *msg, isc_sockaddr_t *peer, int len) { 3722 dns_rdataset_t *rdataset = NULL; 3723 dns_rdata_t rdata = DNS_RDATA_INIT; 3724 dns_rdata_soa_t soa; 3725 uint32_t ixfr_serial = lookup->ixfr_serial, serial; 3726 isc_result_t result; 3727 bool ixfr = lookup->rdtype == dns_rdatatype_ixfr; 3728 bool axfr = lookup->rdtype == dns_rdatatype_axfr; 3729 3730 if (ixfr) { 3731 axfr = query->ixfr_axfr; 3732 } 3733 3734 debug("check_for_more_data()"); 3735 3736 /* 3737 * By the time we're in this routine, we know we're doing 3738 * either an AXFR or IXFR. If there's no second_rr_type, 3739 * then we don't yet know which kind of answer we got back 3740 * from the server. Here, we're going to walk through the 3741 * rr's in the message, acting as necessary whenever we hit 3742 * an SOA rr. 3743 */ 3744 3745 query->msg_count++; 3746 query->byte_count += len; 3747 result = dns_message_firstname(msg, DNS_SECTION_ANSWER); 3748 if (result != ISC_R_SUCCESS) { 3749 puts("; Transfer failed."); 3750 return true; 3751 } 3752 do { 3753 dns_name_t *name; 3754 name = NULL; 3755 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); 3756 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; 3757 rdataset = ISC_LIST_NEXT(rdataset, link)) 3758 { 3759 result = dns_rdataset_first(rdataset); 3760 if (result != ISC_R_SUCCESS) { 3761 continue; 3762 } 3763 do { 3764 query->rr_count++; 3765 dns_rdata_reset(&rdata); 3766 dns_rdataset_current(rdataset, &rdata); 3767 /* 3768 * If this is the first rr, make sure 3769 * it's an SOA 3770 */ 3771 if ((!query->first_soa_rcvd) && 3772 (rdata.type != dns_rdatatype_soa)) 3773 { 3774 puts("; Transfer failed. " 3775 "Didn't start with SOA answer."); 3776 return true; 3777 } 3778 if ((!query->second_rr_rcvd) && 3779 (rdata.type != dns_rdatatype_soa)) 3780 { 3781 query->second_rr_rcvd = true; 3782 query->second_rr_serial = 0; 3783 debug("got the second rr as nonsoa"); 3784 axfr = query->ixfr_axfr = true; 3785 goto next_rdata; 3786 } 3787 3788 /* 3789 * If the record is anything except an SOA 3790 * now, just continue on... 3791 */ 3792 if (rdata.type != dns_rdatatype_soa) { 3793 goto next_rdata; 3794 } 3795 3796 /* Now we have an SOA. Work with it. */ 3797 debug("got an SOA"); 3798 result = dns_rdata_tostruct(&rdata, &soa, NULL); 3799 check_result(result, "dns_rdata_tostruct"); 3800 serial = soa.serial; 3801 dns_rdata_freestruct(&soa); 3802 if (!query->first_soa_rcvd) { 3803 query->first_soa_rcvd = true; 3804 query->first_rr_serial = serial; 3805 debug("this is the first serial %u", 3806 serial); 3807 if (ixfr && 3808 isc_serial_ge(ixfr_serial, serial)) 3809 { 3810 debug("got up to date " 3811 "response"); 3812 goto doexit; 3813 } 3814 goto next_rdata; 3815 } 3816 if (axfr) { 3817 debug("doing axfr, got second SOA"); 3818 goto doexit; 3819 } 3820 if (!query->second_rr_rcvd) { 3821 if (query->first_rr_serial == serial) { 3822 debug("doing ixfr, got " 3823 "empty zone"); 3824 goto doexit; 3825 } 3826 debug("this is the second serial %u", 3827 serial); 3828 query->second_rr_rcvd = true; 3829 query->second_rr_serial = serial; 3830 goto next_rdata; 3831 } 3832 /* 3833 * If we get to this point, we're doing an 3834 * IXFR and have to start really looking 3835 * at serial numbers. 3836 */ 3837 if (query->first_rr_serial == serial) { 3838 debug("got a match for ixfr"); 3839 if (!query->first_repeat_rcvd) { 3840 query->first_repeat_rcvd = true; 3841 goto next_rdata; 3842 } 3843 debug("done with ixfr"); 3844 goto doexit; 3845 } 3846 debug("meaningless soa %u", serial); 3847 next_rdata: 3848 result = dns_rdataset_next(rdataset); 3849 } while (result == ISC_R_SUCCESS); 3850 } 3851 result = dns_message_nextname(msg, DNS_SECTION_ANSWER); 3852 } while (result == ISC_R_SUCCESS); 3853 isc_nmhandle_detach(&query->readhandle); 3854 launch_next_query(query); 3855 query_detach(&query); 3856 return false; 3857 doexit: 3858 dighost_received(len, peer, query); 3859 return true; 3860 } 3861 3862 static void 3863 process_cookie(dig_lookup_t *l, dns_message_t *msg, isc_buffer_t *optbuf, 3864 size_t optlen) { 3865 char bb[256]; 3866 isc_buffer_t hexbuf; 3867 size_t len; 3868 const unsigned char *sent; 3869 bool copy = true; 3870 isc_result_t result; 3871 3872 if (l->cookie != NULL) { 3873 isc_buffer_init(&hexbuf, bb, sizeof(bb)); 3874 result = isc_hex_decodestring(l->cookie, &hexbuf); 3875 check_result(result, "isc_hex_decodestring"); 3876 sent = isc_buffer_base(&hexbuf); 3877 len = isc_buffer_usedlength(&hexbuf); 3878 } else { 3879 sent = cookie; 3880 len = sizeof(cookie); 3881 } 3882 3883 INSIST(msg->cc_ok == 0 && msg->cc_bad == 0); 3884 if (len >= 8 && optlen >= 8U) { 3885 if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) { 3886 msg->cc_ok = 1; 3887 } else { 3888 dighost_warning("Warning: Client COOKIE mismatch"); 3889 msg->cc_bad = 1; 3890 copy = false; 3891 } 3892 } else { 3893 dighost_warning("Warning: COOKIE bad token (too short)"); 3894 msg->cc_bad = 1; 3895 copy = false; 3896 } 3897 if (copy) { 3898 isc_region_t r; 3899 3900 r.base = isc_buffer_current(optbuf); 3901 r.length = (unsigned int)optlen; 3902 isc_buffer_init(&hexbuf, servercookie, sizeof(servercookie)); 3903 result = isc_hex_totext(&r, 2, "", &hexbuf); 3904 check_result(result, "isc_hex_totext"); 3905 if (isc_buffer_availablelength(&hexbuf) > 0) { 3906 isc_buffer_putuint8(&hexbuf, 0); 3907 l->cookie = servercookie; 3908 } 3909 } 3910 isc_buffer_forward(optbuf, (unsigned int)optlen); 3911 } 3912 3913 static void 3914 process_opt(dig_lookup_t *l, dns_message_t *msg) { 3915 dns_rdata_t rdata; 3916 isc_result_t result; 3917 isc_buffer_t optbuf; 3918 uint16_t optcode, optlen; 3919 dns_rdataset_t *opt = msg->opt; 3920 bool seen_cookie = false; 3921 3922 result = dns_rdataset_first(opt); 3923 if (result == ISC_R_SUCCESS) { 3924 dns_rdata_init(&rdata); 3925 dns_rdataset_current(opt, &rdata); 3926 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3927 isc_buffer_add(&optbuf, rdata.length); 3928 while (isc_buffer_remaininglength(&optbuf) >= 4) { 3929 optcode = isc_buffer_getuint16(&optbuf); 3930 optlen = isc_buffer_getuint16(&optbuf); 3931 switch (optcode) { 3932 case DNS_OPT_COOKIE: 3933 /* 3934 * Only process the first cookie option. 3935 */ 3936 if (seen_cookie) { 3937 isc_buffer_forward(&optbuf, optlen); 3938 break; 3939 } 3940 process_cookie(l, msg, &optbuf, optlen); 3941 seen_cookie = true; 3942 break; 3943 default: 3944 isc_buffer_forward(&optbuf, optlen); 3945 break; 3946 } 3947 } 3948 } 3949 } 3950 3951 static int 3952 ednsvers(dns_rdataset_t *opt) { 3953 return (opt->ttl >> 16) & 0xff; 3954 } 3955 3956 /*% 3957 * Event handler for recv complete. Perform whatever actions are necessary, 3958 * based on the specifics of the user's request. 3959 */ 3960 static void 3961 recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, 3962 void *arg) { 3963 dig_query_t *query = (dig_query_t *)arg; 3964 isc_buffer_t b; 3965 dns_message_t *msg = NULL; 3966 isc_result_t result; 3967 dig_lookup_t *n = NULL; 3968 dig_lookup_t *l = NULL; 3969 bool docancel = false; 3970 bool donext = false; 3971 bool match = true; 3972 bool done_process_opt = false; 3973 unsigned int parseflags; 3974 dns_messageid_t id; 3975 unsigned int msgflags; 3976 int newedns; 3977 isc_sockaddr_t peer; 3978 3979 REQUIRE(DIG_VALID_QUERY(query)); 3980 REQUIRE(query->readhandle != NULL); 3981 INSIST(!free_now); 3982 3983 debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult), 3984 region, arg); 3985 3986 isc_refcount_decrement0(&recvcount); 3987 debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount)); 3988 3989 lookup_attach(query->lookup, &l); 3990 3991 if (eresult == ISC_R_CANCELED || eresult == ISC_R_SHUTTINGDOWN || 3992 query->canceled) 3993 { 3994 debug("recv_done: cancel"); 3995 isc_nmhandle_detach(&query->readhandle); 3996 if (eresult == ISC_R_SHUTTINGDOWN) { 3997 cancel_all(); 3998 } else if (!query->canceled) { 3999 cancel_lookup(l); 4000 } 4001 query_detach(&query); 4002 lookup_detach(&l); 4003 clear_current_lookup(); 4004 return; 4005 } 4006 4007 if (query->lookup->use_usec) { 4008 query->time_recv = isc_time_now_hires(); 4009 } else { 4010 query->time_recv = isc_time_now(); 4011 } 4012 4013 if ((!l->pending && !l->ns_search_only) || cancel_now) { 4014 debug("no longer pending. Got %s", isc_result_totext(eresult)); 4015 4016 goto next_lookup; 4017 } 4018 4019 /* 4020 * NSSEARCH mode is special, because the queries in the followup lookup 4021 * are independent and they are being started in parallel, so if one of 4022 * them fails there is no need to start the next query in the lookup, 4023 * and this failure can be treated as a soft error (with a warning 4024 * message), because there are usually more than one NS servers in the 4025 * lookup's queries list. However, if there was not a single successful 4026 * query in the followup lookup, then print an error message and exit 4027 * with a non-zero exit code. 4028 */ 4029 if (l->ns_search_only && !l->trace_root) { 4030 if (eresult == ISC_R_SUCCESS) { 4031 l->ns_search_success = true; 4032 } else { 4033 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 4034 isc_sockaddr_format(&query->sockaddr, sockstr, 4035 sizeof(sockstr)); 4036 4037 dighost_warning("communications error to %s: %s", 4038 sockstr, isc_result_totext(eresult)); 4039 4040 /* 4041 * If this is not the last query, then we detach the 4042 * query, but keep the lookup running. 4043 */ 4044 if (!check_if_queries_done(l, query)) { 4045 goto detach_query; 4046 } 4047 4048 /* 4049 * This is the last query, and if there was not a 4050 * single successful query in the whole lookup, then 4051 * treat the situation as an error. 4052 */ 4053 if (!l->ns_search_success) { 4054 dighost_error( 4055 "NS servers could not be reached"); 4056 if (exitcode < 9) { 4057 exitcode = 9; 4058 } 4059 } 4060 4061 goto cancel_lookup; 4062 } 4063 } 4064 4065 if (eresult != ISC_R_SUCCESS) { 4066 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 4067 4068 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); 4069 dighost_warning("communications error to %s: %s", sockstr, 4070 isc_result_totext(eresult)); 4071 4072 if (l->retries > 1 && !l->tcp_mode) { 4073 dig_query_t *newq = NULL; 4074 4075 /* 4076 * For UDP, insert a copy of the current query just 4077 * after itself in the list, and start it to retry the 4078 * request. 4079 */ 4080 newq = new_query(l, query->servname, query->userarg); 4081 ISC_LIST_INSERTAFTER(l->q, query, newq, link); 4082 if (l->current_query == query) { 4083 query_detach(&l->current_query); 4084 } 4085 if (l->current_query == NULL) { 4086 l->retries--; 4087 debug("making new UDP request, %d tries left", 4088 l->retries); 4089 start_udp(newq); 4090 } 4091 if (check_if_queries_done(l, query)) { 4092 goto cancel_lookup; 4093 } 4094 4095 goto detach_query; 4096 } else if (l->retries > 1 && l->tcp_mode) { 4097 /* 4098 * For TCP, we have to requeue the whole lookup, see 4099 * the comments above the start_tcp() function. 4100 */ 4101 l->retries--; 4102 debug("making new TCP request, %d tries left", 4103 l->retries); 4104 requeue_lookup(l, true); 4105 4106 if (keep != NULL) { 4107 isc_nmhandle_detach(&keep); 4108 } 4109 4110 goto cancel_lookup; 4111 } else { 4112 dig_query_t *next = ISC_LIST_NEXT(query, link); 4113 4114 /* 4115 * No retries left, go to the next query, if there is 4116 * one. 4117 */ 4118 if (next != NULL) { 4119 if (l->current_query == query) { 4120 query_detach(&l->current_query); 4121 } 4122 if (l->current_query == NULL) { 4123 debug("starting next query %p", next); 4124 if (l->tcp_mode) { 4125 start_tcp(next); 4126 } else { 4127 start_udp(next); 4128 } 4129 } 4130 if (check_if_queries_done(l, query)) { 4131 goto cancel_lookup; 4132 } 4133 4134 goto detach_query; 4135 } 4136 4137 /* 4138 * Otherwise, print the cmdline and an error message, 4139 * and cancel the lookup. 4140 */ 4141 printf("%s", l->cmdline); 4142 dighost_error("no servers could be reached"); 4143 4144 if (exitcode < 9) { 4145 exitcode = 9; 4146 } 4147 4148 if (keep != NULL) { 4149 isc_nmhandle_detach(&keep); 4150 } 4151 4152 goto cancel_lookup; 4153 } 4154 } 4155 4156 isc_buffer_init(&b, region->base, region->length); 4157 isc_buffer_add(&b, region->length); 4158 4159 peer = isc_nmhandle_peeraddr(handle); 4160 4161 result = dns_message_peekheader(&b, &id, &msgflags); 4162 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) { 4163 match = false; 4164 if (l->tcp_mode) { 4165 bool fail = true; 4166 if (result == ISC_R_SUCCESS) { 4167 if (!query->first_soa_rcvd || query->warn_id) { 4168 dighost_warning("%s: ID mismatch: " 4169 "expected ID %u, got " 4170 "%u", 4171 query->first_soa_rcvd 4172 ? "WARNING" 4173 : "ERROR", 4174 l->sendmsg->id, id); 4175 } 4176 if (query->first_soa_rcvd) { 4177 fail = false; 4178 } 4179 query->warn_id = false; 4180 } else { 4181 dighost_warning("ERROR: short (< header size) " 4182 "message"); 4183 } 4184 if (fail) { 4185 goto cancel_lookup; 4186 } 4187 match = true; 4188 } else if (result == ISC_R_SUCCESS) { 4189 dighost_warning("Warning: ID mismatch: expected ID %u," 4190 " got %u", 4191 l->sendmsg->id, id); 4192 } else { 4193 dighost_warning("Warning: short (< header size) " 4194 "message received"); 4195 } 4196 } 4197 4198 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0) { 4199 dighost_warning("Warning: query response not set"); 4200 } 4201 4202 if (!match) { 4203 /* 4204 * We are still attached to query and the query->readhandle is 4205 * also attached 4206 */ 4207 isc_refcount_increment0(&recvcount); 4208 debug("recvcount=%" PRIuFAST32, 4209 isc_refcount_current(&recvcount)); 4210 isc_nm_read(handle, recv_done, query); 4211 goto keep_query; 4212 } 4213 4214 dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &msg); 4215 4216 if (tsigkey != NULL) { 4217 if (l->querysig == NULL) { 4218 debug("getting initial querysig"); 4219 result = dns_message_getquerytsig(l->sendmsg, mctx, 4220 &l->querysig); 4221 check_result(result, "dns_message_getquerytsig"); 4222 } 4223 dns_message_setquerytsig(msg, l->querysig); 4224 result = dns_message_settsigkey(msg, tsigkey); 4225 check_result(result, "dns_message_settsigkey"); 4226 msg->tsigctx = l->tsigctx; 4227 l->tsigctx = NULL; 4228 if (l->msgcounter != 0) { 4229 msg->tcp_continuation = 1; 4230 } 4231 l->msgcounter++; 4232 } 4233 4234 debug("before parse starts"); 4235 parseflags = l->dns64prefix ? 0 : DNS_MESSAGEPARSE_PRESERVEORDER; 4236 if (l->besteffort) { 4237 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT; 4238 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION; 4239 } 4240 4241 result = dns_message_parse(msg, &b, parseflags); 4242 if (result == DNS_R_RECOVERABLE) { 4243 dighost_warning("Warning: Message parser reports malformed " 4244 "message packet."); 4245 } else if (result != ISC_R_SUCCESS) { 4246 if (!yaml) { 4247 printf(";; Got bad packet: %s\n", 4248 isc_result_totext(result)); 4249 hex_dump(&b); 4250 } 4251 goto cancel_lookup; 4252 } 4253 4254 if (msg->opcode != l->opcode) { 4255 char expect[20] = { 0 }, got[20] = { 0 }; 4256 4257 isc_buffer_init(&b, &expect, sizeof(expect)); 4258 result = dns_opcode_totext(l->opcode, &b); 4259 check_result(result, "dns_opcode_totext"); 4260 4261 isc_buffer_init(&b, &got, sizeof(got)); 4262 result = dns_opcode_totext(msg->opcode, &b); 4263 check_result(result, "dns_opcode_totext"); 4264 4265 dighost_warning("Warning: Opcode mismatch: expected %s, got %s", 4266 expect, got); 4267 4268 isc_refcount_increment0(&recvcount); 4269 debug("recvcount=%" PRIuFAST32, 4270 isc_refcount_current(&recvcount)); 4271 isc_nm_read(handle, recv_done, query); 4272 goto keep_query; 4273 } 4274 4275 if (msg->counts[DNS_SECTION_QUESTION] == 0) { 4276 if (l->doing_xfr) { 4277 if (query->msg_count == 0) { 4278 dighost_warning("missing question section"); 4279 } 4280 } else if (!l->header_only && msg->opcode == dns_opcode_query) { 4281 dighost_warning("missing question section"); 4282 } 4283 } else { 4284 match = true; 4285 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); 4286 result == ISC_R_SUCCESS && match; 4287 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) 4288 { 4289 dns_name_t *name = NULL; 4290 dns_rdataset_t *rdataset; 4291 4292 dns_message_currentname(msg, DNS_SECTION_QUESTION, 4293 &name); 4294 for (rdataset = ISC_LIST_HEAD(name->list); 4295 rdataset != NULL; 4296 rdataset = ISC_LIST_NEXT(rdataset, link)) 4297 { 4298 if (l->rdtype != rdataset->type || 4299 l->rdclass != rdataset->rdclass || 4300 !dns_name_equal(l->name, name)) 4301 { 4302 char namestr[DNS_NAME_FORMATSIZE]; 4303 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 4304 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 4305 dns_name_format(name, namestr, 4306 sizeof(namestr)); 4307 dns_rdatatype_format(rdataset->type, 4308 typebuf, 4309 sizeof(typebuf)); 4310 dns_rdataclass_format(rdataset->rdclass, 4311 classbuf, 4312 sizeof(classbuf)); 4313 dighost_warning(";; Question section " 4314 "mismatch: got " 4315 "%s/%s/%s", 4316 namestr, typebuf, 4317 classbuf); 4318 match = false; 4319 } 4320 } 4321 } 4322 4323 if (!match) { 4324 if (l->tcp_mode) { 4325 goto cancel_lookup; 4326 } 4327 4328 /* 4329 * We are still attached to query and the 4330 * query->readhandle is also attached 4331 */ 4332 isc_refcount_increment0(&recvcount); 4333 debug("recvcount=%" PRIuFAST32, 4334 isc_refcount_current(&recvcount)); 4335 isc_nm_read(handle, recv_done, query); 4336 goto keep_query; 4337 } 4338 } 4339 4340 if (msg->rcode == dns_rcode_badvers && msg->opt != NULL && 4341 (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) 4342 { 4343 if (l->showbadvers) { 4344 dighost_printmessage(query, &b, msg, true); 4345 dighost_received(isc_buffer_usedlength(&b), &peer, 4346 query); 4347 } 4348 /* 4349 * Add minimum EDNS version required checks here if needed. 4350 */ 4351 dighost_comments(l, "BADVERS, retrying with EDNS version %u.", 4352 (unsigned int)newedns); 4353 l->edns = newedns; 4354 /* 4355 * Extract the server cookie so it can be sent in the retry. 4356 */ 4357 if (l->cookie == NULL && l->sendcookie) { 4358 process_opt(l, msg); 4359 } 4360 n = requeue_lookup(l, true); 4361 if (l->trace && l->trace_root) { 4362 n->rdtype = l->qrdtype; 4363 } 4364 goto cancel_lookup; 4365 } 4366 4367 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 && !l->ignore && 4368 !l->tcp_mode) 4369 { 4370 if (l->cookie == NULL && l->sendcookie && msg->opt != NULL) { 4371 process_opt(l, msg); 4372 } 4373 dighost_comments(l, "Truncated, retrying in TCP mode."); 4374 n = requeue_lookup(l, true); 4375 n->tcp_mode = true; 4376 if (l->trace && l->trace_root) { 4377 n->rdtype = l->qrdtype; 4378 } 4379 goto cancel_lookup; 4380 } 4381 4382 if (msg->rcode == dns_rcode_badcookie && !l->tcp_mode && 4383 l->sendcookie && l->badcookie) 4384 { 4385 process_opt(l, msg); 4386 if (msg->cc_ok) { 4387 if (l->showbadcookie) { 4388 dighost_printmessage(query, &b, msg, true); 4389 dighost_received(isc_buffer_usedlength(&b), 4390 &peer, query); 4391 } 4392 dighost_comments(l, "BADCOOKIE, retrying%s.", 4393 l->seenbadcookie ? " in TCP mode" 4394 : ""); 4395 n = requeue_lookup(l, true); 4396 if (l->seenbadcookie) { 4397 n->tcp_mode = true; 4398 } 4399 n->seenbadcookie = true; 4400 if (l->trace && l->trace_root) { 4401 n->rdtype = l->qrdtype; 4402 } 4403 goto cancel_lookup; 4404 } 4405 done_process_opt = true; 4406 } 4407 4408 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || 4409 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) 4410 { 4411 const char *err = (msg->rcode == dns_rcode_servfail && 4412 !l->servfail_stops) 4413 ? "SERVFAIL reply" 4414 : "recursion not available"; 4415 dig_query_t *next = ISC_LIST_NEXT(query, link); 4416 if (l->current_query == query) { 4417 query_detach(&l->current_query); 4418 } 4419 if (next != NULL && (!l->ns_search_only || l->trace_root)) { 4420 dighost_comments(l, 4421 "Got %s from %s, trying next server", 4422 err, query->servname); 4423 debug("sending query %p", next); 4424 if (l->tcp_mode) { 4425 start_tcp(next); 4426 } else { 4427 start_udp(next); 4428 } 4429 if (check_if_queries_done(l, query)) { 4430 goto cancel_lookup; 4431 } 4432 4433 goto detach_query; 4434 } else { 4435 dighost_comments(l, "Got %s from %s", err, 4436 query->servname); 4437 } 4438 } 4439 4440 if (tsigkey != NULL) { 4441 result = dns_tsig_verify(&b, msg, NULL, NULL); 4442 if (result != ISC_R_SUCCESS) { 4443 dighost_warning("Couldn't verify signature: %s", 4444 isc_result_totext(result)); 4445 validated = false; 4446 } 4447 l->tsigctx = msg->tsigctx; 4448 msg->tsigctx = NULL; 4449 if (l->querysig != NULL) { 4450 debug("freeing querysig buffer %p", l->querysig); 4451 isc_buffer_free(&l->querysig); 4452 } 4453 result = dns_message_getquerytsig(msg, mctx, &l->querysig); 4454 check_result(result, "dns_message_getquerytsig"); 4455 } 4456 4457 extrabytes = isc_buffer_remaininglength(&b); 4458 4459 debug("after parse"); 4460 if (l->doing_xfr && l->xfr_q == NULL) { 4461 l->xfr_q = query; 4462 /* 4463 * Once we are in the XFR message, increase 4464 * the timeout to much longer, so brief network 4465 * outages won't cause the XFR to abort 4466 */ 4467 if (timeout != INT_MAX && query->timer != NULL) { 4468 unsigned int local_timeout; 4469 4470 if (timeout == 0) { 4471 if (l->tcp_mode) { 4472 local_timeout = TCP_TIMEOUT * 4000; 4473 } else { 4474 local_timeout = UDP_TIMEOUT * 4000; 4475 } 4476 } else { 4477 if (timeout < (INT_MAX / 4)) { 4478 local_timeout = timeout * 4000; 4479 } else { 4480 local_timeout = INT_MAX; 4481 } 4482 } 4483 4484 debug("have local timeout of %d", local_timeout); 4485 isc_nmhandle_settimeout(query->handle, local_timeout); 4486 } 4487 } 4488 4489 if (!done_process_opt) { 4490 if (l->cookie != NULL) { 4491 if (msg->opt == NULL) { 4492 dighost_warning("expected opt record in " 4493 "response"); 4494 } else { 4495 process_opt(l, msg); 4496 } 4497 } else if (l->sendcookie && msg->opt != NULL) { 4498 process_opt(l, msg); 4499 } 4500 } 4501 4502 if (!l->doing_xfr || l->xfr_q == query) { 4503 if (msg->rcode == dns_rcode_nxdomain && 4504 (l->origin != NULL || l->need_search)) 4505 { 4506 if (!next_origin(l) || showsearch) { 4507 dighost_printmessage(query, &b, msg, true); 4508 dighost_received(isc_buffer_usedlength(&b), 4509 &peer, query); 4510 } 4511 } else if (!l->trace && !l->ns_search_only) { 4512 dighost_printmessage(query, &b, msg, true); 4513 } else if (l->trace) { 4514 int nl = 0; 4515 int count = msg->counts[DNS_SECTION_ANSWER]; 4516 4517 debug("in TRACE code"); 4518 if (!l->ns_search_only) { 4519 dighost_printmessage(query, &b, msg, true); 4520 } 4521 4522 l->rdtype = l->qrdtype; 4523 if (l->trace_root || (l->ns_search_only && count > 0)) { 4524 if (!l->trace_root) { 4525 l->rdtype = dns_rdatatype_soa; 4526 } 4527 nl = followup_lookup(msg, query, 4528 DNS_SECTION_ANSWER); 4529 l->trace_root = false; 4530 } else if (count == 0) { 4531 nl = followup_lookup(msg, query, 4532 DNS_SECTION_AUTHORITY); 4533 } 4534 if (nl == 0) { 4535 docancel = true; 4536 } 4537 } else { 4538 debug("in NSSEARCH code"); 4539 4540 if (l->trace_root) { 4541 /* 4542 * This is the initial NS query. 4543 */ 4544 int nl; 4545 4546 l->rdtype = dns_rdatatype_soa; 4547 nl = followup_lookup(msg, query, 4548 DNS_SECTION_ANSWER); 4549 if (nl == 0) { 4550 docancel = true; 4551 } 4552 l->trace_root = false; 4553 usesearch = false; 4554 } else { 4555 /* 4556 * This is a query in the followup lookup 4557 */ 4558 dighost_printmessage(query, &b, msg, true); 4559 4560 docancel = check_if_queries_done(l, query); 4561 } 4562 } 4563 } 4564 4565 if (l->pending) { 4566 debug("still pending."); 4567 } 4568 4569 if (l->doing_xfr) { 4570 if (query != l->xfr_q) { 4571 goto detach_query; 4572 } 4573 if (!docancel) { 4574 docancel = check_for_more_data(l, query, msg, &peer, 4575 region->length); 4576 } 4577 if (docancel) { 4578 goto cancel_lookup; 4579 } 4580 /* 4581 * check_for_more_data() will detach from query->readhandle 4582 * and query on its own, as it needs to reuse the query and 4583 * reattach to the readhandle in launch_next_query(). 4584 */ 4585 goto keep_query; 4586 } else { 4587 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) { 4588 dighost_received(isc_buffer_usedlength(&b), &peer, 4589 query); 4590 } 4591 4592 if (!l->ns_search_only) { 4593 l->pending = false; 4594 } 4595 if (!l->ns_search_only || l->trace_root || docancel) { 4596 goto cancel_lookup; 4597 } 4598 goto next_lookup; 4599 } 4600 cancel_lookup: 4601 docancel = true; 4602 next_lookup: 4603 donext = true; 4604 detach_query: 4605 isc_nmhandle_detach(&query->readhandle); 4606 query_detach(&query); 4607 if (docancel) { 4608 cancel_lookup(l); 4609 } 4610 keep_query: 4611 if (msg != NULL) { 4612 dns_message_detach(&msg); 4613 } 4614 lookup_detach(&l); 4615 if (donext) { 4616 clear_current_lookup(); 4617 } 4618 } 4619 4620 /*% 4621 * Turn a name into an address, using system-supplied routines. This is 4622 * used in looking up server names, etc... and needs to use system-supplied 4623 * routines, since they may be using a non-DNS system for these lookups. 4624 */ 4625 isc_result_t 4626 get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) { 4627 int count; 4628 isc_result_t result; 4629 4630 isc_loopmgr_blocking(loopmgr); 4631 result = isc_getaddresses(host, myport, sockaddr, 1, &count); 4632 isc_loopmgr_nonblocking(loopmgr); 4633 if (result != ISC_R_SUCCESS) { 4634 return result; 4635 } 4636 4637 INSIST(count == 1); 4638 4639 return ISC_R_SUCCESS; 4640 } 4641 4642 int 4643 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) { 4644 isc_result_t result; 4645 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; 4646 isc_netaddr_t netaddr; 4647 int count, i; 4648 dig_server_t *srv; 4649 char tmp[ISC_NETADDR_FORMATSIZE]; 4650 4651 isc_loopmgr_blocking(loopmgr); 4652 result = isc_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES, 4653 &count); 4654 isc_loopmgr_nonblocking(loopmgr); 4655 SET_IF_NOT_NULL(resultp, result); 4656 if (result != ISC_R_SUCCESS) { 4657 if (resultp == NULL) { 4658 fatal("couldn't get address for '%s': %s", host, 4659 isc_result_totext(result)); 4660 } 4661 return 0; 4662 } 4663 4664 for (i = 0; i < count; i++) { 4665 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); 4666 isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); 4667 srv = make_server(tmp, host); 4668 ISC_LIST_APPEND(lookup->my_server_list, srv, link); 4669 } 4670 4671 return count; 4672 } 4673 4674 /*% 4675 * Initiate either a TCP or UDP lookup 4676 */ 4677 void 4678 do_lookup(dig_lookup_t *lookup) { 4679 dig_query_t *query; 4680 4681 REQUIRE(lookup != NULL); 4682 4683 debug("do_lookup()"); 4684 lookup->pending = true; 4685 query = ISC_LIST_HEAD(lookup->q); 4686 if (query != NULL) { 4687 REQUIRE(DIG_VALID_QUERY(query)); 4688 if (lookup->tcp_mode) { 4689 start_tcp(query); 4690 } else { 4691 start_udp(query); 4692 } 4693 } 4694 } 4695 4696 /*% 4697 * Start everything in action upon task startup. 4698 */ 4699 void 4700 onrun_callback(void *arg) { 4701 UNUSED(arg); 4702 4703 start_lookup(); 4704 } 4705 4706 void 4707 run_loop(void *arg) { 4708 UNUSED(arg); 4709 4710 start_lookup(); 4711 } 4712 4713 /*% 4714 * Make everything on the lookup queue go away. Mainly used by the 4715 * SIGINT handler. 4716 */ 4717 void 4718 cancel_all(void) { 4719 dig_lookup_t *l, *n; 4720 dig_query_t *q, *nq; 4721 4722 debug("cancel_all()"); 4723 4724 if (free_now) { 4725 return; 4726 } 4727 4728 cancel_now = true; 4729 4730 while (current_lookup != NULL) { 4731 for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) { 4732 nq = ISC_LIST_NEXT(q, link); 4733 debug("canceling pending query %p, belonging to %p", q, 4734 current_lookup); 4735 q->canceled = true; 4736 if (q->readhandle != NULL && 4737 !isc_nm_is_http_handle(q->readhandle)) 4738 { 4739 isc_nm_cancelread(q->readhandle); 4740 } 4741 query_detach(&q); 4742 } 4743 4744 /* 4745 * current_lookup could have been detached via query_detach(). 4746 */ 4747 if (current_lookup != NULL) { 4748 lookup_detach(¤t_lookup); 4749 } 4750 } 4751 l = ISC_LIST_HEAD(lookup_list); 4752 while (l != NULL) { 4753 n = ISC_LIST_NEXT(l, link); 4754 ISC_LIST_DEQUEUE(lookup_list, l, link); 4755 lookup_detach(&l); 4756 l = n; 4757 } 4758 } 4759 4760 void 4761 cleanup_openssl_refs(void) { 4762 if (tsigkey != NULL) { 4763 debug("freeing TSIG key %p", tsigkey); 4764 dns_tsigkey_detach(&tsigkey); 4765 } 4766 4767 if (sig0key != NULL) { 4768 debug("freeing SIG(0) key %p", sig0key); 4769 dst_key_free(&sig0key); 4770 } 4771 4772 if (is_dst_up) { 4773 debug("destroy DST lib"); 4774 dst_lib_destroy(); 4775 is_dst_up = false; 4776 } 4777 } 4778 4779 /*% 4780 * Destroy all of the libs we are using, and get everything ready for a 4781 * clean shutdown. 4782 */ 4783 void 4784 destroy_libs(void) { 4785 debug("destroy_libs()"); 4786 4787 isc_refcount_destroy(&recvcount); 4788 isc_refcount_destroy(&sendcount); 4789 4790 INSIST(ISC_LIST_HEAD(lookup_list) == NULL); 4791 INSIST(current_lookup == NULL); 4792 INSIST(!free_now); 4793 4794 free_now = true; 4795 4796 flush_server_list(); 4797 4798 clear_searchlist(); 4799 4800 cleanup_openssl_refs(); 4801 4802 if (namebuf != NULL) { 4803 debug("freeing key %p", tsigkey); 4804 isc_buffer_free(&namebuf); 4805 } 4806 4807 debug("Removing log context"); 4808 isc_log_destroy(&lctx); 4809 4810 debug("Destroy memory"); 4811 if (memdebugging != 0) { 4812 isc_mem_stats(mctx, stderr); 4813 } 4814 4815 isc_managers_destroy(&mctx, &loopmgr, &netmgr); 4816 4817 #if ENABLE_LEAK_DETECTION 4818 isc__tls_setdestroycheck(true); 4819 isc__uv_setdestroycheck(true); 4820 isc__xml_setdestroycheck(true); 4821 #endif 4822 4823 isc_mem_checkdestroyed(stderr); 4824 } 4825 4826 #ifdef HAVE_LIBIDN2 4827 4828 static isc_result_t 4829 idn_filter(isc_buffer_t *buffer, unsigned int start) { 4830 char src[MXNAME]; 4831 char *dst = NULL; 4832 size_t srclen, dstlen; 4833 int res; 4834 4835 /* 4836 * Copy name from 'buffer' to 'src' and terminate it with NULL. 4837 */ 4838 srclen = isc_buffer_usedlength(buffer) - start; 4839 INSIST(srclen < sizeof(src)); 4840 memmove(src, (char *)isc_buffer_base(buffer) + start, srclen); 4841 src[srclen] = '\0'; 4842 4843 /* 4844 * Try to convert the name; leave it unchanged if conversion fails. 4845 */ 4846 systemlocale(LC_ALL); 4847 res = idn2_to_unicode_8zlz(src, &dst, IDN2_NONTRANSITIONAL); 4848 if (res == IDN2_DISALLOWED) { 4849 res = idn2_to_unicode_8zlz(src, &dst, IDN2_TRANSITIONAL); 4850 } 4851 resetlocale(LC_ALL); 4852 if (res != IDN2_OK) { 4853 return ISC_R_SUCCESS; 4854 } 4855 4856 /* 4857 * Copy the converted back into 'buffer' if it fits. 4858 */ 4859 dstlen = strlen(dst); 4860 if (isc_buffer_length(buffer) < start + dstlen) { 4861 return ISC_R_NOSPACE; 4862 } 4863 isc_buffer_subtract(buffer, srclen); 4864 memmove(isc_buffer_used(buffer), dst, dstlen); 4865 isc_buffer_add(buffer, dstlen); 4866 4867 idn2_free(dst); 4868 return ISC_R_SUCCESS; 4869 } 4870 4871 /*% 4872 * Convert 'src', which is a string using the current locale's character 4873 * encoding, into an ACE string suitable for use in the DNS, storing the 4874 * conversion result in 'dst', which is 'dstlen' bytes large. 4875 * 4876 * 'dst' MUST be large enough to hold any valid domain name. 4877 */ 4878 static void 4879 idn_input(const char *src, char *dst, size_t dstlen) { 4880 char *ascii = NULL; 4881 size_t len; 4882 int res; 4883 4884 /* 4885 * We trust libidn2 to return an error if 'src' is too large to be a 4886 * valid domain name. 4887 * 4888 * If conversion fails under IDNA2008 rules, retry with transitional 4889 * rules. The aim is that characters whose interpretation changed will 4890 * be handled under the new rules, but we will accept characters (such 4891 * as emoji) that were OK but are now forbidden. 4892 */ 4893 systemlocale(LC_ALL); 4894 res = idn2_to_ascii_lz(src, &ascii, IDN2_NONTRANSITIONAL); 4895 if (res == IDN2_DISALLOWED) { 4896 res = idn2_to_ascii_lz(src, &ascii, IDN2_TRANSITIONAL); 4897 } 4898 resetlocale(LC_ALL); 4899 4900 /* 4901 * idn2_to_ascii_lz() normalizes all strings to lower case, but 4902 * we generally don't want to lowercase all input strings; make 4903 * sure to return the original case if the two strings differ 4904 * only in case. 4905 */ 4906 if (res == IDN2_OK && strcasecmp(src, ascii) != 0) { 4907 len = strlcpy(dst, ascii, dstlen); 4908 } else { 4909 len = strlcpy(dst, src, dstlen); 4910 } 4911 INSIST(len < dstlen); 4912 idn2_free(ascii); 4913 } 4914 4915 #endif /* HAVE_LIBIDN2 */ 4916 4917 void 4918 dig_idnsetup(dig_lookup_t *lookup, bool active) { 4919 #ifdef HAVE_LIBIDN2 4920 isc_result_t result; 4921 result = dns_name_settotextfilter( 4922 (active && lookup->idnout) ? idn_filter : NULL); 4923 check_result(result, "dns_name_settotextfilter"); 4924 #else 4925 UNUSED(lookup); 4926 UNUSED(active); 4927 return; 4928 #endif /* HAVE_LIBIDN2 */ 4929 } 4930 4931 bool 4932 dig_lookup_is_tls(const dig_lookup_t *lookup) { 4933 if (lookup->tls_mode || (lookup->tls_ca_set && !lookup->https_mode)) { 4934 return true; 4935 } 4936 4937 return false; 4938 } 4939