diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 126ea8a971..0382983a28 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -15,7 +15,6 @@ * SOFTWARE. */ -#define TWIDDLE #include @@ -24,6 +23,7 @@ #include #include #include +#include extern int h_errno; @@ -60,7 +60,7 @@ extern int h_errno; extern ISC_LIST(dig_lookup_t) lookup_list; extern ISC_LIST(dig_server_t) server_list; -extern isc_boolean_t tcp_mode, recurse, have_ipv6; +extern isc_boolean_t tcp_mode, recurse, have_ipv6, show_details; extern in_port_t port; extern unsigned int timeout; extern isc_mem_t *mctx; @@ -73,11 +73,17 @@ extern dns_name_t rootorg; extern char *rootspace[BUFSIZE]; extern isc_buffer_t rootbuf; extern int sendcount; +extern int ndots; +extern int tries; #ifdef TWIDDLE extern isc_boolean_t twiddle; #endif -isc_boolean_t short_form=ISC_FALSE; +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; static char *opcodetext[] = { "QUERY", @@ -120,7 +126,34 @@ static char *rcodetext[] = { static void show_usage() { - fatal("Usage."); + fputs ( +"Usage: dig [@server] [domain] [q-type] [q-class] {q-opt} {d-opt}\n" +"where: server,\n" +" domain are in the Domain Name System\n" +" q-class is one of (in,chaos,...) [default: in]\n" +" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n" +" q-opt is one of:\n" +" -x dot-notation (shortcut for in-addr lookups)\n" +" -f filename (batch mode)\n" +" -p port (specify port number)\n" +" d-opt is of the form +keyword[=value], where keyword is:\n" +" +[no]vc (TCP mode)\n" +" +time=### (Set query timeout) [30]\n" +" +tries=### (Set number of UDP attempts) [2]\n" +" +[no]rec (Recursive mode)\n" +" +[no]details (Show details of all requests)\n" +" +[no]nssearch (Search for info on all authorative\n" +" nameservers for the domain.)\n" +#ifdef TWIDDLE +" +twiddle (Intentionally form bad requests)\n" +#endif +" +ndots=### (Set NDOTS value)\n" +" +[no]comments (Control display of comment lines)\n" +" +[no]question (Control display of question)\n" +" +[no]answer (Control display of answer)\n" +" +[no]autority (Control display of authority)\n" +" +[no]additional (Control display of additional)\n" +, stderr); } void @@ -142,23 +175,58 @@ check_next_lookup(dig_lookup_t *lookup) { return; next = ISC_LIST_NEXT(lookup, link); - if (next == NULL) { + debug ("Have %d retries left for %s\n", + lookup->retries, lookup->textname); + if ((next == NULL)&&((lookup->retries <= 1) + ||tcp_mode)) { debug("Shutting Down.",stderr); isc_app_shutdown(); return; } - setup_lookup(next); - if (tcp_mode) + if (tcp_mode) { + setup_lookup(next); do_lookup_tcp(next); - else - do_lookup_udp(next); - + } else { + if (lookup->retries > 1) { + lookup->retries --; + send_udp(lookup); + } else { + 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 (!short_form && 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)); + } +} + +void +trying(int frmsize, char *frm, dig_lookup_t *lookup) { + if (lookup->comments) + printf ("; Trying %.*s\n", frmsize, frm); +} + + static isc_result_t printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name, - isc_boolean_t headers) + isc_boolean_t headers, dig_query_t *query) { dns_name_t *name, *print_name; dns_rdataset_t *rdataset; @@ -175,7 +243,7 @@ printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name, else no_rdata = ISC_FALSE; - if (headers) + if (headers && query->lookup->comments) printf(";; %s SECTION:\n", section_name); dns_name_init(&empty_name, NULL); @@ -264,94 +332,103 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { result = ISC_R_SUCCESS; if (headers) { - 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 (query->lookup->comments) { + 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; + } + 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]); + } + 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"); } - 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; - } - 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]); - 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"); } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && - headers ) { + headers && query->lookup->section_question) { printf("\n"); result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", - ISC_TRUE); + ISC_TRUE, query); if (result != ISC_R_SUCCESS) return (result); } - if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { - if (headers) + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]) && + query->lookup->section_answer ) { + if (headers && query->lookup->comments) printf("\n"); result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", - headers); + headers, query); if (result != ISC_R_SUCCESS) return (result); } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && - headers ) { - printf("\n"); + headers && query->lookup->section_authority) { + if (headers && query->lookup->comments) + printf("\n"); result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", - ISC_TRUE); + ISC_TRUE, query); if (result != ISC_R_SUCCESS) return (result); } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && - headers ) { - printf("\n"); + headers && query->lookup->section_additional) { + if (headers && query->lookup->comments) + printf("\n"); result = printsection(msg, DNS_SECTION_ADDITIONAL, - "ADDITIONAL", ISC_TRUE); + "ADDITIONAL", ISC_TRUE, query); if (result != ISC_R_SUCCESS) return (result); } - if ((tsig != NULL) && headers) { - printf("\n"); + if ((tsig != NULL) && headers && query->lookup->section_additional) { + if (headers && query->lookup->comments) + printf("\n"); result = printrdata(msg, tsig, tsigname, "PSEUDOSECTION TSIG", ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); } - if (headers) + if (headers && query->lookup->comments) printf("\n"); return (result); @@ -389,16 +466,50 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { } else if ((strcmp(argv[0],"+novc") == 0) && (!is_batchfile)) { tcp_mode = ISC_FALSE; - } else if ((strncmp(argv[0],"+time=",6) == 0) || - (strncmp(argv[0],"+tim=",5) == 0) || - (strncmp(argv[0],"+ti=",4) == 0)) { + } else if (strncmp(argv[0],"+time=",6) == 0) { timeout = atoi(&argv[0][6]); if (timeout <= 0) timeout = 1; - } else if (strncmp(argv[0],"+rec",6) == 0) { + } else if (strncmp(argv[0],"+tries=",7) == 0) { + tries = atoi(&argv[0][7]); + if (tries <= 0) + tries = 1; + } else if (strncmp(argv[0],"+ndots=",7) == 0) { + ndots = atoi(&argv[0][7]); + if (timeout <= 0) + timeout = 1; + } else if (strncmp(argv[0],"+rec",4) == 0) { recurse = ISC_TRUE; } else if (strncmp(argv[0],"+norec",6) == 0) { recurse = ISC_FALSE; + } else if (strncmp(argv[0],"+ns",3) == 0) { + ns_search_only = ISC_TRUE; + } else if (strncmp(argv[0],"+nons",6) == 0) { + ns_search_only = ISC_FALSE; + } else if (strncmp(argv[0],"+det",4) == 0) { + show_details = ISC_TRUE; + } else if (strncmp(argv[0],"+nodet",6) == 0) { + show_details = ISC_FALSE; + } else if (strncmp(argv[0],"+com",4) == 0) { + comments = ISC_TRUE; + } else if (strncmp(argv[0],"+nocom",6) == 0) { + comments = ISC_FALSE; + } else if (strncmp(argv[0],"+que",4) == 0) { + section_question = ISC_TRUE; + } else if (strncmp(argv[0],"+noque",6) == 0) { + section_question = ISC_FALSE; + } else if (strncmp(argv[0],"+ans",4) == 0) { + section_answer = ISC_TRUE; + } else if (strncmp(argv[0],"+noans",6) == 0) { + section_answer = ISC_FALSE; + } else if (strncmp(argv[0],"+add",4) == 0) { + section_additional = ISC_TRUE; + } else if (strncmp(argv[0],"+noadd",6) == 0) { + section_additional = ISC_FALSE; + } else if (strncmp(argv[0],"+aut",4) == 0) { + section_authority = ISC_TRUE; + } else if (strncmp(argv[0],"+noaut",6) == 0) { + section_authority = ISC_FALSE; #ifdef TWIDDLE } else if (strncmp(argv[0],"+twiddle",6) == 0) { twiddle = ISC_TRUE; @@ -419,6 +530,9 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { argv++; argc--; } + } else if (strncmp(argv[0],"-h",2) == 0) { + show_usage(); + exit (0); } else if (strncmp(argv[0],"-x",2) == 0) { n = sscanf(argv[1],"%d.%d.%d.%d", &adrs[0], &adrs[1], &adrs[2], &adrs[3]); @@ -443,12 +557,22 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->sendspace[0]=0; lookup->sendmsg=NULL; lookup->name=NULL; + lookup->oname=NULL; lookup->timer = NULL; lookup->xfr_q = NULL; lookup->use_my_server_list = ISC_FALSE; - lookup->ns_search_only = ISC_FALSE; + lookup->ns_search_only = ns_search_only; lookup->doing_xfr = ISC_FALSE; + lookup->identify = ISC_FALSE; + lookup->retries = tries; + lookup->comments = comments; + 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); + lookup->origin = NULL; + ISC_LIST_INIT(lookup->my_server_list); ISC_LIST_APPEND(lookup_list, lookup, link); have_host = ISC_TRUE; argv++; @@ -477,13 +601,23 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->sendspace[0]=0; lookup->sendmsg=NULL; lookup->name=NULL; + lookup->oname=NULL; lookup->timer = NULL; lookup->xfr_q = NULL; lookup->use_my_server_list = ISC_FALSE; lookup->doing_xfr = ISC_FALSE; - lookup->ns_search_only = ISC_FALSE; + lookup->ns_search_only = ns_search_only; + lookup->identify = ISC_FALSE; + lookup->retries = tries; + lookup->comments = comments; + 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); } @@ -517,12 +651,22 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->sendspace[0]=0; lookup->sendmsg=NULL; lookup->name=NULL; + lookup->oname=NULL; lookup->timer = NULL; lookup->xfr_q = NULL; lookup->use_my_server_list = ISC_FALSE; lookup->doing_xfr = ISC_FALSE; - lookup->ns_search_only = ISC_FALSE; + lookup->ns_search_only = ns_search_only; + lookup->identify = ISC_FALSE; + lookup->retries = tries; + lookup->comments = comments; + 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); + lookup->origin = NULL; + ISC_LIST_INIT(lookup->my_server_list); strcpy(lookup->textname,"."); strcpy(lookup->rttext, "NS"); lookup->rctext[0]=0; diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index cfea541aa8..fd93bf0239 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,8 +15,6 @@ * SOFTWARE. */ -#define TWIDDLE (random()%4+1) - #include #include @@ -59,9 +57,10 @@ extern int h_errno; 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, recurse = ISC_TRUE, have_ipv6 = ISC_FALSE, - free_now = ISC_FALSE; + free_now = ISC_FALSE, show_details = ISC_FALSE; #ifdef TWIDDLE isc_boolean_t twiddle = ISC_FALSE; #endif @@ -77,12 +76,26 @@ dns_name_t rootorg; char *rootspace[BUFSIZE]; isc_buffer_t rootbuf; int sendcount = 0; - -extern isc_boolean_t short_form; +int ndots = -1; +int tries = 2; static void free_lists(void); +static int +count_dots(char *string) { + char *s; + int i=0; + + s = string; + while (*s != 0) { + if (*s == '.') + i++; + s++; + } + return (i); +} + static void hex_dump(isc_buffer_t *b) { unsigned int len; @@ -109,11 +122,16 @@ fatal(char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); +#ifdef NEVER + isc_app_shutdown(); free_lists(); - isc_app_finish(); - if (mctx != NULL) + if (mctx != NULL) { +#ifdef MEMDEBUG + isc_mem_stats(mctx,stderr); +#endif isc_mem_destroy(&mctx); - + } +#endif exit(1); } @@ -216,21 +234,25 @@ setup_system(void) { FILE *fp; char *ptr; dig_server_t *srv; - - id = getpid() << 8; + dig_searchlist_t *search; + dig_lookup_t *l; + isc_boolean_t get_servers; debug ("setup_system()"); - if (server_list.head == NULL) { - fp = fopen (RESOLVCONF, "r"); - if (fp != NULL) { - while (fgets(rcinput, MXNAME, fp) != 0) { - ptr = strtok (rcinput, " \t"); - if (ptr != NULL && + id = getpid() << 8; + get_servers = (server_list.head == NULL); + fp = fopen (RESOLVCONF, "r"); + if (fp != NULL) { + while (fgets(rcinput, MXNAME, fp) != 0) { + ptr = strtok (rcinput, " \t\r\n"); + if (ptr != NULL) { + if (get_servers && strcasecmp(ptr, "nameserver") == 0) { - ptr = strtok (NULL, " \t"); + debug ("Got a nameserver line"); + ptr = strtok (NULL, " \t\r\n"); if (ptr != NULL) { srv = isc_mem_allocate(mctx, - sizeof(struct dig_server)); + sizeof(struct dig_server)); if (srv == NULL) fatal("Memory " "allocation " @@ -243,12 +265,48 @@ setup_system(void) { (server_list, srv, link); } + } else if (strcasecmp(ptr,"options") == 0) { + ptr = strtok(NULL, " \t\r\n"); + if (ptr != NULL) { + if ((strncasecmp(ptr, "ndots:", + 6) == 0) && + (ndots == -1)) { + ndots = atoi( + &ptr[6]); + debug ("ndots is " + "%d.", + ndots); + } + } + } else if (strcasecmp(ptr,"search") == 0) { + while ((ptr = strtok(NULL, " \t\r\n")) + != NULL) { + search = isc_mem_allocate( + mctx, sizeof(struct + dig_server)); + if (search == NULL) + fatal("Memory " + "allocation " + "failure."); + strncpy(search-> + origin, + ptr, + MXNAME - 1); + ISC_LIST_APPEND + (search_list, + search, + link); + } } + } - fclose (fp); } + fclose (fp); } + if (ndots == -1) + ndots = 1; + if (server_list.head == NULL) { srv = isc_mem_allocate(mctx, sizeof(dig_server_t)); if (srv == NULL) @@ -256,6 +314,12 @@ setup_system(void) { strcpy(srv->servername, "127.0.0.1"); ISC_LIST_APPEND(server_list, srv, link); } + + for (l = ISC_LIST_HEAD(lookup_list) ; + l != NULL; + l = ISC_LIST_NEXT(l, link) ) { + l -> origin = ISC_LIST_HEAD(search_list); + } } static void @@ -384,6 +448,7 @@ followup_lookup(dns_message_t *msg, dig_query_t *query) { 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; @@ -392,6 +457,21 @@ followup_lookup(dns_message_t *msg, dig_query_t *query) { 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); @@ -436,24 +516,101 @@ followup_lookup(dns_message_t *msg, dig_query_t *query) { return; /* We didn't get a NS. Just give up. */ } +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); + + debug ("next_origin()"); + debug ("Following up %s", query->lookup->textname); + + if (query->lookup->origin == NULL) { /*Then we just did rootorg; + there's nothing left. */ + debug ("Made it to the root whith nowhere to go."); + return; + } + 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->doing_xfr = ISC_FALSE; + lookup->identify = query->lookup->identify; + 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->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 (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."); + 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); + +} + + void setup_lookup(dig_lookup_t *lookup) { - isc_result_t result; + isc_result_t result, res2; int len; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; dig_server_t *serv; dig_query_t *query; - isc_textregion_t r; + isc_region_t r; + isc_textregion_t tr; isc_buffer_t b; + char store[MXNAME]; debug("setup_lookup()"); debug("Setting up for looking up %s @%ld->%ld", lookup->textname, (long int)lookup, (long int)lookup->link.next); - len=strlen(lookup->textname); - isc_buffer_init(&b, lookup->textname, len); - isc_buffer_add(&b, len); result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &lookup->sendmsg); @@ -465,14 +622,73 @@ setup_lookup(dig_lookup_t *lookup) { dns_name_init(lookup->name, NULL); isc_buffer_init(&lookup->namebuf, lookup->namespace, BUFSIZE); + isc_buffer_init(&lookup->onamebuf, lookup->onamespace, BUFSIZE); - result = dns_name_fromtext(lookup->name, &b, &rootorg, - ISC_FALSE, &lookup->namebuf); - if (result != ISC_R_SUCCESS) { - dns_message_puttempname(lookup->sendmsg, &lookup->name); - fatal("Aborting: %s is not a legal name syntax.", - lookup->textname); - } + if (count_dots(lookup->textname) >= ndots) + lookup->origin = NULL; /* Force root lookup */ + if (lookup->origin != NULL) { + debug ("Trying origin %s",lookup->origin->origin); + result = dns_message_gettempname(lookup->sendmsg, + &lookup->oname); + check_result(result, "dns_message_gettempname"); + dns_name_init(lookup->oname, NULL); + len=strlen(lookup->origin->origin); + isc_buffer_init(&b, lookup->origin->origin, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(lookup->oname, &b, &rootorg, + ISC_FALSE, &lookup->onamebuf); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(lookup->sendmsg, + &lookup->name); + dns_message_puttempname(lookup->sendmsg, + &lookup->oname); + fatal("Aborting: %s is not a legal name syntax. (%s)", + 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 (result != ISC_R_SUCCESS) { + dns_message_puttempname(lookup->sendmsg, + &lookup->name); + dns_message_puttempname(lookup->sendmsg, + &lookup->oname); + fatal("Aborting: %s is not a legal name syntax. (%s)", + lookup->textname, dns_result_totext(result)); + } + 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, &rootorg, + ISC_FALSE, &lookup->namebuf); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(lookup->sendmsg, + &lookup->name); + isc_buffer_init(&b, store, MXNAME); + res2 = dns_name_totext(&rootorg, ISC_FALSE, &b); + check_result (res2, "dns_name_totext"); + isc_buffer_usedregion (&b, &r); + fatal("Aborting: %s/%.*s is not a legal name syntax. " + "(%s)", lookup->textname, (int)r.length, + (char *)r.base, dns_result_totext(result)); + } + } + isc_buffer_init (&b, store, MXNAME); + dns_name_totext(lookup->name, ISC_FALSE, &b); + isc_buffer_usedregion (&b, &r); + trying((int)r.length, (char *)r.base, lookup); +#ifdef DEBUG + if (dns_name_isabsolute(lookup->name)) + debug ("This is an absolute name."); + else + debug ("This is a relative name (which is wrong)."); +#endif if (lookup->rctext[0] == 0) strcpy(lookup->rctext, "IN"); @@ -489,13 +705,13 @@ setup_lookup(dig_lookup_t *lookup) { if (!lookup->ns_search_only) { - r.base=lookup->rttext; - r.length=strlen(lookup->rttext); + tr.base=lookup->rttext; + tr.length=strlen(lookup->rttext); } else { - r.base="NS"; - r.length=2; + tr.base="NS"; + tr.length=2; } - result = dns_rdatatype_fromtext(&rdtype, &r); + result = dns_rdatatype_fromtext(&rdtype, &tr); check_result(result, "dns_rdatatype_fromtext"); if (rdtype == dns_rdatatype_axfr) { lookup->doing_xfr = ISC_TRUE; @@ -505,17 +721,18 @@ setup_lookup(dig_lookup_t *lookup) { tcp_mode = ISC_TRUE; } if (!lookup->ns_search_only) { - r.base=lookup->rctext; - r.length=strlen(lookup->rctext); + tr.base=lookup->rctext; + tr.length=strlen(lookup->rctext); } else { - r.base="IN"; - r.length=2; + tr.base="IN"; + tr.length=2; } - result = dns_rdataclass_fromtext(&rdclass, &r); + result = dns_rdataclass_fromtext(&rdclass, &tr); check_result(result, "dns_rdataclass_fromtext"); add_type(lookup->sendmsg, lookup->name, rdclass, rdtype); isc_buffer_init(&lookup->sendbuf, lookup->sendspace, COMMSIZE); + debug ("Starting to render the message"); result = dns_message_renderbegin(lookup->sendmsg, &lookup->sendbuf); check_result(result, "dns_message_renderbegin"); result = dns_message_rendersection(lookup->sendmsg, @@ -523,6 +740,7 @@ setup_lookup(dig_lookup_t *lookup) { check_result(result, "dns_message_rendersection"); result = dns_message_renderend(lookup->sendmsg); check_result(result, "dns_message_renderend"); + debug ("Done rendering."); lookup->pending = ISC_FALSE; @@ -570,6 +788,7 @@ cancel_lookup(dig_lookup_t *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)) { @@ -580,6 +799,50 @@ 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); + +void +send_udp(dig_lookup_t *lookup) { + dig_query_t *query; + isc_result_t result; + + debug ("send_udp()"); + + isc_interval_set(&lookup->interval, timeout, 0); + result = isc_timer_create(timermgr, isc_timertype_once, NULL, + &lookup->interval, task, connect_timeout, + lookup, &lookup->timer); + check_result(result, "isc_timer_create"); + for (query = ISC_LIST_HEAD(lookup->q); + query != NULL; + query = ISC_LIST_NEXT(query, link)) { + ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); + query->working = ISC_TRUE; + result = isc_socket_recvv(query->sock, &query->recvlist, 1, + task, recv_done, query); + check_result(result, "isc_socket_recvv"); + sendcount++; + debug("Sent count number %d", sendcount); +#ifdef TWIDDLE + if (twiddle) { + twiddlebuf(lookup->sendbuf); + } +#endif + ISC_LIST_ENQUEUE(query->sendlist, &lookup->sendbuf, link); + debug("Sending a request."); + result = isc_time_now(&query->time_sent); + check_result(result, "isc_time_now"); + result = isc_socket_sendtov(query->sock, &query->sendlist, + task, send_done, query, + &query->sockaddr, NULL); + check_result(result, "isc_socket_sendtov"); + } +} + /* connect_timeout is used for both UDP recieves and TCP connects. */ static void connect_timeout(isc_task_t *task, isc_event_t *event) { @@ -606,10 +869,18 @@ connect_timeout(isc_task_t *task, isc_event_t *event) { result = isc_sockaddr_totext(&q->sockaddr, b); check_result(result, "isc_sockaddr_totext"); isc_buffer_usedregion(b, &r); - printf(";; Connection to server %.*s for %s " - "failed: Connection timed out.\n", - (int)r.length, r.base, - q->lookup->textname); + if (q->lookup->retries > 1) + printf(";; Connection to server %.*s " + "for %s timed out. " + "Retrying.\n", + (int)r.length, r.base, + q->lookup->textname); + else + printf(";; Connection to server %.*s " + "for %s timed out. " + "Giving up.\n", + (int)r.length, r.base, + q->lookup->textname); } isc_socket_cancel(q->sock, task, ISC_SOCKCANCEL_ALL); @@ -619,11 +890,9 @@ connect_timeout(isc_task_t *task, isc_event_t *event) { isc_timer_detach(&lookup->timer); isc_buffer_free(&b); isc_event_free(&event); + debug ("Done with connect_timeout()"); } -static void -recv_done(isc_task_t *task, isc_event_t *event); - static void tcp_length_done(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent; @@ -724,6 +993,8 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) { sendcount++; if (!query->first_soa_rcvd) { debug("Sending a request."); + result = isc_time_now(&query->time_sent); + check_result(result, "isc_time_now"); result = isc_socket_sendv(query->sock, &query->sendlist, task, send_done, query); check_result(result, "isc_socket_recvv"); @@ -848,7 +1119,13 @@ recv_done(isc_task_t *task, isc_event_t *event) { if (query->lookup->xfr_q == query) { if (query->lookup->ns_search_only) followup_lookup(msg, query); - else { + else if ((msg->rcode != 0) && + (query->lookup->origin != NULL)) { + next_origin(msg, query); + if (show_details) { + printmessage(query, msg, ISC_TRUE); + } + } else { if (query->first_soa_rcvd && query->lookup->doing_xfr) printmessage(query, msg, ISC_FALSE); @@ -880,6 +1157,17 @@ 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); + check_result(result, + "isc_sockaddr_totext"); + isc_buffer_usedregion(&ab, &r); + received(b->used, r.length, r.base, + query); cancel_lookup(query->lookup); query->working = ISC_FALSE; check_next_lookup(query->lookup); @@ -893,18 +1181,20 @@ recv_done(isc_task_t *task, isc_event_t *event) { } } else { + 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"); + isc_buffer_usedregion(&ab, &r); + received(b->used, r.length, r.base, query); + } query->working = ISC_FALSE; cancel_lookup(query->lookup); } if (!query->lookup->pending) { - 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"); - isc_buffer_usedregion(&ab, &r); - if (!short_form) - printf("; Received %u bytes from %s\n", - b->used, r.base); check_next_lookup(query->lookup); } dns_message_destroy(&msg); @@ -914,26 +1204,26 @@ recv_done(isc_task_t *task, isc_event_t *event) { /* In truth, we should never get into the CANCELED routine, since the cancel_lookup() routine clears the pending flag. */ if (sevent->result == ISC_R_CANCELED) { + debug ("In cancel handler"); query->working = ISC_FALSE; query->waiting_connect = ISC_FALSE; check_next_lookup(query->lookup); isc_event_free(&event); return; } + isc_event_free(&event); fatal("recv_done got result %s", isc_result_totext(sevent->result)); } static void -get_address(char *hostname, 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 in6_addr in6; struct hostent *he; - char host[MXNAME]; debug("get_address()"); - sscanf (hostname, "%s", host); /* Force CR, etc... out */ if (have_ipv6 && inet_pton(AF_INET6, host, &in6) == 1) isc_sockaddr_fromin6(sockaddr, &in6, port); else if (inet_pton(AF_INET, host, &in4) == 1) @@ -942,7 +1232,7 @@ get_address(char *hostname, in_port_t port, isc_sockaddr_t *sockaddr) { he = gethostbyname(host); if (he == NULL) fatal("Couldn't look up your server host %s. errno=%d", - hostname, h_errno); + host, h_errno); INSIST(he->h_addrtype == AF_INET); isc_sockaddr_fromin(sockaddr, (struct in_addr *)(he->h_addr_list[0]), @@ -991,11 +1281,6 @@ do_lookup_udp(dig_lookup_t *lookup) { debug("I'm starting UDP with tcp_mode set!!!"); #endif lookup->pending = ISC_TRUE; - isc_interval_set(&lookup->interval, timeout, 0); - result = isc_timer_create(timermgr, isc_timertype_once, NULL, - &lookup->interval, task, connect_timeout, - lookup, &lookup->timer); - check_result(result, "isc_timer_create"); for (query = ISC_LIST_HEAD(lookup->q); query != NULL; @@ -1008,24 +1293,9 @@ do_lookup_udp(dig_lookup_t *lookup) { isc_sockaddr_pf(&query->sockaddr), isc_sockettype_udp, &query->sock) ; check_result(result, "isc_socket_create"); - ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); - result = isc_socket_recvv(query->sock, &query->recvlist, 1, - task, recv_done, query); - check_result(result, "isc_socket_recvv"); - sendcount++; - debug("Sent count number %d", sendcount); -#ifdef TWIDDLE - if (twiddle) { - twiddlebuf(lookup->sendbuf); - } -#endif - ISC_LIST_ENQUEUE(query->sendlist, &lookup->sendbuf, link); - debug("Sending a request."); - result = isc_socket_sendtov(query->sock, &query->sendlist, - task, send_done, query, - &query->sockaddr, NULL); - check_result(result, "isc_socket_sendtov"); } + + send_udp(lookup); } static void @@ -1034,15 +1304,21 @@ free_lists(void) { dig_lookup_t *l; dig_query_t *q; dig_server_t *s; + dig_searchlist_t *o; debug("free_lists()"); + if (free_now) + return; + free_now = ISC_TRUE; 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); @@ -1063,6 +1339,8 @@ 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); @@ -1077,12 +1355,23 @@ 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); + } dns_name_invalidate(&rootorg); if (socketmgr != NULL) isc_socketmgr_destroy(&socketmgr); @@ -1092,6 +1381,15 @@ free_lists(void) { isc_task_detach(&task); if (taskmgr != NULL) isc_taskmgr_destroy(&taskmgr); + +#ifdef MEMDEBUG + isc_mem_stats(mctx, stderr); +#endif + isc_app_finish(); + if (mctx != NULL) + isc_mem_destroy(&mctx); + + exit(0); } int @@ -1104,6 +1402,7 @@ main(int argc, char **argv) { ISC_LIST_INIT(lookup_list); ISC_LIST_INIT(server_list); + ISC_LIST_INIT(search_list); #ifdef TWIDDLE fp = fopen("/dev/urandom","r"); @@ -1130,12 +1429,5 @@ main(int argc, char **argv) { do_lookup_udp(lookup); isc_app_run(); free_lists(); -#ifdef MEMDEBUG - isc_mem_stats(mctx, stderr); -#endif - isc_app_finish(); - if (mctx != NULL) - isc_mem_destroy(&mctx); - - return (0); + exit (1); /* Should never get here. */ } diff --git a/bin/dig/host.c b/bin/dig/host.c index e49110ef05..69449df885 100644 --- a/bin/dig/host.c +++ b/bin/dig/host.c @@ -58,6 +58,7 @@ extern int h_errno; 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, recurse, @@ -74,6 +75,8 @@ extern dns_name_t rootorg; extern char *rootspace[BUFSIZE]; extern isc_buffer_t rootbuf; extern int sendcount; +extern int ndots; +extern int tries; isc_boolean_t short_form=ISC_TRUE, filter=ISC_FALSE, @@ -180,6 +183,30 @@ check_next_lookup (dig_lookup_t *lookup) { 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)) { + debug("Shutting Down.",stderr); + isc_app_shutdown(); + return; + } + + if (tcp_mode) { + setup_lookup(next); + do_lookup_tcp(next); + } else { + if (lookup->retries > 1) { + lookup->retries --; + send_udp(lookup); + } else { + setup_lookup(next); + do_lookup_udp(next); + } + } + +#ifdef NEVER next = ISC_LIST_NEXT (lookup, link); if (next == NULL) { debug ("Shutting Down."); @@ -192,14 +219,46 @@ check_next_lookup (dig_lookup_t *lookup) { do_lookup_tcp(next); else do_lookup_udp(next); - +#endif } static void show_usage() { - fatal ("Usage."); + fputs ( +"Usage: host [-aCdlrTwv] [-c class] [-N ndots] [-t type] [-W time]\n" +" [-R number] hostname [server]\n" +" -a is equivalent to -v -t *\n" +" -c specifies query class for non-IN data\n" +" -C compares SOA records on authorative nameservers\n" +" -d is equivalent to -v\n" +" -l lists all hosts in a domain, using AXFR\n" +" -N changes the number of dots allowed before root lookup is done\n" +" -r disables recursive processing\n" +" -R specifies number of retries for UDP packets\n" +" -t specifies the query type\n" +" -T enables TCP/IP mode\n" +" -v enables verbose output\n" +" -w specifies to wait forever for a reply\n" +" -W specifies how long to wait for a reply\n",stderr); + exit (0); } +void +received(int bytes, int frmsize, char *frm, dig_query_t *query) { + UNUSED(query); + if (!short_form) + printf("Received %u bytes from %.*s\n", + bytes, frmsize, frm); +} + +void +trying(int frmsize, char *frm, dig_lookup_t *lookup) { + UNUSED (lookup); + + if (!short_form) + printf ("Trying \"%.*s\"\n", frmsize, frm); +} + static void say_message(dns_name_t *name, char *msg, dns_rdata_t *rdata, dig_query_t *query) @@ -475,7 +534,8 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { UNUSED(is_batchfile); - while ((c = isc_commandline_parse(argc, argv,"lvwrdt:aTC")) != EOF) { + while ((c = isc_commandline_parse(argc, argv,"lvwrdt:c:aTCN:R:W:")) + != EOF) { switch (c) { case 'l': tcp_mode = ISC_TRUE; @@ -505,6 +565,16 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { 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; @@ -517,6 +587,11 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { nsfind = ISC_TRUE; showallsoa = ISC_TRUE; break; + case 'N': + debug ("Setting NDOTS to %s", + isc_commandline_argument); + ndots = atoi(isc_commandline_argument); + break; } } if (isc_commandline_index >= argc) { @@ -550,14 +625,18 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { 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->identify = ISC_FALSE; lookup->ns_search_only = showallsoa; lookup->use_my_server_list = ISC_FALSE; + lookup->retries = tries; 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; } diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 5d4995e8a8..f046cf8cf1 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -41,6 +41,7 @@ ISC_LANG_BEGINDECLS typedef struct dig_lookup dig_lookup_t; typedef struct dig_query dig_query_t; 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 */ @@ -53,17 +54,27 @@ struct dig_lookup { char rttext[MXRD]; /* rdata type text */ char rctext[MXRD]; /* rdata class text */ char namespace[BUFSIZE]; + char onamespace[BUFSIZE]; isc_buffer_t namebuf; + isc_buffer_t onamebuf; isc_buffer_t sendbuf; char sendspace[COMMSIZE]; dns_name_t *name; isc_timer_t *timer; isc_interval_t interval; dns_message_t *sendmsg; + dns_name_t *oname; ISC_LINK(dig_lookup_t) link; ISC_LIST(dig_query_t) q; ISC_LIST(dig_server_t) my_server_list; + dig_searchlist_t *origin; dig_query_t *xfr_q; + int retries; + isc_boolean_t comments, + section_question, + section_answer, + section_authority, + section_additional; }; struct dig_query { @@ -72,6 +83,7 @@ struct dig_query { waiting_connect, first_pass, first_soa_rcvd; + int retries; char *servname; isc_bufferlist_t sendlist, recvlist, @@ -85,6 +97,7 @@ struct dig_query { isc_socket_t *sock; ISC_LINK(dig_query_t) link; isc_sockaddr_t sockaddr; + isc_time_t time_sent; }; struct dig_server { @@ -92,6 +105,11 @@ struct dig_server { ISC_LINK(dig_server_t) link; }; +struct dig_searchlist { + char origin[MXNAME]; + ISC_LINK(dig_searchlist_t) link; +}; + /* Routines in dighost.c */ void fatal(char *format, ...) ; @@ -109,6 +127,8 @@ void do_lookup_udp (dig_lookup_t *lookup); void do_lookup_tcp (dig_lookup_t *lookup); +void +send_udp(dig_lookup_t *lookup); /* Routines needed in dig.c and host.c */ void @@ -117,7 +137,10 @@ 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); ISC_LANG_ENDDECLS