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