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.38 2024/04/23 13:34:50 jsg 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
71static lwres_conf_t  lwconfdata;
72static lwres_conf_t *lwconf = &lwconfdata;
73
74dig_lookuplist_t lookup_list;
75dig_serverlist_t server_list;
76dig_serverlist_t root_hints_server_list;
77dig_searchlistlist_t search_list;
78
79int
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;
91in_port_t port = 53;
92unsigned int timeout = 0;
93unsigned int extrabytes;
94isc_log_t *lctx = NULL;
95isc_taskmgr_t *taskmgr = NULL;
96isc_task_t *global_task = NULL;
97isc_timermgr_t *timermgr = NULL;
98isc_socketmgr_t *socketmgr = NULL;
99struct sockaddr_storage bind_address;
100struct sockaddr_storage bind_any;
101int sendcount = 0;
102int recvcount = 0;
103int sockcount = 0;
104int ndots = -1;
105int tries = 3;
106int lookup_counter = 0;
107
108static char sitvalue[256];
109
110isc_socket_t *keep = NULL;
111struct sockaddr_storage keepaddr;
112
113static 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 */
155int exitcode = 0;
156int fatalexit = 0;
157char keynametext[MXNAME];
158char keyfile[MXNAME] = "";
159char keysecret[MXNAME] = "";
160unsigned char cookie_secret[33];
161unsigned char cookie[8];
162dns_name_t *hmacname = NULL;
163unsigned int digestbits = 0;
164isc_buffer_t *namebuf = NULL;
165dns_tsigkey_t *tsigkey = NULL;
166int validated = 1;
167int debugging = 0;
168int debugtiming = 0;
169char *progname = NULL;
170dig_lookup_t *current_lookup = NULL;
171
172#define DIG_MAX_ADDRESSES 20
173
174/* dynamic callbacks */
175
176isc_result_t
177(*dighost_printmessage)(dig_query_t *query, dns_message_t *msg,
178	int headers);
179
180void
181(*dighost_received)(unsigned int bytes, struct sockaddr_storage *from, dig_query_t *query);
182
183void
184(*dighost_trying)(char *frm, dig_lookup_t *lookup);
185
186void
187(*dighost_shutdown)(void);
188
189/* forward declarations */
190
191static void
192cancel_lookup(dig_lookup_t *lookup);
193
194static void
195recv_done(isc_task_t *task, isc_event_t *event);
196
197static void
198send_udp(dig_query_t *query);
199
200static void
201connect_timeout(isc_task_t *task, isc_event_t *event);
202
203static void
204launch_next_query(dig_query_t *query, int include_question);
205
206static void
207check_next_lookup(dig_lookup_t *lookup);
208
209static int
210next_origin(dig_lookup_t *oldlookup);
211
212char *
213next_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
224static int
225count_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
238static void
239hex_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 */
277static isc_result_t
278append(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
286static isc_result_t
287reverse_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
305isc_result_t
306get_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
362void
363fatal(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
379void
380debug(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
398void
399check_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 */
410dig_server_t *
411make_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
427static int
428addr2af(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 */
449static void
450copy_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
480void
481flush_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 */
495static isc_result_t
496get_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
552isc_result_t
553set_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
585static isc_result_t
586add_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 */
617void
618clone_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 */
637dig_lookup_t *
638make_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
720static void
721cloneopts(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 */
760dig_lookup_t *
761clone_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 */
850dig_lookup_t *
851requeue_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
871void
872setup_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
921static uint32_t
922parse_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
933isc_result_t
934parse_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
966done:
967	*plen = prefix_length;
968	*sap = sa;
969
970	return (ISC_R_SUCCESS);
971}
972
973/*
974 * Parse HMAC algorithm specification
975 */
976void
977parse_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 */
1025static isc_result_t
1026read_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
1074void
1075setup_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
1088static dig_searchlist_t *
1089make_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
1101static void
1102clear_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
1110static void
1111create_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 */
1128void
1129setup_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 */
1206void
1207set_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 */
1218void
1219setup_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
1259typedef struct dig_ednsoptname {
1260	uint32_t code;
1261	const char  *name;
1262} dig_ednsoptname_t;
1263
1264dig_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
1282void
1283save_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 */
1341static void
1342add_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 */
1360static void
1361add_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 */
1383static void
1384check_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 */
1400static void
1401clear_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 */
1446static int
1447try_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
1482void
1483destroy_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 */
1530void
1531start_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 */
1561static void
1562check_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 */
1584static int
1585followup_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 */
1751static int
1752next_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 */
1806static void
1807insert_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
1863static void
1864compute_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]))
1871static void
1872populate_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 */
1898int
1899setup_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 */
2350static void
2351send_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 */
2397static void
2398cancel_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
2418static void
2419bringup_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
2450static void
2451force_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
2474static void
2475connect_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 */
2482static void
2483send_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
2575static isc_buffer_t *
2576clone_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 */
2591static void
2592send_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 */
2661static void
2662connect_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 */
2728static void
2729tcp_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 */
2814static void
2815launch_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 */
2878static void
2879connect_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 */
2967static int
2968check_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
3105static void
3106process_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
3159static void
3160process_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
3197static int
3198ednsvers(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 */
3206static void
3207recv_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			dighost_received(b->used, &sevent->address, query);
3647		}
3648
3649		if (!query->lookup->ns_search_only)
3650			query->lookup->pending = 0;
3651		if (!query->lookup->ns_search_only ||
3652		    query->lookup->trace_root || docancel) {
3653			dns_message_destroy(&msg);
3654
3655			cancel_lookup(l);
3656		}
3657		clear_query(query);
3658		check_next_lookup(l);
3659	}
3660	if (msg != NULL) {
3661			dns_message_destroy(&msg);
3662	}
3663	isc_event_free(&event);
3664	return;
3665
3666 udp_mismatch:
3667	isc_buffer_invalidate(&query->recvbuf);
3668	isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3669	ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3670	result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3671				  global_task, recv_done, query);
3672	check_result(result, "isc_socket_recvv");
3673	recvcount++;
3674	isc_event_free(&event);
3675	return;
3676}
3677
3678/*%
3679 * Turn a name into an address, using system-supplied routines.  This is
3680 * used in looking up server names, etc... and needs to use system-supplied
3681 * routines, since they may be using a non-DNS system for these lookups.
3682 */
3683isc_result_t
3684get_address(char *host, in_port_t myport, struct sockaddr_storage *sockaddr) {
3685	int count;
3686	isc_result_t result;
3687
3688	result = get_addresses(host, myport, sockaddr, 1, &count);
3689	if (result != ISC_R_SUCCESS)
3690		return (result);
3691
3692	INSIST(count == 1);
3693
3694	return (ISC_R_SUCCESS);
3695}
3696
3697int
3698getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3699	isc_result_t result;
3700	struct sockaddr_storage sockaddrs[DIG_MAX_ADDRESSES];
3701	int count, i;
3702	dig_server_t *srv;
3703	char tmp[NI_MAXHOST];
3704
3705	result = get_addresses(host, 0, sockaddrs,
3706				    DIG_MAX_ADDRESSES, &count);
3707	if (resultp != NULL)
3708		*resultp = result;
3709	if (result != ISC_R_SUCCESS) {
3710		if (resultp == NULL)
3711			fatal("couldn't get address for '%s': %s",
3712			      host, isc_result_totext(result));
3713		return (0);
3714	}
3715
3716	for (i = 0; i < count; i++) {
3717		int error;
3718		error = getnameinfo((struct sockaddr *)&sockaddrs[i],
3719		    sockaddrs[i].ss_len, tmp, sizeof(tmp), NULL, 0,
3720		    NI_NUMERICHOST | NI_NUMERICSERV);
3721		if (error)
3722			fatal("%s", gai_strerror(error));
3723
3724		srv = make_server(tmp, host);
3725		ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3726	}
3727
3728	return (count);
3729}
3730
3731/*%
3732 * Initiate either a TCP or UDP lookup
3733 */
3734void
3735do_lookup(dig_lookup_t *lookup) {
3736	dig_query_t *query;
3737
3738	REQUIRE(lookup != NULL);
3739
3740	debug("do_lookup()");
3741	lookup->pending = 1;
3742	query = ISC_LIST_HEAD(lookup->q);
3743	if (query != NULL) {
3744		if (lookup->tcp_mode)
3745			send_tcp_connect(query);
3746		else
3747			send_udp(query);
3748	}
3749}
3750
3751/*%
3752 * Start everything in action upon task startup.
3753 */
3754void
3755onrun_callback(isc_task_t *task, isc_event_t *event) {
3756	UNUSED(task);
3757
3758	isc_event_free(&event);
3759	start_lookup();
3760}
3761
3762/*%
3763 * Make everything on the lookup queue go away.  Mainly used by the
3764 * SIGINT handler.
3765 */
3766void
3767cancel_all(void) {
3768	dig_lookup_t *l, *n;
3769	dig_query_t *q, *nq;
3770
3771	debug("cancel_all()");
3772
3773	if (free_now) {
3774		return;
3775	}
3776	cancel_now = 1;
3777	if (current_lookup != NULL) {
3778		for (q = ISC_LIST_HEAD(current_lookup->q);
3779		     q != NULL;
3780		     q = nq)
3781		{
3782			nq = ISC_LIST_NEXT(q, link);
3783			debug("canceling pending query %p, belonging to %p",
3784			      q, current_lookup);
3785			if (q->sock != NULL)
3786				isc_socket_cancel(q->sock, NULL,
3787						  ISC_SOCKCANCEL_ALL);
3788			else
3789				clear_query(q);
3790		}
3791		for (q = ISC_LIST_HEAD(current_lookup->connecting);
3792		     q != NULL;
3793		     q = nq)
3794		{
3795			nq = ISC_LIST_NEXT(q, clink);
3796			debug("canceling connecting query %p, belonging to %p",
3797			      q, current_lookup);
3798			if (q->sock != NULL)
3799				isc_socket_cancel(q->sock, NULL,
3800						  ISC_SOCKCANCEL_ALL);
3801			else
3802				clear_query(q);
3803		}
3804	}
3805	l = ISC_LIST_HEAD(lookup_list);
3806	while (l != NULL) {
3807		n = ISC_LIST_NEXT(l, link);
3808		ISC_LIST_DEQUEUE(lookup_list, l, link);
3809		try_clear_lookup(l);
3810		l = n;
3811	}
3812}
3813
3814/*%
3815 * Destroy all of the libs we are using, and get everything ready for a
3816 * clean shutdown.
3817 */
3818void
3819destroy_libs(void) {
3820
3821	if (keep != NULL)
3822		isc_socket_detach(&keep);
3823	debug("destroy_libs()");
3824	if (global_task != NULL) {
3825		debug("freeing task");
3826		isc_task_detach(&global_task);
3827	}
3828	/*
3829	 * The taskmgr_destroy() call blocks until all events are cleared
3830	 * from the task.
3831	 */
3832	if (taskmgr != NULL) {
3833		debug("freeing taskmgr");
3834		isc_taskmgr_destroy(&taskmgr);
3835	}
3836	REQUIRE(sockcount == 0);
3837	REQUIRE(recvcount == 0);
3838	REQUIRE(sendcount == 0);
3839
3840	INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3841	INSIST(current_lookup == NULL);
3842	INSIST(!free_now);
3843
3844	free_now = 1;
3845
3846	lwres_conf_clear(lwconf);
3847
3848	flush_server_list();
3849
3850	clear_searchlist();
3851
3852	if (socketmgr != NULL) {
3853		debug("freeing socketmgr");
3854		isc_socketmgr_destroy(&socketmgr);
3855	}
3856	if (timermgr != NULL) {
3857		debug("freeing timermgr");
3858		isc_timermgr_destroy(&timermgr);
3859	}
3860	if (tsigkey != NULL) {
3861		debug("freeing key %p", tsigkey);
3862		dns_tsigkey_detach(&tsigkey);
3863	}
3864	if (namebuf != NULL)
3865		isc_buffer_free(&namebuf);
3866
3867	if (is_dst_up) {
3868		debug("destroy DST lib");
3869		dst_lib_destroy();
3870		is_dst_up = 0;
3871	}
3872
3873	debug("Removing log context");
3874	isc_log_destroy(&lctx);
3875
3876}
3877
3878int64_t
3879uelapsed(const struct timespec *t1, const struct timespec *t2)
3880{
3881	struct timespec	 diff, zero = {0, 0};
3882	struct timeval	 tv;
3883
3884	timespecsub(t1, t2, &diff);
3885
3886	if (timespeccmp(&diff, &zero, <=))
3887		return 0;
3888
3889	TIMESPEC_TO_TIMEVAL(&tv, &diff);
3890
3891	return (tv.tv_sec * 1000000 + tv.tv_usec);
3892}
3893