GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bind/bin/dig/dighost.c Lines: 0 1561 0.0 %
Date: 2016-12-06 Branches: 0 967 0.0 %

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