dig.c revision 1a69a1a78cfaa86f3b68bbc965232b7876d4da2a
36a048753a41b465ae130b361fb3b68c605e3e86kiirala/*
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * Copyright (C) 2000 Internet Software Consortium.
36a048753a41b465ae130b361fb3b68c605e3e86kiirala *
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * Permission to use, copy, modify, and distribute this software for any
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * purpose with or without fee is hereby granted, provided that the above
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * copyright notice and this permission notice appear in all copies.
fb86717633bfcfe161571aed7058ea6a39b7a69bkiirala *
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
8635140fb4734dae6ae5f42e1db9778749ef024aKrzysztof Kosiński * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
8635140fb4734dae6ae5f42e1db9778749ef024aKrzysztof Kosiński * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
36a048753a41b465ae130b361fb3b68c605e3e86kiirala * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
8635140fb4734dae6ae5f42e1db9778749ef024aKrzysztof Kosiński * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski * SOFTWARE.
7f18e8ab01ce21c98cc7b9f58ffe5e771ebbb64eLiam P. White */
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#include <config.h>
36a048753a41b465ae130b361fb3b68c605e3e86kiirala
5c40454c286013e02d9ea7521a3bdaf72bea39d9tavmjong-free#include <stdlib.h>
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelenextern int h_errno;
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#include <isc/app.h>
8635140fb4734dae6ae5f42e1db9778749ef024aKrzysztof Kosiński#include <isc/string.h>
8635140fb4734dae6ae5f42e1db9778749ef024aKrzysztof Kosiński#include <isc/util.h>
8635140fb4734dae6ae5f42e1db9778749ef024aKrzysztof Kosiński
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#include <dns/message.h>
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#include <dns/rdata.h>
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#include <dns/rdataset.h>
a72861cd83f11ef8b1247abca181a3ad31df0307kiirala#include <dns/rdatatype.h>
a72861cd83f11ef8b1247abca181a3ad31df0307kiirala
4d2111f1991274cf80f89219637fca969697e661Krzysztof Kosiński#include <dig/dig.h>
7f18e8ab01ce21c98cc7b9f58ffe5e771ebbb64eLiam P. White
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinskiextern ISC_LIST(dig_lookup_t) lookup_list;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern ISC_LIST(dig_server_t) server_list;
36a048753a41b465ae130b361fb3b68c605e3e86kiirala
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_boolean_t tcp_mode, have_ipv6, show_details,
36a048753a41b465ae130b361fb3b68c605e3e86kiirala usesearch, trace;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern in_port_t port;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern unsigned int timeout;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_mem_t *mctx;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_taskmgr_t *taskmgr;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_task_t *task;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_timermgr_t *timermgr;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_socketmgr_t *socketmgr;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern dns_messageid_t id;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern char *rootspace[BUFSIZE];
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_buffer_t rootbuf;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern int sendcount;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern int ndots;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern int tries;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern int lookup_counter;
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern char fixeddomain[MXNAME];
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#ifdef TWIDDLE
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaextern isc_boolean_t twiddle;
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#endif
36a048753a41b465ae130b361fb3b68c605e3e86kiirala
36a048753a41b465ae130b361fb3b68c605e3e86kiiralaisc_boolean_t short_form = ISC_FALSE;
36a048753a41b465ae130b361fb3b68c605e3e86kiirala
36a048753a41b465ae130b361fb3b68c605e3e86kiirala
36a048753a41b465ae130b361fb3b68c605e3e86kiiralastatic char *opcodetext[] = {
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "QUERY",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "IQUERY",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "STATUS",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "RESERVED3",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "NOTIFY",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "UPDATE",
1cf2607271f83cc4b20ccace552395d793055c90Krzysztof Kosiński "RESERVED6",
1cf2607271f83cc4b20ccace552395d793055c90Krzysztof Kosiński "RESERVED7",
1cf2607271f83cc4b20ccace552395d793055c90Krzysztof Kosiński "RESERVED8",
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński "RESERVED9",
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński "RESERVED10",
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński "RESERVED11",
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński "RESERVED12",
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński "RESERVED13",
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński "RESERVED14",
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński "RESERVED15"
d1eeafe871c5909edd05ee72dfa603533ad39a87Krzysztof Kosiński};
1cf2607271f83cc4b20ccace552395d793055c90Krzysztof Kosiński
36a048753a41b465ae130b361fb3b68c605e3e86kiiralastatic char *rcodetext[] = {
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "NOERROR",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "FORMERR",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "SERVFAIL",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "NXDOMAIN",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "NOTIMPL",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "REFUSED",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "YXDOMAIN",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "YXRRSET",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "NXRRSET",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "NOTAUTH",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "NOTZONE",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "RESERVED11",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "RESERVED12",
36a048753a41b465ae130b361fb3b68c605e3e86kiirala "RESERVED13",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "RESERVED14",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "RESERVED15",
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free "BADVERS"
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free};
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-freestatic void
36a048753a41b465ae130b361fb3b68c605e3e86kiiralashow_usage() {
712a383b4aa88de4041f1d6247719e2c3a5800d8Jon A. Cruz fputs (
712a383b4aa88de4041f1d6247719e2c3a5800d8Jon A. Cruz"Usage: dig [@server] [domain] [q-type] [q-class] {q-opt} {d-opt}\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński"where: server,\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" domain are in the Domain Name System\n"
8635140fb4734dae6ae5f42e1db9778749ef024aKrzysztof Kosiński" q-class is one of (in,chaos,...) [default: in]\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" q-opt is one of:\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" -x dot-notation (shortcut for in-addr lookups)\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" -f filename (batch mode)\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" -p port (specify port number)\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" -t type (specify query type)\n"
1cf2607271f83cc4b20ccace552395d793055c90Krzysztof Kosiński" -c class (specify query class)\n"
712a383b4aa88de4041f1d6247719e2c3a5800d8Jon A. Cruz" d-opt is of the form +keyword[=value], where keyword is:\n"
712a383b4aa88de4041f1d6247719e2c3a5800d8Jon A. Cruz" +[no]vc (TCP mode)\n"
dff9bb0d25ad38c515c32e2c76a20e747c8eed10Krzysztof Kosiński" +[no]tcp (TCP mode, alternate syntax)\n"
7059798b454ecd2386eb02769ad8d9c6d9d5f98eKrzysztof Kosiński" +time=### (Set query timeout) [5]\n"
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free" +tries=### (Set number of UDP attempts) [3]\n"
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free" +domain=### (Set default domainname)\n"
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free" +[no]search (Set whether to use searchlist)\n"
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free" +[no]recursive (Recursive mode)\n"
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free" +[no]details (Show details of all requests)\n"
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#ifdef TWIDDLE
36a048753a41b465ae130b361fb3b68c605e3e86kiirala" +twiddle (Intentionally form bad requests)\n"
36a048753a41b465ae130b361fb3b68c605e3e86kiirala#endif
36a048753a41b465ae130b361fb3b68c605e3e86kiirala" +ndots=### (Set NDOTS value)\n"
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free" +[no]comments (Control display of comment lines)\n"
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free" +[no]question (Control display of question)\n"
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free" +[no]answer (Control display of answer)\n"
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free" +[no]authority (Control display of authority)\n"
7c89b734639fa72a5d2ffdc9cf1f7ab22eff67f1tavmjong-free" +[no]additional (Control display of additional)\n"
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free" +[no]short (Disable everything except short\n"
9f6f7e74a1ded383518676e0ecb2ccc5caa73d25tavmjong-free" form of answer)\n"
36a048753a41b465ae130b361fb3b68c605e3e86kiirala" Additional d-opts subject to removal before release:\n"
36a048753a41b465ae130b361fb3b68c605e3e86kiirala" +[no]nssearch (Search all authorative nameservers)\n"
36a048753a41b465ae130b361fb3b68c605e3e86kiirala" +[no]identify (ID responders in short answers)\n"
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen" Available but not yet completed:\n"
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen" +[no]trace (Trace delegation down from root)\n"
36a048753a41b465ae130b361fb3b68c605e3e86kiirala, stderr);
36a048753a41b465ae130b361fb3b68c605e3e86kiirala}
36a048753a41b465ae130b361fb3b68c605e3e86kiirala
36a048753a41b465ae130b361fb3b68c605e3e86kiiralavoid
36a048753a41b465ae130b361fb3b68c605e3e86kiiralacheck_next_lookup(dig_lookup_t *lookup) {
36a048753a41b465ae130b361fb3b68c605e3e86kiirala dig_lookup_t *next;
36a048753a41b465ae130b361fb3b68c605e3e86kiirala dig_query_t *query;
36a048753a41b465ae130b361fb3b68c605e3e86kiirala isc_boolean_t still_working=ISC_FALSE;
36a048753a41b465ae130b361fb3b68c605e3e86kiirala
36a048753a41b465ae130b361fb3b68c605e3e86kiirala debug("In check_next_lookup", stderr);
36a048753a41b465ae130b361fb3b68c605e3e86kiirala for (query = ISC_LIST_HEAD(lookup->q);
36a048753a41b465ae130b361fb3b68c605e3e86kiirala query != NULL;
36a048753a41b465ae130b361fb3b68c605e3e86kiirala query = ISC_LIST_NEXT(query, link)) {
36a048753a41b465ae130b361fb3b68c605e3e86kiirala if (query->working) {
a4030d5ca449e7e384bc699cd249ee704faaeab0Chris Morgan debug("Still have a worker.", stderr);
still_working=ISC_TRUE;
}
}
if (still_working)
return;
next = ISC_LIST_NEXT(lookup, link);
debug ("Have %d retries left for %s\n",
lookup->retries, lookup->textname);
if ((next == NULL)&&((lookup->retries <= 1)
||tcp_mode || !lookup->pending)) {
debug("Shutting Down.", stderr);
isc_app_shutdown();
return;
}
if (tcp_mode) {
setup_lookup(next);
do_lookup_tcp(next);
} else {
if ((lookup->retries > 1) && (lookup->pending)) {
lookup->retries --;
send_udp(lookup);
} else {
ENSURE (next != NULL);
setup_lookup(next);
do_lookup_udp(next);
}
}
}
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->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));
} 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) {
if (lookup->comments && !short_form)
printf ("; Trying %.*s\n", frmsize, frm);
}
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);
result = ISC_R_SUCCESS;
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);
}
/*
* 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<end-1; i++) {
if (argv[i][0]=='@') {
debug ("Arg[%d]=%s", i, argv[i]);
ptr=argv[i];
for (j=i+1; j<end; j++) {
debug ("Moving %s to %d", argv[j], j-1);
argv[j-1]=argv[j];
}
debug ("Moving %s to end, %d", ptr, end-1);
argv[end-1]=ptr;
end--;
if (end < 1)
return;
}
}
}
/*
* 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
* that routine. There is a portability issue here.
*/
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;
char batchline[MXNAME];
FILE *fp = NULL;
int bargc;
char *bargv[16];
int i, n;
int adrs[4];
for (argc--, argv++; argc > 0; argc--, argv++) {
debug ("Main parsing %s", argv[0]);
if (strncmp(argv[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);
if (is_batchfile && have_host) {
if (!lookup->use_my_server_list) {
ISC_LIST_INIT (lookup->
my_server_list);
lookup->use_my_server_list =
ISC_TRUE;
}
ISC_LIST_APPEND(lookup->my_server_list,
srv, link);
} else {
ISC_LIST_APPEND(server_list, srv, link);
}
} else if ((strcmp(argv[0], "+vc") == 0)
&& (!is_batchfile)) {
tcp_mode = ISC_TRUE;
} else if ((strcmp(argv[0], "+novc") == 0)
&& (!is_batchfile)) {
tcp_mode = ISC_FALSE;
} else if ((strcmp(argv[0], "+tcp") == 0)
&& (!is_batchfile)) {
tcp_mode = ISC_TRUE;
} else if ((strcmp(argv[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) {
usesearch = ISC_TRUE;
} else if (strncmp(argv[0], "+nosea", 6) == 0) {
usesearch = ISC_FALSE;
} else if (strncmp(argv[0], "+time=", 6) == 0) {
timeout = atoi(&argv[0][6]);
if (timeout <= 0)
timeout = 1;
} 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;
recurse = ISC_FALSE;
identify = ISC_TRUE;
short_form = ISC_TRUE;
identify = ISC_TRUE;
if (!forcecomment)
comments = ISC_FALSE;
section_additional = ISC_FALSE;
section_authority = ISC_FALSE;
section_question = ISC_FALSE;
} else if (strncmp(argv[0], "+nons", 6) == 0) {
ns_search_only = ISC_FALSE;
} else if (strncmp(argv[0], "+tr", 3) == 0) {
trace = ISC_TRUE;
recurse = ISC_FALSE;
identify = ISC_TRUE;
if (!forcecomment)
comments = 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) {
trace = 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], "+sho", 4) == 0) {
short_form = ISC_TRUE;
if (!forcecomment)
comments = ISC_FALSE;
section_additional = ISC_FALSE;
section_authority = ISC_FALSE;
section_question = ISC_FALSE;
} else if (strncmp(argv[0], "+nosho", 6) == 0) {
short_form = ISC_FALSE;
} else if (strncmp(argv[0], "+id", 3) == 0) {
identify = ISC_TRUE;
} else if (strncmp(argv[0], "+noid", 5) == 0) {
identify = ISC_FALSE;
} else if (strncmp(argv[0], "+com", 4) == 0) {
comments = ISC_TRUE;
forcecomment = ISC_TRUE;
} else if (strncmp(argv[0], "+nocom", 6) == 0) {
comments = ISC_FALSE;
forcecomment = 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;
} else if (strncmp(argv[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) {
section_question = ISC_FALSE;
section_authority = ISC_FALSE;
section_answer = ISC_FALSE;
section_additional = ISC_FALSE;
comments = ISC_FALSE;
#ifdef TWIDDLE
} else if (strncmp(argv[0], "+twiddle", 6) == 0) {
twiddle = ISC_TRUE;
#endif
} else if (strncmp(argv[0], "-c", 2) == 0) {
if (have_host) {
if (argv[0][2]!=0) {
strncpy(lookup->rctext, &argv[0][2],
MXRD);
} else {
strncpy(lookup->rctext, argv[1],
MXRD);
argv++;
argc--;
}
}
} else if (strncmp(argv[0], "-t", 2) == 0) {
if (have_host) {
if (argv[0][2]!=0) {
strncpy(lookup->rttext, &argv[0][2],
MXRD);
} else {
strncpy(lookup->rttext, argv[1],
MXRD);
argv++;
argc--;
}
}
} else if (strncmp(argv[0], "-f", 2) == 0) {
if (argv[0][2]!=0) {
batchname=&argv[0][2];
} else {
batchname=argv[1];
argv++;
argc--;
}
} else if (strncmp(argv[0], "-p", 2) == 0) {
if (argv[0][2]!=0) {
port=atoi(&argv[0][2]);
} else {
port=atoi(argv[1]);
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]);
if (n == 0)
show_usage();
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;
lookup->textname[0]=0;
for (i = n - 1; i >= 0; i--) {
snprintf(batchline, MXNAME/8, "%d.",
adrs[i]);
strncat(lookup->textname, batchline, MXNAME);
}
strncat(lookup->textname, "in-addr.arpa.", MXNAME);
debug("Looking up %s", lookup->textname);
strcpy(lookup->rttext, "ptr");
strcpy(lookup->rctext, "in");
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->use_my_server_list = ISC_FALSE;
lookup->trace = (trace || ns_search_only);
lookup->trace_root = trace;
lookup->ns_search_only = ns_search_only;
lookup->doing_xfr = ISC_FALSE;
lookup->identify = identify;
lookup->recurse = recurse;
lookup->retries = tries;
lookup->nsfound = 0;
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++;
argc--;
} else {
if (have_host) {
ENSURE(lookup != NULL);
if (istype(argv[0])) {
strncpy(lookup->rttext, argv[0], MXRD);
continue;
} else if (isclass(argv[0])) {
strncpy(lookup->rctext, argv[0],
MXRD);
continue;
}
}
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;
strncpy(lookup->textname, argv[0], MXNAME-1);
lookup->rttext[0]=0;
lookup->rctext[0]=0;
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->use_my_server_list = ISC_FALSE;
lookup->doing_xfr = 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->retries = tries;
lookup->nsfound = 0;
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);
}
}
if (batchname != NULL) {
fp = fopen(batchname, "r");
if (fp == NULL) {
perror(batchname);
fatal("Couldn't open specified batch file.");
}
while (fgets(batchline, MXNAME, fp) != 0) {
debug ("Batch line %s", batchline);
bargc=1;
bargv[bargc]=strtok(batchline, " \t\r\n");
while ((bargv[bargc] != NULL) &&
(bargc < 14 )) {
bargc++;
bargv[bargc]=strtok(NULL, " \t\r\n");
}
bargc--;
bargv[0]="dig";
reorder_args(bargc+1, (char**)bargv);
parse_args(ISC_TRUE, bargc+1, (char**)bargv);
}
}
if (lookup_list.head == NULL) {
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;
lookup->rctext[0]=0;
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->use_my_server_list = ISC_FALSE;
lookup->doing_xfr = 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->retries = tries;
lookup->nsfound = 0;
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_INIT(lookup->my_server_list);
strcpy(lookup->textname, ".");
strcpy(lookup->rttext, "NS");
lookup->rctext[0]=0;
ISC_LIST_APPEND(lookup_list, lookup, link);
}
}