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