From 6c7a2db63cb10cda9ce3289f38c5ee55f63bba10 Mon Sep 17 00:00:00 2001 From: Michael Sawyer Date: Sat, 6 May 2000 01:16:07 +0000 Subject: [PATCH] Add +trace option, change some of the behavior of other options. --- bin/dig/dig.c | 129 ++++++++++---- bin/dig/dighost.c | 349 ++++++++++++++++++++++++-------------- bin/dig/host.c | 33 ++-- bin/dig/include/dig/dig.h | 16 +- 4 files changed, 346 insertions(+), 181 deletions(-) diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 5b205d8aa8..a4e7eed100 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -15,8 +15,6 @@ * SOFTWARE. */ - - #include #include @@ -76,16 +74,13 @@ extern isc_buffer_t rootbuf; extern int sendcount; extern int ndots; extern int tries; +extern int lookup_counter; extern char fixeddomain[MXNAME]; #ifdef TWIDDLE extern isc_boolean_t twiddle; #endif isc_boolean_t short_form = ISC_FALSE; -isc_boolean_t ns_search_only = ISC_FALSE; -isc_boolean_t comments = ISC_TRUE, section_question = ISC_TRUE, - section_answer = ISC_TRUE, section_authority = ISC_TRUE, - section_additional = ISC_TRUE, recurse = ISC_TRUE; static char *opcodetext[] = { @@ -191,7 +186,7 @@ check_next_lookup(dig_lookup_t *lookup) { debug ("Have %d retries left for %s\n", lookup->retries, lookup->textname); if ((next == NULL)&&((lookup->retries <= 1) - ||tcp_mode)) { + ||tcp_mode || !lookup->pending)) { debug("Shutting Down.", stderr); isc_app_shutdown(); return; @@ -201,10 +196,11 @@ check_next_lookup(dig_lookup_t *lookup) { setup_lookup(next); do_lookup_tcp(next); } else { - if (lookup->retries > 1) { + if ((lookup->retries > 1) && (lookup->pending)) { lookup->retries --; send_udp(lookup); } else { + ENSURE (next != NULL); setup_lookup(next); do_lookup_udp(next); } @@ -220,37 +216,59 @@ received(int bytes, int frmsize, char *frm, dig_query_t *query) { result = isc_time_now(&now); check_result (result, "isc_time_now"); - if (!short_form && query->lookup->comments) { + + if (query->lookup->comments) { diff = isc_time_microdiff(&now, &query->time_sent); printf(";; Query time: %ld msec\n", (long int)diff/1000); printf(";; Received %u bytes from %.*s\n", bytes, frmsize, frm); time (&tnow); printf(";; When: %s\n", ctime(&tnow)); + } else if (query->lookup->identify && !short_form) { + diff = isc_time_microdiff(&now, &query->time_sent); + printf(";; Received %u bytes from %.*s in %d ms\n", + bytes, frmsize, frm, (int)diff/1000); } } void trying(int frmsize, char *frm, dig_lookup_t *lookup) { - if (lookup->comments) + if (lookup->comments && !short_form) printf ("; Trying %.*s\n", frmsize, frm); } static void say_message(dns_rdata_t *rdata, dig_query_t *query) { - isc_buffer_t *b=NULL; - isc_region_t r; + isc_buffer_t *b=NULL, *b2=NULL; + isc_region_t r, r2; isc_result_t result; + isc_uint64_t diff; + isc_time_t now; result = isc_buffer_allocate(mctx, &b, BUFSIZE); check_result (result, "isc_buffer_allocate"); result = dns_rdata_totext(rdata, NULL, b); check_result(result, "dns_rdata_totext"); isc_buffer_usedregion(b, &r); - printf ( "%.*s", (int)r.length, (char *)r.base); + if (!query->lookup->trace && !query->lookup->ns_search_only) + printf ( "%.*s", (int)r.length, (char *)r.base); + else { + result = isc_buffer_allocate(mctx, &b2, BUFSIZE); + check_result (result, "isc_buffer_allocate"); + result = dns_rdatatype_totext(rdata->type, b2); + check_result(result, "dns_rdatatype_totext"); + isc_buffer_usedregion(b2, &r2); + printf ( "%.*s %.*s",(int)r2.length, (char *)r2.base, + (int)r.length, (char *)r.base); + isc_buffer_free (&b2); + } if (query->lookup->identify) { - printf (" on server %s", query->servname); + result = isc_time_now(&now); + check_result (result, "isc_time_now"); + diff = isc_time_microdiff(&now, &query->time_sent); + printf (" from server %s in %d ms", query->servname, + (int)diff/1000); } printf ("\n"); isc_buffer_free(&b); @@ -276,7 +294,7 @@ printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name, else no_rdata = ISC_FALSE; - if (headers && query->lookup->comments) + if (headers && query->lookup->comments && !short_form) printf(";; %s SECTION:\n", section_name); dns_name_init(&empty_name, NULL); @@ -376,7 +394,7 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { result = ISC_R_SUCCESS; if (headers) { - if (query->lookup->comments) { + if (query->lookup->comments && !short_form) { printf(";; ->>HEADER<<- opcode: %s, status: %s, " "id: %u\n", opcodetext[msg->opcode], rcodetext[msg->rcode], @@ -439,16 +457,19 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]) && query->lookup->section_answer ) { - if (headers && query->lookup->comments) + if (headers && query->lookup->comments && !short_form) printf("\n"); result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", headers, query); if (result != ISC_R_SUCCESS) return (result); } - if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && - headers && query->lookup->section_authority) { - if (headers && query->lookup->comments) + if ((! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && + headers && query->lookup->section_authority) || + ( ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]) && + headers && query->lookup->section_answer && + query->lookup->trace )) { + if (headers && query->lookup->comments && !short_form) printf("\n"); result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", ISC_TRUE, query); @@ -457,7 +478,7 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && headers && query->lookup->section_additional) { - if (headers && query->lookup->comments) + if (headers && query->lookup->comments && !short_form) printf("\n"); result = printsection(msg, DNS_SECTION_ADDITIONAL, "ADDITIONAL", ISC_TRUE, query); @@ -465,14 +486,14 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { return (result); } if ((tsig != NULL) && headers && query->lookup->section_additional) { - if (headers && query->lookup->comments) + if (headers && query->lookup->comments && !short_form) printf("\n"); result = printrdata(msg, tsig, tsigname, "PSEUDOSECTION TSIG", ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); } - if (headers && query->lookup->comments) + if (headers && query->lookup->comments && !short_form) printf("\n"); return (result); @@ -521,7 +542,12 @@ reorder_args(int argc, char *argv[]) { */ void parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { - isc_boolean_t have_host = ISC_FALSE, identify = ISC_FALSE; + isc_boolean_t have_host = ISC_FALSE, identify = ISC_FALSE, + trace = ISC_FALSE, ns_search_only = ISC_FALSE, + forcecomment = ISC_FALSE, + comments = ISC_TRUE, section_question = ISC_TRUE, + section_answer = ISC_TRUE, section_authority = ISC_TRUE, + section_additional = ISC_TRUE, recurse = ISC_TRUE; dig_server_t *srv = NULL; dig_lookup_t *lookup = NULL; char *batchname = NULL; @@ -539,7 +565,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { if (srv == NULL) fatal("Memory allocation failure."); strncpy(srv->servername, &argv[0][1], MXNAME-1); - if ((is_batchfile) || (!have_host)) { + if (is_batchfile && have_host) { if (!lookup->use_my_server_list) { ISC_LIST_INIT (lookup-> my_server_list); @@ -589,23 +615,35 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { ns_search_only = ISC_TRUE; recurse = ISC_FALSE; identify = ISC_TRUE; + short_form = ISC_TRUE; + identify = ISC_TRUE; + if (!forcecomment) + comments = ISC_FALSE; + section_additional = ISC_FALSE; + section_authority = ISC_FALSE; + section_question = ISC_FALSE; } else if (strncmp(argv[0], "+nons", 6) == 0) { ns_search_only = ISC_FALSE; } else if (strncmp(argv[0], "+tr", 3) == 0) { trace = ISC_TRUE; - ns_search_only = ISC_TRUE; recurse = ISC_FALSE; + identify = ISC_TRUE; + if (!forcecomment) + comments = ISC_FALSE; + section_additional = ISC_FALSE; + section_authority = ISC_FALSE; + section_question = ISC_FALSE; + show_details = ISC_TRUE; } else if (strncmp(argv[0], "+notr", 6) == 0) { trace = ISC_FALSE; } else if (strncmp(argv[0], "+det", 4) == 0) { show_details = ISC_TRUE; - short_form = ISC_FALSE; } else if (strncmp(argv[0], "+nodet", 6) == 0) { show_details = ISC_FALSE; } else if (strncmp(argv[0], "+sho", 4) == 0) { short_form = ISC_TRUE; - show_details = ISC_FALSE; - comments = ISC_FALSE; + if (!forcecomment) + comments = ISC_FALSE; section_additional = ISC_FALSE; section_authority = ISC_FALSE; section_question = ISC_FALSE; @@ -617,8 +655,10 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { identify = ISC_FALSE; } else if (strncmp(argv[0], "+com", 4) == 0) { comments = ISC_TRUE; + forcecomment = ISC_TRUE; } else if (strncmp(argv[0], "+nocom", 6) == 0) { comments = ISC_FALSE; + forcecomment = ISC_FALSE; } else if (strncmp(argv[0], "+que", 4) == 0) { section_question = ISC_TRUE; } else if (strncmp(argv[0], "+noque", 6) == 0) { @@ -635,6 +675,19 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { section_authority = ISC_TRUE; } else if (strncmp(argv[0], "+noaut", 6) == 0) { section_authority = ISC_FALSE; + } else if (strncmp(argv[0], "+all", 4) == 0) { + section_question = ISC_TRUE; + section_authority = ISC_TRUE; + section_answer = ISC_TRUE; + section_additional = ISC_TRUE; + comments = ISC_TRUE; + } else if (strncmp(argv[0], "+noall", 6) == 0) { + section_question = ISC_FALSE; + section_authority = ISC_FALSE; + section_answer = ISC_FALSE; + section_additional = ISC_FALSE; + comments = ISC_FALSE; + #ifdef TWIDDLE } else if (strncmp(argv[0], "+twiddle", 6) == 0) { twiddle = ISC_TRUE; @@ -687,6 +740,9 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { &adrs[2], &adrs[3]); if (n == 0) show_usage(); + lookup_counter++; + if (lookup_counter > LOOKUP_LIMIT) + fatal ("Too many lookups."); lookup = isc_mem_allocate(mctx, sizeof(struct dig_lookup)); if (lookup == NULL) @@ -711,11 +767,14 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->xfr_q = NULL; lookup->origin = NULL; lookup->use_my_server_list = ISC_FALSE; + lookup->trace = (trace || ns_search_only); + lookup->trace_root = trace; lookup->ns_search_only = ns_search_only; lookup->doing_xfr = ISC_FALSE; lookup->identify = identify; lookup->recurse = recurse; lookup->retries = tries; + lookup->nsfound = 0; lookup->comments = comments; lookup->section_question = section_question; lookup->section_answer = section_answer; @@ -740,6 +799,9 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { continue; } } + lookup_counter++; + if (lookup_counter > LOOKUP_LIMIT) + fatal ("Too many lookups."); lookup = isc_mem_allocate(mctx, sizeof(struct dig_lookup)); if (lookup == NULL) @@ -758,10 +820,13 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->origin = NULL; lookup->use_my_server_list = ISC_FALSE; lookup->doing_xfr = ISC_FALSE; + lookup->trace = (trace || ns_search_only); + lookup->trace_root = trace; lookup->ns_search_only = ns_search_only; lookup->identify = identify; lookup->recurse = recurse; lookup->retries = tries; + lookup->nsfound = 0; lookup->comments = comments; lookup->section_question = section_question; lookup->section_answer = section_answer; @@ -797,6 +862,9 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { } } if (lookup_list.head == NULL) { + lookup_counter++; + if (lookup_counter > LOOKUP_LIMIT) + fatal ("Too many lookups."); lookup = isc_mem_allocate(mctx, sizeof(struct dig_lookup)); if (lookup == NULL) fatal("Memory allocation failure."); @@ -812,10 +880,13 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->origin = NULL; lookup->use_my_server_list = ISC_FALSE; lookup->doing_xfr = ISC_FALSE; + lookup->trace = (trace || ns_search_only); + lookup->trace_root = trace; lookup->ns_search_only = ns_search_only; lookup->identify = identify; lookup->recurse = recurse; lookup->retries = tries; + lookup->nsfound = 0; lookup->comments = comments; lookup->section_question = section_question; lookup->section_answer = section_answer; diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index d01b2635fe..3dae94a223 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -60,8 +60,7 @@ ISC_LIST(dig_server_t) server_list; ISC_LIST(dig_searchlist_t) search_list; isc_boolean_t tcp_mode = ISC_FALSE, have_ipv6 = ISC_FALSE, - free_now = ISC_FALSE, show_details = ISC_FALSE, usesearch=ISC_TRUE, - trace = ISC_FALSE; + free_now = ISC_FALSE, show_details = ISC_FALSE, usesearch=ISC_TRUE; #ifdef TWIDDLE isc_boolean_t twiddle = ISC_FALSE; #endif @@ -78,6 +77,7 @@ isc_buffer_t rootbuf; int sendcount = 0; int ndots = -1; int tries = 3; +int lookup_counter = 0; char fixeddomain[MXNAME]=""; static void @@ -167,8 +167,8 @@ isclass(char *text) { * initialized. This list will have to be manually kept in * sync with what the libs support. */ - const char *classlist[] = {"in", "hs", "any"}; - const int numclasses = 3; + const char *classlist[] = {"in", "hs"}; + const int numclasses = 2; int i; for (i = 0; i < numclasses; i++) @@ -193,8 +193,8 @@ istype(char *text) { "gpos", "aaaa", "loc", "nxt", "srv", "naptr", "kx", "cert", "a6", "dname", "opt", "unspec", - "tkey", "tsig", "axfr"}; - const int numtypes = 41; + "tkey", "tsig", "axfr", "any"}; + const int numtypes = 42; int i; for (i = 0; i < numtypes; i++) { @@ -245,7 +245,8 @@ setup_system(void) { if (fixeddomain[0]!=0) { search = isc_mem_allocate( mctx, sizeof(struct dig_server)); if (search == NULL) - fatal("Memory allocation failure."); + fatal("Memory allocation failure in %s:%d", + __FILE__, __LINE__); strncpy(search->origin, fixeddomain, MXNAME - 1); ISC_LIST_PREPEND(search_list, search, link); } @@ -268,7 +269,10 @@ setup_system(void) { if (srv == NULL) fatal("Memory " "allocation " - "failure."); + "failure in " + "%s:%d", + __FILE__, + __LINE__); strncpy((char *)srv-> servername, ptr, @@ -300,7 +304,9 @@ setup_system(void) { if (search == NULL) fatal("Memory " "allocation " - "failure."); + "failure in %s:" + "%d", __FILE__, + __LINE__); strncpy(search-> origin, ptr, @@ -320,7 +326,9 @@ setup_system(void) { if (search == NULL) fatal("Memory " "allocation " - "failure."); + "failure in %s:" + "%d", __FILE__, + __LINE__); strncpy(search-> origin, ptr, @@ -406,7 +414,8 @@ add_type(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, } 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) { dig_lookup_t *lookup = NULL; dig_server_t *srv = NULL; dns_rdataset_t *rdataset = NULL; @@ -415,13 +424,17 @@ followup_lookup(dns_message_t *msg, dig_query_t *query) { isc_result_t result, loopresult; isc_buffer_t *b = NULL; isc_region_t r; + isc_boolean_t success = ISC_FALSE; int len; debug ("followup_lookup()"); - result = dns_message_firstname (msg, DNS_SECTION_ANSWER); + result = dns_message_firstname (msg,section); if (result != ISC_R_SUCCESS) { debug ("Firstname returned %s", isc_result_totext(result)); + if ((section == DNS_SECTION_ANSWER) && + query->lookup->trace) + followup_lookup (msg, query, DNS_SECTION_AUTHORITY); return; } @@ -429,15 +442,20 @@ followup_lookup(dns_message_t *msg, dig_query_t *query) { for (;;) { name = NULL; - dns_message_currentname(msg, DNS_SECTION_ANSWER, - &name); + dns_message_currentname(msg, section, &name); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { loopresult = dns_rdataset_first(rdataset); while (loopresult == ISC_R_SUCCESS) { dns_rdataset_current(rdataset, &rdata); - if (rdata.type == dns_rdatatype_ns) { + debug ("Got rdata with type %d", + rdata.type); + if ((rdata.type == dns_rdatatype_ns) && + (!query->lookup->trace_root || + (query->lookup->nsfound < ROOTNS))) + { + query->lookup->nsfound++; result = isc_buffer_allocate(mctx, &b, BUFSIZE); check_result (result, @@ -455,65 +473,114 @@ followup_lookup(dns_message_t *msg, dig_query_t *query) { debug ("Found NS %d %.*s", (int)r.length, (int)r.length, (char *)r.base); - lookup = isc_mem_allocate - (mctx, - sizeof(struct - dig_lookup)); - if (lookup == NULL) - fatal ("Memory " - "allocation " - "failure."); - lookup->pending = ISC_FALSE; - strncpy (lookup->textname, - query->lookup-> - textname, MXNAME); - strncpy (lookup->rttext, - query->lookup-> - rttext, 32); - strncpy (lookup->rctext, - query->lookup-> - rctext, 32); - lookup->namespace[0]=0; - lookup->sendspace[0]=0; - lookup->sendmsg=NULL; - lookup->name=NULL; - lookup->oname=NULL; - lookup->timer = NULL; - lookup->xfr_q = NULL; - lookup->origin = NULL; - lookup->doing_xfr = ISC_FALSE; - lookup->identify = ISC_TRUE; - lookup->recurse = query->lookup-> - recurse; - lookup->ns_search_only = - ISC_FALSE; - lookup->use_my_server_list = - ISC_TRUE; - lookup->retries = tries; - lookup->comments = - query->lookup->comments; - lookup->section_question = - query->lookup-> - section_question; - lookup->section_answer = - query->lookup-> - section_answer; - lookup->section_authority = - query->lookup-> - section_authority; - lookup->section_additional = - query->lookup-> - section_additional; - ISC_LIST_INIT(lookup-> - my_server_list); - ISC_LIST_INIT(lookup->q); + if (!success) { + success = ISC_TRUE; + lookup_counter++; + if (lookup_counter > + LOOKUP_LIMIT) + fatal ("Too many " + "lookups."); + lookup = isc_mem_allocate + (mctx, + sizeof(struct + dig_lookup)); + if (lookup == NULL) + fatal ("Memory " + "allocation " + "failure in %s:" + "%d", __FILE__, + __LINE__); + lookup->pending = ISC_FALSE; + strncpy (lookup->textname, + query->lookup-> + textname, MXNAME); + strncpy (lookup->rttext, + query->lookup-> + rttext, 32); + strncpy (lookup->rctext, + query->lookup-> + rctext, 32); + lookup->namespace[0]=0; + lookup->sendspace[0]=0; + lookup->sendmsg=NULL; + lookup->name=NULL; + lookup->oname=NULL; + lookup->timer = NULL; + lookup->xfr_q = NULL; + lookup->origin = NULL; + lookup->doing_xfr = ISC_FALSE; + lookup->identify = + query->lookup->identify; + lookup->recurse = + query->lookup-> + recurse; + lookup->ns_search_only = + query->lookup-> + ns_search_only; + lookup->use_my_server_list = + ISC_TRUE; + if (section == + DNS_SECTION_ANSWER) + lookup->trace = + ISC_FALSE; + else + lookup->trace = + query-> + lookup->trace; + lookup->trace_root = ISC_FALSE; + lookup->retries = tries; + lookup->nsfound = 0; + lookup->comments = + query->lookup-> + comments; + lookup->section_question = + query->lookup-> + section_question; + lookup->section_answer = + query->lookup-> + section_answer; + lookup->section_authority = + query->lookup-> + section_authority; + lookup->section_additional = + query->lookup-> + section_additional; + ISC_LIST_INIT(lookup-> + my_server_list); + ISC_LIST_INIT(lookup->q); + debug ("Before insertion, " + "init@%lx " + "-> %lx, new@%lx " + "-> %lx", + (long int)query->lookup, + (long int)query-> + lookup->link.next, + (long int)lookup, + (long int)lookup-> + link.next); + ISC_LIST_INSERTAFTER( + lookup_list, + query->lookup, + lookup, + link); + debug ("After insertion, " + "init -> " + "%lx, new = %lx, " + "new -> %lx", + (long int)query-> + lookup->link.next, + (long int)lookup, + (long int)lookup-> + link.next); + } srv = isc_mem_allocate (mctx, sizeof( struct dig_server)); if (srv == NULL) fatal("Memory allocation " - "failure."); + "failure in %s:%d", + __FILE__, __LINE__); strncpy(srv->servername, (char *)r.base, len); srv->servername[len]=0; @@ -522,30 +589,16 @@ followup_lookup(dns_message_t *msg, dig_query_t *query) { srv, link); isc_buffer_free (&b); } - debug ("Before insertion, init@%lx " - "-> %lx, new@%lx " - "-> %lx", (long int)query->lookup, - (long int)query->lookup->link.next, - (long int)lookup, (long int)lookup-> - link.next); - ISC_LIST_INSERTAFTER(lookup_list, query-> - lookup, lookup, - link); - debug ("After insertion, init -> " - "%lx, new = %lx, " - "new -> %lx", (long int)query-> - lookup->link.next, - (long int)lookup, (long int)lookup-> - link.next); loopresult = dns_rdataset_next(rdataset); } } - result = dns_message_nextname (msg, DNS_SECTION_ANSWER); - if (result != ISC_R_SUCCESS) - break; + result = dns_message_nextname (msg, section); + if (result != ISC_R_SUCCESS) + break; } - if (lookup == NULL) - return; /* We didn't get a NS. Just give up. */ + if ((lookup == NULL) && (section == DNS_SECTION_ANSWER) && + query->lookup->trace) + followup_lookup(msg, query, DNS_SECTION_AUTHORITY); } static void @@ -564,10 +617,14 @@ next_origin(dns_message_t *msg, dig_query_t *query) { debug ("Made it to the root whith nowhere to go."); return; } + lookup_counter++; + if (lookup_counter > LOOKUP_LIMIT) + fatal ("Too many lookups."); lookup = isc_mem_allocate (mctx, sizeof(struct dig_lookup)); if (lookup == NULL) - fatal ("Memory allocation failure."); + fatal ("Memory allocation failure in %s:%d", + __FILE__, __LINE__); lookup->pending = ISC_FALSE; strncpy (lookup->textname, query->lookup-> textname, MXNAME); strncpy (lookup->rttext, query->lookup-> rttext, 32); @@ -580,12 +637,15 @@ next_origin(dns_message_t *msg, dig_query_t *query) { lookup->timer = NULL; lookup->xfr_q = NULL; lookup->doing_xfr = ISC_FALSE; + lookup->trace = query->lookup->trace; + lookup->trace_root = query->lookup->trace_root; lookup->identify = query->lookup->identify; lookup->recurse = query->lookup->recurse; lookup->ns_search_only = query->lookup->ns_search_only; lookup->use_my_server_list = query->lookup->use_my_server_list; lookup->origin = ISC_LIST_NEXT(query->lookup->origin, link); lookup->retries = tries; + lookup->nsfound = 0; lookup->comments = query->lookup->comments; lookup->section_question = query->lookup->section_question; lookup->section_answer = query->lookup->section_answer; @@ -600,7 +660,7 @@ next_origin(dns_message_t *msg, dig_query_t *query) { srv = isc_mem_allocate (mctx, sizeof(struct dig_server)); if (srv == NULL) - fatal("Memory allocation failure."); + fatal("Memory allocation failure in %s:%d", __FILE__, __LINE__); strncpy(srv->servername, s->servername, MXNAME); ISC_LIST_ENQUEUE(lookup->my_server_list, srv, link); @@ -680,11 +740,20 @@ setup_lookup(dig_lookup_t *lookup) { lookup->origin->origin, dns_result_totext(result)); } - len=strlen(lookup->textname); - isc_buffer_init(&b, lookup->textname, len); - isc_buffer_add(&b, len); - result = dns_name_fromtext(lookup->name, &b, lookup->oname, - ISC_FALSE, &lookup->namebuf); + if (!lookup->trace_root) { + len=strlen(lookup->textname); + isc_buffer_init(&b, lookup->textname, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(lookup->name, &b, + lookup->oname, ISC_FALSE, + &lookup->namebuf); + } else { + isc_buffer_init(&b, ". ", 1); + isc_buffer_add(&b, 1); + result = dns_name_fromtext(lookup->name, &b, + lookup->oname, ISC_FALSE, + &lookup->namebuf); + } if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); @@ -696,11 +765,22 @@ setup_lookup(dig_lookup_t *lookup) { dns_message_puttempname(lookup->sendmsg, &lookup->oname); } else { debug ("Using root origin."); - len = strlen (lookup->textname); - isc_buffer_init(&b, lookup->textname, len); - isc_buffer_add(&b, len); - result = dns_name_fromtext(lookup->name, &b, dns_rootname, - ISC_FALSE, &lookup->namebuf); + if (!lookup->trace_root) { + len = strlen (lookup->textname); + isc_buffer_init(&b, lookup->textname, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(lookup->name, &b, + dns_rootname, + ISC_FALSE, + &lookup->namebuf); + } else { + isc_buffer_init(&b, ". ", 1); + isc_buffer_add(&b, 1); + result = dns_name_fromtext(lookup->name, &b, + dns_rootname, + ISC_FALSE, + &lookup->namebuf); + } if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); @@ -731,7 +811,9 @@ setup_lookup(dig_lookup_t *lookup) { lookup->sendmsg->id = id++; lookup->sendmsg->opcode = dns_opcode_query; - if (lookup->recurse) { + /* If this is a trace request, completely disallow recursion, since + * it's meaningless for traces */ + if (lookup->recurse && !lookup->trace) { debug ("Recursive query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; } @@ -740,12 +822,12 @@ setup_lookup(dig_lookup_t *lookup) { DNS_SECTION_QUESTION); - if (!lookup->ns_search_only) { + if (lookup->trace_root) { + tr.base="SOA"; + tr.length=3; + } else { tr.base=lookup->rttext; tr.length=strlen(lookup->rttext); - } else { - tr.base="NS"; - tr.length=2; } result = dns_rdatatype_fromtext(&rdtype, &tr); check_result(result, "dns_rdatatype_fromtext"); @@ -756,12 +838,12 @@ setup_lookup(dig_lookup_t *lookup) { */ tcp_mode = ISC_TRUE; } - if (!lookup->ns_search_only) { - tr.base=lookup->rctext; - tr.length=strlen(lookup->rctext); - } else { + if (lookup->trace_root) { tr.base="IN"; tr.length=2; + } else { + tr.base=lookup->rctext; + tr.length=strlen(lookup->rctext); } result = dns_rdataclass_fromtext(&rdclass, &tr); check_result(result, "dns_rdataclass_fromtext"); @@ -788,7 +870,7 @@ setup_lookup(dig_lookup_t *lookup) { serv = ISC_LIST_NEXT(serv, link)) { query = isc_mem_allocate(mctx, sizeof(dig_query_t)); if (query == NULL) - fatal("Memory allocation failure."); + fatal("Memory allocation failure in %s:%d", __FILE__, __LINE__); query->lookup = lookup; query->working = ISC_FALSE; query->waiting_connect = ISC_FALSE; @@ -1129,7 +1211,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { sevent = (isc_socketevent_t *)event; query = event->ev_arg; - if (!query->lookup->pending) { + if (!query->lookup->pending && !query->lookup->ns_search_only) { debug("No longer pending. Got %s", isc_result_totext(sevent->result)); query->working = ISC_FALSE; @@ -1153,15 +1235,24 @@ recv_done(isc_task_t *task, isc_event_t *event) { if (query->lookup->xfr_q == NULL) query->lookup->xfr_q = query; if (query->lookup->xfr_q == query) { - if (query->lookup->ns_search_only) { - if (show_details) { - printmessage(query, msg, ISC_TRUE); + if (query->lookup->trace) { + if (show_details || ((dns_message_firstname + (msg, DNS_SECTION_ANSWER)== + ISC_R_SUCCESS) && + !query->lookup->trace_root)) { + printmessage(query, msg, ISC_TRUE); } if ((msg->rcode != 0) && (query->lookup->origin != NULL)) { next_origin(msg, query); - } else - followup_lookup(msg, query); + } else { + result = dns_message_firstname + (msg,DNS_SECTION_ANSWER); + if ((result != ISC_R_SUCCESS) || + query->lookup->trace_root) + followup_lookup(msg, query, + DNS_SECTION_AUTHORITY); + } } else if ((msg->rcode != 0) && (query->lookup->origin != NULL)) { next_origin(msg, query); @@ -1175,7 +1266,13 @@ recv_done(isc_task_t *task, isc_event_t *event) { else printmessage(query, msg, ISC_TRUE); } + } else if (( dns_message_firstname(msg, DNS_SECTION_ANSWER) + == ISC_R_SUCCESS) && + query->lookup->ns_search_only && + !query->lookup->trace_root ) { + printmessage (query, msg, ISC_TRUE); } + #ifdef DEBUG if (query->lookup->pending) debug("Still pending."); @@ -1201,8 +1298,6 @@ recv_done(isc_task_t *task, isc_event_t *event) { else { if (msg_contains_soa(msg, query)) { isc_buffer_init(&ab, abspace, MXNAME); - check_result(result, - "isc_buffer_init"); result = isc_sockaddr_totext(&sevent-> address, &ab); @@ -1227,7 +1322,6 @@ recv_done(isc_task_t *task, isc_event_t *event) { if ((msg->rcode == 0) || (query->lookup->origin == NULL)) { isc_buffer_init(&ab, abspace, MXNAME); - check_result(result, "isc_buffer_init"); result = isc_sockaddr_totext(&sevent->address, &ab); check_result(result, "isc_sockaddr_totext"); @@ -1236,9 +1330,11 @@ recv_done(isc_task_t *task, isc_event_t *event) { query); } query->working = ISC_FALSE; - cancel_lookup(query->lookup); - } - if (!query->lookup->pending) { + query->lookup->pending = ISC_FALSE; + if (!query->lookup->ns_search_only || + query->lookup->trace_root ) { + cancel_lookup(query->lookup); + } check_next_lookup(query->lookup); } dns_message_destroy(&msg); @@ -1359,10 +1455,8 @@ free_lists(void) { l = ISC_LIST_HEAD(lookup_list); while (l != NULL) { - debug ("Freeing the lookup of %s", l->textname); q = ISC_LIST_HEAD(l->q); while (q != NULL) { - debug ("Freeing the query of %s", q->servname); if (q->sock != NULL) { isc_socket_cancel(q->sock, NULL, ISC_SOCKCANCEL_ALL); @@ -1383,8 +1477,6 @@ free_lists(void) { if (l->use_my_server_list) { s = ISC_LIST_HEAD(l->my_server_list); while (s != NULL) { - debug ("Freeing lookup server %s", - s->servername); ptr = s; s = ISC_LIST_NEXT(s, link); isc_mem_free(mctx, ptr); @@ -1399,19 +1491,14 @@ free_lists(void) { l = ISC_LIST_NEXT(l, link); isc_mem_free(mctx, ptr); } - debug ("Starting to free things globally."); s = ISC_LIST_HEAD(server_list); while (s != NULL) { - debug ("Freeing global server list entry %s", - s->servername); ptr = s; s = ISC_LIST_NEXT(s, link); isc_mem_free(mctx, ptr); } o = ISC_LIST_HEAD(search_list); while (o != NULL) { - debug ("Freeing origin list entry %s", - o->origin); ptr = o; o = ISC_LIST_NEXT(o, link); isc_mem_free(mctx, ptr); diff --git a/bin/dig/host.c b/bin/dig/host.c index 96f7c94221..f106127943 100644 --- a/bin/dig/host.c +++ b/bin/dig/host.c @@ -76,6 +76,7 @@ extern isc_buffer_t rootbuf; extern int sendcount; extern int ndots; extern int tries; +extern int lookup_counter; isc_boolean_t short_form=ISC_TRUE, filter=ISC_FALSE, @@ -165,17 +166,17 @@ static char *rtypetext[] = { "has optional information"}; /* 41 */ void -check_next_lookup (dig_lookup_t *lookup) { +check_next_lookup(dig_lookup_t *lookup) { dig_lookup_t *next; dig_query_t *query; isc_boolean_t still_working=ISC_FALSE; - debug("check_next_lookup()"); + debug("In check_next_lookup", stderr); for (query = ISC_LIST_HEAD(lookup->q); query != NULL; query = ISC_LIST_NEXT(query, link)) { if (query->working) { - debug("Still have a worker."); + debug("Still have a worker.", stderr); still_working=ISC_TRUE; } } @@ -186,7 +187,7 @@ check_next_lookup (dig_lookup_t *lookup) { debug ("Have %d retries left for %s\n", lookup->retries, lookup->textname); if ((next == NULL)&&((lookup->retries <= 1) - ||tcp_mode)) { + ||tcp_mode || !lookup->pending)) { debug("Shutting Down.", stderr); isc_app_shutdown(); return; @@ -196,29 +197,15 @@ check_next_lookup (dig_lookup_t *lookup) { setup_lookup(next); do_lookup_tcp(next); } else { - if (lookup->retries > 1) { + if ((lookup->retries > 1) && (lookup->pending)) { lookup->retries --; send_udp(lookup); } else { + ENSURE (next != NULL); setup_lookup(next); do_lookup_udp(next); } } - -#ifdef NEVER - next = ISC_LIST_NEXT (lookup, link); - if (next == NULL) { - debug ("Shutting Down."); - isc_app_shutdown(); - return; - } - - setup_lookup(next); - if (tcp_mode) - do_lookup_tcp(next); - else - do_lookup_udp(next); -#endif } static void @@ -630,6 +617,9 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { if (queryclass[0] == 0) strcpy (queryclass, "in"); + lookup_counter++; + if (lookup_counter > LOOKUP_LIMIT) + fatal ("Too many lookups."); lookup = isc_mem_allocate (mctx, sizeof(struct dig_lookup)); if (lookup == NULL) @@ -652,6 +642,9 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->ns_search_only = showallsoa; lookup->use_my_server_list = ISC_FALSE; lookup->retries = tries; + lookup->nsfound = 0; + lookup->trace = showallsoa; + lookup->trace_root = ISC_FALSE; ISC_LIST_INIT(lookup->q); ISC_LIST_APPEND(lookup_list, lookup, link); lookup->origin = NULL; diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 30506c6acf..42f5f66498 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -35,6 +35,17 @@ #define BUFSIZE 512 #define COMMSIZE 65536 #define RESOLVCONF "/etc/resolv.conf" +#define LOOKUP_LIMIT 64 +/* Lookup_limit is just a limiter, keeping too many lookups from being + * created. It's job is mainly to prevent the program from running away + * in a tight loop of constant lookups. It's value is arbitrary. + */ +#define ROOTNS 1 +/* Set the number of root servers to ask for information when running in + * trace mode. + * XXXMWS -- trace mode is currently semi-broken, and this number *MUST* + * be 1. + */ ISC_LANG_BEGINDECLS @@ -50,7 +61,9 @@ struct dig_lookup { ns_search_only, use_my_server_list, identify, - recurse; + recurse, + trace, + trace_root; char textname[MXNAME]; /* Name we're going to be looking up */ char rttext[MXRD]; /* rdata type text */ char rctext[MXRD]; /* rdata class text */ @@ -71,6 +84,7 @@ struct dig_lookup { dig_searchlist_t *origin; dig_query_t *xfr_q; int retries; + int nsfound; isc_boolean_t comments, section_question, section_answer,