diff options
Diffstat (limited to 'contrib/bind9/bin/dig/dig.c')
-rw-r--r-- | contrib/bind9/bin/dig/dig.c | 1797 |
1 files changed, 0 insertions, 1797 deletions
diff --git a/contrib/bind9/bin/dig/dig.c b/contrib/bind9/bin/dig/dig.c deleted file mode 100644 index ba5d87b..0000000 --- a/contrib/bind9/bin/dig/dig.c +++ /dev/null @@ -1,1797 +0,0 @@ -/* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: dig.c,v 1.186.18.29 2007/08/28 07:19:55 tbox Exp $ */ - -/*! \file */ - -#include <config.h> -#include <stdlib.h> -#include <time.h> -#include <ctype.h> - -#include <isc/app.h> -#include <isc/netaddr.h> -#include <isc/parseint.h> -#include <isc/print.h> -#include <isc/string.h> -#include <isc/util.h> -#include <isc/task.h> - -#include <dns/byaddr.h> -#include <dns/fixedname.h> -#include <dns/masterdump.h> -#include <dns/message.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataset.h> -#include <dns/rdatatype.h> -#include <dns/rdataclass.h> -#include <dns/result.h> -#include <dns/tsig.h> - -#include <bind9/getaddresses.h> - -#include <dig/dig.h> - -#define ADD_STRING(b, s) { \ - if (strlen(s) >= isc_buffer_availablelength(b)) \ - return (ISC_R_NOSPACE); \ - else \ - isc_buffer_putstr(b, s); \ -} - -#define DIG_MAX_ADDRESSES 20 - -dig_lookup_t *default_lookup = NULL; - -static char *batchname = NULL; -static FILE *batchfp = NULL; -static char *argv0; -static int addresscount = 0; - -static char domainopt[DNS_NAME_MAXTEXT]; - -static isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE, - ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE, - multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE; - -/*% opcode text */ -static const char *opcodetext[] = { - "QUERY", - "IQUERY", - "STATUS", - "RESERVED3", - "NOTIFY", - "UPDATE", - "RESERVED6", - "RESERVED7", - "RESERVED8", - "RESERVED9", - "RESERVED10", - "RESERVED11", - "RESERVED12", - "RESERVED13", - "RESERVED14", - "RESERVED15" -}; - -/*% return code text */ -static const char *rcodetext[] = { - "NOERROR", - "FORMERR", - "SERVFAIL", - "NXDOMAIN", - "NOTIMP", - "REFUSED", - "YXDOMAIN", - "YXRRSET", - "NXRRSET", - "NOTAUTH", - "NOTZONE", - "RESERVED11", - "RESERVED12", - "RESERVED13", - "RESERVED14", - "RESERVED15", - "BADVERS" -}; - -/*% print usage */ -static void -print_usage(FILE *fp) { - fputs( -"Usage: dig [@global-server] [domain] [q-type] [q-class] {q-opt}\n" -" {global-d-opt} host [@local-server] {local-d-opt}\n" -" [ host [@local-server] {local-d-opt} [...]]\n", fp); -} - -static void -usage(void) { - print_usage(stderr); - fputs("\nUse \"dig -h\" (or \"dig -h | more\") " - "for complete list of options\n", stderr); - exit(1); -} - -/*% version */ -static void -version(void) { - fputs("DiG " VERSION "\n", stderr); -} - -/*% help */ -static void -help(void) { - print_usage(stdout); - fputs( -"Where: domain is in the Domain Name System\n" -" q-class is one of (in,hs,ch,...) [default: in]\n" -" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n" -" (Use ixfr=version for type ixfr)\n" -" q-opt is one of:\n" -" -x dot-notation (shortcut for in-addr lookups)\n" -" -i (IP6.INT reverse IPv6 lookups)\n" -" -f filename (batch mode)\n" -" -b address[#port] (bind to source address/port)\n" -" -p port (specify port number)\n" -" -q name (specify query name)\n" -" -t type (specify query type)\n" -" -c class (specify query class)\n" -" -k keyfile (specify tsig key file)\n" -" -y [hmac:]name:key (specify named base64 tsig key)\n" -" -4 (use IPv4 query transport only)\n" -" -6 (use IPv6 query transport only)\n" -" d-opt is of the form +keyword[=value], where keyword is:\n" -" +[no]vc (TCP mode)\n" -" +[no]tcp (TCP mode, alternate syntax)\n" -" +time=### (Set query timeout) [5]\n" -" +tries=### (Set number of UDP attempts) [3]\n" -" +retry=### (Set number of UDP retries) [2]\n" -" +domain=### (Set default domainname)\n" -" +bufsize=### (Set EDNS0 Max UDP packet size)\n" -" +ndots=### (Set NDOTS value)\n" -" +edns=### (Set EDNS version)\n" -" +[no]search (Set whether to use searchlist)\n" -" +[no]showsearch (Search with intermediate results)\n" -" +[no]defname (Ditto)\n" -" +[no]recurse (Recursive mode)\n" -" +[no]ignore (Don't revert to TCP for TC responses.)" -"\n" -" +[no]fail (Don't try next server on SERVFAIL)\n" -" +[no]besteffort (Try to parse even illegal messages)\n" -" +[no]aaonly (Set AA flag in query (+[no]aaflag))\n" -" +[no]adflag (Set AD flag in query)\n" -" +[no]cdflag (Set CD flag in query)\n" -" +[no]cl (Control display of class in records)\n" -" +[no]cmd (Control display of command line)\n" -" +[no]comments (Control display of comment lines)\n" -" +[no]question (Control display of question)\n" -" +[no]answer (Control display of answer)\n" -" +[no]authority (Control display of authority)\n" -" +[no]additional (Control display of additional)\n" -" +[no]stats (Control display of statistics)\n" -" +[no]short (Disable everything except short\n" -" form of answer)\n" -" +[no]ttlid (Control display of ttls in records)\n" -" +[no]all (Set or clear all display flags)\n" -" +[no]qr (Print question before sending)\n" -" +[no]nssearch (Search all authoritative nameservers)\n" -" +[no]identify (ID responders in short answers)\n" -" +[no]trace (Trace delegation down from root)\n" -" +[no]dnssec (Request DNSSEC records)\n" -#ifdef DIG_SIGCHASE -" +[no]sigchase (Chase DNSSEC signatures)\n" -" +trusted-key=#### (Trusted Key when chasing DNSSEC sigs)\n" -#if DIG_SIGCHASE_TD -" +[no]topdown (Do DNSSEC validation top down mode)\n" -#endif -#endif -" +[no]multiline (Print records in an expanded format)\n" -" global d-opts and servers (before host name) affect all queries.\n" -" local d-opts and servers (after host name) affect only that lookup.\n" -" -h (print help and exit)\n" -" -v (print version and exit)\n", - stdout); -} - -/*% - * Callback from dighost.c to print the received message. - */ -void -received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { - isc_uint64_t diff; - isc_time_t now; - time_t tnow; - char fromtext[ISC_SOCKADDR_FORMATSIZE]; - - isc_sockaddr_format(from, fromtext, sizeof(fromtext)); - - TIME_NOW(&now); - - if (query->lookup->stats && !short_form) { - diff = isc_time_microdiff(&now, &query->time_sent); - printf(";; Query time: %ld msec\n", (long int)diff/1000); - printf(";; SERVER: %s(%s)\n", fromtext, query->servname); - time(&tnow); - printf(";; WHEN: %s", ctime(&tnow)); - if (query->lookup->doing_xfr) { - printf(";; XFR size: %u records (messages %u, " - "bytes %" ISC_PRINT_QUADFORMAT "u)\n", - query->rr_count, query->msg_count, - query->byte_count); - } else { - printf(";; MSG SIZE rcvd: %u\n", bytes); - - } - if (key != NULL) { - if (!validated) - puts(";; WARNING -- Some TSIG could not " - "be validated"); - } - if ((key == NULL) && (keysecret[0] != 0)) { - puts(";; WARNING -- TSIG key was not used."); - } - puts(""); - } else if (query->lookup->identify && !short_form) { - diff = isc_time_microdiff(&now, &query->time_sent); - printf(";; Received %" ISC_PRINT_QUADFORMAT "u bytes " - "from %s(%s) in %d ms\n\n", - query->lookup->doing_xfr ? - query->byte_count : (isc_uint64_t)bytes, - fromtext, query->servname, - (int)diff/1000); - } -} - -/* - * Callback from dighost.c to print that it is trying a server. - * Not used in dig. - * XXX print_trying - */ -void -trying(char *frm, dig_lookup_t *lookup) { - UNUSED(frm); - UNUSED(lookup); -} - -/*% - * Internal print routine used to print short form replies. - */ -static isc_result_t -say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) { - isc_result_t result; - isc_uint64_t diff; - isc_time_t now; - char store[sizeof("12345678901234567890")]; - - if (query->lookup->trace || query->lookup->ns_search_only) { - result = dns_rdatatype_totext(rdata->type, buf); - if (result != ISC_R_SUCCESS) - return (result); - ADD_STRING(buf, " "); - } - result = dns_rdata_totext(rdata, NULL, buf); - check_result(result, "dns_rdata_totext"); - if (query->lookup->identify) { - TIME_NOW(&now); - diff = isc_time_microdiff(&now, &query->time_sent); - ADD_STRING(buf, " from server "); - ADD_STRING(buf, query->servname); - snprintf(store, 19, " in %d ms.", (int)diff/1000); - ADD_STRING(buf, store); - } - ADD_STRING(buf, "\n"); - return (ISC_R_SUCCESS); -} - -/*% - * short_form message print handler. Calls above say_message() - */ -static isc_result_t -short_answer(dns_message_t *msg, dns_messagetextflag_t flags, - isc_buffer_t *buf, dig_query_t *query) -{ - dns_name_t *name; - dns_rdataset_t *rdataset; - isc_buffer_t target; - isc_result_t result, loopresult; - dns_name_t empty_name; - char t[4096]; - dns_rdata_t rdata = DNS_RDATA_INIT; - - UNUSED(flags); - - dns_name_init(&empty_name, NULL); - result = dns_message_firstname(msg, DNS_SECTION_ANSWER); - if (result == ISC_R_NOMORE) - return (ISC_R_SUCCESS); - else if (result != ISC_R_SUCCESS) - return (result); - - for (;;) { - name = NULL; - dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); - - isc_buffer_init(&target, t, sizeof(t)); - - 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); - result = say_message(&rdata, query, - buf); - check_result(result, "say_message"); - loopresult = dns_rdataset_next(rdataset); - dns_rdata_reset(&rdata); - } - } - result = dns_message_nextname(msg, DNS_SECTION_ANSWER); - if (result == ISC_R_NOMORE) - break; - else if (result != ISC_R_SUCCESS) - return (result); - } - - return (ISC_R_SUCCESS); -} -#ifdef DIG_SIGCHASE -isc_result_t -printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, - isc_buffer_t *target) -{ - isc_result_t result; - dns_master_style_t *style = NULL; - unsigned int styleflags = 0; - - if (rdataset == NULL || owner_name == NULL || target == NULL) - return(ISC_FALSE); - - styleflags |= DNS_STYLEFLAG_REL_OWNER; - if (nottl) - styleflags |= DNS_STYLEFLAG_NO_TTL; - if (noclass) - styleflags |= DNS_STYLEFLAG_NO_CLASS; - if (multiline) { - styleflags |= DNS_STYLEFLAG_OMIT_OWNER; - styleflags |= DNS_STYLEFLAG_OMIT_CLASS; - styleflags |= DNS_STYLEFLAG_REL_DATA; - styleflags |= DNS_STYLEFLAG_OMIT_TTL; - styleflags |= DNS_STYLEFLAG_TTL; - styleflags |= DNS_STYLEFLAG_MULTILINE; - styleflags |= DNS_STYLEFLAG_COMMENT; - } - if (multiline || (nottl && noclass)) - result = dns_master_stylecreate(&style, styleflags, - 24, 24, 24, 32, 80, 8, mctx); - else if (nottl || noclass) - result = dns_master_stylecreate(&style, styleflags, - 24, 24, 32, 40, 80, 8, mctx); - else - result = dns_master_stylecreate(&style, styleflags, - 24, 32, 40, 48, 80, 8, mctx); - check_result(result, "dns_master_stylecreate"); - - result = dns_master_rdatasettotext(owner_name, rdataset, style, target); - - if (style != NULL) - dns_master_styledestroy(&style, mctx); - - return(result); -} -#endif - -/* - * Callback from dighost.c to print the reply from a server - */ -isc_result_t -printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { - isc_result_t result; - dns_messagetextflag_t flags; - isc_buffer_t *buf = NULL; - unsigned int len = OUTPUTBUF; - dns_master_style_t *style = NULL; - unsigned int styleflags = 0; - - styleflags |= DNS_STYLEFLAG_REL_OWNER; - if (nottl) - styleflags |= DNS_STYLEFLAG_NO_TTL; - if (noclass) - styleflags |= DNS_STYLEFLAG_NO_CLASS; - if (multiline) { - styleflags |= DNS_STYLEFLAG_OMIT_OWNER; - styleflags |= DNS_STYLEFLAG_OMIT_CLASS; - styleflags |= DNS_STYLEFLAG_REL_DATA; - styleflags |= DNS_STYLEFLAG_OMIT_TTL; - styleflags |= DNS_STYLEFLAG_TTL; - styleflags |= DNS_STYLEFLAG_MULTILINE; - styleflags |= DNS_STYLEFLAG_COMMENT; - } - if (multiline || (nottl && noclass)) - result = dns_master_stylecreate(&style, styleflags, - 24, 24, 24, 32, 80, 8, mctx); - else if (nottl || noclass) - result = dns_master_stylecreate(&style, styleflags, - 24, 24, 32, 40, 80, 8, mctx); - else - result = dns_master_stylecreate(&style, styleflags, - 24, 32, 40, 48, 80, 8, mctx); - check_result(result, "dns_master_stylecreate"); - - if (query->lookup->cmdline[0] != 0) { - if (!short_form) - fputs(query->lookup->cmdline, stdout); - query->lookup->cmdline[0]=0; - } - debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders", - query->lookup->comments ? "comments" : "nocomments", - short_form ? "short_form" : "long_form"); - - flags = 0; - if (!headers) { - flags |= DNS_MESSAGETEXTFLAG_NOHEADERS; - flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; - } - if (!query->lookup->comments) - flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; - - result = ISC_R_SUCCESS; - - result = isc_buffer_allocate(mctx, &buf, len); - check_result(result, "isc_buffer_allocate"); - - if (query->lookup->comments && !short_form) { - if (query->lookup->cmdline[0] != 0) - printf("; %s\n", query->lookup->cmdline); - if (msg == query->lookup->sendmsg) - printf(";; Sending:\n"); - else - printf(";; Got answer:\n"); - - 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"); - if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) - printf(" aa"); - if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) - printf(" tc"); - if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) - printf(" rd"); - if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) - printf(" ra"); - if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) - printf(" ad"); - if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) - printf(" cd"); - - 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]); - - if (msg != query->lookup->sendmsg && - (msg->flags & DNS_MESSAGEFLAG_RD) != 0 && - (msg->flags & DNS_MESSAGEFLAG_RA) == 0) - printf(";; WARNING: recursion requested " - "but not available\n"); - } - if (msg != query->lookup->sendmsg && extrabytes != 0U) - printf(";; WARNING: Messages has %u extra byte%s at " - "end\n", extrabytes, extrabytes != 0 ? "s" : ""); - } - -repopulate_buffer: - - if (query->lookup->comments && headers && !short_form) { - result = dns_message_pseudosectiontotext(msg, - DNS_PSEUDOSECTION_OPT, - style, flags, buf); - if (result == ISC_R_NOSPACE) { -buftoosmall: - len += OUTPUTBUF; - isc_buffer_free(&buf); - result = isc_buffer_allocate(mctx, &buf, len); - if (result == ISC_R_SUCCESS) - goto repopulate_buffer; - else - goto cleanup; - } - check_result(result, - "dns_message_pseudosectiontotext"); - } - - if (query->lookup->section_question && headers) { - if (!short_form) { - result = dns_message_sectiontotext(msg, - DNS_SECTION_QUESTION, - style, flags, buf); - if (result == ISC_R_NOSPACE) - goto buftoosmall; - check_result(result, "dns_message_sectiontotext"); - } - } - if (query->lookup->section_answer) { - if (!short_form) { - result = dns_message_sectiontotext(msg, - DNS_SECTION_ANSWER, - style, flags, buf); - if (result == ISC_R_NOSPACE) - goto buftoosmall; - check_result(result, "dns_message_sectiontotext"); - } else { - result = short_answer(msg, flags, buf, query); - if (result == ISC_R_NOSPACE) - goto buftoosmall; - check_result(result, "short_answer"); - } - } - if (query->lookup->section_authority) { - if (!short_form) { - result = dns_message_sectiontotext(msg, - DNS_SECTION_AUTHORITY, - style, flags, buf); - if (result == ISC_R_NOSPACE) - goto buftoosmall; - check_result(result, "dns_message_sectiontotext"); - } - } - if (query->lookup->section_additional) { - if (!short_form) { - result = dns_message_sectiontotext(msg, - DNS_SECTION_ADDITIONAL, - style, flags, buf); - if (result == ISC_R_NOSPACE) - goto buftoosmall; - check_result(result, "dns_message_sectiontotext"); - /* - * Only print the signature on the first record. - */ - if (headers) { - result = dns_message_pseudosectiontotext( - msg, - DNS_PSEUDOSECTION_TSIG, - style, flags, buf); - if (result == ISC_R_NOSPACE) - goto buftoosmall; - check_result(result, - "dns_message_pseudosectiontotext"); - result = dns_message_pseudosectiontotext( - msg, - DNS_PSEUDOSECTION_SIG0, - style, flags, buf); - if (result == ISC_R_NOSPACE) - goto buftoosmall; - check_result(result, - "dns_message_pseudosectiontotext"); - } - } - } - - if (headers && query->lookup->comments && !short_form) - printf("\n"); - - printf("%.*s", (int)isc_buffer_usedlength(buf), - (char *)isc_buffer_base(buf)); - isc_buffer_free(&buf); - -cleanup: - if (style != NULL) - dns_master_styledestroy(&style, mctx); - return (result); -} - -/*% - * print the greeting message when the program first starts up. - */ -static void -printgreeting(int argc, char **argv, dig_lookup_t *lookup) { - int i; - int remaining; - static isc_boolean_t first = ISC_TRUE; - char append[MXNAME]; - - if (printcmd) { - lookup->cmdline[sizeof(lookup->cmdline) - 1] = 0; - snprintf(lookup->cmdline, sizeof(lookup->cmdline), - "%s; <<>> DiG " VERSION " <<>>", - first?"\n":""); - i = 1; - while (i < argc) { - snprintf(append, sizeof(append), " %s", argv[i++]); - remaining = sizeof(lookup->cmdline) - - strlen(lookup->cmdline) - 1; - strncat(lookup->cmdline, append, remaining); - } - remaining = sizeof(lookup->cmdline) - - strlen(lookup->cmdline) - 1; - strncat(lookup->cmdline, "\n", remaining); - if (first && addresscount != 0) { - snprintf(append, sizeof(append), - "; (%d server%s found)\n", - addresscount, - addresscount > 1 ? "s" : ""); - remaining = sizeof(lookup->cmdline) - - strlen(lookup->cmdline) - 1; - strncat(lookup->cmdline, append, remaining); - } - if (first) { - snprintf(append, sizeof(append), - ";; global options: %s %s\n", - short_form ? "short_form" : "", - printcmd ? "printcmd" : ""); - first = ISC_FALSE; - remaining = sizeof(lookup->cmdline) - - strlen(lookup->cmdline) - 1; - strncat(lookup->cmdline, append, remaining); - } - } -} - -static isc_uint32_t -parse_uint(char *arg, const char *desc, isc_uint32_t max) { - isc_result_t result; - isc_uint32_t tmp; - - result = isc_parse_uint32(&tmp, arg, 10); - if (result == ISC_R_SUCCESS && tmp > max) - result = ISC_R_RANGE; - if (result != ISC_R_SUCCESS) - fatal("%s '%s': %s", desc, arg, isc_result_totext(result)); - return (tmp); -} - -/*% - * We're not using isc_commandline_parse() here since the command line - * syntax of dig is quite a bit different from that which can be described - * by that routine. - * XXX doc options - */ - -static void -plus_option(char *option, isc_boolean_t is_batchfile, - dig_lookup_t *lookup) -{ - char option_store[256]; - char *cmd, *value, *ptr; - isc_boolean_t state = ISC_TRUE; -#ifdef DIG_SIGCHASE - size_t n; -#endif - - strncpy(option_store, option, sizeof(option_store)); - option_store[sizeof(option_store)-1]=0; - ptr = option_store; - cmd = next_token(&ptr,"="); - if (cmd == NULL) { - printf(";; Invalid option %s\n", option_store); - return; - } - value = ptr; - if (strncasecmp(cmd, "no", 2)==0) { - cmd += 2; - state = ISC_FALSE; - } - -#define FULLCHECK(A) \ - do { \ - size_t _l = strlen(cmd); \ - if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ - goto invalid_option; \ - } while (0) -#define FULLCHECK2(A, B) \ - do { \ - size_t _l = strlen(cmd); \ - if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \ - (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \ - goto invalid_option; \ - } while (0) - - switch (cmd[0]) { - case 'a': - switch (cmd[1]) { - case 'a': /* aaonly / aaflag */ - FULLCHECK2("aaonly", "aaflag"); - lookup->aaonly = state; - break; - case 'd': - switch (cmd[2]) { - case 'd': /* additional */ - FULLCHECK("additional"); - lookup->section_additional = state; - break; - case 'f': /* adflag */ - FULLCHECK("adflag"); - lookup->adflag = state; - break; - default: - goto invalid_option; - } - break; - case 'l': /* all */ - FULLCHECK("all"); - lookup->section_question = state; - lookup->section_authority = state; - lookup->section_answer = state; - lookup->section_additional = state; - lookup->comments = state; - lookup->stats = state; - printcmd = state; - break; - case 'n': /* answer */ - FULLCHECK("answer"); - lookup->section_answer = state; - break; - case 'u': /* authority */ - FULLCHECK("authority"); - lookup->section_authority = state; - break; - default: - goto invalid_option; - } - break; - case 'b': - switch (cmd[1]) { - case 'e':/* besteffort */ - FULLCHECK("besteffort"); - lookup->besteffort = state; - break; - case 'u':/* bufsize */ - FULLCHECK("bufsize"); - if (value == NULL) - goto need_value; - if (!state) - goto invalid_option; - lookup->udpsize = (isc_uint16_t) parse_uint(value, - "buffer size", COMMSIZE); - break; - default: - goto invalid_option; - } - break; - case 'c': - switch (cmd[1]) { - case 'd':/* cdflag */ - FULLCHECK("cdflag"); - lookup->cdflag = state; - break; - case 'l': /* cl */ - FULLCHECK("cl"); - noclass = ISC_TF(!state); - break; - case 'm': /* cmd */ - FULLCHECK("cmd"); - printcmd = state; - break; - case 'o': /* comments */ - FULLCHECK("comments"); - lookup->comments = state; - if (lookup == default_lookup) - pluscomm = state; - break; - default: - goto invalid_option; - } - break; - case 'd': - switch (cmd[1]) { - case 'e': /* defname */ - FULLCHECK("defname"); - usesearch = state; - break; - case 'n': /* dnssec */ - FULLCHECK("dnssec"); - if (state && lookup->edns == -1) - lookup->edns = 0; - lookup->dnssec = state; - break; - case 'o': /* domain */ - FULLCHECK("domain"); - if (value == NULL) - goto need_value; - if (!state) - goto invalid_option; - strncpy(domainopt, value, sizeof(domainopt)); - domainopt[sizeof(domainopt)-1] = '\0'; - break; - default: - goto invalid_option; - } - break; - case 'e': - FULLCHECK("edns"); - if (!state) { - lookup->edns = -1; - break; - } - if (value == NULL) - goto need_value; - lookup->edns = (isc_int16_t) parse_uint(value, "edns", 255); - break; - case 'f': /* fail */ - FULLCHECK("fail"); - lookup->servfail_stops = state; - break; - case 'i': - switch (cmd[1]) { - case 'd': /* identify */ - FULLCHECK("identify"); - lookup->identify = state; - break; - case 'g': /* ignore */ - default: /* Inherets default for compatibility */ - FULLCHECK("ignore"); - lookup->ignore = ISC_TRUE; - } - break; - case 'm': /* multiline */ - FULLCHECK("multiline"); - multiline = state; - break; - case 'n': - switch (cmd[1]) { - case 'd': /* ndots */ - FULLCHECK("ndots"); - if (value == NULL) - goto need_value; - if (!state) - goto invalid_option; - ndots = parse_uint(value, "ndots", MAXNDOTS); - break; - case 's': /* nssearch */ - FULLCHECK("nssearch"); - lookup->ns_search_only = state; - if (state) { - lookup->trace_root = ISC_TRUE; - lookup->recurse = ISC_TRUE; - lookup->identify = ISC_TRUE; - lookup->stats = ISC_FALSE; - lookup->comments = ISC_FALSE; - lookup->section_additional = ISC_FALSE; - lookup->section_authority = ISC_FALSE; - lookup->section_question = ISC_FALSE; - lookup->rdtype = dns_rdatatype_ns; - lookup->rdtypeset = ISC_TRUE; - short_form = ISC_TRUE; - } - break; - default: - goto invalid_option; - } - break; - case 'q': - switch (cmd[1]) { - case 'r': /* qr */ - FULLCHECK("qr"); - qr = state; - break; - case 'u': /* question */ - FULLCHECK("question"); - lookup->section_question = state; - if (lookup == default_lookup) - plusquest = state; - break; - default: - goto invalid_option; - } - break; - case 'r': - switch (cmd[1]) { - case 'e': - switch (cmd[2]) { - case 'c': /* recurse */ - FULLCHECK("recurse"); - lookup->recurse = state; - break; - case 't': /* retry / retries */ - FULLCHECK2("retry", "retries"); - if (value == NULL) - goto need_value; - if (!state) - goto invalid_option; - lookup->retries = parse_uint(value, "retries", - MAXTRIES - 1); - lookup->retries++; - break; - default: - goto invalid_option; - } - break; - default: - goto invalid_option; - } - break; - case 's': - switch (cmd[1]) { - case 'e': /* search */ - FULLCHECK("search"); - usesearch = state; - break; - case 'h': - if (cmd[2] != 'o') - goto invalid_option; - switch (cmd[3]) { - case 'r': /* short */ - FULLCHECK("short"); - short_form = state; - if (state) { - printcmd = ISC_FALSE; - lookup->section_additional = ISC_FALSE; - lookup->section_answer = ISC_TRUE; - lookup->section_authority = ISC_FALSE; - lookup->section_question = ISC_FALSE; - lookup->comments = ISC_FALSE; - lookup->stats = ISC_FALSE; - } - break; - case 'w': /* showsearch */ - FULLCHECK("showsearch"); - showsearch = state; - usesearch = state; - break; - default: - goto invalid_option; - } - break; -#ifdef DIG_SIGCHASE - case 'i': /* sigchase */ - FULLCHECK("sigchase"); - lookup->sigchase = state; - if (lookup->sigchase) - lookup->dnssec = ISC_TRUE; - break; -#endif - case 't': /* stats */ - FULLCHECK("stats"); - lookup->stats = state; - break; - default: - goto invalid_option; - } - break; - case 't': - switch (cmd[1]) { - case 'c': /* tcp */ - FULLCHECK("tcp"); - if (!is_batchfile) - lookup->tcp_mode = state; - break; - case 'i': /* timeout */ - FULLCHECK("timeout"); - if (value == NULL) - goto need_value; - if (!state) - goto invalid_option; - timeout = parse_uint(value, "timeout", MAXTIMEOUT); - if (timeout == 0) - timeout = 1; - break; -#if DIG_SIGCHASE_TD - case 'o': /* topdown */ - FULLCHECK("topdown"); - lookup->do_topdown = state; - break; -#endif - case 'r': - switch (cmd[2]) { - case 'a': /* trace */ - FULLCHECK("trace"); - lookup->trace = state; - lookup->trace_root = state; - if (state) { - lookup->recurse = ISC_FALSE; - lookup->identify = ISC_TRUE; - lookup->comments = ISC_FALSE; - lookup->stats = ISC_FALSE; - lookup->section_additional = ISC_FALSE; - lookup->section_authority = ISC_TRUE; - lookup->section_question = ISC_FALSE; - } - break; - case 'i': /* tries */ - FULLCHECK("tries"); - if (value == NULL) - goto need_value; - if (!state) - goto invalid_option; - lookup->retries = parse_uint(value, "tries", - MAXTRIES); - if (lookup->retries == 0) - lookup->retries = 1; - break; -#ifdef DIG_SIGCHASE - case 'u': /* trusted-key */ - FULLCHECK("trusted-key"); - if (value == NULL) - goto need_value; - if (!state) - goto invalid_option; - n = strlcpy(trustedkey, ptr, - sizeof(trustedkey)); - if (n >= sizeof(trustedkey)) - fatal("trusted key too large"); - break; -#endif - default: - goto invalid_option; - } - break; - case 't': /* ttlid */ - FULLCHECK("ttlid"); - nottl = ISC_TF(!state); - break; - default: - goto invalid_option; - } - break; - case 'v': - FULLCHECK("vc"); - if (!is_batchfile) - lookup->tcp_mode = state; - break; - default: - invalid_option: - need_value: - fprintf(stderr, "Invalid option: +%s\n", - option); - usage(); - } - return; -} - -/*% - * #ISC_TRUE returned if value was used - */ -static const char *single_dash_opts = "46dhimnv"; -static const char *dash_opts = "46bcdfhikmnptvyx"; -static isc_boolean_t -dash_option(char *option, char *next, dig_lookup_t **lookup, - isc_boolean_t *open_type_class, isc_boolean_t *need_clone, - isc_boolean_t config_only, int argc, char **argv, - isc_boolean_t *firstarg) -{ - char opt, *value, *ptr, *ptr2, *ptr3; - isc_result_t result; - isc_boolean_t value_from_next; - isc_textregion_t tr; - dns_rdatatype_t rdtype; - dns_rdataclass_t rdclass; - char textname[MXNAME]; - struct in_addr in4; - struct in6_addr in6; - in_port_t srcport; - char *hash, *cmd; - - while (strpbrk(option, single_dash_opts) == &option[0]) { - /* - * Since the -[46dhimnv] options do not take an argument, - * account for them (in any number and/or combination) - * if they appear as the first character(s) of a q-opt. - */ - opt = option[0]; - switch (opt) { - case '4': - if (have_ipv4) { - isc_net_disableipv6(); - have_ipv6 = ISC_FALSE; - } else { - fatal("can't find IPv4 networking"); - return (ISC_FALSE); - } - break; - case '6': - if (have_ipv6) { - isc_net_disableipv4(); - have_ipv4 = ISC_FALSE; - } else { - fatal("can't find IPv6 networking"); - return (ISC_FALSE); - } - break; - case 'd': - ptr = strpbrk(&option[1], dash_opts); - if (ptr != &option[1]) { - cmd = option; - FULLCHECK("debug"); - debugging = ISC_TRUE; - return (ISC_FALSE); - } else - debugging = ISC_TRUE; - break; - case 'h': - help(); - exit(0); - break; - case 'i': - ip6_int = ISC_TRUE; - break; - case 'm': /* memdebug */ - /* memdebug is handled in preparse_args() */ - break; - case 'n': - /* deprecated */ - break; - case 'v': - version(); - exit(0); - break; - } - if (strlen(option) > 1U) - option = &option[1]; - else - return (ISC_FALSE); - } - opt = option[0]; - if (strlen(option) > 1U) { - value_from_next = ISC_FALSE; - value = &option[1]; - } else { - value_from_next = ISC_TRUE; - value = next; - } - if (value == NULL) - goto invalid_option; - switch (opt) { - case 'b': - hash = strchr(value, '#'); - if (hash != NULL) { - srcport = (in_port_t) - parse_uint(hash + 1, - "port number", MAXPORT); - *hash = '\0'; - } else - srcport = 0; - if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) { - isc_sockaddr_fromin6(&bind_address, &in6, srcport); - isc_net_disableipv4(); - } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) { - isc_sockaddr_fromin(&bind_address, &in4, srcport); - isc_net_disableipv6(); - } else { - if (hash != NULL) - *hash = '#'; - fatal("invalid address %s", value); - } - if (hash != NULL) - *hash = '#'; - specified_source = ISC_TRUE; - return (value_from_next); - case 'c': - if ((*lookup)->rdclassset) { - fprintf(stderr, ";; Warning, extra class option\n"); - } - *open_type_class = ISC_FALSE; - tr.base = value; - tr.length = strlen(value); - result = dns_rdataclass_fromtext(&rdclass, - (isc_textregion_t *)&tr); - if (result == ISC_R_SUCCESS) { - (*lookup)->rdclass = rdclass; - (*lookup)->rdclassset = ISC_TRUE; - } else - fprintf(stderr, ";; Warning, ignoring " - "invalid class %s\n", - value); - return (value_from_next); - case 'f': - batchname = value; - return (value_from_next); - case 'k': - strncpy(keyfile, value, sizeof(keyfile)); - keyfile[sizeof(keyfile)-1]=0; - return (value_from_next); - case 'p': - port = (in_port_t) parse_uint(value, "port number", MAXPORT); - return (value_from_next); - case 'q': - if (!config_only) { - if (*need_clone) - (*lookup) = clone_lookup(default_lookup, - ISC_TRUE); - *need_clone = ISC_TRUE; - strncpy((*lookup)->textname, value, - sizeof((*lookup)->textname)); - (*lookup)->textname[sizeof((*lookup)->textname)-1]=0; - (*lookup)->trace_root = ISC_TF((*lookup)->trace || - (*lookup)->ns_search_only); - (*lookup)->new_search = ISC_TRUE; - if (*firstarg) { - printgreeting(argc, argv, *lookup); - *firstarg = ISC_FALSE; - } - ISC_LIST_APPEND(lookup_list, (*lookup), link); - debug("looking up %s", (*lookup)->textname); - } - return (value_from_next); - case 't': - *open_type_class = ISC_FALSE; - if (strncasecmp(value, "ixfr=", 5) == 0) { - rdtype = dns_rdatatype_ixfr; - result = ISC_R_SUCCESS; - } else { - tr.base = value; - tr.length = strlen(value); - result = dns_rdatatype_fromtext(&rdtype, - (isc_textregion_t *)&tr); - if (result == ISC_R_SUCCESS && - rdtype == dns_rdatatype_ixfr) { - result = DNS_R_UNKNOWN; - } - } - if (result == ISC_R_SUCCESS) { - if ((*lookup)->rdtypeset) { - fprintf(stderr, ";; Warning, " - "extra type option\n"); - } - if (rdtype == dns_rdatatype_ixfr) { - (*lookup)->rdtype = dns_rdatatype_ixfr; - (*lookup)->rdtypeset = ISC_TRUE; - (*lookup)->ixfr_serial = - parse_uint(&value[5], "serial number", - MAXSERIAL); - (*lookup)->section_question = plusquest; - (*lookup)->comments = pluscomm; - } else { - (*lookup)->rdtype = rdtype; - (*lookup)->rdtypeset = ISC_TRUE; - if (rdtype == dns_rdatatype_axfr) { - (*lookup)->section_question = plusquest; - (*lookup)->comments = pluscomm; - } - (*lookup)->ixfr_serial = ISC_FALSE; - } - } else - fprintf(stderr, ";; Warning, ignoring " - "invalid type %s\n", - value); - return (value_from_next); - case 'y': - ptr = next_token(&value,":"); /* hmac type or name */ - if (ptr == NULL) { - usage(); - } - ptr2 = next_token(&value, ":"); /* name or secret */ - if (ptr2 == NULL) - usage(); - ptr3 = next_token(&value,":"); /* secret or NULL */ - if (ptr3 != NULL) { - if (strcasecmp(ptr, "hmac-md5") == 0) { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-md5-", 9) == 0) { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = parse_uint(&ptr[9], - "digest-bits [0..128]", - 128); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha1") == 0) { - hmacname = DNS_TSIG_HMACSHA1_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha1-", 10) == 0) { - hmacname = DNS_TSIG_HMACSHA1_NAME; - digestbits = parse_uint(&ptr[10], - "digest-bits [0..160]", - 160); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha224") == 0) { - hmacname = DNS_TSIG_HMACSHA224_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha224-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA224_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..224]", - 224); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha256") == 0) { - hmacname = DNS_TSIG_HMACSHA256_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha256-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA256_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..256]", - 256); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha384") == 0) { - hmacname = DNS_TSIG_HMACSHA384_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha384-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA384_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..384]", - 384); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha512") == 0) { - hmacname = DNS_TSIG_HMACSHA512_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha512-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA512_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..512]", - 512); - digestbits = (digestbits + 7) & ~0x7U; - } else { - fprintf(stderr, ";; Warning, ignoring " - "invalid TSIG algorithm %s\n", ptr); - return (value_from_next); - } - ptr = ptr2; - ptr2 = ptr3; - } else { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = 0; - } - strncpy(keynametext, ptr, sizeof(keynametext)); - keynametext[sizeof(keynametext)-1]=0; - strncpy(keysecret, ptr2, sizeof(keysecret)); - keysecret[sizeof(keysecret)-1]=0; - return (value_from_next); - case 'x': - if (*need_clone) - *lookup = clone_lookup(default_lookup, ISC_TRUE); - *need_clone = ISC_TRUE; - if (get_reverse(textname, sizeof(textname), value, - ip6_int, ISC_FALSE) == ISC_R_SUCCESS) { - strncpy((*lookup)->textname, textname, - sizeof((*lookup)->textname)); - debug("looking up %s", (*lookup)->textname); - (*lookup)->trace_root = ISC_TF((*lookup)->trace || - (*lookup)->ns_search_only); - (*lookup)->ip6_int = ip6_int; - if (!(*lookup)->rdtypeset) - (*lookup)->rdtype = dns_rdatatype_ptr; - if (!(*lookup)->rdclassset) - (*lookup)->rdclass = dns_rdataclass_in; - (*lookup)->new_search = ISC_TRUE; - if (*firstarg) { - printgreeting(argc, argv, *lookup); - *firstarg = ISC_FALSE; - } - ISC_LIST_APPEND(lookup_list, *lookup, link); - } else { - fprintf(stderr, "Invalid IP address %s\n", value); - exit(1); - } - return (value_from_next); - invalid_option: - default: - fprintf(stderr, "Invalid option: -%s\n", option); - usage(); - } - return (ISC_FALSE); -} - -/*% - * Because we may be trying to do memory allocation recording, we're going - * to need to parse the arguments for the -m *before* we start the main - * argument parsing routine. - * - * I'd prefer not to have to do this, but I am not quite sure how else to - * fix the problem. Argument parsing in dig involves memory allocation - * by its nature, so it can't be done in the main argument parser. - */ -static void -preparse_args(int argc, char **argv) { - int rc; - char **rv; - char *option; - - rc = argc; - rv = argv; - for (rc--, rv++; rc > 0; rc--, rv++) { - if (rv[0][0] != '-') - continue; - option = &rv[0][1]; - while (strpbrk(option, single_dash_opts) == &option[0]) { - if (option[0] == 'm') { - memdebugging = ISC_TRUE; - isc_mem_debugging = ISC_MEM_DEBUGTRACE | - ISC_MEM_DEBUGRECORD; - return; - } - option = &option[1]; - } - } -} - -static void -getaddresses(dig_lookup_t *lookup, const char *host) { - isc_result_t result; - isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; - isc_netaddr_t netaddr; - int count, i; - dig_server_t *srv; - char tmp[ISC_NETADDR_FORMATSIZE]; - - result = bind9_getaddresses(host, 0, sockaddrs, - DIG_MAX_ADDRESSES, &count); - if (result != ISC_R_SUCCESS) - fatal("couldn't get address for '%s': %s", - host, isc_result_totext(result)); - - for (i = 0; i < count; i++) { - isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); - isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); - srv = make_server(tmp, host); - ISC_LIST_APPEND(lookup->my_server_list, srv, link); - } - addresscount = count; -} - -static void -parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only, - int argc, char **argv) { - isc_result_t result; - isc_textregion_t tr; - isc_boolean_t firstarg = ISC_TRUE; - dig_lookup_t *lookup = NULL; - dns_rdatatype_t rdtype; - dns_rdataclass_t rdclass; - isc_boolean_t open_type_class = ISC_TRUE; - char batchline[MXNAME]; - int bargc; - char *bargv[64]; - int rc; - char **rv; -#ifndef NOPOSIX - char *homedir; - char rcfile[256]; -#endif - char *input; - int i; - isc_boolean_t need_clone = ISC_TRUE; - - /* - * The semantics for parsing the args is a bit complex; if - * we don't have a host yet, make the arg apply globally, - * otherwise make it apply to the latest host. This is - * a bit different than the previous versions, but should - * form a consistent user interface. - * - * First, create a "default lookup" which won't actually be used - * anywhere, except for cloning into new lookups - */ - - debug("parse_args()"); - if (!is_batchfile) { - debug("making new lookup"); - default_lookup = make_empty_lookup(); - -#ifndef NOPOSIX - /* - * Treat ${HOME}/.digrc as a special batchfile - */ - INSIST(batchfp == NULL); - homedir = getenv("HOME"); - if (homedir != NULL) { - unsigned int n; - n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc", - homedir); - if (n < sizeof(rcfile)) - batchfp = fopen(rcfile, "r"); - } - if (batchfp != NULL) { - while (fgets(batchline, sizeof(batchline), - batchfp) != 0) { - debug("config line %s", batchline); - bargc = 1; - input = batchline; - bargv[bargc] = next_token(&input, " \t\r\n"); - while ((bargv[bargc] != NULL) && - (bargc < 62)) { - bargc++; - bargv[bargc] = - next_token(&input, " \t\r\n"); - } - - bargv[0] = argv[0]; - argv0 = argv[0]; - - for(i = 0; i < bargc; i++) - debug(".digrc argv %d: %s", - i, bargv[i]); - parse_args(ISC_TRUE, ISC_TRUE, bargc, - (char **)bargv); - } - fclose(batchfp); - } -#endif - } - - if (is_batchfile && !config_only) { - /* Processing '-f batchfile'. */ - lookup = clone_lookup(default_lookup, ISC_TRUE); - need_clone = ISC_FALSE; - } else - lookup = default_lookup; - - rc = argc; - rv = argv; - for (rc--, rv++; rc > 0; rc--, rv++) { - debug("main parsing %s", rv[0]); - if (strncmp(rv[0], "%", 1) == 0) - break; - if (strncmp(rv[0], "@", 1) == 0) { - getaddresses(lookup, &rv[0][1]); - } else if (rv[0][0] == '+') { - plus_option(&rv[0][1], is_batchfile, - lookup); - } else if (rv[0][0] == '-') { - if (rc <= 1) { - if (dash_option(&rv[0][1], NULL, - &lookup, &open_type_class, - &need_clone, config_only, - argc, argv, &firstarg)) { - rc--; - rv++; - } - } else { - if (dash_option(&rv[0][1], rv[1], - &lookup, &open_type_class, - &need_clone, config_only, - argc, argv, &firstarg)) { - rc--; - rv++; - } - } - } else { - /* - * Anything which isn't an option - */ - if (open_type_class) { - if (strncasecmp(rv[0], "ixfr=", 5) == 0) { - rdtype = dns_rdatatype_ixfr; - result = ISC_R_SUCCESS; - } else { - tr.base = rv[0]; - tr.length = strlen(rv[0]); - result = dns_rdatatype_fromtext(&rdtype, - (isc_textregion_t *)&tr); - if (result == ISC_R_SUCCESS && - rdtype == dns_rdatatype_ixfr) { - result = DNS_R_UNKNOWN; - fprintf(stderr, ";; Warning, " - "ixfr requires a " - "serial number\n"); - continue; - } - } - if (result == ISC_R_SUCCESS) { - if (lookup->rdtypeset) { - fprintf(stderr, ";; Warning, " - "extra type option\n"); - } - if (rdtype == dns_rdatatype_ixfr) { - lookup->rdtype = - dns_rdatatype_ixfr; - lookup->rdtypeset = ISC_TRUE; - lookup->ixfr_serial = - parse_uint(&rv[0][5], - "serial number", - MAXSERIAL); - lookup->section_question = - plusquest; - lookup->comments = pluscomm; - } else { - lookup->rdtype = rdtype; - lookup->rdtypeset = ISC_TRUE; - if (rdtype == - dns_rdatatype_axfr) { - lookup->section_question = - plusquest; - lookup->comments = pluscomm; - } - lookup->ixfr_serial = ISC_FALSE; - } - continue; - } - result = dns_rdataclass_fromtext(&rdclass, - (isc_textregion_t *)&tr); - if (result == ISC_R_SUCCESS) { - if (lookup->rdclassset) { - fprintf(stderr, ";; Warning, " - "extra class option\n"); - } - lookup->rdclass = rdclass; - lookup->rdclassset = ISC_TRUE; - continue; - } - } - - if (!config_only) { - if (need_clone) - lookup = clone_lookup(default_lookup, - ISC_TRUE); - need_clone = ISC_TRUE; - strncpy(lookup->textname, rv[0], - sizeof(lookup->textname)); - lookup->textname[sizeof(lookup->textname)-1]=0; - lookup->trace_root = ISC_TF(lookup->trace || - lookup->ns_search_only); - lookup->new_search = ISC_TRUE; - if (firstarg) { - printgreeting(argc, argv, lookup); - firstarg = ISC_FALSE; - } - ISC_LIST_APPEND(lookup_list, lookup, link); - debug("looking up %s", lookup->textname); - } - /* XXX Error message */ - } - } - - /* - * If we have a batchfile, seed the lookup list with the - * first entry, then trust the callback in dighost_shutdown - * to get the rest - */ - if ((batchname != NULL) && !(is_batchfile)) { - if (strcmp(batchname, "-") == 0) - batchfp = stdin; - else - batchfp = fopen(batchname, "r"); - if (batchfp == NULL) { - perror(batchname); - if (exitcode < 8) - exitcode = 8; - fatal("couldn't open specified batch file"); - } - /* XXX Remove code dup from shutdown code */ - next_line: - if (fgets(batchline, sizeof(batchline), batchfp) != 0) { - bargc = 1; - debug("batch line %s", batchline); - if (batchline[0] == '\r' || batchline[0] == '\n' - || batchline[0] == '#' || batchline[0] == ';') - goto next_line; - input = batchline; - bargv[bargc] = next_token(&input, " \t\r\n"); - while ((bargv[bargc] != NULL) && (bargc < 14)) { - bargc++; - bargv[bargc] = next_token(&input, " \t\r\n"); - } - - bargv[0] = argv[0]; - argv0 = argv[0]; - - for(i = 0; i < bargc; i++) - debug("batch argv %d: %s", i, bargv[i]); - parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv); - return; - } - return; - } - /* - * If no lookup specified, search for root - */ - if ((lookup_list.head == NULL) && !config_only) { - if (need_clone) - lookup = clone_lookup(default_lookup, ISC_TRUE); - need_clone = ISC_TRUE; - lookup->trace_root = ISC_TF(lookup->trace || - lookup->ns_search_only); - lookup->new_search = ISC_TRUE; - strcpy(lookup->textname, "."); - lookup->rdtype = dns_rdatatype_ns; - lookup->rdtypeset = ISC_TRUE; - if (firstarg) { - printgreeting(argc, argv, lookup); - firstarg = ISC_FALSE; - } - ISC_LIST_APPEND(lookup_list, lookup, link); - } - if (!need_clone) - destroy_lookup(lookup); -} - -/* - * Callback from dighost.c to allow program-specific shutdown code. - * Here, we're possibly reading from a batch file, then shutting down - * for real if there's nothing in the batch file to read. - */ -void -dighost_shutdown(void) { - char batchline[MXNAME]; - int bargc; - char *bargv[16]; - char *input; - int i; - - if (batchname == NULL) { - isc_app_shutdown(); - return; - } - - fflush(stdout); - if (feof(batchfp)) { - batchname = NULL; - isc_app_shutdown(); - if (batchfp != stdin) - fclose(batchfp); - return; - } - - if (fgets(batchline, sizeof(batchline), batchfp) != 0) { - debug("batch line %s", batchline); - bargc = 1; - input = batchline; - bargv[bargc] = next_token(&input, " \t\r\n"); - while ((bargv[bargc] != NULL) && (bargc < 14)) { - bargc++; - bargv[bargc] = next_token(&input, " \t\r\n"); - } - - bargv[0] = argv0; - - for(i = 0; i < bargc; i++) - debug("batch argv %d: %s", i, bargv[i]); - parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv); - start_lookup(); - } else { - batchname = NULL; - if (batchfp != stdin) - fclose(batchfp); - isc_app_shutdown(); - return; - } -} - -/*% Main processing routine for dig */ -int -main(int argc, char **argv) { - isc_result_t result; - - ISC_LIST_INIT(lookup_list); - ISC_LIST_INIT(server_list); - ISC_LIST_INIT(search_list); - - debug("main()"); - preparse_args(argc, argv); - progname = argv[0]; - result = isc_app_start(); - check_result(result, "isc_app_start"); - setup_libs(); - parse_args(ISC_FALSE, ISC_FALSE, argc, argv); - setup_system(); - if (domainopt[0] != '\0') { - set_search_domain(domainopt); - usesearch = ISC_TRUE; - } - result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); - check_result(result, "isc_app_onrun"); - isc_app_run(); - destroy_lookup(default_lookup); - if (batchname != NULL) { - if (batchfp != stdin) - fclose(batchfp); - batchname = NULL; - } -#ifdef DIG_SIGCHASE - clean_trustedkey(); -#endif - cancel_all(); - destroy_libs(); - isc_app_finish(); - return (exitcode); -} |