No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / dig / nslookup.c
blobee26b96dfb8e33dfb6362f466e5985018e991eb9
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: nslookup.c,v 1.124 2009/10/20 01:04:03 marka Exp */
22 #include <config.h>
24 #include <stdlib.h>
26 #include <isc/app.h>
27 #include <isc/buffer.h>
28 #include <isc/commandline.h>
29 #include <isc/event.h>
30 #include <isc/parseint.h>
31 #include <isc/print.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>
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>
48 #include <dig/dig.h>
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;
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;
63 static char domainopt[DNS_NAME_MAXTEXT];
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"
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 */
130 #define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
132 static void flush_lookup_list(void);
133 static void getinput(isc_task_t *task, isc_event_t *event);
135 static char *
136 rcode_totext(dns_rcode_t rcode)
138 static char buf[sizeof("?65535")];
139 union {
140 const char *consttext;
141 char *deconsttext;
142 } totext;
144 if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
145 snprintf(buf, sizeof(buf), "?%u", rcode);
146 totext.deconsttext = buf;
147 } else
148 totext.consttext = rcodetext[rcode];
149 return totext.deconsttext;
152 void
153 dighost_shutdown(void) {
154 isc_event_t *event = global_event;
156 flush_lookup_list();
157 debug("dighost_shutdown()");
159 if (!in_use) {
160 isc_app_shutdown();
161 return;
164 isc_task_send(global_task, &event);
167 static void
168 printsoa(dns_rdata_t *rdata) {
169 dns_rdata_soa_t soa;
170 isc_result_t result;
171 char namebuf[DNS_NAME_FORMATSIZE];
173 result = dns_rdata_tostruct(rdata, &soa, NULL);
174 check_result(result, "dns_rdata_tostruct");
176 dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
177 printf("\torigin = %s\n", namebuf);
178 dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
179 printf("\tmail addr = %s\n", namebuf);
180 printf("\tserial = %u\n", soa.serial);
181 printf("\trefresh = %u\n", soa.refresh);
182 printf("\tretry = %u\n", soa.retry);
183 printf("\texpire = %u\n", soa.expire);
184 printf("\tminimum = %u\n", soa.minimum);
185 dns_rdata_freestruct(&soa);
188 static void
189 printa(dns_rdata_t *rdata) {
190 isc_result_t result;
191 char text[sizeof("255.255.255.255")];
192 isc_buffer_t b;
194 isc_buffer_init(&b, text, sizeof(text));
195 result = dns_rdata_totext(rdata, NULL, &b);
196 check_result(result, "dns_rdata_totext");
197 printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
198 (char *)isc_buffer_base(&b));
200 #ifdef DIG_SIGCHASE
201 /* Just for compatibility : not use in host program */
202 isc_result_t
203 printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
204 isc_buffer_t *target)
206 UNUSED(owner_name);
207 UNUSED(rdataset);
208 UNUSED(target);
209 return(ISC_FALSE);
211 #endif
212 static void
213 printrdata(dns_rdata_t *rdata) {
214 isc_result_t result;
215 isc_buffer_t *b = NULL;
216 unsigned int size = 1024;
217 isc_boolean_t done = ISC_FALSE;
219 if (rdata->type < N_KNOWN_RRTYPES)
220 printf("%s", rtypetext[rdata->type]);
221 else
222 printf("rdata_%d = ", rdata->type);
224 while (!done) {
225 result = isc_buffer_allocate(mctx, &b, size);
226 if (result != ISC_R_SUCCESS)
227 check_result(result, "isc_buffer_allocate");
228 result = dns_rdata_totext(rdata, NULL, b);
229 if (result == ISC_R_SUCCESS) {
230 printf("%.*s\n", (int)isc_buffer_usedlength(b),
231 (char *)isc_buffer_base(b));
232 done = ISC_TRUE;
233 } else if (result != ISC_R_NOSPACE)
234 check_result(result, "dns_rdata_totext");
235 isc_buffer_free(&b);
236 size *= 2;
240 static isc_result_t
241 printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
242 dns_section_t section) {
243 isc_result_t result, loopresult;
244 dns_name_t *name;
245 dns_rdataset_t *rdataset = NULL;
246 dns_rdata_t rdata = DNS_RDATA_INIT;
247 char namebuf[DNS_NAME_FORMATSIZE];
249 UNUSED(query);
250 UNUSED(headers);
252 debug("printsection()");
254 result = dns_message_firstname(msg, section);
255 if (result == ISC_R_NOMORE)
256 return (ISC_R_SUCCESS);
257 else if (result != ISC_R_SUCCESS)
258 return (result);
259 for (;;) {
260 name = NULL;
261 dns_message_currentname(msg, section,
262 &name);
263 for (rdataset = ISC_LIST_HEAD(name->list);
264 rdataset != NULL;
265 rdataset = ISC_LIST_NEXT(rdataset, link)) {
266 loopresult = dns_rdataset_first(rdataset);
267 while (loopresult == ISC_R_SUCCESS) {
268 dns_rdataset_current(rdataset, &rdata);
269 switch (rdata.type) {
270 case dns_rdatatype_a:
271 if (section != DNS_SECTION_ANSWER)
272 goto def_short_section;
273 dns_name_format(name, namebuf,
274 sizeof(namebuf));
275 printf("Name:\t%s\n", namebuf);
276 printa(&rdata);
277 break;
278 case dns_rdatatype_soa:
279 dns_name_format(name, namebuf,
280 sizeof(namebuf));
281 printf("%s\n", namebuf);
282 printsoa(&rdata);
283 break;
284 default:
285 def_short_section:
286 dns_name_format(name, namebuf,
287 sizeof(namebuf));
288 printf("%s\t", namebuf);
289 printrdata(&rdata);
290 break;
292 dns_rdata_reset(&rdata);
293 loopresult = dns_rdataset_next(rdataset);
296 result = dns_message_nextname(msg, section);
297 if (result == ISC_R_NOMORE)
298 break;
299 else if (result != ISC_R_SUCCESS) {
300 return (result);
303 return (ISC_R_SUCCESS);
306 static isc_result_t
307 detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
308 dns_section_t section) {
309 isc_result_t result, loopresult;
310 dns_name_t *name;
311 dns_rdataset_t *rdataset = NULL;
312 dns_rdata_t rdata = DNS_RDATA_INIT;
313 char namebuf[DNS_NAME_FORMATSIZE];
315 UNUSED(query);
317 debug("detailsection()");
319 if (headers) {
320 switch (section) {
321 case DNS_SECTION_QUESTION:
322 puts(" QUESTIONS:");
323 break;
324 case DNS_SECTION_ANSWER:
325 puts(" ANSWERS:");
326 break;
327 case DNS_SECTION_AUTHORITY:
328 puts(" AUTHORITY RECORDS:");
329 break;
330 case DNS_SECTION_ADDITIONAL:
331 puts(" ADDITIONAL RECORDS:");
332 break;
336 result = dns_message_firstname(msg, section);
337 if (result == ISC_R_NOMORE)
338 return (ISC_R_SUCCESS);
339 else if (result != ISC_R_SUCCESS)
340 return (result);
341 for (;;) {
342 name = NULL;
343 dns_message_currentname(msg, section,
344 &name);
345 for (rdataset = ISC_LIST_HEAD(name->list);
346 rdataset != NULL;
347 rdataset = ISC_LIST_NEXT(rdataset, link)) {
348 if (section == DNS_SECTION_QUESTION) {
349 dns_name_format(name, namebuf,
350 sizeof(namebuf));
351 printf("\t%s, ", namebuf);
352 dns_rdatatype_format(rdataset->type,
353 namebuf,
354 sizeof(namebuf));
355 printf("type = %s, ", namebuf);
356 dns_rdataclass_format(rdataset->rdclass,
357 namebuf,
358 sizeof(namebuf));
359 printf("class = %s\n", namebuf);
361 loopresult = dns_rdataset_first(rdataset);
362 while (loopresult == ISC_R_SUCCESS) {
363 dns_rdataset_current(rdataset, &rdata);
365 dns_name_format(name, namebuf,
366 sizeof(namebuf));
367 printf(" -> %s\n", namebuf);
369 switch (rdata.type) {
370 case dns_rdatatype_soa:
371 printsoa(&rdata);
372 break;
373 default:
374 printf("\t");
375 printrdata(&rdata);
377 dns_rdata_reset(&rdata);
378 printf("\tttl = %u\n", rdataset->ttl);
379 loopresult = dns_rdataset_next(rdataset);
382 result = dns_message_nextname(msg, section);
383 if (result == ISC_R_NOMORE)
384 break;
385 else if (result != ISC_R_SUCCESS) {
386 return (result);
389 return (ISC_R_SUCCESS);
392 void
393 received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
395 UNUSED(bytes);
396 UNUSED(from);
397 UNUSED(query);
400 void
401 trying(char *frm, dig_lookup_t *lookup) {
402 UNUSED(frm);
403 UNUSED(lookup);
407 isc_result_t
408 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
409 char servtext[ISC_SOCKADDR_FORMATSIZE];
411 debug("printmessage()");
413 isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
414 printf("Server:\t\t%s\n", query->userarg);
415 printf("Address:\t%s\n", servtext);
417 puts("");
419 if (!short_form) {
420 isc_boolean_t headers = ISC_TRUE;
421 puts("------------");
422 /* detailheader(query, msg);*/
423 detailsection(query, msg, headers, DNS_SECTION_QUESTION);
424 detailsection(query, msg, headers, DNS_SECTION_ANSWER);
425 detailsection(query, msg, headers, DNS_SECTION_AUTHORITY);
426 detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL);
427 puts("------------");
430 if (msg->rcode != 0) {
431 char nametext[DNS_NAME_FORMATSIZE];
432 dns_name_format(query->lookup->name,
433 nametext, sizeof(nametext));
434 printf("** server can't find %s: %s\n",
435 (msg->rcode != dns_rcode_nxdomain) ? nametext :
436 query->lookup->textname, rcode_totext(msg->rcode));
437 debug("returning with rcode == 0");
438 return (ISC_R_SUCCESS);
441 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
442 puts("Non-authoritative answer:");
443 if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
444 printsection(query, msg, headers, DNS_SECTION_ANSWER);
445 else
446 printf("*** Can't find %s: No answer\n",
447 query->lookup->textname);
449 if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
450 (query->lookup->rdtype != dns_rdatatype_a)) {
451 puts("\nAuthoritative answers can be found from:");
452 printsection(query, msg, headers,
453 DNS_SECTION_AUTHORITY);
454 printsection(query, msg, headers,
455 DNS_SECTION_ADDITIONAL);
457 return (ISC_R_SUCCESS);
460 static void
461 show_settings(isc_boolean_t full, isc_boolean_t serv_only) {
462 dig_server_t *srv;
463 isc_sockaddr_t sockaddr;
464 dig_searchlist_t *listent;
465 isc_result_t result;
467 srv = ISC_LIST_HEAD(server_list);
469 while (srv != NULL) {
470 char sockstr[ISC_SOCKADDR_FORMATSIZE];
472 result = get_address(srv->servername, port, &sockaddr);
473 check_result(result, "get_address");
475 isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
476 printf("Default server: %s\nAddress: %s\n",
477 srv->userarg, sockstr);
478 if (!full)
479 return;
480 srv = ISC_LIST_NEXT(srv, link);
482 if (serv_only)
483 return;
484 printf("\nSet options:\n");
485 printf(" %s\t\t\t%s\t\t%s\n",
486 tcpmode ? "vc" : "novc",
487 short_form ? "nodebug" : "debug",
488 debugging ? "d2" : "nod2");
489 printf(" %s\t\t%s\n",
490 usesearch ? "search" : "nosearch",
491 recurse ? "recurse" : "norecurse");
492 printf(" timeout = %d\t\tretry = %d\tport = %d\n",
493 timeout, tries, port);
494 printf(" querytype = %-8s\tclass = %s\n", deftype, defclass);
495 printf(" srchlist = ");
496 for (listent = ISC_LIST_HEAD(search_list);
497 listent != NULL;
498 listent = ISC_LIST_NEXT(listent, link)) {
499 printf("%s", listent->origin);
500 if (ISC_LIST_NEXT(listent, link) != NULL)
501 printf("/");
503 printf("\n");
506 static isc_boolean_t
507 testtype(char *typetext) {
508 isc_result_t result;
509 isc_textregion_t tr;
510 dns_rdatatype_t rdtype;
512 tr.base = typetext;
513 tr.length = strlen(typetext);
514 result = dns_rdatatype_fromtext(&rdtype, &tr);
515 if (result == ISC_R_SUCCESS)
516 return (ISC_TRUE);
517 else {
518 printf("unknown query type: %s\n", typetext);
519 return (ISC_FALSE);
523 static isc_boolean_t
524 testclass(char *typetext) {
525 isc_result_t result;
526 isc_textregion_t tr;
527 dns_rdataclass_t rdclass;
529 tr.base = typetext;
530 tr.length = strlen(typetext);
531 result = dns_rdataclass_fromtext(&rdclass, &tr);
532 if (result == ISC_R_SUCCESS)
533 return (ISC_TRUE);
534 else {
535 printf("unknown query class: %s\n", typetext);
536 return (ISC_FALSE);
540 static void
541 safecpy(char *dest, char *src, int size) {
542 strncpy(dest, src, size);
543 dest[size-1] = 0;
546 static void
547 set_port(const char *value) {
548 isc_uint32_t n;
549 isc_result_t result = parse_uint(&n, value, 65535, "port");
550 if (result == ISC_R_SUCCESS)
551 port = (isc_uint16_t) n;
554 static void
555 set_timeout(const char *value) {
556 isc_uint32_t n;
557 isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
558 if (result == ISC_R_SUCCESS)
559 timeout = n;
562 static void
563 set_tries(const char *value) {
564 isc_uint32_t n;
565 isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
566 if (result == ISC_R_SUCCESS)
567 tries = n;
570 static void
571 setoption(char *opt) {
572 if (strncasecmp(opt, "all", 4) == 0) {
573 show_settings(ISC_TRUE, ISC_FALSE);
574 } else if (strncasecmp(opt, "class=", 6) == 0) {
575 if (testclass(&opt[6]))
576 safecpy(defclass, &opt[6], sizeof(defclass));
577 } else if (strncasecmp(opt, "cl=", 3) == 0) {
578 if (testclass(&opt[3]))
579 safecpy(defclass, &opt[3], sizeof(defclass));
580 } else if (strncasecmp(opt, "type=", 5) == 0) {
581 if (testtype(&opt[5]))
582 safecpy(deftype, &opt[5], sizeof(deftype));
583 } else if (strncasecmp(opt, "ty=", 3) == 0) {
584 if (testtype(&opt[3]))
585 safecpy(deftype, &opt[3], sizeof(deftype));
586 } else if (strncasecmp(opt, "querytype=", 10) == 0) {
587 if (testtype(&opt[10]))
588 safecpy(deftype, &opt[10], sizeof(deftype));
589 } else if (strncasecmp(opt, "query=", 6) == 0) {
590 if (testtype(&opt[6]))
591 safecpy(deftype, &opt[6], sizeof(deftype));
592 } else if (strncasecmp(opt, "qu=", 3) == 0) {
593 if (testtype(&opt[3]))
594 safecpy(deftype, &opt[3], sizeof(deftype));
595 } else if (strncasecmp(opt, "q=", 2) == 0) {
596 if (testtype(&opt[2]))
597 safecpy(deftype, &opt[2], sizeof(deftype));
598 } else if (strncasecmp(opt, "domain=", 7) == 0) {
599 safecpy(domainopt, &opt[7], sizeof(domainopt));
600 set_search_domain(domainopt);
601 usesearch = ISC_TRUE;
602 } else if (strncasecmp(opt, "do=", 3) == 0) {
603 safecpy(domainopt, &opt[3], sizeof(domainopt));
604 set_search_domain(domainopt);
605 usesearch = ISC_TRUE;
606 } else if (strncasecmp(opt, "port=", 5) == 0) {
607 set_port(&opt[5]);
608 } else if (strncasecmp(opt, "po=", 3) == 0) {
609 set_port(&opt[3]);
610 } else if (strncasecmp(opt, "timeout=", 8) == 0) {
611 set_timeout(&opt[8]);
612 } else if (strncasecmp(opt, "t=", 2) == 0) {
613 set_timeout(&opt[2]);
614 } else if (strncasecmp(opt, "rec", 3) == 0) {
615 recurse = ISC_TRUE;
616 } else if (strncasecmp(opt, "norec", 5) == 0) {
617 recurse = ISC_FALSE;
618 } else if (strncasecmp(opt, "retry=", 6) == 0) {
619 set_tries(&opt[6]);
620 } else if (strncasecmp(opt, "ret=", 4) == 0) {
621 set_tries(&opt[4]);
622 } else if (strncasecmp(opt, "def", 3) == 0) {
623 usesearch = ISC_TRUE;
624 } else if (strncasecmp(opt, "nodef", 5) == 0) {
625 usesearch = ISC_FALSE;
626 } else if (strncasecmp(opt, "vc", 3) == 0) {
627 tcpmode = ISC_TRUE;
628 } else if (strncasecmp(opt, "novc", 5) == 0) {
629 tcpmode = ISC_FALSE;
630 } else if (strncasecmp(opt, "deb", 3) == 0) {
631 short_form = ISC_FALSE;
632 showsearch = ISC_TRUE;
633 } else if (strncasecmp(opt, "nodeb", 5) == 0) {
634 short_form = ISC_TRUE;
635 showsearch = ISC_FALSE;
636 } else if (strncasecmp(opt, "d2", 2) == 0) {
637 debugging = ISC_TRUE;
638 } else if (strncasecmp(opt, "nod2", 4) == 0) {
639 debugging = ISC_FALSE;
640 } else if (strncasecmp(opt, "search", 3) == 0) {
641 usesearch = ISC_TRUE;
642 } else if (strncasecmp(opt, "nosearch", 5) == 0) {
643 usesearch = ISC_FALSE;
644 } else if (strncasecmp(opt, "sil", 3) == 0) {
645 /* deprecation_msg = ISC_FALSE; */
646 } else if (strncasecmp(opt, "fail", 3) == 0) {
647 nofail=ISC_FALSE;
648 } else if (strncasecmp(opt, "nofail", 3) == 0) {
649 nofail=ISC_TRUE;
650 } else {
651 printf("*** Invalid option: %s\n", opt);
655 static void
656 addlookup(char *opt) {
657 dig_lookup_t *lookup;
658 isc_result_t result;
659 isc_textregion_t tr;
660 dns_rdatatype_t rdtype;
661 dns_rdataclass_t rdclass;
662 char store[MXNAME];
664 debug("addlookup()");
665 tr.base = deftype;
666 tr.length = strlen(deftype);
667 result = dns_rdatatype_fromtext(&rdtype, &tr);
668 if (result != ISC_R_SUCCESS) {
669 printf("unknown query type: %s\n", deftype);
670 rdclass = dns_rdatatype_a;
672 tr.base = defclass;
673 tr.length = strlen(defclass);
674 result = dns_rdataclass_fromtext(&rdclass, &tr);
675 if (result != ISC_R_SUCCESS) {
676 printf("unknown query class: %s\n", defclass);
677 rdclass = dns_rdataclass_in;
679 lookup = make_empty_lookup();
680 if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
681 == ISC_R_SUCCESS) {
682 safecpy(lookup->textname, store, sizeof(lookup->textname));
683 lookup->rdtype = dns_rdatatype_ptr;
684 lookup->rdtypeset = ISC_TRUE;
685 } else {
686 safecpy(lookup->textname, opt, sizeof(lookup->textname));
687 lookup->rdtype = rdtype;
688 lookup->rdtypeset = ISC_TRUE;
690 lookup->rdclass = rdclass;
691 lookup->rdclassset = ISC_TRUE;
692 lookup->trace = ISC_FALSE;
693 lookup->trace_root = lookup->trace;
694 lookup->ns_search_only = ISC_FALSE;
695 lookup->identify = identify;
696 lookup->recurse = recurse;
697 lookup->aaonly = aaonly;
698 lookup->retries = tries;
699 lookup->udpsize = 0;
700 lookup->comments = comments;
701 lookup->tcp_mode = tcpmode;
702 lookup->stats = stats;
703 lookup->section_question = section_question;
704 lookup->section_answer = section_answer;
705 lookup->section_authority = section_authority;
706 lookup->section_additional = section_additional;
707 lookup->new_search = ISC_TRUE;
708 if (nofail)
709 lookup->servfail_stops = ISC_FALSE;
710 ISC_LIST_INIT(lookup->q);
711 ISC_LINK_INIT(lookup, link);
712 ISC_LIST_APPEND(lookup_list, lookup, link);
713 lookup->origin = NULL;
714 ISC_LIST_INIT(lookup->my_server_list);
715 debug("looking up %s", lookup->textname);
718 static void
719 get_next_command(void) {
720 char *buf;
721 char *ptr, *arg;
722 char *input;
724 fflush(stdout);
725 buf = isc_mem_allocate(mctx, COMMSIZE);
726 if (buf == NULL)
727 fatal("memory allocation failure");
728 fputs("> ", stderr);
729 fflush(stderr);
730 isc_app_block();
731 ptr = fgets(buf, COMMSIZE, stdin);
732 isc_app_unblock();
733 if (ptr == NULL) {
734 in_use = ISC_FALSE;
735 goto cleanup;
737 input = buf;
738 ptr = next_token(&input, " \t\r\n");
739 if (ptr == NULL)
740 goto cleanup;
741 arg = next_token(&input, " \t\r\n");
742 if ((strcasecmp(ptr, "set") == 0) &&
743 (arg != NULL))
744 setoption(arg);
745 else if ((strcasecmp(ptr, "server") == 0) ||
746 (strcasecmp(ptr, "lserver") == 0)) {
747 isc_app_block();
748 set_nameserver(arg);
749 check_ra = ISC_FALSE;
750 isc_app_unblock();
751 show_settings(ISC_TRUE, ISC_TRUE);
752 } else if (strcasecmp(ptr, "exit") == 0) {
753 in_use = ISC_FALSE;
754 goto cleanup;
755 } else if (strcasecmp(ptr, "help") == 0 ||
756 strcasecmp(ptr, "?") == 0) {
757 printf("The '%s' command is not yet implemented.\n", ptr);
758 goto cleanup;
759 } else if (strcasecmp(ptr, "finger") == 0 ||
760 strcasecmp(ptr, "root") == 0 ||
761 strcasecmp(ptr, "ls") == 0 ||
762 strcasecmp(ptr, "view") == 0) {
763 printf("The '%s' command is not implemented.\n", ptr);
764 goto cleanup;
765 } else
766 addlookup(ptr);
767 cleanup:
768 isc_mem_free(mctx, buf);
771 static void
772 parse_args(int argc, char **argv) {
773 isc_boolean_t have_lookup = ISC_FALSE;
775 usesearch = ISC_TRUE;
776 for (argc--, argv++; argc > 0; argc--, argv++) {
777 debug("main parsing %s", argv[0]);
778 if (argv[0][0] == '-') {
779 if (argv[0][1] != 0)
780 setoption(&argv[0][1]);
781 else
782 have_lookup = ISC_TRUE;
783 } else {
784 if (!have_lookup) {
785 have_lookup = ISC_TRUE;
786 in_use = ISC_TRUE;
787 addlookup(argv[0]);
788 } else {
789 set_nameserver(argv[0]);
790 check_ra = ISC_FALSE;
796 static void
797 flush_lookup_list(void) {
798 dig_lookup_t *l, *lp;
799 dig_query_t *q, *qp;
800 dig_server_t *s, *sp;
802 lookup_counter = 0;
803 l = ISC_LIST_HEAD(lookup_list);
804 while (l != NULL) {
805 q = ISC_LIST_HEAD(l->q);
806 while (q != NULL) {
807 if (q->sock != NULL) {
808 isc_socket_cancel(q->sock, NULL,
809 ISC_SOCKCANCEL_ALL);
810 isc_socket_detach(&q->sock);
812 if (ISC_LINK_LINKED(&q->recvbuf, link))
813 ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
814 link);
815 if (ISC_LINK_LINKED(&q->lengthbuf, link))
816 ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
817 link);
818 isc_buffer_invalidate(&q->recvbuf);
819 isc_buffer_invalidate(&q->lengthbuf);
820 qp = q;
821 q = ISC_LIST_NEXT(q, link);
822 ISC_LIST_DEQUEUE(l->q, qp, link);
823 isc_mem_free(mctx, qp);
825 s = ISC_LIST_HEAD(l->my_server_list);
826 while (s != NULL) {
827 sp = s;
828 s = ISC_LIST_NEXT(s, link);
829 ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
830 isc_mem_free(mctx, sp);
833 if (l->sendmsg != NULL)
834 dns_message_destroy(&l->sendmsg);
835 if (l->timer != NULL)
836 isc_timer_detach(&l->timer);
837 lp = l;
838 l = ISC_LIST_NEXT(l, link);
839 ISC_LIST_DEQUEUE(lookup_list, lp, link);
840 isc_mem_free(mctx, lp);
844 static void
845 getinput(isc_task_t *task, isc_event_t *event) {
846 UNUSED(task);
847 if (global_event == NULL)
848 global_event = event;
849 while (in_use) {
850 get_next_command();
851 if (ISC_LIST_HEAD(lookup_list) != NULL) {
852 start_lookup();
853 return;
856 isc_app_shutdown();
860 main(int argc, char **argv) {
861 isc_result_t result;
863 ISC_LIST_INIT(lookup_list);
864 ISC_LIST_INIT(server_list);
865 ISC_LIST_INIT(search_list);
867 check_ra = ISC_TRUE;
869 result = isc_app_start();
870 check_result(result, "isc_app_start");
872 setup_libs();
873 progname = argv[0];
875 parse_args(argc, argv);
877 setup_system();
878 if (domainopt[0] != '\0')
879 set_search_domain(domainopt);
880 if (in_use)
881 result = isc_app_onrun(mctx, global_task, onrun_callback,
882 NULL);
883 else
884 result = isc_app_onrun(mctx, global_task, getinput, NULL);
885 check_result(result, "isc_app_onrun");
886 in_use = ISC_TF(!in_use);
888 (void)isc_app_run();
890 puts("");
891 debug("done, and starting to shut down");
892 if (global_event != NULL)
893 isc_event_free(&global_event);
894 cancel_all();
895 destroy_libs();
896 isc_app_finish();
898 return (0);