diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
index cf9d65bf88..73187c9b78 100644
--- a/bin/dig/Makefile.in
+++ b/bin/dig/Makefile.in
@@ -55,6 +55,9 @@ dig: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
host: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
${LIBTOOL} ${CC} ${CFLAGS} -o $@ host.@O@ dighost.@O@ ${UOBJS} ${LIBS}
+nslookup: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL} ${CC} ${CFLAGS} -o $@ nslookup.@O@ dighost.@O@ ${UOBJS} ${LIBS}
+
clean distclean::
rm -f ${TARGETS}
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
index def75d7412..68f0fb8d81 100644
--- a/bin/dig/dig.c
+++ b/bin/dig/dig.c
@@ -34,6 +34,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, have_ipv6, show_details,
usesearch, trace, qr;
@@ -979,3 +980,43 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
}
printgreeting (argc, argv);
}
+
+int
+main(int argc, char **argv) {
+ dig_lookup_t *lookup = NULL;
+#ifdef TWIDDLE
+ FILE *fp;
+ int i, p;
+#endif
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ debug ("dhmain()");
+#ifdef TWIDDLE
+ fp = fopen("/dev/urandom", "r");
+ if (fp!=NULL) {
+ fread (&i, sizeof(int), 1, fp);
+ srandom(i);
+ }
+ else {
+ srandom ((int)&main);
+ }
+ p = getpid()%16+8;
+ for (i=0 ; i
textname[0]=0;
n = sscanf(hostname, "%d.%d.%d.%d", &adrs[0], &adrs[1],
&adrs[2], &adrs[3]);
@@ -649,6 +649,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
lookup->ns_search_only = showallsoa;
lookup->use_my_server_list = ISC_FALSE;
lookup->retries = tries;
+ lookup->udpsize = 0;
lookup->nsfound = 0;
lookup->trace = showallsoa;
lookup->trace_root = ISC_FALSE;
@@ -659,3 +660,42 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
have_host = ISC_TRUE;
}
+int
+main(int argc, char **argv) {
+ dig_lookup_t *lookup = NULL;
+#ifdef TWIDDLE
+ FILE *fp;
+ int i, p;
+#endif
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ debug ("dhmain()");
+#ifdef TWIDDLE
+ fp = fopen("/dev/urandom", "r");
+ if (fp!=NULL) {
+ fread (&i, sizeof(int), 1, fp);
+ srandom(i);
+ }
+ else {
+ srandom ((int)&main);
+ }
+ p = getpid()%16+8;
+ for (i=0 ; i
+
+#include
+
+extern int h_errno;
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+extern ISC_LIST(dig_lookup_t) lookup_list;
+extern ISC_LIST(dig_server_t) server_list;
+extern ISC_LIST(dig_searchlist_t) search_list;
+
+extern isc_boolean_t tcp_mode, have_ipv6, show_details,
+ usesearch, trace, qr;
+extern in_port_t port;
+extern unsigned int timeout;
+extern isc_mem_t *mctx;
+extern isc_taskmgr_t *taskmgr;
+extern isc_task_t *task;
+extern isc_timermgr_t *timermgr;
+extern isc_socketmgr_t *socketmgr;
+extern dns_messageid_t id;
+extern char *rootspace[BUFSIZE];
+extern isc_buffer_t rootbuf;
+extern int sendcount;
+extern int ndots;
+extern int tries;
+extern int lookup_counter;
+extern char fixeddomain[MXNAME];
+#ifdef TWIDDLE
+extern isc_boolean_t twiddle;
+#endif
+extern int exitcode;
+
+isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE,
+ filter = ISC_FALSE, showallsoa = ISC_FALSE;
+
+isc_uint16_t bufsize = 0;
+isc_boolean_t 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;
+isc_mutex_t lock;
+isc_condition_t cond;
+isc_boolean_t busy = ISC_FALSE, arg_lookup = ISC_FALSE;
+
+
+static char *opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMPL",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+static void
+show_usage() {
+ fputs (
+"Usage:\n"
+, stderr);
+}
+
+void
+check_next_lookup(dig_lookup_t *lookup) {
+ dig_lookup_t *next;
+ dig_query_t *query;
+ isc_boolean_t still_working=ISC_FALSE;
+
+ debug("In check_next_lookup", stderr);
+ for (query = ISC_LIST_HEAD(lookup->q);
+ query != NULL;
+ query = ISC_LIST_NEXT(query, link)) {
+ if (query->working) {
+ debug("Still have a worker.", stderr);
+ still_working=ISC_TRUE;
+ }
+ }
+ if (still_working)
+ return;
+
+ next = ISC_LIST_NEXT(lookup, link);
+ debug ("Have %d retries left for %s\n",
+ lookup->retries, lookup->textname);
+ if ((next == NULL)&&((lookup->retries <= 1)
+ ||tcp_mode || !lookup->pending)) {
+ debug("Shutting Down.", stderr);
+ isc_mutex_lock(&lock);
+ busy = ISC_FALSE;
+ isc_condition_signal(&cond);
+ isc_mutex_unlock(&lock);
+ return;
+ }
+
+ if (tcp_mode) {
+ setup_lookup(next);
+ do_lookup_tcp(next);
+ } else {
+ if ((lookup->retries > 1) && (lookup->pending)) {
+ lookup->retries --;
+ send_udp(lookup);
+ } else {
+ ENSURE (next != NULL);
+ setup_lookup(next);
+ do_lookup_udp(next);
+ }
+ }
+}
+
+void
+received(int bytes, int frmsize, char *frm, dig_query_t *query) {
+ isc_uint64_t diff;
+ isc_time_t now;
+ isc_result_t result;
+ time_t tnow;
+
+ result = isc_time_now(&now);
+ check_result (result, "isc_time_now");
+
+ if (query->lookup->stats) {
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ printf(";; Query time: %ld msec\n", (long int)diff/1000);
+ printf(";; SERVER: %.*s\n", frmsize, frm);
+ time (&tnow);
+ printf(";; WHEN: %s", ctime(&tnow));
+ printf (";; MSG SIZE rcvd: %d\n\n", bytes);
+ } else if (query->lookup->identify && !short_form) {
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ printf(";; Received %u bytes from %.*s in %d ms\n",
+ bytes, frmsize, frm, (int)diff/1000);
+ }
+}
+
+void
+trying(int frmsize, char *frm, dig_lookup_t *lookup) {
+ UNUSED (frmsize);
+ UNUSED (frm);
+ UNUSED (lookup);
+
+}
+
+static void
+say_message(dns_rdata_t *rdata, dig_query_t *query) {
+ isc_buffer_t *b=NULL, *b2=NULL;
+ isc_region_t r, r2;
+ isc_result_t result;
+ isc_uint64_t diff;
+ isc_time_t now;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result (result, "isc_buffer_allocate");
+ result = dns_rdata_totext(rdata, NULL, b);
+ check_result(result, "dns_rdata_totext");
+ isc_buffer_usedregion(b, &r);
+ if (!query->lookup->trace && !query->lookup->ns_search_only)
+ printf ( "%.*s", (int)r.length, (char *)r.base);
+ else {
+ result = isc_buffer_allocate(mctx, &b2, BUFSIZE);
+ check_result (result, "isc_buffer_allocate");
+ result = dns_rdatatype_totext(rdata->type, b2);
+ check_result(result, "dns_rdatatype_totext");
+ isc_buffer_usedregion(b2, &r2);
+ printf ( "%.*s %.*s",(int)r2.length, (char *)r2.base,
+ (int)r.length, (char *)r.base);
+ isc_buffer_free (&b2);
+ }
+ if (query->lookup->identify) {
+ result = isc_time_now(&now);
+ check_result (result, "isc_time_now");
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ printf (" from server %s in %d ms", query->servname,
+ (int)diff/1000);
+ }
+ printf ("\n");
+ isc_buffer_free(&b);
+}
+
+static isc_result_t
+printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name,
+ isc_boolean_t headers, dig_query_t *query)
+{
+ dns_name_t *name, *print_name;
+ dns_rdataset_t *rdataset;
+ isc_buffer_t target;
+ isc_result_t result, loopresult;
+ isc_region_t r;
+ dns_name_t empty_name;
+ char t[4096];
+ isc_boolean_t first;
+ isc_boolean_t no_rdata;
+ dns_rdata_t rdata;
+
+ if (sectionid == DNS_SECTION_QUESTION)
+ no_rdata = ISC_TRUE;
+ else
+ no_rdata = ISC_FALSE;
+
+ if (headers && query->lookup->comments && !short_form)
+ printf(";; %s SECTION:\n", section_name);
+
+ dns_name_init(&empty_name, NULL);
+
+ result = dns_message_firstname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, sectionid, &name);
+
+ isc_buffer_init(&target, t, sizeof(t));
+ first = ISC_TRUE;
+ print_name = name;
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (!short_form) {
+ result = dns_rdataset_totext(rdataset,
+ print_name,
+ ISC_FALSE,
+ no_rdata,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#ifdef USEINITALWS
+ if (first) {
+ print_name = &empty_name;
+ first = ISC_FALSE;
+ }
+#endif
+ } else {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ say_message(&rdata, query);
+ loopresult = dns_rdataset_next(
+ rdataset);
+ }
+ }
+
+ }
+ isc_buffer_usedregion(&target, &r);
+ if (no_rdata)
+ printf(";%.*s", (int)r.length, (char *)r.base);
+ else
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ result = dns_message_nextname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
+ char *set_name, isc_boolean_t headers)
+{
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[4096];
+
+ UNUSED(msg);
+ if (headers)
+ printf(";; %s SECTION:\n", set_name);
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
+ isc_boolean_t did_flag = ISC_FALSE;
+ isc_result_t result;
+ dns_rdataset_t *opt, *tsig = NULL;
+ dns_name_t *tsigname;
+
+ 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, "
+ "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 (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
+ headers && query->lookup->section_question) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
+ ISC_TRUE, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]) &&
+ query->lookup->section_answer ) {
+ if (headers && query->lookup->comments && !short_form)
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
+ headers, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if ((! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
+ headers && query->lookup->section_authority) ||
+ ( ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]) &&
+ headers && query->lookup->section_answer &&
+ query->lookup->trace )) {
+ if (headers && query->lookup->comments && !short_form)
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
+ ISC_TRUE, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
+ headers && query->lookup->section_additional) {
+ if (headers && query->lookup->comments && !short_form)
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ADDITIONAL,
+ "ADDITIONAL", ISC_TRUE, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if ((tsig != NULL) && headers && query->lookup->section_additional) {
+ if (headers && query->lookup->comments && !short_form)
+ printf("\n");
+ result = printrdata(msg, tsig, tsigname,
+ "PSEUDOSECTION TSIG", ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (headers && query->lookup->comments && !short_form)
+ printf("\n");
+
+ 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
+ * handle the server options.
+ */
+static void
+reorder_args(int argc, char *argv[]) {
+ int i, j;
+ char *ptr;
+ int end;
+
+ debug ("reorder_args()");
+ end = argc-1;
+ while (argv[end][0] == '@') {
+ end--;
+ if (end == 0)
+ return;
+ }
+ debug ("arg[end]=%s",argv[end]);
+ for (i=1; i= argc) {
+ show_usage();
+ }
+ strncpy (hostname, argv[isc_commandline_index], MXNAME);
+ if (argc > isc_commandline_index+1) {
+ srv=isc_mem_allocate(mctx, sizeof(struct dig_server));
+ if (srv == NULL)
+ fatal ("Memory allocation failure.");
+ strncpy(srv->servername,
+ argv[isc_commandline_index+1], MXNAME-1);
+ debug("Server is %s", srv->servername);
+ ISC_LIST_APPEND(server_list, srv, link);
+ }
+
+ lookup_counter++;
+ if (lookup_counter > LOOKUP_LIMIT)
+ fatal ("Too many lookups.");
+ lookup = isc_mem_allocate (mctx,
+ sizeof(struct dig_lookup));
+ if (lookup == NULL)
+ fatal ("Memory allocation failure.");
+ lookup->pending = ISC_FALSE;
+ /*
+ * XXXMWS Add IPv6 translation here, probably using inet_pton
+ * to extract the formatted text.
+ */
+ if (strcspn(hostname, "0123456789.") != strlen(hostname)) {
+ lookup->textname[0]=0;
+ n = sscanf(hostname, "%d.%d.%d.%d", &adrs[0], &adrs[1],
+ &adrs[2], &adrs[3]);
+ if (n==0) {
+ show_usage();
+ exit (exitcode);
+ }
+ for (i = n - 1; i >= 0; i--) {
+ snprintf(store, MXNAME/8, "%d.",
+ adrs[i]);
+ strncat(lookup->textname, store, MXNAME);
+ }
+ strncat(lookup->textname, "in-addr.arpa.", MXNAME);
+ if (querytype[0] == 0)
+ strcpy (querytype, "ptr");
+ } else
+ strncpy (lookup->textname, hostname, MXNAME);
+ if (querytype[0] == 0)
+ strcpy (querytype, "a");
+ if (queryclass[0] == 0)
+ strcpy (queryclass, "in");
+ strncpy (lookup->rttext, querytype, 32);
+ strncpy (lookup->rctext, queryclass, 32);
+ lookup->namespace[0]=0;
+ lookup->sendspace[0]=0;
+ lookup->sendmsg=NULL;
+ lookup->name=NULL;
+ lookup->oname=NULL;
+ lookup->timer = NULL;
+ lookup->xfr_q = NULL;
+ lookup->origin = NULL;
+ lookup->doing_xfr = ISC_FALSE;
+ lookup->defname = ISC_FALSE;
+ lookup->identify = ISC_FALSE;
+ lookup->recurse = recursion;
+ lookup->ns_search_only = showallsoa;
+ lookup->use_my_server_list = ISC_FALSE;
+ lookup->retries = tries;
+ lookup->nsfound = 0;
+ lookup->trace = showallsoa;
+ lookup->trace_root = ISC_FALSE;
+ ISC_LIST_INIT(lookup->q);
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ lookup->origin = NULL;
+ ISC_LIST_INIT(lookup->my_server_list);
+ have_host = ISC_TRUE;
+}
+
+int
+main(int argc, char **argv) {
+ dig_lookup_t *lookup = NULL;
+ isc_result_t result;
+#ifdef TWIDDLE
+ FILE *fp;
+ int i, p;
+#endif
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+#ifdef TWIDDLE
+ fp = fopen("/dev/urandom", "r");
+ if (fp!=NULL) {
+ fread (&i, sizeof(int), 1, fp);
+ srandom(i);
+ }
+ else {
+ srandom ((int)&main);
+ }
+ p = getpid()%16+8;
+ for (i=0 ; i