diff --git a/bin/dig/dig.c b/bin/dig/dig.c index c238a0731c..def75d7412 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_boolean_t tcp_mode, have_ipv6, show_details, - usesearch, trace; + usesearch, trace, qr; extern in_port_t port; extern unsigned int timeout; extern isc_mem_t *mctx; @@ -55,8 +55,18 @@ extern char fixeddomain[MXNAME]; #ifdef TWIDDLE extern isc_boolean_t twiddle; #endif +extern int exitcode; -isc_boolean_t short_form = ISC_FALSE; +isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE; + +isc_uint16_t bufsize = 0; +isc_boolean_t have_host = ISC_FALSE, identify = ISC_FALSE, + trace = ISC_FALSE, ns_search_only = ISC_FALSE, + forcecomment = ISC_FALSE, stats = ISC_TRUE, + 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; static char *opcodetext[] = { @@ -118,8 +128,11 @@ show_usage() { " +time=### (Set query timeout) [5]\n" " +tries=### (Set number of UDP attempts) [3]\n" " +domain=### (Set default domainname)\n" +" +bufsize=### (Set EDNS0 Max UDP packet size)\n" " +[no]search (Set whether to use searchlist)\n" +" +[no]defname (Set whether to use default domaon)\n" " +[no]recursive (Recursive mode)\n" +" +[no]aaonly (Set AA flag in query)\n" " +[no]details (Show details of all requests)\n" #ifdef TWIDDLE " +twiddle (Intentionally form bad requests)\n" @@ -132,6 +145,7 @@ show_usage() { " +[no]additional (Control display of additional)\n" " +[no]short (Disable everything except short\n" " form of answer)\n" +" +qr (Print question before sending)\n" " Additional d-opts subject to removal before release:\n" " +[no]nssearch (Search all authorative nameservers)\n" " +[no]identify (ID responders in short answers)\n" @@ -193,13 +207,13 @@ received(int bytes, int frmsize, char *frm, dig_query_t *query) { result = isc_time_now(&now); check_result (result, "isc_time_now"); - if (query->lookup->comments) { + if (query->lookup->stats) { 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); + printf(";; SERVER: %.*s\n", frmsize, frm); time (&tnow); - printf(";; When: %s\n", ctime(&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", @@ -209,10 +223,11 @@ received(int bytes, int frmsize, char *frm, dig_query_t *query) { void trying(int frmsize, char *frm, dig_lookup_t *lookup) { - if (lookup->comments && !short_form) - printf ("; Trying %.*s\n", frmsize, frm); -} + UNUSED (frmsize); + UNUSED (frm); + UNUSED (lookup); +} static void say_message(dns_rdata_t *rdata, dig_query_t *query) { @@ -367,8 +382,23 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { UNUSED (query); + /* + * Exitcode 9 means we timed out, but if we're printing a message, + * we much have recovered. Go ahead and reset it to code 0, and + * call this a success. + */ + 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, " @@ -475,6 +505,23 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { return (result); } +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 @@ -518,12 +565,6 @@ reorder_args(int argc, char *argv[]) { */ void parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { - isc_boolean_t have_host = ISC_FALSE, identify = ISC_FALSE, - trace = ISC_FALSE, ns_search_only = ISC_FALSE, - forcecomment = ISC_FALSE, - comments = ISC_TRUE, section_question = ISC_TRUE, - section_answer = ISC_TRUE, section_authority = ISC_TRUE, - section_additional = ISC_TRUE, recurse = ISC_TRUE; dig_server_t *srv = NULL; dig_lookup_t *lookup = NULL; char *batchname = NULL; @@ -533,14 +574,18 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { char *bargv[16]; int i, n; int adrs[4]; + int rc; + char **rv; - for (argc--, argv++; argc > 0; argc--, argv++) { - debug ("Main parsing %s", argv[0]); - if (strncmp(argv[0], "@", 1) == 0) { + rc = argc; + rv = argv; + for (rc--, rv++; rc > 0; rc--, rv++) { + debug ("Main parsing %s", rv[0]); + if (strncmp(rv[0], "@", 1) == 0) { srv=isc_mem_allocate(mctx, sizeof(struct dig_server)); if (srv == NULL) fatal("Memory allocation failure."); - strncpy(srv->servername, &argv[0][1], MXNAME-1); + strncpy(srv->servername, &rv[0][1], MXNAME-1); if (is_batchfile && have_host) { if (!lookup->use_my_server_list) { ISC_LIST_INIT (lookup-> @@ -553,41 +598,61 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { } else { ISC_LIST_APPEND(server_list, srv, link); } - } else if ((strcmp(argv[0], "+vc") == 0) + } else if ((strcmp(rv[0], "+vc") == 0) && (!is_batchfile)) { tcp_mode = ISC_TRUE; - } else if ((strcmp(argv[0], "+novc") == 0) + } else if ((strcmp(rv[0], "+novc") == 0) && (!is_batchfile)) { tcp_mode = ISC_FALSE; - } else if ((strcmp(argv[0], "+tcp") == 0) + } else if ((strcmp(rv[0], "+tcp") == 0) && (!is_batchfile)) { tcp_mode = ISC_TRUE; - } else if ((strcmp(argv[0], "+notcp") == 0) + } else if ((strcmp(rv[0], "+notcp") == 0) && (!is_batchfile)) { tcp_mode = ISC_FALSE; - } else if (strncmp(argv[0], "+domain=", 8) == 0) { - strncpy (fixeddomain, &argv[0][8], MXNAME); - } else if (strncmp(argv[0], "+sea", 4) == 0) { + } else if (strncmp(rv[0], "+domain=", 8) == 0) { + strncpy (fixeddomain, &rv[0][8], MXNAME); + } else if (strncmp(rv[0], "+sea", 4) == 0) { usesearch = ISC_TRUE; - } else if (strncmp(argv[0], "+nosea", 6) == 0) { + } else if (strncmp(rv[0], "+nosea", 6) == 0) { usesearch = ISC_FALSE; - } else if (strncmp(argv[0], "+time=", 6) == 0) { - timeout = atoi(&argv[0][6]); + } else if (strncmp(rv[0], "+defn", 5) == 0) { + defname = ISC_TRUE; + } else if (strncmp(rv[0], "+nodefn", 7) == 0) { + defname = ISC_FALSE; + } else if (strncmp(rv[0], "+time=", 6) == 0) { + timeout = atoi(&rv[0][6]); if (timeout <= 0) timeout = 1; - } else if (strncmp(argv[0], "+tries=", 7) == 0) { - tries = atoi(&argv[0][7]); + } else if (strncmp(rv[0], "+tries=", 7) == 0) { + tries = atoi(&rv[0][7]); if (tries <= 0) tries = 1; - } else if (strncmp(argv[0], "+ndots=", 7) == 0) { - ndots = atoi(&argv[0][7]); + } else if (strncmp(rv[0], "+buf=", 5) == 0) { + bufsize = atoi(&rv[0][5]); + if (bufsize <= 0) + bufsize = 0; + if (bufsize > COMMSIZE) + bufsize = COMMSIZE; + } else if (strncmp(rv[0], "+bufsize=", 9) == 0) { + bufsize = atoi(&rv[0][9]); + if (bufsize <= 0) + bufsize = 0; + if (bufsize > COMMSIZE) + bufsize = COMMSIZE; + } else if (strncmp(rv[0], "+ndots=", 7) == 0) { + ndots = atoi(&rv[0][7]); if (timeout <= 0) timeout = 1; - } else if (strncmp(argv[0], "+rec", 4) == 0) { + } else if (strncmp(rv[0], "+rec", 4) == 0) { recurse = ISC_TRUE; - } else if (strncmp(argv[0], "+norec", 6) == 0) { + } else if (strncmp(rv[0], "+norec", 6) == 0) { recurse = ISC_FALSE; - } else if (strncmp(argv[0], "+ns", 3) == 0) { + } else if (strncmp(rv[0], "+aa", 3) == 0) { + aaonly = ISC_TRUE; + } else if (strncmp(rv[0], "+noaa", 5) == 0) { + aaonly = ISC_FALSE; + } else if (strncmp(rv[0], "+ns", 3) == 0) { ns_search_only = ISC_TRUE; recurse = ISC_FALSE; identify = ISC_TRUE; @@ -598,66 +663,80 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { section_additional = ISC_FALSE; section_authority = ISC_FALSE; section_question = ISC_FALSE; - } else if (strncmp(argv[0], "+nons", 6) == 0) { + } else if (strncmp(rv[0], "+nons", 6) == 0) { ns_search_only = ISC_FALSE; - } else if (strncmp(argv[0], "+tr", 3) == 0) { + } else if (strncmp(rv[0], "+tr", 3) == 0) { trace = ISC_TRUE; recurse = ISC_FALSE; identify = ISC_TRUE; - if (!forcecomment) + if (!forcecomment) { comments = ISC_FALSE; + stats = ISC_FALSE; + } section_additional = ISC_FALSE; section_authority = ISC_FALSE; section_question = ISC_FALSE; show_details = ISC_TRUE; - } else if (strncmp(argv[0], "+notr", 6) == 0) { + } else if (strncmp(rv[0], "+notr", 6) == 0) { trace = ISC_FALSE; - } else if (strncmp(argv[0], "+det", 4) == 0) { + } else if (strncmp(rv[0], "+det", 4) == 0) { show_details = ISC_TRUE; - } else if (strncmp(argv[0], "+nodet", 6) == 0) { + } else if (strncmp(rv[0], "+nodet", 6) == 0) { show_details = ISC_FALSE; - } else if (strncmp(argv[0], "+sho", 4) == 0) { + } else if (strncmp(rv[0], "+sho", 4) == 0) { short_form = ISC_TRUE; - if (!forcecomment) + if (!forcecomment) { comments = ISC_FALSE; + stats = ISC_FALSE; + } + printcmd = ISC_FALSE; section_additional = ISC_FALSE; section_authority = ISC_FALSE; section_question = ISC_FALSE; - } else if (strncmp(argv[0], "+nosho", 6) == 0) { + } else if (strncmp(rv[0], "+nosho", 6) == 0) { short_form = ISC_FALSE; - } else if (strncmp(argv[0], "+id", 3) == 0) { + } else if (strncmp(rv[0], "+id", 3) == 0) { identify = ISC_TRUE; - } else if (strncmp(argv[0], "+noid", 5) == 0) { + } else if (strncmp(rv[0], "+noid", 5) == 0) { identify = ISC_FALSE; - } else if (strncmp(argv[0], "+com", 4) == 0) { + } else if (strncmp(rv[0], "+com", 4) == 0) { comments = ISC_TRUE; forcecomment = ISC_TRUE; - } else if (strncmp(argv[0], "+nocom", 6) == 0) { + } else if (strncmp(rv[0], "+nocom", 6) == 0) { comments = ISC_FALSE; forcecomment = ISC_FALSE; - } else if (strncmp(argv[0], "+que", 4) == 0) { + stats = ISC_FALSE; + } else if (strncmp(rv[0], "+sta", 4) == 0) { + stats = ISC_TRUE; + } else if (strncmp(rv[0], "+nosta", 6) == 0) { + stats = ISC_FALSE; + } else if (strncmp(rv[0], "+qr", 3) == 0) { + qr = ISC_TRUE; + } else if (strncmp(rv[0], "+noqr", 5) == 0) { + qr = ISC_FALSE; + } else if (strncmp(rv[0], "+que", 4) == 0) { section_question = ISC_TRUE; - } else if (strncmp(argv[0], "+noque", 6) == 0) { + } else if (strncmp(rv[0], "+noque", 6) == 0) { section_question = ISC_FALSE; - } else if (strncmp(argv[0], "+ans", 4) == 0) { + } else if (strncmp(rv[0], "+ans", 4) == 0) { section_answer = ISC_TRUE; - } else if (strncmp(argv[0], "+noans", 6) == 0) { + } else if (strncmp(rv[0], "+noans", 6) == 0) { section_answer = ISC_FALSE; - } else if (strncmp(argv[0], "+add", 4) == 0) { + } else if (strncmp(rv[0], "+add", 4) == 0) { section_additional = ISC_TRUE; - } else if (strncmp(argv[0], "+noadd", 6) == 0) { + } else if (strncmp(rv[0], "+noadd", 6) == 0) { section_additional = ISC_FALSE; - } else if (strncmp(argv[0], "+aut", 4) == 0) { + } else if (strncmp(rv[0], "+aut", 4) == 0) { section_authority = ISC_TRUE; - } else if (strncmp(argv[0], "+noaut", 6) == 0) { + } else if (strncmp(rv[0], "+noaut", 6) == 0) { section_authority = ISC_FALSE; - } else if (strncmp(argv[0], "+all", 4) == 0) { + } else if (strncmp(rv[0], "+all", 4) == 0) { section_question = ISC_TRUE; section_authority = ISC_TRUE; section_answer = ISC_TRUE; section_additional = ISC_TRUE; comments = ISC_TRUE; - } else if (strncmp(argv[0], "+noall", 6) == 0) { + } else if (strncmp(rv[0], "+noall", 6) == 0) { section_question = ISC_FALSE; section_authority = ISC_FALSE; section_answer = ISC_FALSE; @@ -665,54 +744,63 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { comments = ISC_FALSE; #ifdef TWIDDLE - } else if (strncmp(argv[0], "+twiddle", 6) == 0) { + } else if (strncmp(rv[0], "+twiddle", 6) == 0) { twiddle = ISC_TRUE; #endif - } else if (strncmp(argv[0], "-c", 2) == 0) { + } else if (strncmp(rv[0], "-c", 2) == 0) { if (have_host) { - if (argv[0][2]!=0) { - strncpy(lookup->rctext, &argv[0][2], + if (rv[0][2]!=0) { + strncpy(lookup->rctext, &rv[0][2], MXRD); } else { - strncpy(lookup->rctext, argv[1], + strncpy(lookup->rctext, rv[1], MXRD); - argv++; - argc--; + rv++; + rc--; } } - } else if (strncmp(argv[0], "-t", 2) == 0) { + } else if (strncmp(rv[0], "-t", 2) == 0) { if (have_host) { - if (argv[0][2]!=0) { - strncpy(lookup->rttext, &argv[0][2], + if (rv[0][2]!=0) { + strncpy(lookup->rttext, &rv[0][2], MXRD); } else { - strncpy(lookup->rttext, argv[1], + strncpy(lookup->rttext, rv[1], MXRD); - argv++; - argc--; + rv++; + rc--; } } - } else if (strncmp(argv[0], "-f", 2) == 0) { - if (argv[0][2]!=0) { - batchname=&argv[0][2]; + } else if (strncmp(rv[0], "-f", 2) == 0) { + if (rv[0][2]!=0) { + batchname=&rv[0][2]; } else { - batchname=argv[1]; - argv++; - argc--; + batchname=rv[1]; + rv++; + rc--; } - } else if (strncmp(argv[0], "-p", 2) == 0) { - if (argv[0][2]!=0) { - port=atoi(&argv[0][2]); + } else if (strncmp(rv[0], "-p", 2) == 0) { + if (rv[0][2]!=0) { + port=atoi(&rv[0][2]); } else { - port=atoi(argv[1]); - argv++; - argc--; + port=atoi(rv[1]); + rv++; + rc--; } - } else if (strncmp(argv[0], "-h", 2) == 0) { + } else if (strncmp(rv[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], + exit (exitcode); + } else if (strncmp(rv[0], "-x", 2) == 0) { + /* + *XXXMWS Only works for ipv4 now. + * Can't use inet_pton here, since we allow + * partial addresses. + */ + if (rc == 1) { + show_usage(); + exit (exitcode); + } + n = sscanf(rv[1], "%d.%d.%d.%d", &adrs[0], &adrs[1], &adrs[2], &adrs[3]); if (n == 0) show_usage(); @@ -747,11 +835,15 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->trace_root = trace; lookup->ns_search_only = ns_search_only; lookup->doing_xfr = ISC_FALSE; + lookup->defname = ISC_FALSE; lookup->identify = identify; lookup->recurse = recurse; + lookup->aaonly = aaonly; lookup->retries = tries; + lookup->udpsize = bufsize; lookup->nsfound = 0; lookup->comments = comments; + lookup->stats = stats; lookup->section_question = section_question; lookup->section_answer = section_answer; lookup->section_authority = section_authority; @@ -761,16 +853,16 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { ISC_LIST_INIT(lookup->my_server_list); ISC_LIST_APPEND(lookup_list, lookup, link); have_host = ISC_TRUE; - argv++; - argc--; + rv++; + rc--; } else { if (have_host) { ENSURE(lookup != NULL); - if (istype(argv[0])) { - strncpy(lookup->rttext, argv[0], MXRD); + if (istype(rv[0])) { + strncpy(lookup->rttext, rv[0], MXRD); continue; - } else if (isclass(argv[0])) { - strncpy(lookup->rctext, argv[0], + } else if (isclass(rv[0])) { + strncpy(lookup->rctext, rv[0], MXRD); continue; } @@ -783,7 +875,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { if (lookup == NULL) fatal("Memory allocation failure."); lookup->pending = ISC_FALSE; - strncpy(lookup->textname, argv[0], MXNAME-1); + strncpy(lookup->textname, rv[0], MXNAME-1); lookup->rttext[0]=0; lookup->rctext[0]=0; lookup->namespace[0]=0; @@ -796,14 +888,18 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->origin = NULL; lookup->use_my_server_list = ISC_FALSE; lookup->doing_xfr = ISC_FALSE; + lookup->defname = 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->comments = comments; + lookup->stats = stats; lookup->section_question = section_question; lookup->section_answer = section_answer; lookup->section_authority = section_authority; @@ -820,6 +916,8 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { fp = fopen(batchname, "r"); if (fp == NULL) { perror(batchname); + if (exitcode < 10) + exitcode = 10; fatal("Couldn't open specified batch file."); } while (fgets(batchline, MXNAME, fp) != 0) { @@ -856,14 +954,18 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->origin = NULL; lookup->use_my_server_list = ISC_FALSE; lookup->doing_xfr = ISC_FALSE; + lookup->defname = 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->comments = comments; + lookup->stats = stats; lookup->section_question = section_question; lookup->section_answer = section_answer; lookup->section_authority = section_authority; @@ -875,4 +977,5 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->rctext[0]=0; ISC_LIST_APPEND(lookup_list, lookup, link); } + printgreeting (argc, argv); } diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index f697103554..0cd9dfa539 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,6 +15,15 @@ * SOFTWARE. */ +/* + * Notice to programmers: Do not use this code as an example of how to + * use the ISC library to perform DNS lookups. Dig and Host both operate + * on the request level, since they allow fine-tuning of output and are + * intended as debugging tools. As a result, they perform many of the + * functions which could be better handled using the dns_resolver + * functions in most applications. + */ + #include #include @@ -34,6 +43,7 @@ extern int h_errno; #include #include #include +#include #include #include @@ -43,7 +53,8 @@ ISC_LIST(dig_server_t) server_list; ISC_LIST(dig_searchlist_t) search_list; isc_boolean_t tcp_mode = ISC_FALSE, have_ipv6 = ISC_FALSE, - free_now = ISC_FALSE, show_details = ISC_FALSE, usesearch=ISC_TRUE; + free_now = ISC_FALSE, show_details = ISC_FALSE, usesearch=ISC_TRUE, + qr = ISC_FALSE; #ifdef TWIDDLE isc_boolean_t twiddle = ISC_FALSE; #endif @@ -54,7 +65,6 @@ isc_taskmgr_t *taskmgr = NULL; isc_task_t *task = NULL; isc_timermgr_t *timermgr = NULL; isc_socketmgr_t *socketmgr = NULL; -dns_messageid_t id; char *rootspace[BUFSIZE]; isc_buffer_t rootbuf; int sendcount = 0; @@ -62,6 +72,7 @@ int ndots = -1; int tries = 3; int lookup_counter = 0; char fixeddomain[MXNAME]=""; +int exitcode = 9; static void free_lists(void); @@ -116,7 +127,7 @@ fatal(char *format, ...) { isc_mem_destroy(&mctx); } #endif - exit(1); + exit(exitcode); } #ifdef DEBUG @@ -140,8 +151,10 @@ debug(char *format, ...) { void check_result(isc_result_t result, char *msg) { - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + exitcode = 1; fatal("%s: %s", msg, isc_result_totext(result)); + } } isc_boolean_t @@ -235,7 +248,12 @@ setup_system(void) { } debug ("setup_system()"); - id = getpid() << 8; + /* + * 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); get_servers = (server_list.head == NULL); fp = fopen (RESOLVCONF, "r"); if (fp != NULL) { @@ -380,6 +398,34 @@ setup_libs(void) { isc_buffer_add(&b, 1); } +static void +add_opt (dns_message_t *msg, isc_uint16_t udpsize) { + dns_rdataset_t *rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdata_t *rdata = NULL; + isc_result_t result; + + result = dns_message_gettemprdataset(msg, &rdataset); + check_result (result, "dns_message_gettemprdataset"); + dns_rdataset_init (rdataset); + result = dns_message_gettemprdatalist(msg, &rdatalist); + check_result (result, "dns_message_gettemprdatalist"); + result = dns_message_gettemprdata(msg, &rdata); + check_result (result, "dns_message_gettemprdata"); + + rdatalist->type = dns_rdatatype_opt; + rdatalist->covers = 0; + rdatalist->rdclass = udpsize; + rdatalist->ttl = 0; + rdata->data = NULL; + rdata->length = 0; + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + dns_rdatalist_tordataset(rdatalist, rdataset); + result = dns_message_setopt(msg, rdataset); + check_result (result, "dns_message_setopt"); +} + static void add_type(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, dns_rdatatype_t rdtype) @@ -492,11 +538,17 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, lookup->xfr_q = NULL; lookup->origin = NULL; 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; @@ -516,6 +568,9 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, lookup->comments = query->lookup-> comments; + lookup->stats = + query->lookup-> + stats; lookup->section_question = query->lookup-> section_question; @@ -620,16 +675,20 @@ next_origin(dns_message_t *msg, dig_query_t *query) { lookup->timer = NULL; lookup->xfr_q = NULL; lookup->doing_xfr = ISC_FALSE; + 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; @@ -700,7 +759,7 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&lookup->namebuf, lookup->namespace, BUFSIZE); isc_buffer_init(&lookup->onamebuf, lookup->onamespace, BUFSIZE); - if (count_dots(lookup->textname) >= ndots) + if ((count_dots(lookup->textname) >= ndots) || lookup->defname) lookup->origin = NULL; /* Force root lookup */ debug ("lookup->origin = %lx", (long int)lookup->origin); if (lookup->origin != NULL) { @@ -792,7 +851,7 @@ setup_lookup(dig_lookup_t *lookup) { if (lookup->rttext[0] == 0) strcpy(lookup->rttext, "A"); - lookup->sendmsg->id = id++; + lookup->sendmsg->id = random(); lookup->sendmsg->opcode = dns_opcode_query; /* If this is a trace request, completely disallow recursion, since * it's meaningless for traces */ @@ -801,6 +860,11 @@ setup_lookup(dig_lookup_t *lookup) { lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; } + if (lookup->aaonly) { + debug ("AA query"); + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA; + } + dns_message_addname(lookup->sendmsg, lookup->name, DNS_SECTION_QUESTION); @@ -836,6 +900,9 @@ setup_lookup(dig_lookup_t *lookup) { debug ("Starting to render the message"); result = dns_message_renderbegin(lookup->sendmsg, &lookup->sendbuf); check_result(result, "dns_message_renderbegin"); + if (lookup->udpsize > 0) { + add_opt(lookup->sendmsg, lookup->udpsize); + } result = dns_message_rendersection(lookup->sendmsg, DNS_SECTION_QUESTION, 0); check_result(result, "dns_message_rendersection"); @@ -871,6 +938,10 @@ setup_lookup(dig_lookup_t *lookup) { ISC_LIST_ENQUEUE(lookup->q, query, link); } + if (!ISC_LIST_EMPTY(lookup->q) && qr) { + printmessage (ISC_LIST_HEAD(lookup->q), lookup->sendmsg, + ISC_TRUE); + } } static void @@ -977,12 +1048,13 @@ connect_timeout(isc_task_t *task, isc_event_t *event) { (int)r.length, r.base, q->lookup->textname, q->lookup->retries-1); - else + 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); @@ -1135,6 +1207,8 @@ connect_done(isc_task_t *task, isc_event_t *event) { printf(";; Connection to server %.*s for %s failed: %s.\n", (int)r.length, r.base, query->lookup->textname, isc_result_totext(sevent->result)); + if (exitcode < 9) + exitcode = 9; isc_buffer_free(&b); query->working = ISC_FALSE; query->waiting_connect = ISC_FALSE; @@ -1502,7 +1576,7 @@ free_lists(void) { if (mctx != NULL) isc_mem_destroy(&mctx); - exit(0); + exit(exitcode); } int @@ -1544,5 +1618,5 @@ main(int argc, char **argv) { /* * Should never get here. */ - return (1); + return (2); } diff --git a/bin/dig/host.c b/bin/dig/host.c index 4c45c5ca34..6fd7313ed7 100644 --- a/bin/dig/host.c +++ b/bin/dig/host.c @@ -53,6 +53,7 @@ extern int sendcount; extern int ndots; extern int tries; extern int lookup_counter; +extern int exitcode; isc_boolean_t short_form=ISC_TRUE, filter=ISC_FALSE, @@ -202,7 +203,7 @@ show_usage() { " -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); + exit (exitcode); } void @@ -391,6 +392,14 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { UNUSED (headers); + /* + * Exitcode 9 means we timed out, but if we're printing a message, + * we much have recovered. Go ahead and reset it to code 0, and + * call this a success. + */ + if (exitcode == 9) + exitcode = 0; + if (msg->rcode != 0) { result = isc_buffer_allocate(mctx, &b, MXNAME); check_result (result, "isc_buffer_allocate"); @@ -509,7 +518,8 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { char queryclass[32]=""; dig_server_t *srv; dig_lookup_t *lookup; - int c; + int i, c, n, adrs[4]; + char store[MXNAME]; UNUSED(is_batchfile); @@ -588,11 +598,6 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { ISC_LIST_APPEND(server_list, srv, link); } - if (querytype[0] == 0) - strcpy (querytype, "a"); - if (queryclass[0] == 0) - strcpy (queryclass, "in"); - lookup_counter++; if (lookup_counter > LOOKUP_LIMIT) fatal ("Too many lookups."); @@ -601,7 +606,32 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { if (lookup == NULL) fatal ("Memory allocation failure."); lookup->pending = ISC_FALSE; - strncpy (lookup->textname, hostname, MXNAME); + /* + * 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); lookup->namespace[0]=0; @@ -613,6 +643,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { lookup->xfr_q = NULL; lookup->origin = NULL; lookup->doing_xfr = ISC_FALSE; + lookup->defname = ISC_FALSE; lookup->identify = ISC_FALSE; lookup->recurse = recursion; lookup->ns_search_only = showallsoa; diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 42f5f66498..e5ebed8d41 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -33,7 +33,7 @@ #define MXNAME 256 #define MXRD 32 #define BUFSIZE 512 -#define COMMSIZE 65536 +#define COMMSIZE 32767 #define RESOLVCONF "/etc/resolv.conf" #define LOOKUP_LIMIT 64 /* Lookup_limit is just a limiter, keeping too many lookups from being @@ -62,8 +62,10 @@ struct dig_lookup { use_my_server_list, identify, recurse, + aaonly, trace, - trace_root; + trace_root, + defname; char textname[MXNAME]; /* Name we're going to be looking up */ char rttext[MXRD]; /* rdata type text */ char rctext[MXRD]; /* rdata class text */ @@ -85,7 +87,9 @@ struct dig_lookup { dig_query_t *xfr_q; int retries; int nsfound; + isc_uint16_t udpsize; isc_boolean_t comments, + stats, section_question, section_answer, section_authority,