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