diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 68f0fb8d81..6b494a45c9 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -36,7 +36,7 @@ extern ISC_LIST(dig_lookup_t) lookup_list; extern ISC_LIST(dig_server_t) server_list; extern ISC_LIST(dig_searchlist_t) search_list; -extern isc_boolean_t tcp_mode, have_ipv6, show_details, +extern isc_boolean_t have_ipv6, show_details, usesearch, trace, qr; extern in_port_t port; extern unsigned int timeout; @@ -67,7 +67,7 @@ isc_boolean_t have_host = ISC_FALSE, identify = ISC_FALSE, comments = ISC_TRUE, section_question = ISC_TRUE, section_answer = ISC_TRUE, section_authority = ISC_TRUE, section_additional = ISC_TRUE, recurse = ISC_TRUE, - defname = ISC_TRUE, aaonly = ISC_FALSE; + defname = ISC_TRUE, aaonly = ISC_FALSE, tcpmode = ISC_FALSE; static char *opcodetext[] = { @@ -156,46 +156,8 @@ show_usage() { } void -check_next_lookup(dig_lookup_t *lookup) { - dig_lookup_t *next; - dig_query_t *query; - isc_boolean_t still_working=ISC_FALSE; - - 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.", stderr); - still_working=ISC_TRUE; - } - } - if (still_working) - return; - - next = ISC_LIST_NEXT(lookup, link); - debug ("Have %d retries left for %s\n", - lookup->retries, lookup->textname); - if ((next == NULL)&&((lookup->retries <= 1) - ||tcp_mode || !lookup->pending)) { - debug("Shutting Down.", stderr); - isc_app_shutdown(); - return; - } - - if (tcp_mode) { - setup_lookup(next); - do_lookup_tcp(next); - } else { - if ((lookup->retries > 1) && (lookup->pending)) { - lookup->retries --; - send_udp(lookup); - } else { - ENSURE (next != NULL); - setup_lookup(next); - do_lookup_udp(next); - } - } +dighost_shutdown(void) { + isc_app_shutdown(); } void @@ -564,7 +526,7 @@ reorder_args(int argc, char *argv[]) { * syntax of dig is quite a bit different from that which can be described * that routine. There is a portability issue here. */ -void +static void parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { dig_server_t *srv = NULL; dig_lookup_t *lookup = NULL; @@ -601,16 +563,16 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { } } else if ((strcmp(rv[0], "+vc") == 0) && (!is_batchfile)) { - tcp_mode = ISC_TRUE; + tcpmode = ISC_TRUE; } else if ((strcmp(rv[0], "+novc") == 0) && (!is_batchfile)) { - tcp_mode = ISC_FALSE; + tcpmode = ISC_FALSE; } else if ((strcmp(rv[0], "+tcp") == 0) && (!is_batchfile)) { - tcp_mode = ISC_TRUE; + tcpmode = ISC_TRUE; } else if ((strcmp(rv[0], "+notcp") == 0) && (!is_batchfile)) { - tcp_mode = ISC_FALSE; + tcpmode = ISC_FALSE; } else if (strncmp(rv[0], "+domain=", 8) == 0) { strncpy (fixeddomain, &rv[0][8], MXNAME); } else if (strncmp(rv[0], "+sea", 4) == 0) { @@ -844,6 +806,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->udpsize = bufsize; lookup->nsfound = 0; lookup->comments = comments; + lookup->tcp_mode = tcpmode; lookup->stats = stats; lookup->section_question = section_question; lookup->section_answer = section_answer; @@ -900,6 +863,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->udpsize = bufsize; lookup->nsfound = 0; lookup->comments = comments; + lookup->tcp_mode = tcpmode; lookup->stats = stats; lookup->section_question = section_question; lookup->section_answer = section_answer; @@ -966,6 +930,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->udpsize = bufsize; lookup->nsfound = 0; lookup->comments = comments; + lookup->tcp_mode = tcpmode; lookup->stats = stats; lookup->section_question = section_question; lookup->section_answer = section_answer; @@ -983,7 +948,6 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { int main(int argc, char **argv) { - dig_lookup_t *lookup = NULL; #ifdef TWIDDLE FILE *fp; int i, p; @@ -1009,12 +973,7 @@ main(int argc, char **argv) { setup_libs(); parse_args(ISC_FALSE, argc, argv); setup_system(); - lookup = ISC_LIST_HEAD(lookup_list); - setup_lookup(lookup); - if (tcp_mode) - do_lookup_tcp(lookup); - else - do_lookup_udp(lookup); + start_lookup(); isc_app_run(); free_lists(0); return (0); diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 332196a00b..4c8e2ee32a 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -52,7 +52,7 @@ ISC_LIST(dig_lookup_t) lookup_list; 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, +isc_boolean_t have_ipv6 = ISC_FALSE, free_now = ISC_FALSE, show_details = ISC_FALSE, usesearch=ISC_TRUE, qr = ISC_FALSE; #ifdef TWIDDLE @@ -74,6 +74,9 @@ int lookup_counter = 0; char fixeddomain[MXNAME]=""; int exitcode = 9; +static void +cancel_lookup(dig_lookup_t *lookup); + static int count_dots(char *string) { char *s; @@ -117,7 +120,7 @@ fatal(char *format, ...) { if (exitcode == 0) exitcode = 8; #ifdef NEVER - isc_app_shutdown(); + dighost_shutdown(); free_lists(exitcode); if (mctx != NULL) { #ifdef MEMDEBUG @@ -226,6 +229,88 @@ twiddlebuf(isc_buffer_t buf) { } #endif +dig_lookup_t +*requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { + dig_lookup_t *looknew; + dig_server_t *s, *srv; + + debug("requeue_lookup()"); + + lookup_counter++; + if (lookup_counter > LOOKUP_LIMIT) + fatal ("Too many lookups."); + looknew = isc_mem_allocate + (mctx, sizeof(struct dig_lookup)); + if (looknew == NULL) + fatal ("Memory allocation failure in %s:%d", + __FILE__, __LINE__); + looknew->pending = ISC_FALSE; + strncpy (looknew->textname, lookold-> textname, MXNAME); + strncpy (looknew->rttext, lookold-> rttext, 32); + strncpy (looknew->rctext, lookold-> rctext, 32); + looknew->namespace[0]=0; + looknew->sendspace[0]=0; + looknew->sendmsg=NULL; + looknew->name=NULL; + looknew->oname=NULL; + looknew->timer = NULL; + looknew->xfr_q = NULL; + looknew->doing_xfr = lookold->doing_xfr; + looknew->defname = lookold->defname; + looknew->trace = lookold->trace; + looknew->trace_root = lookold->trace_root; + looknew->identify = lookold->identify; + looknew->udpsize = lookold->udpsize; + looknew->recurse = lookold->recurse; + looknew->aaonly = lookold->aaonly; + looknew->ns_search_only = lookold->ns_search_only; + looknew->origin = NULL; + looknew->retries = tries; + looknew->nsfound = 0; + looknew->tcp_mode = lookold->tcp_mode; + looknew->comments = lookold->comments; + looknew->stats = lookold->stats; + looknew->section_question = lookold->section_question; + looknew->section_answer = lookold->section_answer; + looknew->section_authority = lookold->section_authority; + looknew->section_additional = lookold->section_additional; + ISC_LIST_INIT(looknew->my_server_list); + ISC_LIST_INIT(looknew->q); + + looknew->use_my_server_list = ISC_FALSE; + if (servers) { + looknew->use_my_server_list = lookold->use_my_server_list; + if (looknew->use_my_server_list) { + s = ISC_LIST_HEAD(lookold->my_server_list); + while (s != NULL) { + srv = isc_mem_allocate (mctx, sizeof(struct + dig_server)); + if (srv == NULL) + fatal("Memory allocation failure " + "in %s:%d", __FILE__, __LINE__); + strncpy(srv->servername, s->servername, + MXNAME); + ISC_LIST_ENQUEUE(looknew->my_server_list, srv, + link); + s = ISC_LIST_NEXT(s, link); + } + } + } + debug ("Before insertion, init@%ld " + "-> %ld, new@%ld " + "-> %ld", (long int)lookold, + (long int)lookold->link.next, + (long int)looknew, (long int)looknew-> + link.next); + ISC_LIST_INSERTAFTER(lookup_list, lookold, looknew, link); + debug ("After insertion, init -> " + "%ld, new = %ld, " + "new -> %ld", (long int)lookold, + (long int)looknew, (long int)looknew-> + link.next); + return (looknew); +} + void setup_system(void) { char rcinput[MXNAME]; @@ -247,12 +332,6 @@ setup_system(void) { } debug ("setup_system()"); - /* - * Warning: This is not particularly good randomness. We'll - * just use random() now for getting id values, but doing so - * does NOT insure that id's cann't be guessed. - */ - srandom (getpid() + (int)&setup_system); free_now = ISC_FALSE; get_servers = (server_list.head == NULL); @@ -371,6 +450,14 @@ setup_libs(void) { isc_buffer_t b; debug ("setup_libs()"); + + /* + * Warning: This is not particularly good randomness. We'll + * just use random() now for getting id values, but doing so + * does NOT insure that id's cann't be guessed. + */ + srandom (getpid() + (int)&setup_libs); + result = isc_app_start(); check_result(result, "isc_app_start"); @@ -443,6 +530,69 @@ add_type(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, ISC_LIST_APPEND(name->list, rdataset, link); } +static void +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(%lx)", (long int)lookup); + for (query = ISC_LIST_HEAD(lookup->q); + query != NULL; + query = ISC_LIST_NEXT(query, link)) { + if (query->working) { + debug("Still have a worker.", stderr); + still_working=ISC_TRUE; + } + } + if (still_working) + return; + + debug ("Have %d retries left for %s", + lookup->retries-1, lookup->textname); + debug ("Lookup %s pending", lookup->pending?"is":"is not"); + + next = ISC_LIST_NEXT(lookup, link); + + if (lookup->tcp_mode) { + if (next == NULL) { + debug("Shutting Down.", stderr); + dighost_shutdown(); + return; + } + if (next->sendmsg == NULL) { + debug ("Setting up for TCP"); + setup_lookup(next); + do_lookup(next); + } + } else { + if (!lookup->pending) { + if (next == NULL) { + debug("Shutting Down.", stderr); + dighost_shutdown(); + return; + } + if (next->sendmsg == NULL) { + debug ("Setting up for UDP"); + setup_lookup(next); + do_lookup(next); + } + } else { + if (lookup->retries > 1) { + debug ("Retrying"); + lookup->retries --; + if (lookup->timer != NULL) + isc_timer_detach(&lookup->timer); + send_udp(lookup); + } else { + debug ("Cancelling"); + cancel_lookup(lookup); + } + } + } +} + + static void followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) { @@ -506,53 +656,11 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, 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 = requeue_lookup + (query->lookup, + ISC_FALSE); lookup->doing_xfr = ISC_FALSE; lookup->defname = ISC_FALSE; - lookup->identify = - query->lookup->identify; - lookup->udpsize = - query->lookup->udpsize; - lookup->recurse = - query->lookup-> - recurse; - lookup->aaonly = - query->lookup-> - aaonly; - lookup->ns_search_only = - query->lookup-> - ns_search_only; lookup->use_my_server_list = ISC_TRUE; if (section == @@ -564,53 +672,8 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, query-> lookup->trace; lookup->trace_root = ISC_FALSE; - lookup->retries = tries; - lookup->nsfound = 0; - lookup->comments = - query->lookup-> - comments; - lookup->stats = - query->lookup-> - stats; - 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( @@ -623,6 +686,8 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, strncpy(srv->servername, (char *)r.base, len); srv->servername[len]=0; + debug ("Adding server %s", + srv->servername); ISC_LIST_APPEND (lookup->my_server_list, srv, link); @@ -643,8 +708,6 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, static void next_origin(dns_message_t *msg, dig_query_t *query) { dig_lookup_t *lookup; - dig_server_t *srv; - dig_server_t *s; UNUSED (msg); @@ -656,77 +719,9 @@ 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 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->doing_xfr = ISC_FALSE; + lookup = requeue_lookup(query->lookup, ISC_TRUE); lookup->defname = ISC_FALSE; - lookup->trace = query->lookup->trace; - lookup->trace_root = query->lookup->trace_root; - lookup->identify = query->lookup->identify; - lookup->udpsize = query->lookup->udpsize; - lookup->recurse = query->lookup->recurse; - lookup->aaonly = query->lookup->aaonly; - 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->stats = query->lookup->stats; - 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 (lookup->use_my_server_list) { - s = ISC_LIST_HEAD(query->lookup->my_server_list); - while (s != NULL) { - srv = isc_mem_allocate (mctx, sizeof(struct - dig_server)); - if (srv == NULL) - fatal("Memory allocation failure in %s:%d", __FILE__, __LINE__); - strncpy(srv->servername, s->servername, MXNAME); - ISC_LIST_ENQUEUE(lookup->my_server_list, srv, - link); - s = ISC_LIST_NEXT(s, link); - } - } - - debug ("Before insertion, init@%ld " - "-> %ld, new@%ld " - "-> %ld", (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 -> " - "%ld, new = %ld, " - "new -> %ld", (long int)query-> - lookup->link.next, - (long int)lookup, (long int)lookup-> - link.next); - } @@ -743,7 +738,10 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_t b; char store[MXNAME]; - debug("setup_lookup()"); + debug("setup_lookup(%lx)",(long int)lookup); + + REQUIRE (lookup != NULL); + debug("Setting up for looking up %s @%lx->%lx", lookup->textname, (long int)lookup, (long int)lookup->link.next); @@ -884,7 +882,7 @@ setup_lookup(dig_lookup_t *lookup) { /* * Force TCP mode if we're doing an xfr. */ - tcp_mode = ISC_TRUE; + lookup->tcp_mode = ISC_TRUE; } if (lookup->trace_root) { tr.base="IN"; @@ -958,18 +956,18 @@ cancel_lookup(dig_lookup_t *lookup) { dig_query_t *query=NULL; debug("cancel_lookup()"); - if (!lookup->pending) - return; - lookup->pending = ISC_FALSE; - lookup->retries = 0; for (query = ISC_LIST_HEAD(lookup->q); query != NULL; query = ISC_LIST_NEXT(query, link)) { if (query->working) { + debug ("Cancelling a worker."); isc_socket_cancel(query->sock, task, ISC_SOCKCANCEL_ALL); } } + lookup->pending = ISC_FALSE; + lookup->retries = 0; + check_next_lookup(lookup); } static void @@ -1019,7 +1017,7 @@ send_udp(dig_lookup_t *lookup) { /* connect_timeout is used for both UDP recieves and TCP connects. */ static void connect_timeout(isc_task_t *task, isc_event_t *event) { - dig_lookup_t *lookup=NULL; + dig_lookup_t *lookup=NULL, *next=NULL; dig_query_t *q=NULL; isc_result_t result; isc_buffer_t *b=NULL; @@ -1050,11 +1048,24 @@ connect_timeout(isc_task_t *task, isc_event_t *event) { q->lookup->textname, q->lookup->retries-1); else { - printf(";; Connection to server %.*s " - "for %s timed out. " - "Giving up.\n", - (int)r.length, r.base, - q->lookup->textname); + if (lookup->tcp_mode) { + printf(";; Connection to " + "server %.*s " + "for %s timed out. " + "Giving up.\n", + (int)r.length, r.base, + q->lookup->textname); + } else { + printf(";; Connection to " + "server %.*s " + "for %s timed out. " + "Trying TCP.\n", + (int)r.length, r.base, + q->lookup->textname); + next = requeue_lookup + (lookup,ISC_TRUE); + next->tcp_mode = ISC_TRUE; + } } } isc_socket_cancel(q->sock, task, @@ -1252,6 +1263,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { isc_buffer_t ab; char abspace[MXNAME]; isc_region_t r; + dig_lookup_t *n; UNUSED (task); @@ -1270,12 +1282,13 @@ recv_done(isc_task_t *task, isc_event_t *event) { query = event->ev_arg; if (!query->lookup->pending && !query->lookup->ns_search_only) { + debug("No longer pending. Got %s", isc_result_totext(sevent->result)); query->working = ISC_FALSE; query->waiting_connect = ISC_FALSE; + cancel_lookup(query->lookup); - check_next_lookup(query->lookup); isc_event_free(&event); return; } @@ -1286,10 +1299,24 @@ recv_done(isc_task_t *task, isc_event_t *event) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); check_result(result, "dns_message_create"); + debug ("Before parse starts"); result = dns_message_parse(msg, b, ISC_TRUE); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + printf (";; Got bad UDP packet:\n"); hex_dump(b); - check_result(result, "dns_message_parse"); + isc_event_free(&event); + query->working = ISC_FALSE; + query->waiting_connect = ISC_FALSE; + if (!query->lookup->tcp_mode) { + printf (";; Retrying in TCP mode.\n"); + n = requeue_lookup(query->lookup, ISC_TRUE); + n->tcp_mode = ISC_TRUE; + } + cancel_lookup(query->lookup); + dns_message_destroy(&msg); + return; + } + debug ("After parse has started"); if (query->lookup->xfr_q == NULL) query->lookup->xfr_q = query; if (query->lookup->xfr_q == query) { @@ -1343,7 +1370,6 @@ recv_done(isc_task_t *task, isc_event_t *event) { "Didn't start with SOA answer."); query->working = ISC_FALSE; cancel_lookup(query->lookup); - check_next_lookup (query->lookup); isc_event_free (&event); dns_message_destroy (&msg); return; @@ -1364,9 +1390,8 @@ recv_done(isc_task_t *task, isc_event_t *event) { isc_buffer_usedregion(&ab, &r); received(b->used, r.length, (char *)r.base, query); - cancel_lookup(query->lookup); query->working = ISC_FALSE; - check_next_lookup(query->lookup); + cancel_lookup(query->lookup); isc_event_free(&event); dns_message_destroy (&msg); return; @@ -1438,7 +1463,7 @@ get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) { } } -void +static void do_lookup_tcp(dig_lookup_t *lookup) { dig_query_t *query; isc_result_t result; @@ -1468,14 +1493,14 @@ do_lookup_tcp(dig_lookup_t *lookup) { } } -void +static void do_lookup_udp(dig_lookup_t *lookup) { dig_query_t *query; isc_result_t result; #ifdef DEBUG debug("do_lookup_udp()"); - if (tcp_mode) + if (lookup->tcp_mode) debug("I'm starting UDP with tcp_mode set!!!"); #endif lookup->pending = ISC_TRUE; @@ -1496,6 +1521,29 @@ do_lookup_udp(dig_lookup_t *lookup) { send_udp(lookup); } +void +do_lookup(dig_lookup_t *lookup) { + + REQUIRE (lookup != NULL); + + if (lookup->tcp_mode) + do_lookup_tcp(lookup); + else + do_lookup_udp(lookup); +} + +void +start_lookup(void) { + dig_lookup_t *lookup; + + debug ("start_lookup()"); + lookup = ISC_LIST_HEAD(lookup_list); + if (lookup != NULL) { + setup_lookup(lookup); + do_lookup(lookup); + } +} + void free_lists(int exitcode) { void *ptr; diff --git a/bin/dig/host.c b/bin/dig/host.c index c00691dced..0c09507be7 100644 --- a/bin/dig/host.c +++ b/bin/dig/host.c @@ -36,8 +36,7 @@ extern ISC_LIST(dig_lookup_t) lookup_list; extern ISC_LIST(dig_server_t) server_list; extern ISC_LIST(dig_searchlist_t) search_list; -extern isc_boolean_t tcp_mode, - have_ipv6, show_details; +extern isc_boolean_t have_ipv6, show_details; extern in_port_t port; extern unsigned int timeout; extern isc_mem_t *mctx; @@ -57,7 +56,8 @@ extern int exitcode; isc_boolean_t short_form=ISC_TRUE, filter=ISC_FALSE, - showallsoa=ISC_FALSE; + showallsoa=ISC_FALSE, + tcpmode = ISC_FALSE; static char *opcodetext[] = { "QUERY", @@ -142,48 +142,6 @@ static char *rtypetext[] = { "has 40 record", /* 40 */ "has optional information"}; /* 41 */ -void -check_next_lookup(dig_lookup_t *lookup) { - dig_lookup_t *next; - dig_query_t *query; - isc_boolean_t still_working=ISC_FALSE; - - 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.", stderr); - still_working=ISC_TRUE; - } - } - if (still_working) - return; - - next = ISC_LIST_NEXT(lookup, link); - debug ("Have %d retries left for %s\n", - lookup->retries, lookup->textname); - if ((next == NULL)&&((lookup->retries <= 1) - ||tcp_mode || !lookup->pending)) { - debug("Shutting Down.", stderr); - isc_app_shutdown(); - return; - } - - if (tcp_mode) { - setup_lookup(next); - do_lookup_tcp(next); - } else { - if ((lookup->retries > 1) && (lookup->pending)) { - lookup->retries --; - send_udp(lookup); - } else { - ENSURE (next != NULL); - setup_lookup(next); - do_lookup_udp(next); - } - } -} static void show_usage() { @@ -206,6 +164,11 @@ show_usage() { exit (exitcode); } +void +dighost_shutdown(void) { + isc_app_shutdown(); +} + void received(int bytes, int frmsize, char *frm, dig_query_t *query) { isc_time_t now; @@ -507,7 +470,7 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { return (result); } -void +static void parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { isc_boolean_t have_host=ISC_FALSE, recursion=ISC_TRUE, @@ -527,7 +490,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { != EOF) { switch (c) { case 'l': - tcp_mode = ISC_TRUE; + tcpmode = ISC_TRUE; xfr_mode = ISC_TRUE; filter = ISC_TRUE; strcpy (querytype, "axfr"); @@ -565,7 +528,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { tries = 1; break; case 'T': - tcp_mode = ISC_TRUE; + tcpmode = ISC_TRUE; break; case 'C': debug ("Showing all SOA's"); @@ -653,6 +616,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->nsfound = 0; lookup->trace = showallsoa; lookup->trace_root = ISC_FALSE; + lookup->tcp_mode = tcpmode; ISC_LIST_INIT(lookup->q); ISC_LIST_APPEND(lookup_list, lookup, link); lookup->origin = NULL; @@ -662,7 +626,6 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { int main(int argc, char **argv) { - dig_lookup_t *lookup = NULL; #ifdef TWIDDLE FILE *fp; int i, p; @@ -688,12 +651,7 @@ main(int argc, char **argv) { setup_libs(); parse_args(ISC_FALSE, argc, argv); setup_system(); - lookup = ISC_LIST_HEAD(lookup_list); - setup_lookup(lookup); - if (tcp_mode) - do_lookup_tcp(lookup); - else - do_lookup_udp(lookup); + start_lookup(); isc_app_run(); free_lists(0); return (0); diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 367c928bfe..c57145438d 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -55,7 +55,8 @@ typedef struct dig_server dig_server_t; typedef struct dig_searchlist dig_searchlist_t; struct dig_lookup { - isc_boolean_t pending, /* Pending a successful answer */ + isc_boolean_t + pending, /* Pending a successful answer */ waiting_connect, doing_xfr, ns_search_only, @@ -65,7 +66,14 @@ struct dig_lookup { aaonly, trace, trace_root, - defname; + defname, + tcp_mode, + comments, + stats, + section_question, + section_answer, + section_authority, + section_additional; char textname[MXNAME]; /* Name we're going to be looking up */ char rttext[MXRD]; /* rdata type text */ char rctext[MXRD]; /* rdata class text */ @@ -88,12 +96,6 @@ struct dig_lookup { int retries; int nsfound; isc_uint16_t udpsize; - isc_boolean_t comments, - stats, - section_question, - section_answer, - section_authority, - section_additional; }; struct dig_query { @@ -143,9 +145,9 @@ istype(char *text) ; void setup_lookup(dig_lookup_t *lookup); void -do_lookup_udp (dig_lookup_t *lookup); +do_lookup(dig_lookup_t *lookup); void -do_lookup_tcp (dig_lookup_t *lookup); +start_lookup (void); void send_udp(dig_lookup_t *lookup); int @@ -156,19 +158,19 @@ void setup_system(void); void free_lists(int exitcode); +dig_lookup_t +*requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers); /* Routines needed in dig.c and host.c */ -void -parse_args(isc_boolean_t is_batchfile, int argc, char **argv) ; isc_result_t printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) ; void -check_next_lookup (dig_lookup_t *lookup); -void received(int bytes, int frmsize, char *frm, dig_query_t *query); void trying(int frmsize, char *frm, dig_lookup_t *lookup); +void +dighost_shutdown(void); ISC_LANG_ENDDECLS diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c index c253a933d6..5fd79357f1 100644 --- a/bin/dig/nslookup.c +++ b/bin/dig/nslookup.c @@ -27,6 +27,7 @@ extern int h_errno; #include #include #include +#include #include #include @@ -39,7 +40,7 @@ extern ISC_LIST(dig_lookup_t) lookup_list; extern ISC_LIST(dig_server_t) server_list; extern ISC_LIST(dig_searchlist_t) search_list; -extern isc_boolean_t tcp_mode, have_ipv6, show_details, +extern isc_boolean_t have_ipv6, show_details, usesearch, trace, qr; extern in_port_t port; extern unsigned int timeout; @@ -56,13 +57,11 @@ extern int ndots; extern int tries; extern int lookup_counter; extern char fixeddomain[MXNAME]; -#ifdef TWIDDLE -extern isc_boolean_t twiddle; -#endif extern int exitcode; isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE, - filter = ISC_FALSE, showallsoa = ISC_FALSE; + filter = ISC_FALSE, showallsoa = ISC_FALSE, + tcpmode = ISC_FALSE; isc_uint16_t bufsize = 0; isc_boolean_t identify = ISC_FALSE, @@ -74,27 +73,9 @@ isc_boolean_t identify = ISC_FALSE, defname = ISC_TRUE, aaonly = ISC_FALSE; isc_mutex_t lock; isc_condition_t cond; -isc_boolean_t busy = ISC_FALSE, arg_lookup = ISC_FALSE; - - -static char *opcodetext[] = { - "QUERY", - "IQUERY", - "STATUS", - "RESERVED3", - "NOTIFY", - "UPDATE", - "RESERVED6", - "RESERVED7", - "RESERVED8", - "RESERVED9", - "RESERVED10", - "RESERVED11", - "RESERVED12", - "RESERVED13", - "RESERVED14", - "RESERVED15" -}; +isc_boolean_t busy = ISC_FALSE, in_use = ISC_FALSE; +char defclass[MXRD] = "IN"; +char deftype[MXRD] = "A"; static char *rcodetext[] = { "NOERROR", @@ -116,6 +97,51 @@ static char *rcodetext[] = { "BADVERS" }; +static char *rtypetext[] = { + "rtype_0 = ", /* 0 */ + "internet address = ", /* 1 */ + "nameserver = ", /* 2 */ + "md = ", /* 3 */ + "mf = ", /* 4 */ + "canonical name = ", /* 5 */ + "soa = ", /* 6 */ + "mb = ", /* 7 */ + "mg = ", /* 8 */ + "mr = ", /* 9 */ + "rtype_10 = ", /* 10 */ + "protocol = ", /* 11 */ + "name = ", /* 12 */ + "hinfo = ", /* 13 */ + "minfo = ", /* 14 */ + "mail exchanger = ", /* 15 */ + "text = ", /* 16 */ + "rp = ", /* 17 */ + "afsdb = ", /* 18 */ + "x25 address = ", /* 19 */ + "isdn address = ", /* 20 */ + "rt = " /* 21 */ + "nsap = ", /* 22 */ + "nsap_ptr = ", /* 23 */ + "signature = ", /* 24 */ + "key = ", /* 25 */ + "px = ", /* 26 */ + "gpos = ", /* 27 */ + "has AAAA address", /* 28 */ + "loc = ", /* 29 */ + "next = ", /* 30 */ + "rtype_31 = ", /* 31 */ + "rtype_32 = ", /* 32 */ + "service = ", /* 33 */ + "rtype_34 = ", /* 34 */ + "naptr = ", /* 35 */ + "kx = ", /* 36 */ + "cert = ", /* 37 */ + "v6 address = ", /* 38 */ + "dname = ", /* 39 */ + "rtype_40 = ", /* 40 */ + "optional = "}; /* 41 */ + + static void show_usage() { fputs ( @@ -124,73 +150,19 @@ show_usage() { } void -check_next_lookup(dig_lookup_t *lookup) { - dig_lookup_t *next; - dig_query_t *query; - isc_boolean_t still_working=ISC_FALSE; - - 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.", stderr); - still_working=ISC_TRUE; - } - } - if (still_working) - return; +dighost_shutdown(void) { + isc_mutex_lock(&lock); + busy = ISC_FALSE; + isc_condition_signal(&cond); + isc_mutex_unlock(&lock); - next = ISC_LIST_NEXT(lookup, link); - debug ("Have %d retries left for %s\n", - lookup->retries, lookup->textname); - if ((next == NULL)&&((lookup->retries <= 1) - ||tcp_mode || !lookup->pending)) { - debug("Shutting Down.", stderr); - isc_mutex_lock(&lock); - busy = ISC_FALSE; - isc_condition_signal(&cond); - isc_mutex_unlock(&lock); - return; - } - - if (tcp_mode) { - setup_lookup(next); - do_lookup_tcp(next); - } else { - if ((lookup->retries > 1) && (lookup->pending)) { - lookup->retries --; - send_udp(lookup); - } else { - ENSURE (next != NULL); - setup_lookup(next); - do_lookup_udp(next); - } - } } - void received(int bytes, int frmsize, char *frm, dig_query_t *query) { - isc_uint64_t diff; - isc_time_t now; - isc_result_t result; - time_t tnow; - - result = isc_time_now(&now); - check_result (result, "isc_time_now"); - - if (query->lookup->stats) { - diff = isc_time_microdiff(&now, &query->time_sent); - printf(";; Query time: %ld msec\n", (long int)diff/1000); - printf(";; SERVER: %.*s\n", frmsize, frm); - time (&tnow); - printf(";; WHEN: %s", ctime(&tnow)); - printf (";; MSG SIZE rcvd: %d\n\n", bytes); - } 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); - } + UNUSED (bytes); + UNUSED (frmsize); + UNUSED (frm); + UNUSED (query); } void @@ -201,158 +173,21 @@ trying(int frmsize, char *frm, dig_lookup_t *lookup) { } -static void -say_message(dns_rdata_t *rdata, dig_query_t *query) { - 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); - 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) { - 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); -} static isc_result_t -printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name, - isc_boolean_t headers, dig_query_t *query) -{ - dns_name_t *name, *print_name; - dns_rdataset_t *rdataset; - isc_buffer_t target; +printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers, + dns_section_t section) { isc_result_t result, loopresult; - isc_region_t r; - dns_name_t empty_name; - char t[4096]; - isc_boolean_t first; - isc_boolean_t no_rdata; + isc_buffer_t *b = NULL; + dns_name_t *name; + dns_rdataset_t *rdataset = NULL; dns_rdata_t rdata; - - if (sectionid == DNS_SECTION_QUESTION) - no_rdata = ISC_TRUE; - else - no_rdata = ISC_FALSE; - - if (headers && query->lookup->comments && !short_form) - printf(";; %s SECTION:\n", section_name); - - dns_name_init(&empty_name, NULL); - - result = dns_message_firstname(msg, sectionid); - if (result == ISC_R_NOMORE) - return (ISC_R_SUCCESS); - else if (result != ISC_R_SUCCESS) - return (result); - - for (;;) { - name = NULL; - dns_message_currentname(msg, sectionid, &name); - - isc_buffer_init(&target, t, sizeof(t)); - first = ISC_TRUE; - print_name = name; - - for (rdataset = ISC_LIST_HEAD(name->list); - rdataset != NULL; - rdataset = ISC_LIST_NEXT(rdataset, link)) { - if (!short_form) { - result = dns_rdataset_totext(rdataset, - print_name, - ISC_FALSE, - no_rdata, - &target); - if (result != ISC_R_SUCCESS) - return (result); -#ifdef USEINITALWS - if (first) { - print_name = &empty_name; - first = ISC_FALSE; - } -#endif - } else { - loopresult = dns_rdataset_first(rdataset); - while (loopresult == ISC_R_SUCCESS) { - dns_rdataset_current(rdataset, &rdata); - say_message(&rdata, query); - loopresult = dns_rdataset_next( - rdataset); - } - } - - } - isc_buffer_usedregion(&target, &r); - if (no_rdata) - printf(";%.*s", (int)r.length, (char *)r.base); - else - printf("%.*s", (int)r.length, (char *)r.base); - - result = dns_message_nextname(msg, sectionid); - if (result == ISC_R_NOMORE) - break; - else if (result != ISC_R_SUCCESS) - return (result); - } - - return (ISC_R_SUCCESS); -} - -static isc_result_t -printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner, - char *set_name, isc_boolean_t headers) -{ - isc_buffer_t target; - isc_result_t result; - isc_region_t r; - char t[4096]; - - UNUSED(msg); - if (headers) - printf(";; %s SECTION:\n", set_name); - - isc_buffer_init(&target, t, sizeof(t)); - - result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, - &target); - if (result != ISC_R_SUCCESS) - return (result); - isc_buffer_usedregion(&target, &r); - printf("%.*s", (int)r.length, (char *)r.base); - - return (ISC_R_SUCCESS); -} - -isc_result_t -printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { - isc_boolean_t did_flag = ISC_FALSE; - isc_result_t result; - dns_rdataset_t *opt, *tsig = NULL; - dns_name_t *tsigname; + char *ptr; UNUSED (query); + UNUSED (headers); + + debug("printsection()"); /* * Exitcode 9 means we timed out, but if we're printing a message, @@ -362,301 +197,275 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { if (exitcode == 9) exitcode = 0; - result = ISC_R_SUCCESS; - - if (query->lookup->comments && !short_form) { - if (msg == query->lookup->sendmsg) - printf (";; Sending:\n"); - else - printf (";; Got answer:\n"); - } - - if (headers) { - if (query->lookup->comments && !short_form) { - printf(";; ->>HEADER<<- opcode: %s, status: %s, " - "id: %u\n", - opcodetext[msg->opcode], rcodetext[msg->rcode], - msg->id); - printf(";; flags: "); - if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { - printf("qr"); - did_flag = ISC_TRUE; - } - if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { - printf("%saa", did_flag ? " " : ""); - did_flag = ISC_TRUE; - if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { - printf("%stc", did_flag ? " " : ""); - did_flag = ISC_TRUE; + result = dns_message_firstname(msg, section); + if (result == ISC_R_NOMORE) + return (ISC_R_SUCCESS); + else if (result != ISC_R_SUCCESS) + return (result); + result = isc_buffer_allocate(mctx, &b, MXNAME); + check_result(result, "isc_buffer_allocate"); + for (;;) { + name = NULL; + 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); + switch (rdata.type) { + case dns_rdatatype_a: + if (section != DNS_SECTION_ANSWER) + goto def_short_section; + isc_buffer_clear(b); + result = dns_name_totext(name, + ISC_TRUE, + b); + check_result(result, + "dns_name_totext"); + printf("Name:\t%.*s\n", + (int)isc_buffer_usedlength(b), + (char*)isc_buffer_base(b)); + isc_buffer_clear(b); + result = dns_rdata_totext(&rdata, + NULL, + b); + check_result(result, + "dns_rdata_totext"); + printf("Address: %.*s\n", + (int)isc_buffer_usedlength(b), + (char*)isc_buffer_base(b)); + break; + case dns_rdatatype_soa: + isc_buffer_clear(b); + result = dns_name_totext(name, + ISC_TRUE, + b); + check_result(result, + "dns_name_totext"); + printf("%.*s\n", + (int)isc_buffer_usedlength(b), + (char*)isc_buffer_base(b)); + isc_buffer_clear(b); + result = dns_rdata_totext(&rdata, + NULL, + b); + check_result(result, + "dns_rdata_totext"); + isc_buffer_used(b)[0]=0; + ptr = strtok(isc_buffer_base(b), + " \t\r\n"); + if (ptr == NULL) + break; + printf("\torigin = %s\n", + ptr); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + break; + printf("\tmail addr = %s\n", + ptr); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + break; + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + break; + printf("\tserial = %s\n", + ptr); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + break; + printf("\trefresh = %s\n", + ptr); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + break; + printf("\tretry = %s\n", + ptr); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + break; + printf("\texpire = %s\n", + ptr); + ptr = strtok(NULL, " \t\r\n"); + if (ptr == NULL) + break; + printf("\tminimum = %s\n", + ptr); + break; + default: + def_short_section: + isc_buffer_clear(b); + result = dns_name_totext(name, + ISC_TRUE, + b); + check_result(result, + "dns_name_totext"); + if (rdata.type <= 41) + printf ("%.*s\t%s", + (int)isc_buffer_usedlength(b), + (char*)isc_buffer_base(b), + rtypetext[rdata.type]); + else + printf ("%.*s\trdata_%d = ", + (int)isc_buffer_usedlength(b), + (char*)isc_buffer_base(b), + rdata.type); + isc_buffer_clear(b); + result = dns_rdata_totext(&rdata, + NULL, b); + check_result(result, + "dns_rdata_totext"); + printf("%.*s\n", + (int)isc_buffer_usedlength(b), + (char*)isc_buffer_base(b)); } - if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { - printf("%srd", did_flag ? " " : ""); - did_flag = ISC_TRUE; - } - if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { - printf("%sra", did_flag ? " " : ""); - did_flag = ISC_TRUE; - } - if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { - printf("%sad", did_flag ? " " : ""); - did_flag = ISC_TRUE; - } - if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { - printf("%scd", did_flag ? " " : ""); - did_flag = ISC_TRUE; - } - - printf("; QUERY: %u, ANSWER: %u, " - "AUTHORITY: %u, ADDITIONAL: %u\n", - msg->counts[DNS_SECTION_QUESTION], - msg->counts[DNS_SECTION_ANSWER], - msg->counts[DNS_SECTION_AUTHORITY], - msg->counts[DNS_SECTION_ADDITIONAL]); + loopresult = dns_rdataset_next(rdataset); } - opt = dns_message_getopt(msg); - if (opt != NULL) - printf(";; EDNS: version: %u, udp=%u\n", - (unsigned int)((opt->ttl & - 0x00ff0000) >> 16), - (unsigned int)opt->rdclass); - tsigname = NULL; - tsig = dns_message_gettsig(msg, &tsigname); - if (tsig != NULL) - printf(";; PSEUDOSECTIONS: TSIG\n"); + } + result = dns_message_nextname(msg, section); + if (result == ISC_R_NOMORE) + break; + else if (result != ISC_R_SUCCESS) { + isc_buffer_free (&b); + return (result); } } - if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && - headers && query->lookup->section_question) { - printf("\n"); - result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", - ISC_TRUE, query); - if (result != ISC_R_SUCCESS) - return (result); - } - if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]) && - query->lookup->section_answer ) { - 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) || - ( 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); - if (result != ISC_R_SUCCESS) - return (result); - } - if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && - headers && query->lookup->section_additional) { - if (headers && query->lookup->comments && !short_form) - printf("\n"); - result = printsection(msg, DNS_SECTION_ADDITIONAL, - "ADDITIONAL", ISC_TRUE, query); - if (result != ISC_R_SUCCESS) - return (result); - } - if ((tsig != NULL) && headers && query->lookup->section_additional) { - 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 && !short_form) - printf("\n"); + isc_buffer_free(&b); + return (ISC_R_SUCCESS); +} - return (result); +isc_result_t +printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { + isc_buffer_t *b = NULL; + isc_region_t r; + isc_result_t result; + + debug ("printmessage()"); + + if (msg->rcode != 0) { + result = isc_buffer_allocate(mctx, &b, MXNAME); + check_result(result, "isc_buffer_allocate"); + result = dns_name_totext(query->lookup->name, ISC_FALSE, + b); + check_result(result, "dns_name_totext"); + isc_buffer_usedregion(b, &r); + printf("** server can't find %.*s: %s\n", + (int)r.length, (char*)r.base, + rcodetext[msg->rcode]); + isc_buffer_free(&b); + debug ("Returning with rcode == 0"); + return (ISC_R_SUCCESS); + } + debug ("Continuing on with rcode != 0"); + result = isc_buffer_allocate(mctx, &b, MXNAME); + check_result(result, "isc_buffer_allocate"); + printf("Server:\t\t%s\n", query->servname); + result = isc_sockaddr_totext(&query->sockaddr, b); + check_result(result, "isc_sockaddr_totext"); + printf("Address:\t%.*s\n", (int)isc_buffer_usedlength(b), + (char*)isc_buffer_base(b)); + puts(""); + if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) + puts ("Non-authorative answer:"); + isc_buffer_free(&b); + printsection(query, msg, headers, DNS_SECTION_ANSWER); + + if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) && + (strcasecmp(query->lookup->rttext,"a") != 0)) { + puts ("\nAuthorative answers can be found from:"); + printsection(query, msg, headers, DNS_SECTION_AUTHORITY); + printsection(query, msg, headers, DNS_SECTION_ADDITIONAL); + } + return (ISC_R_SUCCESS); } static void -printgreeting(int argc, char **argv) { - int i = 1; - - if (printcmd) { - puts (""); - printf ("; <<>> DiG 9.0 <<>>"); - while (i < argc) { - printf (" %s", argv[i++]); - } - puts (""); - printf (";; global options: %s %s\n", - short_form?"short_form":"", - printcmd?"printcmd":""); - } -} - -/* - * Reorder an argument list so that server names all come at the end. - * This is a bit of a hack, to allow batch-mode processing to properly - * handle the server options. - */ -static void -reorder_args(int argc, char *argv[]) { - int i, j; - char *ptr; - int end; - - debug ("reorder_args()"); - end = argc-1; - while (argv[end][0] == '@') { - end--; - if (end == 0) - return; - } - debug ("arg[end]=%s",argv[end]); - for (i=1; iservername); + srv = ISC_LIST_NEXT(srv, link); + } + printf ("\n\tSet options:\n"); + printf ("\t %s\t\t\t%s\t\t%s\n", + tcpmode?"vc":"novc", short_form?"nodebug":"debug", + recurse?"recurse":"norecurse"); + printf ("\t %s\t\t%s\t\tport = %d\n", + defname?"defname":"nodefname", usesearch?"search":"nosearch", + port); + printf ("\t timeout = %d\t\tretry = %d\n", + timeout, tries); + printf ("\t querytype = %-8s\tclass=%s\n",deftype, defclass); + + +} + +static void +setoption(char *opt) { + + if (strncasecmp(opt,"all",4) == 0) { + showsettings() ; + } else if (strncasecmp(opt, "class=", 6) == 0) { + strncpy(defclass, &opt[6], MXRD); + } else if (strncasecmp(opt, "cl=", 3) == 0) { + strncpy(defclass, &opt[3], MXRD); + } else if (strncasecmp(opt, "type=", 5) == 0) { + strncpy(deftype, &opt[5], MXRD); + } else if (strncasecmp(opt, "ty=", 3) == 0) { + strncpy(deftype, &opt[3], MXRD); + } else if (strncasecmp(opt, "querytype=", 10) == 0) { + strncpy(deftype, &opt[10], MXRD); + } else if (strncasecmp(opt, "query=", 6) == 0) { + strncpy(deftype, &opt[6], MXRD); + } else if (strncasecmp(opt, "qu=", 3) == 0) { + strncpy(deftype, &opt[3], MXRD); + } else if (strncasecmp(opt, "domain=", 7) == 0) { + strncpy(fixeddomain, &opt[7], MXNAME); + } else if (strncasecmp(opt, "do=", 3) == 0) { + strncpy(fixeddomain, &opt[3], MXNAME); + } else if (strncasecmp(opt, "port=", 5) == 0) { + port = atoi(&opt[5]); + } else if (strncasecmp(opt, "po=", 3) == 0) { + port = atoi(&opt[3]); + } else if (strncasecmp(opt, "timeout=", 8) == 0) { + timeout = atoi(&opt[8]); + } else if (strncasecmp(opt, "t=", 2) == 0) { + timeout = atoi(&opt[2]); + } else if (strncasecmp(opt, "retry=", 6) == 0) { + tries = atoi(&opt[6]); + } else if (strncasecmp(opt, "ret=", 4) == 0) { + tries = atoi(&opt[4]); + } else if (strncasecmp(opt, "def", 3) == 0) { + defname = ISC_TRUE; + } else if (strncasecmp(opt, "nodef", 5) == 0) { + defname = ISC_FALSE; + } else if (strncasecmp(opt, "deb", 3) == 0) { + short_form = ISC_FALSE; + } else if (strncasecmp(opt, "nodeb", 5) == 0) { + short_form = ISC_TRUE; + } +} + +static void +addlookup(char *opt) { dig_lookup_t *lookup; - int i, c, n, adrs[4]; - char store[MXNAME]; - UNUSED(is_batchfile); - - while ((c = isc_commandline_parse(argc, argv, "lvwrdt:c:aTCN:R:W:")) - != EOF) { - switch (c) { - case 'l': - tcp_mode = ISC_TRUE; - xfr_mode = ISC_TRUE; - filter = ISC_TRUE; - strcpy (querytype, "axfr"); - break; - case 'v': - case 'd': - short_form = ISC_FALSE; - break; - case 'r': - recursion = ISC_FALSE; - break; - case 't': - strncpy (querytype, isc_commandline_argument, 32); - break; - case 'c': - strncpy (queryclass, isc_commandline_argument, 32); - break; - case 'a': - strcpy (querytype, "any"); - short_form = ISC_FALSE; - break; - case 'w': - /* XXXMWS This should be a system-indep. - * thing! */ - timeout = 32767; - break; - case 'W': - timeout = atoi(isc_commandline_argument); - if (timeout < 1) - timeout = 1; - break; - case 'R': - tries = atoi(isc_commandline_argument); - if (tries < 1) - tries = 1; - break; - case 'T': - tcp_mode = ISC_TRUE; - break; - case 'C': - debug ("Showing all SOA's"); - if (querytype[0] == 0) - strcpy (querytype, "soa"); - if (queryclass[0] == 0) - strcpy (queryclass, "in"); - nsfind = ISC_TRUE; - showallsoa = ISC_TRUE; - show_details = ISC_TRUE; - break; - case 'N': - debug ("Setting NDOTS to %s", - isc_commandline_argument); - ndots = atoi(isc_commandline_argument); - break; - } - } - if (isc_commandline_index >= argc) { - show_usage(); - } - strncpy (hostname, argv[isc_commandline_index], MXNAME); - if (argc > isc_commandline_index+1) { - srv=isc_mem_allocate(mctx, sizeof(struct dig_server)); - if (srv == NULL) - fatal ("Memory allocation failure."); - strncpy(srv->servername, - argv[isc_commandline_index+1], MXNAME-1); - debug("Server is %s", srv->servername); - ISC_LIST_APPEND(server_list, srv, link); - } - + debug ("addlookup()"); 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."); + lookup = isc_mem_allocate(mctx, sizeof(struct dig_lookup)); + if (lookup == NULL) + fatal("Memory allocation failure."); lookup->pending = ISC_FALSE; - /* - * XXXMWS Add IPv6 translation here, probably using inet_pton - * to extract the formatted text. - */ - if (strcspn(hostname, "0123456789.") != strlen(hostname)) { - lookup->textname[0]=0; - n = sscanf(hostname, "%d.%d.%d.%d", &adrs[0], &adrs[1], - &adrs[2], &adrs[3]); - if (n==0) { - show_usage(); - exit (exitcode); - } - for (i = n - 1; i >= 0; i--) { - snprintf(store, MXNAME/8, "%d.", - adrs[i]); - strncat(lookup->textname, store, MXNAME); - } - strncat(lookup->textname, "in-addr.arpa.", MXNAME); - if (querytype[0] == 0) - strcpy (querytype, "ptr"); - } else - strncpy (lookup->textname, hostname, MXNAME); - if (querytype[0] == 0) - strcpy (querytype, "a"); - if (queryclass[0] == 0) - strcpy (queryclass, "in"); - strncpy (lookup->rttext, querytype, 32); - strncpy (lookup->rctext, queryclass, 32); + strncpy(lookup->textname, opt, MXNAME-1); + strncpy (lookup->rttext, deftype, MXNAME); + strncpy (lookup->rctext, defclass, MXNAME); lookup->namespace[0]=0; lookup->sendspace[0]=0; lookup->sendmsg=NULL; @@ -665,48 +474,172 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->timer = NULL; lookup->xfr_q = NULL; lookup->origin = NULL; + lookup->use_my_server_list = ISC_FALSE; lookup->doing_xfr = ISC_FALSE; lookup->defname = ISC_FALSE; - lookup->identify = ISC_FALSE; - lookup->recurse = recursion; - lookup->ns_search_only = showallsoa; - 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->identify = identify; + lookup->recurse = recurse; + lookup->aaonly = aaonly; lookup->retries = tries; + lookup->udpsize = bufsize; lookup->nsfound = 0; - lookup->trace = showallsoa; - lookup->trace_root = ISC_FALSE; + lookup->comments = comments; + lookup->stats = stats; + lookup->section_question = section_question; + lookup->section_answer = section_answer; + lookup->section_authority = section_authority; + lookup->section_additional = section_additional; ISC_LIST_INIT(lookup->q); ISC_LIST_APPEND(lookup_list, lookup, link); lookup->origin = NULL; ISC_LIST_INIT(lookup->my_server_list); - have_host = ISC_TRUE; + debug("Looking up %s", lookup->textname); } +static void +flush_server_list() { + dig_server_t *s, *ps; + + s = ISC_LIST_HEAD(server_list); + while (s != NULL) { + ps = s; + s = ISC_LIST_NEXT(s, link); + ISC_LIST_DEQUEUE(server_list, ps, link); + isc_mem_free(mctx, ps); + } + +} + +/* + * This works on the global server list, instead of on a per-lookup + * server list, since the change is persistent. + */ +static void +setsrv(char *opt) { + dig_server_t *srv; + + flush_server_list(); + srv=isc_mem_allocate(mctx, sizeof(struct dig_server)); + if (srv == NULL) + fatal("Memory allocation failure."); + strncpy(srv->servername, opt, MXNAME-1); + ISC_LIST_APPEND(server_list, srv, link); +} + +static void +get_next_command() { + char input[COMMSIZE]; + char *ptr, *arg; + + fputs("> ", stderr); + ptr = fgets(input, COMMSIZE, stdin); + if (ptr == NULL) { + in_use = ISC_FALSE; + return; + } + ptr = strtok(input, " \t\r\n"); + if (ptr == NULL) { + in_use = ISC_FALSE; + return; + } + arg = strtok(NULL, " \t\r\n"); + if ((strcasecmp(ptr, "set") == 0) && + (arg != NULL)) + setoption(arg); + else if ((strcasecmp(ptr, "server") == 0) || + (strcasecmp(ptr, "lserver") == 0)) { + printf("Server:\t%s\n", arg); + setsrv(arg); + } else + addlookup(ptr); +} + +static void +parse_args(int argc, char **argv) { + dig_lookup_t *lookup = NULL; + + for (argc--, argv++; argc > 0; argc--, argv++) { + debug ("Main parsing %s", argv[0]); + if (argv[0][0] == '-') { + if ((argv[0][1] == 'h') && + (argv[0][2] == 0)) { + show_usage(); + exit (1); + } + if (argv[0][1] != 0) + setoption(&argv[0][1]); + } else { + if (lookup == NULL) { + in_use = ISC_TRUE; + addlookup(argv[0]); + } + else + setsrv(argv[0]); + } + } +} + +static void +flush_lookup_list(void) { + dig_lookup_t *l, *lp; + dig_query_t *q, *qp; + dig_server_t *s, *sp; + + lookup_counter = 0; + l = ISC_LIST_HEAD(lookup_list); + while (l != NULL) { + q = ISC_LIST_HEAD(l->q); + while (q != NULL) { + if (q->sock != NULL) { + isc_socket_cancel(q->sock, NULL, + ISC_SOCKCANCEL_ALL); + isc_socket_detach(&q->sock); + } + if (ISC_LINK_LINKED(&q->recvbuf, link)) + ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf, + link); + if (ISC_LINK_LINKED(&q->lengthbuf, link)) + ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf, + link); + isc_buffer_invalidate(&q->recvbuf); + isc_buffer_invalidate(&q->lengthbuf); + qp = q; + q = ISC_LIST_NEXT(q, link); + ISC_LIST_DEQUEUE(l->q, qp, link); + isc_mem_free(mctx, qp); + } + if (l->use_my_server_list) { + s = ISC_LIST_HEAD(l->my_server_list); + while (s != NULL) { + sp = s; + s = ISC_LIST_NEXT(s, link); + ISC_LIST_DEQUEUE(l->my_server_list, sp, link); + isc_mem_free(mctx, sp); + + } + } + if (l->sendmsg != NULL) + dns_message_destroy(&l->sendmsg); + if (l->timer != NULL) + isc_timer_detach(&l->timer); + lp = l; + l = ISC_LIST_NEXT(l, link); + ISC_LIST_DEQUEUE(lookup_list, lp, link); + isc_mem_free(mctx, lp); + } +} + int main(int argc, char **argv) { - dig_lookup_t *lookup = NULL; isc_result_t result; -#ifdef TWIDDLE - FILE *fp; - int i, p; -#endif ISC_LIST_INIT(lookup_list); ISC_LIST_INIT(server_list); ISC_LIST_INIT(search_list); -#ifdef TWIDDLE - fp = fopen("/dev/urandom", "r"); - if (fp!=NULL) { - fread (&i, sizeof(int), 1, fp); - srandom(i); - } - else { - srandom ((int)&main); - } - p = getpid()%16+8; - for (i=0 ; i