dighost.c revision 1.4.4.3 1 /* $NetBSD: dighost.c,v 1.4.4.3 2024/02/29 12:28:11 martin 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
90 dig_lookuplist_t lookup_list;
91 dig_serverlist_t server_list;
92 dig_searchlistlist_t search_list;
93
94 static atomic_bool cancel_now = false;
95
96 bool check_ra = false, have_ipv4 = false, have_ipv6 = false,
97 specified_source = false, free_now = false, usesearch = false,
98 showsearch = false, is_dst_up = false, keep_open = false, verbose = false,
99 yaml = false;
100 in_port_t port = 53;
101 bool port_set = false;
102 unsigned int timeout = 0;
103 unsigned int extrabytes;
104 isc_mem_t *mctx = NULL;
105 isc_log_t *lctx = NULL;
106 isc_nm_t *netmgr = NULL;
107 isc_taskmgr_t *taskmgr = NULL;
108 isc_task_t *global_task = NULL;
109 isc_sockaddr_t localaddr;
110 isc_refcount_t sendcount = 0;
111 isc_refcount_t recvcount = 0;
112 int ndots = -1;
113 int tries = -1;
114 int lookup_counter = 0;
115
116 static char servercookie[256];
117
118 #ifdef HAVE_LIBIDN2
119 static void
120 idn_locale_to_ace(const char *src, char *dst, size_t dstlen);
121 static void
122 idn_ace_to_locale(const char *src, char **dst);
123 static isc_result_t
124 idn_output_filter(isc_buffer_t *buffer, unsigned int used_org);
125 #endif /* HAVE_LIBIDN2 */
126
127 isc_nmhandle_t *keep = NULL;
128 isc_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 */
140 int exitcode = 0;
141 int fatalexit = 0;
142 char keynametext[MXNAME];
143 char keyfile[MXNAME] = "";
144 char keysecret[MXNAME] = "";
145 unsigned char cookie_secret[33];
146 unsigned char cookie[8];
147 const dns_name_t *hmacname = NULL;
148 unsigned int digestbits = 0;
149 isc_buffer_t *namebuf = NULL;
150 dns_tsigkey_t *tsigkey = NULL;
151 dst_key_t *sig0key = NULL;
152 bool validated = true;
153 bool debugging = false;
154 bool debugtiming = false;
155 bool memdebugging = false;
156 const char *progname = NULL;
157 isc_mutex_t lookup_lock;
158 dig_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
180 static void
181 default_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
191 static void
192 default_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
206 isc_result_t (*dighost_printmessage)(dig_query_t *query,
207 const isc_buffer_t *msgbuf,
208 dns_message_t *msg, bool headers);
209
210 void (*dighost_error)(const char *format, ...) = default_warnerr;
211
212 void (*dighost_warning)(const char *format, ...) = default_warnerr;
213
214 void (*dighost_comments)(dig_lookup_t *lookup, const char *format,
215 ...) = default_comments;
216
217 void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from,
218 dig_query_t *query);
219
220 void (*dighost_trying)(char *frm, dig_lookup_t *lookup);
221
222 void (*dighost_shutdown)(void);
223
224 /* forward declarations */
225
226 #define cancel_lookup(l) _cancel_lookup(l, __FILE__, __LINE__)
227 static void
228 _cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line);
229
230 static void
231 recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
232 void *arg);
233
234 static void
235 start_udp(dig_query_t *query);
236
237 static void
238 start_tcp(dig_query_t *query);
239
240 static void
241 force_next(dig_query_t *query);
242
243 static void
244 launch_next_query(dig_query_t *query);
245
246 static void
247 clear_current_lookup(void);
248
249 static bool
250 next_origin(dig_lookup_t *oldlookup);
251
252 static int
253 count_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
267 static void
268 hex_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 */
309 static isc_result_t
310 append(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
319 static isc_result_t
320 reverse_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
340 isc_result_t
341 get_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
388 void (*dighost_pre_exit_hook)(void) = NULL;
389
390 #if TARGET_OS_IPHONE
391 void
392 warn(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 */
403 void
404 warn(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
416 void
417 digexit(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
430 void
431 fatal(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
443 void
444 debug(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
462 void
463 check_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 */
474 dig_server_t *
475 make_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 */
492 static void
493 get_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
534 void
535 flush_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
548 void
549 set_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 */
585 void
586 clone_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 */
605 dig_lookup_t *
606 make_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
662 static void
663 cloneopts(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 */
699 dig_lookup_t *
700 clone_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 */
853 dig_lookup_t *
854 requeue_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
875 void
876 setup_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);
910 failure:
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
923 static isc_result_t
924 parse_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
940 isc_result_t
941 parse_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
945 isc_result_t
946 parse_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
950 static uint32_t
951 parse_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
963 isc_result_t
964 parse_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
1034 done:
1035 sa->length = prefix_length;
1036 *sap = sa;
1037
1038 return (ISC_R_SUCCESS);
1039 }
1040
1041 /*
1042 * Parse HMAC algorithm specification
1043 */
1044 void
1045 parse_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 */
1101 static isc_result_t
1102 read_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
1147 cleanup:
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
1158 void
1159 setup_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 }
1221 failure:
1222 if (dstkey != NULL) {
1223 dst_key_free(&dstkey);
1224 }
1225 }
1226
1227 static dig_searchlist_t *
1228 make_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
1237 static void
1238 clear_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
1246 static void
1247 create_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 */
1270 static void
1271 add_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 */
1281 void
1282 setup_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 */
1357 void
1358 set_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 */
1369 void
1370 setup_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
1415 typedef struct dig_ednsoptname {
1416 uint32_t code;
1417 const char *name;
1418 } dig_ednsoptname_t;
1419
1420 dig_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
1442 void
1443 save_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 */
1502 static void
1503 add_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 */
1520 static void
1521 add_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 */
1542 static void
1543 check_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 */
1571 static bool
1572 check_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
1590 static 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__)
1668 static 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__)
1683 static 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
1702 void
1703 destroy_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 */
1714 static void
1715 destroy_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
1734 static 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
1750 static 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 */
1786 void
1787 start_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 */
1828 static void
1829 clear_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 */
1863 static int
1864 followup_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 */
2041 static bool
2042 next_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 */
2100 static void
2101 insert_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
2156 static void
2157 compute_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
2165 static 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 */
2209 bool
2210 setup_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 */
2705 static void
2706 nssearch_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 */
2751 static void
2752 send_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
2801 static 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
2827 static isc_tlsctx_t *
2828 get_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);
2934 failure:
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
2951 static void
2952 tcp_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 */
2959 static void
2960 start_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;
3100 failure_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
3124 static void
3125 print_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
3132 static void
3133 send_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
3164 static void
3165 udp_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 */
3294 static void
3295 start_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 */
3360 static bool
3361 try_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
3385 static void
3386 force_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 */
3458 static void
3459 launch_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 */
3554 static void
3555 tcp_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 */
3692 static bool
3693 check_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);
3830 doexit:
3831 dighost_received(len, peer, query);
3832 return (true);
3833 }
3834
3835 static void
3836 process_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
3886 static void
3887 process_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
3924 static int
3925 ednsvers(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 */
3933 static void
3934 recv_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 }
4552 cancel_lookup:
4553 docancel = true;
4554 next_lookup:
4555 donext = true;
4556 detach_query:
4557 isc_nmhandle_detach(&query->readhandle);
4558 query_detach(&query);
4559 if (docancel) {
4560 cancel_lookup(l);
4561 }
4562 keep_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 */
4578 isc_result_t
4579 get_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
4601 int
4602 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
4603 isc_result_t result;
4604 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
4605 isc_netaddr_t netaddr;
4606 int count, i;
4607 dig_server_t *srv;
4608 char tmp[ISC_NETADDR_FORMATSIZE];
4609
4610 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 */
4636 void
4637 do_lookup(dig_lookup_t *lookup) {
4638 dig_query_t *query;
4639
4640 REQUIRE(lookup != NULL);
4641
4642 debug("do_lookup()");
4643 lookup->pending = true;
4644 query = ISC_LIST_HEAD(lookup->q);
4645 if (query != NULL) {
4646 REQUIRE(DIG_VALID_QUERY(query));
4647 if (lookup->tcp_mode) {
4648 start_tcp(query);
4649 } else {
4650 start_udp(query);
4651 }
4652 }
4653 }
4654
4655 /*%
4656 * Start everything in action upon task startup.
4657 */
4658 void
4659 onrun_callback(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 */
4672 void
4673 cancel_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
4716 void
4717 cleanup_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 */
4739 void
4740 destroy_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
4789 static isc_result_t
4790 idn_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 */
4834 cleanup:
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 */
4849 static void
4850 idn_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 */
4891 static void
4892 idn_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
4972 void
4973 dig_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
4986 bool
4987 dig_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