dighost.c 163 KB
Newer Older
1
/*
2
 * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 2000-2003  Internet Software Consortium.
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
6 7
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
8
 *
Mark Andrews's avatar
Mark Andrews committed
9 10 11 12 13 14 15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
16 17
 */

18 19
/*! \file
 *  \note
20 21 22 23 24 25 26 27
 * Notice to programmers:  Do not use this code as an example of how to
 * use the ISC library to perform DNS lookups.  Dig and Host both operate
 * on the request level, since they allow fine-tuning of output and are
 * intended as debugging tools.  As a result, they perform many of the
 * functions which could be better handled using the dns_resolver
 * functions in most applications.
 */

28 29 30
#include <config.h>
#include <stdlib.h>
#include <unistd.h>
31
#include <string.h>
32
#include <limits.h>
33

34 35 36 37 38 39 40 41 42 43 44
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif

#ifdef WITH_IDN
#include <idn/result.h>
#include <idn/log.h>
#include <idn/resconf.h>
#include <idn/api.h>
#endif

45
#include <dns/byaddr.h>
46
#ifdef DIG_SIGCHASE
47
#include <dns/callbacks.h>
48 49
#include <dns/dnssec.h>
#include <dns/ds.h>
50
#include <dns/master.h>
51 52 53 54
#include <dns/nsec.h>
#include <isc/random.h>
#include <ctype.h>
#endif
55
#include <dns/fixedname.h>
56
#include <dns/log.h>
57
#include <dns/message.h>
Brian Wellington's avatar
Brian Wellington committed
58
#include <dns/name.h>
59
#include <dns/rcode.h>
60 61
#include <dns/rdata.h>
#include <dns/rdataclass.h>
Michael Sawyer's avatar
Michael Sawyer committed
62
#include <dns/rdatalist.h>
63
#include <dns/rdataset.h>
Michael Sawyer's avatar
Michael Sawyer committed
64
#include <dns/rdatastruct.h>
65 66
#include <dns/rdatatype.h>
#include <dns/result.h>
67
#include <dns/tsig.h>
68

69
#include <dst/dst.h>
70
#include <dst/result.h>
71

Michael Sawyer's avatar
Michael Sawyer committed
72 73 74
#include <isc/app.h>
#include <isc/base64.h>
#include <isc/entropy.h>
75
#include <isc/file.h>
76
#include <isc/hex.h>
Michael Sawyer's avatar
Michael Sawyer committed
77
#include <isc/lang.h>
78
#include <isc/log.h>
79
#include <isc/netaddr.h>
80
#include <isc/netdb.h>
81
#include <isc/parseint.h>
Mark Andrews's avatar
Mark Andrews committed
82
#include <isc/print.h>
83
#include <isc/random.h>
Michael Sawyer's avatar
Michael Sawyer committed
84
#include <isc/result.h>
85
#include <isc/safe.h>
86
#include <isc/serial.h>
Evan Hunt's avatar
Evan Hunt committed
87
#include <isc/sockaddr.h>
Michael Sawyer's avatar
Michael Sawyer committed
88 89 90 91 92
#include <isc/string.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/types.h>
#include <isc/util.h>
93

94 95
#include <isccfg/namedconf.h>

96 97 98
#include <lwres/lwres.h>
#include <lwres/net.h>

99
#include <bind9/getaddresses.h>
100

101
#include <dig/dig.h>
102

103 104 105 106
#ifdef PKCS11CRYPTO
#include <pk11/result.h>
#endif

107 108 109 110 111 112 113 114
#if ! defined(NS_INADDRSZ)
#define NS_INADDRSZ	 4
#endif

#if ! defined(NS_IN6ADDRSZ)
#define NS_IN6ADDRSZ	16
#endif

115 116 117
static lwres_context_t *lwctx = NULL;
static lwres_conf_t *lwconf;

118
dig_lookuplist_t lookup_list;
119
dig_serverlist_t server_list;
120
dig_searchlistlist_t search_list;
121

122
isc_boolean_t
123
	check_ra = ISC_FALSE,
124
	have_ipv4 = ISC_FALSE,
125 126 127
	have_ipv6 = ISC_FALSE,
	specified_source = ISC_FALSE,
	free_now = ISC_FALSE,
128
	cancel_now = ISC_FALSE,
129
	usesearch = ISC_FALSE,
130
	showsearch = ISC_FALSE,
131
	qr = ISC_FALSE,
132
	is_dst_up = ISC_FALSE,
133 134
	keep_open = ISC_FALSE,
	verbose = ISC_FALSE;
135
in_port_t port = 53;
136
unsigned int timeout = 0;
137
unsigned int extrabytes;
138
isc_mem_t *mctx = NULL;
139
isc_log_t *lctx = NULL;
140
isc_taskmgr_t *taskmgr = NULL;
141
isc_task_t *global_task = NULL;
142 143
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
144
isc_sockaddr_t bind_address;
Michael Sawyer's avatar
Michael Sawyer committed
145
isc_sockaddr_t bind_any;
146
int sendcount = 0;
147
int recvcount = 0;
Michael Sawyer's avatar
Michael Sawyer committed
148
int sockcount = 0;
149
int ndots = -1;
150
int tries = 3;
151
int lookup_counter = 0;
152

153
static char servercookie[256];
154

155 156 157 158 159 160 161 162 163 164
#ifdef WITH_IDN
static void		initialize_idn(void);
static isc_result_t	output_filter(isc_buffer_t *buffer,
				      unsigned int used_org,
				      isc_boolean_t absolute);
static idn_result_t	append_textname(char *name, const char *origin,
					size_t namesize);
static void		idn_check_result(idn_result_t r, const char *msg);

#define MAXDLEN		256
165
int  idnoptions	= 0;
166 167
#endif

168 169 170
isc_socket_t *keep = NULL;
isc_sockaddr_t keepaddr;

171
/*%
172
 * Exit Codes:
173
 *
174 175 176 177 178 179
 *\li	0   Everything went well, including things like NXDOMAIN
 *\li	1   Usage error
 *\li	7   Got too many RR's or Names
 *\li	8   Couldn't open batch file
 *\li	9   No reply from server
 *\li	10  Internal error
180 181
 */
int exitcode = 0;
182
int fatalexit = 0;
183
char keynametext[MXNAME];
184
char keyfile[MXNAME] = "";
185
char keysecret[MXNAME] = "";
186 187
unsigned char cookie_secret[33];
unsigned char cookie[8];
188 189
dns_name_t *hmacname = NULL;
unsigned int digestbits = 0;
190 191
isc_buffer_t *namebuf = NULL;
dns_tsigkey_t *key = NULL;
192
isc_boolean_t validated = ISC_TRUE;
193
isc_entropy_t *entp = NULL;
194
isc_mempool_t *commctx = NULL;
195
isc_boolean_t debugging = ISC_FALSE;
196
isc_boolean_t debugtiming = ISC_FALSE;
197
isc_boolean_t memdebugging = ISC_FALSE;
Michael Sawyer's avatar
Michael Sawyer committed
198
char *progname = NULL;
199
isc_mutex_t lookup_lock;
200
dig_lookup_t *current_lookup = NULL;
201

202 203
#ifdef DIG_SIGCHASE

204
isc_result_t	  get_trusted_key(void);
205 206 207 208 209 210 211 212 213
dns_rdataset_t *  sigchase_scanname(dns_rdatatype_t type,
				    dns_rdatatype_t covers,
				    isc_boolean_t *lookedup,
				    dns_name_t *rdata_name);
dns_rdataset_t *  chase_scanname_section(dns_message_t *msg,
					 dns_name_t *name,
					 dns_rdatatype_t type,
					 dns_rdatatype_t covers,
					 int section);
214
isc_result_t	  advanced_rrsearch(dns_rdataset_t **rdataset,
215 216 217 218
				    dns_name_t *name,
				    dns_rdatatype_t type,
				    dns_rdatatype_t covers,
				    isc_boolean_t *lookedup);
219
isc_result_t	  sigchase_verify_sig_key(dns_name_t *name,
220 221
					  dns_rdataset_t *rdataset,
					  dst_key_t* dnsseckey,
222
					  dns_rdataset_t *sigrdataset);
223
isc_result_t	  sigchase_verify_sig(dns_name_t *name,
224 225
				      dns_rdataset_t *rdataset,
				      dns_rdataset_t *keyrdataset,
226
				      dns_rdataset_t *sigrdataset);
227
isc_result_t	  sigchase_verify_ds(dns_name_t *name,
228
				     dns_rdataset_t *keyrdataset,
229
				     dns_rdataset_t *dsrdataset);
230 231
void		  sigchase(dns_message_t *msg);
void		  print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
232 233 234
void		  print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset);
void		  dup_name(dns_name_t *source, dns_name_t* target);
void		  free_name(dns_name_t *name);
235 236
void		  dump_database(void);
void		  dump_database_section(dns_message_t *msg, int section);
237 238
dns_rdataset_t *  search_type(dns_name_t *name, dns_rdatatype_t type,
			      dns_rdatatype_t covers);
239
isc_result_t	  contains_trusted_key(dns_name_t *name,
240
				       dns_rdataset_t *rdataset,
241
				       dns_rdataset_t *sigrdataset);
242 243
void		  print_type(dns_rdatatype_t type);
isc_result_t	  prove_nx_domain(dns_message_t * msg,
244 245 246 247
				  dns_name_t * name,
				  dns_name_t * rdata_name,
				  dns_rdataset_t ** rdataset,
				  dns_rdataset_t ** sigrdataset);
248
isc_result_t	  prove_nx_type(dns_message_t * msg, dns_name_t *name,
249 250 251 252 253 254
				dns_rdataset_t *nsec,
				dns_rdataclass_t class,
				dns_rdatatype_t type,
				dns_name_t * rdata_name,
				dns_rdataset_t ** rdataset,
				dns_rdataset_t ** sigrdataset);
255
isc_result_t	  prove_nx(dns_message_t * msg, dns_name_t * name,
256 257 258 259 260
			   dns_rdataclass_t class,
			   dns_rdatatype_t type,
			   dns_name_t * rdata_name,
			   dns_rdataset_t ** rdataset,
			   dns_rdataset_t ** sigrdataset);
261
static void	  nameFromString(const char *str, dns_name_t *p_ret);
262
int		  inf_name(dns_name_t * name1, dns_name_t * name2);
263
isc_result_t	  removetmpkey(const char *file);
264
void		  clean_trustedkey(void);
265 266
isc_result_t 	  insert_trustedkey(void *arg, dns_name_t *name,
				    dns_rdataset_t *rdataset);
267
#if DIG_SIGCHASE_BU
268 269 270
isc_result_t	  getneededrr(dns_message_t *msg);
void		  sigchase_bottom_up(dns_message_t *msg);
void		  sigchase_bu(dns_message_t *msg);
271 272
#endif
#if DIG_SIGCHASE_TD
273 274 275
isc_result_t	  initialization(dns_name_t *name);
isc_result_t	  prepare_lookup(dns_name_t *name);
isc_result_t	  grandfather_pb_test(dns_name_t * zone_name,
276
				      dns_rdataset_t *sigrdataset);
277
isc_result_t	  child_of_zone(dns_name_t *name,
278 279
				dns_name_t *zone_name,
				dns_name_t *child_name);
280
void		  sigchase_td(dns_message_t *msg);
281 282 283
#endif
char trustedkey[MXNAME] = "";

284 285 286 287 288 289 290
dns_rdataset_t *chase_rdataset = NULL;
dns_rdataset_t *chase_sigrdataset = NULL;
dns_rdataset_t *chase_dsrdataset = NULL;
dns_rdataset_t *chase_sigdsrdataset = NULL;
dns_rdataset_t *chase_keyrdataset = NULL;
dns_rdataset_t *chase_sigkeyrdataset = NULL;
dns_rdataset_t *chase_nsrdataset = NULL;
291

292
dns_name_t chase_name; /* the query name */
293 294 295 296
#if DIG_SIGCHASE_TD
/*
 * the current name is the parent name when we follow delegation
 */
Automatic Updater's avatar
Automatic Updater committed
297
dns_name_t chase_current_name;
298 299 300
/*
 * the child name is used for delegation (NS DS responses in AUTHORITY section)
 */
301
dns_name_t chase_authority_name;
302 303
#endif
#if DIG_SIGCHASE_BU
304
dns_name_t chase_signame;
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
#endif


isc_boolean_t chase_siglookedup = ISC_FALSE;
isc_boolean_t chase_keylookedup = ISC_FALSE;
isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
isc_boolean_t chase_dslookedup = ISC_FALSE;
isc_boolean_t chase_sigdslookedup = ISC_FALSE;
#if DIG_SIGCHASE_TD
isc_boolean_t chase_nslookedup = ISC_FALSE;
isc_boolean_t chase_lookedup = ISC_FALSE;


isc_boolean_t delegation_follow = ISC_FALSE;
isc_boolean_t grandfather_pb = ISC_FALSE;
isc_boolean_t have_response = ISC_FALSE;
isc_boolean_t have_delegation_ns = ISC_FALSE;
dns_message_t * error_message = NULL;
#endif

isc_boolean_t dsvalidating = ISC_FALSE;
326
isc_boolean_t chase_name_dup = ISC_FALSE;
327 328 329 330 331 332 333

ISC_LIST(dig_message_t) chase_message_list;
ISC_LIST(dig_message_t) chase_message_list2;


#define MAX_TRUSTED_KEY 5
typedef struct struct_trusted_key_list {
334 335
	dst_key_t * key[MAX_TRUSTED_KEY];
	int nb_tk;
336 337
} struct_tk_list;

338
struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
339 340 341

#endif

342 343
#define DIG_MAX_ADDRESSES 20

344
/*%
345
 * Apply and clear locks at the event level in global task.
346
 * Can I get rid of these using shutdown events?  XXX
347 348
 */
#define LOCK_LOOKUP {\
Brian Wellington's avatar
Brian Wellington committed
349 350 351
	debug("lock_lookup %s:%d", __FILE__, __LINE__);\
	check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
	debug("success");\
352 353
}
#define UNLOCK_LOOKUP {\
Brian Wellington's avatar
Brian Wellington committed
354 355 356
	debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
	check_result(isc_mutex_unlock((&lookup_lock)),\
		     "isc_mutex_unlock");\
357
}
358

359
static void
360 361
cancel_lookup(dig_lookup_t *lookup);

Michael Sawyer's avatar
Michael Sawyer committed
362 363 364
static void
recv_done(isc_task_t *task, isc_event_t *event);

365 366 367
static void
send_udp(dig_query_t *query);

Michael Sawyer's avatar
Michael Sawyer committed
368 369 370
static void
connect_timeout(isc_task_t *task, isc_event_t *event);

371 372 373
static void
launch_next_query(dig_query_t *query, isc_boolean_t include_question);

374 375 376 377 378
static void
check_next_lookup(dig_lookup_t *lookup);

static isc_boolean_t
next_origin(dig_lookup_t *oldlookup);
379 380 381 382 383 384 385 386 387 388 389

static void *
mem_alloc(void *arg, size_t size) {
	return (isc_mem_get(arg, size));
}

static void
mem_free(void *arg, void *mem, size_t size) {
	isc_mem_put(arg, mem, size);
}

Mark Andrews's avatar
Mark Andrews committed
390
char *
391 392 393 394 395 396 397 398 399
next_token(char **stringp, const char *delim) {
	char *res;

	do {
		res = strsep(stringp, delim);
		if (res == NULL)
			break;
	} while (*res == '\0');
	return (res);
Brian Wellington's avatar
Brian Wellington committed
400
}
401

402 403 404
static int
count_dots(char *string) {
	char *s;
405
	int i = 0;
406 407

	s = string;
408
	while (*s != '\0') {
409 410 411 412 413 414 415
		if (*s == '.')
			i++;
		s++;
	}
	return (i);
}

416
static void
417
hex_dump(isc_buffer_t *b) {
418
	unsigned int len, i;
419 420
	isc_region_t r;

421
	isc_buffer_usedregion(b, &r);
422

423
	printf("%d bytes\n", r.length);
424
	for (len = 0; len < r.length; len++) {
425
		printf("%02x ", r.base[len]);
426 427 428 429 430
		if (len % 16 == 15) {
			fputs("         ", stdout);
			for (i = len - 15; i <= len; i++) {
				if (r.base[i] >= '!' && r.base[i] <= '}')
					putchar(r.base[i]);
Automatic Updater's avatar
Automatic Updater committed
431
				else
432 433
					putchar('.');
			}
434
			printf("\n");
435
		}
436
	}
437 438 439 440 441 442 443
	if (len % 16 != 0) {
		for (i = len; (i % 16) != 0; i++)
			fputs("   ", stdout);
		fputs("         ", stdout);
		for (i = ((len>>4)<<4); i < len; i++) {
			if (r.base[i] >= '!' && r.base[i] <= '}')
				putchar(r.base[i]);
Automatic Updater's avatar
Automatic Updater committed
444
			else
445 446
				putchar('.');
		}
447
		printf("\n");
448
	}
449 450
}

451
/*%
452 453 454 455 456 457 458
 * Append 'len' bytes of 'text' at '*p', failing with
 * ISC_R_NOSPACE if that would advance p past 'end'.
 */
static isc_result_t
append(const char *text, int len, char **p, char *end) {
	if (len > end - *p)
		return (ISC_R_NOSPACE);
459
	memmove(*p, text, len);
460 461 462 463 464 465
	*p += len;
	return (ISC_R_SUCCESS);
}

static isc_result_t
reverse_octets(const char *in, char **p, char *end) {
466
	const char *dot = strchr(in, '.');
467 468 469 470 471 472 473 474 475
	int len;
	if (dot != NULL) {
		isc_result_t result;
		result = reverse_octets(dot + 1, p, end);
		if (result != ISC_R_SUCCESS)
			return (result);
		result = append(".", 1, p, end);
		if (result != ISC_R_SUCCESS)
			return (result);
476
		len = (int)(dot - in);
477 478 479 480 481
	} else {
		len = strlen(in);
	}
	return (append(in, len, p, end));
}
482 483

isc_result_t
484
get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
485 486 487
	    isc_boolean_t strict)
{
	int r;
488
	isc_result_t result;
489
	isc_netaddr_t addr;
490

491
	addr.family = AF_INET6;
Andreas Gustafsson's avatar
spacing  
Andreas Gustafsson committed
492
	r = inet_pton(AF_INET6, value, &addr.type.in6);
493 494
	if (r > 0) {
		/* This is a valid IPv6 address. */
495 496
		dns_fixedname_t fname;
		dns_name_t *name;
Mark Andrews's avatar
Mark Andrews committed
497 498
		unsigned int options = 0;

499 500
		if (ip6_int)
			options |= DNS_BYADDROPT_IPV6INT;
501 502
		dns_fixedname_init(&fname);
		name = dns_fixedname_name(&fname);
503
		result = dns_byaddr_createptrname2(&addr, options, name);
504 505
		if (result != ISC_R_SUCCESS)
			return (result);
506
		dns_name_format(name, reverse, (unsigned int)len);
507 508 509 510 511 512 513 514 515 516 517
		return (ISC_R_SUCCESS);
	} else {
		/*
		 * Not a valid IPv6 address.  Assume IPv4.
		 * If 'strict' is not set, construct the
		 * in-addr.arpa name by blindly reversing
		 * octets whether or not they look like integers,
		 * so that this can be used for RFC2317 names
		 * and such.
		 */
		char *p = reverse;
518
		char *end = reverse + len;
Michael Graff's avatar
Michael Graff committed
519 520
		if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
			return (DNS_R_BADDOTTEDQUAD);
521 522 523 524 525 526 527 528
		result = reverse_octets(value, &p, end);
		if (result != ISC_R_SUCCESS)
			return (result);
		/* Append .in-addr.arpa. and a terminating NUL. */
		result = append(".in-addr.arpa.", 15, &p, end);
		if (result != ISC_R_SUCCESS)
			return (result);
		return (ISC_R_SUCCESS);
529 530 531
	}
}

532
void
David Lawrence's avatar
David Lawrence committed
533
fatal(const char *format, ...) {
534 535
	va_list args;

536
	fflush(stdout);
537
	fprintf(stderr, "%s: ", progname);
538
	va_start(args, format);
539 540 541
	vfprintf(stderr, format, args);
	va_end(args);
	fprintf(stderr, "\n");
542 543
	if (exitcode < 10)
		exitcode = 10;
544 545
	if (fatalexit != 0)
		exitcode = fatalexit;
546
	exit(exitcode);
547 548
}

549
void
David Lawrence's avatar
David Lawrence committed
550
debug(const char *format, ...) {
551
	va_list args;
Evan Hunt's avatar
Evan Hunt committed
552
	isc_time_t t;
553

554
	if (debugging) {
555
		fflush(stdout);
556
		if (debugtiming) {
Evan Hunt's avatar
Evan Hunt committed
557
			TIME_NOW(&t);
558 559
			fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
				isc_time_nanoseconds(&t) / 1000);
560
		}
561
		va_start(args, format);
562 563 564 565
		vfprintf(stderr, format, args);
		va_end(args);
		fprintf(stderr, "\n");
	}
566 567
}

568
void
David Lawrence's avatar
David Lawrence committed
569
check_result(isc_result_t result, const char *msg) {
570
	if (result != ISC_R_SUCCESS) {
571
		fatal("%s: %s", msg, isc_result_totext(result));
572
	}
573 574
}

575
/*%
Michael Sawyer's avatar
Michael Sawyer committed
576 577 578 579
 * Create a server structure, which is part of the lookup structure.
 * This is little more than a linked list of servers to query in hopes
 * of finding the answer the user is looking for
 */
580
dig_server_t *
581
make_server(const char *servname, const char *userarg) {
582 583 584 585
	dig_server_t *srv;

	REQUIRE(servname != NULL);

586
	debug("make_server(%s)", servname);
587 588
	srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
	if (srv == NULL)
589
		fatal("memory allocation failure in %s:%d",
590
		      __FILE__, __LINE__);
591 592
	strlcpy(srv->servername, servname, MXNAME);
	strlcpy(srv->userarg, userarg, MXNAME);
593
	ISC_LINK_INIT(srv, link);
594 595
	return (srv);
}
596

597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
static int
addr2af(int lwresaddrtype)
{
	int af = 0;

	switch (lwresaddrtype) {
	case LWRES_ADDRTYPE_V4:
		af = AF_INET;
		break;

	case LWRES_ADDRTYPE_V6:
		af = AF_INET6;
		break;
	}

	return (af);
}
614

615
/*%
616 617 618
 * Create a copy of the server list from the lwres configuration structure.
 * The dest list must have already had ISC_LIST_INIT applied.
 */
619
static void
620 621
copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
	dig_server_t *newsrv;
Mark Andrews's avatar
Mark Andrews committed
622 623
	char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
		 sizeof("%4000000000")];
624 625 626 627 628 629 630
	int af;
	int i;

	debug("copy_server_list()");
	for (i = 0; i < confdata->nsnext; i++) {
		af = addr2af(confdata->nameservers[i].family);

631 632 633 634 635
		if (af == AF_INET && !have_ipv4)
			continue;
		if (af == AF_INET6 && !have_ipv6)
			continue;

636 637
		lwres_net_ntop(af, confdata->nameservers[i].address,
				   tmp, sizeof(tmp));
Mark Andrews's avatar
Mark Andrews committed
638 639 640 641 642 643
		if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
			char buf[sizeof("%4000000000")];
			snprintf(buf, sizeof(buf), "%%%u",
				 confdata->nameservers[i].zone);
			strlcat(tmp, buf, sizeof(tmp));
		}
644
		newsrv = make_server(tmp, tmp);
645 646 647 648
		ISC_LINK_INIT(newsrv, link);
		ISC_LIST_ENQUEUE(*dest, newsrv, link);
	}
}
649

650 651 652 653 654 655 656 657 658 659 660 661 662
void
flush_server_list(void) {
	dig_server_t *s, *ps;

	debug("flush_server_list()");
	s = ISC_LIST_HEAD(server_list);
	while (s != NULL) {
		ps = s;
		s = ISC_LIST_NEXT(s, link);
		ISC_LIST_DEQUEUE(server_list, ps, link);
		isc_mem_free(mctx, ps);
	}
}
663

664 665
void
set_nameserver(char *opt) {
666 667 668
	isc_result_t result;
	isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
	isc_netaddr_t netaddr;
Mark Andrews's avatar
Mark Andrews committed
669
	int count, i;
670
	dig_server_t *srv;
671
	char tmp[ISC_NETADDR_FORMATSIZE];
672 673 674 675

	if (opt == NULL)
		return;

676
	result = bind9_getaddresses(opt, 0, sockaddrs,
Automatic Updater's avatar
Automatic Updater committed
677
				    DIG_MAX_ADDRESSES, &count);
678 679 680 681
	if (result != ISC_R_SUCCESS)
		fatal("couldn't get address for '%s': %s",
		      opt, isc_result_totext(result));

682
	flush_server_list();
Automatic Updater's avatar
Automatic Updater committed
683

684 685 686 687 688 689 690 691
	for (i = 0; i < count; i++) {
		isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
		isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
		srv = make_server(tmp, opt);
		if (srv == NULL)
			fatal("memory allocation failure");
		ISC_LIST_APPEND(server_list, srv, link);
	}
692 693
}

694
static isc_result_t
Mark Andrews's avatar
Mark Andrews committed
695
add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
696 697 698 699 700 701

	int i = confdata->nsnext;

	if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
		return (ISC_R_FAILURE);

702 703 704 705 706 707 708 709 710 711 712 713 714 715
	switch (af) {
	case AF_INET:
		confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
		confdata->nameservers[i].length = NS_INADDRSZ;
		break;
	case AF_INET6:
		confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
		confdata->nameservers[i].length = NS_IN6ADDRSZ;
		break;
	default:
		return (ISC_R_FAILURE);
	}

	if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
716 717 718 719 720
		confdata->nsnext++;
		return (ISC_R_SUCCESS);
	}
	return (ISC_R_FAILURE);
}
721

722
/*%
Michael Sawyer's avatar
Michael Sawyer committed
723 724 725
 * Produce a cloned server list.  The dest list must have already had
 * ISC_LIST_INIT applied.
 */
726
void
727
clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
728 729 730 731 732
	dig_server_t *srv, *newsrv;

	debug("clone_server_list()");
	srv = ISC_LIST_HEAD(src);
	while (srv != NULL) {
733
		newsrv = make_server(srv->servername, srv->userarg);
734
		ISC_LINK_INIT(newsrv, link);
735 736 737 738 739
		ISC_LIST_ENQUEUE(*dest, newsrv, link);
		srv = ISC_LIST_NEXT(srv, link);
	}
}

740
/*%
Michael Sawyer's avatar
Michael Sawyer committed
741 742 743 744 745
 * Create an empty lookup structure, which holds all the information needed
 * to get an answer to a user's question.  This structure contains two
 * linked lists: the server list (servers to query) and the query list
 * (outstanding queries which have been made to the listed servers).
 */
746
dig_lookup_t *
747
make_empty_lookup(void) {
748 749
	dig_lookup_t *looknew;

Michael Sawyer's avatar
Michael Sawyer committed
750
	debug("make_empty_lookup()");
751

752
	INSIST(!free_now);
753

754
	looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
755
	if (looknew == NULL)
756
		fatal("memory allocation failure in %s:%d",
757
		       __FILE__, __LINE__);
758
	looknew->pending = ISC_TRUE;
Andreas Gustafsson's avatar
spacing  
Andreas Gustafsson committed
759
	looknew->textname[0] = 0;
760
	looknew->cmdline[0] = 0;
Ben Cottrell's avatar
Ben Cottrell committed
761
	looknew->rdtype = dns_rdatatype_a;
762
	looknew->qrdtype = dns_rdatatype_a;
Ben Cottrell's avatar
Ben Cottrell committed
763
	looknew->rdclass = dns_rdataclass_in;
Michael Sawyer's avatar
Michael Sawyer committed
764 765
	looknew->rdtypeset = ISC_FALSE;
	looknew->rdclassset = ISC_FALSE;
766
	looknew->sendspace = NULL;
767 768 769
	looknew->sendmsg = NULL;
	looknew->name = NULL;
	looknew->oname = NULL;
770 771
	looknew->timer = NULL;
	looknew->xfr_q = NULL;
Michael Sawyer's avatar
Michael Sawyer committed
772
	looknew->current_query = NULL;
773
	looknew->doing_xfr = ISC_FALSE;
774
	looknew->ixfr_serial = 0;
775 776 777
	looknew->trace = ISC_FALSE;
	looknew->trace_root = ISC_FALSE;
	looknew->identify = ISC_FALSE;
Ben Cottrell's avatar
Ben Cottrell committed
778
	looknew->identify_previous_line = ISC_FALSE;
Michael Sawyer's avatar
Michael Sawyer committed
779
	looknew->ignore = ISC_FALSE;
780
	looknew->servfail_stops = ISC_TRUE;
781
	looknew->besteffort = ISC_TRUE;
782
	looknew->dnssec = ISC_FALSE;
783
	looknew->ednsflags = 0;
784
	looknew->opcode = dns_opcode_query;
785
	looknew->expire = ISC_FALSE;
786
	looknew->nsid = ISC_FALSE;
787
	looknew->header_only = ISC_FALSE;
788 789 790
	looknew->sendcookie = ISC_FALSE;
	looknew->seenbadcookie = ISC_FALSE;
	looknew->badcookie = ISC_TRUE;
791 792 793
#ifdef DIG_SIGCHASE
	looknew->sigchase = ISC_FALSE;
#if DIG_SIGCHASE_TD
794
	looknew->do_topdown = ISC_FALSE;
795 796 797 798 799
	looknew->trace_root_sigchase = ISC_FALSE;
	looknew->rdtype_sigchaseset = ISC_FALSE;
	looknew->rdtype_sigchase = dns_rdatatype_any;
	looknew->qrdtype_sigchase = dns_rdatatype_any;
	looknew->rdclass_sigchase = dns_rdataclass_in;
800
	looknew->rdclass_sigchaseset = ISC_FALSE;
801 802
#endif
#endif
803
	looknew->udpsize = 0;
804
	looknew->edns = -1;
805
	looknew->recurse = ISC_TRUE;
Michael Sawyer's avatar
Michael Sawyer committed
806
	looknew->aaonly = ISC_FALSE;
807 808
	looknew->adflag = ISC_FALSE;
	looknew->cdflag = ISC_FALSE;
809
	looknew->zflag = ISC_FALSE;
810 811
	looknew->ns_search_only = ISC_FALSE;
	looknew->origin = NULL;
812
	looknew->tsigctx = NULL;
813 814 815 816
	looknew->querysig = NULL;
	looknew->retries = tries;
	looknew->nsfound = 0;
	looknew->tcp_mode = ISC_FALSE;
817
	looknew->tcp_mode_set = ISC_FALSE;
818
	looknew->ip6_int = ISC_FALSE;
819 820 821 822 823 824 825
	looknew->comments = ISC_TRUE;
	looknew->stats = ISC_TRUE;
	looknew->section_question = ISC_TRUE;
	looknew->section_answer = ISC_TRUE;
	looknew->section_authority = ISC_TRUE;
	looknew->section_additional = ISC_TRUE;
	looknew->new_search = ISC_FALSE;
826 827
	looknew->done_as_is = ISC_FALSE;
	looknew->need_search = ISC_FALSE;
Evan Hunt's avatar
Evan Hunt committed
828
	looknew->ecs_addr = NULL;
829
	looknew->cookie = NULL;
830 831
	looknew->ednsopts = NULL;
	looknew->ednsoptscnt = 0;