xref: /openbsd/usr.bin/dig/dighost.c (revision 55cc5ba3)
1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /* $Id: dighost.c,v 1.37 2020/12/21 11:41:08 florian Exp $ */
18 
19 /*! \file
20  *  \note
21  * Notice to programmers:  Do not use this code as an example of how to
22  * use the ISC library to perform DNS lookups.  Dig and Host both operate
23  * on the request level, since they allow fine-tuning of output and are
24  * intended as debugging tools.  As a result, they perform many of the
25  * functions which could be better handled using the dns_resolver
26  * functions in most applications.
27  */
28 
29 #include <sys/socket.h>
30 #include <sys/time.h>
31 #include <limits.h>
32 #include <locale.h>
33 #include <netdb.h>
34 #include <resolv.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38 #include <stdint.h>
39 
40 #include <dns/fixedname.h>
41 #include <dns/log.h>
42 #include <dns/message.h>
43 #include <dns/name.h>
44 #include <dns/rdata.h>
45 #include <dns/rdataclass.h>
46 #include <dns/rdatalist.h>
47 #include <dns/rdataset.h>
48 #include <dns/rdatatype.h>
49 #include <dns/result.h>
50 #include <dns/tsig.h>
51 
52 #include <dst/dst.h>
53 #include <dst/result.h>
54 
55 #include <isc/base64.h>
56 #include <isc/hex.h>
57 #include <isc/log.h>
58 #include <isc/result.h>
59 #include <isc/serial.h>
60 #include <isc/sockaddr.h>
61 #include <isc/task.h>
62 #include <isc/timer.h>
63 #include <isc/types.h>
64 #include <isc/util.h>
65 
66 #include <isccfg/namedconf.h>
67 #include <lwres/lwres.h>
68 
69 #include "dig.h"
70 
71 static lwres_conf_t  lwconfdata;
72 static lwres_conf_t *lwconf = &lwconfdata;
73 
74 dig_lookuplist_t lookup_list;
75 dig_serverlist_t server_list;
76 dig_serverlist_t root_hints_server_list;
77 dig_searchlistlist_t search_list;
78 
79 int
80 	check_ra = 0,
81 	have_ipv4 = 1,
82 	have_ipv6 = 1,
83 	specified_source = 0,
84 	free_now = 0,
85 	cancel_now = 0,
86 	usesearch = 0,
87 	showsearch = 0,
88 	qr = 0,
89 	is_dst_up = 0,
90 	keep_open = 0;
91 in_port_t port = 53;
92 unsigned int timeout = 0;
93 unsigned int extrabytes;
94 isc_log_t *lctx = NULL;
95 isc_taskmgr_t *taskmgr = NULL;
96 isc_task_t *global_task = NULL;
97 isc_timermgr_t *timermgr = NULL;
98 isc_socketmgr_t *socketmgr = NULL;
99 struct sockaddr_storage bind_address;
100 struct sockaddr_storage bind_any;
101 int sendcount = 0;
102 int recvcount = 0;
103 int sockcount = 0;
104 int ndots = -1;
105 int tries = 3;
106 int lookup_counter = 0;
107 
108 static char sitvalue[256];
109 
110 isc_socket_t *keep = NULL;
111 struct sockaddr_storage keepaddr;
112 
113 static const struct {
114 	const char *ns;
115 	const int af;
116 } root_hints[] = {
117 	{ "198.41.0.4", AF_INET },		/*  a.root-servers.net  */
118 	{ "2001:503:ba3e::2:30", AF_INET6 },	/*  a.root-servers.net  */
119 	{ "199.9.14.201", AF_INET },		/*  b.root-servers.net  */
120 	{ "2001:500:200::b", AF_INET6 },	/*  b.root-servers.net  */
121 	{ "192.33.4.12", AF_INET },		/*  c.root-servers.net  */
122 	{ "2001:500:2::c", AF_INET6 },		/*  c.root-servers.net  */
123 	{ "199.7.91.13", AF_INET },		/*  d.root-servers.net  */
124 	{ "2001:500:2d::d", AF_INET6 },		/*  d.root-servers.net  */
125 	{ "192.203.230.10", AF_INET },		/*  e.root-servers.net  */
126 	{ "2001:500:a8::e", AF_INET6 },		/*  e.root-servers.net  */
127 	{ "192.5.5.241", AF_INET },		/*  f.root-servers.net  */
128 	{ "2001:500:2f::f", AF_INET6 },		/*  f.root-servers.net  */
129 	{ "192.112.36.4", AF_INET },		/*  g.root-servers.net  */
130 	{ "2001:500:12::d0d", AF_INET6 },	/*  g.root-servers.net  */
131 	{ "198.97.190.53", AF_INET },		/*  h.root-servers.net  */
132 	{ "2001:500:1::53", AF_INET6 },		/*  h.root-servers.net */
133 	{ "192.36.148.17", AF_INET },		/*  i.root-servers.net  */
134 	{ "2001:7fe::53", AF_INET6 },		/*  i.root-servers.net  */
135 	{ "192.58.128.30", AF_INET },		/*  j.root-servers.net  */
136 	{ "2001:503:c27::2:30", AF_INET6 },	/*  j.root-servers.net  */
137 	{ "193.0.14.129", AF_INET },		/*  k.root-servers.net  */
138 	{ "2001:7fd::1", AF_INET6 },		/*  k.root-servers.net  */
139 	{ "199.7.83.42", AF_INET },		/*  l.root-servers.net  */
140 	{ "2001:500:9f::42", AF_INET6 },	/*  l.root-servers.net  */
141 	{ "202.12.27.33", AF_INET },		/*  m.root-servers.net  */
142 	{ "2001:dc3::35", AF_INET6 }		/*  m.root-servers.net  */
143 };
144 
145 /*%
146  * Exit Codes:
147  *
148  *\li	0   Everything went well, including things like NXDOMAIN
149  *\li	1   Usage error
150  *\li	7   Got too many RR's or Names
151  *\li	8   Couldn't open batch file
152  *\li	9   No reply from server
153  *\li	10  Internal error
154  */
155 int exitcode = 0;
156 int fatalexit = 0;
157 char keynametext[MXNAME];
158 char keyfile[MXNAME] = "";
159 char keysecret[MXNAME] = "";
160 unsigned char cookie_secret[33];
161 unsigned char cookie[8];
162 dns_name_t *hmacname = NULL;
163 unsigned int digestbits = 0;
164 isc_buffer_t *namebuf = NULL;
165 dns_tsigkey_t *tsigkey = NULL;
166 int validated = 1;
167 int debugging = 0;
168 int debugtiming = 0;
169 char *progname = NULL;
170 dig_lookup_t *current_lookup = NULL;
171 
172 #define DIG_MAX_ADDRESSES 20
173 
174 /* dynamic callbacks */
175 
176 isc_result_t
177 (*dighost_printmessage)(dig_query_t *query, dns_message_t *msg,
178 	int headers);
179 
180 void
181 (*dighost_received)(unsigned int bytes, struct sockaddr_storage *from, dig_query_t *query);
182 
183 void
184 (*dighost_trying)(char *frm, dig_lookup_t *lookup);
185 
186 void
187 (*dighost_shutdown)(void);
188 
189 /* forward declarations */
190 
191 static void
192 cancel_lookup(dig_lookup_t *lookup);
193 
194 static void
195 recv_done(isc_task_t *task, isc_event_t *event);
196 
197 static void
198 send_udp(dig_query_t *query);
199 
200 static void
201 connect_timeout(isc_task_t *task, isc_event_t *event);
202 
203 static void
204 launch_next_query(dig_query_t *query, int include_question);
205 
206 static void
207 check_next_lookup(dig_lookup_t *lookup);
208 
209 static int
210 next_origin(dig_lookup_t *oldlookup);
211 
212 char *
213 next_token(char **stringp, const char *delim) {
214 	char *res;
215 
216 	do {
217 		res = strsep(stringp, delim);
218 		if (res == NULL)
219 			break;
220 	} while (*res == '\0');
221 	return (res);
222 }
223 
224 static int
225 count_dots(char *string) {
226 	char *s;
227 	int i = 0;
228 
229 	s = string;
230 	while (*s != '\0') {
231 		if (*s == '.')
232 			i++;
233 		s++;
234 	}
235 	return (i);
236 }
237 
238 static void
239 hex_dump(isc_buffer_t *b) {
240 	unsigned int len, i;
241 	isc_region_t r;
242 
243 	isc_buffer_usedregion(b, &r);
244 
245 	printf("%u bytes\n", r.length);
246 	for (len = 0; len < r.length; len++) {
247 		printf("%02x ", r.base[len]);
248 		if (len % 16 == 15) {
249 			fputs("         ", stdout);
250 			for (i = len - 15; i <= len; i++) {
251 				if (r.base[i] >= '!' && r.base[i] <= '}')
252 					putchar(r.base[i]);
253 				else
254 					putchar('.');
255 			}
256 			printf("\n");
257 		}
258 	}
259 	if (len % 16 != 0) {
260 		for (i = len; (i % 16) != 0; i++)
261 			fputs("   ", stdout);
262 		fputs("         ", stdout);
263 		for (i = ((len>>4)<<4); i < len; i++) {
264 			if (r.base[i] >= '!' && r.base[i] <= '}')
265 				putchar(r.base[i]);
266 			else
267 				putchar('.');
268 		}
269 		printf("\n");
270 	}
271 }
272 
273 /*%
274  * Append 'len' bytes of 'text' at '*p', failing with
275  * ISC_R_NOSPACE if that would advance p past 'end'.
276  */
277 static isc_result_t
278 append(const char *text, size_t len, char **p, char *end) {
279 	if (*p + len > end)
280 		return (ISC_R_NOSPACE);
281 	memmove(*p, text, len);
282 	*p += len;
283 	return (ISC_R_SUCCESS);
284 }
285 
286 static isc_result_t
287 reverse_octets(const char *in, char **p, char *end) {
288 	const char *dot = strchr(in, '.');
289 	size_t len;
290 	if (dot != NULL) {
291 		isc_result_t result;
292 		result = reverse_octets(dot + 1, p, end);
293 		if (result != ISC_R_SUCCESS)
294 			return (result);
295 		result = append(".", 1, p, end);
296 		if (result != ISC_R_SUCCESS)
297 			return (result);
298 		len = (int) (dot - in);
299 	} else {
300 		len = (int) strlen(in);
301 	}
302 	return (append(in, len, p, end));
303 }
304 
305 isc_result_t
306 get_reverse(char *reverse, size_t len, char *value, int ip6_int,
307 	    int strict)
308 {
309 	int r;
310 	struct in_addr in;
311 	struct in6_addr in6;
312 	isc_result_t result;
313 
314 	r = inet_pton(AF_INET6, value, &in6);
315 	if (r > 0) {
316 		/* This is a valid IPv6 address. */
317 		static char hex_digits[] = {
318 			'0', '1', '2', '3', '4', '5', '6', '7',
319 			'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
320 		};
321 		int i;
322 		unsigned char *bytes = (unsigned char *)&in6;
323 		char* cp;
324 
325 		if (len <= 15 * 4 + sizeof("ip6.int"))
326 			return (ISC_R_NOMEMORY);
327 
328 		cp = reverse;
329 		for (i = 15; i >= 0; i--) {
330 			*cp++ = hex_digits[bytes[i] & 0x0f];
331 			*cp++ = '.';
332 			*cp++ = hex_digits[(bytes[i] >> 4) & 0x0f];
333 			*cp++ = '.';
334 		}
335 		*cp = '\0';
336 		if (strlcat(reverse, ip6_int ? "ip6.int" : "ip6.arpa", len)
337 		    >= len)
338 			return (ISC_R_NOSPACE);
339 		return (ISC_R_SUCCESS);
340 	} else {
341 		/*
342 		 * Not a valid IPv6 address.  Assume IPv4.
343 		 * If 'strict' is not set, construct the
344 		 * in-addr.arpa name by blindly reversing
345 		 * octets whether or not they look like integers,
346 		 * so that this can be used for RFC2317 names
347 		 * and such.
348 		 */
349 		char *p = reverse;
350 		char *end = reverse + len;
351 		if (strict && inet_pton(AF_INET, value, &in) != 1)
352 			return (DNS_R_BADDOTTEDQUAD);
353 		result = reverse_octets(value, &p, end);
354 		if (result != ISC_R_SUCCESS)
355 			return (result);
356 		/* Append .in-addr.arpa. and a terminating NUL. */
357 		result = append(".in-addr.arpa.", 15, &p, end);
358 		return (result);
359 	}
360 }
361 
362 void
363 fatal(const char *format, ...) {
364 	va_list args;
365 
366 	fflush(stdout);
367 	fprintf(stderr, "%s: ", progname);
368 	va_start(args, format);
369 	vfprintf(stderr, format, args);
370 	va_end(args);
371 	fprintf(stderr, "\n");
372 	if (exitcode < 10)
373 		exitcode = 10;
374 	if (fatalexit != 0)
375 		exitcode = fatalexit;
376 	exit(exitcode);
377 }
378 
379 void
380 debug(const char *format, ...) {
381 	va_list args;
382 	struct timespec t;
383 
384 	if (debugging) {
385 		fflush(stdout);
386 		if (debugtiming) {
387 			clock_gettime(CLOCK_MONOTONIC, &t);
388 			fprintf(stderr, "%lld.%06ld: ", t.tv_sec, t.tv_nsec /
389 			    1000);
390 		}
391 		va_start(args, format);
392 		vfprintf(stderr, format, args);
393 		va_end(args);
394 		fprintf(stderr, "\n");
395 	}
396 }
397 
398 void
399 check_result(isc_result_t result, const char *msg) {
400 	if (result != ISC_R_SUCCESS) {
401 		fatal("%s: %s", msg, isc_result_totext(result));
402 	}
403 }
404 
405 /*%
406  * Create a server structure, which is part of the lookup structure.
407  * This is little more than a linked list of servers to query in hopes
408  * of finding the answer the user is looking for
409  */
410 dig_server_t *
411 make_server(const char *servname, const char *userarg) {
412 	dig_server_t *srv;
413 
414 	REQUIRE(servname != NULL);
415 
416 	debug("make_server(%s)", servname);
417 	srv = malloc(sizeof(struct dig_server));
418 	if (srv == NULL)
419 		fatal("memory allocation failure in %s:%d",
420 		      __FILE__, __LINE__);
421 	strlcpy(srv->servername, servname, MXNAME);
422 	strlcpy(srv->userarg, userarg, MXNAME);
423 	ISC_LINK_INIT(srv, link);
424 	return (srv);
425 }
426 
427 static int
428 addr2af(int lwresaddrtype)
429 {
430 	int af = 0;
431 
432 	switch (lwresaddrtype) {
433 	case LWRES_ADDRTYPE_V4:
434 		af = AF_INET;
435 		break;
436 
437 	case LWRES_ADDRTYPE_V6:
438 		af = AF_INET6;
439 		break;
440 	}
441 
442 	return (af);
443 }
444 
445 /*%
446  * Create a copy of the server list from the lwres configuration structure.
447  * The dest list must have already had ISC_LIST_INIT applied.
448  */
449 static void
450 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
451 	dig_server_t *newsrv;
452 	char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
453 		 sizeof("%4000000000")];
454 	int af;
455 	int i;
456 
457 	debug("copy_server_list()");
458 	for (i = 0; i < confdata->nsnext; i++) {
459 		af = addr2af(confdata->nameservers[i].family);
460 
461 		if (af == AF_INET && !have_ipv4)
462 			continue;
463 		if (af == AF_INET6 && !have_ipv6)
464 			continue;
465 
466 		inet_ntop(af, confdata->nameservers[i].address,
467 				   tmp, sizeof(tmp));
468 		if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
469 			char buf[sizeof("%4000000000")];
470 			snprintf(buf, sizeof(buf), "%%%u",
471 				 confdata->nameservers[i].zone);
472 			strlcat(tmp, buf, sizeof(tmp));
473 		}
474 		newsrv = make_server(tmp, tmp);
475 		ISC_LINK_INIT(newsrv, link);
476 		ISC_LIST_ENQUEUE(*dest, newsrv, link);
477 	}
478 }
479 
480 void
481 flush_server_list(void) {
482 	dig_server_t *s, *ps;
483 
484 	debug("flush_server_list()");
485 	s = ISC_LIST_HEAD(server_list);
486 	while (s != NULL) {
487 		ps = s;
488 		s = ISC_LIST_NEXT(s, link);
489 		ISC_LIST_DEQUEUE(server_list, ps, link);
490 		free(ps);
491 	}
492 }
493 
494 /* this used to be bind9_getaddresses from lib/bind9 */
495 static isc_result_t
496 get_addresses(const char *hostname, in_port_t dstport,
497 		   struct sockaddr_storage *addrs, int addrsize, int *addrcount)
498 {
499 	struct addrinfo *ai = NULL, *tmpai, hints;
500 	int result, i;
501 	char dport[sizeof("65535")];
502 
503 	REQUIRE(hostname != NULL);
504 	REQUIRE(addrs != NULL);
505 	REQUIRE(addrcount != NULL);
506 	REQUIRE(addrsize > 0);
507 
508 	memset(&hints, 0, sizeof(hints));
509 	if (!have_ipv6)
510 		hints.ai_family = PF_INET;
511 	else if (!have_ipv4)
512 		hints.ai_family = PF_INET6;
513 	else {
514 		hints.ai_family = PF_UNSPEC;
515 		hints.ai_flags = AI_ADDRCONFIG;
516 	}
517 	hints.ai_socktype = SOCK_DGRAM;
518 
519 	snprintf(dport, sizeof(dport), "%d", dstport);
520 	result = getaddrinfo(hostname, dport, &hints, &ai);
521 	switch (result) {
522 	case 0:
523 		break;
524 	case EAI_NONAME:
525 	case EAI_NODATA:
526 		return (ISC_R_NOTFOUND);
527 	default:
528 		return (ISC_R_FAILURE);
529 	}
530 	for (tmpai = ai, i = 0;
531 	     tmpai != NULL && i < addrsize;
532 	     tmpai = tmpai->ai_next)
533 	{
534 		if (tmpai->ai_family != AF_INET &&
535 		    tmpai->ai_family != AF_INET6)
536 			continue;
537 		if (tmpai->ai_addrlen > sizeof(addrs[i]))
538 			continue;
539 		memset(&addrs[i], 0, sizeof(addrs[i]));
540 		memcpy(&addrs[i], tmpai->ai_addr, tmpai->ai_addrlen);
541 		i++;
542 
543 	}
544 	freeaddrinfo(ai);
545 	*addrcount = i;
546 	if (*addrcount == 0)
547 		return (ISC_R_NOTFOUND);
548 	else
549 		return (ISC_R_SUCCESS);
550 }
551 
552 isc_result_t
553 set_nameserver(char *opt) {
554 	isc_result_t result;
555 	struct sockaddr_storage sockaddrs[DIG_MAX_ADDRESSES];
556 	int count, i;
557 	dig_server_t *srv;
558 	char tmp[NI_MAXHOST];
559 
560 	if (opt == NULL)
561 		return ISC_R_NOTFOUND;
562 
563 	result = get_addresses(opt, 0, sockaddrs,
564 				    DIG_MAX_ADDRESSES, &count);
565 	if (result != ISC_R_SUCCESS)
566 		return (result);
567 
568 	flush_server_list();
569 
570 	for (i = 0; i < count; i++) {
571 		int error;
572 		error = getnameinfo((struct sockaddr *)&sockaddrs[i],
573 		    sockaddrs[i].ss_len, tmp, sizeof(tmp), NULL, 0,
574 		    NI_NUMERICHOST | NI_NUMERICSERV);
575 		if (error)
576 			fatal("%s", gai_strerror(error));
577 		srv = make_server(tmp, opt);
578 		if (srv == NULL)
579 			fatal("memory allocation failure");
580 		ISC_LIST_APPEND(server_list, srv, link);
581 	}
582 	return (ISC_R_SUCCESS);
583 }
584 
585 static isc_result_t
586 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
587 
588 	int i = confdata->nsnext;
589 
590 	if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
591 		return (ISC_R_FAILURE);
592 
593 	switch (af) {
594 	case AF_INET:
595 		confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
596 		confdata->nameservers[i].length = sizeof(struct in_addr);
597 		break;
598 	case AF_INET6:
599 		confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
600 		confdata->nameservers[i].length = sizeof(struct in6_addr);
601 		break;
602 	default:
603 		return (ISC_R_FAILURE);
604 	}
605 
606 	if (inet_pton(af, addr, &confdata->nameservers[i].address) == 1) {
607 		confdata->nsnext++;
608 		return (ISC_R_SUCCESS);
609 	}
610 	return (ISC_R_FAILURE);
611 }
612 
613 /*%
614  * Produce a cloned server list.  The dest list must have already had
615  * ISC_LIST_INIT applied.
616  */
617 void
618 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
619 	dig_server_t *srv, *newsrv;
620 
621 	debug("clone_server_list()");
622 	srv = ISC_LIST_HEAD(src);
623 	while (srv != NULL) {
624 		newsrv = make_server(srv->servername, srv->userarg);
625 		ISC_LINK_INIT(newsrv, link);
626 		ISC_LIST_ENQUEUE(*dest, newsrv, link);
627 		srv = ISC_LIST_NEXT(srv, link);
628 	}
629 }
630 
631 /*%
632  * Create an empty lookup structure, which holds all the information needed
633  * to get an answer to a user's question.  This structure contains two
634  * linked lists: the server list (servers to query) and the query list
635  * (outstanding queries which have been made to the listed servers).
636  */
637 dig_lookup_t *
638 make_empty_lookup(void) {
639 	dig_lookup_t *looknew;
640 
641 	debug("make_empty_lookup()");
642 
643 	INSIST(!free_now);
644 
645 	looknew = malloc(sizeof(struct dig_lookup));
646 	if (looknew == NULL)
647 		fatal("memory allocation failure in %s:%d",
648 		       __FILE__, __LINE__);
649 	looknew->pending = 1;
650 	looknew->textname[0] = 0;
651 	looknew->cmdline[0] = 0;
652 	looknew->rdtype = dns_rdatatype_a;
653 	looknew->qrdtype = dns_rdatatype_a;
654 	looknew->rdclass = dns_rdataclass_in;
655 	looknew->rdtypeset = 0;
656 	looknew->rdclassset = 0;
657 	looknew->sendspace = NULL;
658 	looknew->sendmsg = NULL;
659 	looknew->name = NULL;
660 	looknew->oname = NULL;
661 	looknew->xfr_q = NULL;
662 	looknew->current_query = NULL;
663 	looknew->doing_xfr = 0;
664 	looknew->ixfr_serial = 0;
665 	looknew->trace = 0;
666 	looknew->trace_root = 0;
667 	looknew->identify = 0;
668 	looknew->identify_previous_line = 0;
669 	looknew->ignore = 0;
670 	looknew->servfail_stops = 1;
671 	looknew->besteffort = 1;
672 	looknew->dnssec = 0;
673 	looknew->ednsflags = 0;
674 	looknew->opcode = dns_opcode_query;
675 	looknew->expire = 0;
676 	looknew->nsid = 0;
677 	looknew->idnout = 0;
678 	looknew->sit = 0;
679 	looknew->udpsize = 0;
680 	looknew->edns = -1;
681 	looknew->recurse = 1;
682 	looknew->aaonly = 0;
683 	looknew->adflag = 0;
684 	looknew->cdflag = 0;
685 	looknew->ns_search_only = 0;
686 	looknew->origin = NULL;
687 	looknew->tsigctx = NULL;
688 	looknew->querysig = NULL;
689 	looknew->retries = tries;
690 	looknew->nsfound = 0;
691 	looknew->tcp_mode = 0;
692 	looknew->tcp_mode_set = 0;
693 	looknew->ip6_int = 0;
694 	looknew->comments = 1;
695 	looknew->stats = 1;
696 	looknew->section_question = 1;
697 	looknew->section_answer = 1;
698 	looknew->section_authority = 1;
699 	looknew->section_additional = 1;
700 	looknew->new_search = 0;
701 	looknew->done_as_is = 0;
702 	looknew->need_search = 0;
703 	looknew->ecs_addr = NULL;
704 	looknew->ecs_plen = 0;
705 	looknew->sitvalue = NULL;
706 	looknew->ednsopts = NULL;
707 	looknew->ednsoptscnt = 0;
708 	looknew->ednsneg = 0;
709 	looknew->eoferr = 0;
710 	dns_fixedname_init(&looknew->fdomain);
711 	ISC_LINK_INIT(looknew, link);
712 	ISC_LIST_INIT(looknew->q);
713 	ISC_LIST_INIT(looknew->connecting);
714 	ISC_LIST_INIT(looknew->my_server_list);
715 	return (looknew);
716 }
717 
718 #define EDNSOPT_OPTIONS 100U
719 
720 static void
721 cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) {
722 	size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS;
723 	size_t i;
724 	looknew->ednsopts = malloc(len);
725 	if (looknew->ednsopts == NULL)
726 		fatal("out of memory");
727 	for (i = 0; i < EDNSOPT_OPTIONS; i++) {
728 		looknew->ednsopts[i].code = 0;
729 		looknew->ednsopts[i].length = 0;
730 		looknew->ednsopts[i].value = NULL;
731 	}
732 	looknew->ednsoptscnt = 0;
733 	if (lookold == NULL || lookold->ednsopts == NULL)
734 		return;
735 
736 	for (i = 0; i < lookold->ednsoptscnt; i++) {
737 		len = lookold->ednsopts[i].length;
738 		if (len != 0) {
739 			INSIST(lookold->ednsopts[i].value != NULL);
740 			looknew->ednsopts[i].value =
741 				 malloc(len);
742 			if (looknew->ednsopts[i].value == NULL)
743 				fatal("out of memory");
744 			memmove(looknew->ednsopts[i].value,
745 				lookold->ednsopts[i].value, len);
746 		}
747 		looknew->ednsopts[i].code = lookold->ednsopts[i].code;
748 		looknew->ednsopts[i].length = len;
749 	}
750 	looknew->ednsoptscnt = lookold->ednsoptscnt;
751 }
752 
753 /*%
754  * Clone a lookup, perhaps copying the server list.  This does not clone
755  * the query list, since it will be regenerated by the setup_lookup()
756  * function, nor does it queue up the new lookup for processing.
757  * Caution: If you don't clone the servers, you MUST clone the server
758  * list separately from somewhere else, or construct it by hand.
759  */
760 dig_lookup_t *
761 clone_lookup(dig_lookup_t *lookold, int servers) {
762 	dig_lookup_t *looknew;
763 
764 	debug("clone_lookup()");
765 
766 	INSIST(!free_now);
767 
768 	looknew = make_empty_lookup();
769 	INSIST(looknew != NULL);
770 	strlcpy(looknew->textname, lookold->textname, MXNAME);
771 	strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
772 	looknew->textname[MXNAME-1] = 0;
773 	looknew->rdtype = lookold->rdtype;
774 	looknew->qrdtype = lookold->qrdtype;
775 	looknew->rdclass = lookold->rdclass;
776 	looknew->rdtypeset = lookold->rdtypeset;
777 	looknew->rdclassset = lookold->rdclassset;
778 	looknew->doing_xfr = lookold->doing_xfr;
779 	looknew->ixfr_serial = lookold->ixfr_serial;
780 	looknew->trace = lookold->trace;
781 	looknew->trace_root = lookold->trace_root;
782 	looknew->identify = lookold->identify;
783 	looknew->identify_previous_line = lookold->identify_previous_line;
784 	looknew->ignore = lookold->ignore;
785 	looknew->servfail_stops = lookold->servfail_stops;
786 	looknew->besteffort = lookold->besteffort;
787 	looknew->dnssec = lookold->dnssec;
788 	looknew->ednsflags = lookold->ednsflags;
789 	looknew->opcode = lookold->opcode;
790 	looknew->expire = lookold->expire;
791 	looknew->nsid = lookold->nsid;
792 	looknew->sit = lookold->sit;
793 	looknew->sitvalue = lookold->sitvalue;
794 	if (lookold->ednsopts != NULL) {
795 		cloneopts(looknew, lookold);
796 	} else {
797 		looknew->ednsopts = NULL;
798 		looknew->ednsoptscnt = 0;
799 	}
800 	looknew->ednsneg = lookold->ednsneg;
801 	looknew->idnout = lookold->idnout;
802 	looknew->udpsize = lookold->udpsize;
803 	looknew->edns = lookold->edns;
804 	looknew->recurse = lookold->recurse;
805 	looknew->aaonly = lookold->aaonly;
806 	looknew->adflag = lookold->adflag;
807 	looknew->cdflag = lookold->cdflag;
808 	looknew->ns_search_only = lookold->ns_search_only;
809 	looknew->tcp_mode = lookold->tcp_mode;
810 	looknew->tcp_mode_set = lookold->tcp_mode_set;
811 	looknew->comments = lookold->comments;
812 	looknew->stats = lookold->stats;
813 	looknew->section_question = lookold->section_question;
814 	looknew->section_answer = lookold->section_answer;
815 	looknew->section_authority = lookold->section_authority;
816 	looknew->section_additional = lookold->section_additional;
817 	looknew->origin = lookold->origin;
818 	looknew->retries = lookold->retries;
819 	looknew->tsigctx = NULL;
820 	looknew->need_search = lookold->need_search;
821 	looknew->done_as_is = lookold->done_as_is;
822 	looknew->eoferr = lookold->eoferr;
823 
824 	if (lookold->ecs_addr != NULL) {
825 		size_t len = sizeof(struct sockaddr_storage);
826 		looknew->ecs_addr = malloc(len);
827 		if (looknew->ecs_addr == NULL)
828 			fatal("out of memory");
829 		memmove(looknew->ecs_addr, lookold->ecs_addr, len);
830 		looknew->ecs_plen = lookold->ecs_plen;
831 	}
832 
833 	dns_name_copy(dns_fixedname_name(&lookold->fdomain),
834 		      dns_fixedname_name(&looknew->fdomain), NULL);
835 
836 	if (servers)
837 		clone_server_list(lookold->my_server_list,
838 				  &looknew->my_server_list);
839 	return (looknew);
840 }
841 
842 /*%
843  * Requeue a lookup for further processing, perhaps copying the server
844  * list.  The new lookup structure is returned to the caller, and is
845  * queued for processing.  If servers are not cloned in the requeue, they
846  * must be added before allowing the current event to complete, since the
847  * completion of the event may result in the next entry on the lookup
848  * queue getting run.
849  */
850 dig_lookup_t *
851 requeue_lookup(dig_lookup_t *lookold, int servers) {
852 	dig_lookup_t *looknew;
853 
854 	debug("requeue_lookup()");
855 
856 	lookup_counter++;
857 	if (lookup_counter > LOOKUP_LIMIT)
858 		fatal("too many lookups");
859 
860 	looknew = clone_lookup(lookold, servers);
861 	INSIST(looknew != NULL);
862 
863 	debug("before insertion, init@%p -> %p, new@%p -> %p",
864 	      lookold, lookold->link.next, looknew, looknew->link.next);
865 	ISC_LIST_PREPEND(lookup_list, looknew, link);
866 	debug("after insertion, init -> %p, new = %p, new -> %p",
867 	      lookold, looknew, looknew->link.next);
868 	return (looknew);
869 }
870 
871 void
872 setup_text_key(void) {
873 	isc_result_t result;
874 	dns_name_t keyname;
875 	isc_buffer_t secretbuf;
876 	unsigned int secretsize;
877 	unsigned char *secretstore;
878 
879 	debug("setup_text_key()");
880 	result = isc_buffer_allocate(&namebuf, MXNAME);
881 	check_result(result, "isc_buffer_allocate");
882 	dns_name_init(&keyname, NULL);
883 	check_result(result, "dns_name_init");
884 	isc_buffer_putstr(namebuf, keynametext);
885 	secretsize = (unsigned int) strlen(keysecret) * 3 / 4;
886 	secretstore = malloc(secretsize);
887 	if (secretstore == NULL)
888 		fatal("memory allocation failure in %s:%d",
889 		      __FILE__, __LINE__);
890 	isc_buffer_init(&secretbuf, secretstore, secretsize);
891 	result = isc_base64_decodestring(keysecret, &secretbuf);
892 	if (result != ISC_R_SUCCESS)
893 		goto failure;
894 
895 	secretsize = isc_buffer_usedlength(&secretbuf);
896 
897 	if (hmacname == NULL) {
898 		result = DST_R_UNSUPPORTEDALG;
899 		goto failure;
900 	}
901 
902 	result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
903 	if (result != ISC_R_SUCCESS)
904 		goto failure;
905 
906 	result = dns_tsigkey_create(&keyname, hmacname, secretstore,
907 				    (int)secretsize, 0, NULL, 0, 0,
908 				    &tsigkey);
909  failure:
910 	if (result != ISC_R_SUCCESS)
911 		printf(";; Couldn't create key %s: %s\n",
912 		       keynametext, isc_result_totext(result));
913 	else
914 		dst_key_setbits(tsigkey->key, digestbits);
915 
916 	free(secretstore);
917 	dns_name_invalidate(&keyname);
918 	isc_buffer_free(&namebuf);
919 }
920 
921 static uint32_t
922 parse_bits(char *arg, uint32_t max) {
923 	uint32_t tmp;
924 	const char *errstr;
925 
926 	tmp = strtonum(arg, 0, max, &errstr);
927 	if (errstr != NULL)
928 		fatal("digest bits is %s: '%s'", errstr, arg);
929 	tmp = (tmp + 7) & ~0x7U;
930 	return (tmp);
931 }
932 
933 isc_result_t
934 parse_netprefix(struct sockaddr_storage **sap, int *plen, const char *value) {
935 	struct sockaddr_storage *sa = NULL;
936 	struct in_addr *in4;
937 	struct in6_addr *in6;
938 	int prefix_length;
939 
940 	REQUIRE(sap != NULL && *sap == NULL);
941 
942 	sa = calloc(1, sizeof(*sa));
943 	if (sa == NULL)
944 		fatal("out of memory");
945 
946 	in4 = &((struct sockaddr_in *)sa)->sin_addr;
947 	in6 = &((struct sockaddr_in6 *)sa)->sin6_addr;
948 
949 	if (strcmp(value, "0") == 0) {
950 		sa->ss_family = AF_UNSPEC;
951 		prefix_length = 0;
952 		goto done;
953 	}
954 
955 	if ((prefix_length = inet_net_pton(AF_INET6, value, in6, sizeof(*in6)))
956 	    != -1) {
957 		sa->ss_len = sizeof(struct sockaddr_in6);
958 		sa->ss_family = AF_INET6;
959 	} else if ((prefix_length = inet_net_pton(AF_INET, value, in4,
960 	    sizeof(*in4))) != -1) {
961 		sa->ss_len = sizeof(struct sockaddr_in);
962 		sa->ss_family = AF_INET;
963 	} else
964 		fatal("invalid address '%s'", value);
965 
966 done:
967 	*plen = prefix_length;
968 	*sap = sa;
969 
970 	return (ISC_R_SUCCESS);
971 }
972 
973 /*
974  * Parse HMAC algorithm specification
975  */
976 void
977 parse_hmac(const char *hmac) {
978 	char buf[20];
979 	size_t len;
980 
981 	REQUIRE(hmac != NULL);
982 
983 	len = strlen(hmac);
984 	if (len >= sizeof(buf))
985 		fatal("unknown key type '%.*s'", (int)len, hmac);
986 	strlcpy(buf, hmac, sizeof(buf));
987 
988 	digestbits = 0;
989 
990 	if (strcasecmp(buf, "hmac-sha1") == 0) {
991 		hmacname = DNS_TSIG_HMACSHA1_NAME;
992 		digestbits = 0;
993 	} else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
994 		hmacname = DNS_TSIG_HMACSHA1_NAME;
995 		digestbits = parse_bits(&buf[10], 160);
996 	} else if (strcasecmp(buf, "hmac-sha224") == 0) {
997 		hmacname = DNS_TSIG_HMACSHA224_NAME;
998 	} else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
999 		hmacname = DNS_TSIG_HMACSHA224_NAME;
1000 		digestbits = parse_bits(&buf[12], 224);
1001 	} else if (strcasecmp(buf, "hmac-sha256") == 0) {
1002 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1003 	} else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1004 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1005 		digestbits = parse_bits(&buf[12], 256);
1006 	} else if (strcasecmp(buf, "hmac-sha384") == 0) {
1007 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1008 	} else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1009 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1010 		digestbits = parse_bits(&buf[12], 384);
1011 	} else if (strcasecmp(buf, "hmac-sha512") == 0) {
1012 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1013 	} else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1014 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1015 		digestbits = parse_bits(&buf[12], 512);
1016 	} else {
1017 		fprintf(stderr, ";; Warning, ignoring "
1018 			"invalid TSIG algorithm %s\n", buf);
1019 	}
1020 }
1021 
1022 /*
1023  * Get a key from a named.conf format keyfile
1024  */
1025 static isc_result_t
1026 read_confkey(void) {
1027 	cfg_parser_t *pctx = NULL;
1028 	cfg_obj_t *file = NULL;
1029 	const cfg_obj_t *keyobj = NULL;
1030 	const cfg_obj_t *secretobj = NULL;
1031 	const cfg_obj_t *algorithmobj = NULL;
1032 	const char *keyname;
1033 	const char *secretstr;
1034 	const char *algorithm;
1035 	isc_result_t result;
1036 
1037 	result = cfg_parser_create(NULL, &pctx);
1038 	if (result != ISC_R_SUCCESS)
1039 		goto cleanup;
1040 
1041 	result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1042 				&file);
1043 	if (result != ISC_R_SUCCESS)
1044 		goto cleanup;
1045 
1046 	result = cfg_map_get(file, "key", &keyobj);
1047 	if (result != ISC_R_SUCCESS)
1048 		goto cleanup;
1049 
1050 	(void) cfg_map_get(keyobj, "secret", &secretobj);
1051 	(void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
1052 	if (secretobj == NULL || algorithmobj == NULL)
1053 		fatal("key must have algorithm and secret");
1054 
1055 	keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
1056 	secretstr = cfg_obj_asstring(secretobj);
1057 	algorithm = cfg_obj_asstring(algorithmobj);
1058 
1059 	strlcpy(keynametext, keyname, sizeof(keynametext));
1060 	strlcpy(keysecret, secretstr, sizeof(keysecret));
1061 	parse_hmac(algorithm);
1062 	setup_text_key();
1063 
1064  cleanup:
1065 	if (pctx != NULL) {
1066 		if (file != NULL)
1067 			cfg_obj_destroy(pctx, &file);
1068 		cfg_parser_destroy(&pctx);
1069 	}
1070 
1071 	return (result);
1072 }
1073 
1074 void
1075 setup_file_key(void) {
1076 	isc_result_t result;
1077 
1078 	debug("setup_file_key()");
1079 
1080 	/* Try reading the key as a session.key keyfile */
1081 	result = read_confkey();
1082 
1083 	if (result != ISC_R_SUCCESS)
1084 		fprintf(stderr, "Couldn't read key from %s: %s\n",
1085 			keyfile, isc_result_totext(result));
1086 }
1087 
1088 static dig_searchlist_t *
1089 make_searchlist_entry(char *domain) {
1090 	dig_searchlist_t *search;
1091 	search = malloc(sizeof(*search));
1092 	if (search == NULL)
1093 		fatal("memory allocation failure in %s:%d",
1094 		      __FILE__, __LINE__);
1095 	strlcpy(search->origin, domain, MXNAME);
1096 	search->origin[MXNAME-1] = 0;
1097 	ISC_LINK_INIT(search, link);
1098 	return (search);
1099 }
1100 
1101 static void
1102 clear_searchlist(void) {
1103 	dig_searchlist_t *search;
1104 	while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1105 		ISC_LIST_UNLINK(search_list, search, link);
1106 		free(search);
1107 	}
1108 }
1109 
1110 static void
1111 create_search_list(lwres_conf_t *confdata) {
1112 	int i;
1113 	dig_searchlist_t *search;
1114 
1115 	debug("create_search_list()");
1116 	clear_searchlist();
1117 
1118 	for (i = 0; i < confdata->searchnxt; i++) {
1119 		search = make_searchlist_entry(confdata->search[i]);
1120 		ISC_LIST_APPEND(search_list, search, link);
1121 	}
1122 }
1123 
1124 /*%
1125  * Setup the system as a whole, reading key information and resolv.conf
1126  * settings.
1127  */
1128 void
1129 setup_system(int ipv4only, int ipv6only) {
1130 	dig_searchlist_t *domain = NULL;
1131 	lwres_result_t lwresult;
1132 	int lwresflags = 0;
1133 
1134 	debug("setup_system()");
1135 
1136 	if (ipv4only) {
1137 		if (have_ipv4)
1138 			have_ipv6 = 0;
1139 		else
1140 			fatal("can't find IPv4 networking");
1141 	}
1142 
1143 	if (ipv6only) {
1144 		if (have_ipv6)
1145 			have_ipv4 = 0;
1146 		else
1147 			fatal("can't find IPv6 networking");
1148 	}
1149 
1150 	if (have_ipv4)
1151 		lwresflags |= LWRES_USEIPV4;
1152 	if (have_ipv6)
1153 		lwresflags |= LWRES_USEIPV6;
1154 	lwres_conf_init(lwconf, lwresflags);
1155 
1156 	lwresult = lwres_conf_parse(lwconf, _PATH_RESCONF);
1157 	if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1158 		fatal("parse of %s failed", _PATH_RESCONF);
1159 
1160 	/* Make the search list */
1161 	if (lwconf->searchnxt > 0)
1162 		create_search_list(lwconf);
1163 	else { /* No search list. Use the domain name if any */
1164 		if (lwconf->domainname != NULL) {
1165 			domain = make_searchlist_entry(lwconf->domainname);
1166 			ISC_LIST_APPEND(search_list, domain, link);
1167 			domain  = NULL;
1168 		}
1169 	}
1170 
1171 	if (ndots == -1) {
1172 		ndots = lwconf->ndots;
1173 		debug("ndots is %d.", ndots);
1174 	}
1175 
1176 	/* If user doesn't specify server use nameservers from resolv.conf. */
1177 	if (ISC_LIST_EMPTY(server_list))
1178 		copy_server_list(lwconf, &server_list);
1179 
1180 	/* If we don't find a nameserver fall back to localhost */
1181 	if (ISC_LIST_EMPTY(server_list)) {
1182 		if (have_ipv4) {
1183 			lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1184 			if (lwresult != ISC_R_SUCCESS)
1185 				fatal("add_nameserver failed");
1186 		}
1187 		if (have_ipv6) {
1188 			lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1189 			if (lwresult != ISC_R_SUCCESS)
1190 				fatal("add_nameserver failed");
1191 		}
1192 
1193 		copy_server_list(lwconf, &server_list);
1194 	}
1195 
1196 	if (keyfile[0] != 0)
1197 		setup_file_key();
1198 	else if (keysecret[0] != 0)
1199 		setup_text_key();
1200 	arc4random_buf(cookie_secret, sizeof(cookie_secret));
1201 }
1202 
1203 /*%
1204  * Override the search list derived from resolv.conf by 'domain'.
1205  */
1206 void
1207 set_search_domain(char *domain) {
1208 	dig_searchlist_t *search;
1209 
1210 	clear_searchlist();
1211 	search = make_searchlist_entry(domain);
1212 	ISC_LIST_APPEND(search_list, search, link);
1213 }
1214 
1215 /*%
1216  * Setup the ISC and DNS libraries for use by the system.
1217  */
1218 void
1219 setup_libs(void) {
1220 	isc_result_t result;
1221 	isc_logconfig_t *logconfig = NULL;
1222 
1223 	debug("setup_libs()");
1224 
1225 	dns_result_register();
1226 
1227 	result = isc_log_create(&lctx, &logconfig);
1228 	check_result(result, "isc_log_create");
1229 
1230 	isc_log_setcontext(lctx);
1231 	dns_log_init(lctx);
1232 	dns_log_setcontext(lctx);
1233 
1234 	result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1235 	check_result(result, "isc_log_usechannel");
1236 
1237 	isc_log_setdebuglevel(lctx, 0);
1238 
1239 	result = isc_taskmgr_create(1, 0, &taskmgr);
1240 	check_result(result, "isc_taskmgr_create");
1241 
1242 	result = isc_task_create(taskmgr, 0, &global_task);
1243 	check_result(result, "isc_task_create");
1244 	isc_task_setname(global_task, "dig", NULL);
1245 
1246 	result = isc_timermgr_create(&timermgr);
1247 	check_result(result, "isc_timermgr_create");
1248 
1249 	result = isc_socketmgr_create(&socketmgr);
1250 	check_result(result, "isc_socketmgr_create");
1251 
1252 	check_result(result, "isc_entropy_create");
1253 
1254 	result = dst_lib_init();
1255 	check_result(result, "dst_lib_init");
1256 	is_dst_up = 1;
1257 }
1258 
1259 typedef struct dig_ednsoptname {
1260 	uint32_t code;
1261 	const char  *name;
1262 } dig_ednsoptname_t;
1263 
1264 dig_ednsoptname_t optnames[] = {
1265 	{ 3, "NSID" },		/* RFC 5001 */
1266 	{ 5, "DAU" },		/* RFC 6975 */
1267 	{ 6, "DHU" },		/* RFC 6975 */
1268 	{ 7, "N3U" },		/* RFC 6975 */
1269 	{ 8, "ECS" },		/* RFC 7871 */
1270 	{ 9, "EXPIRE" },	/* RFC 7314 */
1271 	{ 10, "COOKIE" },	/* RFC 7873 */
1272 	{ 11, "KEEPALIVE" },	/* RFC 7828 */
1273 	{ 12, "PADDING" },	/* RFC 7830 */
1274 	{ 12, "PAD" },		/* shorthand */
1275 	{ 13, "CHAIN" },	/* RFC 7901 */
1276 	{ 14, "KEY-TAG" },	/* RFC 8145 */
1277 	{ 26946, "DEVICEID" },	/* Brian Hartvigsen */
1278 };
1279 
1280 #define N_EDNS_OPTNAMES  (sizeof(optnames) / sizeof(optnames[0]))
1281 
1282 void
1283 save_opt(dig_lookup_t *lookup, char *code, char *value) {
1284 	isc_result_t result;
1285 	uint32_t num = 0;
1286 	isc_buffer_t b;
1287 	int found = 0;
1288 	unsigned int i;
1289 	const char *errstr;
1290 
1291 	if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS)
1292 		fatal("too many ednsopts");
1293 
1294 	for (i = 0; i < N_EDNS_OPTNAMES; i++) {
1295 		if (strcasecmp(code, optnames[i].name) == 0) {
1296 			num = optnames[i].code;
1297 			found = 1;
1298 			break;
1299 		}
1300 	}
1301 
1302 	if (!found) {
1303 		num = strtonum(code, 0, 65535, &errstr);
1304 		if (errstr != NULL)
1305 			fatal("edns code point is %s: '%s'", errstr, code);
1306 	}
1307 
1308 	if (lookup->ednsopts == NULL) {
1309 		cloneopts(lookup, NULL);
1310 	}
1311 
1312 	if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL)
1313 		free(lookup->ednsopts[lookup->ednsoptscnt].value);
1314 
1315 	lookup->ednsopts[lookup->ednsoptscnt].code = num;
1316 	lookup->ednsopts[lookup->ednsoptscnt].length = 0;
1317 	lookup->ednsopts[lookup->ednsoptscnt].value = NULL;
1318 
1319 	if (value != NULL) {
1320 		char *buf;
1321 		buf = malloc(strlen(value)/2 + 1);
1322 		if (buf == NULL)
1323 			fatal("out of memory");
1324 		isc_buffer_init(&b, buf, (unsigned int) strlen(value)/2 + 1);
1325 		result = isc_hex_decodestring(value, &b);
1326 		check_result(result, "isc_hex_decodestring");
1327 		lookup->ednsopts[lookup->ednsoptscnt].value =
1328 						 isc_buffer_base(&b);
1329 		lookup->ednsopts[lookup->ednsoptscnt].length =
1330 						 isc_buffer_usedlength(&b);
1331 	}
1332 
1333 	lookup->ednsoptscnt++;
1334 }
1335 
1336 /*%
1337  * Add EDNS0 option record to a message.  Currently, the only supported
1338  * options are UDP buffer size, the DO bit, and EDNS options
1339  * (e.g., NSID, SIT, client-subnet)
1340  */
1341 static void
1342 add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns,
1343 	unsigned int flags, dns_ednsopt_t *opts, size_t count)
1344 {
1345 	dns_rdataset_t *rdataset = NULL;
1346 	isc_result_t result;
1347 
1348 	debug("add_opt()");
1349 	result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
1350 				      opts, count);
1351 	check_result(result, "dns_message_buildopt");
1352 	result = dns_message_setopt(msg, rdataset);
1353 	check_result(result, "dns_message_setopt");
1354 }
1355 
1356 /*%
1357  * Add a question section to a message, asking for the specified name,
1358  * type, and class.
1359  */
1360 static void
1361 add_question(dns_message_t *message, dns_name_t *name,
1362 	     dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1363 {
1364 	dns_rdataset_t *rdataset;
1365 	isc_result_t result;
1366 
1367 	debug("add_question()");
1368 	rdataset = NULL;
1369 	result = dns_message_gettemprdataset(message, &rdataset);
1370 	check_result(result, "dns_message_gettemprdataset()");
1371 	dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1372 	ISC_LIST_APPEND(name->list, rdataset, link);
1373 }
1374 
1375 /*%
1376  * Check if we're done with all the queued lookups, which is true iff
1377  * all sockets, sends, and recvs are accounted for (counters == 0),
1378  * and the lookup list is empty.
1379  * If we are done, pass control back out to dighost_shutdown() (which is
1380  * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1381  * a whole or reseed the lookup list.
1382  */
1383 static void
1384 check_if_done(void) {
1385 	debug("check_if_done()");
1386 	debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1387 	if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1388 	    sendcount == 0) {
1389 		INSIST(sockcount == 0);
1390 		INSIST(recvcount == 0);
1391 		debug("shutting down");
1392 		dighost_shutdown();
1393 	}
1394 }
1395 
1396 /*%
1397  * Clear out a query when we're done with it.  WARNING: This routine
1398  * WILL invalidate the query pointer.
1399  */
1400 static void
1401 clear_query(dig_query_t *query) {
1402 	dig_lookup_t *lookup;
1403 
1404 	REQUIRE(query != NULL);
1405 
1406 	debug("clear_query(%p)", query);
1407 
1408 	if (query->timer != NULL)
1409 		isc_timer_detach(&query->timer);
1410 	lookup = query->lookup;
1411 
1412 	if (lookup->current_query == query)
1413 		lookup->current_query = NULL;
1414 
1415 	if (ISC_LINK_LINKED(query, link))
1416 		ISC_LIST_UNLINK(lookup->q, query, link);
1417 	if (ISC_LINK_LINKED(query, clink))
1418 		ISC_LIST_UNLINK(lookup->connecting, query, clink);
1419 	if (ISC_LINK_LINKED(&query->recvbuf, link))
1420 		ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1421 				 link);
1422 	if (ISC_LINK_LINKED(&query->lengthbuf, link))
1423 		ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1424 				 link);
1425 	INSIST(query->recvspace != NULL);
1426 
1427 	if (query->sock != NULL) {
1428 		isc_socket_detach(&query->sock);
1429 		sockcount--;
1430 		debug("sockcount=%d", sockcount);
1431 	}
1432 	free(query->recvspace);
1433 	isc_buffer_invalidate(&query->recvbuf);
1434 	isc_buffer_invalidate(&query->lengthbuf);
1435 	if (query->waiting_senddone)
1436 		query->pending_free = 1;
1437 	else
1438 		free(query);
1439 }
1440 
1441 /*%
1442  * Try and clear out a lookup if we're done with it.  Return 1 if
1443  * the lookup was successfully cleared.  If 1 is returned, the
1444  * lookup pointer has been invalidated.
1445  */
1446 static int
1447 try_clear_lookup(dig_lookup_t *lookup) {
1448 	dig_query_t *q;
1449 
1450 	REQUIRE(lookup != NULL);
1451 
1452 	debug("try_clear_lookup(%p)", lookup);
1453 
1454 	if (ISC_LIST_HEAD(lookup->q) != NULL ||
1455 	    ISC_LIST_HEAD(lookup->connecting) != NULL)
1456 	{
1457 		if (debugging) {
1458 			q = ISC_LIST_HEAD(lookup->q);
1459 			while (q != NULL) {
1460 				debug("query to %s still pending", q->servname);
1461 				q = ISC_LIST_NEXT(q, link);
1462 			}
1463 
1464 			q = ISC_LIST_HEAD(lookup->connecting);
1465 			while (q != NULL) {
1466 				debug("query to %s still connecting",
1467 				      q->servname);
1468 				q = ISC_LIST_NEXT(q, clink);
1469 			}
1470 		}
1471 		return (0);
1472 	}
1473 
1474 	/*
1475 	 * At this point, we know there are no queries on the lookup,
1476 	 * so can make it go away also.
1477 	 */
1478 	destroy_lookup(lookup);
1479 	return (1);
1480 }
1481 
1482 void
1483 destroy_lookup(dig_lookup_t *lookup) {
1484 	dig_server_t *s;
1485 	void *ptr;
1486 
1487 	debug("destroy");
1488 	s = ISC_LIST_HEAD(lookup->my_server_list);
1489 	while (s != NULL) {
1490 		debug("freeing server %p belonging to %p", s, lookup);
1491 		ptr = s;
1492 		s = ISC_LIST_NEXT(s, link);
1493 		ISC_LIST_DEQUEUE(lookup->my_server_list,
1494 				 (dig_server_t *)ptr, link);
1495 		free(ptr);
1496 	}
1497 	if (lookup->sendmsg != NULL)
1498 		dns_message_destroy(&lookup->sendmsg);
1499 	if (lookup->querysig != NULL) {
1500 		debug("freeing buffer %p", lookup->querysig);
1501 		isc_buffer_free(&lookup->querysig);
1502 	}
1503 	if (lookup->sendspace != NULL)
1504 		free(lookup->sendspace);
1505 
1506 	if (lookup->tsigctx != NULL)
1507 		dst_context_destroy(&lookup->tsigctx);
1508 
1509 	if (lookup->ecs_addr != NULL)
1510 		free(lookup->ecs_addr);
1511 
1512 	if (lookup->ednsopts != NULL) {
1513 		size_t i;
1514 		for (i = 0; i < EDNSOPT_OPTIONS; i++) {
1515 			if (lookup->ednsopts[i].value != NULL)
1516 				free(lookup->ednsopts[i].value);
1517 		}
1518 		free(lookup->ednsopts);
1519 	}
1520 
1521 	free(lookup);
1522 }
1523 
1524 /*%
1525  * If we can, start the next lookup in the queue running.
1526  * This assumes that the lookup on the head of the queue hasn't been
1527  * started yet.  It also removes the lookup from the head of the queue,
1528  * setting the current_lookup pointer pointing to it.
1529  */
1530 void
1531 start_lookup(void) {
1532 	debug("start_lookup()");
1533 	if (cancel_now)
1534 		return;
1535 
1536 	/*
1537 	 * If there's a current lookup running, we really shouldn't get
1538 	 * here.
1539 	 */
1540 	INSIST(current_lookup == NULL);
1541 
1542 	current_lookup = ISC_LIST_HEAD(lookup_list);
1543 	/*
1544 	 * Put the current lookup somewhere so cancel_all can find it
1545 	 */
1546 	if (current_lookup != NULL) {
1547 		ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1548 		if (setup_lookup(current_lookup))
1549 			do_lookup(current_lookup);
1550 		else if (next_origin(current_lookup))
1551 			check_next_lookup(current_lookup);
1552 	} else {
1553 		check_if_done();
1554 	}
1555 }
1556 
1557 /*%
1558  * If we can, clear the current lookup and start the next one running.
1559  * This calls try_clear_lookup, so may invalidate the lookup pointer.
1560  */
1561 static void
1562 check_next_lookup(dig_lookup_t *lookup) {
1563 
1564 	INSIST(!free_now);
1565 
1566 	debug("check_next_lookup(%p)", lookup);
1567 
1568 	if (ISC_LIST_HEAD(lookup->q) != NULL) {
1569 		debug("still have a worker");
1570 		return;
1571 	}
1572 	if (try_clear_lookup(lookup)) {
1573 		current_lookup = NULL;
1574 		start_lookup();
1575 	}
1576 }
1577 
1578 /*%
1579  * Create and queue a new lookup as a followup to the current lookup,
1580  * based on the supplied message and section.  This is used in trace and
1581  * name server search modes to start a new lookup using servers from
1582  * NS records in a reply. Returns the number of followup lookups made.
1583  */
1584 static int
1585 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1586 {
1587 	dig_lookup_t *lookup = NULL;
1588 	dig_server_t *srv = NULL;
1589 	dns_rdataset_t *rdataset = NULL;
1590 	dns_rdata_t rdata = DNS_RDATA_INIT;
1591 	dns_name_t *name = NULL;
1592 	isc_result_t result;
1593 	int success = 0;
1594 	int numLookups = 0;
1595 	int num;
1596 	isc_result_t lresult, addresses_result;
1597 	char bad_namestr[DNS_NAME_FORMATSIZE];
1598 	dns_name_t *domain;
1599 	int horizontal = 0, bad = 0;
1600 
1601 	INSIST(!free_now);
1602 
1603 	debug("following up %s", query->lookup->textname);
1604 
1605 	addresses_result = ISC_R_SUCCESS;
1606 	bad_namestr[0] = '\0';
1607 	for (result = dns_message_firstname(msg, section);
1608 	     result == ISC_R_SUCCESS;
1609 	     result = dns_message_nextname(msg, section)) {
1610 		name = NULL;
1611 		dns_message_currentname(msg, section, &name);
1612 
1613 		if (section == DNS_SECTION_AUTHORITY) {
1614 			rdataset = NULL;
1615 			result = dns_message_findtype(name, dns_rdatatype_soa,
1616 						      0, &rdataset);
1617 			if (result == ISC_R_SUCCESS)
1618 				return (0);
1619 		}
1620 		rdataset = NULL;
1621 		result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1622 					      &rdataset);
1623 		if (result != ISC_R_SUCCESS)
1624 			continue;
1625 
1626 		debug("found NS set");
1627 
1628 		if (query->lookup->trace && !query->lookup->trace_root) {
1629 			dns_namereln_t namereln;
1630 			unsigned int nlabels;
1631 			int order;
1632 
1633 			domain = dns_fixedname_name(&query->lookup->fdomain);
1634 			namereln = dns_name_fullcompare(name, domain,
1635 							&order, &nlabels);
1636 			if (namereln == dns_namereln_equal) {
1637 				if (!horizontal)
1638 					printf(";; BAD (HORIZONTAL) REFERRAL\n");
1639 				horizontal = 1;
1640 			} else if (namereln != dns_namereln_subdomain) {
1641 				if (!bad)
1642 					printf(";; BAD REFERRAL\n");
1643 				bad = 1;
1644 				continue;
1645 			}
1646 		}
1647 
1648 		for (result = dns_rdataset_first(rdataset);
1649 		     result == ISC_R_SUCCESS;
1650 		     result = dns_rdataset_next(rdataset)) {
1651 			char namestr[DNS_NAME_FORMATSIZE];
1652 			dns_rdata_ns_t ns;
1653 
1654 			if (query->lookup->trace_root &&
1655 			    query->lookup->nsfound >= MXSERV)
1656 				break;
1657 
1658 			dns_rdataset_current(rdataset, &rdata);
1659 
1660 			query->lookup->nsfound++;
1661 			result = dns_rdata_tostruct_ns(&rdata, &ns);
1662 			check_result(result, "dns_rdata_tostruct_ns");
1663 			dns_name_format(&ns.name, namestr, sizeof(namestr));
1664 			dns_rdata_freestruct_ns(&ns);
1665 
1666 			/* Initialize lookup if we've not yet */
1667 			debug("found NS %s", namestr);
1668 			if (!success) {
1669 				success = 1;
1670 				lookup_counter++;
1671 				lookup = requeue_lookup(query->lookup,
1672 							0);
1673 				cancel_lookup(query->lookup);
1674 				lookup->doing_xfr = 0;
1675 				if (!lookup->trace_root &&
1676 				    section == DNS_SECTION_ANSWER)
1677 					lookup->trace = 0;
1678 				else
1679 					lookup->trace = query->lookup->trace;
1680 				lookup->ns_search_only =
1681 					query->lookup->ns_search_only;
1682 				lookup->trace_root = 0;
1683 				if (lookup->ns_search_only)
1684 					lookup->recurse = 0;
1685 				domain = dns_fixedname_name(&lookup->fdomain);
1686 				dns_name_copy(name, domain, NULL);
1687 			}
1688 			debug("adding server %s", namestr);
1689 			num = getaddresses(lookup, namestr, &lresult);
1690 			if (lresult != ISC_R_SUCCESS) {
1691 				printf("couldn't get address for '%s': %s\n",
1692 				       namestr, isc_result_totext(lresult));
1693 				if (addresses_result == ISC_R_SUCCESS) {
1694 					addresses_result = lresult;
1695 					strlcpy(bad_namestr, namestr,
1696 						sizeof(bad_namestr));
1697 				}
1698 			}
1699 			numLookups += num;
1700 			dns_rdata_reset(&rdata);
1701 		}
1702 	}
1703 	if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1704 		fatal("couldn't get address for '%s': %s",
1705 		      bad_namestr, isc_result_totext(result));
1706 	}
1707 
1708 	if (lookup == NULL &&
1709 	    section == DNS_SECTION_ANSWER &&
1710 	    (query->lookup->trace || query->lookup->ns_search_only))
1711 		return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1712 
1713 	/*
1714 	 * Randomize the order the nameserver will be tried.
1715 	 */
1716 	if (numLookups > 1) {
1717 		uint32_t i, j;
1718 		dig_serverlist_t my_server_list;
1719 		dig_server_t *next;
1720 
1721 		ISC_LIST_INIT(my_server_list);
1722 
1723 		i = numLookups;
1724 		for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1725 		     srv != NULL;
1726 		     srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1727 			INSIST(i > 0);
1728 			j = arc4random_uniform(i);
1729 			next = ISC_LIST_NEXT(srv, link);
1730 			while (j-- > 0 && next != NULL) {
1731 				srv = next;
1732 				next = ISC_LIST_NEXT(srv, link);
1733 			}
1734 			ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1735 			ISC_LIST_APPEND(my_server_list, srv, link);
1736 			i--;
1737 		}
1738 		ISC_LIST_APPENDLIST(lookup->my_server_list,
1739 				    my_server_list, link);
1740 	}
1741 
1742 	return (numLookups);
1743 }
1744 
1745 /*%
1746  * Create and queue a new lookup using the next origin from the search
1747  * list, read in setup_system().
1748  *
1749  * Return 1 iff there was another searchlist entry.
1750  */
1751 static int
1752 next_origin(dig_lookup_t *oldlookup) {
1753 	dig_lookup_t *newlookup;
1754 	dig_searchlist_t *search;
1755 	dns_fixedname_t fixed;
1756 	dns_name_t *name;
1757 	isc_result_t result;
1758 
1759 	INSIST(!free_now);
1760 
1761 	debug("next_origin()");
1762 	debug("following up %s", oldlookup->textname);
1763 
1764 	if (!usesearch)
1765 		/*
1766 		 * We're not using a search list, so don't even think
1767 		 * about finding the next entry.
1768 		 */
1769 		return (0);
1770 
1771 	/*
1772 	 * Check for a absolute name or ndots being met.
1773 	 */
1774 	dns_fixedname_init(&fixed);
1775 	name = dns_fixedname_name(&fixed);
1776 	result = dns_name_fromstring2(name, oldlookup->textname, NULL, 0);
1777 	if (result == ISC_R_SUCCESS &&
1778 	    (dns_name_isabsolute(name) ||
1779 	     (int)dns_name_countlabels(name) > ndots))
1780 		return (0);
1781 
1782 	if (oldlookup->origin == NULL && !oldlookup->need_search)
1783 		/*
1784 		 * Then we just did rootorg; there's nothing left.
1785 		 */
1786 		return (0);
1787 	if (oldlookup->origin == NULL && oldlookup->need_search) {
1788 		newlookup = requeue_lookup(oldlookup, 1);
1789 		newlookup->origin = ISC_LIST_HEAD(search_list);
1790 		newlookup->need_search = 0;
1791 	} else {
1792 		search = ISC_LIST_NEXT(oldlookup->origin, link);
1793 		if (search == NULL && oldlookup->done_as_is)
1794 			return (0);
1795 		newlookup = requeue_lookup(oldlookup, 1);
1796 		newlookup->origin = search;
1797 	}
1798 	cancel_lookup(oldlookup);
1799 	return (1);
1800 }
1801 
1802 /*%
1803  * Insert an SOA record into the sendmessage in a lookup.  Used for
1804  * creating IXFR queries.
1805  */
1806 static void
1807 insert_soa(dig_lookup_t *lookup) {
1808 	isc_result_t result;
1809 	dns_rdata_soa_t soa;
1810 	dns_rdata_t *rdata = NULL;
1811 	dns_rdatalist_t *rdatalist = NULL;
1812 	dns_rdataset_t *rdataset = NULL;
1813 	dns_name_t *soaname = NULL;
1814 
1815 	debug("insert_soa()");
1816 	soa.serial = lookup->ixfr_serial;
1817 	soa.refresh = 0;
1818 	soa.retry = 0;
1819 	soa.expire = 0;
1820 	soa.minimum = 0;
1821 	soa.common.rdclass = lookup->rdclass;
1822 	soa.common.rdtype = dns_rdatatype_soa;
1823 
1824 	dns_name_init(&soa.origin, NULL);
1825 	dns_name_init(&soa.contact, NULL);
1826 
1827 	dns_name_clone(dns_rootname, &soa.origin);
1828 	dns_name_clone(dns_rootname, &soa.contact);
1829 
1830 	isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1831 			sizeof(lookup->rdatastore));
1832 
1833 	result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1834 	check_result(result, "dns_message_gettemprdata");
1835 
1836 	result = dns_rdata_fromstruct_soa(rdata, lookup->rdclass,
1837 				      dns_rdatatype_soa, &soa,
1838 				      &lookup->rdatabuf);
1839 	check_result(result, "isc_rdata_fromstruct_soa");
1840 
1841 	result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1842 	check_result(result, "dns_message_gettemprdatalist");
1843 
1844 	result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1845 	check_result(result, "dns_message_gettemprdataset");
1846 
1847 	dns_rdatalist_init(rdatalist);
1848 	rdatalist->type = dns_rdatatype_soa;
1849 	rdatalist->rdclass = lookup->rdclass;
1850 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1851 
1852 	dns_rdatalist_tordataset(rdatalist, rdataset);
1853 
1854 	result = dns_message_gettempname(lookup->sendmsg, &soaname);
1855 	check_result(result, "dns_message_gettempname");
1856 	dns_name_init(soaname, NULL);
1857 	dns_name_clone(lookup->name, soaname);
1858 	ISC_LIST_INIT(soaname->list);
1859 	ISC_LIST_APPEND(soaname->list, rdataset, link);
1860 	dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
1861 }
1862 
1863 static void
1864 compute_cookie(unsigned char *clientcookie, size_t len) {
1865 	/* XXXMPA need to fix, should be per server. */
1866 	INSIST(len >= 8U);
1867 	memmove(clientcookie, cookie_secret, 8);
1868 }
1869 
1870 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
1871 static void
1872 populate_root_hints(void)
1873 {
1874 	dig_server_t *newsrv;
1875 	size_t i;
1876 
1877 	if (!ISC_LIST_EMPTY(root_hints_server_list))
1878 		return;
1879 
1880 	for (i = 0; i < nitems(root_hints); i++) {
1881 		if (!have_ipv4 && root_hints[i].af == AF_INET)
1882 			continue;
1883 		if (!have_ipv6 && root_hints[i].af == AF_INET6)
1884 			continue;
1885 		newsrv = make_server(root_hints[i].ns, root_hints[i].ns);
1886 		ISC_LINK_INIT(newsrv, link);
1887 		ISC_LIST_ENQUEUE(root_hints_server_list, newsrv, link);
1888 	}
1889 }
1890 #undef nitems
1891 
1892 /*%
1893  * Setup the supplied lookup structure, making it ready to start sending
1894  * queries to servers.  Create and initialize the message to be sent as
1895  * well as the query structures and buffer space for the replies.  If the
1896  * server list is empty, clone it from the system default list.
1897  */
1898 int
1899 setup_lookup(dig_lookup_t *lookup) {
1900 	isc_result_t result;
1901 	uint32_t id;
1902 	unsigned int len;
1903 	dig_server_t *serv;
1904 	dig_query_t *query;
1905 	isc_buffer_t b;
1906 	dns_compress_t cctx;
1907 	char store[MXNAME];
1908 	char ecsbuf[20];
1909 	char sitbuf[256];
1910 
1911 	REQUIRE(lookup != NULL);
1912 	INSIST(!free_now);
1913 
1914 	debug("setup_lookup(%p)", lookup);
1915 
1916 	result = dns_message_create(DNS_MESSAGE_INTENTRENDER,
1917 				    &lookup->sendmsg);
1918 	check_result(result, "dns_message_create");
1919 
1920 	if (lookup->new_search) {
1921 		debug("resetting lookup counter.");
1922 		lookup_counter = 0;
1923 	}
1924 
1925 	if (ISC_LIST_EMPTY(lookup->my_server_list)) {
1926 		if (lookup->trace && lookup->trace_root) {
1927 			populate_root_hints();
1928 			clone_server_list(root_hints_server_list,
1929 			    &lookup->my_server_list);
1930 		} else {
1931 			debug("cloning server list");
1932 			clone_server_list(server_list,
1933 			    &lookup->my_server_list);
1934 		}
1935 	}
1936 	result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
1937 	check_result(result, "dns_message_gettempname");
1938 	dns_name_init(lookup->name, NULL);
1939 
1940 	isc_buffer_init(&lookup->namebuf, lookup->name_space,
1941 			sizeof(lookup->name_space));
1942 	isc_buffer_init(&lookup->onamebuf, lookup->oname_space,
1943 			sizeof(lookup->oname_space));
1944 
1945 	/*
1946 	 * If the name has too many dots, force the origin to be NULL
1947 	 * (which produces an absolute lookup).  Otherwise, take the origin
1948 	 * we have if there's one in the struct already.  If it's NULL,
1949 	 * take the first entry in the searchlist iff either usesearch
1950 	 * is TRUE or we got a domain line in the resolv.conf file.
1951 	 */
1952 	if (lookup->new_search) {
1953 		if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
1954 			lookup->origin = NULL; /* Force abs lookup */
1955 			lookup->done_as_is = 1;
1956 			lookup->need_search = usesearch;
1957 		} else if (lookup->origin == NULL && usesearch) {
1958 			lookup->origin = ISC_LIST_HEAD(search_list);
1959 			lookup->need_search = 0;
1960 		}
1961 	}
1962 
1963 	if (lookup->origin != NULL) {
1964 		debug("trying origin %s", lookup->origin->origin);
1965 		result = dns_message_gettempname(lookup->sendmsg,
1966 						 &lookup->oname);
1967 		check_result(result, "dns_message_gettempname");
1968 		dns_name_init(lookup->oname, NULL);
1969 		/* XXX Helper funct to conv char* to name? */
1970 		len = (unsigned int) strlen(lookup->origin->origin);
1971 		isc_buffer_init(&b, lookup->origin->origin, len);
1972 		isc_buffer_add(&b, len);
1973 		result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
1974 					   0, &lookup->onamebuf);
1975 		if (result != ISC_R_SUCCESS) {
1976 			dns_message_puttempname(lookup->sendmsg,
1977 						&lookup->name);
1978 			dns_message_puttempname(lookup->sendmsg,
1979 						&lookup->oname);
1980 			fatal("'%s' is not in legal name syntax (%s)",
1981 			      lookup->origin->origin,
1982 			      isc_result_totext(result));
1983 		}
1984 		if (lookup->trace && lookup->trace_root) {
1985 			dns_name_clone(dns_rootname, lookup->name);
1986 		} else {
1987 			dns_fixedname_t fixed;
1988 			dns_name_t *name;
1989 
1990 			dns_fixedname_init(&fixed);
1991 			name = dns_fixedname_name(&fixed);
1992 			len = (unsigned int) strlen(lookup->textname);
1993 			isc_buffer_init(&b, lookup->textname, len);
1994 			isc_buffer_add(&b, len);
1995 			result = dns_name_fromtext(name, &b, NULL, 0, NULL);
1996 			if (result == ISC_R_SUCCESS &&
1997 			    !dns_name_isabsolute(name))
1998 				result = dns_name_concatenate(name,
1999 							      lookup->oname,
2000 							      lookup->name,
2001 							      &lookup->namebuf);
2002 			else if (result == ISC_R_SUCCESS)
2003 				result = dns_name_copy(name, lookup->name,
2004 						       &lookup->namebuf);
2005 			if (result != ISC_R_SUCCESS) {
2006 				dns_message_puttempname(lookup->sendmsg,
2007 							&lookup->name);
2008 				dns_message_puttempname(lookup->sendmsg,
2009 							&lookup->oname);
2010 				if (result == DNS_R_NAMETOOLONG)
2011 					return (0);
2012 				fatal("'%s' is not in legal name syntax (%s)",
2013 				      lookup->textname,
2014 				      isc_result_totext(result));
2015 			}
2016 		}
2017 		dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2018 	} else
2019 	{
2020 		debug("using root origin");
2021 		if (lookup->trace && lookup->trace_root)
2022 			dns_name_clone(dns_rootname, lookup->name);
2023 		else {
2024 			len = (unsigned int) strlen(lookup->textname);
2025 			isc_buffer_init(&b, lookup->textname, len);
2026 			isc_buffer_add(&b, len);
2027 			result = dns_name_fromtext(lookup->name, &b,
2028 						   dns_rootname, 0,
2029 						   &lookup->namebuf);
2030 		}
2031 		if (result != ISC_R_SUCCESS) {
2032 			dns_message_puttempname(lookup->sendmsg,
2033 						&lookup->name);
2034 			fatal("'%s' is not a legal name "
2035 			      "(%s)", lookup->textname,
2036 			      isc_result_totext(result));
2037 		}
2038 	}
2039 	dns_name_format(lookup->name, store, sizeof(store));
2040 	dighost_trying(store, lookup);
2041 	INSIST(dns_name_isabsolute(lookup->name));
2042 
2043 	id = arc4random();
2044 	lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2045 	lookup->sendmsg->opcode = lookup->opcode;
2046 	lookup->msgcounter = 0;
2047 	/*
2048 	 * If this is a trace request, completely disallow recursion, since
2049 	 * it's meaningless for traces.
2050 	 */
2051 	if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2052 		lookup->recurse = 0;
2053 
2054 	if (lookup->recurse &&
2055 	    lookup->rdtype != dns_rdatatype_axfr &&
2056 	    lookup->rdtype != dns_rdatatype_ixfr) {
2057 		debug("recursive query");
2058 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2059 	}
2060 
2061 	/* XXX aaflag */
2062 	if (lookup->aaonly) {
2063 		debug("AA query");
2064 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2065 	}
2066 
2067 	if (lookup->adflag) {
2068 		debug("AD query");
2069 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2070 	}
2071 
2072 	if (lookup->cdflag) {
2073 		debug("CD query");
2074 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2075 	}
2076 
2077 	dns_message_addname(lookup->sendmsg, lookup->name,
2078 			    DNS_SECTION_QUESTION);
2079 
2080 	if (lookup->trace && lookup->trace_root) {
2081 		lookup->qrdtype = lookup->rdtype;
2082 		lookup->rdtype = dns_rdatatype_ns;
2083 	}
2084 
2085 	if ((lookup->rdtype == dns_rdatatype_axfr) ||
2086 	    (lookup->rdtype == dns_rdatatype_ixfr)) {
2087 		/*
2088 		 * Force TCP mode if we're doing an axfr.
2089 		 */
2090 		if (lookup->rdtype == dns_rdatatype_axfr) {
2091 			lookup->doing_xfr = 1;
2092 			lookup->tcp_mode = 1;
2093 		} else if (lookup->tcp_mode) {
2094 			lookup->doing_xfr = 1;
2095 		}
2096 	}
2097 
2098 	add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2099 		     lookup->rdtype);
2100 
2101 	/* add_soa */
2102 	if (lookup->rdtype == dns_rdatatype_ixfr)
2103 		insert_soa(lookup);
2104 
2105 	/* XXX Insist this? */
2106 	lookup->tsigctx = NULL;
2107 	lookup->querysig = NULL;
2108 	if (tsigkey != NULL) {
2109 		debug("initializing keys");
2110 		result = dns_message_settsigkey(lookup->sendmsg, tsigkey);
2111 		check_result(result, "dns_message_settsigkey");
2112 	}
2113 
2114 	lookup->sendspace = malloc(COMMSIZE);
2115 	if (lookup->sendspace == NULL)
2116 		fatal("memory allocation failure");
2117 
2118 	result = dns_compress_init(&cctx, -1);
2119 	check_result(result, "dns_compress_init");
2120 
2121 	debug("starting to render the message");
2122 	isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2123 	result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2124 					 &lookup->renderbuf);
2125 	check_result(result, "dns_message_renderbegin");
2126 	if (lookup->udpsize > 0 || lookup->dnssec ||
2127 	    lookup->edns > -1 || lookup->ecs_addr != NULL)
2128 	{
2129 #define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS)
2130 		dns_ednsopt_t opts[MAXOPTS];
2131 		unsigned int flags;
2132 		unsigned int i = 0;
2133 
2134 		if (lookup->udpsize == 0)
2135 			lookup->udpsize = 4096;
2136 		if (lookup->edns < 0)
2137 			lookup->edns = 0;
2138 
2139 		if (lookup->nsid) {
2140 			INSIST(i < MAXOPTS);
2141 			opts[i].code = DNS_OPT_NSID;
2142 			opts[i].length = 0;
2143 			opts[i].value = NULL;
2144 			i++;
2145 		}
2146 
2147 		if (lookup->ecs_addr != NULL) {
2148 			uint8_t addr[16];
2149 			uint16_t family;
2150 			uint32_t plen;
2151 			struct sockaddr *sa;
2152 			struct sockaddr_in *sin;
2153 			struct sockaddr_in6 *sin6;
2154 			size_t addrl;
2155 
2156 			sa = (struct sockaddr *)lookup->ecs_addr;
2157 			plen = lookup->ecs_plen;
2158 
2159 			/* Round up prefix len to a multiple of 8 */
2160 			addrl = (plen + 7) / 8;
2161 
2162 			INSIST(i < MAXOPTS);
2163 			opts[i].code = DNS_OPT_CLIENT_SUBNET;
2164 			opts[i].length = (uint16_t) addrl + 4;
2165 			check_result(result, "isc_buffer_allocate");
2166 
2167 			/*
2168 			 * XXXMUKS: According to RFC7871, "If there is
2169 			 * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is
2170 			 * set to 0, then FAMILY SHOULD be set to the
2171 			 * transport over which the query is sent."
2172 			 *
2173 			 * However, at this point we don't know what
2174 			 * transport(s) we'll be using, so we can't
2175 			 * set the value now. For now, we're using
2176 			 * IPv4 as the default the +subnet option
2177 			 * used an IPv4 prefix, or for +subnet=0,
2178 			 * and IPv6 if the +subnet option used an
2179 			 * IPv6 prefix.
2180 			 *
2181 			 * (For future work: preserve the offset into
2182 			 * the buffer where the family field is;
2183 			 * that way we can update it in send_udp()
2184 			 * or send_tcp_connect() once we know
2185 			 * what it outght to be.)
2186 			 */
2187 			switch (sa->sa_family) {
2188 			case AF_UNSPEC:
2189 				INSIST(plen == 0);
2190 				family = 1;
2191 				break;
2192 			case AF_INET:
2193 				INSIST(plen <= 32);
2194 				family = 1;
2195 				sin = (struct sockaddr_in *) sa;
2196 				memmove(addr, &sin->sin_addr, addrl);
2197 				break;
2198 			case AF_INET6:
2199 				INSIST(plen <= 128);
2200 				family = 2;
2201 				sin6 = (struct sockaddr_in6 *) sa;
2202 				memmove(addr, &sin6->sin6_addr, addrl);
2203 				break;
2204 			default:
2205 				INSIST(0);
2206 			}
2207 
2208 			isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
2209 			/* family */
2210 			isc_buffer_putuint16(&b, family);
2211 			/* source prefix-length */
2212 			isc_buffer_putuint8(&b, plen);
2213 			/* scope prefix-length */
2214 			isc_buffer_putuint8(&b, 0);
2215 
2216 			/* address */
2217 			if (addrl > 0) {
2218 				/* Mask off last address byte */
2219 				if ((plen % 8) != 0)
2220 					addr[addrl - 1] &=
2221 						~0U << (8 - (plen % 8));
2222 				isc_buffer_putmem(&b, addr,
2223 						  (unsigned)addrl);
2224 			}
2225 
2226 			opts[i].value = (uint8_t *) ecsbuf;
2227 			i++;
2228 		}
2229 
2230 		if (lookup->sit) {
2231 			INSIST(i < MAXOPTS);
2232 			opts[i].code = DNS_OPT_COOKIE;
2233 			if (lookup->sitvalue != NULL) {
2234 				isc_buffer_init(&b, sitbuf, sizeof(sitbuf));
2235 				result = isc_hex_decodestring(lookup->sitvalue,
2236 							      &b);
2237 				check_result(result, "isc_hex_decodestring");
2238 				opts[i].value = isc_buffer_base(&b);
2239 				opts[i].length = isc_buffer_usedlength(&b);
2240 			} else {
2241 				compute_cookie(cookie, sizeof(cookie));
2242 				opts[i].length = 8;
2243 				opts[i].value = cookie;
2244 			}
2245 			i++;
2246 		}
2247 
2248 		if (lookup->expire) {
2249 			INSIST(i < MAXOPTS);
2250 			opts[i].code = DNS_OPT_EXPIRE;
2251 			opts[i].length = 0;
2252 			opts[i].value = NULL;
2253 			i++;
2254 		}
2255 
2256 		if (lookup->ednsoptscnt != 0) {
2257 			INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
2258 			memmove(&opts[i], lookup->ednsopts,
2259 				sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
2260 			i += lookup->ednsoptscnt;
2261 		}
2262 
2263 		flags = lookup->ednsflags;
2264 		flags &= ~DNS_MESSAGEEXTFLAG_DO;
2265 		if (lookup->dnssec)
2266 			flags |= DNS_MESSAGEEXTFLAG_DO;
2267 		add_opt(lookup->sendmsg, lookup->udpsize,
2268 			lookup->edns, flags, opts, i);
2269 	}
2270 
2271 	result = dns_message_rendersection(lookup->sendmsg,
2272 					   DNS_SECTION_QUESTION);
2273 	check_result(result, "dns_message_rendersection");
2274 	result = dns_message_rendersection(lookup->sendmsg,
2275 					   DNS_SECTION_AUTHORITY);
2276 	check_result(result, "dns_message_rendersection");
2277 	result = dns_message_renderend(lookup->sendmsg);
2278 	check_result(result, "dns_message_renderend");
2279 	debug("done rendering");
2280 
2281 	dns_compress_invalidate(&cctx);
2282 
2283 	/*
2284 	 * Force TCP mode if the request is larger than 512 bytes.
2285 	 */
2286 	if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2287 		lookup->tcp_mode = 1;
2288 
2289 	lookup->pending = 0;
2290 
2291 	for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2292 	     serv != NULL;
2293 	     serv = ISC_LIST_NEXT(serv, link)) {
2294 		query = malloc(sizeof(dig_query_t));
2295 		if (query == NULL)
2296 			fatal("memory allocation failure in %s:%d",
2297 			      __FILE__, __LINE__);
2298 		debug("create query %p linked to lookup %p",
2299 		       query, lookup);
2300 		query->lookup = lookup;
2301 		query->timer = NULL;
2302 		query->waiting_connect = 0;
2303 		query->waiting_senddone = 0;
2304 		query->pending_free = 0;
2305 		query->recv_made = 0;
2306 		query->first_pass = 1;
2307 		query->first_soa_rcvd = 0;
2308 		query->second_rr_rcvd = 0;
2309 		query->first_repeat_rcvd = 0;
2310 		query->warn_id = 1;
2311 		query->timedout = 0;
2312 		query->first_rr_serial = 0;
2313 		query->second_rr_serial = 0;
2314 		query->servname = serv->servername;
2315 		query->userarg = serv->userarg;
2316 		query->rr_count = 0;
2317 		query->msg_count = 0;
2318 		query->byte_count = 0;
2319 		query->ixfr_axfr = 0;
2320 		ISC_LIST_INIT(query->recvlist);
2321 		ISC_LIST_INIT(query->lengthlist);
2322 		query->sock = NULL;
2323 		query->recvspace = malloc(COMMSIZE);
2324 		if (query->recvspace == NULL)
2325 			fatal("memory allocation failure");
2326 
2327 		isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2328 		isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2329 		isc_buffer_init(&query->slbuf, query->slspace, 2);
2330 		query->sendbuf = lookup->renderbuf;
2331 
2332 		ISC_LINK_INIT(query, clink);
2333 		ISC_LINK_INIT(query, link);
2334 		ISC_LIST_ENQUEUE(lookup->q, query, link);
2335 	}
2336 
2337 	/* XXX qrflag, print_query, etc... */
2338 	if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2339 		extrabytes = 0;
2340 		dighost_printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2341 			     1);
2342 	}
2343 	return (1);
2344 }
2345 
2346 /*%
2347  * Event handler for send completion.  Track send counter, and clear out
2348  * the query if the send was canceled.
2349  */
2350 static void
2351 send_done(isc_task_t *_task, isc_event_t *event) {
2352 	isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2353 	isc_buffer_t *b = NULL;
2354 	dig_query_t *query, *next;
2355 	dig_lookup_t *l;
2356 
2357 	REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2358 
2359 	UNUSED(_task);
2360 
2361 	debug("send_done()");
2362 	sendcount--;
2363 	debug("sendcount=%d", sendcount);
2364 	INSIST(sendcount >= 0);
2365 
2366 	for  (b = ISC_LIST_HEAD(sevent->bufferlist);
2367 	      b != NULL;
2368 	      b = ISC_LIST_HEAD(sevent->bufferlist)) {
2369 		ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2370 		free(b);
2371 	}
2372 
2373 	query = event->ev_arg;
2374 	query->waiting_senddone = 0;
2375 	l = query->lookup;
2376 
2377 	if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2378 		debug("sending next, since searching");
2379 		next = ISC_LIST_NEXT(query, link);
2380 		if (next != NULL)
2381 			send_udp(next);
2382 	}
2383 
2384 	isc_event_free(&event);
2385 
2386 	if (query->pending_free)
2387 		free(query);
2388 
2389 	check_if_done();
2390 }
2391 
2392 /*%
2393  * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2394  * IO sockets.  The cancel handlers should take care of cleaning up the
2395  * query and lookup structures
2396  */
2397 static void
2398 cancel_lookup(dig_lookup_t *lookup) {
2399 	dig_query_t *query, *next;
2400 
2401 	debug("cancel_lookup()");
2402 	query = ISC_LIST_HEAD(lookup->q);
2403 	while (query != NULL) {
2404 		next = ISC_LIST_NEXT(query, link);
2405 		if (query->sock != NULL) {
2406 			isc_socket_cancel(query->sock, global_task,
2407 					  ISC_SOCKCANCEL_ALL);
2408 			check_if_done();
2409 		} else {
2410 			clear_query(query);
2411 		}
2412 		query = next;
2413 	}
2414 	lookup->pending = 0;
2415 	lookup->retries = 0;
2416 }
2417 
2418 static void
2419 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2420 	dig_lookup_t *l;
2421 	unsigned int local_timeout;
2422 	isc_result_t result;
2423 
2424 	debug("bringup_timer()");
2425 	/*
2426 	 * If the timer already exists, that means we're calling this
2427 	 * a second time (for a retry).  Don't need to recreate it,
2428 	 * just reset it.
2429 	 */
2430 	l = query->lookup;
2431 	if (ISC_LINK_LINKED(query, link) && ISC_LIST_NEXT(query, link) != NULL)
2432 		local_timeout = SERVER_TIMEOUT;
2433 	else {
2434 		if (timeout == 0)
2435 			local_timeout = default_timeout;
2436 		else
2437 			local_timeout = timeout;
2438 	}
2439 	debug("have local timeout of %d", local_timeout);
2440 	l->interval.tv_sec = local_timeout;
2441 	l->interval.tv_nsec = 0;
2442 	if (query->timer != NULL)
2443 		isc_timer_detach(&query->timer);
2444 	result = isc_timer_create(timermgr,
2445 				  &l->interval, global_task, connect_timeout,
2446 				  query, &query->timer);
2447 	check_result(result, "isc_timer_create");
2448 }
2449 
2450 static void
2451 force_timeout(dig_query_t *query) {
2452 	isc_event_t *event;
2453 
2454 	debug("force_timeout ()");
2455 	event = isc_event_allocate(query, ISC_TIMEREVENT_IDLE,
2456 				   connect_timeout, query,
2457 				   sizeof(isc_event_t));
2458 	if (event == NULL) {
2459 		fatal("isc_event_allocate: %s",
2460 		      isc_result_totext(ISC_R_NOMEMORY));
2461 	}
2462 	isc_task_send(global_task, &event);
2463 
2464 	/*
2465 	 * The timer may have expired if, for example, get_address() takes
2466 	 * long time and the timer was running on a different thread.
2467 	 * We need to cancel the possible timeout event not to confuse
2468 	 * ourselves due to the duplicate events.
2469 	 */
2470 	if (query->timer != NULL)
2471 		isc_timer_detach(&query->timer);
2472 }
2473 
2474 static void
2475 connect_done(isc_task_t *task, isc_event_t *event);
2476 
2477 /*%
2478  * Unlike send_udp, this can't be called multiple times with the same
2479  * query.  When we retry TCP, we requeue the whole lookup, which should
2480  * start anew.
2481  */
2482 static void
2483 send_tcp_connect(dig_query_t *query) {
2484 	isc_result_t result;
2485 	dig_query_t *next;
2486 	dig_lookup_t *l;
2487 
2488 	debug("send_tcp_connect(%p)", query);
2489 
2490 	l = query->lookup;
2491 	query->waiting_connect = 1;
2492 	query->lookup->current_query = query;
2493 	result = get_address(query->servname, port, &query->sockaddr);
2494 	if (result != ISC_R_SUCCESS) {
2495 		/*
2496 		 * This servname doesn't have an address.  Try the next server
2497 		 * by triggering an immediate 'timeout' (we lie, but the effect
2498 		 * is the same).
2499 		 */
2500 		force_timeout(query);
2501 		return;
2502 	}
2503 
2504 	if (specified_source &&
2505 	    (isc_sockaddr_pf(&query->sockaddr) !=
2506 	     isc_sockaddr_pf(&bind_address))) {
2507 		printf(";; Skipping server %s, incompatible "
2508 		       "address family\n", query->servname);
2509 		query->waiting_connect = 0;
2510 		if (ISC_LINK_LINKED(query, link))
2511 			next = ISC_LIST_NEXT(query, link);
2512 		else
2513 			next = NULL;
2514 		l = query->lookup;
2515 		clear_query(query);
2516 		if (next == NULL) {
2517 			printf(";; No acceptable nameservers\n");
2518 			check_next_lookup(l);
2519 			return;
2520 		}
2521 		send_tcp_connect(next);
2522 		return;
2523 	}
2524 
2525 	INSIST(query->sock == NULL);
2526 
2527 	if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2528 		sockcount++;
2529 		isc_socket_attach(keep, &query->sock);
2530 		query->waiting_connect = 0;
2531 		launch_next_query(query, 1);
2532 		goto search;
2533 	}
2534 
2535 	result = isc_socket_create(socketmgr,
2536 				   isc_sockaddr_pf(&query->sockaddr),
2537 				   isc_sockettype_tcp, &query->sock);
2538 	check_result(result, "isc_socket_create");
2539 	sockcount++;
2540 	debug("sockcount=%d", sockcount);
2541 	if (specified_source)
2542 		result = isc_socket_bind(query->sock, &bind_address,
2543 					 ISC_SOCKET_REUSEADDRESS);
2544 	else {
2545 		if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2546 		    have_ipv4)
2547 			isc_sockaddr_any(&bind_any);
2548 		else
2549 			isc_sockaddr_any6(&bind_any);
2550 		result = isc_socket_bind(query->sock, &bind_any, 0);
2551 	}
2552 	check_result(result, "isc_socket_bind");
2553 	bringup_timer(query, TCP_TIMEOUT);
2554 	result = isc_socket_connect(query->sock, &query->sockaddr,
2555 				    global_task, connect_done, query);
2556 	check_result(result, "isc_socket_connect");
2557  search:
2558 	/*
2559 	 * If we're at the endgame of a nameserver search, we need to
2560 	 * immediately bring up all the queries.  Do it here.
2561 	 */
2562 	if (l->ns_search_only && !l->trace_root) {
2563 		debug("sending next, since searching");
2564 		if (ISC_LINK_LINKED(query, link)) {
2565 			next = ISC_LIST_NEXT(query, link);
2566 			ISC_LIST_DEQUEUE(l->q, query, link);
2567 		} else
2568 			next = NULL;
2569 		ISC_LIST_ENQUEUE(l->connecting, query, clink);
2570 		if (next != NULL)
2571 			send_tcp_connect(next);
2572 	}
2573 }
2574 
2575 static isc_buffer_t *
2576 clone_buffer(isc_buffer_t *source) {
2577 	isc_buffer_t *buffer;
2578 	buffer = malloc(sizeof(*buffer));
2579 	if (buffer == NULL)
2580 		fatal("memory allocation failure in %s:%d",
2581 		      __FILE__, __LINE__);
2582 	*buffer = *source;
2583 	return (buffer);
2584 }
2585 
2586 /*%
2587  * Send a UDP packet to the remote nameserver, possible starting the
2588  * recv action as well.  Also make sure that the timer is running and
2589  * is properly reset.
2590  */
2591 static void
2592 send_udp(dig_query_t *query) {
2593 	dig_lookup_t *l = NULL;
2594 	isc_result_t result;
2595 	isc_buffer_t *sendbuf;
2596 
2597 	debug("send_udp(%p)", query);
2598 
2599 	l = query->lookup;
2600 	bringup_timer(query, UDP_TIMEOUT);
2601 	l->current_query = query;
2602 	debug("working on lookup %p, query %p", query->lookup, query);
2603 	if (!query->recv_made) {
2604 		/* XXX Check the sense of this, need assertion? */
2605 		query->waiting_connect = 0;
2606 		result = get_address(query->servname, port, &query->sockaddr);
2607 		if (result != ISC_R_SUCCESS) {
2608 			/* This servname doesn't have an address. */
2609 			force_timeout(query);
2610 			return;
2611 		}
2612 
2613 		result = isc_socket_create(socketmgr,
2614 					   isc_sockaddr_pf(&query->sockaddr),
2615 					   isc_sockettype_udp, &query->sock);
2616 		check_result(result, "isc_socket_create");
2617 		sockcount++;
2618 		debug("sockcount=%d", sockcount);
2619 		if (specified_source) {
2620 			result = isc_socket_bind(query->sock, &bind_address,
2621 						 ISC_SOCKET_REUSEADDRESS);
2622 		} else {
2623 			isc_sockaddr_anyofpf(&bind_any,
2624 					isc_sockaddr_pf(&query->sockaddr));
2625 			result = isc_socket_bind(query->sock, &bind_any, 0);
2626 		}
2627 		check_result(result, "isc_socket_bind");
2628 
2629 		query->recv_made = 1;
2630 		ISC_LINK_INIT(&query->recvbuf, link);
2631 		ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2632 				 link);
2633 		debug("recving with lookup=%p, query=%p, sock=%p",
2634 		      query->lookup, query, query->sock);
2635 		result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2636 					  global_task, recv_done, query);
2637 		check_result(result, "isc_socket_recvv");
2638 		recvcount++;
2639 		debug("recvcount=%d", recvcount);
2640 	}
2641 	ISC_LIST_INIT(query->sendlist);
2642 	sendbuf = clone_buffer(&query->sendbuf);
2643 	ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
2644 	debug("sending a request");
2645 	clock_gettime(CLOCK_MONOTONIC, &query->time_sent);
2646 	INSIST(query->sock != NULL);
2647 	query->waiting_senddone = 1;
2648 	result = isc_socket_sendtov2(query->sock, &query->sendlist,
2649 				     global_task, send_done, query,
2650 				     &query->sockaddr, NULL,
2651 				     ISC_SOCKFLAG_NORETRY);
2652 	check_result(result, "isc_socket_sendtov");
2653 	sendcount++;
2654 }
2655 
2656 /*%
2657  * IO timeout handler, used for both connect and recv timeouts.  If
2658  * retries are still allowed, either resend the UDP packet or queue a
2659  * new TCP lookup.  Otherwise, cancel the lookup.
2660  */
2661 static void
2662 connect_timeout(isc_task_t *task, isc_event_t *event) {
2663 	dig_lookup_t *l = NULL;
2664 	dig_query_t *query = NULL, *cq;
2665 
2666 	UNUSED(task);
2667 	REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2668 
2669 	debug("connect_timeout()");
2670 
2671 	query = event->ev_arg;
2672 	l = query->lookup;
2673 	isc_event_free(&event);
2674 
2675 	INSIST(!free_now);
2676 
2677 	if ((query != NULL) && (query->lookup->current_query != NULL) &&
2678 	    ISC_LINK_LINKED(query->lookup->current_query, link) &&
2679 	    (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2680 		debug("trying next server...");
2681 		cq = query->lookup->current_query;
2682 		if (!l->tcp_mode)
2683 			send_udp(ISC_LIST_NEXT(cq, link));
2684 		else {
2685 			if (query->sock != NULL)
2686 				isc_socket_cancel(query->sock, NULL,
2687 						  ISC_SOCKCANCEL_ALL);
2688 			send_tcp_connect(ISC_LIST_NEXT(cq, link));
2689 		}
2690 		return;
2691 	}
2692 
2693 	if (l->tcp_mode && query->sock != NULL) {
2694 		query->timedout = 1;
2695 		isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL);
2696 	}
2697 
2698 	if (l->retries > 1) {
2699 		if (!l->tcp_mode) {
2700 			l->retries--;
2701 			debug("resending UDP request to first server");
2702 			send_udp(ISC_LIST_HEAD(l->q));
2703 		} else {
2704 			debug("making new TCP request, %d tries left",
2705 			      l->retries);
2706 			l->retries--;
2707 			requeue_lookup(l, 1);
2708 			cancel_lookup(l);
2709 			check_next_lookup(l);
2710 		}
2711 	} else {
2712 		if (!l->ns_search_only) {
2713 			fputs(l->cmdline, stdout);
2714 			printf(";; connection timed out; no servers could be "
2715 			       "reached\n");
2716 		}
2717 		cancel_lookup(l);
2718 		check_next_lookup(l);
2719 		if (exitcode < 9)
2720 			exitcode = 9;
2721 	}
2722 }
2723 
2724 /*%
2725  * Event handler for the TCP recv which gets the length header of TCP
2726  * packets.  Start the next recv of length bytes.
2727  */
2728 static void
2729 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2730 	isc_socketevent_t *sevent;
2731 	isc_buffer_t *b = NULL;
2732 	isc_result_t result;
2733 	dig_query_t *query = NULL;
2734 	dig_lookup_t *l, *n;
2735 	uint16_t length;
2736 
2737 	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2738 	INSIST(!free_now);
2739 
2740 	UNUSED(task);
2741 
2742 	debug("tcp_length_done()");
2743 
2744 	sevent = (isc_socketevent_t *)event;
2745 	query = event->ev_arg;
2746 
2747 	recvcount--;
2748 	INSIST(recvcount >= 0);
2749 
2750 	b = ISC_LIST_HEAD(sevent->bufferlist);
2751 	INSIST(b ==  &query->lengthbuf);
2752 	ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2753 
2754 	if (sevent->result == ISC_R_CANCELED) {
2755 		isc_event_free(&event);
2756 		l = query->lookup;
2757 		clear_query(query);
2758 		check_next_lookup(l);
2759 		return;
2760 	}
2761 	if (sevent->result != ISC_R_SUCCESS) {
2762 		char sockstr[ISC_SOCKADDR_FORMATSIZE];
2763 		isc_sockaddr_format(&query->sockaddr, sockstr,
2764 				    sizeof(sockstr));
2765 		printf(";; communications error to %s: %s\n",
2766 		       sockstr, isc_result_totext(sevent->result));
2767 		if (keep != NULL)
2768 			isc_socket_detach(&keep);
2769 		l = query->lookup;
2770 		isc_socket_detach(&query->sock);
2771 		sockcount--;
2772 		debug("sockcount=%d", sockcount);
2773 		INSIST(sockcount >= 0);
2774 		if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
2775 			n = requeue_lookup(l, 1);
2776 			n->eoferr++;
2777 		}
2778 		isc_event_free(&event);
2779 		clear_query(query);
2780 		cancel_lookup(l);
2781 		check_next_lookup(l);
2782 		return;
2783 	}
2784 	length = isc_buffer_getuint16(b);
2785 	if (length == 0) {
2786 		isc_event_free(&event);
2787 		launch_next_query(query, 0);
2788 		return;
2789 	}
2790 
2791 	/*
2792 	 * Even though the buffer was already init'ed, we need
2793 	 * to redo it now, to force the length we want.
2794 	 */
2795 	isc_buffer_invalidate(&query->recvbuf);
2796 	isc_buffer_init(&query->recvbuf, query->recvspace, length);
2797 	ENSURE(ISC_LIST_EMPTY(query->recvlist));
2798 	ISC_LINK_INIT(&query->recvbuf, link);
2799 	ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2800 	debug("recving with lookup=%p, query=%p", query->lookup, query);
2801 	result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2802 				  recv_done, query);
2803 	check_result(result, "isc_socket_recvv");
2804 	recvcount++;
2805 	debug("resubmitted recv request with length %d, recvcount=%d",
2806 	      length, recvcount);
2807 	isc_event_free(&event);
2808 }
2809 
2810 /*%
2811  * For transfers that involve multiple recvs (XFR's in particular),
2812  * launch the next recv.
2813  */
2814 static void
2815 launch_next_query(dig_query_t *query, int include_question) {
2816 	isc_result_t result;
2817 	dig_lookup_t *l;
2818 	isc_buffer_t *buffer;
2819 
2820 	INSIST(!free_now);
2821 
2822 	debug("launch_next_query()");
2823 
2824 	if (!query->lookup->pending) {
2825 		debug("ignoring launch_next_query because !pending");
2826 		isc_socket_detach(&query->sock);
2827 		sockcount--;
2828 		debug("sockcount=%d", sockcount);
2829 		INSIST(sockcount >= 0);
2830 		query->waiting_connect = 0;
2831 		l = query->lookup;
2832 		clear_query(query);
2833 		check_next_lookup(l);
2834 		return;
2835 	}
2836 
2837 	isc_buffer_clear(&query->slbuf);
2838 	isc_buffer_clear(&query->lengthbuf);
2839 	isc_buffer_putuint16(&query->slbuf, (uint16_t) query->sendbuf.used);
2840 	ISC_LIST_INIT(query->sendlist);
2841 	ISC_LINK_INIT(&query->slbuf, link);
2842 	if (!query->first_soa_rcvd) {
2843 		buffer = clone_buffer(&query->slbuf);
2844 		ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2845 		if (include_question) {
2846 			buffer = clone_buffer(&query->sendbuf);
2847 			ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2848 		}
2849 	}
2850 
2851 	ISC_LINK_INIT(&query->lengthbuf, link);
2852 	ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2853 
2854 	result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2855 				  global_task, tcp_length_done, query);
2856 	check_result(result, "isc_socket_recvv");
2857 	recvcount++;
2858 	debug("recvcount=%d", recvcount);
2859 	if (!query->first_soa_rcvd) {
2860 		debug("sending a request in launch_next_query");
2861 		clock_gettime(CLOCK_MONOTONIC, &query->time_sent);
2862 		query->waiting_senddone = 1;
2863 		result = isc_socket_sendv(query->sock, &query->sendlist,
2864 					  global_task, send_done, query);
2865 		check_result(result, "isc_socket_sendv");
2866 		sendcount++;
2867 		debug("sendcount=%d", sendcount);
2868 	}
2869 	query->waiting_connect = 0;
2870 	return;
2871 }
2872 
2873 /*%
2874  * Event handler for TCP connect complete.  Make sure the connection was
2875  * successful, then pass into launch_next_query to actually send the
2876  * question.
2877  */
2878 static void
2879 connect_done(isc_task_t *task, isc_event_t *event) {
2880 	char sockstr[ISC_SOCKADDR_FORMATSIZE];
2881 	isc_socketevent_t *sevent = NULL;
2882 	dig_query_t *query = NULL, *next;
2883 	dig_lookup_t *l;
2884 
2885 	UNUSED(task);
2886 
2887 	REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2888 	INSIST(!free_now);
2889 
2890 	debug("connect_done()");
2891 
2892 	sevent = (isc_socketevent_t *)event;
2893 	query = sevent->ev_arg;
2894 
2895 	INSIST(query->waiting_connect);
2896 
2897 	query->waiting_connect = 0;
2898 
2899 	if (sevent->result == ISC_R_CANCELED) {
2900 		debug("in cancel handler");
2901 		isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2902 		if (query->timedout)
2903 			printf(";; Connection to %s(%s) for %s failed: %s.\n",
2904 			       sockstr, query->servname,
2905 			       query->lookup->textname,
2906 			       isc_result_totext(ISC_R_TIMEDOUT));
2907 		isc_socket_detach(&query->sock);
2908 		INSIST(sockcount > 0);
2909 		sockcount--;
2910 		debug("sockcount=%d", sockcount);
2911 		query->waiting_connect = 0;
2912 		isc_event_free(&event);
2913 		l = query->lookup;
2914 		clear_query(query);
2915 		check_next_lookup(l);
2916 		return;
2917 	}
2918 	if (sevent->result != ISC_R_SUCCESS) {
2919 
2920 		debug("unsuccessful connection: %s",
2921 		      isc_result_totext(sevent->result));
2922 		isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2923 		if (sevent->result != ISC_R_CANCELED)
2924 			printf(";; Connection to %s(%s) for %s failed: "
2925 			       "%s.\n", sockstr,
2926 			       query->servname, query->lookup->textname,
2927 			       isc_result_totext(sevent->result));
2928 		isc_socket_detach(&query->sock);
2929 		INSIST(sockcount > 0);
2930 		sockcount--;
2931 		/* XXX Clean up exitcodes */
2932 		if (exitcode < 9)
2933 			exitcode = 9;
2934 		debug("sockcount=%d", sockcount);
2935 		query->waiting_connect = 0;
2936 		isc_event_free(&event);
2937 		l = query->lookup;
2938 		if ((l->current_query != NULL) &&
2939 		    (ISC_LINK_LINKED(l->current_query, link)))
2940 			next = ISC_LIST_NEXT(l->current_query, link);
2941 		else
2942 			next = NULL;
2943 		clear_query(query);
2944 		if (next != NULL) {
2945 			bringup_timer(next, TCP_TIMEOUT);
2946 			send_tcp_connect(next);
2947 		} else
2948 			check_next_lookup(l);
2949 		return;
2950 	}
2951 	if (keep_open) {
2952 		if (keep != NULL)
2953 			isc_socket_detach(&keep);
2954 		isc_socket_attach(query->sock, &keep);
2955 		keepaddr = query->sockaddr;
2956 	}
2957 	launch_next_query(query, 1);
2958 	isc_event_free(&event);
2959 }
2960 
2961 /*%
2962  * Check if the ongoing XFR needs more data before it's complete, using
2963  * the semantics of IXFR and AXFR protocols.  Much of the complexity of
2964  * this routine comes from determining when an IXFR is complete.
2965  * 0 means more data is on the way, and the recv has been issued.
2966  */
2967 static int
2968 check_for_more_data(dig_query_t *query, dns_message_t *msg,
2969 		    isc_socketevent_t *sevent)
2970 {
2971 	dns_rdataset_t *rdataset = NULL;
2972 	dns_rdata_t rdata = DNS_RDATA_INIT;
2973 	dns_rdata_soa_t soa;
2974 	uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
2975 	isc_result_t result;
2976 	int ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
2977 	int axfr = query->lookup->rdtype == dns_rdatatype_axfr;
2978 
2979 	if (ixfr)
2980 		axfr = query->ixfr_axfr;
2981 
2982 	debug("check_for_more_data()");
2983 
2984 	/*
2985 	 * By the time we're in this routine, we know we're doing
2986 	 * either an AXFR or IXFR.  If there's no second_rr_type,
2987 	 * then we don't yet know which kind of answer we got back
2988 	 * from the server.  Here, we're going to walk through the
2989 	 * rr's in the message, acting as necessary whenever we hit
2990 	 * an SOA rr.
2991 	 */
2992 
2993 	query->msg_count++;
2994 	query->byte_count += sevent->n;
2995 	result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
2996 	if (result != ISC_R_SUCCESS) {
2997 		puts("; Transfer failed.");
2998 		return (1);
2999 	}
3000 	do {
3001 		dns_name_t *name;
3002 		name = NULL;
3003 		dns_message_currentname(msg, DNS_SECTION_ANSWER,
3004 					&name);
3005 		for (rdataset = ISC_LIST_HEAD(name->list);
3006 		     rdataset != NULL;
3007 		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
3008 			result = dns_rdataset_first(rdataset);
3009 			if (result != ISC_R_SUCCESS)
3010 				continue;
3011 			do {
3012 				query->rr_count++;
3013 				dns_rdata_reset(&rdata);
3014 				dns_rdataset_current(rdataset, &rdata);
3015 				/*
3016 				 * If this is the first rr, make sure
3017 				 * it's an SOA
3018 				 */
3019 				if ((!query->first_soa_rcvd) &&
3020 				    (rdata.type != dns_rdatatype_soa)) {
3021 					puts("; Transfer failed.  "
3022 					     "Didn't start with SOA answer.");
3023 					return (1);
3024 				}
3025 				if ((!query->second_rr_rcvd) &&
3026 				    (rdata.type != dns_rdatatype_soa)) {
3027 					query->second_rr_rcvd = 1;
3028 					query->second_rr_serial = 0;
3029 					debug("got the second rr as nonsoa");
3030 					axfr = query->ixfr_axfr = 1;
3031 					goto next_rdata;
3032 				}
3033 
3034 				/*
3035 				 * If the record is anything except an SOA
3036 				 * now, just continue on...
3037 				 */
3038 				if (rdata.type != dns_rdatatype_soa)
3039 					goto next_rdata;
3040 
3041 				/* Now we have an SOA.  Work with it. */
3042 				debug("got an SOA");
3043 				result = dns_rdata_tostruct_soa(&rdata, &soa);
3044 				check_result(result, "dns_rdata_tostruct_soa");
3045 				serial = soa.serial;
3046 				dns_rdata_freestruct_soa(&soa);
3047 				if (!query->first_soa_rcvd) {
3048 					query->first_soa_rcvd = 1;
3049 					query->first_rr_serial = serial;
3050 					debug("this is the first serial %u",
3051 					      serial);
3052 					if (ixfr && isc_serial_ge(ixfr_serial,
3053 								  serial)) {
3054 						debug("got up to date "
3055 						      "response");
3056 						goto doexit;
3057 					}
3058 					goto next_rdata;
3059 				}
3060 				if (axfr) {
3061 					debug("doing axfr, got second SOA");
3062 					goto doexit;
3063 				}
3064 				if (!query->second_rr_rcvd) {
3065 					if (query->first_rr_serial == serial) {
3066 						debug("doing ixfr, got "
3067 						      "empty zone");
3068 						goto doexit;
3069 					}
3070 					debug("this is the second serial %u",
3071 					      serial);
3072 					query->second_rr_rcvd = 1;
3073 					query->second_rr_serial = serial;
3074 					goto next_rdata;
3075 				}
3076 				/*
3077 				 * If we get to this point, we're doing an
3078 				 * IXFR and have to start really looking
3079 				 * at serial numbers.
3080 				 */
3081 				if (query->first_rr_serial == serial) {
3082 					debug("got a match for ixfr");
3083 					if (!query->first_repeat_rcvd) {
3084 						query->first_repeat_rcvd =
3085 							1;
3086 						goto next_rdata;
3087 					}
3088 					debug("done with ixfr");
3089 					goto doexit;
3090 				}
3091 				debug("meaningless soa %u", serial);
3092 			next_rdata:
3093 				result = dns_rdataset_next(rdataset);
3094 			} while (result == ISC_R_SUCCESS);
3095 		}
3096 		result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3097 	} while (result == ISC_R_SUCCESS);
3098 	launch_next_query(query, 0);
3099 	return (0);
3100  doexit:
3101 	dighost_received(sevent->n, &sevent->address, query);
3102 	return (1);
3103 }
3104 
3105 static void
3106 process_sit(dig_lookup_t *l, dns_message_t *msg,
3107 	    isc_buffer_t *optbuf, size_t optlen)
3108 {
3109 	char bb[256];
3110 	isc_buffer_t hexbuf;
3111 	size_t len;
3112 	const unsigned char *sit;
3113 	int copysit;
3114 	isc_result_t result;
3115 
3116 	if (l->sitvalue != NULL) {
3117 		isc_buffer_init(&hexbuf, bb, sizeof(bb));
3118 		result = isc_hex_decodestring(l->sitvalue, &hexbuf);
3119 		check_result(result, "isc_hex_decodestring");
3120 		sit = isc_buffer_base(&hexbuf);
3121 		len = isc_buffer_usedlength(&hexbuf);
3122 		copysit = 0;
3123 	} else {
3124 		sit = cookie;
3125 		len = sizeof(cookie);
3126 		copysit = 1;
3127 	}
3128 
3129 	INSIST(msg->sitok == 0 && msg->sitbad == 0);
3130 	if (optlen >= len && optlen >= 8U) {
3131 		if (timingsafe_bcmp(isc_buffer_current(optbuf), sit, 8) == 0) {
3132 			msg->sitok = 1;
3133 		} else {
3134 			printf(";; Warning: SIT client cookie mismatch\n");
3135 			msg->sitbad = 1;
3136 			copysit = 0;
3137 		}
3138 	} else {
3139 		printf(";; Warning: SIT bad token (too short)\n");
3140 		msg->sitbad = 1;
3141 		copysit = 0;
3142 	}
3143 	if (copysit) {
3144 		isc_region_t r;
3145 
3146 		r.base = isc_buffer_current(optbuf);
3147 		r.length = (unsigned int)optlen;
3148 		isc_buffer_init(&hexbuf, sitvalue, sizeof(sitvalue));
3149 		result = isc_hex_totext(&r, 2, "", &hexbuf);
3150 		check_result(result, "isc_hex_totext");
3151 		if (isc_buffer_availablelength(&hexbuf) > 0) {
3152 			isc_buffer_putuint8(&hexbuf, 0);
3153 			l->sitvalue = sitvalue;
3154 		}
3155 	}
3156 	isc_buffer_forward(optbuf, (unsigned int)optlen);
3157 }
3158 
3159 static void
3160 process_opt(dig_lookup_t *l, dns_message_t *msg) {
3161 	dns_rdata_t rdata;
3162 	isc_result_t result;
3163 	isc_buffer_t optbuf;
3164 	uint16_t optcode, optlen;
3165 	dns_rdataset_t *opt = msg->opt;
3166 	int seen_cookie = 0;
3167 
3168 	result = dns_rdataset_first(opt);
3169 	if (result == ISC_R_SUCCESS) {
3170 		dns_rdata_init(&rdata);
3171 		dns_rdataset_current(opt, &rdata);
3172 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
3173 		isc_buffer_add(&optbuf, rdata.length);
3174 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
3175 			optcode = isc_buffer_getuint16(&optbuf);
3176 			optlen = isc_buffer_getuint16(&optbuf);
3177 			switch (optcode) {
3178 			case DNS_OPT_COOKIE:
3179 				/*
3180 				 * Only process the first cookie option.
3181 				 */
3182 				if (seen_cookie) {
3183 					isc_buffer_forward(&optbuf, optlen);
3184 					break;
3185 				}
3186 				process_sit(l, msg, &optbuf, optlen);
3187 				seen_cookie = 1;
3188 				break;
3189 			default:
3190 				isc_buffer_forward(&optbuf, optlen);
3191 				break;
3192 			}
3193 		}
3194 	}
3195 }
3196 
3197 static int
3198 ednsvers(dns_rdataset_t *opt) {
3199 	return ((opt->ttl >> 16) & 0xff);
3200 }
3201 
3202 /*%
3203  * Event handler for recv complete.  Perform whatever actions are necessary,
3204  * based on the specifics of the user's request.
3205  */
3206 static void
3207 recv_done(isc_task_t *task, isc_event_t *event) {
3208 	isc_socketevent_t *sevent = NULL;
3209 	dig_query_t *query = NULL;
3210 	isc_buffer_t *b = NULL;
3211 	dns_message_t *msg = NULL;
3212 	isc_result_t result;
3213 	dig_lookup_t *n, *l;
3214 	int docancel = 0;
3215 	int match = 1;
3216 	unsigned int parseflags;
3217 	dns_messageid_t id;
3218 	unsigned int msgflags;
3219 	int newedns;
3220 
3221 	UNUSED(task);
3222 	INSIST(!free_now);
3223 
3224 	debug("recv_done()");
3225 
3226 	recvcount--;
3227 	debug("recvcount=%d", recvcount);
3228 	INSIST(recvcount >= 0);
3229 
3230 	query = event->ev_arg;
3231 	clock_gettime(CLOCK_MONOTONIC, &query->time_recv);
3232 	debug("lookup=%p, query=%p", query->lookup, query);
3233 
3234 	l = query->lookup;
3235 
3236 	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3237 	sevent = (isc_socketevent_t *)event;
3238 
3239 	b = ISC_LIST_HEAD(sevent->bufferlist);
3240 	INSIST(b == &query->recvbuf);
3241 	ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3242 
3243 	if ((l->tcp_mode) && (query->timer != NULL))
3244 		isc_timer_touch(query->timer);
3245 	if ((!l->pending && !l->ns_search_only) || cancel_now) {
3246 		debug("no longer pending.  Got %s",
3247 			isc_result_totext(sevent->result));
3248 		query->waiting_connect = 0;
3249 
3250 		isc_event_free(&event);
3251 		clear_query(query);
3252 		check_next_lookup(l);
3253 		return;
3254 	}
3255 
3256 	if (sevent->result != ISC_R_SUCCESS) {
3257 		if (sevent->result == ISC_R_CANCELED) {
3258 			debug("in recv cancel handler");
3259 			query->waiting_connect = 0;
3260 		} else {
3261 			printf(";; communications error: %s\n",
3262 			       isc_result_totext(sevent->result));
3263 			if (keep != NULL)
3264 				isc_socket_detach(&keep);
3265 			isc_socket_detach(&query->sock);
3266 			sockcount--;
3267 			debug("sockcount=%d", sockcount);
3268 			INSIST(sockcount >= 0);
3269 		}
3270 		if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
3271 			n = requeue_lookup(l, 1);
3272 			n->eoferr++;
3273 		}
3274 		isc_event_free(&event);
3275 		clear_query(query);
3276 		cancel_lookup(l);
3277 		check_next_lookup(l);
3278 		return;
3279 	}
3280 
3281 	if (!l->tcp_mode &&
3282 	    !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3283 				  ISC_SOCKADDR_CMPADDR|
3284 				  ISC_SOCKADDR_CMPPORT|
3285 				  ISC_SOCKADDR_CMPSCOPE|
3286 				  ISC_SOCKADDR_CMPSCOPEZERO)) {
3287 		char buf1[ISC_SOCKADDR_FORMATSIZE];
3288 		char buf2[ISC_SOCKADDR_FORMATSIZE];
3289 		struct sockaddr_storage any;
3290 
3291 		if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3292 			isc_sockaddr_any(&any);
3293 		else
3294 			isc_sockaddr_any6(&any);
3295 
3296 		/*
3297 		* We don't expect a match when the packet is
3298 		* sent to 0.0.0.0, :: or to a multicast addresses.
3299 		* XXXMPA broadcast needs to be handled here as well.
3300 		*/
3301 		if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3302 		     !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3303 		    isc_sockaddr_getport(&query->sockaddr) !=
3304 		    isc_sockaddr_getport(&sevent->address)) {
3305 			isc_sockaddr_format(&sevent->address, buf1,
3306 			sizeof(buf1));
3307 			isc_sockaddr_format(&query->sockaddr, buf2,
3308 			sizeof(buf2));
3309 			printf(";; reply from unexpected source: %s,"
3310 			" expected %s\n", buf1, buf2);
3311 			match = 0;
3312 		}
3313 	}
3314 
3315 	result = dns_message_peekheader(b, &id, &msgflags);
3316 	if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3317 		match = 0;
3318 		if (l->tcp_mode) {
3319 			int fail = 1;
3320 			if (result == ISC_R_SUCCESS) {
3321 				if (!query->first_soa_rcvd ||
3322 				     query->warn_id)
3323 					printf(";; %s: ID mismatch: "
3324 					       "expected ID %u, got %u\n",
3325 					       query->first_soa_rcvd ?
3326 					       "WARNING" : "ERROR",
3327 					       l->sendmsg->id, id);
3328 				if (query->first_soa_rcvd)
3329 					fail = 0;
3330 				query->warn_id = 0;
3331 			} else
3332 				printf(";; ERROR: short "
3333 				       "(< header size) message\n");
3334 			if (fail) {
3335 				isc_event_free(&event);
3336 				clear_query(query);
3337 				cancel_lookup(l);
3338 				check_next_lookup(l);
3339 				return;
3340 			}
3341 			match = 1;
3342 		} else if (result == ISC_R_SUCCESS)
3343 			printf(";; Warning: ID mismatch: "
3344 			       "expected ID %u, got %u\n", l->sendmsg->id, id);
3345 		else
3346 			printf(";; Warning: short "
3347 			       "(< header size) message received\n");
3348 	}
3349 
3350 	if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3351 		printf(";; Warning: query response not set\n");
3352 
3353 	if (!match)
3354 		goto udp_mismatch;
3355 
3356 	result = dns_message_create(DNS_MESSAGE_INTENTPARSE, &msg);
3357 	check_result(result, "dns_message_create");
3358 
3359 	if (tsigkey != NULL) {
3360 		if (l->querysig == NULL) {
3361 			debug("getting initial querysig");
3362 			result = dns_message_getquerytsig(l->sendmsg,
3363 							  &l->querysig);
3364 			check_result(result, "dns_message_getquerytsig");
3365 		}
3366 		result = dns_message_setquerytsig(msg, l->querysig);
3367 		check_result(result, "dns_message_setquerytsig");
3368 		result = dns_message_settsigkey(msg, tsigkey);
3369 		check_result(result, "dns_message_settsigkey");
3370 		msg->tsigctx = l->tsigctx;
3371 		l->tsigctx = NULL;
3372 		if (l->msgcounter != 0)
3373 			msg->tcp_continuation = 1;
3374 		l->msgcounter++;
3375 	}
3376 
3377 	debug("before parse starts");
3378 	parseflags = 0;
3379 	if (l->besteffort) {
3380 		parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3381 		parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3382 	}
3383 	result = dns_message_parse(msg, b, parseflags);
3384 	if (result == DNS_R_RECOVERABLE) {
3385 		printf(";; Warning: Message parser reports malformed "
3386 		       "message packet.\n");
3387 		result = ISC_R_SUCCESS;
3388 	}
3389 	if (result != ISC_R_SUCCESS) {
3390 		printf(";; Got bad packet: %s\n", isc_result_totext(result));
3391 		hex_dump(b);
3392 		query->waiting_connect = 0;
3393 		dns_message_destroy(&msg);
3394 		isc_event_free(&event);
3395 		clear_query(query);
3396 		cancel_lookup(l);
3397 		check_next_lookup(l);
3398 		return;
3399 	}
3400 	if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3401 		match = 1;
3402 		for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3403 		     result == ISC_R_SUCCESS && match;
3404 		     result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3405 			dns_name_t *name = NULL;
3406 			dns_rdataset_t *rdataset;
3407 
3408 			dns_message_currentname(msg, DNS_SECTION_QUESTION,
3409 						&name);
3410 			for (rdataset = ISC_LIST_HEAD(name->list);
3411 			     rdataset != NULL;
3412 			     rdataset = ISC_LIST_NEXT(rdataset, link)) {
3413 				if (l->rdtype != rdataset->type ||
3414 				    l->rdclass != rdataset->rdclass ||
3415 				    !dns_name_equal(l->name, name)) {
3416 					char namestr[DNS_NAME_FORMATSIZE];
3417 					char typebuf[DNS_RDATATYPE_FORMATSIZE];
3418 					char classbuf[DNS_RDATACLASS_FORMATSIZE];
3419 					dns_name_format(name, namestr,
3420 							sizeof(namestr));
3421 					dns_rdatatype_format(rdataset->type,
3422 							     typebuf,
3423 							     sizeof(typebuf));
3424 					dns_rdataclass_format(rdataset->rdclass,
3425 							      classbuf,
3426 							      sizeof(classbuf));
3427 					printf(";; Question section mismatch: "
3428 					       "got %s/%s/%s\n",
3429 					       namestr, typebuf, classbuf);
3430 					match = 0;
3431 				}
3432 			}
3433 		}
3434 		if (!match) {
3435 			dns_message_destroy(&msg);
3436 			if (l->tcp_mode) {
3437 				isc_event_free(&event);
3438 				clear_query(query);
3439 				cancel_lookup(l);
3440 				check_next_lookup(l);
3441 				return;
3442 			} else
3443 				goto udp_mismatch;
3444 		}
3445 	}
3446 	if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
3447 	    (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) {
3448 		/*
3449 		 * Add minimum EDNS version required checks here if needed.
3450 		 */
3451 		if (l->comments)
3452 			printf(";; BADVERS, retrying with EDNS version %u.\n",
3453 			       (unsigned int)newedns);
3454 		l->edns = newedns;
3455 		n = requeue_lookup(l, 1);
3456 		if (l->trace && l->trace_root)
3457 			n->rdtype = l->qrdtype;
3458 		dns_message_destroy(&msg);
3459 		isc_event_free(&event);
3460 		clear_query(query);
3461 		cancel_lookup(l);
3462 		check_next_lookup(l);
3463 		return;
3464 	}
3465 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3466 	    !l->ignore && !l->tcp_mode) {
3467 		if (l->sitvalue == NULL && l->sit && msg->opt != NULL)
3468 			process_opt(l, msg);
3469 		if (l->comments)
3470 			printf(";; Truncated, retrying in TCP mode.\n");
3471 		n = requeue_lookup(l, 1);
3472 		n->tcp_mode = 1;
3473 		if (l->trace && l->trace_root)
3474 			n->rdtype = l->qrdtype;
3475 		dns_message_destroy(&msg);
3476 		isc_event_free(&event);
3477 		clear_query(query);
3478 		cancel_lookup(l);
3479 		check_next_lookup(l);
3480 		return;
3481 	}
3482 	if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3483 	    (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3484 	{
3485 		dig_query_t *next = ISC_LIST_NEXT(query, link);
3486 		if (l->current_query == query)
3487 			l->current_query = NULL;
3488 		if (next != NULL) {
3489 			debug("sending query %p\n", next);
3490 			if (l->tcp_mode)
3491 				send_tcp_connect(next);
3492 			else
3493 				send_udp(next);
3494 		}
3495 		/*
3496 		 * If our query is at the head of the list and there
3497 		 * is no next, we're the only one left, so fall
3498 		 * through to print the message.
3499 		 */
3500 		if ((ISC_LIST_HEAD(l->q) != query) ||
3501 		    (ISC_LIST_NEXT(query, link) != NULL)) {
3502 			if (l->comments)
3503 				printf(";; Got %s from %s, "
3504 				       "trying next server\n",
3505 				       msg->rcode == dns_rcode_servfail ?
3506 				       "SERVFAIL reply" :
3507 				       "recursion not available",
3508 				       query->servname);
3509 			clear_query(query);
3510 			check_next_lookup(l);
3511 			dns_message_destroy(&msg);
3512 			isc_event_free(&event);
3513 			return;
3514 		}
3515 	}
3516 
3517 	if (tsigkey != NULL) {
3518 		result = dns_tsig_verify(&query->recvbuf, msg);
3519 		if (result != ISC_R_SUCCESS) {
3520 			printf(";; Couldn't verify signature: %s\n",
3521 			       isc_result_totext(result));
3522 			validated = 0;
3523 		}
3524 		l->tsigctx = msg->tsigctx;
3525 		msg->tsigctx = NULL;
3526 		if (l->querysig != NULL) {
3527 			debug("freeing querysig buffer %p", l->querysig);
3528 			isc_buffer_free(&l->querysig);
3529 		}
3530 		result = dns_message_getquerytsig(msg, &l->querysig);
3531 		check_result(result,"dns_message_getquerytsig");
3532 	}
3533 
3534 	extrabytes = isc_buffer_remaininglength(b);
3535 
3536 	debug("after parse");
3537 	if (l->doing_xfr && l->xfr_q == NULL) {
3538 		l->xfr_q = query;
3539 		/*
3540 		 * Once we are in the XFR message, increase
3541 		 * the timeout to much longer, so brief network
3542 		 * outages won't cause the XFR to abort
3543 		 */
3544 		if (timeout != INT_MAX && query->timer != NULL) {
3545 			unsigned int local_timeout;
3546 
3547 			if (timeout == 0) {
3548 				if (l->tcp_mode)
3549 					local_timeout = TCP_TIMEOUT * 4;
3550 				else
3551 					local_timeout = UDP_TIMEOUT * 4;
3552 			} else {
3553 				if (timeout < (INT_MAX / 4))
3554 					local_timeout = timeout * 4;
3555 				else
3556 					local_timeout = INT_MAX;
3557 			}
3558 			debug("have local timeout of %d", local_timeout);
3559 			l->interval.tv_sec = local_timeout;
3560 			l->interval.tv_nsec = 0;
3561 			result = isc_timer_reset(query->timer,
3562 						 &l->interval,
3563 						 0);
3564 			check_result(result, "isc_timer_reset");
3565 		}
3566 	}
3567 
3568 	if (l->sitvalue != NULL) {
3569 		if (msg->opt == NULL)
3570 			printf(";; expected opt record in response\n");
3571 		else
3572 			process_opt(l, msg);
3573 	} else if (l->sit && msg->opt != NULL)
3574 		process_opt(l, msg);
3575 
3576 	if (!l->doing_xfr || l->xfr_q == query) {
3577 		if (msg->rcode == dns_rcode_nxdomain &&
3578 		    (l->origin != NULL || l->need_search)) {
3579 			if (!next_origin(query->lookup) || showsearch) {
3580 				dighost_printmessage(query, msg, 1);
3581 				dighost_received(b->used, &sevent->address, query);
3582 			}
3583 		} else if (!l->trace && !l->ns_search_only) {
3584 				dighost_printmessage(query, msg, 1);
3585 		} else if (l->trace) {
3586 			int nl = 0;
3587 			int count = msg->counts[DNS_SECTION_ANSWER];
3588 
3589 			debug("in TRACE code");
3590 			if (!l->ns_search_only)
3591 				dighost_printmessage(query, msg, 1);
3592 
3593 			l->rdtype = l->qrdtype;
3594 			if (l->trace_root || (l->ns_search_only && count > 0)) {
3595 				if (!l->trace_root)
3596 					l->rdtype = dns_rdatatype_soa;
3597 				nl = followup_lookup(msg, query,
3598 						     DNS_SECTION_ANSWER);
3599 				l->trace_root = 0;
3600 			} else if (count == 0)
3601 				nl = followup_lookup(msg, query,
3602 						     DNS_SECTION_AUTHORITY);
3603 			if (nl == 0)
3604 				docancel = 1;
3605 		} else {
3606 			debug("in NSSEARCH code");
3607 
3608 			if (l->trace_root) {
3609 				/*
3610 				 * This is the initial NS query.
3611 				 */
3612 				int nl;
3613 
3614 				l->rdtype = dns_rdatatype_soa;
3615 				nl = followup_lookup(msg, query,
3616 						     DNS_SECTION_ANSWER);
3617 				if (nl == 0)
3618 					docancel = 1;
3619 				l->trace_root = 0;
3620 				usesearch = 0;
3621 			} else
3622 				dighost_printmessage(query, msg, 1);
3623 		}
3624 	}
3625 
3626 	if (l->pending)
3627 		debug("still pending.");
3628 	if (l->doing_xfr) {
3629 		if (query != l->xfr_q) {
3630 			dns_message_destroy(&msg);
3631 			isc_event_free(&event);
3632 			query->waiting_connect = 0;
3633 			return;
3634 		}
3635 		if (!docancel)
3636 			docancel = check_for_more_data(query, msg, sevent);
3637 		if (docancel) {
3638 			dns_message_destroy(&msg);
3639 			clear_query(query);
3640 			cancel_lookup(l);
3641 			check_next_lookup(l);
3642 		}
3643 	} else {
3644 
3645 		if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3646 
3647 				dighost_received(b->used, &sevent->address, query);
3648 		}
3649 
3650 		if (!query->lookup->ns_search_only)
3651 			query->lookup->pending = 0;
3652 		if (!query->lookup->ns_search_only ||
3653 		    query->lookup->trace_root || docancel) {
3654 				dns_message_destroy(&msg);
3655 
3656 			cancel_lookup(l);
3657 		}
3658 		clear_query(query);
3659 		check_next_lookup(l);
3660 	}
3661 	if (msg != NULL) {
3662 			dns_message_destroy(&msg);
3663 	}
3664 	isc_event_free(&event);
3665 	return;
3666 
3667  udp_mismatch:
3668 	isc_buffer_invalidate(&query->recvbuf);
3669 	isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3670 	ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3671 	result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3672 				  global_task, recv_done, query);
3673 	check_result(result, "isc_socket_recvv");
3674 	recvcount++;
3675 	isc_event_free(&event);
3676 	return;
3677 }
3678 
3679 /*%
3680  * Turn a name into an address, using system-supplied routines.  This is
3681  * used in looking up server names, etc... and needs to use system-supplied
3682  * routines, since they may be using a non-DNS system for these lookups.
3683  */
3684 isc_result_t
3685 get_address(char *host, in_port_t myport, struct sockaddr_storage *sockaddr) {
3686 	int count;
3687 	isc_result_t result;
3688 
3689 	result = get_addresses(host, myport, sockaddr, 1, &count);
3690 	if (result != ISC_R_SUCCESS)
3691 		return (result);
3692 
3693 	INSIST(count == 1);
3694 
3695 	return (ISC_R_SUCCESS);
3696 }
3697 
3698 int
3699 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3700 	isc_result_t result;
3701 	struct sockaddr_storage sockaddrs[DIG_MAX_ADDRESSES];
3702 	int count, i;
3703 	dig_server_t *srv;
3704 	char tmp[NI_MAXHOST];
3705 
3706 	result = get_addresses(host, 0, sockaddrs,
3707 				    DIG_MAX_ADDRESSES, &count);
3708 	if (resultp != NULL)
3709 		*resultp = result;
3710 	if (result != ISC_R_SUCCESS) {
3711 		if (resultp == NULL)
3712 			fatal("couldn't get address for '%s': %s",
3713 			      host, isc_result_totext(result));
3714 		return (0);
3715 	}
3716 
3717 	for (i = 0; i < count; i++) {
3718 		int error;
3719 		error = getnameinfo((struct sockaddr *)&sockaddrs[i],
3720 		    sockaddrs[i].ss_len, tmp, sizeof(tmp), NULL, 0,
3721 		    NI_NUMERICHOST | NI_NUMERICSERV);
3722 		if (error)
3723 			fatal("%s", gai_strerror(error));
3724 
3725 		srv = make_server(tmp, host);
3726 		ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3727 	}
3728 
3729 	return (count);
3730 }
3731 
3732 /*%
3733  * Initiate either a TCP or UDP lookup
3734  */
3735 void
3736 do_lookup(dig_lookup_t *lookup) {
3737 	dig_query_t *query;
3738 
3739 	REQUIRE(lookup != NULL);
3740 
3741 	debug("do_lookup()");
3742 	lookup->pending = 1;
3743 	query = ISC_LIST_HEAD(lookup->q);
3744 	if (query != NULL) {
3745 		if (lookup->tcp_mode)
3746 			send_tcp_connect(query);
3747 		else
3748 			send_udp(query);
3749 	}
3750 }
3751 
3752 /*%
3753  * Start everything in action upon task startup.
3754  */
3755 void
3756 onrun_callback(isc_task_t *task, isc_event_t *event) {
3757 	UNUSED(task);
3758 
3759 	isc_event_free(&event);
3760 	start_lookup();
3761 }
3762 
3763 /*%
3764  * Make everything on the lookup queue go away.  Mainly used by the
3765  * SIGINT handler.
3766  */
3767 void
3768 cancel_all(void) {
3769 	dig_lookup_t *l, *n;
3770 	dig_query_t *q, *nq;
3771 
3772 	debug("cancel_all()");
3773 
3774 	if (free_now) {
3775 		return;
3776 	}
3777 	cancel_now = 1;
3778 	if (current_lookup != NULL) {
3779 		for (q = ISC_LIST_HEAD(current_lookup->q);
3780 		     q != NULL;
3781 		     q = nq)
3782 		{
3783 			nq = ISC_LIST_NEXT(q, link);
3784 			debug("canceling pending query %p, belonging to %p",
3785 			      q, current_lookup);
3786 			if (q->sock != NULL)
3787 				isc_socket_cancel(q->sock, NULL,
3788 						  ISC_SOCKCANCEL_ALL);
3789 			else
3790 				clear_query(q);
3791 		}
3792 		for (q = ISC_LIST_HEAD(current_lookup->connecting);
3793 		     q != NULL;
3794 		     q = nq)
3795 		{
3796 			nq = ISC_LIST_NEXT(q, clink);
3797 			debug("canceling connecting query %p, belonging to %p",
3798 			      q, current_lookup);
3799 			if (q->sock != NULL)
3800 				isc_socket_cancel(q->sock, NULL,
3801 						  ISC_SOCKCANCEL_ALL);
3802 			else
3803 				clear_query(q);
3804 		}
3805 	}
3806 	l = ISC_LIST_HEAD(lookup_list);
3807 	while (l != NULL) {
3808 		n = ISC_LIST_NEXT(l, link);
3809 		ISC_LIST_DEQUEUE(lookup_list, l, link);
3810 		try_clear_lookup(l);
3811 		l = n;
3812 	}
3813 }
3814 
3815 /*%
3816  * Destroy all of the libs we are using, and get everything ready for a
3817  * clean shutdown.
3818  */
3819 void
3820 destroy_libs(void) {
3821 
3822 	if (keep != NULL)
3823 		isc_socket_detach(&keep);
3824 	debug("destroy_libs()");
3825 	if (global_task != NULL) {
3826 		debug("freeing task");
3827 		isc_task_detach(&global_task);
3828 	}
3829 	/*
3830 	 * The taskmgr_destroy() call blocks until all events are cleared
3831 	 * from the task.
3832 	 */
3833 	if (taskmgr != NULL) {
3834 		debug("freeing taskmgr");
3835 		isc_taskmgr_destroy(&taskmgr);
3836 	}
3837 	REQUIRE(sockcount == 0);
3838 	REQUIRE(recvcount == 0);
3839 	REQUIRE(sendcount == 0);
3840 
3841 	INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3842 	INSIST(current_lookup == NULL);
3843 	INSIST(!free_now);
3844 
3845 	free_now = 1;
3846 
3847 	lwres_conf_clear(lwconf);
3848 
3849 	flush_server_list();
3850 
3851 	clear_searchlist();
3852 
3853 	if (socketmgr != NULL) {
3854 		debug("freeing socketmgr");
3855 		isc_socketmgr_destroy(&socketmgr);
3856 	}
3857 	if (timermgr != NULL) {
3858 		debug("freeing timermgr");
3859 		isc_timermgr_destroy(&timermgr);
3860 	}
3861 	if (tsigkey != NULL) {
3862 		debug("freeing key %p", tsigkey);
3863 		dns_tsigkey_detach(&tsigkey);
3864 	}
3865 	if (namebuf != NULL)
3866 		isc_buffer_free(&namebuf);
3867 
3868 	if (is_dst_up) {
3869 		debug("destroy DST lib");
3870 		dst_lib_destroy();
3871 		is_dst_up = 0;
3872 	}
3873 
3874 	debug("Removing log context");
3875 	isc_log_destroy(&lctx);
3876 
3877 }
3878 
3879 int64_t
3880 uelapsed(const struct timespec *t1, const struct timespec *t2)
3881 {
3882 	struct timespec	 diff, zero = {0, 0};
3883 	struct timeval	 tv;
3884 
3885 	timespecsub(t1, t2, &diff);
3886 
3887 	if (timespeccmp(&diff, &zero, <=))
3888 		return 0;
3889 
3890 	TIMESPEC_TO_TIMEVAL(&tv, &diff);
3891 
3892 	return (tv.tv_sec * 1000000 + tv.tv_usec);
3893 }
3894