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 */
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>
36 #include <isc/netaddr.h>
38 #include <dns/message.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>
50 static isc_boolean_t short_form
= ISC_TRUE
,
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
[] = {
85 static const char *rtypetext
[] = {
87 "internet address = ", /* 1 */
88 "nameserver = ", /* 2 */
91 "canonical name = ", /* 5 */
96 "rtype_10 = ", /* 10 */
97 "protocol = ", /* 11 */
101 "mail exchanger = ", /* 15 */
105 "x25 address = ", /* 19 */
106 "isdn address = ", /* 20 */
109 "nsap_ptr = ", /* 23 */
110 "signature = ", /* 24 */
114 "has AAAA address ", /* 28 */
117 "rtype_31 = ", /* 31 */
118 "rtype_32 = ", /* 32 */
119 "service = ", /* 33 */
120 "rtype_34 = ", /* 34 */
124 "v6 address = ", /* 38 */
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
);
136 rcode_totext(dns_rcode_t rcode
)
138 static char buf
[sizeof("?65535")];
140 const char *consttext
;
144 if (rcode
>= (sizeof(rcodetext
)/sizeof(rcodetext
[0]))) {
145 snprintf(buf
, sizeof(buf
), "?%u", rcode
);
146 totext
.deconsttext
= buf
;
148 totext
.consttext
= rcodetext
[rcode
];
149 return totext
.deconsttext
;
153 dighost_shutdown(void) {
154 isc_event_t
*event
= global_event
;
157 debug("dighost_shutdown()");
164 isc_task_send(global_task
, &event
);
168 printsoa(dns_rdata_t
*rdata
) {
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
);
189 printa(dns_rdata_t
*rdata
) {
191 char text
[sizeof("255.255.255.255")];
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
));
201 /* Just for compatibility : not use in host program */
203 printrdataset(dns_name_t
*owner_name
, dns_rdataset_t
*rdataset
,
204 isc_buffer_t
*target
)
213 printrdata(dns_rdata_t
*rdata
) {
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
]);
222 printf("rdata_%d = ", rdata
->type
);
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
));
233 } else if (result
!= ISC_R_NOSPACE
)
234 check_result(result
, "dns_rdata_totext");
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
;
245 dns_rdataset_t
*rdataset
= NULL
;
246 dns_rdata_t rdata
= DNS_RDATA_INIT
;
247 char namebuf
[DNS_NAME_FORMATSIZE
];
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
)
261 dns_message_currentname(msg
, section
,
263 for (rdataset
= ISC_LIST_HEAD(name
->list
);
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
,
275 printf("Name:\t%s\n", namebuf
);
278 case dns_rdatatype_soa
:
279 dns_name_format(name
, namebuf
,
281 printf("%s\n", namebuf
);
286 dns_name_format(name
, namebuf
,
288 printf("%s\t", namebuf
);
292 dns_rdata_reset(&rdata
);
293 loopresult
= dns_rdataset_next(rdataset
);
296 result
= dns_message_nextname(msg
, section
);
297 if (result
== ISC_R_NOMORE
)
299 else if (result
!= ISC_R_SUCCESS
) {
303 return (ISC_R_SUCCESS
);
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
;
311 dns_rdataset_t
*rdataset
= NULL
;
312 dns_rdata_t rdata
= DNS_RDATA_INIT
;
313 char namebuf
[DNS_NAME_FORMATSIZE
];
317 debug("detailsection()");
321 case DNS_SECTION_QUESTION
:
324 case DNS_SECTION_ANSWER
:
327 case DNS_SECTION_AUTHORITY
:
328 puts(" AUTHORITY RECORDS:");
330 case DNS_SECTION_ADDITIONAL
:
331 puts(" ADDITIONAL RECORDS:");
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
)
343 dns_message_currentname(msg
, section
,
345 for (rdataset
= ISC_LIST_HEAD(name
->list
);
347 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
348 if (section
== DNS_SECTION_QUESTION
) {
349 dns_name_format(name
, namebuf
,
351 printf("\t%s, ", namebuf
);
352 dns_rdatatype_format(rdataset
->type
,
355 printf("type = %s, ", namebuf
);
356 dns_rdataclass_format(rdataset
->rdclass
,
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
,
367 printf(" -> %s\n", namebuf
);
369 switch (rdata
.type
) {
370 case dns_rdatatype_soa
:
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
)
385 else if (result
!= ISC_R_SUCCESS
) {
389 return (ISC_R_SUCCESS
);
393 received(int bytes
, isc_sockaddr_t
*from
, dig_query_t
*query
)
401 trying(char *frm
, dig_lookup_t
*lookup
) {
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
);
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
);
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
);
461 show_settings(isc_boolean_t full
, isc_boolean_t serv_only
) {
463 isc_sockaddr_t sockaddr
;
464 dig_searchlist_t
*listent
;
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
);
480 srv
= ISC_LIST_NEXT(srv
, link
);
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
);
498 listent
= ISC_LIST_NEXT(listent
, link
)) {
499 printf("%s", listent
->origin
);
500 if (ISC_LIST_NEXT(listent
, link
) != NULL
)
507 testtype(char *typetext
) {
510 dns_rdatatype_t rdtype
;
513 tr
.length
= strlen(typetext
);
514 result
= dns_rdatatype_fromtext(&rdtype
, &tr
);
515 if (result
== ISC_R_SUCCESS
)
518 printf("unknown query type: %s\n", typetext
);
524 testclass(char *typetext
) {
527 dns_rdataclass_t rdclass
;
530 tr
.length
= strlen(typetext
);
531 result
= dns_rdataclass_fromtext(&rdclass
, &tr
);
532 if (result
== ISC_R_SUCCESS
)
535 printf("unknown query class: %s\n", typetext
);
541 safecpy(char *dest
, char *src
, int size
) {
542 strncpy(dest
, src
, size
);
547 set_port(const char *value
) {
549 isc_result_t result
= parse_uint(&n
, value
, 65535, "port");
550 if (result
== ISC_R_SUCCESS
)
551 port
= (isc_uint16_t
) n
;
555 set_timeout(const char *value
) {
557 isc_result_t result
= parse_uint(&n
, value
, UINT_MAX
, "timeout");
558 if (result
== ISC_R_SUCCESS
)
563 set_tries(const char *value
) {
565 isc_result_t result
= parse_uint(&n
, value
, INT_MAX
, "tries");
566 if (result
== ISC_R_SUCCESS
)
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) {
608 } else if (strncasecmp(opt
, "po=", 3) == 0) {
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) {
616 } else if (strncasecmp(opt
, "norec", 5) == 0) {
618 } else if (strncasecmp(opt
, "retry=", 6) == 0) {
620 } else if (strncasecmp(opt
, "ret=", 4) == 0) {
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) {
628 } else if (strncasecmp(opt
, "novc", 5) == 0) {
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) {
648 } else if (strncasecmp(opt
, "nofail", 3) == 0) {
651 printf("*** Invalid option: %s\n", opt
);
656 addlookup(char *opt
) {
657 dig_lookup_t
*lookup
;
660 dns_rdatatype_t rdtype
;
661 dns_rdataclass_t rdclass
;
664 debug("addlookup()");
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
;
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
)
682 safecpy(lookup
->textname
, store
, sizeof(lookup
->textname
));
683 lookup
->rdtype
= dns_rdatatype_ptr
;
684 lookup
->rdtypeset
= ISC_TRUE
;
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
;
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
;
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
);
719 get_next_command(void) {
725 buf
= isc_mem_allocate(mctx
, COMMSIZE
);
727 fatal("memory allocation failure");
731 ptr
= fgets(buf
, COMMSIZE
, stdin
);
738 ptr
= next_token(&input
, " \t\r\n");
741 arg
= next_token(&input
, " \t\r\n");
742 if ((strcasecmp(ptr
, "set") == 0) &&
745 else if ((strcasecmp(ptr
, "server") == 0) ||
746 (strcasecmp(ptr
, "lserver") == 0)) {
749 check_ra
= ISC_FALSE
;
751 show_settings(ISC_TRUE
, ISC_TRUE
);
752 } else if (strcasecmp(ptr
, "exit") == 0) {
755 } else if (strcasecmp(ptr
, "help") == 0 ||
756 strcasecmp(ptr
, "?") == 0) {
757 printf("The '%s' command is not yet implemented.\n", ptr
);
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
);
768 isc_mem_free(mctx
, buf
);
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] == '-') {
780 setoption(&argv
[0][1]);
782 have_lookup
= ISC_TRUE
;
785 have_lookup
= ISC_TRUE
;
789 set_nameserver(argv
[0]);
790 check_ra
= ISC_FALSE
;
797 flush_lookup_list(void) {
798 dig_lookup_t
*l
, *lp
;
800 dig_server_t
*s
, *sp
;
803 l
= ISC_LIST_HEAD(lookup_list
);
805 q
= ISC_LIST_HEAD(l
->q
);
807 if (q
->sock
!= NULL
) {
808 isc_socket_cancel(q
->sock
, NULL
,
810 isc_socket_detach(&q
->sock
);
812 if (ISC_LINK_LINKED(&q
->recvbuf
, link
))
813 ISC_LIST_DEQUEUE(q
->recvlist
, &q
->recvbuf
,
815 if (ISC_LINK_LINKED(&q
->lengthbuf
, link
))
816 ISC_LIST_DEQUEUE(q
->lengthlist
, &q
->lengthbuf
,
818 isc_buffer_invalidate(&q
->recvbuf
);
819 isc_buffer_invalidate(&q
->lengthbuf
);
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
);
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
);
838 l
= ISC_LIST_NEXT(l
, link
);
839 ISC_LIST_DEQUEUE(lookup_list
, lp
, link
);
840 isc_mem_free(mctx
, lp
);
845 getinput(isc_task_t
*task
, isc_event_t
*event
) {
847 if (global_event
== NULL
)
848 global_event
= event
;
851 if (ISC_LIST_HEAD(lookup_list
) != NULL
) {
860 main(int argc
, char **argv
) {
863 ISC_LIST_INIT(lookup_list
);
864 ISC_LIST_INIT(server_list
);
865 ISC_LIST_INIT(search_list
);
869 result
= isc_app_start();
870 check_result(result
, "isc_app_start");
875 parse_args(argc
, argv
);
878 if (domainopt
[0] != '\0')
879 set_search_domain(domainopt
);
881 result
= isc_app_onrun(mctx
, global_task
, onrun_callback
,
884 result
= isc_app_onrun(mctx
, global_task
, getinput
, NULL
);
885 check_result(result
, "isc_app_onrun");
886 in_use
= ISC_TF(!in_use
);
891 debug("done, and starting to shut down");
892 if (global_event
!= NULL
)
893 isc_event_free(&global_event
);