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