1 /*
2  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* $Id: dighost.c,v 1.345 2011/12/07 17:23:28 each Exp $ */
19 
20 /*! \file
21  *  \note
22  * Notice to programmers:  Do not use this code as an example of how to
23  * use the ISC library to perform DNS lookups.  Dig and Host both operate
24  * on the request level, since they allow fine-tuning of output and are
25  * intended as debugging tools.  As a result, they perform many of the
26  * functions which could be better handled using the dns_resolver
27  * functions in most applications.
28  */
29 
30 #include <config.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <limits.h>
35 
36 #ifdef HAVE_LOCALE_H
37 #include <locale.h>
38 #endif
39 
40 #ifdef WITH_IDN
41 #include <idn/result.h>
42 #include <idn/log.h>
43 #include <idn/resconf.h>
44 #include <idn/api.h>
45 #endif
46 
47 #include <dns/byaddr.h>
48 #ifdef DIG_SIGCHASE
49 #include <dns/callbacks.h>
50 #include <dns/dnssec.h>
51 #include <dns/ds.h>
52 #include <dns/master.h>
53 #include <dns/nsec.h>
54 #include <isc/random.h>
55 #include <ctype.h>
56 #endif
57 #include <dns/fixedname.h>
58 #include <dns/log.h>
59 #include <dns/message.h>
60 #include <dns/name.h>
61 #include <dns/rcode.h>
62 #include <dns/rdata.h>
63 #include <dns/rdataclass.h>
64 #include <dns/rdatalist.h>
65 #include <dns/rdataset.h>
66 #include <dns/rdatastruct.h>
67 #include <dns/rdatatype.h>
68 #include <dns/result.h>
69 #include <dns/tsig.h>
70 
71 #include <dst/dst.h>
72 #include <dst/result.h>
73 
74 #include <isc/app.h>
75 #include <isc/base64.h>
76 #include <isc/entropy.h>
77 #include <isc/file.h>
78 #include <isc/lang.h>
79 #include <isc/log.h>
80 #include <isc/netaddr.h>
81 #ifdef DIG_SIGCHASE
82 #include <isc/netdb.h>
83 #endif
84 #include <isc/parseint.h>
85 #include <isc/print.h>
86 #include <isc/random.h>
87 #include <isc/result.h>
88 #include <isc/safe.h>
89 #include <isc/serial.h>
90 #include <isc/string.h>
91 #include <isc/task.h>
92 #include <isc/timer.h>
93 #include <isc/types.h>
94 #include <isc/util.h>
95 
96 #include <isccfg/namedconf.h>
97 
98 #include <lwres/lwres.h>
99 #include <lwres/net.h>
100 
101 #include <bind9/getaddresses.h>
102 
103 #include <dig/dig.h>
104 
105 #if ! defined(NS_INADDRSZ)
106 #define NS_INADDRSZ	 4
107 #endif
108 
109 #if ! defined(NS_IN6ADDRSZ)
110 #define NS_IN6ADDRSZ	16
111 #endif
112 
113 static lwres_context_t *lwctx = NULL;
114 static lwres_conf_t *lwconf;
115 
116 dig_lookuplist_t lookup_list;
117 dig_serverlist_t server_list;
118 dig_searchlistlist_t search_list;
119 
120 isc_boolean_t
121 	check_ra = ISC_FALSE,
122 	have_ipv4 = ISC_FALSE,
123 	have_ipv6 = ISC_FALSE,
124 	specified_source = ISC_FALSE,
125 	free_now = ISC_FALSE,
126 	cancel_now = ISC_FALSE,
127 	usesearch = ISC_FALSE,
128 	showsearch = ISC_FALSE,
129 	qr = ISC_FALSE,
130 	is_dst_up = ISC_FALSE,
131 	keep_open = ISC_FALSE;
132 in_port_t port = 53;
133 unsigned int timeout = 0;
134 unsigned int extrabytes;
135 isc_mem_t *mctx = NULL;
136 isc_log_t *lctx = NULL;
137 isc_taskmgr_t *taskmgr = NULL;
138 isc_task_t *global_task = NULL;
139 isc_timermgr_t *timermgr = NULL;
140 isc_socketmgr_t *socketmgr = NULL;
141 isc_sockaddr_t bind_address;
142 isc_sockaddr_t bind_any;
143 int sendcount = 0;
144 int recvcount = 0;
145 int sockcount = 0;
146 int ndots = -1;
147 int tries = 3;
148 int lookup_counter = 0;
149 
150 #ifdef WITH_IDN
151 static void		initialize_idn(void);
152 static isc_result_t	output_filter(isc_buffer_t *buffer,
153 				      unsigned int used_org,
154 				      isc_boolean_t absolute);
155 static idn_result_t	append_textname(char *name, const char *origin,
156 					size_t namesize);
157 static void		idn_check_result(idn_result_t r, const char *msg);
158 
159 #define MAXDLEN		256
160 int  idnoptions	= 0;
161 #endif
162 
163 isc_socket_t *keep = NULL;
164 isc_sockaddr_t keepaddr;
165 
166 /*%
167  * Exit Codes:
168  *
169  *\li	0   Everything went well, including things like NXDOMAIN
170  *\li	1   Usage error
171  *\li	7   Got too many RR's or Names
172  *\li	8   Couldn't open batch file
173  *\li	9   No reply from server
174  *\li	10  Internal error
175  */
176 int exitcode = 0;
177 int fatalexit = 0;
178 char keynametext[MXNAME];
179 char keyfile[MXNAME] = "";
180 char keysecret[MXNAME] = "";
181 dns_name_t *hmacname = NULL;
182 unsigned int digestbits = 0;
183 isc_buffer_t *namebuf = NULL;
184 dns_tsigkey_t *key = NULL;
185 isc_boolean_t validated = ISC_TRUE;
186 isc_entropy_t *entp = NULL;
187 isc_mempool_t *commctx = NULL;
188 isc_boolean_t debugging = ISC_FALSE;
189 isc_boolean_t debugtiming = ISC_FALSE;
190 isc_boolean_t memdebugging = ISC_FALSE;
191 char *progname = NULL;
192 isc_mutex_t lookup_lock;
193 dig_lookup_t *current_lookup = NULL;
194 
195 #ifdef DIG_SIGCHASE
196 
197 isc_result_t	  get_trusted_key(void);
198 dns_rdataset_t *  sigchase_scanname(dns_rdatatype_t type,
199 				    dns_rdatatype_t covers,
200 				    isc_boolean_t *lookedup,
201 				    dns_name_t *rdata_name);
202 dns_rdataset_t *  chase_scanname_section(dns_message_t *msg,
203 					 dns_name_t *name,
204 					 dns_rdatatype_t type,
205 					 dns_rdatatype_t covers,
206 					 int section);
207 isc_result_t	  advanced_rrsearch(dns_rdataset_t **rdataset,
208 				    dns_name_t *name,
209 				    dns_rdatatype_t type,
210 				    dns_rdatatype_t covers,
211 				    isc_boolean_t *lookedup);
212 isc_result_t	  sigchase_verify_sig_key(dns_name_t *name,
213 					  dns_rdataset_t *rdataset,
214 					  dst_key_t* dnsseckey,
215 					  dns_rdataset_t *sigrdataset);
216 isc_result_t	  sigchase_verify_sig(dns_name_t *name,
217 				      dns_rdataset_t *rdataset,
218 				      dns_rdataset_t *keyrdataset,
219 				      dns_rdataset_t *sigrdataset);
220 isc_result_t	  sigchase_verify_ds(dns_name_t *name,
221 				     dns_rdataset_t *keyrdataset,
222 				     dns_rdataset_t *dsrdataset);
223 void		  sigchase(dns_message_t *msg);
224 void		  print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
225 void		  print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset);
226 void		  dup_name(dns_name_t *source, dns_name_t* target);
227 void		  free_name(dns_name_t *name);
228 void		  dump_database(void);
229 void		  dump_database_section(dns_message_t *msg, int section);
230 dns_rdataset_t *  search_type(dns_name_t *name, dns_rdatatype_t type,
231 			      dns_rdatatype_t covers);
232 isc_result_t	  contains_trusted_key(dns_name_t *name,
233 				       dns_rdataset_t *rdataset,
234 				       dns_rdataset_t *sigrdataset);
235 void		  print_type(dns_rdatatype_t type);
236 isc_result_t	  prove_nx_domain(dns_message_t * msg,
237 				  dns_name_t * name,
238 				  dns_name_t * rdata_name,
239 				  dns_rdataset_t ** rdataset,
240 				  dns_rdataset_t ** sigrdataset);
241 isc_result_t	  prove_nx_type(dns_message_t * msg, dns_name_t *name,
242 				dns_rdataset_t *nsec,
243 				dns_rdataclass_t class,
244 				dns_rdatatype_t type,
245 				dns_name_t * rdata_name,
246 				dns_rdataset_t ** rdataset,
247 				dns_rdataset_t ** sigrdataset);
248 isc_result_t	  prove_nx(dns_message_t * msg, dns_name_t * name,
249 			   dns_rdataclass_t class,
250 			   dns_rdatatype_t type,
251 			   dns_name_t * rdata_name,
252 			   dns_rdataset_t ** rdataset,
253 			   dns_rdataset_t ** sigrdataset);
254 static void	  nameFromString(const char *str, dns_name_t *p_ret);
255 int		  inf_name(dns_name_t * name1, dns_name_t * name2);
256 isc_result_t	  removetmpkey(const char *file);
257 void		  clean_trustedkey(void);
258 isc_result_t 	  insert_trustedkey(void *arg, dns_name_t *name,
259 				    dns_rdataset_t *rdataset);
260 #if DIG_SIGCHASE_BU
261 isc_result_t	  getneededrr(dns_message_t *msg);
262 void		  sigchase_bottom_up(dns_message_t *msg);
263 void		  sigchase_bu(dns_message_t *msg);
264 #endif
265 #if DIG_SIGCHASE_TD
266 isc_result_t	  initialization(dns_name_t *name);
267 isc_result_t	  prepare_lookup(dns_name_t *name);
268 isc_result_t	  grandfather_pb_test(dns_name_t * zone_name,
269 				      dns_rdataset_t *sigrdataset);
270 isc_result_t	  child_of_zone(dns_name_t *name,
271 				dns_name_t *zone_name,
272 				dns_name_t *child_name);
273 void		  sigchase_td(dns_message_t *msg);
274 #endif
275 char trustedkey[MXNAME] = "";
276 
277 dns_rdataset_t *chase_rdataset = NULL;
278 dns_rdataset_t *chase_sigrdataset = NULL;
279 dns_rdataset_t *chase_dsrdataset = NULL;
280 dns_rdataset_t *chase_sigdsrdataset = NULL;
281 dns_rdataset_t *chase_keyrdataset = NULL;
282 dns_rdataset_t *chase_sigkeyrdataset = NULL;
283 dns_rdataset_t *chase_nsrdataset = NULL;
284 
285 dns_name_t chase_name; /* the query name */
286 #if DIG_SIGCHASE_TD
287 /*
288  * the current name is the parent name when we follow delegation
289  */
290 dns_name_t chase_current_name;
291 /*
292  * the child name is used for delegation (NS DS responses in AUTHORITY section)
293  */
294 dns_name_t chase_authority_name;
295 #endif
296 #if DIG_SIGCHASE_BU
297 dns_name_t chase_signame;
298 #endif
299 
300 
301 isc_boolean_t chase_siglookedup = ISC_FALSE;
302 isc_boolean_t chase_keylookedup = ISC_FALSE;
303 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
304 isc_boolean_t chase_dslookedup = ISC_FALSE;
305 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
306 #if DIG_SIGCHASE_TD
307 isc_boolean_t chase_nslookedup = ISC_FALSE;
308 isc_boolean_t chase_lookedup = ISC_FALSE;
309 
310 
311 isc_boolean_t delegation_follow = ISC_FALSE;
312 isc_boolean_t grandfather_pb = ISC_FALSE;
313 isc_boolean_t have_response = ISC_FALSE;
314 isc_boolean_t have_delegation_ns = ISC_FALSE;
315 dns_message_t * error_message = NULL;
316 #endif
317 
318 isc_boolean_t dsvalidating = ISC_FALSE;
319 isc_boolean_t chase_name_dup = ISC_FALSE;
320 
321 ISC_LIST(dig_message_t) chase_message_list;
322 ISC_LIST(dig_message_t) chase_message_list2;
323 
324 
325 #define MAX_TRUSTED_KEY 5
326 typedef struct struct_trusted_key_list {
327 	dst_key_t * key[MAX_TRUSTED_KEY];
328 	int nb_tk;
329 } struct_tk_list;
330 
331 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
332 
333 #endif
334 
335 #define DIG_MAX_ADDRESSES 20
336 
337 /*%
338  * Apply and clear locks at the event level in global task.
339  * Can I get rid of these using shutdown events?  XXX
340  */
341 #define LOCK_LOOKUP {\
342 	debug("lock_lookup %s:%d", __FILE__, __LINE__);\
343 	check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
344 	debug("success");\
345 }
346 #define UNLOCK_LOOKUP {\
347 	debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
348 	check_result(isc_mutex_unlock((&lookup_lock)),\
349 		     "isc_mutex_unlock");\
350 }
351 
352 static void
353 cancel_lookup(dig_lookup_t *lookup);
354 
355 static void
356 recv_done(isc_task_t *task, isc_event_t *event);
357 
358 static void
359 send_udp(dig_query_t *query);
360 
361 static void
362 connect_timeout(isc_task_t *task, isc_event_t *event);
363 
364 static void
365 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
366 
367 static void
368 check_next_lookup(dig_lookup_t *lookup);
369 
370 static isc_boolean_t
371 next_origin(dig_lookup_t *oldlookup);
372 
373 static void *
mem_alloc(void * arg,size_t size)374 mem_alloc(void *arg, size_t size) {
375 	return (isc_mem_get(arg, size));
376 }
377 
378 static void
mem_free(void * arg,void * mem,size_t size)379 mem_free(void *arg, void *mem, size_t size) {
380 	isc_mem_put(arg, mem, size);
381 }
382 
383 char *
next_token(char ** stringp,const char * delim)384 next_token(char **stringp, const char *delim) {
385 	char *res;
386 
387 	do {
388 		res = strsep(stringp, delim);
389 		if (res == NULL)
390 			break;
391 	} while (*res == '\0');
392 	return (res);
393 }
394 
395 static int
count_dots(char * string)396 count_dots(char *string) {
397 	char *s;
398 	int i = 0;
399 
400 	s = string;
401 	while (*s != '\0') {
402 		if (*s == '.')
403 			i++;
404 		s++;
405 	}
406 	return (i);
407 }
408 
409 static void
hex_dump(isc_buffer_t * b)410 hex_dump(isc_buffer_t *b) {
411 	unsigned int len, i;
412 	isc_region_t r;
413 
414 	isc_buffer_usedregion(b, &r);
415 
416 	printf("%d bytes\n", r.length);
417 	for (len = 0; len < r.length; len++) {
418 		printf("%02x ", r.base[len]);
419 		if (len % 16 == 15) {
420 			fputs("         ", stdout);
421 			for (i = len - 15; i <= len; i++) {
422 				if (r.base[i] >= '!' && r.base[i] <= '}')
423 					putchar(r.base[i]);
424 				else
425 					putchar('.');
426 			}
427 			printf("\n");
428 		}
429 	}
430 	if (len % 16 != 0) {
431 		for (i = len; (i % 16) != 0; i++)
432 			fputs("   ", stdout);
433 		fputs("         ", stdout);
434 		for (i = ((len>>4)<<4); i < len; i++) {
435 			if (r.base[i] >= '!' && r.base[i] <= '}')
436 				putchar(r.base[i]);
437 			else
438 				putchar('.');
439 		}
440 		printf("\n");
441 	}
442 }
443 
444 /*%
445  * Append 'len' bytes of 'text' at '*p', failing with
446  * ISC_R_NOSPACE if that would advance p past 'end'.
447  */
448 static isc_result_t
append(const char * text,int len,char ** p,char * end)449 append(const char *text, int len, char **p, char *end) {
450 	if (len > end - *p)
451 		return (ISC_R_NOSPACE);
452 	memmove(*p, text, len);
453 	*p += len;
454 	return (ISC_R_SUCCESS);
455 }
456 
457 static isc_result_t
reverse_octets(const char * in,char ** p,char * end)458 reverse_octets(const char *in, char **p, char *end) {
459 	const char *dot = strchr(in, '.');
460 	int len;
461 	if (dot != NULL) {
462 		isc_result_t result;
463 		result = reverse_octets(dot + 1, p, end);
464 		if (result != ISC_R_SUCCESS)
465 			return (result);
466 		result = append(".", 1, p, end);
467 		if (result != ISC_R_SUCCESS)
468 			return (result);
469 		len = (int)(dot - in);
470 	} else {
471 		len = strlen(in);
472 	}
473 	return (append(in, len, p, end));
474 }
475 
476 isc_result_t
get_reverse(char * reverse,size_t len,char * value,isc_boolean_t ip6_int,isc_boolean_t strict)477 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
478 	    isc_boolean_t strict)
479 {
480 	int r;
481 	isc_result_t result;
482 	isc_netaddr_t addr;
483 
484 	addr.family = AF_INET6;
485 	r = inet_pton(AF_INET6, value, &addr.type.in6);
486 	if (r > 0) {
487 		/* This is a valid IPv6 address. */
488 		dns_fixedname_t fname;
489 		dns_name_t *name;
490 		unsigned int options = 0;
491 
492 		if (ip6_int)
493 			options |= DNS_BYADDROPT_IPV6INT;
494 		dns_fixedname_init(&fname);
495 		name = dns_fixedname_name(&fname);
496 		result = dns_byaddr_createptrname2(&addr, options, name);
497 		if (result != ISC_R_SUCCESS)
498 			return (result);
499 		dns_name_format(name, reverse, (unsigned int)len);
500 		return (ISC_R_SUCCESS);
501 	} else {
502 		/*
503 		 * Not a valid IPv6 address.  Assume IPv4.
504 		 * If 'strict' is not set, construct the
505 		 * in-addr.arpa name by blindly reversing
506 		 * octets whether or not they look like integers,
507 		 * so that this can be used for RFC2317 names
508 		 * and such.
509 		 */
510 		char *p = reverse;
511 		char *end = reverse + len;
512 		if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
513 			return (DNS_R_BADDOTTEDQUAD);
514 		result = reverse_octets(value, &p, end);
515 		if (result != ISC_R_SUCCESS)
516 			return (result);
517 		/* Append .in-addr.arpa. and a terminating NUL. */
518 		result = append(".in-addr.arpa.", 15, &p, end);
519 		if (result != ISC_R_SUCCESS)
520 			return (result);
521 		return (ISC_R_SUCCESS);
522 	}
523 }
524 
525 void
fatal(const char * format,...)526 fatal(const char *format, ...) {
527 	va_list args;
528 
529 	fflush(stdout);
530 	fprintf(stderr, "%s: ", progname);
531 	va_start(args, format);
532 	vfprintf(stderr, format, args);
533 	va_end(args);
534 	fprintf(stderr, "\n");
535 	if (exitcode < 10)
536 		exitcode = 10;
537 	if (fatalexit != 0)
538 		exitcode = fatalexit;
539 	exit(exitcode);
540 }
541 
542 void
debug(const char * format,...)543 debug(const char *format, ...) {
544 	va_list args;
545 	isc_time_t t;
546 
547 	if (debugging) {
548 		fflush(stdout);
549 		if (debugtiming) {
550 			TIME_NOW(&t);
551 			fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
552 				isc_time_nanoseconds(&t) / 1000);
553 		}
554 		va_start(args, format);
555 		vfprintf(stderr, format, args);
556 		va_end(args);
557 		fprintf(stderr, "\n");
558 	}
559 }
560 
561 void
check_result(isc_result_t result,const char * msg)562 check_result(isc_result_t result, const char *msg) {
563 	if (result != ISC_R_SUCCESS) {
564 		fatal("%s: %s", msg, isc_result_totext(result));
565 	}
566 }
567 
568 /*%
569  * Create a server structure, which is part of the lookup structure.
570  * This is little more than a linked list of servers to query in hopes
571  * of finding the answer the user is looking for
572  */
573 dig_server_t *
make_server(const char * servname,const char * userarg)574 make_server(const char *servname, const char *userarg) {
575 	dig_server_t *srv;
576 
577 	REQUIRE(servname != NULL);
578 
579 	debug("make_server(%s)", servname);
580 	srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
581 	if (srv == NULL)
582 		fatal("memory allocation failure in %s:%d",
583 		      __FILE__, __LINE__);
584 	strlcpy(srv->servername, servname, MXNAME);
585 	strlcpy(srv->userarg, userarg, MXNAME);
586 	ISC_LINK_INIT(srv, link);
587 	return (srv);
588 }
589 
590 static int
addr2af(int lwresaddrtype)591 addr2af(int lwresaddrtype)
592 {
593 	int af = 0;
594 
595 	switch (lwresaddrtype) {
596 	case LWRES_ADDRTYPE_V4:
597 		af = AF_INET;
598 		break;
599 
600 	case LWRES_ADDRTYPE_V6:
601 		af = AF_INET6;
602 		break;
603 	}
604 
605 	return (af);
606 }
607 
608 /*%
609  * Create a copy of the server list from the lwres configuration structure.
610  * The dest list must have already had ISC_LIST_INIT applied.
611  */
612 static void
copy_server_list(lwres_conf_t * confdata,dig_serverlist_t * dest)613 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
614 	dig_server_t *newsrv;
615 	char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
616 		 sizeof("%4000000000")];
617 	int af;
618 	int i;
619 
620 	debug("copy_server_list()");
621 	for (i = 0; i < confdata->nsnext; i++) {
622 		af = addr2af(confdata->nameservers[i].family);
623 
624 		if (af == AF_INET && !have_ipv4)
625 			continue;
626 		if (af == AF_INET6 && !have_ipv6)
627 			continue;
628 
629 		lwres_net_ntop(af, confdata->nameservers[i].address,
630 				   tmp, sizeof(tmp));
631 		if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
632 			char buf[sizeof("%4000000000")];
633 			snprintf(buf, sizeof(buf), "%%%u",
634 				 confdata->nameservers[i].zone);
635 			strlcat(tmp, buf, sizeof(tmp));
636 		}
637 		newsrv = make_server(tmp, tmp);
638 		ISC_LINK_INIT(newsrv, link);
639 		ISC_LIST_ENQUEUE(*dest, newsrv, link);
640 	}
641 }
642 
643 void
flush_server_list(void)644 flush_server_list(void) {
645 	dig_server_t *s, *ps;
646 
647 	debug("flush_server_list()");
648 	s = ISC_LIST_HEAD(server_list);
649 	while (s != NULL) {
650 		ps = s;
651 		s = ISC_LIST_NEXT(s, link);
652 		ISC_LIST_DEQUEUE(server_list, ps, link);
653 		isc_mem_free(mctx, ps);
654 	}
655 }
656 
657 void
set_nameserver(char * opt)658 set_nameserver(char *opt) {
659 	isc_result_t result;
660 	isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
661 	isc_netaddr_t netaddr;
662 	int count, i;
663 	dig_server_t *srv;
664 	char tmp[ISC_NETADDR_FORMATSIZE];
665 
666 	if (opt == NULL)
667 		return;
668 
669 	result = bind9_getaddresses(opt, 0, sockaddrs,
670 				    DIG_MAX_ADDRESSES, &count);
671 	if (result != ISC_R_SUCCESS)
672 		fatal("couldn't get address for '%s': %s",
673 		      opt, isc_result_totext(result));
674 
675 	flush_server_list();
676 
677 	for (i = 0; i < count; i++) {
678 		isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
679 		isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
680 		srv = make_server(tmp, opt);
681 		if (srv == NULL)
682 			fatal("memory allocation failure");
683 		ISC_LIST_APPEND(server_list, srv, link);
684 	}
685 }
686 
687 static isc_result_t
add_nameserver(lwres_conf_t * confdata,const char * addr,int af)688 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
689 
690 	int i = confdata->nsnext;
691 
692 	if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
693 		return (ISC_R_FAILURE);
694 
695 	switch (af) {
696 	case AF_INET:
697 		confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
698 		confdata->nameservers[i].length = NS_INADDRSZ;
699 		break;
700 	case AF_INET6:
701 		confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
702 		confdata->nameservers[i].length = NS_IN6ADDRSZ;
703 		break;
704 	default:
705 		return (ISC_R_FAILURE);
706 	}
707 
708 	if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
709 		confdata->nsnext++;
710 		return (ISC_R_SUCCESS);
711 	}
712 	return (ISC_R_FAILURE);
713 }
714 
715 /*%
716  * Produce a cloned server list.  The dest list must have already had
717  * ISC_LIST_INIT applied.
718  */
719 void
clone_server_list(dig_serverlist_t src,dig_serverlist_t * dest)720 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
721 	dig_server_t *srv, *newsrv;
722 
723 	debug("clone_server_list()");
724 	srv = ISC_LIST_HEAD(src);
725 	while (srv != NULL) {
726 		newsrv = make_server(srv->servername, srv->userarg);
727 		ISC_LINK_INIT(newsrv, link);
728 		ISC_LIST_ENQUEUE(*dest, newsrv, link);
729 		srv = ISC_LIST_NEXT(srv, link);
730 	}
731 }
732 
733 /*%
734  * Create an empty lookup structure, which holds all the information needed
735  * to get an answer to a user's question.  This structure contains two
736  * linked lists: the server list (servers to query) and the query list
737  * (outstanding queries which have been made to the listed servers).
738  */
739 dig_lookup_t *
make_empty_lookup(void)740 make_empty_lookup(void) {
741 	dig_lookup_t *looknew;
742 
743 	debug("make_empty_lookup()");
744 
745 	INSIST(!free_now);
746 
747 	looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
748 	if (looknew == NULL)
749 		fatal("memory allocation failure in %s:%d",
750 		       __FILE__, __LINE__);
751 	looknew->pending = ISC_TRUE;
752 	looknew->textname[0] = 0;
753 	looknew->cmdline[0] = 0;
754 	looknew->rdtype = dns_rdatatype_a;
755 	looknew->qrdtype = dns_rdatatype_a;
756 	looknew->rdclass = dns_rdataclass_in;
757 	looknew->rdtypeset = ISC_FALSE;
758 	looknew->rdclassset = ISC_FALSE;
759 	looknew->sendspace = NULL;
760 	looknew->sendmsg = NULL;
761 	looknew->name = NULL;
762 	looknew->oname = NULL;
763 	looknew->timer = NULL;
764 	looknew->xfr_q = NULL;
765 	looknew->current_query = NULL;
766 	looknew->doing_xfr = ISC_FALSE;
767 	looknew->ixfr_serial = 0;
768 	looknew->trace = ISC_FALSE;
769 	looknew->trace_root = ISC_FALSE;
770 	looknew->identify = ISC_FALSE;
771 	looknew->identify_previous_line = ISC_FALSE;
772 	looknew->ignore = ISC_FALSE;
773 	looknew->servfail_stops = ISC_TRUE;
774 	looknew->besteffort = ISC_TRUE;
775 	looknew->dnssec = ISC_FALSE;
776 	looknew->nsid = ISC_FALSE;
777 #ifdef DIG_SIGCHASE
778 	looknew->sigchase = ISC_FALSE;
779 #if DIG_SIGCHASE_TD
780 	looknew->do_topdown = ISC_FALSE;
781 	looknew->trace_root_sigchase = ISC_FALSE;
782 	looknew->rdtype_sigchaseset = ISC_FALSE;
783 	looknew->rdtype_sigchase = dns_rdatatype_any;
784 	looknew->qrdtype_sigchase = dns_rdatatype_any;
785 	looknew->rdclass_sigchase = dns_rdataclass_in;
786 	looknew->rdclass_sigchaseset = ISC_FALSE;
787 #endif
788 #endif
789 	looknew->udpsize = 0;
790 	looknew->edns = -1;
791 	looknew->recurse = ISC_TRUE;
792 	looknew->aaonly = ISC_FALSE;
793 	looknew->adflag = ISC_FALSE;
794 	looknew->cdflag = ISC_FALSE;
795 	looknew->ns_search_only = ISC_FALSE;
796 	looknew->origin = NULL;
797 	looknew->tsigctx = NULL;
798 	looknew->querysig = NULL;
799 	looknew->retries = tries;
800 	looknew->nsfound = 0;
801 	looknew->tcp_mode = ISC_FALSE;
802 	looknew->tcp_mode_set = ISC_FALSE;
803 	looknew->ip6_int = ISC_FALSE;
804 	looknew->comments = ISC_TRUE;
805 	looknew->stats = ISC_TRUE;
806 	looknew->section_question = ISC_TRUE;
807 	looknew->section_answer = ISC_TRUE;
808 	looknew->section_authority = ISC_TRUE;
809 	looknew->section_additional = ISC_TRUE;
810 	looknew->new_search = ISC_FALSE;
811 	looknew->done_as_is = ISC_FALSE;
812 	looknew->need_search = ISC_FALSE;
813 	dns_fixedname_init(&looknew->fdomain);
814 	ISC_LINK_INIT(looknew, link);
815 	ISC_LIST_INIT(looknew->q);
816 	ISC_LIST_INIT(looknew->connecting);
817 	ISC_LIST_INIT(looknew->my_server_list);
818 	return (looknew);
819 }
820 
821 /*%
822  * Clone a lookup, perhaps copying the server list.  This does not clone
823  * the query list, since it will be regenerated by the setup_lookup()
824  * function, nor does it queue up the new lookup for processing.
825  * Caution: If you don't clone the servers, you MUST clone the server
826  * list separately from somewhere else, or construct it by hand.
827  */
828 dig_lookup_t *
clone_lookup(dig_lookup_t * lookold,isc_boolean_t servers)829 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
830 	dig_lookup_t *looknew;
831 
832 	debug("clone_lookup()");
833 
834 	INSIST(!free_now);
835 
836 	looknew = make_empty_lookup();
837 	INSIST(looknew != NULL);
838 	strlcpy(looknew->textname, lookold->textname, MXNAME);
839 #if DIG_SIGCHASE_TD
840 	strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
841 #endif
842 	strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
843 	looknew->textname[MXNAME-1] = 0;
844 	looknew->rdtype = lookold->rdtype;
845 	looknew->qrdtype = lookold->qrdtype;
846 	looknew->rdclass = lookold->rdclass;
847 	looknew->rdtypeset = lookold->rdtypeset;
848 	looknew->rdclassset = lookold->rdclassset;
849 	looknew->doing_xfr = lookold->doing_xfr;
850 	looknew->ixfr_serial = lookold->ixfr_serial;
851 	looknew->trace = lookold->trace;
852 	looknew->trace_root = lookold->trace_root;
853 	looknew->identify = lookold->identify;
854 	looknew->identify_previous_line = lookold->identify_previous_line;
855 	looknew->ignore = lookold->ignore;
856 	looknew->servfail_stops = lookold->servfail_stops;
857 	looknew->besteffort = lookold->besteffort;
858 	looknew->dnssec = lookold->dnssec;
859 	looknew->nsid = lookold->nsid;
860 #ifdef DIG_SIGCHASE
861 	looknew->sigchase = lookold->sigchase;
862 #if DIG_SIGCHASE_TD
863 	looknew->do_topdown = lookold->do_topdown;
864 	looknew->trace_root_sigchase = lookold->trace_root_sigchase;
865 	looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
866 	looknew->rdtype_sigchase = lookold->rdtype_sigchase;
867 	looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
868 	looknew->rdclass_sigchase = lookold->rdclass_sigchase;
869 	looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
870 #endif
871 #endif
872 	looknew->udpsize = lookold->udpsize;
873 	looknew->edns = lookold->edns;
874 	looknew->recurse = lookold->recurse;
875 	looknew->aaonly = lookold->aaonly;
876 	looknew->adflag = lookold->adflag;
877 	looknew->cdflag = lookold->cdflag;
878 	looknew->ns_search_only = lookold->ns_search_only;
879 	looknew->tcp_mode = lookold->tcp_mode;
880 	looknew->tcp_mode_set = lookold->tcp_mode_set;
881 	looknew->comments = lookold->comments;
882 	looknew->stats = lookold->stats;
883 	looknew->section_question = lookold->section_question;
884 	looknew->section_answer = lookold->section_answer;
885 	looknew->section_authority = lookold->section_authority;
886 	looknew->section_additional = lookold->section_additional;
887 	looknew->retries = lookold->retries;
888 	looknew->tsigctx = NULL;
889 	looknew->need_search = lookold->need_search;
890 	looknew->done_as_is = lookold->done_as_is;
891 
892 	dns_name_copy(dns_fixedname_name(&lookold->fdomain),
893 		      dns_fixedname_name(&looknew->fdomain), NULL);
894 
895 	if (servers)
896 		clone_server_list(lookold->my_server_list,
897 				  &looknew->my_server_list);
898 	return (looknew);
899 }
900 
901 /*%
902  * Requeue a lookup for further processing, perhaps copying the server
903  * list.  The new lookup structure is returned to the caller, and is
904  * queued for processing.  If servers are not cloned in the requeue, they
905  * must be added before allowing the current event to complete, since the
906  * completion of the event may result in the next entry on the lookup
907  * queue getting run.
908  */
909 dig_lookup_t *
requeue_lookup(dig_lookup_t * lookold,isc_boolean_t servers)910 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
911 	dig_lookup_t *looknew;
912 
913 	debug("requeue_lookup()");
914 
915 	lookup_counter++;
916 	if (lookup_counter > LOOKUP_LIMIT)
917 		fatal("too many lookups");
918 
919 	looknew = clone_lookup(lookold, servers);
920 	INSIST(looknew != NULL);
921 
922 	debug("before insertion, init@%p -> %p, new@%p -> %p",
923 	      lookold, lookold->link.next, looknew, looknew->link.next);
924 	ISC_LIST_PREPEND(lookup_list, looknew, link);
925 	debug("after insertion, init -> %p, new = %p, new -> %p",
926 	      lookold, looknew, looknew->link.next);
927 	return (looknew);
928 }
929 
930 
931 static void
setup_text_key(void)932 setup_text_key(void) {
933 	isc_result_t result;
934 	dns_name_t keyname;
935 	isc_buffer_t secretbuf;
936 	int secretsize;
937 	unsigned char *secretstore;
938 
939 	debug("setup_text_key()");
940 	result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
941 	check_result(result, "isc_buffer_allocate");
942 	dns_name_init(&keyname, NULL);
943 	check_result(result, "dns_name_init");
944 	isc_buffer_putstr(namebuf, keynametext);
945 	secretsize = strlen(keysecret) * 3 / 4;
946 	secretstore = isc_mem_allocate(mctx, secretsize);
947 	if (secretstore == NULL)
948 		fatal("memory allocation failure in %s:%d",
949 		      __FILE__, __LINE__);
950 	isc_buffer_init(&secretbuf, secretstore, secretsize);
951 	result = isc_base64_decodestring(keysecret, &secretbuf);
952 	if (result != ISC_R_SUCCESS)
953 		goto failure;
954 
955 	secretsize = isc_buffer_usedlength(&secretbuf);
956 
957 	if (hmacname == NULL) {
958 		result = DST_R_UNSUPPORTEDALG;
959 		goto failure;
960 	}
961 
962 	result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
963 	if (result != ISC_R_SUCCESS)
964 		goto failure;
965 
966 	result = dns_tsigkey_create(&keyname, hmacname, secretstore,
967 				    secretsize, ISC_FALSE, NULL, 0, 0, mctx,
968 				    NULL, &key);
969  failure:
970 	if (result != ISC_R_SUCCESS)
971 		printf(";; Couldn't create key %s: %s\n",
972 		       keynametext, isc_result_totext(result));
973 	else
974 		dst_key_setbits(key->key, digestbits);
975 
976 	isc_mem_free(mctx, secretstore);
977 	dns_name_invalidate(&keyname);
978 	isc_buffer_free(&namebuf);
979 }
980 
981 isc_result_t
parse_uint(isc_uint32_t * uip,const char * value,isc_uint32_t max,const char * desc)982 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
983 	   const char *desc) {
984 	isc_uint32_t n;
985 	isc_result_t result = isc_parse_uint32(&n, value, 10);
986 	if (result == ISC_R_SUCCESS && n > max)
987 		result = ISC_R_RANGE;
988 	if (result != ISC_R_SUCCESS) {
989 		printf("invalid %s '%s': %s\n", desc,
990 		       value, isc_result_totext(result));
991 		return (result);
992 	}
993 	*uip = n;
994 	return (ISC_R_SUCCESS);
995 }
996 
997 static isc_uint32_t
parse_bits(char * arg,const char * desc,isc_uint32_t max)998 parse_bits(char *arg, const char *desc, isc_uint32_t max) {
999 	isc_result_t result;
1000 	isc_uint32_t tmp;
1001 
1002 	result = parse_uint(&tmp, arg, max, desc);
1003 	if (result != ISC_R_SUCCESS)
1004 		fatal("couldn't parse digest bits");
1005 	tmp = (tmp + 7) & ~0x7U;
1006 	return (tmp);
1007 }
1008 
1009 /*
1010  * Parse HMAC algorithm specification
1011  */
1012 void
parse_hmac(const char * hmac)1013 parse_hmac(const char *hmac) {
1014 	char buf[20];
1015 	int len;
1016 
1017 	REQUIRE(hmac != NULL);
1018 
1019 	len = strlen(hmac);
1020 	if (len >= (int) sizeof(buf))
1021 		fatal("unknown key type '%.*s'", len, hmac);
1022 	strlcpy(buf, hmac, sizeof(buf));
1023 
1024 	digestbits = 0;
1025 
1026 	if (strcasecmp(buf, "hmac-md5") == 0) {
1027 		hmacname = DNS_TSIG_HMACMD5_NAME;
1028 	} else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
1029 		hmacname = DNS_TSIG_HMACMD5_NAME;
1030 		digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
1031 	} else if (strcasecmp(buf, "hmac-sha1") == 0) {
1032 		hmacname = DNS_TSIG_HMACSHA1_NAME;
1033 		digestbits = 0;
1034 	} else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1035 		hmacname = DNS_TSIG_HMACSHA1_NAME;
1036 		digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1037 	} else if (strcasecmp(buf, "hmac-sha224") == 0) {
1038 		hmacname = DNS_TSIG_HMACSHA224_NAME;
1039 	} else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1040 		hmacname = DNS_TSIG_HMACSHA224_NAME;
1041 		digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1042 	} else if (strcasecmp(buf, "hmac-sha256") == 0) {
1043 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1044 	} else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1045 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1046 		digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1047 	} else if (strcasecmp(buf, "hmac-sha384") == 0) {
1048 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1049 	} else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1050 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1051 		digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1052 	} else if (strcasecmp(buf, "hmac-sha512") == 0) {
1053 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1054 	} else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1055 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1056 		digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1057 	} else {
1058 		fprintf(stderr, ";; Warning, ignoring "
1059 			"invalid TSIG algorithm %s\n", buf);
1060 	}
1061 }
1062 
1063 /*
1064  * Get a key from a named.conf format keyfile
1065  */
1066 static isc_result_t
read_confkey(void)1067 read_confkey(void) {
1068 	cfg_parser_t *pctx = NULL;
1069 	cfg_obj_t *file = NULL;
1070 	const cfg_obj_t *keyobj = NULL;
1071 	const cfg_obj_t *secretobj = NULL;
1072 	const cfg_obj_t *algorithmobj = NULL;
1073 	const char *keyname;
1074 	const char *secretstr;
1075 	const char *algorithm;
1076 	isc_result_t result;
1077 
1078 	if (! isc_file_exists(keyfile))
1079 		return (ISC_R_FILENOTFOUND);
1080 
1081 	result = cfg_parser_create(mctx, NULL, &pctx);
1082 	if (result != ISC_R_SUCCESS)
1083 		goto cleanup;
1084 
1085 	result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1086 				&file);
1087 	if (result != ISC_R_SUCCESS)
1088 		goto cleanup;
1089 
1090 	result = cfg_map_get(file, "key", &keyobj);
1091 	if (result != ISC_R_SUCCESS)
1092 		goto cleanup;
1093 
1094 	(void) cfg_map_get(keyobj, "secret", &secretobj);
1095 	(void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
1096 	if (secretobj == NULL || algorithmobj == NULL)
1097 		fatal("key must have algorithm and secret");
1098 
1099 	keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
1100 	secretstr = cfg_obj_asstring(secretobj);
1101 	algorithm = cfg_obj_asstring(algorithmobj);
1102 
1103 	strlcpy(keynametext, keyname, sizeof(keynametext));
1104 	strlcpy(keysecret, secretstr, sizeof(keysecret));
1105 	parse_hmac(algorithm);
1106 	setup_text_key();
1107 
1108  cleanup:
1109 	if (pctx != NULL) {
1110 		if (file != NULL)
1111 			cfg_obj_destroy(pctx, &file);
1112 		cfg_parser_destroy(&pctx);
1113 	}
1114 
1115 	return (result);
1116 }
1117 
1118 static void
setup_file_key(void)1119 setup_file_key(void) {
1120 	isc_result_t result;
1121 	dst_key_t *dstkey = NULL;
1122 
1123 	debug("setup_file_key()");
1124 
1125 	/* Try reading the key from a K* pair */
1126 	result = dst_key_fromnamedfile(keyfile, NULL,
1127 				       DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
1128 				       &dstkey);
1129 
1130 	/* If that didn't work, try reading it as a session.key keyfile */
1131 	if (result != ISC_R_SUCCESS) {
1132 		result = read_confkey();
1133 		if (result == ISC_R_SUCCESS)
1134 			return;
1135 	}
1136 
1137 	if (result != ISC_R_SUCCESS) {
1138 		fprintf(stderr, "Couldn't read key from %s: %s\n",
1139 			keyfile, isc_result_totext(result));
1140 		goto failure;
1141 	}
1142 
1143 	switch (dst_key_alg(dstkey)) {
1144 	case DST_ALG_HMACMD5:
1145 		hmacname = DNS_TSIG_HMACMD5_NAME;
1146 		break;
1147 	case DST_ALG_HMACSHA1:
1148 		hmacname = DNS_TSIG_HMACSHA1_NAME;
1149 		break;
1150 	case DST_ALG_HMACSHA224:
1151 		hmacname = DNS_TSIG_HMACSHA224_NAME;
1152 		break;
1153 	case DST_ALG_HMACSHA256:
1154 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1155 		break;
1156 	case DST_ALG_HMACSHA384:
1157 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1158 		break;
1159 	case DST_ALG_HMACSHA512:
1160 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1161 		break;
1162 	default:
1163 		printf(";; Couldn't create key %s: bad algorithm\n",
1164 		       keynametext);
1165 		goto failure;
1166 	}
1167 	result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1168 					   dstkey, ISC_FALSE, NULL, 0, 0,
1169 					   mctx, NULL, &key);
1170 	if (result != ISC_R_SUCCESS) {
1171 		printf(";; Couldn't create key %s: %s\n",
1172 		       keynametext, isc_result_totext(result));
1173 		goto failure;
1174 	}
1175  failure:
1176 	if (dstkey != NULL)
1177 		dst_key_free(&dstkey);
1178 }
1179 
1180 static dig_searchlist_t *
make_searchlist_entry(char * domain)1181 make_searchlist_entry(char *domain) {
1182 	dig_searchlist_t *search;
1183 	search = isc_mem_allocate(mctx, sizeof(*search));
1184 	if (search == NULL)
1185 		fatal("memory allocation failure in %s:%d",
1186 		      __FILE__, __LINE__);
1187 	strlcpy(search->origin, domain, MXNAME);
1188 	search->origin[MXNAME-1] = 0;
1189 	ISC_LINK_INIT(search, link);
1190 	return (search);
1191 }
1192 
1193 static void
clear_searchlist(void)1194 clear_searchlist(void) {
1195 	dig_searchlist_t *search;
1196 	while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1197 		ISC_LIST_UNLINK(search_list, search, link);
1198 		isc_mem_free(mctx, search);
1199 	}
1200 }
1201 
1202 static void
create_search_list(lwres_conf_t * confdata)1203 create_search_list(lwres_conf_t *confdata) {
1204 	int i;
1205 	dig_searchlist_t *search;
1206 
1207 	debug("create_search_list()");
1208 	clear_searchlist();
1209 
1210 	for (i = 0; i < confdata->searchnxt; i++) {
1211 		search = make_searchlist_entry(confdata->search[i]);
1212 		ISC_LIST_APPEND(search_list, search, link);
1213 	}
1214 }
1215 
1216 /*%
1217  * Setup the system as a whole, reading key information and resolv.conf
1218  * settings.
1219  */
1220 void
setup_system(void)1221 setup_system(void) {
1222 	dig_searchlist_t *domain = NULL;
1223 	lwres_result_t lwresult;
1224 	unsigned int lwresflags;
1225 
1226 	debug("setup_system()");
1227 
1228 	lwresflags = LWRES_CONTEXT_SERVERMODE;
1229 	if (have_ipv4)
1230 		lwresflags |= LWRES_CONTEXT_USEIPV4;
1231 	if (have_ipv6)
1232 		lwresflags |= LWRES_CONTEXT_USEIPV6;
1233 
1234 	lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
1235 					lwresflags);
1236 	if (lwresult != LWRES_R_SUCCESS)
1237 		fatal("lwres_context_create failed");
1238 
1239 	lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
1240 	if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1241 		fatal("parse of %s failed", RESOLV_CONF);
1242 
1243 	lwconf = lwres_conf_get(lwctx);
1244 
1245 	/* Make the search list */
1246 	if (lwconf->searchnxt > 0)
1247 		create_search_list(lwconf);
1248 	else { /* No search list. Use the domain name if any */
1249 		if (lwconf->domainname != NULL) {
1250 			domain = make_searchlist_entry(lwconf->domainname);
1251 			ISC_LIST_APPEND(search_list, domain, link);
1252 			domain  = NULL;
1253 		}
1254 	}
1255 
1256 	if (ndots == -1) {
1257 		ndots = lwconf->ndots;
1258 		debug("ndots is %d.", ndots);
1259 	}
1260 
1261 	/* If user doesn't specify server use nameservers from resolv.conf. */
1262 	if (ISC_LIST_EMPTY(server_list))
1263 		copy_server_list(lwconf, &server_list);
1264 
1265 	/* If we don't find a nameserver fall back to localhost */
1266 	if (ISC_LIST_EMPTY(server_list)) {
1267 		if (have_ipv4) {
1268 			lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1269 			if (lwresult != ISC_R_SUCCESS)
1270 				fatal("add_nameserver failed");
1271 		}
1272 		if (have_ipv6) {
1273 			lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1274 			if (lwresult != ISC_R_SUCCESS)
1275 				fatal("add_nameserver failed");
1276 		}
1277 
1278 		copy_server_list(lwconf, &server_list);
1279 	}
1280 
1281 #ifdef WITH_IDN
1282 	initialize_idn();
1283 #endif
1284 
1285 	if (keyfile[0] != 0)
1286 		setup_file_key();
1287 	else if (keysecret[0] != 0)
1288 		setup_text_key();
1289 #ifdef DIG_SIGCHASE
1290 	/* Setup the list of messages for +sigchase */
1291 	ISC_LIST_INIT(chase_message_list);
1292 	ISC_LIST_INIT(chase_message_list2);
1293 	dns_name_init(&chase_name, NULL);
1294 #if DIG_SIGCHASE_TD
1295 	dns_name_init(&chase_current_name, NULL);
1296 	dns_name_init(&chase_authority_name, NULL);
1297 #endif
1298 #if DIG_SIGCHASE_BU
1299 	dns_name_init(&chase_signame, NULL);
1300 #endif
1301 
1302 #endif
1303 
1304 }
1305 
1306 /*%
1307  * Override the search list derived from resolv.conf by 'domain'.
1308  */
1309 void
set_search_domain(char * domain)1310 set_search_domain(char *domain) {
1311 	dig_searchlist_t *search;
1312 
1313 	clear_searchlist();
1314 	search = make_searchlist_entry(domain);
1315 	ISC_LIST_APPEND(search_list, search, link);
1316 }
1317 
1318 /*%
1319  * Setup the ISC and DNS libraries for use by the system.
1320  */
1321 void
setup_libs(void)1322 setup_libs(void) {
1323 	isc_result_t result;
1324 	isc_logconfig_t *logconfig = NULL;
1325 
1326 	debug("setup_libs()");
1327 
1328 	result = isc_net_probeipv4();
1329 	if (result == ISC_R_SUCCESS)
1330 		have_ipv4 = ISC_TRUE;
1331 
1332 	result = isc_net_probeipv6();
1333 	if (result == ISC_R_SUCCESS)
1334 		have_ipv6 = ISC_TRUE;
1335 	if (!have_ipv6 && !have_ipv4)
1336 		fatal("can't find either v4 or v6 networking");
1337 
1338 	result = isc_mem_create(0, 0, &mctx);
1339 	check_result(result, "isc_mem_create");
1340 	isc_mem_setname(mctx, "dig", NULL);
1341 
1342 	result = isc_log_create(mctx, &lctx, &logconfig);
1343 	check_result(result, "isc_log_create");
1344 
1345 	isc_log_setcontext(lctx);
1346 	dns_log_init(lctx);
1347 	dns_log_setcontext(lctx);
1348 
1349 	result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1350 	check_result(result, "isc_log_usechannel");
1351 
1352 	isc_log_setdebuglevel(lctx, 0);
1353 
1354 	result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1355 	check_result(result, "isc_taskmgr_create");
1356 
1357 	result = isc_task_create(taskmgr, 0, &global_task);
1358 	check_result(result, "isc_task_create");
1359 	isc_task_setname(global_task, "dig", NULL);
1360 
1361 	result = isc_timermgr_create(mctx, &timermgr);
1362 	check_result(result, "isc_timermgr_create");
1363 
1364 	result = isc_socketmgr_create(mctx, &socketmgr);
1365 	check_result(result, "isc_socketmgr_create");
1366 
1367 	result = isc_entropy_create(mctx, &entp);
1368 	check_result(result, "isc_entropy_create");
1369 
1370 	result = dst_lib_init(mctx, entp, 0);
1371 	check_result(result, "dst_lib_init");
1372 	is_dst_up = ISC_TRUE;
1373 
1374 	result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1375 	check_result(result, "isc_mempool_create");
1376 	isc_mempool_setname(commctx, "COMMPOOL");
1377 	/*
1378 	 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1379 	 * systems.
1380 	 */
1381 	isc_mempool_setfreemax(commctx, 6);
1382 	isc_mempool_setfillcount(commctx, 2);
1383 
1384 	result = isc_mutex_init(&lookup_lock);
1385 	check_result(result, "isc_mutex_init");
1386 
1387 	dns_result_register();
1388 }
1389 
1390 /*%
1391  * Add EDNS0 option record to a message.  Currently, the only supported
1392  * options are UDP buffer size, the DO bit, and NSID request.
1393  */
1394 static void
add_opt(dns_message_t * msg,isc_uint16_t udpsize,isc_uint16_t edns,isc_boolean_t dnssec,isc_boolean_t nsid)1395 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
1396 	isc_boolean_t dnssec, isc_boolean_t nsid)
1397 {
1398 	dns_rdataset_t *rdataset = NULL;
1399 	dns_rdatalist_t *rdatalist = NULL;
1400 	dns_rdata_t *rdata = NULL;
1401 	isc_result_t result;
1402 
1403 	debug("add_opt()");
1404 	result = dns_message_gettemprdataset(msg, &rdataset);
1405 	check_result(result, "dns_message_gettemprdataset");
1406 	dns_rdataset_init(rdataset);
1407 	result = dns_message_gettemprdatalist(msg, &rdatalist);
1408 	check_result(result, "dns_message_gettemprdatalist");
1409 	result = dns_message_gettemprdata(msg, &rdata);
1410 	check_result(result, "dns_message_gettemprdata");
1411 
1412 	debug("setting udp size of %d", udpsize);
1413 	rdatalist->type = dns_rdatatype_opt;
1414 	rdatalist->covers = 0;
1415 	rdatalist->rdclass = udpsize;
1416 	rdatalist->ttl = edns << 16;
1417 	if (dnssec)
1418 		rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1419 	if (nsid) {
1420 		isc_buffer_t *b = NULL;
1421 
1422 		result = isc_buffer_allocate(mctx, &b, 4);
1423 		check_result(result, "isc_buffer_allocate");
1424 		isc_buffer_putuint16(b, DNS_OPT_NSID);
1425 		isc_buffer_putuint16(b, 0);
1426 		rdata->data = isc_buffer_base(b);
1427 		rdata->length = isc_buffer_usedlength(b);
1428 		dns_message_takebuffer(msg, &b);
1429 	} else {
1430 		rdata->data = NULL;
1431 		rdata->length = 0;
1432 	}
1433 	ISC_LIST_INIT(rdatalist->rdata);
1434 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1435 	dns_rdatalist_tordataset(rdatalist, rdataset);
1436 	result = dns_message_setopt(msg, rdataset);
1437 	check_result(result, "dns_message_setopt");
1438 }
1439 
1440 /*%
1441  * Add a question section to a message, asking for the specified name,
1442  * type, and class.
1443  */
1444 static void
add_question(dns_message_t * message,dns_name_t * name,dns_rdataclass_t rdclass,dns_rdatatype_t rdtype)1445 add_question(dns_message_t *message, dns_name_t *name,
1446 	     dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1447 {
1448 	dns_rdataset_t *rdataset;
1449 	isc_result_t result;
1450 
1451 	debug("add_question()");
1452 	rdataset = NULL;
1453 	result = dns_message_gettemprdataset(message, &rdataset);
1454 	check_result(result, "dns_message_gettemprdataset()");
1455 	dns_rdataset_init(rdataset);
1456 	dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1457 	ISC_LIST_APPEND(name->list, rdataset, link);
1458 }
1459 
1460 /*%
1461  * Check if we're done with all the queued lookups, which is true iff
1462  * all sockets, sends, and recvs are accounted for (counters == 0),
1463  * and the lookup list is empty.
1464  * If we are done, pass control back out to dighost_shutdown() (which is
1465  * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1466  * a whole or reseed the lookup list.
1467  */
1468 static void
check_if_done(void)1469 check_if_done(void) {
1470 	debug("check_if_done()");
1471 	debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1472 	if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1473 	    sendcount == 0) {
1474 		INSIST(sockcount == 0);
1475 		INSIST(recvcount == 0);
1476 		debug("shutting down");
1477 		dighost_shutdown();
1478 	}
1479 }
1480 
1481 /*%
1482  * Clear out a query when we're done with it.  WARNING: This routine
1483  * WILL invalidate the query pointer.
1484  */
1485 static void
clear_query(dig_query_t * query)1486 clear_query(dig_query_t *query) {
1487 	dig_lookup_t *lookup;
1488 
1489 	REQUIRE(query != NULL);
1490 
1491 	debug("clear_query(%p)", query);
1492 
1493 	lookup = query->lookup;
1494 
1495 	if (lookup->current_query == query)
1496 		lookup->current_query = NULL;
1497 
1498 	if (ISC_LINK_LINKED(query, link))
1499 		ISC_LIST_UNLINK(lookup->q, query, link);
1500 	if (ISC_LINK_LINKED(query, clink))
1501 		ISC_LIST_UNLINK(lookup->connecting, query, clink);
1502 	if (ISC_LINK_LINKED(&query->recvbuf, link))
1503 		ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1504 				 link);
1505 	if (ISC_LINK_LINKED(&query->lengthbuf, link))
1506 		ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1507 				 link);
1508 	INSIST(query->recvspace != NULL);
1509 
1510 	if (query->sock != NULL) {
1511 		isc_socket_detach(&query->sock);
1512 		sockcount--;
1513 		debug("sockcount=%d", sockcount);
1514 	}
1515 	isc_mempool_put(commctx, query->recvspace);
1516 	isc_buffer_invalidate(&query->recvbuf);
1517 	isc_buffer_invalidate(&query->lengthbuf);
1518 	if (query->waiting_senddone)
1519 		query->pending_free = ISC_TRUE;
1520 	else
1521 		isc_mem_free(mctx, query);
1522 }
1523 
1524 /*%
1525  * Try and clear out a lookup if we're done with it.  Return ISC_TRUE if
1526  * the lookup was successfully cleared.  If ISC_TRUE is returned, the
1527  * lookup pointer has been invalidated.
1528  */
1529 static isc_boolean_t
try_clear_lookup(dig_lookup_t * lookup)1530 try_clear_lookup(dig_lookup_t *lookup) {
1531 	dig_query_t *q;
1532 
1533 	REQUIRE(lookup != NULL);
1534 
1535 	debug("try_clear_lookup(%p)", lookup);
1536 
1537 	if (ISC_LIST_HEAD(lookup->q) != NULL ||
1538 	    ISC_LIST_HEAD(lookup->connecting) != NULL)
1539 	{
1540 		if (debugging) {
1541 			q = ISC_LIST_HEAD(lookup->q);
1542 			while (q != NULL) {
1543 				debug("query to %s still pending", q->servname);
1544 				q = ISC_LIST_NEXT(q, link);
1545 			}
1546 
1547 			q = ISC_LIST_HEAD(lookup->connecting);
1548 			while (q != NULL) {
1549 				debug("query to %s still connecting",
1550 				      q->servname);
1551 				q = ISC_LIST_NEXT(q, clink);
1552 			}
1553 		}
1554 		return (ISC_FALSE);
1555 	}
1556 
1557 	/*
1558 	 * At this point, we know there are no queries on the lookup,
1559 	 * so can make it go away also.
1560 	 */
1561 	destroy_lookup(lookup);
1562 	return (ISC_TRUE);
1563 }
1564 
1565 void
destroy_lookup(dig_lookup_t * lookup)1566 destroy_lookup(dig_lookup_t *lookup) {
1567 	dig_server_t *s;
1568 	void *ptr;
1569 
1570 	debug("destroy");
1571 	s = ISC_LIST_HEAD(lookup->my_server_list);
1572 	while (s != NULL) {
1573 		debug("freeing server %p belonging to %p", s, lookup);
1574 		ptr = s;
1575 		s = ISC_LIST_NEXT(s, link);
1576 		ISC_LIST_DEQUEUE(lookup->my_server_list,
1577 				 (dig_server_t *)ptr, link);
1578 		isc_mem_free(mctx, ptr);
1579 	}
1580 	if (lookup->sendmsg != NULL)
1581 		dns_message_destroy(&lookup->sendmsg);
1582 	if (lookup->querysig != NULL) {
1583 		debug("freeing buffer %p", lookup->querysig);
1584 		isc_buffer_free(&lookup->querysig);
1585 	}
1586 	if (lookup->timer != NULL)
1587 		isc_timer_detach(&lookup->timer);
1588 	if (lookup->sendspace != NULL)
1589 		isc_mempool_put(commctx, lookup->sendspace);
1590 
1591 	if (lookup->tsigctx != NULL)
1592 		dst_context_destroy(&lookup->tsigctx);
1593 
1594 	isc_mem_free(mctx, lookup);
1595 }
1596 
1597 /*%
1598  * If we can, start the next lookup in the queue running.
1599  * This assumes that the lookup on the head of the queue hasn't been
1600  * started yet.  It also removes the lookup from the head of the queue,
1601  * setting the current_lookup pointer pointing to it.
1602  */
1603 void
start_lookup(void)1604 start_lookup(void) {
1605 	debug("start_lookup()");
1606 	if (cancel_now)
1607 		return;
1608 
1609 	/*
1610 	 * If there's a current lookup running, we really shouldn't get
1611 	 * here.
1612 	 */
1613 	INSIST(current_lookup == NULL);
1614 
1615 	current_lookup = ISC_LIST_HEAD(lookup_list);
1616 	/*
1617 	 * Put the current lookup somewhere so cancel_all can find it
1618 	 */
1619 	if (current_lookup != NULL) {
1620 		ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1621 #if DIG_SIGCHASE_TD
1622 		if (current_lookup->do_topdown &&
1623 		    !current_lookup->rdtype_sigchaseset) {
1624 			dst_key_t *dstkey = NULL;
1625 			isc_buffer_t *b = NULL;
1626 			isc_region_t r;
1627 			isc_result_t result;
1628 			dns_name_t query_name;
1629 			dns_name_t *key_name;
1630 			int i;
1631 
1632 			result = get_trusted_key();
1633 			if (result != ISC_R_SUCCESS) {
1634 				printf("\n;; No trusted key, "
1635 				       "+sigchase option is disabled\n");
1636 				current_lookup->sigchase = ISC_FALSE;
1637 				goto novalidation;
1638 			}
1639 			dns_name_init(&query_name, NULL);
1640 			nameFromString(current_lookup->textname, &query_name);
1641 
1642 			for (i = 0; i < tk_list.nb_tk; i++) {
1643 				key_name = dst_key_name(tk_list.key[i]);
1644 
1645 				if (dns_name_issubdomain(&query_name,
1646 							 key_name) == ISC_TRUE)
1647 					dstkey = tk_list.key[i];
1648 				/*
1649 				 * Verify temp is really the lowest
1650 				 * WARNING
1651 				 */
1652 			}
1653 			if (dstkey == NULL) {
1654 				printf("\n;; The queried zone: ");
1655 				dns_name_print(&query_name, stdout);
1656 				printf(" isn't a subdomain of any Trusted Keys"
1657 				       ": +sigchase option is disable\n");
1658 				current_lookup->sigchase = ISC_FALSE;
1659 				free_name(&query_name);
1660 				goto novalidation;
1661 			}
1662 			free_name(&query_name);
1663 
1664 			current_lookup->rdtype_sigchase
1665 				= current_lookup->rdtype;
1666 			current_lookup->rdtype_sigchaseset
1667 				= current_lookup->rdtypeset;
1668 			current_lookup->rdtype = dns_rdatatype_ns;
1669 
1670 			current_lookup->qrdtype_sigchase
1671 				= current_lookup->qrdtype;
1672 			current_lookup->qrdtype = dns_rdatatype_ns;
1673 
1674 			current_lookup->rdclass_sigchase
1675 				= current_lookup->rdclass;
1676 			current_lookup->rdclass_sigchaseset
1677 				= current_lookup->rdclassset;
1678 			current_lookup->rdclass = dns_rdataclass_in;
1679 
1680 			strlcpy(current_lookup->textnamesigchase,
1681 				current_lookup->textname, MXNAME);
1682 
1683 			current_lookup->trace_root_sigchase = ISC_TRUE;
1684 
1685 			result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1686 			check_result(result, "isc_buffer_allocate");
1687 			result = dns_name_totext(dst_key_name(dstkey),
1688 						 ISC_FALSE, b);
1689 			check_result(result, "dns_name_totext");
1690 			isc_buffer_usedregion(b, &r);
1691 			r.base[r.length] = '\0';
1692 			strlcpy(current_lookup->textname, (char*)r.base,
1693 				MXNAME);
1694 			isc_buffer_free(&b);
1695 
1696 			nameFromString(current_lookup->textnamesigchase,
1697 				       &chase_name);
1698 
1699 			dns_name_init(&chase_authority_name, NULL);
1700 		}
1701 	novalidation:
1702 #endif
1703 		if (setup_lookup(current_lookup))
1704 			do_lookup(current_lookup);
1705 		else if (next_origin(current_lookup))
1706 			check_next_lookup(current_lookup);
1707 	} else {
1708 		check_if_done();
1709 	}
1710 }
1711 
1712 /*%
1713  * If we can, clear the current lookup and start the next one running.
1714  * This calls try_clear_lookup, so may invalidate the lookup pointer.
1715  */
1716 static void
check_next_lookup(dig_lookup_t * lookup)1717 check_next_lookup(dig_lookup_t *lookup) {
1718 
1719 	INSIST(!free_now);
1720 
1721 	debug("check_next_lookup(%p)", lookup);
1722 
1723 	if (ISC_LIST_HEAD(lookup->q) != NULL) {
1724 		debug("still have a worker");
1725 		return;
1726 	}
1727 	if (try_clear_lookup(lookup)) {
1728 		current_lookup = NULL;
1729 		start_lookup();
1730 	}
1731 }
1732 
1733 /*%
1734  * Create and queue a new lookup as a followup to the current lookup,
1735  * based on the supplied message and section.  This is used in trace and
1736  * name server search modes to start a new lookup using servers from
1737  * NS records in a reply. Returns the number of followup lookups made.
1738  */
1739 static int
followup_lookup(dns_message_t * msg,dig_query_t * query,dns_section_t section)1740 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1741 {
1742 	dig_lookup_t *lookup = NULL;
1743 	dig_server_t *srv = NULL;
1744 	dns_rdataset_t *rdataset = NULL;
1745 	dns_rdata_t rdata = DNS_RDATA_INIT;
1746 	dns_name_t *name = NULL;
1747 	isc_result_t result;
1748 	isc_boolean_t success = ISC_FALSE;
1749 	int numLookups = 0;
1750 	int num;
1751 	isc_result_t lresult, addresses_result;
1752 	char bad_namestr[DNS_NAME_FORMATSIZE];
1753 	dns_name_t *domain;
1754 	isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
1755 
1756 	INSIST(!free_now);
1757 
1758 	debug("following up %s", query->lookup->textname);
1759 
1760 	addresses_result = ISC_R_SUCCESS;
1761 	bad_namestr[0] = '\0';
1762 	for (result = dns_message_firstname(msg, section);
1763 	     result == ISC_R_SUCCESS;
1764 	     result = dns_message_nextname(msg, section)) {
1765 		name = NULL;
1766 		dns_message_currentname(msg, section, &name);
1767 
1768 		if (section == DNS_SECTION_AUTHORITY) {
1769 			rdataset = NULL;
1770 			result = dns_message_findtype(name, dns_rdatatype_soa,
1771 						      0, &rdataset);
1772 			if (result == ISC_R_SUCCESS)
1773 				return (0);
1774 		}
1775 		rdataset = NULL;
1776 		result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1777 					      &rdataset);
1778 		if (result != ISC_R_SUCCESS)
1779 			continue;
1780 
1781 		debug("found NS set");
1782 
1783 		if (query->lookup->trace && !query->lookup->trace_root) {
1784 			dns_namereln_t namereln;
1785 			unsigned int nlabels;
1786 			int order;
1787 
1788 			domain = dns_fixedname_name(&query->lookup->fdomain);
1789 			namereln = dns_name_fullcompare(name, domain,
1790 							&order, &nlabels);
1791 			if (namereln == dns_namereln_equal) {
1792 				if (!horizontal)
1793 					printf(";; BAD (HORIZONTAL) REFERRAL\n");
1794 				horizontal = ISC_TRUE;
1795 			} else if (namereln != dns_namereln_subdomain) {
1796 				if (!bad)
1797 					printf(";; BAD REFERRAL\n");
1798 				bad = ISC_TRUE;
1799 				continue;
1800 			}
1801 		}
1802 
1803 		for (result = dns_rdataset_first(rdataset);
1804 		     result == ISC_R_SUCCESS;
1805 		     result = dns_rdataset_next(rdataset)) {
1806 			char namestr[DNS_NAME_FORMATSIZE];
1807 			dns_rdata_ns_t ns;
1808 
1809 			if (query->lookup->trace_root &&
1810 			    query->lookup->nsfound >= MXSERV)
1811 				break;
1812 
1813 			dns_rdataset_current(rdataset, &rdata);
1814 
1815 			query->lookup->nsfound++;
1816 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
1817 			check_result(result, "dns_rdata_tostruct");
1818 			dns_name_format(&ns.name, namestr, sizeof(namestr));
1819 			dns_rdata_freestruct(&ns);
1820 
1821 			/* Initialize lookup if we've not yet */
1822 			debug("found NS %s", namestr);
1823 			if (!success) {
1824 				success = ISC_TRUE;
1825 				lookup_counter++;
1826 				lookup = requeue_lookup(query->lookup,
1827 							ISC_FALSE);
1828 				cancel_lookup(query->lookup);
1829 				lookup->doing_xfr = ISC_FALSE;
1830 				if (!lookup->trace_root &&
1831 				    section == DNS_SECTION_ANSWER)
1832 					lookup->trace = ISC_FALSE;
1833 				else
1834 					lookup->trace = query->lookup->trace;
1835 				lookup->ns_search_only =
1836 					query->lookup->ns_search_only;
1837 				lookup->trace_root = ISC_FALSE;
1838 				if (lookup->ns_search_only)
1839 					lookup->recurse = ISC_FALSE;
1840 				domain = dns_fixedname_name(&lookup->fdomain);
1841 				dns_name_copy(name, domain, NULL);
1842 			}
1843 			debug("adding server %s", namestr);
1844 			num = getaddresses(lookup, namestr, &lresult);
1845 			if (lresult != ISC_R_SUCCESS) {
1846 				debug("couldn't get address for '%s': %s",
1847 				      namestr, isc_result_totext(lresult));
1848 				if (addresses_result == ISC_R_SUCCESS) {
1849 					addresses_result = lresult;
1850 					strcpy(bad_namestr, namestr);
1851 				}
1852 			}
1853 			numLookups += num;
1854 			dns_rdata_reset(&rdata);
1855 		}
1856 	}
1857 	if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1858 		fatal("couldn't get address for '%s': %s",
1859 		      bad_namestr, isc_result_totext(result));
1860 	}
1861 
1862 	if (lookup == NULL &&
1863 	    section == DNS_SECTION_ANSWER &&
1864 	    (query->lookup->trace || query->lookup->ns_search_only))
1865 		return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1866 
1867 	/*
1868 	 * Randomize the order the nameserver will be tried.
1869 	 */
1870 	if (numLookups > 1) {
1871 		isc_uint32_t i, j;
1872 		dig_serverlist_t my_server_list;
1873 		dig_server_t *next;
1874 
1875 		ISC_LIST_INIT(my_server_list);
1876 
1877 		i = numLookups;
1878 		for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1879 		     srv != NULL;
1880 		     srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1881 			INSIST(i > 0);
1882 			isc_random_get(&j);
1883 			j %= i;
1884 			next = ISC_LIST_NEXT(srv, link);
1885 			while (j-- > 0 && next != NULL) {
1886 				srv = next;
1887 				next = ISC_LIST_NEXT(srv, link);
1888 			}
1889 			ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1890 			ISC_LIST_APPEND(my_server_list, srv, link);
1891 			i--;
1892 		}
1893 		ISC_LIST_APPENDLIST(lookup->my_server_list,
1894 				    my_server_list, link);
1895 	}
1896 
1897 	return (numLookups);
1898 }
1899 
1900 /*%
1901  * Create and queue a new lookup using the next origin from the search
1902  * list, read in setup_system().
1903  *
1904  * Return ISC_TRUE iff there was another searchlist entry.
1905  */
1906 static isc_boolean_t
next_origin(dig_lookup_t * oldlookup)1907 next_origin(dig_lookup_t *oldlookup) {
1908 	dig_lookup_t *newlookup;
1909 	dig_searchlist_t *search;
1910 	dns_fixedname_t fixed;
1911 	dns_name_t *name;
1912 	isc_result_t result;
1913 
1914 	INSIST(!free_now);
1915 
1916 	debug("next_origin()");
1917 	debug("following up %s", oldlookup->textname);
1918 
1919 	if (!usesearch)
1920 		/*
1921 		 * We're not using a search list, so don't even think
1922 		 * about finding the next entry.
1923 		 */
1924 		return (ISC_FALSE);
1925 
1926 	/*
1927 	 * Check for a absolute name or ndots being met.
1928 	 */
1929 	dns_fixedname_init(&fixed);
1930 	name = dns_fixedname_name(&fixed);
1931 	result = dns_name_fromstring2(name, oldlookup->textname, NULL,
1932 				      0, NULL);
1933 	if (result == ISC_R_SUCCESS &&
1934 	    (dns_name_isabsolute(name) ||
1935 	     (int)dns_name_countlabels(name) > ndots))
1936 		return (ISC_FALSE);
1937 
1938 	if (oldlookup->origin == NULL && !oldlookup->need_search)
1939 		/*
1940 		 * Then we just did rootorg; there's nothing left.
1941 		 */
1942 		return (ISC_FALSE);
1943 	if (oldlookup->origin == NULL && oldlookup->need_search) {
1944 		newlookup = requeue_lookup(oldlookup, ISC_TRUE);
1945 		newlookup->origin = ISC_LIST_HEAD(search_list);
1946 		newlookup->need_search = ISC_FALSE;
1947 	} else {
1948 		search = ISC_LIST_NEXT(oldlookup->origin, link);
1949 		if (search == NULL && oldlookup->done_as_is)
1950 			return (ISC_FALSE);
1951 		newlookup = requeue_lookup(oldlookup, ISC_TRUE);
1952 		newlookup->origin = search;
1953 	}
1954 	cancel_lookup(oldlookup);
1955 	return (ISC_TRUE);
1956 }
1957 
1958 /*%
1959  * Insert an SOA record into the sendmessage in a lookup.  Used for
1960  * creating IXFR queries.
1961  */
1962 static void
insert_soa(dig_lookup_t * lookup)1963 insert_soa(dig_lookup_t *lookup) {
1964 	isc_result_t result;
1965 	dns_rdata_soa_t soa;
1966 	dns_rdata_t *rdata = NULL;
1967 	dns_rdatalist_t *rdatalist = NULL;
1968 	dns_rdataset_t *rdataset = NULL;
1969 	dns_name_t *soaname = NULL;
1970 
1971 	debug("insert_soa()");
1972 	soa.mctx = mctx;
1973 	soa.serial = lookup->ixfr_serial;
1974 	soa.refresh = 0;
1975 	soa.retry = 0;
1976 	soa.expire = 0;
1977 	soa.minimum = 0;
1978 	soa.common.rdclass = lookup->rdclass;
1979 	soa.common.rdtype = dns_rdatatype_soa;
1980 
1981 	dns_name_init(&soa.origin, NULL);
1982 	dns_name_init(&soa.contact, NULL);
1983 
1984 	dns_name_clone(dns_rootname, &soa.origin);
1985 	dns_name_clone(dns_rootname, &soa.contact);
1986 
1987 	isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1988 			sizeof(lookup->rdatastore));
1989 
1990 	result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1991 	check_result(result, "dns_message_gettemprdata");
1992 
1993 	result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1994 				      dns_rdatatype_soa, &soa,
1995 				      &lookup->rdatabuf);
1996 	check_result(result, "isc_rdata_fromstruct");
1997 
1998 	result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1999 	check_result(result, "dns_message_gettemprdatalist");
2000 
2001 	result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
2002 	check_result(result, "dns_message_gettemprdataset");
2003 
2004 	dns_rdatalist_init(rdatalist);
2005 	rdatalist->type = dns_rdatatype_soa;
2006 	rdatalist->rdclass = lookup->rdclass;
2007 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2008 
2009 	dns_rdataset_init(rdataset);
2010 	dns_rdatalist_tordataset(rdatalist, rdataset);
2011 
2012 	result = dns_message_gettempname(lookup->sendmsg, &soaname);
2013 	check_result(result, "dns_message_gettempname");
2014 	dns_name_init(soaname, NULL);
2015 	dns_name_clone(lookup->name, soaname);
2016 	ISC_LIST_INIT(soaname->list);
2017 	ISC_LIST_APPEND(soaname->list, rdataset, link);
2018 	dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
2019 }
2020 
2021 /*%
2022  * Setup the supplied lookup structure, making it ready to start sending
2023  * queries to servers.  Create and initialize the message to be sent as
2024  * well as the query structures and buffer space for the replies.  If the
2025  * server list is empty, clone it from the system default list.
2026  */
2027 isc_boolean_t
setup_lookup(dig_lookup_t * lookup)2028 setup_lookup(dig_lookup_t *lookup) {
2029 	isc_result_t result;
2030 	isc_uint32_t id;
2031 	int len;
2032 	dig_server_t *serv;
2033 	dig_query_t *query;
2034 	isc_buffer_t b;
2035 	dns_compress_t cctx;
2036 	char store[MXNAME];
2037 #ifdef WITH_IDN
2038 	idn_result_t mr;
2039 	char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
2040 #endif
2041 
2042 #ifdef WITH_IDN
2043 	result = dns_name_settotextfilter(output_filter);
2044 	check_result(result, "dns_name_settotextfilter");
2045 #endif
2046 
2047 	REQUIRE(lookup != NULL);
2048 	INSIST(!free_now);
2049 
2050 	debug("setup_lookup(%p)", lookup);
2051 
2052 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2053 				    &lookup->sendmsg);
2054 	check_result(result, "dns_message_create");
2055 
2056 	if (lookup->new_search) {
2057 		debug("resetting lookup counter.");
2058 		lookup_counter = 0;
2059 	}
2060 
2061 	if (ISC_LIST_EMPTY(lookup->my_server_list)) {
2062 		debug("cloning server list");
2063 		clone_server_list(server_list, &lookup->my_server_list);
2064 	}
2065 	result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
2066 	check_result(result, "dns_message_gettempname");
2067 	dns_name_init(lookup->name, NULL);
2068 
2069 	isc_buffer_init(&lookup->namebuf, lookup->namespace,
2070 			sizeof(lookup->namespace));
2071 	isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
2072 			sizeof(lookup->onamespace));
2073 
2074 #ifdef WITH_IDN
2075 	/*
2076 	 * We cannot convert `textname' and `origin' separately.
2077 	 * `textname' doesn't contain TLD, but local mapping needs
2078 	 * TLD.
2079 	 */
2080 	mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
2081 			    utf8_textname, sizeof(utf8_textname));
2082 	idn_check_result(mr, "convert textname to UTF-8");
2083 #endif
2084 
2085 	/*
2086 	 * If the name has too many dots, force the origin to be NULL
2087 	 * (which produces an absolute lookup).  Otherwise, take the origin
2088 	 * we have if there's one in the struct already.  If it's NULL,
2089 	 * take the first entry in the searchlist iff either usesearch
2090 	 * is TRUE or we got a domain line in the resolv.conf file.
2091 	 */
2092 	if (lookup->new_search) {
2093 #ifdef WITH_IDN
2094 		if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
2095 			lookup->origin = NULL; /* Force abs lookup */
2096 			lookup->done_as_is = ISC_TRUE;
2097 			lookup->need_search = usesearch;
2098 		} else if (lookup->origin == NULL && usesearch) {
2099 			lookup->origin = ISC_LIST_HEAD(search_list);
2100 			lookup->need_search = ISC_FALSE;
2101 		}
2102 #else
2103 		if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
2104 			lookup->origin = NULL; /* Force abs lookup */
2105 			lookup->done_as_is = ISC_TRUE;
2106 			lookup->need_search = usesearch;
2107 		} else if (lookup->origin == NULL && usesearch) {
2108 			lookup->origin = ISC_LIST_HEAD(search_list);
2109 			lookup->need_search = ISC_FALSE;
2110 		}
2111 #endif
2112 	}
2113 
2114 #ifdef WITH_IDN
2115 	if (lookup->origin != NULL) {
2116 		mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
2117 				    lookup->origin->origin, utf8_origin,
2118 				    sizeof(utf8_origin));
2119 		idn_check_result(mr, "convert origin to UTF-8");
2120 		mr = append_textname(utf8_textname, utf8_origin,
2121 				     sizeof(utf8_textname));
2122 		idn_check_result(mr, "append origin to textname");
2123 	}
2124 	mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
2125 			    IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
2126 			    idn_textname, sizeof(idn_textname));
2127 	idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
2128 #else
2129 	if (lookup->origin != NULL) {
2130 		debug("trying origin %s", lookup->origin->origin);
2131 		result = dns_message_gettempname(lookup->sendmsg,
2132 						 &lookup->oname);
2133 		check_result(result, "dns_message_gettempname");
2134 		dns_name_init(lookup->oname, NULL);
2135 		/* XXX Helper funct to conv char* to name? */
2136 		len = strlen(lookup->origin->origin);
2137 		isc_buffer_init(&b, lookup->origin->origin, len);
2138 		isc_buffer_add(&b, len);
2139 		result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
2140 					   0, &lookup->onamebuf);
2141 		if (result != ISC_R_SUCCESS) {
2142 			dns_message_puttempname(lookup->sendmsg,
2143 						&lookup->name);
2144 			dns_message_puttempname(lookup->sendmsg,
2145 						&lookup->oname);
2146 			fatal("'%s' is not in legal name syntax (%s)",
2147 			      lookup->origin->origin,
2148 			      isc_result_totext(result));
2149 		}
2150 		if (lookup->trace && lookup->trace_root) {
2151 			dns_name_clone(dns_rootname, lookup->name);
2152 		} else {
2153 			dns_fixedname_t fixed;
2154 			dns_name_t *name;
2155 
2156 			dns_fixedname_init(&fixed);
2157 			name = dns_fixedname_name(&fixed);
2158 			len = strlen(lookup->textname);
2159 			isc_buffer_init(&b, lookup->textname, len);
2160 			isc_buffer_add(&b, len);
2161 			result = dns_name_fromtext(name, &b, NULL, 0, NULL);
2162 			if (result == ISC_R_SUCCESS &&
2163 			    !dns_name_isabsolute(name))
2164 				result = dns_name_concatenate(name,
2165 							      lookup->oname,
2166 							      lookup->name,
2167 							      &lookup->namebuf);
2168 			else if (result == ISC_R_SUCCESS)
2169 				result = dns_name_copy(name, lookup->name,
2170 						       &lookup->namebuf);
2171 			if (result != ISC_R_SUCCESS) {
2172 				dns_message_puttempname(lookup->sendmsg,
2173 							&lookup->name);
2174 				dns_message_puttempname(lookup->sendmsg,
2175 							&lookup->oname);
2176 				if (result == DNS_R_NAMETOOLONG)
2177 					return (ISC_FALSE);
2178 				fatal("'%s' is not in legal name syntax (%s)",
2179 				      lookup->textname,
2180 				      isc_result_totext(result));
2181 			}
2182 		}
2183 		dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2184 	} else
2185 #endif
2186 	{
2187 		debug("using root origin");
2188 		if (lookup->trace && lookup->trace_root)
2189 			dns_name_clone(dns_rootname, lookup->name);
2190 		else {
2191 #ifdef WITH_IDN
2192 			len = strlen(idn_textname);
2193 			isc_buffer_init(&b, idn_textname, len);
2194 			isc_buffer_add(&b, len);
2195 			result = dns_name_fromtext(lookup->name, &b,
2196 						   dns_rootname, 0,
2197 						   &lookup->namebuf);
2198 #else
2199 			len = strlen(lookup->textname);
2200 			isc_buffer_init(&b, lookup->textname, len);
2201 			isc_buffer_add(&b, len);
2202 			result = dns_name_fromtext(lookup->name, &b,
2203 						   dns_rootname, 0,
2204 						   &lookup->namebuf);
2205 #endif
2206 		}
2207 		if (result != ISC_R_SUCCESS) {
2208 			dns_message_puttempname(lookup->sendmsg,
2209 						&lookup->name);
2210 			fatal("'%s' is not a legal name "
2211 			      "(%s)", lookup->textname,
2212 			      isc_result_totext(result));
2213 		}
2214 	}
2215 	dns_name_format(lookup->name, store, sizeof(store));
2216 	trying(store, lookup);
2217 	INSIST(dns_name_isabsolute(lookup->name));
2218 
2219 	isc_random_get(&id);
2220 	lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2221 	lookup->sendmsg->opcode = dns_opcode_query;
2222 	lookup->msgcounter = 0;
2223 	/*
2224 	 * If this is a trace request, completely disallow recursion, since
2225 	 * it's meaningless for traces.
2226 	 */
2227 	if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2228 		lookup->recurse = ISC_FALSE;
2229 
2230 	if (lookup->recurse &&
2231 	    lookup->rdtype != dns_rdatatype_axfr &&
2232 	    lookup->rdtype != dns_rdatatype_ixfr) {
2233 		debug("recursive query");
2234 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2235 	}
2236 
2237 	/* XXX aaflag */
2238 	if (lookup->aaonly) {
2239 		debug("AA query");
2240 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2241 	}
2242 
2243 	if (lookup->adflag) {
2244 		debug("AD query");
2245 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2246 	}
2247 
2248 	if (lookup->cdflag) {
2249 		debug("CD query");
2250 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2251 	}
2252 
2253 	dns_message_addname(lookup->sendmsg, lookup->name,
2254 			    DNS_SECTION_QUESTION);
2255 
2256 	if (lookup->trace && lookup->trace_root) {
2257 		lookup->qrdtype = lookup->rdtype;
2258 		lookup->rdtype = dns_rdatatype_ns;
2259 	}
2260 
2261 	if ((lookup->rdtype == dns_rdatatype_axfr) ||
2262 	    (lookup->rdtype == dns_rdatatype_ixfr)) {
2263 		/*
2264 		 * Force TCP mode if we're doing an axfr.
2265 		 */
2266 		if (lookup->rdtype == dns_rdatatype_axfr) {
2267 			lookup->doing_xfr = ISC_TRUE;
2268 			lookup->tcp_mode = ISC_TRUE;
2269 		} else if (lookup->tcp_mode) {
2270 			lookup->doing_xfr = ISC_TRUE;
2271 		}
2272 	}
2273 
2274 	add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2275 		     lookup->rdtype);
2276 
2277 	/* add_soa */
2278 	if (lookup->rdtype == dns_rdatatype_ixfr)
2279 		insert_soa(lookup);
2280 
2281 	/* XXX Insist this? */
2282 	lookup->tsigctx = NULL;
2283 	lookup->querysig = NULL;
2284 	if (key != NULL) {
2285 		debug("initializing keys");
2286 		result = dns_message_settsigkey(lookup->sendmsg, key);
2287 		check_result(result, "dns_message_settsigkey");
2288 	}
2289 
2290 	lookup->sendspace = isc_mempool_get(commctx);
2291 	if (lookup->sendspace == NULL)
2292 		fatal("memory allocation failure");
2293 
2294 	result = dns_compress_init(&cctx, -1, mctx);
2295 	check_result(result, "dns_compress_init");
2296 
2297 	debug("starting to render the message");
2298 	isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2299 	result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2300 					 &lookup->renderbuf);
2301 	check_result(result, "dns_message_renderbegin");
2302 	if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) {
2303 		if (lookup->udpsize == 0)
2304 			lookup->udpsize = 4096;
2305 		if (lookup->edns < 0)
2306 			lookup->edns = 0;
2307 		add_opt(lookup->sendmsg, lookup->udpsize,
2308 			lookup->edns, lookup->dnssec, lookup->nsid);
2309 	}
2310 
2311 	result = dns_message_rendersection(lookup->sendmsg,
2312 					   DNS_SECTION_QUESTION, 0);
2313 	check_result(result, "dns_message_rendersection");
2314 	result = dns_message_rendersection(lookup->sendmsg,
2315 					   DNS_SECTION_AUTHORITY, 0);
2316 	check_result(result, "dns_message_rendersection");
2317 	result = dns_message_renderend(lookup->sendmsg);
2318 	check_result(result, "dns_message_renderend");
2319 	debug("done rendering");
2320 
2321 	dns_compress_invalidate(&cctx);
2322 
2323 	/*
2324 	 * Force TCP mode if the request is larger than 512 bytes.
2325 	 */
2326 	if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2327 		lookup->tcp_mode = ISC_TRUE;
2328 
2329 	lookup->pending = ISC_FALSE;
2330 
2331 	for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2332 	     serv != NULL;
2333 	     serv = ISC_LIST_NEXT(serv, link)) {
2334 		query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2335 		if (query == NULL)
2336 			fatal("memory allocation failure in %s:%d",
2337 			      __FILE__, __LINE__);
2338 		debug("create query %p linked to lookup %p",
2339 		       query, lookup);
2340 		query->lookup = lookup;
2341 		query->waiting_connect = ISC_FALSE;
2342 		query->waiting_senddone = ISC_FALSE;
2343 		query->pending_free = ISC_FALSE;
2344 		query->recv_made = ISC_FALSE;
2345 		query->first_pass = ISC_TRUE;
2346 		query->first_soa_rcvd = ISC_FALSE;
2347 		query->second_rr_rcvd = ISC_FALSE;
2348 		query->first_repeat_rcvd = ISC_FALSE;
2349 		query->warn_id = ISC_TRUE;
2350 		query->first_rr_serial = 0;
2351 		query->second_rr_serial = 0;
2352 		query->servname = serv->servername;
2353 		query->userarg = serv->userarg;
2354 		query->rr_count = 0;
2355 		query->msg_count = 0;
2356 		query->byte_count = 0;
2357 		query->ixfr_axfr = ISC_FALSE;
2358 		ISC_LIST_INIT(query->recvlist);
2359 		ISC_LIST_INIT(query->lengthlist);
2360 		query->sock = NULL;
2361 		query->recvspace = isc_mempool_get(commctx);
2362 		if (query->recvspace == NULL)
2363 			fatal("memory allocation failure");
2364 
2365 		isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2366 		isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2367 		isc_buffer_init(&query->slbuf, query->slspace, 2);
2368 		query->sendbuf = lookup->renderbuf;
2369 
2370 		ISC_LINK_INIT(query, clink);
2371 		ISC_LINK_INIT(query, link);
2372 		ISC_LIST_ENQUEUE(lookup->q, query, link);
2373 	}
2374 	/* XXX qrflag, print_query, etc... */
2375 	if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2376 		extrabytes = 0;
2377 		printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2378 			     ISC_TRUE);
2379 	}
2380 	return (ISC_TRUE);
2381 }
2382 
2383 /*%
2384  * Event handler for send completion.  Track send counter, and clear out
2385  * the query if the send was canceled.
2386  */
2387 static void
send_done(isc_task_t * _task,isc_event_t * event)2388 send_done(isc_task_t *_task, isc_event_t *event) {
2389 	isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2390 	isc_buffer_t *b = NULL;
2391 	dig_query_t *query, *next;
2392 	dig_lookup_t *l;
2393 
2394 	REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2395 
2396 	UNUSED(_task);
2397 
2398 	LOCK_LOOKUP;
2399 
2400 	debug("send_done()");
2401 	sendcount--;
2402 	debug("sendcount=%d", sendcount);
2403 	INSIST(sendcount >= 0);
2404 
2405 	for  (b = ISC_LIST_HEAD(sevent->bufferlist);
2406 	      b != NULL;
2407 	      b = ISC_LIST_HEAD(sevent->bufferlist)) {
2408 		ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2409 		isc_mem_free(mctx, b);
2410 	}
2411 
2412 	query = event->ev_arg;
2413 	query->waiting_senddone = ISC_FALSE;
2414 	l = query->lookup;
2415 
2416 	if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2417 		debug("sending next, since searching");
2418 		next = ISC_LIST_NEXT(query, link);
2419 		if (next != NULL)
2420 			send_udp(next);
2421 	}
2422 
2423 	isc_event_free(&event);
2424 
2425 	if (query->pending_free)
2426 		isc_mem_free(mctx, query);
2427 
2428 	check_if_done();
2429 	UNLOCK_LOOKUP;
2430 }
2431 
2432 /*%
2433  * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2434  * IO sockets.  The cancel handlers should take care of cleaning up the
2435  * query and lookup structures
2436  */
2437 static void
cancel_lookup(dig_lookup_t * lookup)2438 cancel_lookup(dig_lookup_t *lookup) {
2439 	dig_query_t *query, *next;
2440 
2441 	debug("cancel_lookup()");
2442 	query = ISC_LIST_HEAD(lookup->q);
2443 	while (query != NULL) {
2444 		next = ISC_LIST_NEXT(query, link);
2445 		if (query->sock != NULL) {
2446 			isc_socket_cancel(query->sock, global_task,
2447 					  ISC_SOCKCANCEL_ALL);
2448 			check_if_done();
2449 		} else {
2450 			clear_query(query);
2451 		}
2452 		query = next;
2453 	}
2454 	if (lookup->timer != NULL)
2455 		isc_timer_detach(&lookup->timer);
2456 	lookup->pending = ISC_FALSE;
2457 	lookup->retries = 0;
2458 }
2459 
2460 static void
bringup_timer(dig_query_t * query,unsigned int default_timeout)2461 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2462 	dig_lookup_t *l;
2463 	unsigned int local_timeout;
2464 	isc_result_t result;
2465 
2466 	debug("bringup_timer()");
2467 	/*
2468 	 * If the timer already exists, that means we're calling this
2469 	 * a second time (for a retry).  Don't need to recreate it,
2470 	 * just reset it.
2471 	 */
2472 	l = query->lookup;
2473 	if (ISC_LIST_NEXT(query, link) != NULL)
2474 		local_timeout = SERVER_TIMEOUT;
2475 	else {
2476 		if (timeout == 0)
2477 			local_timeout = default_timeout;
2478 		else
2479 			local_timeout = timeout;
2480 	}
2481 	debug("have local timeout of %d", local_timeout);
2482 	isc_interval_set(&l->interval, local_timeout, 0);
2483 	if (l->timer != NULL)
2484 		isc_timer_detach(&l->timer);
2485 	result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2486 				  &l->interval, global_task, connect_timeout,
2487 				  l, &l->timer);
2488 	check_result(result, "isc_timer_create");
2489 }
2490 
2491 static void
force_timeout(dig_lookup_t * l,dig_query_t * query)2492 force_timeout(dig_lookup_t *l, dig_query_t *query) {
2493 	isc_event_t *event;
2494 
2495 	debug("force_timeout ()");
2496 	event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2497 				   connect_timeout, l,
2498 				   sizeof(isc_event_t));
2499 	if (event == NULL) {
2500 		fatal("isc_event_allocate: %s",
2501 		      isc_result_totext(ISC_R_NOMEMORY));
2502 	}
2503 	isc_task_send(global_task, &event);
2504 
2505 	/*
2506 	 * The timer may have expired if, for example, get_address() takes
2507 	 * long time and the timer was running on a different thread.
2508 	 * We need to cancel the possible timeout event not to confuse
2509 	 * ourselves due to the duplicate events.
2510 	 */
2511 	if (l->timer != NULL)
2512 		isc_timer_detach(&l->timer);
2513 }
2514 
2515 
2516 static void
2517 connect_done(isc_task_t *task, isc_event_t *event);
2518 
2519 /*%
2520  * Unlike send_udp, this can't be called multiple times with the same
2521  * query.  When we retry TCP, we requeue the whole lookup, which should
2522  * start anew.
2523  */
2524 static void
send_tcp_connect(dig_query_t * query)2525 send_tcp_connect(dig_query_t *query) {
2526 	isc_result_t result;
2527 	dig_query_t *next;
2528 	dig_lookup_t *l;
2529 
2530 	debug("send_tcp_connect(%p)", query);
2531 
2532 	l = query->lookup;
2533 	query->waiting_connect = ISC_TRUE;
2534 	query->lookup->current_query = query;
2535 	result = get_address(query->servname, port, &query->sockaddr);
2536 	if (result != ISC_R_SUCCESS) {
2537 		/*
2538 		 * This servname doesn't have an address.  Try the next server
2539 		 * by triggering an immediate 'timeout' (we lie, but the effect
2540 		 * is the same).
2541 		 */
2542 		force_timeout(l, query);
2543 		return;
2544 	}
2545 
2546 	if (specified_source &&
2547 	    (isc_sockaddr_pf(&query->sockaddr) !=
2548 	     isc_sockaddr_pf(&bind_address))) {
2549 		printf(";; Skipping server %s, incompatible "
2550 		       "address family\n", query->servname);
2551 		query->waiting_connect = ISC_FALSE;
2552 		next = ISC_LIST_NEXT(query, link);
2553 		l = query->lookup;
2554 		clear_query(query);
2555 		if (next == NULL) {
2556 			printf(";; No acceptable nameservers\n");
2557 			check_next_lookup(l);
2558 			return;
2559 		}
2560 		send_tcp_connect(next);
2561 		return;
2562 	}
2563 
2564 	INSIST(query->sock == NULL);
2565 
2566 	if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2567 		sockcount++;
2568 		isc_socket_attach(keep, &query->sock);
2569 		query->waiting_connect = ISC_FALSE;
2570 		launch_next_query(query, ISC_TRUE);
2571 		goto search;
2572 	}
2573 
2574 	result = isc_socket_create(socketmgr,
2575 				   isc_sockaddr_pf(&query->sockaddr),
2576 				   isc_sockettype_tcp, &query->sock);
2577 	check_result(result, "isc_socket_create");
2578 	sockcount++;
2579 	debug("sockcount=%d", sockcount);
2580 	if (specified_source)
2581 		result = isc_socket_bind(query->sock, &bind_address,
2582 					 ISC_SOCKET_REUSEADDRESS);
2583 	else {
2584 		if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2585 		    have_ipv4)
2586 			isc_sockaddr_any(&bind_any);
2587 		else
2588 			isc_sockaddr_any6(&bind_any);
2589 		result = isc_socket_bind(query->sock, &bind_any, 0);
2590 	}
2591 	check_result(result, "isc_socket_bind");
2592 	bringup_timer(query, TCP_TIMEOUT);
2593 	result = isc_socket_connect(query->sock, &query->sockaddr,
2594 				    global_task, connect_done, query);
2595 	check_result(result, "isc_socket_connect");
2596  search:
2597 	/*
2598 	 * If we're at the endgame of a nameserver search, we need to
2599 	 * immediately bring up all the queries.  Do it here.
2600 	 */
2601 	if (l->ns_search_only && !l->trace_root) {
2602 		debug("sending next, since searching");
2603 		next = ISC_LIST_NEXT(query, link);
2604 		if (ISC_LINK_LINKED(query, link))
2605 			ISC_LIST_DEQUEUE(l->q, query, link);
2606 		ISC_LIST_ENQUEUE(l->connecting, query, clink);
2607 		if (next != NULL)
2608 			send_tcp_connect(next);
2609 	}
2610 }
2611 
2612 static isc_buffer_t *
clone_buffer(isc_buffer_t * source)2613 clone_buffer(isc_buffer_t *source) {
2614 	isc_buffer_t *buffer;
2615 	buffer = isc_mem_allocate(mctx, sizeof(*buffer));
2616 	if (buffer == NULL)
2617 		fatal("memory allocation failure in %s:%d",
2618 		      __FILE__, __LINE__);
2619 	*buffer = *source;
2620 	return (buffer);
2621 }
2622 
2623 /*%
2624  * Send a UDP packet to the remote nameserver, possible starting the
2625  * recv action as well.  Also make sure that the timer is running and
2626  * is properly reset.
2627  */
2628 static void
send_udp(dig_query_t * query)2629 send_udp(dig_query_t *query) {
2630 	dig_lookup_t *l = NULL;
2631 	isc_result_t result;
2632 	isc_buffer_t *sendbuf;
2633 
2634 	debug("send_udp(%p)", query);
2635 
2636 	l = query->lookup;
2637 	bringup_timer(query, UDP_TIMEOUT);
2638 	l->current_query = query;
2639 	debug("working on lookup %p, query %p", query->lookup, query);
2640 	if (!query->recv_made) {
2641 		/* XXX Check the sense of this, need assertion? */
2642 		query->waiting_connect = ISC_FALSE;
2643 		result = get_address(query->servname, port, &query->sockaddr);
2644 		if (result != ISC_R_SUCCESS) {
2645 			/* This servname doesn't have an address. */
2646 			force_timeout(l, query);
2647 			return;
2648 		}
2649 
2650 		result = isc_socket_create(socketmgr,
2651 					   isc_sockaddr_pf(&query->sockaddr),
2652 					   isc_sockettype_udp, &query->sock);
2653 		check_result(result, "isc_socket_create");
2654 		sockcount++;
2655 		debug("sockcount=%d", sockcount);
2656 		if (specified_source) {
2657 			result = isc_socket_bind(query->sock, &bind_address,
2658 						 ISC_SOCKET_REUSEADDRESS);
2659 		} else {
2660 			isc_sockaddr_anyofpf(&bind_any,
2661 					isc_sockaddr_pf(&query->sockaddr));
2662 			result = isc_socket_bind(query->sock, &bind_any, 0);
2663 		}
2664 		check_result(result, "isc_socket_bind");
2665 
2666 		query->recv_made = ISC_TRUE;
2667 		ISC_LINK_INIT(&query->recvbuf, link);
2668 		ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2669 				 link);
2670 		debug("recving with lookup=%p, query=%p, sock=%p",
2671 		      query->lookup, query, query->sock);
2672 		result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2673 					  global_task, recv_done, query);
2674 		check_result(result, "isc_socket_recvv");
2675 		recvcount++;
2676 		debug("recvcount=%d", recvcount);
2677 	}
2678 	ISC_LIST_INIT(query->sendlist);
2679 	sendbuf = clone_buffer(&query->sendbuf);
2680 	ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
2681 	debug("sending a request");
2682 	TIME_NOW(&query->time_sent);
2683 	INSIST(query->sock != NULL);
2684 	query->waiting_senddone = ISC_TRUE;
2685 	result = isc_socket_sendtov2(query->sock, &query->sendlist,
2686 				     global_task, send_done, query,
2687 				     &query->sockaddr, NULL,
2688 				     ISC_SOCKFLAG_NORETRY);
2689 	check_result(result, "isc_socket_sendtov");
2690 	sendcount++;
2691 }
2692 
2693 /*%
2694  * IO timeout handler, used for both connect and recv timeouts.  If
2695  * retries are still allowed, either resend the UDP packet or queue a
2696  * new TCP lookup.  Otherwise, cancel the lookup.
2697  */
2698 static void
connect_timeout(isc_task_t * task,isc_event_t * event)2699 connect_timeout(isc_task_t *task, isc_event_t *event) {
2700 	dig_lookup_t *l = NULL;
2701 	dig_query_t *query = NULL, *next, *cq;
2702 
2703 	UNUSED(task);
2704 	REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2705 
2706 	debug("connect_timeout()");
2707 
2708 	LOCK_LOOKUP;
2709 	l = event->ev_arg;
2710 	query = l->current_query;
2711 	isc_event_free(&event);
2712 
2713 	INSIST(!free_now);
2714 
2715 	if ((query != NULL) && (query->lookup->current_query != NULL) &&
2716 	    (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2717 		debug("trying next server...");
2718 		cq = query->lookup->current_query;
2719 		if (!l->tcp_mode)
2720 			send_udp(ISC_LIST_NEXT(cq, link));
2721 		else {
2722 			if (query->sock != NULL)
2723 				isc_socket_cancel(query->sock, NULL,
2724 						  ISC_SOCKCANCEL_ALL);
2725 			next = ISC_LIST_NEXT(cq, link);
2726 			if (next != NULL)
2727 				send_tcp_connect(next);
2728 		}
2729 		UNLOCK_LOOKUP;
2730 		return;
2731 	}
2732 
2733 	if (l->retries > 1) {
2734 		if (!l->tcp_mode) {
2735 			l->retries--;
2736 			debug("resending UDP request to first server");
2737 			send_udp(ISC_LIST_HEAD(l->q));
2738 		} else {
2739 			debug("making new TCP request, %d tries left",
2740 			      l->retries);
2741 			l->retries--;
2742 			requeue_lookup(l, ISC_TRUE);
2743 			cancel_lookup(l);
2744 			check_next_lookup(l);
2745 		}
2746 	} else {
2747 		fputs(l->cmdline, stdout);
2748 		printf(";; connection timed out; no servers could be "
2749 		       "reached\n");
2750 		cancel_lookup(l);
2751 		check_next_lookup(l);
2752 		if (exitcode < 9)
2753 			exitcode = 9;
2754 	}
2755 	UNLOCK_LOOKUP;
2756 }
2757 
2758 /*%
2759  * Event handler for the TCP recv which gets the length header of TCP
2760  * packets.  Start the next recv of length bytes.
2761  */
2762 static void
tcp_length_done(isc_task_t * task,isc_event_t * event)2763 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2764 	isc_socketevent_t *sevent;
2765 	isc_buffer_t *b = NULL;
2766 	isc_result_t result;
2767 	dig_query_t *query = NULL;
2768 	dig_lookup_t *l;
2769 	isc_uint16_t length;
2770 
2771 	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2772 	INSIST(!free_now);
2773 
2774 	UNUSED(task);
2775 
2776 	debug("tcp_length_done()");
2777 
2778 	LOCK_LOOKUP;
2779 	sevent = (isc_socketevent_t *)event;
2780 	query = event->ev_arg;
2781 
2782 	recvcount--;
2783 	INSIST(recvcount >= 0);
2784 
2785 	b = ISC_LIST_HEAD(sevent->bufferlist);
2786 	INSIST(b ==  &query->lengthbuf);
2787 	ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2788 
2789 	if (sevent->result == ISC_R_CANCELED) {
2790 		isc_event_free(&event);
2791 		l = query->lookup;
2792 		clear_query(query);
2793 		check_next_lookup(l);
2794 		UNLOCK_LOOKUP;
2795 		return;
2796 	}
2797 	if (sevent->result != ISC_R_SUCCESS) {
2798 		char sockstr[ISC_SOCKADDR_FORMATSIZE];
2799 		isc_sockaddr_format(&query->sockaddr, sockstr,
2800 				    sizeof(sockstr));
2801 		printf(";; communications error to %s: %s\n",
2802 		       sockstr, isc_result_totext(sevent->result));
2803 		l = query->lookup;
2804 		isc_socket_detach(&query->sock);
2805 		sockcount--;
2806 		debug("sockcount=%d", sockcount);
2807 		INSIST(sockcount >= 0);
2808 		isc_event_free(&event);
2809 		clear_query(query);
2810 		check_next_lookup(l);
2811 		UNLOCK_LOOKUP;
2812 		return;
2813 	}
2814 	length = isc_buffer_getuint16(b);
2815 	if (length == 0) {
2816 		isc_event_free(&event);
2817 		launch_next_query(query, ISC_FALSE);
2818 		UNLOCK_LOOKUP;
2819 		return;
2820 	}
2821 
2822 	/*
2823 	 * Even though the buffer was already init'ed, we need
2824 	 * to redo it now, to force the length we want.
2825 	 */
2826 	isc_buffer_invalidate(&query->recvbuf);
2827 	isc_buffer_init(&query->recvbuf, query->recvspace, length);
2828 	ENSURE(ISC_LIST_EMPTY(query->recvlist));
2829 	ISC_LINK_INIT(&query->recvbuf, link);
2830 	ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2831 	debug("recving with lookup=%p, query=%p", query->lookup, query);
2832 	result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2833 				  recv_done, query);
2834 	check_result(result, "isc_socket_recvv");
2835 	recvcount++;
2836 	debug("resubmitted recv request with length %d, recvcount=%d",
2837 	      length, recvcount);
2838 	isc_event_free(&event);
2839 	UNLOCK_LOOKUP;
2840 }
2841 
2842 /*%
2843  * For transfers that involve multiple recvs (XFR's in particular),
2844  * launch the next recv.
2845  */
2846 static void
launch_next_query(dig_query_t * query,isc_boolean_t include_question)2847 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
2848 	isc_result_t result;
2849 	dig_lookup_t *l;
2850 	isc_buffer_t *buffer;
2851 
2852 	INSIST(!free_now);
2853 
2854 	debug("launch_next_query()");
2855 
2856 	if (!query->lookup->pending) {
2857 		debug("ignoring launch_next_query because !pending");
2858 		isc_socket_detach(&query->sock);
2859 		sockcount--;
2860 		debug("sockcount=%d", sockcount);
2861 		INSIST(sockcount >= 0);
2862 		query->waiting_connect = ISC_FALSE;
2863 		l = query->lookup;
2864 		clear_query(query);
2865 		check_next_lookup(l);
2866 		return;
2867 	}
2868 
2869 	isc_buffer_clear(&query->slbuf);
2870 	isc_buffer_clear(&query->lengthbuf);
2871 	isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
2872 	ISC_LIST_INIT(query->sendlist);
2873 	ISC_LINK_INIT(&query->slbuf, link);
2874 	if (!query->first_soa_rcvd) {
2875 		buffer = clone_buffer(&query->slbuf);
2876 		ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2877 		if (include_question) {
2878 			buffer = clone_buffer(&query->sendbuf);
2879 			ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2880 		}
2881 	}
2882 
2883 	ISC_LINK_INIT(&query->lengthbuf, link);
2884 	ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2885 
2886 	result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2887 				  global_task, tcp_length_done, query);
2888 	check_result(result, "isc_socket_recvv");
2889 	recvcount++;
2890 	debug("recvcount=%d", recvcount);
2891 	if (!query->first_soa_rcvd) {
2892 		debug("sending a request in launch_next_query");
2893 		TIME_NOW(&query->time_sent);
2894 		query->waiting_senddone = ISC_TRUE;
2895 		result = isc_socket_sendv(query->sock, &query->sendlist,
2896 					  global_task, send_done, query);
2897 		check_result(result, "isc_socket_sendv");
2898 		sendcount++;
2899 		debug("sendcount=%d", sendcount);
2900 	}
2901 	query->waiting_connect = ISC_FALSE;
2902 #if 0
2903 	check_next_lookup(query->lookup);
2904 #endif
2905 	return;
2906 }
2907 
2908 /*%
2909  * Event handler for TCP connect complete.  Make sure the connection was
2910  * successful, then pass into launch_next_query to actually send the
2911  * question.
2912  */
2913 static void
connect_done(isc_task_t * task,isc_event_t * event)2914 connect_done(isc_task_t *task, isc_event_t *event) {
2915 	isc_socketevent_t *sevent = NULL;
2916 	dig_query_t *query = NULL, *next;
2917 	dig_lookup_t *l;
2918 
2919 	UNUSED(task);
2920 
2921 	REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2922 	INSIST(!free_now);
2923 
2924 	debug("connect_done()");
2925 
2926 	LOCK_LOOKUP;
2927 	sevent = (isc_socketevent_t *)event;
2928 	query = sevent->ev_arg;
2929 
2930 	INSIST(query->waiting_connect);
2931 
2932 	query->waiting_connect = ISC_FALSE;
2933 
2934 	if (sevent->result == ISC_R_CANCELED) {
2935 		debug("in cancel handler");
2936 		isc_socket_detach(&query->sock);
2937 		INSIST(sockcount > 0);
2938 		sockcount--;
2939 		debug("sockcount=%d", sockcount);
2940 		query->waiting_connect = ISC_FALSE;
2941 		isc_event_free(&event);
2942 		l = query->lookup;
2943 		clear_query(query);
2944 		check_next_lookup(l);
2945 		UNLOCK_LOOKUP;
2946 		return;
2947 	}
2948 	if (sevent->result != ISC_R_SUCCESS) {
2949 		char sockstr[ISC_SOCKADDR_FORMATSIZE];
2950 
2951 		debug("unsuccessful connection: %s",
2952 		      isc_result_totext(sevent->result));
2953 		isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2954 		if (sevent->result != ISC_R_CANCELED)
2955 			printf(";; Connection to %s(%s) for %s failed: "
2956 			       "%s.\n", sockstr,
2957 			       query->servname, query->lookup->textname,
2958 			       isc_result_totext(sevent->result));
2959 		isc_socket_detach(&query->sock);
2960 		sockcount--;
2961 		INSIST(sockcount >= 0);
2962 		/* XXX Clean up exitcodes */
2963 		if (exitcode < 9)
2964 			exitcode = 9;
2965 		debug("sockcount=%d", sockcount);
2966 		query->waiting_connect = ISC_FALSE;
2967 		isc_event_free(&event);
2968 		l = query->lookup;
2969 		if ((l->current_query != NULL) &&
2970 		    (ISC_LINK_LINKED(l->current_query, link)))
2971 			next = ISC_LIST_NEXT(l->current_query, link);
2972 		else
2973 			next = NULL;
2974 		clear_query(query);
2975 		if (next != NULL) {
2976 			bringup_timer(next, TCP_TIMEOUT);
2977 			send_tcp_connect(next);
2978 		} else
2979 			check_next_lookup(l);
2980 		UNLOCK_LOOKUP;
2981 		return;
2982 	}
2983 	if (keep_open) {
2984 		if (keep != NULL)
2985 			isc_socket_detach(&keep);
2986 		isc_socket_attach(query->sock, &keep);
2987 		keepaddr = query->sockaddr;
2988 	}
2989 	launch_next_query(query, ISC_TRUE);
2990 	isc_event_free(&event);
2991 	UNLOCK_LOOKUP;
2992 }
2993 
2994 /*%
2995  * Check if the ongoing XFR needs more data before it's complete, using
2996  * the semantics of IXFR and AXFR protocols.  Much of the complexity of
2997  * this routine comes from determining when an IXFR is complete.
2998  * ISC_FALSE means more data is on the way, and the recv has been issued.
2999  */
3000 static isc_boolean_t
check_for_more_data(dig_query_t * query,dns_message_t * msg,isc_socketevent_t * sevent)3001 check_for_more_data(dig_query_t *query, dns_message_t *msg,
3002 		    isc_socketevent_t *sevent)
3003 {
3004 	dns_rdataset_t *rdataset = NULL;
3005 	dns_rdata_t rdata = DNS_RDATA_INIT;
3006 	dns_rdata_soa_t soa;
3007 	isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
3008 	isc_result_t result;
3009 	isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
3010 	isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
3011 
3012 	if (ixfr)
3013 		axfr = query->ixfr_axfr;
3014 
3015 	debug("check_for_more_data()");
3016 
3017 	/*
3018 	 * By the time we're in this routine, we know we're doing
3019 	 * either an AXFR or IXFR.  If there's no second_rr_type,
3020 	 * then we don't yet know which kind of answer we got back
3021 	 * from the server.  Here, we're going to walk through the
3022 	 * rr's in the message, acting as necessary whenever we hit
3023 	 * an SOA rr.
3024 	 */
3025 
3026 	query->msg_count++;
3027 	query->byte_count += sevent->n;
3028 	result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
3029 	if (result != ISC_R_SUCCESS) {
3030 		puts("; Transfer failed.");
3031 		return (ISC_TRUE);
3032 	}
3033 	do {
3034 		dns_name_t *name;
3035 		name = NULL;
3036 		dns_message_currentname(msg, DNS_SECTION_ANSWER,
3037 					&name);
3038 		for (rdataset = ISC_LIST_HEAD(name->list);
3039 		     rdataset != NULL;
3040 		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
3041 			result = dns_rdataset_first(rdataset);
3042 			if (result != ISC_R_SUCCESS)
3043 				continue;
3044 			do {
3045 				query->rr_count++;
3046 				dns_rdata_reset(&rdata);
3047 				dns_rdataset_current(rdataset, &rdata);
3048 				/*
3049 				 * If this is the first rr, make sure
3050 				 * it's an SOA
3051 				 */
3052 				if ((!query->first_soa_rcvd) &&
3053 				    (rdata.type != dns_rdatatype_soa)) {
3054 					puts("; Transfer failed.  "
3055 					     "Didn't start with SOA answer.");
3056 					return (ISC_TRUE);
3057 				}
3058 				if ((!query->second_rr_rcvd) &&
3059 				    (rdata.type != dns_rdatatype_soa)) {
3060 					query->second_rr_rcvd = ISC_TRUE;
3061 					query->second_rr_serial = 0;
3062 					debug("got the second rr as nonsoa");
3063 					axfr = query->ixfr_axfr = ISC_TRUE;
3064 					goto next_rdata;
3065 				}
3066 
3067 				/*
3068 				 * If the record is anything except an SOA
3069 				 * now, just continue on...
3070 				 */
3071 				if (rdata.type != dns_rdatatype_soa)
3072 					goto next_rdata;
3073 
3074 				/* Now we have an SOA.  Work with it. */
3075 				debug("got an SOA");
3076 				result = dns_rdata_tostruct(&rdata, &soa, NULL);
3077 				check_result(result, "dns_rdata_tostruct");
3078 				serial = soa.serial;
3079 				dns_rdata_freestruct(&soa);
3080 				if (!query->first_soa_rcvd) {
3081 					query->first_soa_rcvd = ISC_TRUE;
3082 					query->first_rr_serial = serial;
3083 					debug("this is the first serial %u",
3084 					      serial);
3085 					if (ixfr && isc_serial_ge(ixfr_serial,
3086 								  serial)) {
3087 						debug("got up to date "
3088 						      "response");
3089 						goto doexit;
3090 					}
3091 					goto next_rdata;
3092 				}
3093 				if (axfr) {
3094 					debug("doing axfr, got second SOA");
3095 					goto doexit;
3096 				}
3097 				if (!query->second_rr_rcvd) {
3098 					if (query->first_rr_serial == serial) {
3099 						debug("doing ixfr, got "
3100 						      "empty zone");
3101 						goto doexit;
3102 					}
3103 					debug("this is the second serial %u",
3104 					      serial);
3105 					query->second_rr_rcvd = ISC_TRUE;
3106 					query->second_rr_serial = serial;
3107 					goto next_rdata;
3108 				}
3109 				/*
3110 				 * If we get to this point, we're doing an
3111 				 * IXFR and have to start really looking
3112 				 * at serial numbers.
3113 				 */
3114 				if (query->first_rr_serial == serial) {
3115 					debug("got a match for ixfr");
3116 					if (!query->first_repeat_rcvd) {
3117 						query->first_repeat_rcvd =
3118 							ISC_TRUE;
3119 						goto next_rdata;
3120 					}
3121 					debug("done with ixfr");
3122 					goto doexit;
3123 				}
3124 				debug("meaningless soa %u", serial);
3125 			next_rdata:
3126 				result = dns_rdataset_next(rdataset);
3127 			} while (result == ISC_R_SUCCESS);
3128 		}
3129 		result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3130 	} while (result == ISC_R_SUCCESS);
3131 	launch_next_query(query, ISC_FALSE);
3132 	return (ISC_FALSE);
3133  doexit:
3134 	received(sevent->n, &sevent->address, query);
3135 	return (ISC_TRUE);
3136 }
3137 
3138 /*%
3139  * Event handler for recv complete.  Perform whatever actions are necessary,
3140  * based on the specifics of the user's request.
3141  */
3142 static void
recv_done(isc_task_t * task,isc_event_t * event)3143 recv_done(isc_task_t *task, isc_event_t *event) {
3144 	isc_socketevent_t *sevent = NULL;
3145 	dig_query_t *query = NULL;
3146 	isc_buffer_t *b = NULL;
3147 	dns_message_t *msg = NULL;
3148 #ifdef DIG_SIGCHASE
3149 	dig_message_t *chase_msg = NULL;
3150 	dig_message_t *chase_msg2 = NULL;
3151 #endif
3152 	isc_result_t result;
3153 	dig_lookup_t *n, *l;
3154 	isc_boolean_t docancel = ISC_FALSE;
3155 	isc_boolean_t match = ISC_TRUE;
3156 	unsigned int parseflags;
3157 	dns_messageid_t id;
3158 	unsigned int msgflags;
3159 #ifdef DIG_SIGCHASE
3160 	isc_result_t do_sigchase = ISC_FALSE;
3161 
3162 	dns_message_t *msg_temp = NULL;
3163 	isc_region_t r;
3164 	isc_buffer_t *buf = NULL;
3165 #endif
3166 
3167 	UNUSED(task);
3168 	INSIST(!free_now);
3169 
3170 	debug("recv_done()");
3171 
3172 	LOCK_LOOKUP;
3173 	recvcount--;
3174 	debug("recvcount=%d", recvcount);
3175 	INSIST(recvcount >= 0);
3176 
3177 	query = event->ev_arg;
3178 	TIME_NOW(&query->time_recv);
3179 	debug("lookup=%p, query=%p", query->lookup, query);
3180 
3181 	l = query->lookup;
3182 
3183 	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3184 	sevent = (isc_socketevent_t *)event;
3185 
3186 	b = ISC_LIST_HEAD(sevent->bufferlist);
3187 	INSIST(b == &query->recvbuf);
3188 	ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3189 
3190 	if ((l->tcp_mode) && (l->timer != NULL))
3191 		isc_timer_touch(l->timer);
3192 	if ((!l->pending && !l->ns_search_only) || cancel_now) {
3193 		debug("no longer pending.  Got %s",
3194 			isc_result_totext(sevent->result));
3195 		query->waiting_connect = ISC_FALSE;
3196 
3197 		isc_event_free(&event);
3198 		clear_query(query);
3199 		check_next_lookup(l);
3200 		UNLOCK_LOOKUP;
3201 		return;
3202 	}
3203 
3204 	if (sevent->result != ISC_R_SUCCESS) {
3205 		if (sevent->result == ISC_R_CANCELED) {
3206 			debug("in recv cancel handler");
3207 			query->waiting_connect = ISC_FALSE;
3208 		} else {
3209 			printf(";; communications error: %s\n",
3210 			       isc_result_totext(sevent->result));
3211 			isc_socket_detach(&query->sock);
3212 			sockcount--;
3213 			debug("sockcount=%d", sockcount);
3214 			INSIST(sockcount >= 0);
3215 		}
3216 		isc_event_free(&event);
3217 		clear_query(query);
3218 		check_next_lookup(l);
3219 		UNLOCK_LOOKUP;
3220 		return;
3221 	}
3222 
3223 	if (!l->tcp_mode &&
3224 	    !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3225 				  ISC_SOCKADDR_CMPADDR|
3226 				  ISC_SOCKADDR_CMPPORT|
3227 				  ISC_SOCKADDR_CMPSCOPE|
3228 				  ISC_SOCKADDR_CMPSCOPEZERO)) {
3229 		char buf1[ISC_SOCKADDR_FORMATSIZE];
3230 		char buf2[ISC_SOCKADDR_FORMATSIZE];
3231 		isc_sockaddr_t any;
3232 
3233 		if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3234 			isc_sockaddr_any(&any);
3235 		else
3236 			isc_sockaddr_any6(&any);
3237 
3238 		/*
3239 		* We don't expect a match when the packet is
3240 		* sent to 0.0.0.0, :: or to a multicast addresses.
3241 		* XXXMPA broadcast needs to be handled here as well.
3242 		*/
3243 		if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3244 		     !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3245 		    isc_sockaddr_getport(&query->sockaddr) !=
3246 		    isc_sockaddr_getport(&sevent->address)) {
3247 			isc_sockaddr_format(&sevent->address, buf1,
3248 			sizeof(buf1));
3249 			isc_sockaddr_format(&query->sockaddr, buf2,
3250 			sizeof(buf2));
3251 			printf(";; reply from unexpected source: %s,"
3252 			" expected %s\n", buf1, buf2);
3253 			match = ISC_FALSE;
3254 		}
3255 	}
3256 
3257 	result = dns_message_peekheader(b, &id, &msgflags);
3258 	if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3259 		match = ISC_FALSE;
3260 		if (l->tcp_mode) {
3261 			isc_boolean_t fail = ISC_TRUE;
3262 			if (result == ISC_R_SUCCESS) {
3263 				if (!query->first_soa_rcvd ||
3264 				     query->warn_id)
3265 					printf(";; %s: ID mismatch: "
3266 					       "expected ID %u, got %u\n",
3267 					       query->first_soa_rcvd ?
3268 					       "WARNING" : "ERROR",
3269 					       l->sendmsg->id, id);
3270 				if (query->first_soa_rcvd)
3271 					fail = ISC_FALSE;
3272 				query->warn_id = ISC_FALSE;
3273 			} else
3274 				printf(";; ERROR: short "
3275 				       "(< header size) message\n");
3276 			if (fail) {
3277 				isc_event_free(&event);
3278 				clear_query(query);
3279 				check_next_lookup(l);
3280 				UNLOCK_LOOKUP;
3281 				return;
3282 			}
3283 			match = ISC_TRUE;
3284 		} else if (result == ISC_R_SUCCESS)
3285 			printf(";; Warning: ID mismatch: "
3286 			       "expected ID %u, got %u\n", l->sendmsg->id, id);
3287 		else
3288 			printf(";; Warning: short "
3289 			       "(< header size) message received\n");
3290 	}
3291 
3292 	if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3293 		printf(";; Warning: query response not set\n");
3294 
3295 	if (!match)
3296 		goto udp_mismatch;
3297 
3298 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3299 	check_result(result, "dns_message_create");
3300 
3301 	if (key != NULL) {
3302 		if (l->querysig == NULL) {
3303 			debug("getting initial querysig");
3304 			result = dns_message_getquerytsig(l->sendmsg, mctx,
3305 							  &l->querysig);
3306 			check_result(result, "dns_message_getquerytsig");
3307 		}
3308 		result = dns_message_setquerytsig(msg, l->querysig);
3309 		check_result(result, "dns_message_setquerytsig");
3310 		result = dns_message_settsigkey(msg, key);
3311 		check_result(result, "dns_message_settsigkey");
3312 		msg->tsigctx = l->tsigctx;
3313 		l->tsigctx = NULL;
3314 		if (l->msgcounter != 0)
3315 			msg->tcp_continuation = 1;
3316 		l->msgcounter++;
3317 	}
3318 
3319 	debug("before parse starts");
3320 	parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3321 #ifdef DIG_SIGCHASE
3322 	if (!l->sigchase) {
3323 		do_sigchase = ISC_FALSE;
3324 	} else {
3325 		parseflags = 0;
3326 		do_sigchase = ISC_TRUE;
3327 	}
3328 #endif
3329 	if (l->besteffort) {
3330 		parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3331 		parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3332 	}
3333 	result = dns_message_parse(msg, b, parseflags);
3334 	if (result == DNS_R_RECOVERABLE) {
3335 		printf(";; Warning: Message parser reports malformed "
3336 		       "message packet.\n");
3337 		result = ISC_R_SUCCESS;
3338 	}
3339 	if (result != ISC_R_SUCCESS) {
3340 		printf(";; Got bad packet: %s\n", isc_result_totext(result));
3341 		hex_dump(b);
3342 		query->waiting_connect = ISC_FALSE;
3343 		dns_message_destroy(&msg);
3344 		isc_event_free(&event);
3345 		clear_query(query);
3346 		cancel_lookup(l);
3347 		check_next_lookup(l);
3348 		UNLOCK_LOOKUP;
3349 		return;
3350 	}
3351 	if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3352 		match = ISC_TRUE;
3353 		for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3354 		     result == ISC_R_SUCCESS && match;
3355 		     result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3356 			dns_name_t *name = NULL;
3357 			dns_rdataset_t *rdataset;
3358 
3359 			dns_message_currentname(msg, DNS_SECTION_QUESTION,
3360 						&name);
3361 			for (rdataset = ISC_LIST_HEAD(name->list);
3362 			     rdataset != NULL;
3363 			     rdataset = ISC_LIST_NEXT(rdataset, link)) {
3364 				if (l->rdtype != rdataset->type ||
3365 				    l->rdclass != rdataset->rdclass ||
3366 				    !dns_name_equal(l->name, name)) {
3367 					char namestr[DNS_NAME_FORMATSIZE];
3368 					char typebuf[DNS_RDATATYPE_FORMATSIZE];
3369 					char classbuf[DNS_RDATACLASS_FORMATSIZE];
3370 					dns_name_format(name, namestr,
3371 							sizeof(namestr));
3372 					dns_rdatatype_format(rdataset->type,
3373 							     typebuf,
3374 							     sizeof(typebuf));
3375 					dns_rdataclass_format(rdataset->rdclass,
3376 							      classbuf,
3377 							      sizeof(classbuf));
3378 					printf(";; Question section mismatch: "
3379 					       "got %s/%s/%s\n",
3380 					       namestr, typebuf, classbuf);
3381 					match = ISC_FALSE;
3382 				}
3383 			}
3384 		}
3385 		if (!match) {
3386 			dns_message_destroy(&msg);
3387 			if (l->tcp_mode) {
3388 				isc_event_free(&event);
3389 				clear_query(query);
3390 				check_next_lookup(l);
3391 				UNLOCK_LOOKUP;
3392 				return;
3393 			} else
3394 				goto udp_mismatch;
3395 		}
3396 	}
3397 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3398 	    !l->ignore && !l->tcp_mode) {
3399 		printf(";; Truncated, retrying in TCP mode.\n");
3400 		n = requeue_lookup(l, ISC_TRUE);
3401 		n->tcp_mode = ISC_TRUE;
3402 		n->origin = query->lookup->origin;
3403 		if (l->trace && l->trace_root)
3404 			n->rdtype = l->qrdtype;
3405 		dns_message_destroy(&msg);
3406 		isc_event_free(&event);
3407 		clear_query(query);
3408 		cancel_lookup(l);
3409 		check_next_lookup(l);
3410 		UNLOCK_LOOKUP;
3411 		return;
3412 	}
3413 	if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3414 	    (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3415 	{
3416 		dig_query_t *next = ISC_LIST_NEXT(query, link);
3417 		if (l->current_query == query)
3418 			l->current_query = NULL;
3419 		if (next != NULL) {
3420 			debug("sending query %p\n", next);
3421 			if (l->tcp_mode)
3422 				send_tcp_connect(next);
3423 			else
3424 				send_udp(next);
3425 		}
3426 		/*
3427 		 * If our query is at the head of the list and there
3428 		 * is no next, we're the only one left, so fall
3429 		 * through to print the message.
3430 		 */
3431 		if ((ISC_LIST_HEAD(l->q) != query) ||
3432 		    (ISC_LIST_NEXT(query, link) != NULL)) {
3433 			if( l->comments == ISC_TRUE )
3434 				printf(";; Got %s from %s, "
3435 				       "trying next server\n",
3436 				       msg->rcode == dns_rcode_servfail ?
3437 				       "SERVFAIL reply" :
3438 				       "recursion not available",
3439 				       query->servname);
3440 			clear_query(query);
3441 			check_next_lookup(l);
3442 			dns_message_destroy(&msg);
3443 			isc_event_free(&event);
3444 			UNLOCK_LOOKUP;
3445 			return;
3446 		}
3447 	}
3448 
3449 	if (key != NULL) {
3450 		result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
3451 		if (result != ISC_R_SUCCESS) {
3452 			printf(";; Couldn't verify signature: %s\n",
3453 			       isc_result_totext(result));
3454 			validated = ISC_FALSE;
3455 		}
3456 		l->tsigctx = msg->tsigctx;
3457 		msg->tsigctx = NULL;
3458 		if (l->querysig != NULL) {
3459 			debug("freeing querysig buffer %p", l->querysig);
3460 			isc_buffer_free(&l->querysig);
3461 		}
3462 		result = dns_message_getquerytsig(msg, mctx, &l->querysig);
3463 		check_result(result,"dns_message_getquerytsig");
3464 	}
3465 
3466 	extrabytes = isc_buffer_remaininglength(b);
3467 
3468 	debug("after parse");
3469 	if (l->doing_xfr && l->xfr_q == NULL) {
3470 		l->xfr_q = query;
3471 		/*
3472 		 * Once we are in the XFR message, increase
3473 		 * the timeout to much longer, so brief network
3474 		 * outages won't cause the XFR to abort
3475 		 */
3476 		if (timeout != INT_MAX && l->timer != NULL) {
3477 			unsigned int local_timeout;
3478 
3479 			if (timeout == 0) {
3480 				if (l->tcp_mode)
3481 					local_timeout = TCP_TIMEOUT * 4;
3482 				else
3483 					local_timeout = UDP_TIMEOUT * 4;
3484 			} else {
3485 				if (timeout < (INT_MAX / 4))
3486 					local_timeout = timeout * 4;
3487 				else
3488 					local_timeout = INT_MAX;
3489 			}
3490 			debug("have local timeout of %d", local_timeout);
3491 			isc_interval_set(&l->interval, local_timeout, 0);
3492 			result = isc_timer_reset(l->timer,
3493 						 isc_timertype_once,
3494 						 NULL,
3495 						 &l->interval,
3496 						 ISC_FALSE);
3497 			check_result(result, "isc_timer_reset");
3498 		}
3499 	}
3500 
3501 	if (!l->doing_xfr || l->xfr_q == query) {
3502 		if (msg->rcode == dns_rcode_nxdomain &&
3503 		    (l->origin != NULL || l->need_search)) {
3504 			if (!next_origin(query->lookup) || showsearch) {
3505 				printmessage(query, msg, ISC_TRUE);
3506 				received(b->used, &sevent->address, query);
3507 			}
3508 		} else if (!l->trace && !l->ns_search_only) {
3509 #ifdef DIG_SIGCHASE
3510 			if (!do_sigchase)
3511 #endif
3512 				printmessage(query, msg, ISC_TRUE);
3513 		} else if (l->trace) {
3514 			int nl = 0;
3515 			int count = msg->counts[DNS_SECTION_ANSWER];
3516 
3517 			debug("in TRACE code");
3518 			if (!l->ns_search_only)
3519 				printmessage(query, msg, ISC_TRUE);
3520 
3521 			l->rdtype = l->qrdtype;
3522 			if (l->trace_root || (l->ns_search_only && count > 0)) {
3523 				if (!l->trace_root)
3524 					l->rdtype = dns_rdatatype_soa;
3525 				nl = followup_lookup(msg, query,
3526 						     DNS_SECTION_ANSWER);
3527 				l->trace_root = ISC_FALSE;
3528 			} else if (count == 0)
3529 				nl = followup_lookup(msg, query,
3530 						     DNS_SECTION_AUTHORITY);
3531 			if (nl == 0)
3532 				docancel = ISC_TRUE;
3533 		} else {
3534 			debug("in NSSEARCH code");
3535 
3536 			if (l->trace_root) {
3537 				/*
3538 				 * This is the initial NS query.
3539 				 */
3540 				int nl;
3541 
3542 				l->rdtype = dns_rdatatype_soa;
3543 				nl = followup_lookup(msg, query,
3544 						     DNS_SECTION_ANSWER);
3545 				if (nl == 0)
3546 					docancel = ISC_TRUE;
3547 				l->trace_root = ISC_FALSE;
3548 				usesearch = ISC_FALSE;
3549 			} else
3550 #ifdef DIG_SIGCHASE
3551 				if (!do_sigchase)
3552 #endif
3553 				printmessage(query, msg, ISC_TRUE);
3554 		}
3555 #ifdef DIG_SIGCHASE
3556 		if (do_sigchase) {
3557 			chase_msg = isc_mem_allocate(mctx,
3558 						     sizeof(dig_message_t));
3559 			if (chase_msg == NULL) {
3560 				fatal("Memory allocation failure in %s:%d",
3561 				      __FILE__, __LINE__);
3562 			}
3563 			ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
3564 					       link);
3565 			if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3566 					       &msg_temp) != ISC_R_SUCCESS) {
3567 				fatal("dns_message_create in %s:%d",
3568 				      __FILE__, __LINE__);
3569 			}
3570 
3571 			isc_buffer_usedregion(b, &r);
3572 			result = isc_buffer_allocate(mctx, &buf, r.length);
3573 
3574 			check_result(result, "isc_buffer_allocate");
3575 			result =  isc_buffer_copyregion(buf, &r);
3576 			check_result(result, "isc_buffer_copyregion");
3577 
3578 			result =  dns_message_parse(msg_temp, buf, 0);
3579 
3580 			isc_buffer_free(&buf);
3581 			chase_msg->msg = msg_temp;
3582 
3583 			chase_msg2 = isc_mem_allocate(mctx,
3584 						      sizeof(dig_message_t));
3585 			if (chase_msg2 == NULL) {
3586 				fatal("Memory allocation failure in %s:%d",
3587 				      __FILE__, __LINE__);
3588 			}
3589 			ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
3590 					       link);
3591 			chase_msg2->msg = msg;
3592 		}
3593 #endif
3594 	}
3595 
3596 #ifdef DIG_SIGCHASE
3597 	if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
3598 		sigchase(msg_temp);
3599 	}
3600 #endif
3601 
3602 	if (l->pending)
3603 		debug("still pending.");
3604 	if (l->doing_xfr) {
3605 		if (query != l->xfr_q) {
3606 			dns_message_destroy(&msg);
3607 			isc_event_free(&event);
3608 			query->waiting_connect = ISC_FALSE;
3609 			UNLOCK_LOOKUP;
3610 			return;
3611 		}
3612 		if (!docancel)
3613 			docancel = check_for_more_data(query, msg, sevent);
3614 		if (docancel) {
3615 			dns_message_destroy(&msg);
3616 			clear_query(query);
3617 			cancel_lookup(l);
3618 			check_next_lookup(l);
3619 		}
3620 	} else {
3621 
3622 		if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3623 
3624 #ifdef DIG_SIGCHASE
3625 			if (!l->sigchase)
3626 #endif
3627 				received(b->used, &sevent->address, query);
3628 		}
3629 
3630 		if (!query->lookup->ns_search_only)
3631 			query->lookup->pending = ISC_FALSE;
3632 		if (!query->lookup->ns_search_only ||
3633 		    query->lookup->trace_root || docancel) {
3634 #ifdef DIG_SIGCHASE
3635 			if (!do_sigchase)
3636 #endif
3637 				dns_message_destroy(&msg);
3638 
3639 			cancel_lookup(l);
3640 		}
3641 		clear_query(query);
3642 		check_next_lookup(l);
3643 	}
3644 	if (msg != NULL) {
3645 #ifdef DIG_SIGCHASE
3646 		if (do_sigchase)
3647 			msg = NULL;
3648 		else
3649 #endif
3650 			dns_message_destroy(&msg);
3651 	}
3652 	isc_event_free(&event);
3653 	UNLOCK_LOOKUP;
3654 	return;
3655 
3656  udp_mismatch:
3657 	isc_buffer_invalidate(&query->recvbuf);
3658 	isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3659 	ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3660 	result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3661 				  global_task, recv_done, query);
3662 	check_result(result, "isc_socket_recvv");
3663 	recvcount++;
3664 	isc_event_free(&event);
3665 	UNLOCK_LOOKUP;
3666 	return;
3667 }
3668 
3669 /*%
3670  * Turn a name into an address, using system-supplied routines.  This is
3671  * used in looking up server names, etc... and needs to use system-supplied
3672  * routines, since they may be using a non-DNS system for these lookups.
3673  */
3674 isc_result_t
get_address(char * host,in_port_t myport,isc_sockaddr_t * sockaddr)3675 get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
3676 	int count;
3677 	isc_result_t result;
3678 	isc_boolean_t is_running;
3679 
3680 	is_running = isc_app_isrunning();
3681 	if (is_running)
3682 		isc_app_block();
3683 	result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
3684 	if (is_running)
3685 		isc_app_unblock();
3686 	if (result != ISC_R_SUCCESS)
3687 		return (result);
3688 
3689 	INSIST(count == 1);
3690 
3691 	return (ISC_R_SUCCESS);
3692 }
3693 
3694 int
getaddresses(dig_lookup_t * lookup,const char * host,isc_result_t * resultp)3695 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3696 	isc_result_t result;
3697 	isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
3698 	isc_netaddr_t netaddr;
3699 	int count, i;
3700 	dig_server_t *srv;
3701 	char tmp[ISC_NETADDR_FORMATSIZE];
3702 
3703 	result = bind9_getaddresses(host, 0, sockaddrs,
3704 				    DIG_MAX_ADDRESSES, &count);
3705 	if (resultp != NULL)
3706 		*resultp = result;
3707 	if (result != ISC_R_SUCCESS) {
3708 		if (resultp == NULL)
3709 			fatal("couldn't get address for '%s': %s",
3710 			      host, isc_result_totext(result));
3711 		return 0;
3712 	}
3713 
3714 	for (i = 0; i < count; i++) {
3715 		isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
3716 		isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
3717 		srv = make_server(tmp, host);
3718 		ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3719 	}
3720 
3721 	return count;
3722 }
3723 
3724 /*%
3725  * Initiate either a TCP or UDP lookup
3726  */
3727 void
do_lookup(dig_lookup_t * lookup)3728 do_lookup(dig_lookup_t *lookup) {
3729 	dig_query_t *query;
3730 
3731 	REQUIRE(lookup != NULL);
3732 
3733 	debug("do_lookup()");
3734 	lookup->pending = ISC_TRUE;
3735 	query = ISC_LIST_HEAD(lookup->q);
3736 	if (query != NULL) {
3737 		if (lookup->tcp_mode)
3738 			send_tcp_connect(query);
3739 		else
3740 			send_udp(query);
3741 	}
3742 }
3743 
3744 /*%
3745  * Start everything in action upon task startup.
3746  */
3747 void
onrun_callback(isc_task_t * task,isc_event_t * event)3748 onrun_callback(isc_task_t *task, isc_event_t *event) {
3749 	UNUSED(task);
3750 
3751 	isc_event_free(&event);
3752 	LOCK_LOOKUP;
3753 	start_lookup();
3754 	UNLOCK_LOOKUP;
3755 }
3756 
3757 /*%
3758  * Make everything on the lookup queue go away.  Mainly used by the
3759  * SIGINT handler.
3760  */
3761 void
cancel_all(void)3762 cancel_all(void) {
3763 	dig_lookup_t *l, *n;
3764 	dig_query_t *q, *nq;
3765 
3766 	debug("cancel_all()");
3767 
3768 	LOCK_LOOKUP;
3769 	if (free_now) {
3770 		UNLOCK_LOOKUP;
3771 		return;
3772 	}
3773 	cancel_now = ISC_TRUE;
3774 	if (current_lookup != NULL) {
3775 		if (current_lookup->timer != NULL)
3776 			isc_timer_detach(&current_lookup->timer);
3777 		for (q = ISC_LIST_HEAD(current_lookup->q);
3778 		     q != NULL;
3779 		     q = nq)
3780 		{
3781 			nq = ISC_LIST_NEXT(q, link);
3782 			debug("canceling pending query %p, belonging to %p",
3783 			      q, current_lookup);
3784 			if (q->sock != NULL)
3785 				isc_socket_cancel(q->sock, NULL,
3786 						  ISC_SOCKCANCEL_ALL);
3787 			else
3788 				clear_query(q);
3789 		}
3790 		for (q = ISC_LIST_HEAD(current_lookup->connecting);
3791 		     q != NULL;
3792 		     q = nq)
3793 		{
3794 			nq = ISC_LIST_NEXT(q, clink);
3795 			debug("canceling connecting query %p, belonging to %p",
3796 			      q, current_lookup);
3797 			if (q->sock != NULL)
3798 				isc_socket_cancel(q->sock, NULL,
3799 						  ISC_SOCKCANCEL_ALL);
3800 			else
3801 				clear_query(q);
3802 		}
3803 	}
3804 	l = ISC_LIST_HEAD(lookup_list);
3805 	while (l != NULL) {
3806 		n = ISC_LIST_NEXT(l, link);
3807 		ISC_LIST_DEQUEUE(lookup_list, l, link);
3808 		try_clear_lookup(l);
3809 		l = n;
3810 	}
3811 	UNLOCK_LOOKUP;
3812 }
3813 
3814 /*%
3815  * Destroy all of the libs we are using, and get everything ready for a
3816  * clean shutdown.
3817  */
3818 void
destroy_libs(void)3819 destroy_libs(void) {
3820 #ifdef DIG_SIGCHASE
3821 	void * ptr;
3822 	dig_message_t *chase_msg;
3823 #endif
3824 #ifdef WITH_IDN
3825 	isc_result_t result;
3826 #endif
3827 
3828 	if (keep != NULL)
3829 		isc_socket_detach(&keep);
3830 	debug("destroy_libs()");
3831 	if (global_task != NULL) {
3832 		debug("freeing task");
3833 		isc_task_detach(&global_task);
3834 	}
3835 	/*
3836 	 * The taskmgr_destroy() call blocks until all events are cleared
3837 	 * from the task.
3838 	 */
3839 	if (taskmgr != NULL) {
3840 		debug("freeing taskmgr");
3841 		isc_taskmgr_destroy(&taskmgr);
3842 	}
3843 	LOCK_LOOKUP;
3844 	REQUIRE(sockcount == 0);
3845 	REQUIRE(recvcount == 0);
3846 	REQUIRE(sendcount == 0);
3847 
3848 	INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3849 	INSIST(current_lookup == NULL);
3850 	INSIST(!free_now);
3851 
3852 	free_now = ISC_TRUE;
3853 
3854 	lwres_conf_clear(lwctx);
3855 	lwres_context_destroy(&lwctx);
3856 
3857 	flush_server_list();
3858 
3859 	clear_searchlist();
3860 
3861 #ifdef WITH_IDN
3862 	result = dns_name_settotextfilter(NULL);
3863 	check_result(result, "dns_name_settotextfilter");
3864 #endif
3865 	dns_name_destroy();
3866 
3867 	if (commctx != NULL) {
3868 		debug("freeing commctx");
3869 		isc_mempool_destroy(&commctx);
3870 	}
3871 	if (socketmgr != NULL) {
3872 		debug("freeing socketmgr");
3873 		isc_socketmgr_destroy(&socketmgr);
3874 	}
3875 	if (timermgr != NULL) {
3876 		debug("freeing timermgr");
3877 		isc_timermgr_destroy(&timermgr);
3878 	}
3879 	if (key != NULL) {
3880 		debug("freeing key %p", key);
3881 		dns_tsigkey_detach(&key);
3882 	}
3883 	if (namebuf != NULL)
3884 		isc_buffer_free(&namebuf);
3885 
3886 	if (is_dst_up) {
3887 		debug("destroy DST lib");
3888 		dst_lib_destroy();
3889 		is_dst_up = ISC_FALSE;
3890 	}
3891 	if (entp != NULL) {
3892 		debug("detach from entropy");
3893 		isc_entropy_detach(&entp);
3894 	}
3895 
3896 	UNLOCK_LOOKUP;
3897 	DESTROYLOCK(&lookup_lock);
3898 #ifdef DIG_SIGCHASE
3899 
3900 	debug("Destroy the messages kept for sigchase");
3901 	/* Destroy the messages kept for sigchase */
3902 	chase_msg = ISC_LIST_HEAD(chase_message_list);
3903 
3904 	while (chase_msg != NULL) {
3905 		INSIST(chase_msg->msg != NULL);
3906 		dns_message_destroy(&(chase_msg->msg));
3907 		ptr = chase_msg;
3908 		chase_msg = ISC_LIST_NEXT(chase_msg, link);
3909 		isc_mem_free(mctx, ptr);
3910 	}
3911 
3912 	chase_msg = ISC_LIST_HEAD(chase_message_list2);
3913 
3914 	while (chase_msg != NULL) {
3915 		INSIST(chase_msg->msg != NULL);
3916 		dns_message_destroy(&(chase_msg->msg));
3917 		ptr = chase_msg;
3918 		chase_msg = ISC_LIST_NEXT(chase_msg, link);
3919 		isc_mem_free(mctx, ptr);
3920 	}
3921 	if (dns_name_dynamic(&chase_name))
3922 		free_name(&chase_name);
3923 #if DIG_SIGCHASE_TD
3924 	if (dns_name_dynamic(&chase_current_name))
3925 		free_name(&chase_current_name);
3926 	if (dns_name_dynamic(&chase_authority_name))
3927 		free_name(&chase_authority_name);
3928 #endif
3929 #if DIG_SIGCHASE_BU
3930 	if (dns_name_dynamic(&chase_signame))
3931 		free_name(&chase_signame);
3932 #endif
3933 
3934 #endif
3935 	debug("Removing log context");
3936 	isc_log_destroy(&lctx);
3937 
3938 	debug("Destroy memory");
3939 	if (memdebugging != 0)
3940 		isc_mem_stats(mctx, stderr);
3941 	if (mctx != NULL)
3942 		isc_mem_destroy(&mctx);
3943 }
3944 
3945 #ifdef WITH_IDN
3946 static void
initialize_idn(void)3947 initialize_idn(void) {
3948 	idn_result_t r;
3949 	isc_result_t result;
3950 
3951 #ifdef HAVE_SETLOCALE
3952 	/* Set locale */
3953 	(void)setlocale(LC_ALL, "");
3954 #endif
3955 	/* Create configuration context. */
3956 	r = idn_nameinit(1);
3957 	if (r != idn_success)
3958 		fatal("idn api initialization failed: %s",
3959 		      idn_result_tostring(r));
3960 
3961 	/* Set domain name -> text post-conversion filter. */
3962 	result = dns_name_settotextfilter(output_filter);
3963 	check_result(result, "dns_name_settotextfilter");
3964 }
3965 
3966 static isc_result_t
output_filter(isc_buffer_t * buffer,unsigned int used_org,isc_boolean_t absolute)3967 output_filter(isc_buffer_t *buffer, unsigned int used_org,
3968 	      isc_boolean_t absolute)
3969 {
3970 	char tmp1[MAXDLEN], tmp2[MAXDLEN];
3971 	size_t fromlen, tolen;
3972 	isc_boolean_t end_with_dot;
3973 
3974 	/*
3975 	 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3976 	 * if 'absolute' is true, and terminate with NUL.
3977 	 */
3978 	fromlen = isc_buffer_usedlength(buffer) - used_org;
3979 	if (fromlen >= MAXDLEN)
3980 		return (ISC_R_SUCCESS);
3981 	memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
3982 	end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
3983 	if (absolute && !end_with_dot) {
3984 		fromlen++;
3985 		if (fromlen >= MAXDLEN)
3986 			return (ISC_R_SUCCESS);
3987 		tmp1[fromlen - 1] = '.';
3988 	}
3989 	tmp1[fromlen] = '\0';
3990 
3991 	/*
3992 	 * Convert contents of 'tmp1' to local encoding.
3993 	 */
3994 	if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
3995 		return (ISC_R_SUCCESS);
3996 	strcpy(tmp1, tmp2);
3997 
3998 	/*
3999 	 * Copy the converted contents in 'tmp1' back to 'buffer'.
4000 	 * If we have appended trailing dot, remove it.
4001 	 */
4002 	tolen = strlen(tmp1);
4003 	if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
4004 		tolen--;
4005 
4006 	if (isc_buffer_length(buffer) < used_org + tolen)
4007 		return (ISC_R_NOSPACE);
4008 
4009 	isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
4010 	memmove(isc_buffer_used(buffer), tmp1, tolen);
4011 	isc_buffer_add(buffer, (unsigned int)tolen);
4012 
4013 	return (ISC_R_SUCCESS);
4014 }
4015 
4016 static idn_result_t
append_textname(char * name,const char * origin,size_t namesize)4017 append_textname(char *name, const char *origin, size_t namesize) {
4018 	size_t namelen = strlen(name);
4019 	size_t originlen = strlen(origin);
4020 
4021 	/* Already absolute? */
4022 	if (namelen > 0 && name[namelen - 1] == '.')
4023 		return idn_success;
4024 
4025 	/* Append dot and origin */
4026 
4027 	if (namelen + 1 + originlen >= namesize)
4028 		return idn_buffer_overflow;
4029 
4030 	if (*origin != '.')
4031 		name[namelen++] = '.';
4032 	(void)strcpy(name + namelen, origin);
4033 	return idn_success;
4034 }
4035 
4036 static void
idn_check_result(idn_result_t r,const char * msg)4037 idn_check_result(idn_result_t r, const char *msg) {
4038 	if (r != idn_success) {
4039 		exitcode = 1;
4040 		fatal("%s: %s", msg, idn_result_tostring(r));
4041 	}
4042 }
4043 #endif /* WITH_IDN */
4044 
4045 #ifdef DIG_SIGCHASE
4046 void
print_type(dns_rdatatype_t type)4047 print_type(dns_rdatatype_t type)
4048 {
4049 	isc_buffer_t * b = NULL;
4050 	isc_result_t result;
4051 	isc_region_t r;
4052 
4053 	result = isc_buffer_allocate(mctx, &b, 4000);
4054 	check_result(result, "isc_buffer_allocate");
4055 
4056 	result = dns_rdatatype_totext(type, b);
4057 	check_result(result, "print_type");
4058 
4059 	isc_buffer_usedregion(b, &r);
4060 	r.base[r.length] = '\0';
4061 
4062 	printf("%s", r.base);
4063 
4064 	isc_buffer_free(&b);
4065 }
4066 
4067 void
dump_database_section(dns_message_t * msg,int section)4068 dump_database_section(dns_message_t *msg, int section)
4069 {
4070 	dns_name_t *msg_name=NULL;
4071 
4072 	dns_rdataset_t *rdataset;
4073 
4074 	do {
4075 		dns_message_currentname(msg, section, &msg_name);
4076 
4077 		for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
4078 		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
4079 			dns_name_print(msg_name, stdout);
4080 			printf("\n");
4081 			print_rdataset(msg_name, rdataset);
4082 			printf("end\n");
4083 		}
4084 		msg_name = NULL;
4085 	} while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4086 }
4087 
4088 void
dump_database(void)4089 dump_database(void) {
4090 	dig_message_t * msg;
4091 
4092 	for (msg = ISC_LIST_HEAD(chase_message_list);  msg != NULL;
4093 	     msg = ISC_LIST_NEXT(msg, link)) {
4094 		if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4095 		    == ISC_R_SUCCESS)
4096 			dump_database_section(msg->msg, DNS_SECTION_ANSWER);
4097 
4098 		if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4099 		    == ISC_R_SUCCESS)
4100 			dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
4101 
4102 		if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4103 		    == ISC_R_SUCCESS)
4104 			dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
4105 	}
4106 }
4107 
4108 
4109 dns_rdataset_t *
search_type(dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers)4110 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
4111 	dns_rdataset_t *rdataset;
4112 	dns_rdata_sig_t siginfo;
4113 	dns_rdata_t sigrdata = DNS_RDATA_INIT;
4114 	isc_result_t result;
4115 
4116 	for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
4117 	     rdataset = ISC_LIST_NEXT(rdataset, link)) {
4118 		if (type == dns_rdatatype_any) {
4119 			if (rdataset->type != dns_rdatatype_rrsig)
4120 				return (rdataset);
4121 		} else if ((type == dns_rdatatype_rrsig) &&
4122 			   (rdataset->type == dns_rdatatype_rrsig)) {
4123 			result = dns_rdataset_first(rdataset);
4124 			check_result(result, "empty rdataset");
4125 			dns_rdataset_current(rdataset, &sigrdata);
4126 			result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4127 			check_result(result, "sigrdata tostruct siginfo");
4128 
4129 			if ((siginfo.covered == covers) ||
4130 			    (covers == dns_rdatatype_any)) {
4131 				dns_rdata_reset(&sigrdata);
4132 				dns_rdata_freestruct(&siginfo);
4133 				return (rdataset);
4134 			}
4135 			dns_rdata_reset(&sigrdata);
4136 			dns_rdata_freestruct(&siginfo);
4137 		} else if (rdataset->type == type)
4138 			return (rdataset);
4139 	}
4140 	return (NULL);
4141 }
4142 
4143 dns_rdataset_t *
chase_scanname_section(dns_message_t * msg,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,int section)4144 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
4145 		       dns_rdatatype_t type, dns_rdatatype_t covers,
4146 		       int section)
4147 {
4148 	dns_rdataset_t *rdataset;
4149 	dns_name_t *msg_name = NULL;
4150 
4151 	if (msg->counts[section] == 0)
4152 		return (NULL);
4153 
4154 	do {
4155 		dns_message_currentname(msg, section, &msg_name);
4156 		if (dns_name_compare(msg_name, name) == 0) {
4157 			rdataset = search_type(msg_name, type, covers);
4158 			if (rdataset != NULL)
4159 				return (rdataset);
4160 		}
4161 		msg_name = NULL;
4162 	} while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4163 
4164 	return (NULL);
4165 }
4166 
4167 
4168 dns_rdataset_t *
chase_scanname(dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers)4169 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
4170 {
4171 	dns_rdataset_t *rdataset = NULL;
4172 	dig_message_t * msg;
4173 
4174 	for (msg = ISC_LIST_HEAD(chase_message_list2);  msg != NULL;
4175 	     msg = ISC_LIST_NEXT(msg, link)) {
4176 		if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4177 		    == ISC_R_SUCCESS)
4178 			rdataset = chase_scanname_section(msg->msg, name,
4179 							  type, covers,
4180 							  DNS_SECTION_ANSWER);
4181 			if (rdataset != NULL)
4182 				return (rdataset);
4183 		if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4184 		    == ISC_R_SUCCESS)
4185 			rdataset =
4186 				chase_scanname_section(msg->msg, name,
4187 						       type, covers,
4188 						       DNS_SECTION_AUTHORITY);
4189 			if (rdataset != NULL)
4190 				return (rdataset);
4191 		if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4192 		    == ISC_R_SUCCESS)
4193 			rdataset =
4194 				chase_scanname_section(msg->msg, name, type,
4195 						       covers,
4196 						       DNS_SECTION_ADDITIONAL);
4197 			if (rdataset != NULL)
4198 				return (rdataset);
4199 	}
4200 
4201 	return (NULL);
4202 }
4203 
4204 dns_rdataset_t *
sigchase_scanname(dns_rdatatype_t type,dns_rdatatype_t covers,isc_boolean_t * lookedup,dns_name_t * rdata_name)4205 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
4206 		  isc_boolean_t * lookedup, dns_name_t *rdata_name)
4207 {
4208 	dig_lookup_t *lookup;
4209 	isc_buffer_t *b = NULL;
4210 	isc_region_t r;
4211 	isc_result_t result;
4212 	dns_rdataset_t * temp;
4213 	dns_rdatatype_t querytype;
4214 
4215 	temp = chase_scanname(rdata_name, type, covers);
4216 	if (temp != NULL)
4217 		return (temp);
4218 
4219 	if (*lookedup == ISC_TRUE)
4220 		return (NULL);
4221 
4222 	lookup = clone_lookup(current_lookup, ISC_TRUE);
4223 	lookup->trace_root = ISC_FALSE;
4224 	lookup->new_search = ISC_TRUE;
4225 
4226 	result = isc_buffer_allocate(mctx, &b, BUFSIZE);
4227 	check_result(result, "isc_buffer_allocate");
4228 	result = dns_name_totext(rdata_name, ISC_FALSE, b);
4229 	check_result(result, "dns_name_totext");
4230 	isc_buffer_usedregion(b, &r);
4231 	r.base[r.length] = '\0';
4232 	strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
4233 	isc_buffer_free(&b);
4234 
4235 	if (type ==  dns_rdatatype_rrsig)
4236 		querytype = covers;
4237 	else
4238 		querytype = type;
4239 
4240 	if (querytype == 0 || querytype == 255) {
4241 		printf("Error in the queried type: %d\n", querytype);
4242 		return (NULL);
4243 	}
4244 
4245 	lookup->rdtype = querytype;
4246 	lookup->rdtypeset = ISC_TRUE;
4247 	lookup->qrdtype = querytype;
4248 	*lookedup = ISC_TRUE;
4249 
4250 	ISC_LIST_APPEND(lookup_list, lookup, link);
4251 	printf("\n\nLaunch a query to find a RRset of type ");
4252 	print_type(type);
4253 	printf(" for zone: %s\n", lookup->textname);
4254 	return (NULL);
4255 }
4256 
4257 isc_result_t
insert_trustedkey(void * arg,dns_name_t * name,dns_rdataset_t * rdataset)4258 insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
4259 {
4260 	isc_result_t result;
4261 	dst_key_t *dstkey;
4262 
4263 	UNUSED(arg);
4264 
4265 	if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
4266 		return (ISC_R_SUCCESS);
4267 
4268 	for (result = dns_rdataset_first(rdataset);
4269 	     result == ISC_R_SUCCESS;
4270 	     result = dns_rdataset_next(rdataset)) {
4271 		dns_rdata_t rdata = DNS_RDATA_INIT;
4272 		isc_buffer_t b;
4273 
4274 		dns_rdataset_current(rdataset, &rdata);
4275 		isc_buffer_init(&b, rdata.data, rdata.length);
4276 		isc_buffer_add(&b, rdata.length);
4277 		if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
4278 			return (ISC_R_SUCCESS);
4279 		dstkey = NULL;
4280 		result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &dstkey);
4281 		if (result != ISC_R_SUCCESS)
4282 			continue;
4283 		tk_list.key[tk_list.nb_tk++] = dstkey;
4284 	}
4285 	return (ISC_R_SUCCESS);
4286 }
4287 
4288 void
clean_trustedkey()4289 clean_trustedkey()
4290 {
4291 	int i = 0;
4292 
4293 	for (i= 0; i < MAX_TRUSTED_KEY; i++) {
4294 		if (tk_list.key[i] != NULL) {
4295 			dst_key_free(&tk_list.key[i]);
4296 			tk_list.key[i] = NULL;
4297 		} else
4298 			break;
4299 	}
4300 	tk_list.nb_tk = 0;
4301 	return;
4302 }
4303 
4304 char alphnum[] =
4305 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4306 
4307 isc_result_t
removetmpkey(const char * file)4308 removetmpkey(const char *file)
4309 {
4310 	char *tempnamekey = NULL;
4311 	int tempnamekeylen;
4312 	isc_result_t result;
4313 
4314 	tempnamekeylen = strlen(file)+10;
4315 
4316 	tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4317 	if (tempnamekey == NULL)
4318 		return (ISC_R_NOMEMORY);
4319 
4320 	memset(tempnamekey, 0, tempnamekeylen);
4321 
4322 	strcat(tempnamekey, file);
4323 	strcat(tempnamekey,".key");
4324 	isc_file_remove(tempnamekey);
4325 
4326 	result = isc_file_remove(tempnamekey);
4327 	isc_mem_free(mctx, tempnamekey);
4328 	return (result);
4329 }
4330 
4331 isc_result_t
get_trusted_key(void)4332 get_trusted_key(void) {
4333 	isc_result_t result;
4334 	const char *filename = NULL;
4335 	dns_rdatacallbacks_t callbacks;
4336 
4337 	result = isc_file_exists(trustedkey);
4338 	if (result !=  ISC_TRUE) {
4339 		result = isc_file_exists("/etc/trusted-key.key");
4340 		if (result !=  ISC_TRUE) {
4341 			result = isc_file_exists("./trusted-key.key");
4342 			if (result !=  ISC_TRUE)
4343 				return (ISC_R_FAILURE);
4344 			else
4345 				filename = "./trusted-key.key";
4346 		} else
4347 			filename = "/etc/trusted-key.key";
4348 	} else
4349 		filename = trustedkey;
4350 
4351 	if (filename == NULL) {
4352 		printf("No trusted key\n");
4353 		return (ISC_R_FAILURE);
4354 	}
4355 
4356 	dns_rdatacallbacks_init_stdio(&callbacks);
4357 	callbacks.add = insert_trustedkey;
4358 	return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
4359 				    current_lookup->rdclass, DNS_MASTER_NOTTL,
4360 				    &callbacks, mctx));
4361 }
4362 
4363 
4364 static void
nameFromString(const char * str,dns_name_t * p_ret)4365 nameFromString(const char *str, dns_name_t *p_ret) {
4366 	size_t len = strlen(str);
4367 	isc_result_t result;
4368 	isc_buffer_t buffer;
4369 	dns_fixedname_t fixedname;
4370 
4371 	REQUIRE(p_ret != NULL);
4372 	REQUIRE(str != NULL);
4373 
4374 	isc_buffer_constinit(&buffer, str, len);
4375 	isc_buffer_add(&buffer, len);
4376 
4377 	dns_fixedname_init(&fixedname);
4378 	result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
4379 				   dns_rootname, DNS_NAME_DOWNCASE, NULL);
4380 	check_result(result, "nameFromString");
4381 
4382 	if (dns_name_dynamic(p_ret))
4383 		free_name(p_ret);
4384 
4385 	result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
4386 	check_result(result, "nameFromString");
4387 }
4388 
4389 
4390 #if DIG_SIGCHASE_TD
4391 isc_result_t
prepare_lookup(dns_name_t * name)4392 prepare_lookup(dns_name_t *name)
4393 {
4394 	isc_result_t result;
4395 	dig_lookup_t *lookup = NULL;
4396 	dig_server_t *s;
4397 	void *ptr;
4398 
4399 	lookup = clone_lookup(current_lookup, ISC_TRUE);
4400 	lookup->trace_root = ISC_FALSE;
4401 	lookup->new_search = ISC_TRUE;
4402 	lookup->trace_root_sigchase = ISC_FALSE;
4403 
4404 	strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
4405 
4406 	lookup->rdtype = lookup->rdtype_sigchase;
4407 	lookup->rdtypeset = ISC_TRUE;
4408 	lookup->qrdtype = lookup->qrdtype_sigchase;
4409 
4410 	s = ISC_LIST_HEAD(lookup->my_server_list);
4411 	while (s != NULL) {
4412 		debug("freeing server %p belonging to %p",
4413 		      s, lookup);
4414 		ptr = s;
4415 		s = ISC_LIST_NEXT(s, link);
4416 		ISC_LIST_DEQUEUE(lookup->my_server_list,
4417 				 (dig_server_t *)ptr, link);
4418 		isc_mem_free(mctx, ptr);
4419 	}
4420 
4421 
4422 	for (result = dns_rdataset_first(chase_nsrdataset);
4423 	     result == ISC_R_SUCCESS;
4424 	     result = dns_rdataset_next(chase_nsrdataset)) {
4425 		char namestr[DNS_NAME_FORMATSIZE];
4426 		dns_rdata_ns_t ns;
4427 		dns_rdata_t rdata = DNS_RDATA_INIT;
4428 		dig_server_t * srv = NULL;
4429 #define __FOLLOW_GLUE__
4430 #ifdef __FOLLOW_GLUE__
4431 		isc_buffer_t *b = NULL;
4432 		isc_region_t r;
4433 		dns_rdataset_t *rdataset = NULL;
4434 		isc_boolean_t true = ISC_TRUE;
4435 #endif
4436 
4437 		memset(namestr, 0, DNS_NAME_FORMATSIZE);
4438 
4439 		dns_rdataset_current(chase_nsrdataset, &rdata);
4440 
4441 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
4442 		check_result(result, "dns_rdata_tostruct");
4443 
4444 #ifdef __FOLLOW_GLUE__
4445 
4446 		result = advanced_rrsearch(&rdataset, &ns.name,
4447 					   dns_rdatatype_aaaa,
4448 					   dns_rdatatype_any, &true);
4449 		if (result == ISC_R_SUCCESS) {
4450 			for (result = dns_rdataset_first(rdataset);
4451 			     result == ISC_R_SUCCESS;
4452 			     result = dns_rdataset_next(rdataset)) {
4453 				dns_rdata_t aaaa = DNS_RDATA_INIT;
4454 				dns_rdataset_current(rdataset, &aaaa);
4455 
4456 				result = isc_buffer_allocate(mctx, &b, 80);
4457 				check_result(result, "isc_buffer_allocate");
4458 
4459 				dns_rdata_totext(&aaaa, &ns.name, b);
4460 				isc_buffer_usedregion(b, &r);
4461 				r.base[r.length] = '\0';
4462 				strlcpy(namestr, (char*)r.base,
4463 					DNS_NAME_FORMATSIZE);
4464 				isc_buffer_free(&b);
4465 				dns_rdata_reset(&aaaa);
4466 
4467 
4468 				srv = make_server(namestr, namestr);
4469 
4470 				ISC_LIST_APPEND(lookup->my_server_list,
4471 						srv, link);
4472 			}
4473 		}
4474 
4475 		rdataset = NULL;
4476 		result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
4477 					   dns_rdatatype_any, &true);
4478 		if (result == ISC_R_SUCCESS) {
4479 			for (result = dns_rdataset_first(rdataset);
4480 			     result == ISC_R_SUCCESS;
4481 			     result = dns_rdataset_next(rdataset)) {
4482 				dns_rdata_t a = DNS_RDATA_INIT;
4483 				dns_rdataset_current(rdataset, &a);
4484 
4485 				result = isc_buffer_allocate(mctx, &b, 80);
4486 				check_result(result, "isc_buffer_allocate");
4487 
4488 				dns_rdata_totext(&a, &ns.name, b);
4489 				isc_buffer_usedregion(b, &r);
4490 				r.base[r.length] = '\0';
4491 				strlcpy(namestr, (char*)r.base,
4492 					DNS_NAME_FORMATSIZE);
4493 				isc_buffer_free(&b);
4494 				dns_rdata_reset(&a);
4495 				printf("ns name: %s\n", namestr);
4496 
4497 
4498 				srv = make_server(namestr, namestr);
4499 
4500 				ISC_LIST_APPEND(lookup->my_server_list,
4501 						srv, link);
4502 			}
4503 		}
4504 #else
4505 
4506 		dns_name_format(&ns.name, namestr, sizeof(namestr));
4507 		printf("ns name: ");
4508 		dns_name_print(&ns.name, stdout);
4509 		printf("\n");
4510 		srv = make_server(namestr, namestr);
4511 
4512 		ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4513 
4514 #endif
4515 		dns_rdata_freestruct(&ns);
4516 		dns_rdata_reset(&rdata);
4517 
4518 	}
4519 
4520 	ISC_LIST_APPEND(lookup_list, lookup, link);
4521 	printf("\nLaunch a query to find a RRset of type ");
4522 	print_type(lookup->rdtype);
4523 	printf(" for zone: %s", lookup->textname);
4524 	printf(" with nameservers:");
4525 	printf("\n");
4526 	print_rdataset(name, chase_nsrdataset);
4527 	return (ISC_R_SUCCESS);
4528 }
4529 
4530 
4531 isc_result_t
child_of_zone(dns_name_t * name,dns_name_t * zone_name,dns_name_t * child_name)4532 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
4533 	      dns_name_t * child_name)
4534 {
4535 	dns_namereln_t name_reln;
4536 	int orderp;
4537 	unsigned int nlabelsp;
4538 
4539 	name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
4540 	if (name_reln != dns_namereln_subdomain ||
4541 	    dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
4542 		printf("\n;; ERROR : ");
4543 		dns_name_print(name, stdout);
4544 		printf(" is not a subdomain of: ");
4545 		dns_name_print(zone_name, stdout);
4546 		printf(" FAILED\n\n");
4547 		return (ISC_R_FAILURE);
4548 	}
4549 
4550 	dns_name_getlabelsequence(name,
4551 				  dns_name_countlabels(name) -
4552 				  dns_name_countlabels(zone_name) -1,
4553 				  dns_name_countlabels(zone_name) +1,
4554 				  child_name);
4555 	return (ISC_R_SUCCESS);
4556 }
4557 
4558 isc_result_t
grandfather_pb_test(dns_name_t * zone_name,dns_rdataset_t * sigrdataset)4559 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t  *sigrdataset) {
4560 	dns_rdata_sig_t siginfo;
4561 	dns_rdataset_t mysigrdataset;
4562 	isc_result_t result;
4563 
4564 	dns_rdataset_init(&mysigrdataset);
4565 	dns_rdataset_clone(sigrdataset, &mysigrdataset);
4566 
4567 	result = dns_rdataset_first(&mysigrdataset);
4568 	check_result(result, "empty RRSIG dataset");
4569 
4570 	do {
4571 		dns_rdata_t sigrdata = DNS_RDATA_INIT;
4572 
4573 		dns_rdataset_current(&mysigrdataset, &sigrdata);
4574 
4575 		result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4576 		check_result(result, "sigrdata tostruct siginfo");
4577 
4578 		if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
4579 			result = ISC_R_SUCCESS;
4580 			goto cleanup;
4581 		}
4582 	} while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
4583 
4584 	result = ISC_R_FAILURE;
4585 cleanup:
4586 	dns_rdataset_disassociate(&mysigrdataset);
4587 
4588 	return (result);
4589 }
4590 
4591 
4592 isc_result_t
initialization(dns_name_t * name)4593 initialization(dns_name_t *name)
4594 {
4595 	isc_result_t   result;
4596 	isc_boolean_t  true = ISC_TRUE;
4597 
4598 	chase_nsrdataset = NULL;
4599 	result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
4600 				   dns_rdatatype_any, &true);
4601 	if (result != ISC_R_SUCCESS) {
4602 		printf("\n;; NS RRset is missing to continue validation:"
4603 		       " FAILED\n\n");
4604 		return (ISC_R_FAILURE);
4605 	}
4606 	INSIST(chase_nsrdataset != NULL);
4607 	prepare_lookup(name);
4608 
4609 	dup_name(name, &chase_current_name);
4610 
4611 	return (ISC_R_SUCCESS);
4612 }
4613 #endif
4614 
4615 void
print_rdataset(dns_name_t * name,dns_rdataset_t * rdataset)4616 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset)
4617 {
4618 	isc_buffer_t *b = NULL;
4619 	isc_result_t result;
4620 	isc_region_t r;
4621 
4622 	result = isc_buffer_allocate(mctx, &b, 9000);
4623 	check_result(result, "isc_buffer_allocate");
4624 
4625 	printrdataset(name, rdataset, b);
4626 
4627 	isc_buffer_usedregion(b, &r);
4628 	r.base[r.length] = '\0';
4629 
4630 
4631 	printf("%s\n", r.base);
4632 
4633 	isc_buffer_free(&b);
4634 }
4635 
4636 
4637 void
dup_name(dns_name_t * source,dns_name_t * target)4638 dup_name(dns_name_t *source, dns_name_t *target) {
4639 	isc_result_t result;
4640 
4641 	if (dns_name_dynamic(target))
4642 		free_name(target);
4643 	result = dns_name_dup(source, mctx, target);
4644 	check_result(result, "dns_name_dup");
4645 }
4646 
4647 void
free_name(dns_name_t * name)4648 free_name(dns_name_t *name) {
4649 	dns_name_free(name, mctx);
4650 	dns_name_init(name, NULL);
4651 }
4652 
4653 /*
4654  *
4655  * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4656  * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4657  * 			and the RRset is valid
4658  * return ISC_R_NOTFOUND if not contains trusted key
4659 			or if the RRset isn't valid
4660  * return ISC_R_FAILURE if problem
4661  *
4662  */
4663 isc_result_t
contains_trusted_key(dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)4664 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
4665 		     dns_rdataset_t *sigrdataset)
4666 {
4667 	dns_rdataset_t myrdataset;
4668 	dst_key_t *dnsseckey = NULL;
4669 	int i;
4670 	isc_result_t result;
4671 
4672 	if (name == NULL || rdataset == NULL)
4673 		return (ISC_R_FAILURE);
4674 
4675 	dns_rdataset_init(&myrdataset);
4676 	dns_rdataset_clone(rdataset, &myrdataset);
4677 
4678 	result = dns_rdataset_first(&myrdataset);
4679 	check_result(result, "empty rdataset");
4680 
4681 	do {
4682 		dns_rdata_t rdata = DNS_RDATA_INIT;
4683 
4684 		dns_rdataset_current(&myrdataset, &rdata);
4685 		INSIST(rdata.type == dns_rdatatype_dnskey);
4686 
4687 		result = dns_dnssec_keyfromrdata(name, &rdata,
4688 						 mctx, &dnsseckey);
4689 		check_result(result, "dns_dnssec_keyfromrdata");
4690 
4691 		for (i = 0; i < tk_list.nb_tk; i++) {
4692 			if (dst_key_compare(tk_list.key[i], dnsseckey)
4693 			    == ISC_TRUE) {
4694 				dns_rdata_reset(&rdata);
4695 
4696 				printf(";; Ok, find a Trusted Key in the "
4697 				       "DNSKEY RRset: %d\n",
4698 				       dst_key_id(dnsseckey));
4699 				result = sigchase_verify_sig_key(name, rdataset,
4700 								 dnsseckey,
4701 								 sigrdataset);
4702 				if (result == ISC_R_SUCCESS)
4703 					goto cleanup;
4704 			}
4705 		}
4706 		dst_key_free(&dnsseckey);
4707 	} while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS);
4708 
4709 	result = ISC_R_NOTFOUND;
4710 
4711 cleanup:
4712 	if (dnsseckey != NULL)
4713 		dst_key_free(&dnsseckey);
4714 	dns_rdataset_disassociate(&myrdataset);
4715 
4716 	return (result);
4717 }
4718 
4719 isc_result_t
sigchase_verify_sig(dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * keyrdataset,dns_rdataset_t * sigrdataset)4720 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
4721 		    dns_rdataset_t *keyrdataset,
4722 		    dns_rdataset_t *sigrdataset)
4723 {
4724 	dns_rdataset_t mykeyrdataset;
4725 	dst_key_t *dnsseckey = NULL;
4726 	isc_result_t result;
4727 
4728 	dns_rdataset_init(&mykeyrdataset);
4729 	dns_rdataset_clone(keyrdataset, &mykeyrdataset);
4730 
4731 	result = dns_rdataset_first(&mykeyrdataset);
4732 	check_result(result, "empty DNSKEY dataset");
4733 
4734 	do {
4735 		dns_rdata_t keyrdata = DNS_RDATA_INIT;
4736 
4737 		dns_rdataset_current(&mykeyrdataset, &keyrdata);
4738 		INSIST(keyrdata.type == dns_rdatatype_dnskey);
4739 
4740 		result = dns_dnssec_keyfromrdata(name, &keyrdata,
4741 						 mctx, &dnsseckey);
4742 		check_result(result, "dns_dnssec_keyfromrdata");
4743 
4744 		result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4745 						 sigrdataset);
4746 		if (result == ISC_R_SUCCESS)
4747 			goto cleanup;
4748 		dst_key_free(&dnsseckey);
4749 	} while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
4750 
4751 	result = ISC_R_NOTFOUND;
4752 
4753  cleanup:
4754 	if (dnsseckey != NULL)
4755 		dst_key_free(&dnsseckey);
4756 	dns_rdataset_disassociate(&mykeyrdataset);
4757 
4758 	return (result);
4759 }
4760 
4761 isc_result_t
sigchase_verify_sig_key(dns_name_t * name,dns_rdataset_t * rdataset,dst_key_t * dnsseckey,dns_rdataset_t * sigrdataset)4762 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
4763 			dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset)
4764 {
4765 	dns_rdata_sig_t siginfo;
4766 	dns_rdataset_t myrdataset;
4767 	dns_rdataset_t mysigrdataset;
4768 	isc_result_t result;
4769 
4770 	dns_rdataset_init(&myrdataset);
4771 	dns_rdataset_clone(rdataset, &myrdataset);
4772 	dns_rdataset_init(&mysigrdataset);
4773 	dns_rdataset_clone(sigrdataset, &mysigrdataset);
4774 
4775 	result = dns_rdataset_first(&mysigrdataset);
4776 	check_result(result, "empty RRSIG dataset");
4777 
4778 	do {
4779 		dns_rdata_t sigrdata = DNS_RDATA_INIT;
4780 
4781 		dns_rdataset_current(&mysigrdataset, &sigrdata);
4782 
4783 		result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4784 		check_result(result, "sigrdata tostruct siginfo");
4785 
4786 		/*
4787 		 * Test if the id of the DNSKEY is
4788 		 * the id of the DNSKEY signer's
4789 		 */
4790 		if (siginfo.keyid == dst_key_id(dnsseckey)) {
4791 
4792 			result = dns_rdataset_first(&myrdataset);
4793 			check_result(result, "empty DS dataset");
4794 
4795 			result = dns_dnssec_verify(name, &myrdataset, dnsseckey,
4796 						   ISC_FALSE, mctx, &sigrdata);
4797 
4798 			printf(";; VERIFYING ");
4799 			print_type(rdataset->type);
4800 			printf(" RRset for ");
4801 			dns_name_print(name, stdout);
4802 			printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
4803 			       isc_result_totext(result));
4804 
4805 			if (result == ISC_R_SUCCESS)
4806 				goto cleanup;
4807 		}
4808 	} while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
4809 
4810 	result = ISC_R_NOTFOUND;
4811 
4812  cleanup:
4813 	dns_rdataset_disassociate(&myrdataset);
4814 	dns_rdataset_disassociate(&mysigrdataset);
4815 
4816 	return (result);
4817 }
4818 
4819 
4820 isc_result_t
sigchase_verify_ds(dns_name_t * name,dns_rdataset_t * keyrdataset,dns_rdataset_t * dsrdataset)4821 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
4822 		   dns_rdataset_t *dsrdataset)
4823 {
4824 	dns_rdata_ds_t dsinfo;
4825 	dns_rdataset_t mydsrdataset;
4826 	dns_rdataset_t mykeyrdataset;
4827 	dst_key_t *dnsseckey = NULL;
4828 	isc_result_t result;
4829 	unsigned char dsbuf[DNS_DS_BUFFERSIZE];
4830 
4831 	dns_rdataset_init(&mydsrdataset);
4832 	dns_rdataset_clone(dsrdataset, &mydsrdataset);
4833 	dns_rdataset_init(&mykeyrdataset);
4834 	dns_rdataset_clone(keyrdataset, &mykeyrdataset);
4835 
4836 	result = dns_rdataset_first(&mydsrdataset);
4837 	check_result(result, "empty DSset dataset");
4838 	do {
4839 		dns_rdata_t dsrdata = DNS_RDATA_INIT;
4840 
4841 		dns_rdataset_current(&mydsrdataset, &dsrdata);
4842 
4843 		result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
4844 		check_result(result, "dns_rdata_tostruct for DS");
4845 
4846 		result = dns_rdataset_first(&mykeyrdataset);
4847 		check_result(result, "empty KEY dataset");
4848 
4849 		do {
4850 			dns_rdata_t keyrdata = DNS_RDATA_INIT;
4851 
4852 			dns_rdataset_current(&mykeyrdataset, &keyrdata);
4853 			INSIST(keyrdata.type == dns_rdatatype_dnskey);
4854 
4855 			result = dns_dnssec_keyfromrdata(name, &keyrdata,
4856 							 mctx, &dnsseckey);
4857 			check_result(result, "dns_dnssec_keyfromrdata");
4858 
4859 			/*
4860 			 * Test if the id of the DNSKEY is the
4861 			 * id of DNSKEY referenced by the DS
4862 			 */
4863 			if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
4864 				dns_rdata_t newdsrdata = DNS_RDATA_INIT;
4865 
4866 				result = dns_ds_buildrdata(name, &keyrdata,
4867 							   dsinfo.digest_type,
4868 							   dsbuf, &newdsrdata);
4869 				dns_rdata_freestruct(&dsinfo);
4870 
4871 				if (result != ISC_R_SUCCESS) {
4872 					printf("Oops: impossible to build"
4873 					       " new DS rdata\n");
4874 					goto cleanup;
4875 				}
4876 
4877 
4878 				if (dns_rdata_compare(&dsrdata,
4879 						      &newdsrdata) == 0) {
4880 					printf(";; OK a DS valids a DNSKEY"
4881 					       " in the RRset\n");
4882 					printf(";; Now verify that this"
4883 					       " DNSKEY validates the "
4884 					       "DNSKEY RRset\n");
4885 
4886 					result = sigchase_verify_sig_key(name,
4887 							 keyrdataset,
4888 							 dnsseckey,
4889 							 chase_sigkeyrdataset);
4890 					if (result ==  ISC_R_SUCCESS)
4891 						goto cleanup;
4892 				} else {
4893 					printf(";; This DS is NOT the DS for"
4894 					       " the chasing KEY: FAILED\n");
4895 				}
4896 			}
4897 			dst_key_free(&dnsseckey);
4898 		} while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
4899 	} while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS);
4900 
4901 	result = ISC_R_NOTFOUND;
4902 
4903  cleanup:
4904 	if (dnsseckey != NULL)
4905 		dst_key_free(&dnsseckey);
4906 	dns_rdataset_disassociate(&mydsrdataset);
4907 	dns_rdataset_disassociate(&mykeyrdataset);
4908 
4909 	return (result);
4910 }
4911 
4912 /*
4913  *
4914  * take a pointer on a rdataset in parameter and try to resolv it.
4915  * the searched rrset is a rrset on 'name' with type 'type'
4916  * (and if the type is a rrsig the signature cover 'covers').
4917  * the lookedup is to known if you have already done the query on the net.
4918  * ISC_R_SUCCESS: if we found the rrset
4919  * ISC_R_NOTFOUND: we do not found the rrset in cache
4920  * and we do a query on the net
4921  * ISC_R_FAILURE: rrset not found
4922  */
4923 isc_result_t
advanced_rrsearch(dns_rdataset_t ** rdataset,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,isc_boolean_t * lookedup)4924 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
4925 		  dns_rdatatype_t type, dns_rdatatype_t covers,
4926 		  isc_boolean_t *lookedup)
4927 {
4928 	isc_boolean_t  tmplookedup;
4929 
4930 	INSIST(rdataset != NULL);
4931 
4932 	if (*rdataset != NULL)
4933 		return (ISC_R_SUCCESS);
4934 
4935 	tmplookedup = *lookedup;
4936 	if ((*rdataset = sigchase_scanname(type, covers,
4937 					   lookedup, name)) == NULL) {
4938 		if (tmplookedup)
4939 			return (ISC_R_FAILURE);
4940 		return (ISC_R_NOTFOUND);
4941 	}
4942 	*lookedup = ISC_FALSE;
4943 	return (ISC_R_SUCCESS);
4944 }
4945 
4946 
4947 
4948 #if DIG_SIGCHASE_TD
4949 void
sigchase_td(dns_message_t * msg)4950 sigchase_td(dns_message_t *msg)
4951 {
4952 	isc_result_t result;
4953 	dns_name_t *name = NULL;
4954 	isc_boolean_t have_answer = ISC_FALSE;
4955 	isc_boolean_t true = ISC_TRUE;
4956 
4957 	if (msg->rcode != dns_rcode_noerror &&
4958 	    msg->rcode != dns_rcode_nxdomain) {
4959 		char buf[20];
4960 		isc_buffer_t b;
4961 
4962 		isc_buffer_init(&b, buf, sizeof(buf));
4963 		result = dns_rcode_totext(msg->rcode, &b);
4964 		check_result(result, "dns_rcode_totext failed");
4965 		printf("error response code %.*s\n",
4966 		       (int)isc_buffer_usedlength(&b), buf);
4967 		error_message = msg;
4968 		return;
4969 	}
4970 
4971 	if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4972 	    == ISC_R_SUCCESS) {
4973 		dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4974 		if (current_lookup->trace_root_sigchase) {
4975 			initialization(name);
4976 			return;
4977 		}
4978 		have_answer = true;
4979 	} else {
4980 		if (!current_lookup->trace_root_sigchase) {
4981 			result = dns_message_firstname(msg,
4982 						       DNS_SECTION_AUTHORITY);
4983 			if (result != ISC_R_SUCCESS) {
4984 				printf("no answer or authority section\n");
4985 				error_message = msg;
4986 				return;
4987 			}
4988 			dns_message_currentname(msg, DNS_SECTION_AUTHORITY,
4989 						&name);
4990 			chase_nsrdataset
4991 				= chase_scanname_section(msg, name,
4992 							 dns_rdatatype_ns,
4993 							 dns_rdatatype_any,
4994 							 DNS_SECTION_AUTHORITY);
4995 			dup_name(name, &chase_authority_name);
4996 			if (chase_nsrdataset != NULL) {
4997 				have_delegation_ns = ISC_TRUE;
4998 				printf("no response but there is a delegation"
4999 				       " in authority section: ");
5000 				dns_name_print(name, stdout);
5001 				printf("\n");
5002 			} else {
5003 				printf("no response and no delegation in "
5004 				       "authority section but a reference"
5005 				       " to: ");
5006 				dns_name_print(name, stdout);
5007 				printf("\n");
5008 				error_message = msg;
5009 			}
5010 		} else {
5011 			printf(";; NO ANSWERS: %s\n",
5012 			       isc_result_totext(result));
5013 			free_name(&chase_name);
5014 			clean_trustedkey();
5015 			return;
5016 		}
5017 	}
5018 
5019 
5020 	if (have_answer) {
5021 		chase_rdataset
5022 			= chase_scanname_section(msg, &chase_name,
5023 						 current_lookup
5024 						 ->rdtype_sigchase,
5025 						 dns_rdatatype_any,
5026 						 DNS_SECTION_ANSWER);
5027 		if (chase_rdataset != NULL)
5028 			have_response = ISC_TRUE;
5029 	}
5030 
5031 	result = advanced_rrsearch(&chase_keyrdataset,
5032 				   &chase_current_name,
5033 				   dns_rdatatype_dnskey,
5034 				   dns_rdatatype_any,
5035 				   &chase_keylookedup);
5036 	if (result == ISC_R_FAILURE) {
5037 		printf("\n;; DNSKEY is missing to continue validation:"
5038 		       " FAILED\n\n");
5039 		goto cleanandgo;
5040 	}
5041 	if (result == ISC_R_NOTFOUND)
5042 		return;
5043 	INSIST(chase_keyrdataset != NULL);
5044 	printf("\n;; DNSKEYset:\n");
5045 	print_rdataset(&chase_current_name , chase_keyrdataset);
5046 
5047 
5048 	result = advanced_rrsearch(&chase_sigkeyrdataset,
5049 				   &chase_current_name,
5050 				   dns_rdatatype_rrsig,
5051 				   dns_rdatatype_dnskey,
5052 				   &chase_sigkeylookedup);
5053 	if (result == ISC_R_FAILURE) {
5054 		printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
5055 		       " FAILED\n\n");
5056 		goto cleanandgo;
5057 	}
5058 	if (result == ISC_R_NOTFOUND)
5059 		return;
5060 	INSIST(chase_sigkeyrdataset != NULL);
5061 	printf("\n;; RRSIG of the DNSKEYset:\n");
5062 	print_rdataset(&chase_current_name , chase_sigkeyrdataset);
5063 
5064 
5065 	if (!chase_dslookedup && !chase_nslookedup) {
5066 		if (!delegation_follow) {
5067 			result = contains_trusted_key(&chase_current_name,
5068 						      chase_keyrdataset,
5069 						      chase_sigkeyrdataset);
5070 		} else {
5071 			INSIST(chase_dsrdataset != NULL);
5072 			INSIST(chase_sigdsrdataset != NULL);
5073 			result = sigchase_verify_ds(&chase_current_name,
5074 						    chase_keyrdataset,
5075 						    chase_dsrdataset);
5076 		}
5077 
5078 		if (result != ISC_R_SUCCESS) {
5079 			printf("\n;; chain of trust can't be validated:"
5080 			       " FAILED\n\n");
5081 			goto cleanandgo;
5082 		} else {
5083 			chase_dsrdataset = NULL;
5084 			chase_sigdsrdataset = NULL;
5085 		}
5086 	}
5087 
5088 	if (have_response || (!have_delegation_ns && !have_response)) {
5089 		/* test if it's a grand father case */
5090 
5091 		if (have_response) {
5092 			result = advanced_rrsearch(&chase_sigrdataset,
5093 						   &chase_name,
5094 						   dns_rdatatype_rrsig,
5095 						   current_lookup
5096 						   ->rdtype_sigchase,
5097 						   &true);
5098 			if (result == ISC_R_FAILURE) {
5099 				printf("\n;; RRset is missing to continue"
5100 				       " validation SHOULD NOT APPEND:"
5101 				       " FAILED\n\n");
5102 				goto cleanandgo;
5103 			}
5104 
5105 		} else {
5106 			result = advanced_rrsearch(&chase_sigrdataset,
5107 						   &chase_authority_name,
5108 						   dns_rdatatype_rrsig,
5109 						   dns_rdatatype_any,
5110 						   &true);
5111 			if (result == ISC_R_FAILURE) {
5112 				printf("\n;; RRSIG is missing  to continue"
5113 				       " validation SHOULD NOT APPEND:"
5114 				       " FAILED\n\n");
5115 				goto cleanandgo;
5116 			}
5117 		}
5118 		result =  grandfather_pb_test(&chase_current_name,
5119 					      chase_sigrdataset);
5120 		if (result != ISC_R_SUCCESS) {
5121 			dns_name_t tmp_name;
5122 
5123 			printf("\n;; We are in a Grand Father Problem:"
5124 			       " See 2.2.1 in RFC 3658\n");
5125 			chase_rdataset = NULL;
5126 			chase_sigrdataset = NULL;
5127 			have_response = ISC_FALSE;
5128 			have_delegation_ns = ISC_FALSE;
5129 
5130 			dns_name_init(&tmp_name, NULL);
5131 			result = child_of_zone(&chase_name, &chase_current_name,
5132 					       &tmp_name);
5133 			if (dns_name_dynamic(&chase_authority_name))
5134 				free_name(&chase_authority_name);
5135 			dup_name(&tmp_name, &chase_authority_name);
5136 			printf(";; and we try to continue chain of trust"
5137 			       " validation of the zone: ");
5138 			dns_name_print(&chase_authority_name, stdout);
5139 			printf("\n");
5140 			have_delegation_ns = ISC_TRUE;
5141 		} else {
5142 			if (have_response)
5143 				goto finalstep;
5144 			else
5145 				chase_sigrdataset = NULL;
5146 		}
5147 	}
5148 
5149 	if (have_delegation_ns) {
5150 		chase_nsrdataset = NULL;
5151 		result = advanced_rrsearch(&chase_nsrdataset,
5152 					   &chase_authority_name,
5153 					   dns_rdatatype_ns,
5154 					   dns_rdatatype_any,
5155 					   &chase_nslookedup);
5156 		if (result == ISC_R_FAILURE) {
5157 			printf("\n;;NSset is missing to continue validation:"
5158 			       " FAILED\n\n");
5159 			goto cleanandgo;
5160 		}
5161 		if (result == ISC_R_NOTFOUND) {
5162 			return;
5163 		}
5164 		INSIST(chase_nsrdataset != NULL);
5165 
5166 		result = advanced_rrsearch(&chase_dsrdataset,
5167 					   &chase_authority_name,
5168 					   dns_rdatatype_ds,
5169 					   dns_rdatatype_any,
5170 					   &chase_dslookedup);
5171 		if (result == ISC_R_FAILURE) {
5172 			printf("\n;; DSset is missing to continue validation:"
5173 			       " FAILED\n\n");
5174 			goto cleanandgo;
5175 		}
5176 		if (result == ISC_R_NOTFOUND)
5177 			return;
5178 		INSIST(chase_dsrdataset != NULL);
5179 		printf("\n;; DSset:\n");
5180 		print_rdataset(&chase_authority_name , chase_dsrdataset);
5181 
5182 		result = advanced_rrsearch(&chase_sigdsrdataset,
5183 					   &chase_authority_name,
5184 					   dns_rdatatype_rrsig,
5185 					   dns_rdatatype_ds,
5186 					   &true);
5187 		if (result != ISC_R_SUCCESS) {
5188 			printf("\n;; DSset is missing to continue validation:"
5189 			       " FAILED\n\n");
5190 			goto cleanandgo;
5191 		}
5192 		printf("\n;; RRSIGset of DSset\n");
5193 		print_rdataset(&chase_authority_name, chase_sigdsrdataset);
5194 		INSIST(chase_sigdsrdataset != NULL);
5195 
5196 		result = sigchase_verify_sig(&chase_authority_name,
5197 					     chase_dsrdataset,
5198 					     chase_keyrdataset,
5199 					     chase_sigdsrdataset);
5200 		if (result != ISC_R_SUCCESS) {
5201 			printf("\n;; Impossible to verify the DSset:"
5202 			       " FAILED\n\n");
5203 			goto cleanandgo;
5204 		}
5205 		chase_keyrdataset = NULL;
5206 		chase_sigkeyrdataset = NULL;
5207 
5208 
5209 		prepare_lookup(&chase_authority_name);
5210 
5211 		have_response = ISC_FALSE;
5212 		have_delegation_ns = ISC_FALSE;
5213 		delegation_follow = ISC_TRUE;
5214 		error_message = NULL;
5215 		dup_name(&chase_authority_name, &chase_current_name);
5216 		free_name(&chase_authority_name);
5217 		return;
5218 	}
5219 
5220 
5221 	if (error_message != NULL) {
5222 		dns_rdataset_t *rdataset;
5223 		dns_rdataset_t *sigrdataset;
5224 		dns_name_t rdata_name;
5225 		isc_result_t ret = ISC_R_FAILURE;
5226 
5227 		dns_name_init(&rdata_name, NULL);
5228 		result = prove_nx(error_message, &chase_name,
5229 				  current_lookup->rdclass_sigchase,
5230 				  current_lookup->rdtype_sigchase, &rdata_name,
5231 				  &rdataset, &sigrdataset);
5232 		if (rdataset == NULL || sigrdataset == NULL ||
5233 		    dns_name_countlabels(&rdata_name) == 0) {
5234 			printf("\n;; Impossible to verify the non-existence,"
5235 			       " the NSEC RRset can't be validated:"
5236 			       " FAILED\n\n");
5237 			goto cleanandgo;
5238 		}
5239 		ret = sigchase_verify_sig(&rdata_name, rdataset,
5240 					  chase_keyrdataset,
5241 					  sigrdataset);
5242 		if (ret != ISC_R_SUCCESS) {
5243 			free_name(&rdata_name);
5244 			printf("\n;; Impossible to verify the NSEC RR to prove"
5245 			       " the non-existence : FAILED\n\n");
5246 			goto cleanandgo;
5247 		}
5248 		free_name(&rdata_name);
5249 		if (result != ISC_R_SUCCESS) {
5250 			printf("\n;; Impossible to verify the non-existence:"
5251 			       " FAILED\n\n");
5252 			goto cleanandgo;
5253 		} else {
5254 			printf("\n;; OK the query doesn't have response but"
5255 			       " we have validate this fact : SUCCESS\n\n");
5256 			goto cleanandgo;
5257 		}
5258 	}
5259 
5260  cleanandgo:
5261 	printf(";; cleanandgo \n");
5262 	if (dns_name_dynamic(&chase_current_name))
5263 		free_name(&chase_current_name);
5264 	if (dns_name_dynamic(&chase_authority_name))
5265 		free_name(&chase_authority_name);
5266 	clean_trustedkey();
5267 	return;
5268 
5269 	finalstep :
5270 		result = advanced_rrsearch(&chase_rdataset, &chase_name,
5271 					   current_lookup->rdtype_sigchase,
5272 					   dns_rdatatype_any ,
5273 					   &true);
5274 	if (result == ISC_R_FAILURE) {
5275 		printf("\n;; RRsig of RRset is missing to continue validation"
5276 		       " SHOULD NOT APPEND: FAILED\n\n");
5277 		goto cleanandgo;
5278 	}
5279 	result = sigchase_verify_sig(&chase_name, chase_rdataset,
5280 				     chase_keyrdataset,
5281 				     chase_sigrdataset);
5282 	if (result != ISC_R_SUCCESS) {
5283 		printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5284 		/*
5285 		  printf("RRset:\n");
5286 		  print_rdataset(&chase_name , chase_rdataset);
5287 		  printf("DNSKEYset:\n");
5288 		  print_rdataset(&chase_name , chase_keyrdataset);
5289 		  printf("RRSIG of RRset:\n");
5290 		  print_rdataset(&chase_name , chase_sigrdataset);
5291 		  printf("\n");
5292 		*/
5293 		goto cleanandgo;
5294 	} else {
5295 		printf("\n;; The Answer:\n");
5296 		print_rdataset(&chase_name , chase_rdataset);
5297 
5298 		printf("\n;; FINISH : we have validate the DNSSEC chain"
5299 		       " of trust: SUCCESS\n\n");
5300 		goto cleanandgo;
5301 	}
5302 }
5303 
5304 #endif
5305 
5306 
5307 #if DIG_SIGCHASE_BU
5308 
5309 isc_result_t
getneededrr(dns_message_t * msg)5310 getneededrr(dns_message_t *msg)
5311 {
5312 	isc_result_t result;
5313 	dns_name_t *name = NULL;
5314 	dns_rdata_t sigrdata = DNS_RDATA_INIT;
5315 	dns_rdata_sig_t siginfo;
5316 	isc_boolean_t   true = ISC_TRUE;
5317 
5318 	if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5319 	    != ISC_R_SUCCESS) {
5320 		printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
5321 
5322 		if (chase_name.ndata == NULL)
5323 			return (ISC_R_ADDRNOTAVAIL);
5324 	} else {
5325 		dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5326 	}
5327 
5328 	/* What do we chase? */
5329 	if (chase_rdataset == NULL) {
5330 		result = advanced_rrsearch(&chase_rdataset, name,
5331 					   dns_rdatatype_any,
5332 					   dns_rdatatype_any, &true);
5333 		if (result != ISC_R_SUCCESS) {
5334 			printf("\n;; No Answers: Validation FAILED\n\n");
5335 			return (ISC_R_NOTFOUND);
5336 		}
5337 		dup_name(name, &chase_name);
5338 		printf(";; RRset to chase:\n");
5339 		print_rdataset(&chase_name, chase_rdataset);
5340 	}
5341 	INSIST(chase_rdataset != NULL);
5342 
5343 
5344 	if (chase_sigrdataset == NULL) {
5345 		result = advanced_rrsearch(&chase_sigrdataset, name,
5346 					   dns_rdatatype_rrsig,
5347 					   chase_rdataset->type,
5348 					   &chase_siglookedup);
5349 		if (result == ISC_R_FAILURE) {
5350 			printf("\n;; RRSIG is missing for continue validation:"
5351 			       " FAILED\n\n");
5352 			if (dns_name_dynamic(&chase_name))
5353 				free_name(&chase_name);
5354 			return (ISC_R_NOTFOUND);
5355 		}
5356 		if (result == ISC_R_NOTFOUND) {
5357 			return (ISC_R_NOTFOUND);
5358 		}
5359 		printf("\n;; RRSIG of the RRset to chase:\n");
5360 		print_rdataset(&chase_name, chase_sigrdataset);
5361 	}
5362 	INSIST(chase_sigrdataset != NULL);
5363 
5364 
5365 	/* first find the DNSKEY name */
5366 	result = dns_rdataset_first(chase_sigrdataset);
5367 	check_result(result, "empty RRSIG dataset");
5368 	dns_rdataset_current(chase_sigrdataset, &sigrdata);
5369 	result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5370 	check_result(result, "sigrdata tostruct siginfo");
5371 	dup_name(&siginfo.signer, &chase_signame);
5372 	dns_rdata_freestruct(&siginfo);
5373 	dns_rdata_reset(&sigrdata);
5374 
5375 	/* Do we have a key?  */
5376 	if (chase_keyrdataset == NULL) {
5377 		result = advanced_rrsearch(&chase_keyrdataset,
5378 					   &chase_signame,
5379 					   dns_rdatatype_dnskey,
5380 					   dns_rdatatype_any,
5381 					   &chase_keylookedup);
5382 		if (result == ISC_R_FAILURE) {
5383 			printf("\n;; DNSKEY is missing to continue validation:"
5384 			       " FAILED\n\n");
5385 			free_name(&chase_signame);
5386 			if (dns_name_dynamic(&chase_name))
5387 				free_name(&chase_name);
5388 			return (ISC_R_NOTFOUND);
5389 		}
5390 		if (result == ISC_R_NOTFOUND) {
5391 			free_name(&chase_signame);
5392 			return (ISC_R_NOTFOUND);
5393 		}
5394 		printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5395 		print_rdataset(&chase_signame, chase_keyrdataset);
5396 	}
5397 	INSIST(chase_keyrdataset != NULL);
5398 
5399 	if (chase_sigkeyrdataset == NULL) {
5400 		result = advanced_rrsearch(&chase_sigkeyrdataset,
5401 					   &chase_signame,
5402 					   dns_rdatatype_rrsig,
5403 					   dns_rdatatype_dnskey,
5404 					   &chase_sigkeylookedup);
5405 		if (result == ISC_R_FAILURE) {
5406 			printf("\n;; RRSIG for DNSKEY is missing  to continue"
5407 			       " validation : FAILED\n\n");
5408 			free_name(&chase_signame);
5409 			if (dns_name_dynamic(&chase_name))
5410 				free_name(&chase_name);
5411 			return (ISC_R_NOTFOUND);
5412 		}
5413 		if (result == ISC_R_NOTFOUND) {
5414 			free_name(&chase_signame);
5415 			return (ISC_R_NOTFOUND);
5416 		}
5417 		printf("\n;; RRSIG of the DNSKEYset that signs the "
5418 		       "RRset to chase:\n");
5419 		print_rdataset(&chase_signame, chase_sigkeyrdataset);
5420 	}
5421 	INSIST(chase_sigkeyrdataset != NULL);
5422 
5423 
5424 	if (chase_dsrdataset == NULL) {
5425 		result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
5426 					   dns_rdatatype_ds, dns_rdatatype_any,
5427 					   &chase_dslookedup);
5428 		if (result == ISC_R_FAILURE) {
5429 			printf("\n;; WARNING There is no DS for the zone: ");
5430 			dns_name_print(&chase_signame, stdout);
5431 			printf("\n");
5432 		}
5433 		if (result == ISC_R_NOTFOUND) {
5434 			free_name(&chase_signame);
5435 			return (ISC_R_NOTFOUND);
5436 		}
5437 		if (chase_dsrdataset != NULL) {
5438 			printf("\n;; DSset of the DNSKEYset\n");
5439 			print_rdataset(&chase_signame, chase_dsrdataset);
5440 		}
5441 	}
5442 
5443 	if (chase_dsrdataset != NULL) {
5444 		/*
5445 		 * if there is no RRSIG of DS,
5446 		 * we don't want to search on the network
5447 		 */
5448 		result = advanced_rrsearch(&chase_sigdsrdataset,
5449 					   &chase_signame,
5450 					   dns_rdatatype_rrsig,
5451 					   dns_rdatatype_ds, &true);
5452 		if (result == ISC_R_FAILURE) {
5453 			printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5454 			       " should come with DS\n");
5455 			/*
5456 			 * We continue even the DS couldn't be validated,
5457 			 * because the DNSKEY could be a Trusted Key.
5458 			 */
5459 			chase_dsrdataset = NULL;
5460 		} else {
5461 			printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5462 			print_rdataset(&chase_signame, chase_sigdsrdataset);
5463 		}
5464 	}
5465 	return (1);
5466 }
5467 
5468 
5469 
5470 void
sigchase_bu(dns_message_t * msg)5471 sigchase_bu(dns_message_t *msg)
5472 {
5473 	isc_result_t result;
5474 	int ret;
5475 
5476 	if (tk_list.nb_tk == 0) {
5477 		result = get_trusted_key();
5478 		if (result != ISC_R_SUCCESS) {
5479 			printf("No trusted keys present\n");
5480 			return;
5481 		}
5482 	}
5483 
5484 
5485 	ret = getneededrr(msg);
5486 	if (ret == ISC_R_NOTFOUND)
5487 		return;
5488 
5489 	if (ret == ISC_R_ADDRNOTAVAIL) {
5490 		/* We have no response */
5491 		dns_rdataset_t *rdataset;
5492 		dns_rdataset_t *sigrdataset;
5493 		dns_name_t rdata_name;
5494 		dns_name_t query_name;
5495 
5496 
5497 		dns_name_init(&query_name, NULL);
5498 		dns_name_init(&rdata_name, NULL);
5499 		nameFromString(current_lookup->textname, &query_name);
5500 
5501 		result = prove_nx(msg, &query_name, current_lookup->rdclass,
5502 				  current_lookup->rdtype, &rdata_name,
5503 				  &rdataset, &sigrdataset);
5504 		free_name(&query_name);
5505 		if (rdataset == NULL || sigrdataset == NULL ||
5506 		    dns_name_countlabels(&rdata_name) == 0) {
5507 			printf("\n;; Impossible to verify the Non-existence,"
5508 			       " the NSEC RRset can't be validated: "
5509 			       "FAILED\n\n");
5510 			clean_trustedkey();
5511 			return;
5512 		}
5513 
5514 		if (result != ISC_R_SUCCESS) {
5515 			printf("\n No Answers and impossible to prove the"
5516 			       " unsecurity : Validation FAILED\n\n");
5517 			clean_trustedkey();
5518 			return;
5519 		}
5520 		printf(";; An NSEC prove the non-existence of a answers,"
5521 		       " Now we want validate this NSEC\n");
5522 
5523 		dup_name(&rdata_name, &chase_name);
5524 		free_name(&rdata_name);
5525 		chase_rdataset =  rdataset;
5526 		chase_sigrdataset = sigrdataset;
5527 		chase_keyrdataset = NULL;
5528 		chase_sigkeyrdataset = NULL;
5529 		chase_dsrdataset = NULL;
5530 		chase_sigdsrdataset = NULL;
5531 		chase_siglookedup = ISC_FALSE;
5532 		chase_keylookedup = ISC_FALSE;
5533 		chase_dslookedup = ISC_FALSE;
5534 		chase_sigdslookedup = ISC_FALSE;
5535 		sigchase(msg);
5536 		clean_trustedkey();
5537 		return;
5538 	}
5539 
5540 
5541 	printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5542 
5543 	result = sigchase_verify_sig(&chase_name, chase_rdataset,
5544 				     chase_keyrdataset,
5545 				     chase_sigrdataset);
5546 	if (result != ISC_R_SUCCESS) {
5547 		free_name(&chase_name);
5548 		free_name(&chase_signame);
5549 		printf(";; No DNSKEY is valid to check the RRSIG"
5550 		       " of the RRset: FAILED\n");
5551 		clean_trustedkey();
5552 		return;
5553 	}
5554 	printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5555 
5556 	result = contains_trusted_key(&chase_signame, chase_keyrdataset,
5557 				      chase_sigkeyrdataset);
5558 	if (result ==  ISC_R_SUCCESS) {
5559 		free_name(&chase_name);
5560 		free_name(&chase_signame);
5561 		printf("\n;; Ok this DNSKEY is a Trusted Key,"
5562 		       " DNSSEC validation is ok: SUCCESS\n\n");
5563 		clean_trustedkey();
5564 		return;
5565 	}
5566 
5567 	printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5568 
5569 	if (chase_dsrdataset == NULL) {
5570 		free_name(&chase_name);
5571 		free_name(&chase_signame);
5572 		printf(";; the DNSKEY isn't trusted-key and there isn't"
5573 		       " DS to validate the DNSKEY: FAILED\n");
5574 		clean_trustedkey();
5575 		return;
5576 	}
5577 
5578 	result =  sigchase_verify_ds(&chase_signame, chase_keyrdataset,
5579 				     chase_dsrdataset);
5580 	if (result !=  ISC_R_SUCCESS) {
5581 		free_name(&chase_signame);
5582 		free_name(&chase_name);
5583 		printf(";; ERROR no DS validates a DNSKEY in the"
5584 		       " DNSKEY RRset: FAILED\n");
5585 		clean_trustedkey();
5586 		return;
5587 	} else
5588 		printf(";; OK this DNSKEY (validated by the DS) validates"
5589 		       " the RRset of the DNSKEYs, thus the DNSKEY validates"
5590 		       " the RRset\n");
5591 	INSIST(chase_sigdsrdataset != NULL);
5592 
5593 	dup_name(&chase_signame, &chase_name);
5594 	free_name(&chase_signame);
5595 	chase_rdataset = chase_dsrdataset;
5596 	chase_sigrdataset = chase_sigdsrdataset;
5597 	chase_keyrdataset = NULL;
5598 	chase_sigkeyrdataset = NULL;
5599 	chase_dsrdataset = NULL;
5600 	chase_sigdsrdataset = NULL;
5601 	chase_siglookedup = chase_keylookedup = ISC_FALSE;
5602 	chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
5603 
5604 	printf(";; Now, we want to validate the DS :  recursive call\n");
5605 	sigchase(msg);
5606 	return;
5607 }
5608 #endif
5609 
5610 void
sigchase(dns_message_t * msg)5611 sigchase(dns_message_t *msg) {
5612 #if DIG_SIGCHASE_TD
5613 	if (current_lookup->do_topdown) {
5614 		sigchase_td(msg);
5615 		return;
5616 	}
5617 #endif
5618 #if DIG_SIGCHASE_BU
5619 	sigchase_bu(msg);
5620 	return;
5621 #endif
5622 }
5623 
5624 
5625 /*
5626  * return 1  if name1  <  name2
5627  *	  0  if name1  == name2
5628  *	  -1 if name1  >  name2
5629  *    and -2 if problem
5630  */
5631 int
inf_name(dns_name_t * name1,dns_name_t * name2)5632 inf_name(dns_name_t *name1, dns_name_t *name2)
5633 {
5634 	dns_label_t  label1;
5635 	dns_label_t  label2;
5636 	unsigned int nblabel1;
5637 	unsigned int nblabel2;
5638 	int min_lum_label;
5639 	int i;
5640 	int ret = -2;
5641 
5642 	nblabel1 = dns_name_countlabels(name1);
5643 	nblabel2 = dns_name_countlabels(name2);
5644 
5645 	if (nblabel1 >= nblabel2)
5646 		min_lum_label = nblabel2;
5647 	else
5648 		min_lum_label = nblabel1;
5649 
5650 
5651 	for (i=1 ; i < min_lum_label; i++) {
5652 		dns_name_getlabel(name1, nblabel1 -1  - i, &label1);
5653 		dns_name_getlabel(name2, nblabel2 -1  - i, &label2);
5654 		if ((ret = isc_region_compare(&label1, &label2)) != 0) {
5655 			if (ret < 0)
5656 				return (-1);
5657 			else if (ret > 0)
5658 				return (1);
5659 		}
5660 	}
5661 	if (nblabel1 == nblabel2)
5662 		return (0);
5663 
5664 	if (nblabel1 < nblabel2)
5665 		return (-1);
5666 	else
5667 		return (1);
5668 }
5669 
5670 /**
5671  *
5672  *
5673  *
5674  */
5675 isc_result_t
prove_nx_domain(dns_message_t * msg,dns_name_t * name,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)5676 prove_nx_domain(dns_message_t *msg,
5677 		dns_name_t *name,
5678 		dns_name_t *rdata_name,
5679 		dns_rdataset_t **rdataset,
5680 		dns_rdataset_t **sigrdataset)
5681 {
5682 	isc_result_t ret = ISC_R_FAILURE;
5683 	isc_result_t result = ISC_R_NOTFOUND;
5684 	dns_rdataset_t *nsecset = NULL;
5685 	dns_rdataset_t *signsecset = NULL ;
5686 	dns_rdata_t nsec = DNS_RDATA_INIT;
5687 	dns_name_t *nsecname;
5688 	dns_rdata_nsec_t nsecstruct;
5689 
5690 	if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5691 	    != ISC_R_SUCCESS) {
5692 		printf(";; nothing in authority section : impossible to"
5693 		       " validate the non-existence : FAILED\n");
5694 		return (ISC_R_FAILURE);
5695 	}
5696 
5697 	do {
5698 		nsecname = NULL;
5699 		dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
5700 		nsecset = search_type(nsecname, dns_rdatatype_nsec,
5701 				      dns_rdatatype_any);
5702 		if (nsecset == NULL)
5703 			continue;
5704 
5705 		printf("There is a NSEC for this zone in the"
5706 		       " AUTHORITY section:\n");
5707 		print_rdataset(nsecname, nsecset);
5708 
5709 		for (result = dns_rdataset_first(nsecset);
5710 		     result == ISC_R_SUCCESS;
5711 		     result = dns_rdataset_next(nsecset)) {
5712 			dns_rdataset_current(nsecset, &nsec);
5713 
5714 			signsecset
5715 				= chase_scanname_section(msg, nsecname,
5716 						 dns_rdatatype_rrsig,
5717 						 dns_rdatatype_nsec,
5718 						 DNS_SECTION_AUTHORITY);
5719 			if (signsecset == NULL) {
5720 				printf(";; no RRSIG NSEC in authority section:"
5721 				       " impossible to validate the "
5722 				       "non-existence: FAILED\n");
5723 				return (ISC_R_FAILURE);
5724 			}
5725 
5726 			ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
5727 			check_result(ret,"dns_rdata_tostruct");
5728 
5729 			if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
5730 			     inf_name(name, &nsecstruct.next) == 1) ||
5731 			    (inf_name(name, nsecname) == 1 &&
5732 			     inf_name(&nsecstruct.next, name) == 1)) {
5733 				dns_rdata_freestruct(&nsecstruct);
5734 				*rdataset = nsecset;
5735 				*sigrdataset = signsecset;
5736 				dup_name(nsecname, rdata_name);
5737 
5738 				return (ISC_R_SUCCESS);
5739 			}
5740 
5741 			dns_rdata_freestruct(&nsecstruct);
5742 			dns_rdata_reset(&nsec);
5743 		}
5744 	} while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
5745 		 == ISC_R_SUCCESS);
5746 
5747 	*rdataset = NULL;
5748 	*sigrdataset =  NULL;
5749 	rdata_name = NULL;
5750 	return (ISC_R_FAILURE);
5751 }
5752 
5753 /**
5754  *
5755  *
5756  *
5757  *
5758  *
5759  */
5760 isc_result_t
prove_nx_type(dns_message_t * msg,dns_name_t * name,dns_rdataset_t * nsecset,dns_rdataclass_t class,dns_rdatatype_t type,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)5761 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
5762 	      dns_rdataclass_t class, dns_rdatatype_t type,
5763 	      dns_name_t *rdata_name, dns_rdataset_t **rdataset,
5764 	      dns_rdataset_t **sigrdataset)
5765 {
5766 	isc_result_t ret;
5767 	dns_rdataset_t *signsecset;
5768 	dns_rdata_t nsec = DNS_RDATA_INIT;
5769 
5770 	UNUSED(class);
5771 
5772 	ret = dns_rdataset_first(nsecset);
5773 	check_result(ret,"dns_rdataset_first");
5774 
5775 	dns_rdataset_current(nsecset, &nsec);
5776 
5777 	ret = dns_nsec_typepresent(&nsec, type);
5778 	if (ret == ISC_R_SUCCESS)
5779 		printf("OK the NSEC said that the type doesn't exist \n");
5780 
5781 	signsecset = chase_scanname_section(msg, name,
5782 					    dns_rdatatype_rrsig,
5783 					    dns_rdatatype_nsec,
5784 					    DNS_SECTION_AUTHORITY);
5785 	if (signsecset == NULL) {
5786 		printf("There isn't RRSIG NSEC for the zone \n");
5787 		return (ISC_R_FAILURE);
5788 	}
5789 	dup_name(name, rdata_name);
5790 	*rdataset = nsecset;
5791 	*sigrdataset = signsecset;
5792 
5793 	return (ret);
5794 }
5795 
5796 /**
5797  *
5798  *
5799  *
5800  *
5801  */
5802 isc_result_t
prove_nx(dns_message_t * msg,dns_name_t * name,dns_rdataclass_t class,dns_rdatatype_t type,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)5803 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
5804 	 dns_rdatatype_t type, dns_name_t *rdata_name,
5805 	 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
5806 {
5807 	isc_result_t ret;
5808 	dns_rdataset_t *nsecset = NULL;
5809 
5810 	printf("We want to prove the non-existence of a type of rdata %d"
5811 	       " or of the zone: \n", type);
5812 
5813 	if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5814 	    != ISC_R_SUCCESS) {
5815 		printf(";; nothing in authority section : impossible to"
5816 		       " validate the non-existence : FAILED\n");
5817 		return (ISC_R_FAILURE);
5818 	}
5819 
5820 	nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
5821 					 dns_rdatatype_any,
5822 					 DNS_SECTION_AUTHORITY);
5823 	if (nsecset != NULL) {
5824 		printf("We have a NSEC for this zone :OK\n");
5825 		ret = prove_nx_type(msg, name, nsecset, class,
5826 				    type, rdata_name, rdataset,
5827 				    sigrdataset);
5828 		if (ret != ISC_R_SUCCESS) {
5829 			printf("prove_nx: ERROR type exist\n");
5830 			return (ret);
5831 		} else {
5832 			printf("prove_nx: OK type does not exist\n");
5833 			return (ISC_R_SUCCESS);
5834 		}
5835 	} else {
5836 		printf("there is no NSEC for this zone: validating "
5837 		       "that the zone doesn't exist\n");
5838 		ret = prove_nx_domain(msg, name, rdata_name,
5839 				      rdataset, sigrdataset);
5840 		return (ret);
5841 	}
5842 	/* Never get here */
5843 }
5844 #endif
5845