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 $ */
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>
33 #include <isc/netaddr.h>
35 #include <dns/message.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>
47 static isc_boolean_t short_form
= ISC_TRUE
,
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
[] = {
82 static const char *rtypetext
[] = {
84 "internet address = ", /* 1 */
85 "nameserver = ", /* 2 */
88 "canonical name = ", /* 5 */
93 "rtype_10 = ", /* 10 */
94 "protocol = ", /* 11 */
98 "mail exchanger = ", /* 15 */
102 "x25 address = ", /* 19 */
103 "isdn address = ", /* 20 */
106 "nsap_ptr = ", /* 23 */
107 "signature = ", /* 24 */
111 "has AAAA address ", /* 28 */
114 "rtype_31 = ", /* 31 */
115 "rtype_32 = ", /* 32 */
116 "service = ", /* 33 */
117 "rtype_34 = ", /* 34 */
121 "v6 address = ", /* 38 */
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
);
133 dighost_shutdown(void) {
134 isc_event_t
*event
= global_event
;
137 debug("dighost_shutdown()");
144 isc_task_send(global_task
, &event
);
148 printsoa(dns_rdata_t
*rdata
) {
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
);
169 printa(dns_rdata_t
*rdata
) {
171 char text
[sizeof("255.255.255.255")];
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
));
181 /* Just for compatibility : not use in host program */
183 printrdataset(dns_name_t
*owner_name
, dns_rdataset_t
*rdataset
,
184 isc_buffer_t
*target
)
193 printrdata(dns_rdata_t
*rdata
) {
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
]);
202 printf("rdata_%d = ", rdata
->type
);
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
));
213 } else if (result
!= ISC_R_NOSPACE
)
214 check_result(result
, "dns_rdata_totext");
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
;
225 dns_rdataset_t
*rdataset
= NULL
;
226 dns_rdata_t rdata
= DNS_RDATA_INIT
;
227 char namebuf
[DNS_NAME_FORMATSIZE
];
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
)
241 dns_message_currentname(msg
, section
,
243 for (rdataset
= ISC_LIST_HEAD(name
->list
);
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
,
255 printf("Name:\t%s\n", namebuf
);
258 case dns_rdatatype_soa
:
259 dns_name_format(name
, namebuf
,
261 printf("%s\n", namebuf
);
266 dns_name_format(name
, namebuf
,
268 printf("%s\t", namebuf
);
272 dns_rdata_reset(&rdata
);
273 loopresult
= dns_rdataset_next(rdataset
);
276 result
= dns_message_nextname(msg
, section
);
277 if (result
== ISC_R_NOMORE
)
279 else if (result
!= ISC_R_SUCCESS
) {
283 return (ISC_R_SUCCESS
);
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
;
291 dns_rdataset_t
*rdataset
= NULL
;
292 dns_rdata_t rdata
= DNS_RDATA_INIT
;
293 char namebuf
[DNS_NAME_FORMATSIZE
];
297 debug("detailsection()");
301 case DNS_SECTION_QUESTION
:
304 case DNS_SECTION_ANSWER
:
307 case DNS_SECTION_AUTHORITY
:
308 puts(" AUTHORITY RECORDS:");
310 case DNS_SECTION_ADDITIONAL
:
311 puts(" ADDITIONAL RECORDS:");
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
)
323 dns_message_currentname(msg
, section
,
325 for (rdataset
= ISC_LIST_HEAD(name
->list
);
327 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
328 if (section
== DNS_SECTION_QUESTION
) {
329 dns_name_format(name
, namebuf
,
331 printf("\t%s, ", namebuf
);
332 dns_rdatatype_format(rdataset
->type
,
335 printf("type = %s, ", namebuf
);
336 dns_rdataclass_format(rdataset
->rdclass
,
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
,
347 printf(" -> %s\n", namebuf
);
349 switch (rdata
.type
) {
350 case dns_rdatatype_soa
:
357 dns_rdata_reset(&rdata
);
358 loopresult
= dns_rdataset_next(rdataset
);
361 result
= dns_message_nextname(msg
, section
);
362 if (result
== ISC_R_NOMORE
)
364 else if (result
!= ISC_R_SUCCESS
) {
368 return (ISC_R_SUCCESS
);
372 received(int bytes
, isc_sockaddr_t
*from
, dig_query_t
*query
)
380 trying(char *frm
, dig_lookup_t
*lookup
) {
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
);
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
);
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
);
440 show_settings(isc_boolean_t full
, isc_boolean_t serv_only
) {
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
);
456 srv
= ISC_LIST_NEXT(srv
, link
);
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
);
474 listent
= ISC_LIST_NEXT(listent
, link
)) {
475 printf("%s", listent
->origin
);
476 if (ISC_LIST_NEXT(listent
, link
) != NULL
)
483 testtype(char *typetext
) {
486 dns_rdatatype_t rdtype
;
489 tr
.length
= strlen(typetext
);
490 result
= dns_rdatatype_fromtext(&rdtype
, &tr
);
491 if (result
== ISC_R_SUCCESS
)
494 printf("unknown query type: %s\n", typetext
);
500 testclass(char *typetext
) {
503 dns_rdataclass_t rdclass
;
506 tr
.length
= strlen(typetext
);
507 result
= dns_rdataclass_fromtext(&rdclass
, &tr
);
508 if (result
== ISC_R_SUCCESS
)
511 printf("unknown query class: %s\n", typetext
);
517 safecpy(char *dest
, char *src
, int size
) {
518 strncpy(dest
, src
, size
);
523 parse_uint(isc_uint32_t
*uip
, const char *value
, isc_uint32_t max
,
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
));
535 return (ISC_R_SUCCESS
);
539 set_port(const char *value
) {
541 isc_result_t result
= parse_uint(&n
, value
, 65535, "port");
542 if (result
== ISC_R_SUCCESS
)
543 port
= (isc_uint16_t
) n
;
547 set_timeout(const char *value
) {
549 isc_result_t result
= parse_uint(&n
, value
, UINT_MAX
, "timeout");
550 if (result
== ISC_R_SUCCESS
)
555 set_tries(const char *value
) {
557 isc_result_t result
= parse_uint(&n
, value
, INT_MAX
, "tries");
558 if (result
== ISC_R_SUCCESS
)
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) {
600 } else if (strncasecmp(opt
, "po=", 3) == 0) {
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) {
608 } else if (strncasecmp(opt
, "norec", 5) == 0) {
610 } else if (strncasecmp(opt
, "retry=", 6) == 0) {
612 } else if (strncasecmp(opt
, "ret=", 4) == 0) {
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) {
620 } else if (strncasecmp(opt
, "novc", 5) == 0) {
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) {
640 } else if (strncasecmp(opt
, "nofail", 3) == 0) {
643 printf("*** Invalid option: %s\n", opt
);
648 addlookup(char *opt
) {
649 dig_lookup_t
*lookup
;
652 dns_rdatatype_t rdtype
;
653 dns_rdataclass_t rdclass
;
656 debug("addlookup()");
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
;
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
)
674 safecpy(lookup
->textname
, store
, sizeof(lookup
->textname
));
675 lookup
->rdtype
= dns_rdatatype_ptr
;
676 lookup
->rdtypeset
= ISC_TRUE
;
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
;
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
;
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
);
711 get_next_command(void) {
717 buf
= isc_mem_allocate(mctx
, COMMSIZE
);
719 fatal("memory allocation failure");
723 ptr
= fgets(buf
, COMMSIZE
, stdin
);
730 ptr
= next_token(&input
, " \t\r\n");
733 arg
= next_token(&input
, " \t\r\n");
734 if ((strcasecmp(ptr
, "set") == 0) &&
737 else if ((strcasecmp(ptr
, "server") == 0) ||
738 (strcasecmp(ptr
, "lserver") == 0)) {
741 check_ra
= ISC_FALSE
;
743 show_settings(ISC_TRUE
, ISC_TRUE
);
744 } else if (strcasecmp(ptr
, "exit") == 0) {
747 } else if (strcasecmp(ptr
, "help") == 0 ||
748 strcasecmp(ptr
, "?") == 0) {
749 printf("The '%s' command is not yet implemented.\n", ptr
);
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
);
760 isc_mem_free(mctx
, buf
);
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] == '-') {
772 setoption(&argv
[0][1]);
774 have_lookup
= ISC_TRUE
;
777 have_lookup
= ISC_TRUE
;
781 set_nameserver(argv
[0]);
782 check_ra
= ISC_FALSE
;
789 flush_lookup_list(void) {
790 dig_lookup_t
*l
, *lp
;
792 dig_server_t
*s
, *sp
;
795 l
= ISC_LIST_HEAD(lookup_list
);
797 q
= ISC_LIST_HEAD(l
->q
);
799 if (q
->sock
!= NULL
) {
800 isc_socket_cancel(q
->sock
, NULL
,
802 isc_socket_detach(&q
->sock
);
804 if (ISC_LINK_LINKED(&q
->recvbuf
, link
))
805 ISC_LIST_DEQUEUE(q
->recvlist
, &q
->recvbuf
,
807 if (ISC_LINK_LINKED(&q
->lengthbuf
, link
))
808 ISC_LIST_DEQUEUE(q
->lengthlist
, &q
->lengthbuf
,
810 isc_buffer_invalidate(&q
->recvbuf
);
811 isc_buffer_invalidate(&q
->lengthbuf
);
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
);
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
);
830 l
= ISC_LIST_NEXT(l
, link
);
831 ISC_LIST_DEQUEUE(lookup_list
, lp
, link
);
832 isc_mem_free(mctx
, lp
);
837 getinput(isc_task_t
*task
, isc_event_t
*event
) {
839 if (global_event
== NULL
)
840 global_event
= event
;
843 if (ISC_LIST_HEAD(lookup_list
) != NULL
) {
852 main(int argc
, char **argv
) {
855 ISC_LIST_INIT(lookup_list
);
856 ISC_LIST_INIT(server_list
);
857 ISC_LIST_INIT(search_list
);
861 result
= isc_app_start();
862 check_result(result
, "isc_app_start");
867 parse_args(argc
, argv
);
870 if (domainopt
[0] != '\0')
871 set_search_domain(domainopt
);
873 result
= isc_app_onrun(mctx
, global_task
, onrun_callback
,
876 result
= isc_app_onrun(mctx
, global_task
, getinput
, NULL
);
877 check_result(result
, "isc_app_onrun");
878 in_use
= ISC_TF(!in_use
);
883 debug("done, and starting to shut down");
884 if (global_event
!= NULL
)
885 isc_event_free(&global_event
);