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