2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 06:55:30 +00:00

Add comments to source code

This commit is contained in:
Michael Sawyer
2000-07-18 18:51:40 +00:00
parent 0ade7651fc
commit 5e804988e9
2 changed files with 192 additions and 74 deletions

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: dig.c,v 1.69 2000/07/18 01:28:15 mws Exp $ */ /* $Id: dig.c,v 1.70 2000/07/18 18:51:38 mws Exp $ */
#include <config.h> #include <config.h>
#include <stdlib.h> #include <stdlib.h>
@@ -173,6 +173,9 @@ show_usage(void) {
, stderr); , stderr);
} }
/*
* Callback from dighost.c to print the received message.
*/
void void
received(int bytes, int frmsize, char *frm, dig_query_t *query) { received(int bytes, int frmsize, char *frm, dig_query_t *query) {
isc_uint64_t diff; isc_uint64_t diff;
@@ -208,6 +211,10 @@ received(int bytes, int frmsize, char *frm, dig_query_t *query) {
} }
} }
/*
* Callback from dighost.c to print that it is trying a server.
* Not used in dig.
*/
void void
trying(int frmsize, char *frm, dig_lookup_t *lookup) { trying(int frmsize, char *frm, dig_lookup_t *lookup) {
UNUSED(frmsize); UNUSED(frmsize);
@@ -215,6 +222,9 @@ trying(int frmsize, char *frm, dig_lookup_t *lookup) {
UNUSED(lookup); UNUSED(lookup);
} }
/*
* Internal print routine used to print short form replies.
*/
static isc_result_t static isc_result_t
say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) { say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) {
isc_result_t result; isc_result_t result;
@@ -244,6 +254,9 @@ say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) {
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
/*
* short_form message print handler. Calls above say_message()
*/
static isc_result_t static isc_result_t
short_answer(dns_message_t *msg, dns_messagetextflag_t flags, short_answer(dns_message_t *msg, dns_messagetextflag_t flags,
isc_buffer_t *buf, dig_query_t *query) isc_buffer_t *buf, dig_query_t *query)
@@ -293,7 +306,9 @@ short_answer(dns_message_t *msg, dns_messagetextflag_t flags,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
/*
* Callback from dighost.c to print the reply from a server
*/
isc_result_t isc_result_t
printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
isc_boolean_t did_flag = ISC_FALSE; isc_boolean_t did_flag = ISC_FALSE;
@@ -478,6 +493,9 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
return (result); return (result);
} }
/*
* print the greeting message when the program first starts up.
*/
static void static void
printgreeting(int argc, char **argv) { printgreeting(int argc, char **argv) {
int i = 1; int i = 1;
@@ -534,7 +552,7 @@ reorder_args(int argc, char *argv[]) {
/* /*
* We're not using isc_commandline_parse() here since the command line * We're not using isc_commandline_parse() here since the command line
* syntax of dig is quite a bit different from that which can be described * syntax of dig is quite a bit different from that which can be described
* that routine. There is a portability issue here. * that routine.
*/ */
static void static void
parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
@@ -969,6 +987,11 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
} }
} }
/*
* Callback from dighost.c to allow program-specific shutdown code. Here,
* Here, we're possibly reading from a batch file, then shutting down for
* real if there's nothing in the batch file to read.
*/
void void
dighost_shutdown(void) { dighost_shutdown(void) {
char batchline[MXNAME]; char batchline[MXNAME];

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: dighost.c,v 1.90 2000/07/18 01:28:16 mws Exp $ */ /* $Id: dighost.c,v 1.91 2000/07/18 18:51:40 mws Exp $ */
/* /*
* Notice to programmers: Do not use this code as an example of how to * Notice to programmers: Do not use this code as an example of how to
@@ -128,6 +128,12 @@ dig_lookup_t *current_lookup = NULL;
static void static void
cancel_lookup(dig_lookup_t *lookup); cancel_lookup(dig_lookup_t *lookup);
static void
recv_done(isc_task_t *task, isc_event_t *event);
static void
connect_timeout(isc_task_t *task, isc_event_t *event);
static int static int
count_dots(char *string) { count_dots(char *string) {
char *s; char *s;
@@ -170,15 +176,6 @@ fatal(const char *format, ...) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
if (exitcode == 0) if (exitcode == 0)
exitcode = 8; exitcode = 8;
#ifdef NEVER
dighost_shutdown();
free_lists(exitcode);
if (mctx != NULL) {
if (isc_mem_debugging)
isc_mem_stats(mctx, stderr);
isc_mem_destroy(&mctx);
}
#endif
exit(exitcode); exit(exitcode);
} }
@@ -202,6 +199,11 @@ check_result(isc_result_t result, const char *msg) {
} }
} }
/*
* Create a server structure, which is part of the lookup structure.
* This is little more than a linked list of servers to query in hopes
* of finding the answer the user is looking for
*/
dig_server_t * dig_server_t *
make_server(const char *servname) { make_server(const char *servname) {
dig_server_t *srv; dig_server_t *srv;
@@ -217,6 +219,10 @@ make_server(const char *servname) {
return (srv); return (srv);
} }
/*
* Produce a cloned server list. The dest list must have already had
* ISC_LIST_INIT applied.
*/
void void
clone_server_list(dig_serverlist_t src, clone_server_list(dig_serverlist_t src,
dig_serverlist_t *dest) dig_serverlist_t *dest)
@@ -232,6 +238,12 @@ clone_server_list(dig_serverlist_t src,
} }
} }
/*
* Create an empty lookup structure, which holds all the information needed
* to get an answer to a user's question. This structure contains two
* linked lists: the server list (servers to query) and the query list
* (outstanding queries which have been made to the listed servers).
*/
dig_lookup_t * dig_lookup_t *
make_empty_lookup(void) { make_empty_lookup(void) {
dig_lookup_t *looknew; dig_lookup_t *looknew;
@@ -284,6 +296,9 @@ make_empty_lookup(void) {
} }
/* /*
* Clone a lookup, perhaps copying the server list. This does not clone
* the query list, since it will be regenerated by the setup_lookup()
* function, nor does it queue up the new lookup for processing.
* Caution: If you don't clone the servers, you MUST clone the server * Caution: If you don't clone the servers, you MUST clone the server
* list seperately from somewhere else, or construct it by hand. * list seperately from somewhere else, or construct it by hand.
*/ */
@@ -326,6 +341,14 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
return (looknew); return (looknew);
} }
/*
* Requeue a lookup for further processing, perhaps copying the server
* list. The new lookup structure is returned to the caller, and is
* queued for processing. If servers are not cloned in the requeue, they
* must be added before allowing the current event to complete, since the
* completion of the event may result in the next entry on the lookup
* queue getting run.
*/
dig_lookup_t * dig_lookup_t *
requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
dig_lookup_t *looknew; dig_lookup_t *looknew;
@@ -349,6 +372,10 @@ requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
return (looknew); return (looknew);
} }
/*
* Setup the system as a whole, reading key information and resolv.conf
* settings.
*/
void void
setup_system(void) { setup_system(void) {
char rcinput[MXNAME]; char rcinput[MXNAME];
@@ -542,6 +569,9 @@ setup_system(void) {
} }
} }
/*
* Setup the ISC and DNS libraries for use by the system.
*/
void void
setup_libs(void) { setup_libs(void) {
isc_result_t result; isc_result_t result;
@@ -601,6 +631,10 @@ setup_libs(void) {
check_result(result, "isc_mutex_init"); check_result(result, "isc_mutex_init");
} }
/*
* Add EDNS0 option record to a message. Currently, the only supported
* option is UDP buffer size.
*/
static void static void
add_opt(dns_message_t *msg, isc_uint16_t udpsize) { add_opt(dns_message_t *msg, isc_uint16_t udpsize) {
dns_rdataset_t *rdataset = NULL; dns_rdataset_t *rdataset = NULL;
@@ -631,6 +665,10 @@ add_opt(dns_message_t *msg, isc_uint16_t udpsize) {
check_result(result, "dns_message_setopt"); check_result(result, "dns_message_setopt");
} }
/*
* Add a question section to a message, asking for the specified name,
* type, and class.
*/
static void static void
add_question(dns_message_t *message, dns_name_t *name, add_question(dns_message_t *message, dns_name_t *name,
dns_rdataclass_t rdclass, dns_rdatatype_t rdtype) dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
@@ -648,7 +686,12 @@ add_question(dns_message_t *message, dns_name_t *name,
} }
/* /*
* We're done iff all the counts are zero and the lookup list is empty * Check if we're done with all the queued lookups, which is true iff
* all sockets, sends, and recvs are accounted for (counters == 0),
* and the lookup list is empty.
* If we are done, pass control back out to dighost_shutdown() (which is
* part of dig.c, host.c, or nslookup.c) to either shutdown the system as
* a whole or reseed the lookup list.
*/ */
static void static void
check_if_done(void) { check_if_done(void) {
@@ -696,6 +739,11 @@ clear_query(dig_query_t *query) {
isc_mem_free(mctx, query); isc_mem_free(mctx, query);
} }
/*
* Try and clear out a lookup if we're done with it. Return ISC_TRUE if
* the lookup was successfully cleared. If ISC_TRUE is returned, the
* lookup pointer has been invalidated.
*/
static isc_boolean_t static isc_boolean_t
try_clear_lookup(dig_lookup_t *lookup) { try_clear_lookup(dig_lookup_t *lookup) {
dig_server_t *s; dig_server_t *s;
@@ -751,7 +799,8 @@ try_clear_lookup(dig_lookup_t *lookup) {
/* /*
* If we can, start the next lookup in the queue running. * If we can, start the next lookup in the queue running.
* This assumes that the lookup on the head of the queue hasn't been * This assumes that the lookup on the head of the queue hasn't been
* started yet. * started yet. It also moves the lookup from the head of the queue
* off, setting the current_lookup pointer pointing to it.
*/ */
void void
start_lookup(void) { start_lookup(void) {
@@ -782,9 +831,8 @@ start_lookup(void) {
} }
/* /*
* WARNING: The following routine may invalidate the lookup pointer. * If we can, clear the current lookup and start the next one running.
* Never depend on being able to reference lookup or query pointers on the * This calls try_clear_lookup, so may invalidate the lookup pointer.
* current lookup after calling this.
*/ */
static void static void
check_next_lookup(dig_lookup_t *lookup) { check_next_lookup(dig_lookup_t *lookup) {
@@ -810,6 +858,12 @@ check_next_lookup(dig_lookup_t *lookup) {
} }
} }
/*
* Create and queue a new lookup as a followup to the current lookup,
* based on the supplied message and section. This is used in trace and
* name server search modes to start a new lookup using servers from
* NS records in a reply.
*/
static void static void
followup_lookup(dns_message_t *msg, dig_query_t *query, followup_lookup(dns_message_t *msg, dig_query_t *query,
dns_section_t section) { dns_section_t section) {
@@ -920,6 +974,10 @@ followup_lookup(dns_message_t *msg, dig_query_t *query,
followup_lookup(msg, query, DNS_SECTION_AUTHORITY); followup_lookup(msg, query, DNS_SECTION_AUTHORITY);
} }
/*
* Create and queue a new lookup using the next origin from the origin
* list, read in setup_system().
*/
static void static void
next_origin(dns_message_t *msg, dig_query_t *query) { next_origin(dns_message_t *msg, dig_query_t *query) {
dig_lookup_t *lookup; dig_lookup_t *lookup;
@@ -944,7 +1002,10 @@ next_origin(dns_message_t *msg, dig_query_t *query) {
lookup->origin = ISC_LIST_NEXT(query->lookup->origin, link); lookup->origin = ISC_LIST_NEXT(query->lookup->origin, link);
} }
/*
* Insert an SOA record into the sendmessage in a lookup. Used for
* creating IXFR queries.
*/
static void static void
insert_soa(dig_lookup_t *lookup) { insert_soa(dig_lookup_t *lookup) {
isc_result_t result; isc_result_t result;
@@ -1006,6 +1067,12 @@ insert_soa(dig_lookup_t *lookup) {
dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY); dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
} }
/*
* Setup the supplied lookup structure, making it ready to start sending
* queries to servers. Create and initialize the message to be sent as
* well as the query structures and buffer space for the replies. If the
* server list is empty, clone it from the system default list.
*/
void void
setup_lookup(dig_lookup_t *lookup) { setup_lookup(dig_lookup_t *lookup) {
isc_result_t result, res2; isc_result_t result, res2;
@@ -1235,6 +1302,13 @@ setup_lookup(dig_lookup_t *lookup) {
} }
} }
/*
* Event handler for send completion. Track send counter, and clear out
* the query if the send was canceled.
* XXXMWS Possible race condition! When the send gets canceled, doesn't the
* recv also, so it will also be trying to clear out the query?
* Not really sure that this should touch the query at all.
*/
static void static void
send_done(isc_task_t *task, isc_event_t *event) { send_done(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = NULL; isc_socketevent_t *sevent = NULL;
@@ -1267,6 +1341,11 @@ send_done(isc_task_t *task, isc_event_t *event) {
UNLOCK_LOOKUP; UNLOCK_LOOKUP;
} }
/*
* Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
* IO sockets. The cancel handlers should take care of cleaning up the
* query and lookup structures
*/
void void
cancel_lookup(dig_lookup_t *lookup) { cancel_lookup(dig_lookup_t *lookup) {
dig_query_t *query = NULL; dig_query_t *query = NULL;
@@ -1288,12 +1367,11 @@ cancel_lookup(dig_lookup_t *lookup) {
lookup->retries = 0; lookup->retries = 0;
} }
static void /*
recv_done(isc_task_t *task, isc_event_t *event); * Send a UDP packet to the remote nameserver, possible starting the
* recv action as well. Also make sure that the timer is running and
static void * is properly reset.
connect_timeout(isc_task_t *task, isc_event_t *event); */
static void static void
send_udp(dig_lookup_t *lookup, isc_boolean_t make_recv) { send_udp(dig_lookup_t *lookup, isc_boolean_t make_recv) {
dig_query_t *query; dig_query_t *query;
@@ -1366,7 +1444,9 @@ send_udp(dig_lookup_t *lookup, isc_boolean_t make_recv) {
} }
/* /*
* connect_timeout is used for both UDP recieves and TCP connects. * IO timeout handler, used for both connect and recv timeouts. If
* retries are still allowed, either resend the UDP packet or queue a
* new TCP lookup. Otherwise, cancel the lookup.
*/ */
static void static void
connect_timeout(isc_task_t *task, isc_event_t *event) { connect_timeout(isc_task_t *task, isc_event_t *event) {
@@ -1400,6 +1480,10 @@ connect_timeout(isc_task_t *task, isc_event_t *event) {
UNLOCK_LOOKUP; UNLOCK_LOOKUP;
} }
/*
* Event handler for the TCP recv which gets the length header of TCP
* packets. Start the next recv of length bytes.
*/
static void static void
tcp_length_done(isc_task_t *task, isc_event_t *event) { tcp_length_done(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent; isc_socketevent_t *sevent;
@@ -1481,6 +1565,10 @@ tcp_length_done(isc_task_t *task, isc_event_t *event) {
UNLOCK_LOOKUP; UNLOCK_LOOKUP;
} }
/*
* For transfers that involve multiple recvs (XFR's in particular),
* launch the next recv.
*/
static void static void
launch_next_query(dig_query_t *query, isc_boolean_t include_question) { launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
isc_result_t result; isc_result_t result;
@@ -1521,7 +1609,7 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
recvcount++; recvcount++;
debug("recvcount=%d",recvcount); debug("recvcount=%d",recvcount);
if (!query->first_soa_rcvd) { if (!query->first_soa_rcvd) {
debug("sending a request"); debug("sending a request in launch_next_query");
result = isc_time_now(&query->time_sent); result = isc_time_now(&query->time_sent);
check_result(result, "isc_time_now"); check_result(result, "isc_time_now");
result = isc_socket_sendv(query->sock, &query->sendlist, result = isc_socket_sendv(query->sock, &query->sendlist,
@@ -1531,10 +1619,17 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
debug("sendcount=%d", sendcount); debug("sendcount=%d", sendcount);
} }
query->waiting_connect = ISC_FALSE; query->waiting_connect = ISC_FALSE;
#if 0
check_next_lookup(query->lookup); check_next_lookup(query->lookup);
#endif
return; return;
} }
/*
* Event handler for TCP connect complete. Make sure the connection was
* successful, then pass into launch_next_query to actually send the
* question.
*/
static void static void
connect_done(isc_task_t *task, isc_event_t *event) { connect_done(isc_task_t *task, isc_event_t *event) {
isc_result_t result; isc_result_t result;
@@ -1593,32 +1688,11 @@ connect_done(isc_task_t *task, isc_event_t *event) {
UNLOCK_LOOKUP; UNLOCK_LOOKUP;
} }
#if 0
static isc_boolean_t
msg_contains_soa(dns_message_t *msg, dig_query_t *query) {
isc_result_t result;
dns_name_t *name=NULL;
debug("msg_contains_soa()");
result = dns_message_findname(msg, DNS_SECTION_ANSWER,
query->lookup->name, dns_rdatatype_soa,
0, &name, NULL);
if (result == ISC_R_SUCCESS) {
debug("found SOA", stderr);
return (ISC_TRUE);
} else {
debug("didn't find SOA, result=%d:%s",
result, dns_result_totext(result));
return (ISC_FALSE);
}
}
#endif
/* /*
* Returns true if we should call cancel_lookup(). This is a hack. * Check if the ongoing XFR needs more data before it's complete, using
* the semantics of IXFR and AXFR protocols. Much of the complexity of
* this routine comes from determining when an IXFR is complete.
* ISC_TRUE means more data is on the way, and the recv has been issued.
*/ */
static isc_boolean_t static isc_boolean_t
check_for_more_data(dig_query_t *query, dns_message_t *msg, check_for_more_data(dig_query_t *query, dns_message_t *msg,
@@ -1649,9 +1723,6 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
query->working = ISC_FALSE; query->working = ISC_FALSE;
return (ISC_TRUE); return (ISC_TRUE);
} }
#ifdef NEVER
check_result(result, "dns_message_firstname");
#endif
do { do {
dns_name_t *name = NULL; dns_name_t *name = NULL;
dns_message_currentname(msg, DNS_SECTION_ANSWER, dns_message_currentname(msg, DNS_SECTION_ANSWER,
@@ -1773,6 +1844,10 @@ check_for_more_data(dig_query_t *query, dns_message_t *msg,
return (ISC_FALSE); return (ISC_FALSE);
} }
/*
* Event handler for recv complete. Perform whatever actions are necessary,
* based on the specifics of the user's request.
*/
static void static void
recv_done(isc_task_t *task, isc_event_t *event) { recv_done(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = NULL; isc_socketevent_t *sevent = NULL;
@@ -2040,6 +2115,11 @@ recv_done(isc_task_t *task, isc_event_t *event) {
isc_result_totext(sevent->result)); isc_result_totext(sevent->result));
} }
/*
* Turn a name into an address, using system-supplied routines. This is
* used in looking up server names, etc... and needs to use system-supplied
* routines, since they may be using a non-DNS system for these lookups.
*/
void void
get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) { get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
struct in_addr in4; struct in_addr in4;
@@ -2081,6 +2161,9 @@ get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
} }
} }
/*
* Initiate a TCP lookup, starting all of the queries running
*/
static void static void
do_lookup_tcp(dig_lookup_t *lookup) { do_lookup_tcp(dig_lookup_t *lookup) {
dig_query_t *query; dig_query_t *query;
@@ -2133,6 +2216,9 @@ do_lookup_tcp(dig_lookup_t *lookup) {
} }
} }
/*
* Initiate a UDP lookup, starting all of the queries running
*/
static void static void
do_lookup_udp(dig_lookup_t *lookup) { do_lookup_udp(dig_lookup_t *lookup) {
dig_query_t *query; dig_query_t *query;
@@ -2170,6 +2256,9 @@ do_lookup_udp(dig_lookup_t *lookup) {
send_udp(lookup, ISC_TRUE); send_udp(lookup, ISC_TRUE);
} }
/*
* Initiate either a TCP or UDP lookup
*/
void void
do_lookup(dig_lookup_t *lookup) { do_lookup(dig_lookup_t *lookup) {
@@ -2182,6 +2271,9 @@ do_lookup(dig_lookup_t *lookup) {
do_lookup_udp(lookup); do_lookup_udp(lookup);
} }
/*
* Start everything in action upon task startup.
*/
void void
onrun_callback(isc_task_t *task, isc_event_t *event) { onrun_callback(isc_task_t *task, isc_event_t *event) {
UNUSED(task); UNUSED(task);
@@ -2192,7 +2284,8 @@ onrun_callback(isc_task_t *task, isc_event_t *event) {
} }
/* /*
* This will be used in the SIGINT handler, and perhaps other places. * Make everything on the lookup queue go away. Mainly used by the
* SIGINT handler.
*/ */
void void
cancel_all(void) { cancel_all(void) {
@@ -2231,14 +2324,30 @@ cancel_all(void) {
UNLOCK_LOOKUP; UNLOCK_LOOKUP;
} }
static void /*
xfree_lists(void) { * Destroy all of the libs we are using, and get everything ready for a
* clean shutdown.
*/
void
destroy_libs(void) {
void *ptr; void *ptr;
dig_server_t *s; dig_server_t *s;
dig_searchlist_t *o; dig_searchlist_t *o;
debug("xfree_lists()"); debug("destroy_libs()");
if (global_task != NULL) {
debug("freeing task");
isc_task_detach(&global_task);
}
/*
* The taskmgr_destroy() call blocks until all events are cleared
* from the task.
*/
if (taskmgr != NULL) {
debug("Freeing taskmgr");
isc_taskmgr_destroy(&taskmgr);
}
LOCK_LOOKUP;
REQUIRE(sockcount == 0); REQUIRE(sockcount == 0);
REQUIRE(recvcount == 0); REQUIRE(recvcount == 0);
REQUIRE(sendcount == 0); REQUIRE(sendcount == 0);
@@ -2296,21 +2405,7 @@ xfree_lists(void) {
debug("detach from entropy"); debug("detach from entropy");
isc_entropy_detach(&entp); isc_entropy_detach(&entp);
} }
}
void
destroy_libs(void) {
debug("destroy_libs()");
if (global_task != NULL) {
debug("freeing task");
isc_task_detach(&global_task);
}
if (taskmgr != NULL) {
debug("Freeing taskmgr");
isc_taskmgr_destroy(&taskmgr);
}
LOCK_LOOKUP;
xfree_lists();
isc_mutex_destroy(&lookup_lock); isc_mutex_destroy(&lookup_lock);
if (isc_mem_debugging) if (isc_mem_debugging)
isc_mem_stats(mctx, stderr); isc_mem_stats(mctx, stderr);