diff --git a/bin/dig/host.c b/bin/dig/host.c new file mode 100644 index 0000000000..7fb098780d --- /dev/null +++ b/bin/dig/host.c @@ -0,0 +1,485 @@ +/* + * Copyright (C) 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +#include + +#include +#include +#include +#include +#include + +extern int h_errno; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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_boolean_t tcp_mode, + recurse, + have_ipv6; +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 dns_name_t rootorg; +extern char *rootspace[BUFSIZE]; +extern isc_buffer_t rootbuf; +extern int sendcount; + +isc_boolean_t short_form=ISC_TRUE, + filter=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" +}; + +void +check_next_lookup (dig_lookup_t *lookup) { + dig_lookup_t *next; + dig_query_t *query; + isc_boolean_t still_working=ISC_FALSE; + +#ifdef DEBUG + puts ("In check_next_lookup"); +#endif + for (query = ISC_LIST_HEAD(lookup->q); + query != NULL; + query = ISC_LIST_NEXT(query, link)) { + if (query->working) { +#ifdef DEBUG + puts ("Still have a worker."); +#endif + still_working=ISC_TRUE; + } + } + if (still_working) + return; + + next = ISC_LIST_NEXT (lookup, link); + if (next == NULL) { +#ifdef DEBUG + puts ("Shutting Down."); +#endif + isc_app_shutdown(); + return; + } + + setup_lookup(next); +#ifdef NEVER + if (tcp_mode) + do_lookup_tcp(next); + else +#endif + do_lookup_udp(next); + +} + +static void +show_usage() { + fatal ("Usage."); +} + +static void +say_message(char *host, char *msg, dns_rdata_t *rdata, isc_buffer_t *target) { + isc_region_t r; + isc_result_t result; + + result = dns_rdata_totext( rdata, NULL, target); + check_result(result, "dns_rdata_totext"); + isc_buffer_used(target, &r); + printf ( "%s %s %.*s\n", host, msg, (int)r.length, + (char *)r.base); +} + + +static isc_result_t +printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name, + isc_boolean_t headers) +{ + dns_name_t *name, *print_name; + dns_rdataset_t *rdataset; + dns_rdata_t rdata; + 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; + + if (sectionid == DNS_SECTION_QUESTION) + no_rdata = ISC_TRUE; + else + no_rdata = ISC_FALSE; + + if (headers) + 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, ISC_BUFFERTYPE_TEXT); + 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); + if (rdata.type == dns_rdatatype_a) { + say_message ("Something", + "has address", + &rdata, + &target); + } else if + (rdata.type == dns_rdatatype_mx) { + say_message ("Something", + "mail server", + &rdata, + &target); + } else if + (rdata.type == dns_rdatatype_ns) { + say_message ("Something", + "name server", + &rdata, + &target); + } + loopresult = dns_rdataset_next( + rdataset); + } + } + } + if (!short_form) { + isc_buffer_used(&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, ISC_BUFFERTYPE_TEXT); + + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_used(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +isc_result_t +printmessage(dns_message_t *msg, isc_boolean_t headers) { + isc_boolean_t did_flag = ISC_FALSE; + dns_rdataset_t *opt, *tsig; + dns_name_t *tsigname; + isc_result_t result; + + result = ISC_R_SUCCESS; + + if (!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]) && + !short_form ) { + printf("\n"); + result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", + ISC_TRUE); + if (result != ISC_R_SUCCESS) + return (result); + } + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { + if (!short_form) + printf("\n"); + result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", + !short_form); + if (result != ISC_R_SUCCESS) + return (result); + } + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && + !short_form ) { + printf("\n"); + result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", + ISC_TRUE); + if (result != ISC_R_SUCCESS) + return (result); + } + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && + !short_form ) { + printf("\n"); + result = printsection(msg, DNS_SECTION_ADDITIONAL, + "ADDITIONAL", ISC_TRUE); + if (result != ISC_R_SUCCESS) + return (result); + } + if ((tsig != NULL) && !short_form) { + printf("\n"); + result = printrdata(msg, tsig, tsigname, + "PSEUDOSECTION TSIG", ISC_TRUE); + if (result != ISC_R_SUCCESS) + return (result); + } + if (!short_form) + printf("\n"); + + return (result); +} + +void +parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { + isc_boolean_t have_host=ISC_FALSE, + recursion=ISC_TRUE, + xfr_mode=ISC_FALSE; + char hostname[MXNAME]; + char servname[MXNAME]; + char querytype[32]="a"; + dig_server_t *srv; + dig_lookup_t *lookup; + int c; + + while ((c = isc_commandline_parse(argc, argv,"lvwrdt:a")) != EOF) { + switch (c) { + case 'l': + tcp_mode = ISC_TRUE; + xfr_mode = ISC_TRUE; + filter = ISC_TRUE; + strcpy (querytype, "axfr"); + break; + case 'v': + case 'd': + short_form = ISC_FALSE; + break; + case 'r': + recursion = ISC_FALSE; + break; + case 't': + strncpy (querytype, isc_commandline_argument, 32); + break; + case 'a': + strcpy (querytype, "any"); + short_form = ISC_FALSE; + break; + case 'w': + /* XXXMWS This should be a system-indep. + thing! */ + timeout = 32767; + break; + } + } + if (isc_commandline_index >= 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); +#ifdef DEBUG + fprintf (stderr, "Server is %s\n",srv->servername); +#endif + ISC_LIST_APPEND(server_list, srv, link); + } + + lookup = isc_mem_allocate (mctx, + sizeof(struct dig_lookup)); + if (lookup == NULL) + fatal ("Memory allocation failure."); + lookup->pending = ISC_FALSE; + strncpy (lookup->textname, hostname, MXNAME); + strncpy (lookup->rttext, querytype, 32); + strcpy (lookup->rctext,"in"); + lookup->namespace[0]=0; + lookup->sendspace[0]=0; + lookup->sendmsg=NULL; + lookup->name=NULL; + lookup->timer = NULL; + lookup->xfr_q = NULL; + lookup->doing_xfr = ISC_FALSE; + ISC_LIST_INIT(lookup->q); + ISC_LIST_APPEND(lookup_list, lookup, link); + have_host = ISC_TRUE; +} +