dighost.c 115 KB
Newer Older
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8 9
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
10 11
 */

12 13
/*! \file
 *  \note
14 15 16 17 18 19 20 21
 * 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.
 */

22
#include <errno.h>
23
#include <inttypes.h>
24
#include <limits.h>
25
#include <stdbool.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <unistd.h>
29

30 31
#ifdef HAVE_LOCALE_H
#include <locale.h>
32
#endif /* ifdef HAVE_LOCALE_H */
33

Michał Kępień's avatar
Michał Kępień committed
34
#ifdef HAVE_LIBIDN2
Tomas Hozza's avatar
Tomas Hozza committed
35
#include <idn2.h>
Michał Kępień's avatar
Michał Kępień committed
36
#endif /* HAVE_LIBIDN2 */
Tomas Hozza's avatar
Tomas Hozza committed
37

Michael Sawyer's avatar
Michael Sawyer committed
38 39
#include <isc/app.h>
#include <isc/base64.h>
40
#include <isc/file.h>
41
#include <isc/hex.h>
Michael Sawyer's avatar
Michael Sawyer committed
42
#include <isc/lang.h>
43
#include <isc/log.h>
44
#include <isc/netaddr.h>
45
#include <isc/netdb.h>
46
#include <isc/nonce.h>
47
#include <isc/parseint.h>
Mark Andrews's avatar
Mark Andrews committed
48
#include <isc/print.h>
49
#include <isc/random.h>
Michael Sawyer's avatar
Michael Sawyer committed
50
#include <isc/result.h>
51
#include <isc/safe.h>
52
#include <isc/serial.h>
Evan Hunt's avatar
Evan Hunt committed
53
#include <isc/sockaddr.h>
Michael Sawyer's avatar
Michael Sawyer committed
54 55 56 57 58
#include <isc/string.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/types.h>
#include <isc/util.h>
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73
#include <dns/byaddr.h>
#include <dns/fixedname.h>
#include <dns/log.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/rcode.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
#include <dns/tsig.h>
74

75 76
#include <isccfg/namedconf.h>

77 78
#include <bind9/getaddresses.h>
#include <dig/dig.h>
79 80 81 82
#include <dst/dst.h>
#include <dst/result.h>
#include <irs/resconf.h>
#include <pk11/site.h>
83

Ondřej Surý's avatar
Ondřej Surý committed
84
#if USE_PKCS11
85
#include <pk11/result.h>
86
#endif /* if USE_PKCS11 */
87

88 89
#if !defined(NS_INADDRSZ)
#define NS_INADDRSZ 4
90
#endif /* if !defined(NS_INADDRSZ) */
91

92 93
#if !defined(NS_IN6ADDRSZ)
#define NS_IN6ADDRSZ 16
94
#endif /* if !defined(NS_IN6ADDRSZ) */
95

Evan Hunt's avatar
Evan Hunt committed
96 97
dig_lookuplist_t lookup_list;
dig_serverlist_t server_list;
98
dig_searchlistlist_t search_list;
99

100 101 102 103
bool check_ra = false, have_ipv4 = false, have_ipv6 = false,
     specified_source = false, free_now = false, cancel_now = false,
     usesearch = false, showsearch = false, is_dst_up = false,
     keep_open = false, verbose = false, yaml = false;
Evan Hunt's avatar
Evan Hunt committed
104 105 106 107 108 109 110 111
in_port_t port = 53;
unsigned int timeout = 0;
unsigned int extrabytes;
isc_mem_t *mctx = NULL;
isc_log_t *lctx = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_task_t *global_task = NULL;
isc_timermgr_t *timermgr = NULL;
112
isc_socketmgr_t *socketmgr = NULL;
Evan Hunt's avatar
Evan Hunt committed
113 114 115 116 117 118 119 120
isc_sockaddr_t bind_address;
isc_sockaddr_t bind_any;
int sendcount = 0;
int recvcount = 0;
int sockcount = 0;
int ndots = -1;
int tries = 3;
int lookup_counter = 0;
121

122
static char servercookie[256];
123

Michał Kępień's avatar
Michał Kępień committed
124
#ifdef HAVE_LIBIDN2
Ondřej Surý's avatar
Ondřej Surý committed
125 126 127 128 129 130
static void
idn_locale_to_ace(const char *src, char *dst, size_t dstlen);
static void
idn_ace_to_locale(const char *src, char **dst);
static isc_result_t
idn_output_filter(isc_buffer_t *buffer, unsigned int used_org);
Michał Kępień's avatar
Michał Kępień committed
131
#endif /* HAVE_LIBIDN2 */
132

Evan Hunt's avatar
Evan Hunt committed
133
isc_socket_t *keep = NULL;
134 135
isc_sockaddr_t keepaddr;

136
/*%
137
 * Exit Codes:
138
 *
139 140 141 142 143 144
 *\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
145
 */
Evan Hunt's avatar
Evan Hunt committed
146 147 148 149 150 151 152
int exitcode = 0;
int fatalexit = 0;
char keynametext[MXNAME];
char keyfile[MXNAME] = "";
char keysecret[MXNAME] = "";
unsigned char cookie_secret[33];
unsigned char cookie[8];
153
const dns_name_t *hmacname = NULL;
Evan Hunt's avatar
Evan Hunt committed
154 155 156 157 158 159 160 161 162 163 164
unsigned int digestbits = 0;
isc_buffer_t *namebuf = NULL;
dns_tsigkey_t *tsigkey = NULL;
bool validated = true;
isc_mempool_t *commctx = NULL;
bool debugging = false;
bool debugtiming = false;
bool memdebugging = false;
char *progname = NULL;
isc_mutex_t lookup_lock;
dig_lookup_t *current_lookup = NULL;
165

166 167
#define DIG_MAX_ADDRESSES 20

168
/*%
169
 * Apply and clear locks at the event level in global task.
170
 * Can I get rid of these using shutdown events?  XXX
171
 */
172 173 174 175 176 177 178 179 180 181 182 183 184
#define LOCK_LOOKUP                                                       \
	{                                                                 \
		debug("lock_lookup %s:%d", __FILE__, __LINE__);           \
		check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_" \
							     "lock");     \
		debug("success");                                         \
	}
#define UNLOCK_LOOKUP                                                       \
	{                                                                   \
		debug("unlock_lookup %s:%d", __FILE__, __LINE__);           \
		check_result(isc_mutex_unlock((&lookup_lock)), "isc_mutex_" \
							       "unlock");   \
	}
185

186
static void
Evan Hunt's avatar
Evan Hunt committed
187
default_warnerr(const char *format, ...) {
188 189 190 191 192 193 194
	va_list args;

	printf(";; ");
	va_start(args, format);
	vprintf(format, args);
	va_end(args);
	printf("\n");
195
}
196 197

static void
Evan Hunt's avatar
Evan Hunt committed
198
default_comments(dig_lookup_t *lookup, const char *format, ...) {
199 200 201 202 203 204 205 206 207
	va_list args;

	if (lookup->comments) {
		printf(";; ");
		va_start(args, format);
		vprintf(format, args);
		va_end(args);
		printf("\n");
	}
208
}
209

210 211
/* dynamic callbacks */

Evan Hunt's avatar
Evan Hunt committed
212
isc_result_t (*dighost_printmessage)(dig_query_t *query,
213 214
				     const isc_buffer_t *msgbuf,
				     dns_message_t *msg, bool headers);
215

216
void (*dighost_error)(const char *format, ...) = default_warnerr;
217

218
void (*dighost_warning)(const char *format, ...) = default_warnerr;
219

220 221
void (*dighost_comments)(dig_lookup_t *lookup, const char *format,
			 ...) = default_comments;
Evan Hunt's avatar
Evan Hunt committed
222

223 224
void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from,
			 dig_query_t *query);
225

226
void (*dighost_trying)(char *frm, dig_lookup_t *lookup);
227

228
void (*dighost_shutdown)(void);
229 230 231

/* forward declarations */

Ondřej Surý's avatar
Ondřej Surý committed
232 233
static void
cancel_lookup(dig_lookup_t *lookup);
234

Ondřej Surý's avatar
Ondřej Surý committed
235 236
static void
recv_done(isc_task_t *task, isc_event_t *event);
Michael Sawyer's avatar
Michael Sawyer committed
237

Ondřej Surý's avatar
Ondřej Surý committed
238 239
static void
send_udp(dig_query_t *query);
240

Ondřej Surý's avatar
Ondřej Surý committed
241 242
static void
connect_timeout(isc_task_t *task, isc_event_t *event);
Michael Sawyer's avatar
Michael Sawyer committed
243

Ondřej Surý's avatar
Ondřej Surý committed
244 245
static void
launch_next_query(dig_query_t *query, bool include_question);
246

Ondřej Surý's avatar
Ondřej Surý committed
247 248
static void
check_next_lookup(dig_lookup_t *lookup);
249

Ondřej Surý's avatar
Ondřej Surý committed
250 251
static bool
next_origin(dig_lookup_t *oldlookup);
252

253
static int
Evan Hunt's avatar
Evan Hunt committed
254
count_dots(char *string) {
255
	char *s;
Evan Hunt's avatar
Evan Hunt committed
256
	int i = 0;
257 258

	s = string;
259
	while (*s != '\0') {
260
		if (*s == '.') {
261
			i++;
262
		}
263 264 265 266 267
		s++;
	}
	return (i);
}

268
static void
Evan Hunt's avatar
Evan Hunt committed
269
hex_dump(isc_buffer_t *b) {
270
	unsigned int len, i;
271 272
	isc_region_t r;

273
	isc_buffer_usedregion(b, &r);
274

Mark Andrews's avatar
Mark Andrews committed
275
	printf("%u bytes\n", r.length);
276
	for (len = 0; len < r.length; len++) {
277
		printf("%02x ", r.base[len]);
278 279 280
		if (len % 16 == 15) {
			fputs("         ", stdout);
			for (i = len - 15; i <= len; i++) {
281
				if (r.base[i] >= '!' && r.base[i] <= '}') {
282
					putchar(r.base[i]);
283
				} else {
284
					putchar('.');
285
				}
286
			}
287
			printf("\n");
288
		}
289
	}
290
	if (len % 16 != 0) {
291
		for (i = len; (i % 16) != 0; i++) {
292
			fputs("   ", stdout);
293
		}
294
		fputs("         ", stdout);
295
		for (i = ((len >> 4) << 4); i < len; i++) {
296
			if (r.base[i] >= '!' && r.base[i] <= '}') {
297
				putchar(r.base[i]);
298
			} else {
299
				putchar('.');
300
			}
301
		}
302
		printf("\n");
303
	}
304 305
}

306
/*%
307 308 309 310
 * Append 'len' bytes of 'text' at '*p', failing with
 * ISC_R_NOSPACE if that would advance p past 'end'.
 */
static isc_result_t
Evan Hunt's avatar
Evan Hunt committed
311
append(const char *text, size_t len, char **p, char *end) {
312
	if (*p + len > end) {
313
		return (ISC_R_NOSPACE);
314
	}
315
	memmove(*p, text, len);
316 317 318 319 320
	*p += len;
	return (ISC_R_SUCCESS);
}

static isc_result_t
Evan Hunt's avatar
Evan Hunt committed
321
reverse_octets(const char *in, char **p, char *end) {
322
	const char *dot = strchr(in, '.');
Evan Hunt's avatar
Evan Hunt committed
323
	size_t len;
324 325 326
	if (dot != NULL) {
		isc_result_t result;
		result = reverse_octets(dot + 1, p, end);
327
		if (result != ISC_R_SUCCESS) {
328
			return (result);
329
		}
330
		result = append(".", 1, p, end);
331
		if (result != ISC_R_SUCCESS) {
332
			return (result);
333
		}
334
		len = (int)(dot - in);
335
	} else {
336
		len = (int)strlen(in);
337 338 339
	}
	return (append(in, len, p, end));
}
340 341

isc_result_t
Evan Hunt's avatar
Evan Hunt committed
342 343 344
get_reverse(char *reverse, size_t len, char *value, bool strict) {
	int r;
	isc_result_t result;
345
	isc_netaddr_t addr;
346

347
	addr.family = AF_INET6;
Andreas Gustafsson's avatar
spacing  
Andreas Gustafsson committed
348
	r = inet_pton(AF_INET6, value, &addr.type.in6);
349 350
	if (r > 0) {
		/* This is a valid IPv6 address. */
351
		dns_fixedname_t fname;
Evan Hunt's avatar
Evan Hunt committed
352 353
		dns_name_t *name;
		unsigned int options = 0;
Mark Andrews's avatar
Mark Andrews committed
354

355
		name = dns_fixedname_initname(&fname);
356
		result = dns_byaddr_createptrname(&addr, options, name);
357
		if (result != ISC_R_SUCCESS) {
358
			return (result);
359
		}
360
		dns_name_format(name, reverse, (unsigned int)len);
361 362 363 364 365 366 367 368 369 370 371
		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;
372
		char *end = reverse + len;
373
		if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) {
Michael Graff's avatar
Michael Graff committed
374
			return (DNS_R_BADDOTTEDQUAD);
375
		}
376
		result = reverse_octets(value, &p, end);
377
		if (result != ISC_R_SUCCESS) {
378
			return (result);
379
		}
380 381
		/* Append .in-addr.arpa. and a terminating NUL. */
		result = append(".in-addr.arpa.", 15, &p, end);
382
		if (result != ISC_R_SUCCESS) {
383
			return (result);
384
		}
385
		return (ISC_R_SUCCESS);
386 387 388
	}
}

389 390 391
void (*dighost_pre_exit_hook)(void) = NULL;

#if TARGET_OS_IPHONE
392
void
Evan Hunt's avatar
Evan Hunt committed
393
warn(const char *format, ...) {
394 395 396 397 398 399 400 401 402
	va_list args;

	fflush(stdout);
	fprintf(stderr, ";; Warning: ");
	va_start(args, format);
	vfprintf(stderr, format, args);
	va_end(args);
	fprintf(stderr, "\n");
}
403
#else  /* if TARGET_OS_IPHONE */
404
void
Evan Hunt's avatar
Evan Hunt committed
405
warn(const char *format, ...) {
406 407
	va_list args;

408
	fflush(stdout);
409
	fprintf(stderr, "%s: ", progname);
410
	va_start(args, format);
411 412 413
	vfprintf(stderr, format, args);
	va_end(args);
	fprintf(stderr, "\n");
414
}
415
#endif /* if TARGET_OS_IPHONE */
416 417

void
Evan Hunt's avatar
Evan Hunt committed
418
digexit(void) {
419
	if (exitcode < 10) {
420
		exitcode = 10;
421 422
	}
	if (fatalexit != 0) {
423
		exitcode = fatalexit;
424
	}
425 426 427
	if (dighost_pre_exit_hook != NULL) {
		dighost_pre_exit_hook();
	}
428
	exit(exitcode);
429 430
}

431
void
Evan Hunt's avatar
Evan Hunt committed
432
fatal(const char *format, ...) {
433 434 435 436 437 438 439 440 441 442 443
	va_list args;

	fflush(stdout);
	fprintf(stderr, "%s: ", progname);
	va_start(args, format);
	vfprintf(stderr, format, args);
	va_end(args);
	fprintf(stderr, "\n");
	digexit();
}

444
void
Evan Hunt's avatar
Evan Hunt committed
445 446
debug(const char *format, ...) {
	va_list args;
Evan Hunt's avatar
Evan Hunt committed
447
	isc_time_t t;
448

449
	if (debugging) {
450
		fflush(stdout);
451
		if (debugtiming) {
Evan Hunt's avatar
Evan Hunt committed
452
			TIME_NOW(&t);
Mark Andrews's avatar
Mark Andrews committed
453
			fprintf(stderr, "%u.%06u: ", isc_time_seconds(&t),
454
				isc_time_nanoseconds(&t) / 1000);
455
		}
456
		va_start(args, format);
457 458 459 460
		vfprintf(stderr, format, args);
		va_end(args);
		fprintf(stderr, "\n");
	}
461 462
}

463
void
Evan Hunt's avatar
Evan Hunt committed
464
check_result(isc_result_t result, const char *msg) {
465
	if (result != ISC_R_SUCCESS) {
466
		fatal("%s: %s", msg, isc_result_totext(result));
467
	}
468 469
}

470
/*%
Michael Sawyer's avatar
Michael Sawyer committed
471 472 473 474
 * 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
 */
475
dig_server_t *
Evan Hunt's avatar
Evan Hunt committed
476
make_server(const char *servname, const char *userarg) {
477 478 479 480
	dig_server_t *srv;

	REQUIRE(servname != NULL);

481
	debug("make_server(%s)", servname);
482
	srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
483 484
	strlcpy(srv->servername, servname, MXNAME);
	strlcpy(srv->userarg, userarg, MXNAME);
485
	ISC_LINK_INIT(srv, link);
486 487
	return (srv);
}
488

489
/*%
490
 * Create a copy of the server list from the resolver configuration structure.
491 492
 * The dest list must have already had ISC_LIST_INIT applied.
 */
493
static void
Evan Hunt's avatar
Evan Hunt committed
494
get_server_list(irs_resconf_t *resconf) {
495
	isc_sockaddrlist_t *servers;
Evan Hunt's avatar
Evan Hunt committed
496 497
	isc_sockaddr_t *sa;
	dig_server_t *newsrv;
Mark Andrews's avatar
Mark Andrews committed
498 499
	char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
		 sizeof("%4000000000")];
500 501
	debug("get_server_list()");
	servers = irs_resconf_getnameservers(resconf);
502 503
	for (sa = ISC_LIST_HEAD(*servers); sa != NULL;
	     sa = ISC_LIST_NEXT(sa, link)) {
Evan Hunt's avatar
Evan Hunt committed
504
		int pf = isc_sockaddr_pf(sa);
505
		isc_netaddr_t na;
Evan Hunt's avatar
Evan Hunt committed
506 507
		isc_result_t result;
		isc_buffer_t b;
508

509
		if (pf == AF_INET && !have_ipv4) {
510
			continue;
511 512
		}
		if (pf == AF_INET6 && !have_ipv6) {
513
			continue;
514
		}
515

516 517 518
		isc_buffer_init(&b, tmp, sizeof(tmp));
		isc_netaddr_fromsockaddr(&na, sa);
		result = isc_netaddr_totext(&na, &b);
519
		if (result != ISC_R_SUCCESS) {
520
			continue;
521
		}
522 523
		isc_buffer_putuint8(&b, 0);
		if (pf == AF_INET6 && na.zone != 0) {
Mark Andrews's avatar
Mark Andrews committed
524
			char buf[sizeof("%4000000000")];
525
			snprintf(buf, sizeof(buf), "%%%u", na.zone);
Mark Andrews's avatar
Mark Andrews committed
526 527
			strlcat(tmp, buf, sizeof(tmp));
		}
528
		newsrv = make_server(tmp, tmp);
529
		ISC_LINK_INIT(newsrv, link);
530
		ISC_LIST_APPEND(server_list, newsrv, link);
531 532
	}
}
533

534
void
Evan Hunt's avatar
Evan Hunt committed
535
flush_server_list(void) {
536 537 538 539 540 541 542 543 544 545 546
	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);
	}
}
547

548
void
Evan Hunt's avatar
Evan Hunt committed
549 550
set_nameserver(char *opt) {
	isc_result_t result;
551
	isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
Evan Hunt's avatar
Evan Hunt committed
552 553 554 555
	isc_netaddr_t netaddr;
	int count, i;
	dig_server_t *srv;
	char tmp[ISC_NETADDR_FORMATSIZE];
556

557
	if (opt == NULL) {
558
		return;
559
	}
560

561 562
	result = bind9_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES,
				    &count);
563
	if (result != ISC_R_SUCCESS) {
564 565
		fatal("couldn't get address for '%s': %s", opt,
		      isc_result_totext(result));
566
	}
567

568
	flush_server_list();
Automatic Updater's avatar
Automatic Updater committed
569

570 571 572 573
	for (i = 0; i < count; i++) {
		isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
		isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
		srv = make_server(tmp, opt);
574
		if (srv == NULL) {
575
			fatal("memory allocation failure");
576
		}
577 578
		ISC_LIST_APPEND(server_list, srv, link);
	}
579 580
}

581
/*%
Michael Sawyer's avatar
Michael Sawyer committed
582 583 584
 * Produce a cloned server list.  The dest list must have already had
 * ISC_LIST_INIT applied.
 */
585
void
Evan Hunt's avatar
Evan Hunt committed
586
clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
587 588 589 590 591
	dig_server_t *srv, *newsrv;

	debug("clone_server_list()");
	srv = ISC_LIST_HEAD(src);
	while (srv != NULL) {
592
		newsrv = make_server(srv->servername, srv->userarg);
593
		ISC_LINK_INIT(newsrv, link);
594 595 596 597 598
		ISC_LIST_ENQUEUE(*dest, newsrv, link);
		srv = ISC_LIST_NEXT(srv, link);
	}
}

599
/*%
Michael Sawyer's avatar
Michael Sawyer committed
600 601 602 603 604
 * 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).
 */
605
dig_lookup_t *
Evan Hunt's avatar
Evan Hunt committed
606
make_empty_lookup(void) {
607 608
	dig_lookup_t *looknew;

Michael Sawyer's avatar
Michael Sawyer committed
609
	debug("make_empty_lookup()");
610

611
	INSIST(!free_now);
612

613
	looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
614
	looknew->pending = true;
Andreas Gustafsson's avatar
spacing  
Andreas Gustafsson committed
615
	looknew->textname[0] = 0;
616
	looknew->cmdline[0] = 0;
Ben Cottrell's avatar
Ben Cottrell committed
617
	looknew->rdtype = dns_rdatatype_a;
618
	looknew->qrdtype = dns_rdatatype_a;
Ben Cottrell's avatar
Ben Cottrell committed
619
	looknew->rdclass = dns_rdataclass_in;
620 621
	looknew->rdtypeset = false;
	looknew->rdclassset = false;
622
	looknew->sendspace = NULL;
623 624 625
	looknew->sendmsg = NULL;
	looknew->name = NULL;
	looknew->oname = NULL;
626
	looknew->xfr_q = NULL;
Michael Sawyer's avatar
Michael Sawyer committed
627
	looknew->current_query = NULL;
628
	looknew->doing_xfr = false;
629
	looknew->ixfr_serial = 0;
630 631 632 633 634 635 636 637
	looknew->trace = false;
	looknew->trace_root = false;
	looknew->identify = false;
	looknew->identify_previous_line = false;
	looknew->ignore = false;
	looknew->servfail_stops = true;
	looknew->besteffort = true;
	looknew->dnssec = false;
638
	looknew->ednsflags = 0;
639
	looknew->opcode = dns_opcode_query;
640 641 642
	looknew->expire = false;
	looknew->nsid = false;
	looknew->tcp_keepalive = false;
643
	looknew->padding = 0;
644 645 646 647 648 649 650 651 652 653 654
	looknew->header_only = false;
	looknew->sendcookie = false;
	looknew->seenbadcookie = false;
	looknew->badcookie = true;
	looknew->multiline = false;
	looknew->nottl = false;
	looknew->noclass = false;
	looknew->onesoa = false;
	looknew->use_usec = false;
	looknew->nocrypto = false;
	looknew->ttlunits = false;
655
	looknew->expandaaaa = false;
656
	looknew->qr = false;
657
	looknew->accept_reply_unexpected_src = false;
Michał Kępień's avatar
Michał Kępień committed
658
#ifdef HAVE_LIBIDN2
659
	looknew->idnin = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
660
	looknew->idnout = looknew->idnin;
661
#else  /* ifdef HAVE_LIBIDN2 */
662 663
	looknew->idnin = false;
	looknew->idnout = false;
Michał Kępień's avatar
Michał Kępień committed
664
#endif /* HAVE_LIBIDN2 */
665
	looknew->udpsize = 0;
666
	looknew->edns = -1;
667 668 669 670 671 672 673 674 675
	looknew->recurse = true;
	looknew->aaonly = false;
	looknew->adflag = false;
	looknew->cdflag = false;
	looknew->raflag = false;
	looknew->tcflag = false;
	looknew->print_unknown_format = false;
	looknew->zflag = false;
	looknew->ns_search_only = false;
676
	looknew->origin = NULL;
677
	looknew->tsigctx = NULL;
678 679 680
	looknew->querysig = NULL;
	looknew->retries = tries;
	looknew->nsfound = 0;
681 682 683 684 685 686 687 688 689 690 691
	looknew->tcp_mode = false;
	looknew->tcp_mode_set = false;
	looknew->comments = true;
	looknew->stats = true;
	looknew->section_question = true;
	looknew->section_answer = true;
	looknew->section_authority = true;
	looknew->section_additional = true;
	looknew->new_search = false;
	looknew->done_as_is = false;
	looknew->need_search = false;
Evan Hunt's avatar
Evan Hunt committed
692
	looknew->ecs_addr = NULL;
693
	looknew->cookie = NULL;
694 695
	looknew->ednsopts = NULL;
	looknew->ednsoptscnt = 0;
696 697
	looknew->ednsneg = true;
	looknew->mapped = true;
698
	looknew->dscp = -1;
699
	looknew->rrcomments = 0;
700
	looknew->eoferr = 0;
701
	dns_fixedname_init(&looknew->fdomain);
702
	ISC_LINK_INIT(looknew, link);
703
	ISC_LIST_INIT(looknew->q);
704
	ISC_LIST_INIT(looknew->connecting);
705
	ISC_LIST_INIT(looknew->my_server_list);
706 707 708
	return (looknew);
}

709 710 711
#define EDNSOPT_OPTIONS 100U

static void
Evan Hunt's avatar
Evan Hunt committed
712
cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) {
713 714 715 716 717 718 719 720 721
	size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS;
	size_t i;
	looknew->ednsopts = isc_mem_allocate(mctx, len);
	for (i = 0; i < EDNSOPT_OPTIONS; i++) {
		looknew->ednsopts[i].code = 0;
		looknew->ednsopts[i].length = 0;
		looknew->ednsopts[i].value = NULL;
	}
	looknew->ednsoptscnt = 0;
722
	if (lookold == NULL || lookold->ednsopts == NULL) {
723
		return;
724
	}
725 726 727 728 729

	for (i = 0; i < lookold->ednsoptscnt; i++) {
		len = lookold->ednsopts[i].length;
		if (len != 0) {
			INSIST(lookold->ednsopts[i].value != NULL);
Evan Hunt's avatar
Evan Hunt committed
730 731
			looknew->ednsopts[i].value = isc_mem_allocate(mctx,
								      len);
732 733 734 735 736 737 738 739 740
			memmove(looknew->ednsopts[i].value,
				lookold->ednsopts[i].value, len);
		}
		looknew->ednsopts[i].code = lookold->ednsopts[i].code;
		looknew->ednsopts[i].length = len;
	}
	looknew->ednsoptscnt = lookold->ednsoptscnt;
}

741
/*%
Michael Sawyer's avatar
Michael Sawyer committed
742 743 744
 * Clone a lookup, perhaps copying the server list.  This does not clone
 * the query list, since it will be regenerated by the setup_lookup()
 * function, nor does it queue up the new lookup for processing.
745
 * Caution: If you don't clone the servers, you MUST clone the server
Francis Dupont's avatar
Francis Dupont committed
746
 * list separately from somewhere else, or construct it by hand.
747
 */
748
dig_lookup_t *
Evan Hunt's avatar
Evan Hunt committed
749
clone_lookup(dig_lookup_t *lookold, bool servers) {
750 751 752 753 754 755 756 757
	dig_lookup_t *looknew;

	debug("clone_lookup()");

	INSIST(!free_now);

	looknew = make_empty_lookup();
	INSIST(looknew != NULL);
Evan Hunt's avatar
Evan Hunt committed
758 759
	strlcpy(looknew->textname, lookold->textname, MXNAME);
	strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
760
	looknew->textname[MXNAME - 1] = 0;
761
	looknew->rdtype = lookold->rdtype;
762
	looknew->qrdtype = lookold->qrdtype;
763
	looknew->rdclass = lookold->rdclass;
Michael Sawyer's avatar
Michael Sawyer committed
764 765
	looknew->rdtypeset = lookold->rdtypeset;
	looknew->rdclassset = lookold->rdclassset;
766
	looknew->doing_xfr = lookold->doing_xfr;
Michael Sawyer's avatar
Michael Sawyer committed
767
	looknew->ixfr_serial = lookold->ixfr_serial;
768 769 770
	looknew->trace = lookold->trace;
	looknew->trace_root = lookold->trace_root;
	looknew->identify = lookold->identify;
Ben Cottrell's avatar
Ben Cottrell committed
771
	looknew->identify_previous_line = lookold->identify_previous_line;
Michael Sawyer's avatar
Michael Sawyer committed
772
	looknew->ignore = lookold->ignore;
773
	looknew->servfail_stops = lookold->servfail_stops;
774
	looknew->besteffort = lookold->besteffort;
775
	looknew->dnssec = lookold->dnssec;
776
	looknew->ednsflags = lookold->ednsflags;