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

Line Branch Exec Source
1
/*
2
 * Copyright (C) 2004-2007  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: nslookup.c,v 1.101.18.15 2007/08/28 07:19:55 tbox Exp $ */
19
20
#include <config.h>
21
22
#include <stdlib.h>
23
#include <unistd.h>
24
25
#include <arpa/nameser.h>
26
27
#include <isc/app.h>
28
#include <isc/buffer.h>
29
#include <isc/commandline.h>
30
#include <isc/event.h>
31
#include <isc/parseint.h>
32
#include <isc/string.h>
33
#include <isc/timer.h>
34
#include <isc/util.h>
35
#include <isc/task.h>
36
#include <isc/netaddr.h>
37
38
#include <dns/message.h>
39
#include <dns/name.h>
40
#include <dns/fixedname.h>
41
#include <dns/rdata.h>
42
#include <dns/rdataclass.h>
43
#include <dns/rdataset.h>
44
#include <dns/rdatastruct.h>
45
#include <dns/rdatatype.h>
46
#include <dns/byaddr.h>
47
48
#include <dig/dig.h>
49
50
static isc_boolean_t short_form = ISC_TRUE,
51
	tcpmode = ISC_FALSE,
52
	identify = ISC_FALSE, stats = ISC_TRUE,
53
	comments = ISC_TRUE, section_question = ISC_TRUE,
54
	section_answer = ISC_TRUE, section_authority = ISC_TRUE,
55
	section_additional = ISC_TRUE, recurse = ISC_TRUE,
56
	aaonly = ISC_FALSE, nofail = ISC_TRUE;
57
58
static isc_boolean_t in_use = ISC_FALSE;
59
static char defclass[MXRD] = "IN";
60
static char deftype[MXRD] = "A";
61
static isc_event_t *global_event = NULL;
62
63
static char domainopt[DNS_NAME_MAXTEXT];
64
65
static const char *rcodetext[] = {
66
	"NOERROR",
67
	"FORMERR",
68
	"SERVFAIL",
69
	"NXDOMAIN",
70
	"NOTIMP",
71
	"REFUSED",
72
	"YXDOMAIN",
73
	"YXRRSET",
74
	"NXRRSET",
75
	"NOTAUTH",
76
	"NOTZONE",
77
	"RESERVED11",
78
	"RESERVED12",
79
	"RESERVED13",
80
	"RESERVED14",
81
	"RESERVED15",
82
	"BADVERS"
83
};
84
85
static const char *rtypetext[] = {
86
	"rtype_0 = ",			/* 0 */
87
	"internet address = ",		/* 1 */
88
	"nameserver = ",		/* 2 */
89
	"md = ",			/* 3 */
90
	"mf = ",			/* 4 */
91
	"canonical name = ",		/* 5 */
92
	"soa = ",			/* 6 */
93
	"mb = ",			/* 7 */
94
	"mg = ",			/* 8 */
95
	"mr = ",			/* 9 */
96
	"rtype_10 = ",			/* 10 */
97
	"protocol = ",			/* 11 */
98
	"name = ",			/* 12 */
99
	"hinfo = ",			/* 13 */
100
	"minfo = ",			/* 14 */
101
	"mail exchanger = ",		/* 15 */
102
	"text = ",			/* 16 */
103
	"rp = ",       			/* 17 */
104
	"afsdb = ",			/* 18 */
105
	"x25 address = ",		/* 19 */
106
	"isdn address = ",		/* 20 */
107
	"rt = ",			/* 21 */
108
	"nsap = ",			/* 22 */
109
	"nsap_ptr = ",			/* 23 */
110
	"signature = ",			/* 24 */
111
	"key = ",			/* 25 */
112
	"px = ",			/* 26 */
113
	"gpos = ",			/* 27 */
114
	"has AAAA address ",		/* 28 */
115
	"loc = ",			/* 29 */
116
	"next = ",			/* 30 */
117
	"rtype_31 = ",			/* 31 */
118
	"rtype_32 = ",			/* 32 */
119
	"service = ",			/* 33 */
120
	"rtype_34 = ",			/* 34 */
121
	"naptr = ",			/* 35 */
122
	"kx = ",			/* 36 */
123
	"cert = ",			/* 37 */
124
	"v6 address = ",		/* 38 */
125
	"dname = ",			/* 39 */
126
	"rtype_40 = ",			/* 40 */
127
	"optional = "			/* 41 */
128
};
129
130
#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
131
132
static void flush_lookup_list(void);
133
static void getinput(isc_task_t *task, isc_event_t *event);
134
135
void
136
dighost_shutdown(void) {
137
	isc_event_t *event = global_event;
138
139
	flush_lookup_list();
140
	debug("dighost_shutdown()");
141
142
	if (!in_use) {
143
		isc_app_shutdown();
144
		return;
145
	}
146
147
	isc_task_send(global_task, &event);
148
}
149
150
static void
151
printsoa(dns_rdata_t *rdata) {
152
	dns_rdata_soa_t soa;
153
	isc_result_t result;
154
	char namebuf[DNS_NAME_FORMATSIZE];
155
156
	result = dns_rdata_tostruct(rdata, &soa, NULL);
157
	check_result(result, "dns_rdata_tostruct");
158
159
	dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
160
	printf("\torigin = %s\n", namebuf);
161
	dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
162
	printf("\tmail addr = %s\n", namebuf);
163
	printf("\tserial = %u\n", soa.serial);
164
	printf("\trefresh = %u\n", soa.refresh);
165
	printf("\tretry = %u\n", soa.retry);
166
	printf("\texpire = %u\n", soa.expire);
167
	printf("\tminimum = %u\n", soa.minimum);
168
	dns_rdata_freestruct(&soa);
169
}
170
171
static void
172
printa(dns_rdata_t *rdata) {
173
	isc_result_t result;
174
	char text[sizeof("255.255.255.255")];
175
	isc_buffer_t b;
176
177
	isc_buffer_init(&b, text, sizeof(text));
178
	result = dns_rdata_totext(rdata, NULL, &b);
179
	check_result(result, "dns_rdata_totext");
180
	printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
181
	       (char *)isc_buffer_base(&b));
182
}
183
#ifdef DIG_SIGCHASE
184
/* Just for compatibility : not use in host program */
185
isc_result_t
186
printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
187
	      isc_buffer_t *target)
188
{
189
	UNUSED(owner_name);
190
	UNUSED(rdataset);
191
	UNUSED(target);
192
	return(ISC_FALSE);
193
}
194
#endif
195
static void
196
printrdata(dns_rdata_t *rdata) {
197
	isc_result_t result;
198
	isc_buffer_t *b = NULL;
199
	unsigned int size = 1024;
200
	isc_boolean_t done = ISC_FALSE;
201
202
	if (rdata->type < N_KNOWN_RRTYPES)
203
		printf("%s", rtypetext[rdata->type]);
204
	else
205
		printf("rdata_%d = ", rdata->type);
206
207
	while (!done) {
208
		result = isc_buffer_allocate(mctx, &b, size);
209
		if (result != ISC_R_SUCCESS)
210
			check_result(result, "isc_buffer_allocate");
211
		result = dns_rdata_totext(rdata, NULL, b);
212
		if (result == ISC_R_SUCCESS) {
213
			printf("%.*s\n", (int)isc_buffer_usedlength(b),
214
			       (char *)isc_buffer_base(b));
215
			done = ISC_TRUE;
216
		} else if (result != ISC_R_NOSPACE)
217
			check_result(result, "dns_rdata_totext");
218
		isc_buffer_free(&b);
219
		size *= 2;
220
	}
221
}
222
223
static isc_result_t
224
printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
225
	     dns_section_t section) {
226
	isc_result_t result, loopresult;
227
	dns_name_t *name;
228
	dns_rdataset_t *rdataset = NULL;
229
	dns_rdata_t rdata = DNS_RDATA_INIT;
230
	char namebuf[DNS_NAME_FORMATSIZE];
231
232
	UNUSED(query);
233
	UNUSED(headers);
234
235
	debug("printsection()");
236
237
	result = dns_message_firstname(msg, section);
238
	if (result == ISC_R_NOMORE)
239
		return (ISC_R_SUCCESS);
240
	else if (result != ISC_R_SUCCESS)
241
		return (result);
242
	for (;;) {
243
		name = NULL;
244
		dns_message_currentname(msg, section,
245
					&name);
246
		for (rdataset = ISC_LIST_HEAD(name->list);
247
		     rdataset != NULL;
248
		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
249
			loopresult = dns_rdataset_first(rdataset);
250
			while (loopresult == ISC_R_SUCCESS) {
251
				dns_rdataset_current(rdataset, &rdata);
252
				switch (rdata.type) {
253
				case dns_rdatatype_a:
254
					if (section != DNS_SECTION_ANSWER)
255
						goto def_short_section;
256
					dns_name_format(name, namebuf,
257
							sizeof(namebuf));
258
					printf("Name:\t%s\n", namebuf);
259
					printa(&rdata);
260
					break;
261
				case dns_rdatatype_soa:
262
					dns_name_format(name, namebuf,
263
							sizeof(namebuf));
264
					printf("%s\n", namebuf);
265
					printsoa(&rdata);
266
					break;
267
				default:
268
				def_short_section:
269
					dns_name_format(name, namebuf,
270
							sizeof(namebuf));
271
					printf("%s\t", namebuf);
272
					printrdata(&rdata);
273
					break;
274
				}
275
				dns_rdata_reset(&rdata);
276
				loopresult = dns_rdataset_next(rdataset);
277
			}
278
		}
279
		result = dns_message_nextname(msg, section);
280
		if (result == ISC_R_NOMORE)
281
			break;
282
		else if (result != ISC_R_SUCCESS) {
283
			return (result);
284
		}
285
	}
286
	return (ISC_R_SUCCESS);
287
}
288
289
static isc_result_t
290
detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
291
	     dns_section_t section) {
292
	isc_result_t result, loopresult;
293
	dns_name_t *name;
294
	dns_rdataset_t *rdataset = NULL;
295
	dns_rdata_t rdata = DNS_RDATA_INIT;
296
	char namebuf[DNS_NAME_FORMATSIZE];
297
298
	UNUSED(query);
299
300
	debug("detailsection()");
301
302
	if (headers) {
303
		switch (section) {
304
		case DNS_SECTION_QUESTION:
305
			puts("    QUESTIONS:");
306
			break;
307
		case DNS_SECTION_ANSWER:
308
			puts("    ANSWERS:");
309
			break;
310
		case DNS_SECTION_AUTHORITY:
311
			puts("    AUTHORITY RECORDS:");
312
			break;
313
		case DNS_SECTION_ADDITIONAL:
314
			puts("    ADDITIONAL RECORDS:");
315
			break;
316
		}
317
	}
318
319
	result = dns_message_firstname(msg, section);
320
	if (result == ISC_R_NOMORE)
321
		return (ISC_R_SUCCESS);
322
	else if (result != ISC_R_SUCCESS)
323
		return (result);
324
	for (;;) {
325
		name = NULL;
326
		dns_message_currentname(msg, section,
327
					&name);
328
		for (rdataset = ISC_LIST_HEAD(name->list);
329
		     rdataset != NULL;
330
		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
331
			if (section == DNS_SECTION_QUESTION) {
332
				dns_name_format(name, namebuf,
333
						sizeof(namebuf));
334
				printf("\t%s, ", namebuf);
335
				dns_rdatatype_format(rdataset->type,
336
						     namebuf,
337
						     sizeof(namebuf));
338
				printf("type = %s, ", namebuf);
339
				dns_rdataclass_format(rdataset->rdclass,
340
						      namebuf,
341
						      sizeof(namebuf));
342
				printf("class = %s\n", namebuf);
343
			}
344
			loopresult = dns_rdataset_first(rdataset);
345
			while (loopresult == ISC_R_SUCCESS) {
346
				dns_rdataset_current(rdataset, &rdata);
347
348
				dns_name_format(name, namebuf,
349
						sizeof(namebuf));
350
				printf("    ->  %s\n", namebuf);
351
352
				switch (rdata.type) {
353
				case dns_rdatatype_soa:
354
					printsoa(&rdata);
355
					break;
356
				default:
357
					printf("\t");
358
					printrdata(&rdata);
359
				}
360
				dns_rdata_reset(&rdata);
361
				loopresult = dns_rdataset_next(rdataset);
362
			}
363
		}
364
		result = dns_message_nextname(msg, section);
365
		if (result == ISC_R_NOMORE)
366
			break;
367
		else if (result != ISC_R_SUCCESS) {
368
			return (result);
369
		}
370
	}
371
	return (ISC_R_SUCCESS);
372
}
373
374
void
375
received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
376
{
377
	UNUSED(bytes);
378
	UNUSED(from);
379
	UNUSED(query);
380
}
381
382
void
383
trying(char *frm, dig_lookup_t *lookup) {
384
	UNUSED(frm);
385
	UNUSED(lookup);
386
387
}
388
389
isc_result_t
390
printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
391
	char servtext[ISC_SOCKADDR_FORMATSIZE];
392
393
	debug("printmessage()");
394
395
	isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
396
	printf("Server:\t\t%s\n", query->userarg);
397
	printf("Address:\t%s\n", servtext);
398
399
	puts("");
400
401
	if (!short_form) {
402
		isc_boolean_t headers = ISC_TRUE;
403
		puts("------------");
404
		/*		detailheader(query, msg);*/
405
		detailsection(query, msg, headers, DNS_SECTION_QUESTION);
406
		detailsection(query, msg, headers, DNS_SECTION_ANSWER);
407
		detailsection(query, msg, headers, DNS_SECTION_AUTHORITY);
408
		detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL);
409
		puts("------------");
410
	}
411
412
	if (msg->rcode != 0) {
413
		char nametext[DNS_NAME_FORMATSIZE];
414
		dns_name_format(query->lookup->name,
415
				nametext, sizeof(nametext));
416
		printf("** server can't find %s: %s\n",
417
		       (msg->rcode != dns_rcode_nxdomain) ? nametext :
418
		       query->lookup->textname, rcodetext[msg->rcode]);
419
		debug("returning with rcode == 0");
420
		return (ISC_R_SUCCESS);
421
	}
422
423
	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
424
		puts("Non-authoritative answer:");
425
	if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
426
		printsection(query, msg, headers, DNS_SECTION_ANSWER);
427
	else
428
		printf("*** Can't find %s: No answer\n",
429
		       query->lookup->textname);
430
431
	if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
432
	    (query->lookup->rdtype != dns_rdatatype_a)) {
433
		puts("\nAuthoritative answers can be found from:");
434
		printsection(query, msg, headers,
435
			     DNS_SECTION_AUTHORITY);
436
		printsection(query, msg, headers,
437
			     DNS_SECTION_ADDITIONAL);
438
	}
439
	return (ISC_R_SUCCESS);
440
}
441
442
static void
443
show_settings(isc_boolean_t full, isc_boolean_t serv_only) {
444
	dig_server_t *srv;
445
	isc_sockaddr_t sockaddr;
446
	dig_searchlist_t *listent;
447
	in_port_t servport;
448
449
	servport = (port != 0) ? port : NAMESERVER_PORT;
450
451
	srv = ISC_LIST_HEAD(server_list);
452
453
	while (srv != NULL) {
454
		char sockstr[ISC_SOCKADDR_FORMATSIZE];
455
456
		get_address(srv->servername, servport, &sockaddr);
457
		isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
458
		printf("Default server: %s\nAddress: %s\n",
459
			srv->userarg, sockstr);
460
		if (!full)
461
			return;
462
		srv = ISC_LIST_NEXT(srv, link);
463
	}
464
	if (serv_only)
465
		return;
466
	printf("\nSet options:\n");
467
	printf("  %s\t\t\t%s\t\t%s\n",
468
	       tcpmode ? "vc" : "novc",
469
	       short_form ? "nodebug" : "debug",
470
	       debugging ? "d2" : "nod2");
471
	printf("  %s\t\t%s\n",
472
	       usesearch ? "search" : "nosearch",
473
	       recurse ? "recurse" : "norecurse");
474
	printf("  timeout = %d\t\tretry = %d\tport = %d\n",
475
	       timeout, tries, servport);
476
	printf("  querytype = %-8s\tclass = %s\n", deftype, defclass);
477
	printf("  srchlist = ");
478
	for (listent = ISC_LIST_HEAD(search_list);
479
	     listent != NULL;
480
	     listent = ISC_LIST_NEXT(listent, link)) {
481
		     printf("%s", listent->origin);
482
		     if (ISC_LIST_NEXT(listent, link) != NULL)
483
			     printf("/");
484
	}
485
	printf("\n");
486
}
487
488
static isc_boolean_t
489
testtype(char *typetext) {
490
	isc_result_t result;
491
	isc_textregion_t tr;
492
	dns_rdatatype_t rdtype;
493
494
	tr.base = typetext;
495
	tr.length = strlen(typetext);
496
	result = dns_rdatatype_fromtext(&rdtype, &tr);
497
	if (result == ISC_R_SUCCESS)
498
		return (ISC_TRUE);
499
	else {
500
		printf("unknown query type: %s\n", typetext);
501
		return (ISC_FALSE);
502
	}
503
}
504
505
static isc_boolean_t
506
testclass(char *typetext) {
507
	isc_result_t result;
508
	isc_textregion_t tr;
509
	dns_rdataclass_t rdclass;
510
511
	tr.base = typetext;
512
	tr.length = strlen(typetext);
513
	result = dns_rdataclass_fromtext(&rdclass, &tr);
514
	if (result == ISC_R_SUCCESS)
515
		return (ISC_TRUE);
516
	else {
517
		printf("unknown query class: %s\n", typetext);
518
		return (ISC_FALSE);
519
	}
520
}
521
522
static void
523
safecpy(char *dest, char *src, int size) {
524
	strlcpy(dest, src, size);
525
}
526
527
static isc_result_t
528
parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
529
	   const char *desc) {
530
	isc_uint32_t n;
531
	isc_result_t result = isc_parse_uint32(&n, value, 10);
532
	if (result == ISC_R_SUCCESS && n > max)
533
		result = ISC_R_RANGE;
534
	if (result != ISC_R_SUCCESS) {
535
		printf("invalid %s '%s': %s\n", desc,
536
		       value, isc_result_totext(result));
537
		return result;
538
	}
539
	*uip = n;
540
	return (ISC_R_SUCCESS);
541
}
542
543
static void
544
set_port(const char *value) {
545
	isc_uint32_t n;
546
	isc_result_t result = parse_uint(&n, value, 65535, "port");
547
	if (result == ISC_R_SUCCESS)
548
		port = 0; /* (isc_uint16_t) n;*/
549
	printf("The port command has been disabled.\n");
550
}
551
552
static void
553
set_timeout(const char *value) {
554
	isc_uint32_t n;
555
	isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
556
	if (result == ISC_R_SUCCESS)
557
		timeout = n;
558
}
559
560
static void
561
set_tries(const char *value) {
562
	isc_uint32_t n;
563
	isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
564
	if (result == ISC_R_SUCCESS)
565
		tries = n;
566
}
567
568
static void
569
setoption(char *opt) {
570
	if (strncasecmp(opt, "all", 4) == 0) {
571
		show_settings(ISC_TRUE, ISC_FALSE);
572
	} else if (strncasecmp(opt, "class=", 6) == 0) {
573
		if (testclass(&opt[6]))
574
			safecpy(defclass, &opt[6], sizeof(defclass));
575
	} else if (strncasecmp(opt, "cl=", 3) == 0) {
576
		if (testclass(&opt[3]))
577
			safecpy(defclass, &opt[3], sizeof(defclass));
578
	} else if (strncasecmp(opt, "type=", 5) == 0) {
579
		if (testtype(&opt[5]))
580
			safecpy(deftype, &opt[5], sizeof(deftype));
581
	} else if (strncasecmp(opt, "ty=", 3) == 0) {
582
		if (testtype(&opt[3]))
583
			safecpy(deftype, &opt[3], sizeof(deftype));
584
	} else if (strncasecmp(opt, "querytype=", 10) == 0) {
585
		if (testtype(&opt[10]))
586
			safecpy(deftype, &opt[10], sizeof(deftype));
587
	} else if (strncasecmp(opt, "query=", 6) == 0) {
588
		if (testtype(&opt[6]))
589
			safecpy(deftype, &opt[6], sizeof(deftype));
590
	} else if (strncasecmp(opt, "qu=", 3) == 0) {
591
		if (testtype(&opt[3]))
592
			safecpy(deftype, &opt[3], sizeof(deftype));
593
	} else if (strncasecmp(opt, "q=", 2) == 0) {
594
		if (testtype(&opt[2]))
595
			safecpy(deftype, &opt[2], sizeof(deftype));
596
	} else if (strncasecmp(opt, "domain=", 7) == 0) {
597
		safecpy(domainopt, &opt[7], sizeof(domainopt));
598
		set_search_domain(domainopt);
599
		usesearch = ISC_TRUE;
600
	} else if (strncasecmp(opt, "do=", 3) == 0) {
601
		safecpy(domainopt, &opt[3], sizeof(domainopt));
602
		set_search_domain(domainopt);
603
		usesearch = ISC_TRUE;
604
	} else if (strncasecmp(opt, "port=", 5) == 0) {
605
		set_port(&opt[5]);
606
	} else if (strncasecmp(opt, "po=", 3) == 0) {
607
		set_port(&opt[3]);
608
	} else if (strncasecmp(opt, "timeout=", 8) == 0) {
609
		set_timeout(&opt[8]);
610
	} else if (strncasecmp(opt, "t=", 2) == 0) {
611
		set_timeout(&opt[2]);
612
 	} else if (strncasecmp(opt, "rec", 3) == 0) {
613
		recurse = ISC_TRUE;
614
	} else if (strncasecmp(opt, "norec", 5) == 0) {
615
		recurse = ISC_FALSE;
616
	} else if (strncasecmp(opt, "retry=", 6) == 0) {
617
		set_tries(&opt[6]);
618
	} else if (strncasecmp(opt, "ret=", 4) == 0) {
619
		set_tries(&opt[4]);
620
 	} else if (strncasecmp(opt, "def", 3) == 0) {
621
		usesearch = ISC_TRUE;
622
	} else if (strncasecmp(opt, "nodef", 5) == 0) {
623
		usesearch = ISC_FALSE;
624
 	} else if (strncasecmp(opt, "vc", 3) == 0) {
625
		tcpmode = ISC_TRUE;
626
	} else if (strncasecmp(opt, "novc", 5) == 0) {
627
		tcpmode = ISC_FALSE;
628
 	} else if (strncasecmp(opt, "deb", 3) == 0) {
629
		short_form = ISC_FALSE;
630
		showsearch = ISC_TRUE;
631
	} else if (strncasecmp(opt, "nodeb", 5) == 0) {
632
		short_form = ISC_TRUE;
633
		showsearch = ISC_FALSE;
634
 	} else if (strncasecmp(opt, "d2", 2) == 0) {
635
		debugging = ISC_TRUE;
636
	} else if (strncasecmp(opt, "nod2", 4) == 0) {
637
		debugging = ISC_FALSE;
638
	} else if (strncasecmp(opt, "search", 3) == 0) {
639
		usesearch = ISC_TRUE;
640
	} else if (strncasecmp(opt, "nosearch", 5) == 0) {
641
		usesearch = ISC_FALSE;
642
	} else if (strncasecmp(opt, "sil", 3) == 0) {
643
		/* deprecation_msg = ISC_FALSE; */
644
	} else if (strncasecmp(opt, "fail", 3) == 0) {
645
		nofail=ISC_FALSE;
646
	} else if (strncasecmp(opt, "nofail", 3) == 0) {
647
		nofail=ISC_TRUE;
648
	} else {
649
		printf("*** Invalid option: %s\n", opt);
650
	}
651
}
652
653
static void
654
addlookup(char *opt) {
655
	dig_lookup_t *lookup;
656
	isc_result_t result;
657
	isc_textregion_t tr;
658
	dns_rdatatype_t rdtype;
659
	dns_rdataclass_t rdclass;
660
	char store[MXNAME];
661
662
	debug("addlookup()");
663
	tr.base = deftype;
664
	tr.length = strlen(deftype);
665
	result = dns_rdatatype_fromtext(&rdtype, &tr);
666
	if (result != ISC_R_SUCCESS) {
667
		printf("unknown query type: %s\n", deftype);
668
		rdclass = dns_rdatatype_a;
669
	}
670
	tr.base = defclass;
671
	tr.length = strlen(defclass);
672
	result = dns_rdataclass_fromtext(&rdclass, &tr);
673
	if (result != ISC_R_SUCCESS) {
674
		printf("unknown query class: %s\n", defclass);
675
		rdclass = dns_rdataclass_in;
676
	}
677
	lookup = make_empty_lookup();
678
	if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
679
	    == ISC_R_SUCCESS) {
680
		safecpy(lookup->textname, store, sizeof(lookup->textname));
681
		lookup->rdtype = dns_rdatatype_ptr;
682
		lookup->rdtypeset = ISC_TRUE;
683
	} else {
684
		safecpy(lookup->textname, opt, sizeof(lookup->textname));
685
		lookup->rdtype = rdtype;
686
		lookup->rdtypeset = ISC_TRUE;
687
	}
688
	lookup->rdclass = rdclass;
689
	lookup->rdclassset = ISC_TRUE;
690
	lookup->trace = ISC_FALSE;
691
	lookup->trace_root = lookup->trace;
692
	lookup->ns_search_only = ISC_FALSE;
693
	lookup->identify = identify;
694
	lookup->recurse = recurse;
695
	lookup->aaonly = aaonly;
696
	lookup->retries = tries;
697
	lookup->udpsize = 0;
698
	lookup->comments = comments;
699
	lookup->tcp_mode = tcpmode;
700
	lookup->stats = stats;
701
	lookup->section_question = section_question;
702
	lookup->section_answer = section_answer;
703
	lookup->section_authority = section_authority;
704
	lookup->section_additional = section_additional;
705
	lookup->new_search = ISC_TRUE;
706
	if (nofail)
707
		lookup->servfail_stops = ISC_FALSE;
708
	ISC_LIST_INIT(lookup->q);
709
	ISC_LINK_INIT(lookup, link);
710
	ISC_LIST_APPEND(lookup_list, lookup, link);
711
	lookup->origin = NULL;
712
	ISC_LIST_INIT(lookup->my_server_list);
713
	debug("looking up %s", lookup->textname);
714
}
715
716
static void
717
get_next_command(void) {
718
	char *buf;
719
	char *ptr, *arg;
720
	char *input;
721
722
	fflush(stdout);
723
	buf = isc_mem_allocate(mctx, COMMSIZE);
724
	if (buf == NULL)
725
		fatal("memory allocation failure");
726
	fputs("> ", stdout);
727
	fflush(stdout);
728
	isc_app_block();
729
	ptr = fgets(buf, COMMSIZE, stdin);
730
	isc_app_unblock();
731
	if (ptr == NULL) {
732
		in_use = ISC_FALSE;
733
		goto cleanup;
734
	}
735
	input = buf;
736
	ptr = next_token(&input, " \t\r\n");
737
	if (ptr == NULL)
738
		goto cleanup;
739
	arg = next_token(&input, " \t\r\n");
740
	if ((strcasecmp(ptr, "set") == 0) &&
741
	    (arg != NULL))
742
		setoption(arg);
743
	else if ((strcasecmp(ptr, "server") == 0) ||
744
		 (strcasecmp(ptr, "lserver") == 0)) {
745
		isc_app_block();
746
		set_nameserver(arg);
747
		check_ra = ISC_FALSE;
748
		isc_app_unblock();
749
		show_settings(ISC_TRUE, ISC_TRUE);
750
	} else if (strcasecmp(ptr, "exit") == 0) {
751
		in_use = ISC_FALSE;
752
		goto cleanup;
753
	} else if (strcasecmp(ptr, "help") == 0 ||
754
		   strcasecmp(ptr, "?") == 0) {
755
		printf("The '%s' command is not yet implemented.\n", ptr);
756
		goto cleanup;
757
	} else if (strcasecmp(ptr, "finger") == 0 ||
758
		   strcasecmp(ptr, "root") == 0 ||
759
		   strcasecmp(ptr, "ls") == 0 ||
760
		   strcasecmp(ptr, "view") == 0) {
761
		printf("The '%s' command is not implemented.\n", ptr);
762
		goto cleanup;
763
	} else
764
		addlookup(ptr);
765
 cleanup:
766
	isc_mem_free(mctx, buf);
767
}
768
769
static void
770
parse_args(int argc, char **argv) {
771
	isc_boolean_t have_lookup = ISC_FALSE;
772
773
	usesearch = ISC_TRUE;
774
	for (argc--, argv++; argc > 0; argc--, argv++) {
775
		debug("main parsing %s", argv[0]);
776
		if (argv[0][0] == '-') {
777
			if (argv[0][1] != 0)
778
				setoption(&argv[0][1]);
779
			else
780
				have_lookup = ISC_TRUE;
781
		} else {
782
			if (!have_lookup) {
783
				have_lookup = ISC_TRUE;
784
				in_use = ISC_TRUE;
785
				addlookup(argv[0]);
786
			} else {
787
				set_nameserver(argv[0]);
788
				check_ra = ISC_FALSE;
789
			}
790
		}
791
	}
792
}
793
794
static void
795
flush_lookup_list(void) {
796
	dig_lookup_t *l, *lp;
797
	dig_query_t *q, *qp;
798
	dig_server_t *s, *sp;
799
800
	lookup_counter = 0;
801
	l = ISC_LIST_HEAD(lookup_list);
802
	while (l != NULL) {
803
		q = ISC_LIST_HEAD(l->q);
804
		while (q != NULL) {
805
			if (q->sock != NULL) {
806
				isc_socket_cancel(q->sock, NULL,
807
						  ISC_SOCKCANCEL_ALL);
808
				isc_socket_detach(&q->sock);
809
			}
810
			if (ISC_LINK_LINKED(&q->recvbuf, link))
811
				ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
812
						 link);
813
			if (ISC_LINK_LINKED(&q->lengthbuf, link))
814
				ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
815
						 link);
816
			isc_buffer_invalidate(&q->recvbuf);
817
			isc_buffer_invalidate(&q->lengthbuf);
818
			qp = q;
819
			q = ISC_LIST_NEXT(q, link);
820
			ISC_LIST_DEQUEUE(l->q, qp, link);
821
			isc_mem_free(mctx, qp);
822
		}
823
		s = ISC_LIST_HEAD(l->my_server_list);
824
		while (s != NULL) {
825
			sp = s;
826
			s = ISC_LIST_NEXT(s, link);
827
			ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
828
			isc_mem_free(mctx, sp);
829
830
		}
831
		if (l->sendmsg != NULL)
832
			dns_message_destroy(&l->sendmsg);
833
		if (l->timer != NULL)
834
			isc_timer_detach(&l->timer);
835
		lp = l;
836
		l = ISC_LIST_NEXT(l, link);
837
		ISC_LIST_DEQUEUE(lookup_list, lp, link);
838
		isc_mem_free(mctx, lp);
839
	}
840
}
841
842
static void
843
getinput(isc_task_t *task, isc_event_t *event) {
844
	UNUSED(task);
845
	if (global_event == NULL)
846
		global_event = event;
847
	while (in_use) {
848
		get_next_command();
849
		if (ISC_LIST_HEAD(lookup_list) != NULL) {
850
			start_lookup();
851
			return;
852
		}
853
	}
854
	isc_app_shutdown();
855
}
856
857
int
858
main(int argc, char **argv) {
859
	isc_result_t result;
860
861
	ISC_LIST_INIT(lookup_list);
862
	ISC_LIST_INIT(server_list);
863
	ISC_LIST_INIT(search_list);
864
865
	check_ra = ISC_TRUE;
866
867
	result = isc_app_start();
868
	check_result(result, "isc_app_start");
869
870
	if (pledge("stdio rpath dns wpath cpath", NULL) == -1) {
871
		perror("pledge");
872
		exit(1);
873
	}
874
875
	setup_libs();
876
	progname = argv[0];
877
878
	if (pledge("stdio dns rpath wpath cpath", NULL) == -1) {
879
		perror("pledge");
880
		exit(1);
881
	}
882
883
	parse_args(argc, argv);
884
885
	setup_system();
886
	if (domainopt[0] != '\0')
887
		set_search_domain(domainopt);
888
	if (in_use)
889
		result = isc_app_onrun(mctx, global_task, onrun_callback,
890
				       NULL);
891
	else
892
		result = isc_app_onrun(mctx, global_task, getinput, NULL);
893
	check_result(result, "isc_app_onrun");
894
	in_use = ISC_TF(!in_use);
895
896
	(void)isc_app_run();
897
898
	puts("");
899
	debug("done, and starting to shut down");
900
	if (global_event != NULL)
901
		isc_event_free(&global_event);
902
	cancel_all();
903
	destroy_libs();
904
	isc_app_finish();
905
906
	return (0);
907
}