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