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