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