2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: host.c,v 1.76.2.6 2004/03/09 06:09:13 marka Exp $ */
25 #include <isc/commandline.h>
26 #include <isc/netaddr.h>
27 #include <isc/string.h>
31 #include <dns/byaddr.h>
32 #include <dns/fixedname.h>
33 #include <dns/message.h>
35 #include <dns/rdata.h>
36 #include <dns/rdataclass.h>
37 #include <dns/rdataset.h>
38 #include <dns/rdatatype.h>
42 extern ISC_LIST(dig_lookup_t) lookup_list;
43 extern ISC_LIST(dig_server_t) server_list;
44 extern ISC_LIST(dig_searchlist_t) search_list;
46 extern isc_boolean_t usesearch;
47 extern isc_boolean_t debugging;
48 extern unsigned int timeout;
49 extern isc_mem_t *mctx;
52 extern char *progname;
53 extern isc_task_t *global_task;
56 static isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE;
57 static isc_boolean_t list_addresses = ISC_TRUE;
58 static dns_rdatatype_t list_type = dns_rdatatype_a;
60 static const char *opcodetext[] = {
79 static const char *rcodetext[] = {
99 static const char *rtypetext[] = {
101 "has address", /* 1 */
102 "name server", /* 2 */
105 "is an alias for", /* 5 */
111 "has well known services", /* 11 */
112 "domain name pointer", /* 12 */
113 "host information", /* 13 */
115 "mail is handled by", /* 15 */
119 "x25 address", /* 19 */
120 "isdn address", /* 20 */
124 "has signature", /* 24 */
128 "has AAAA address", /* 28 */
130 "has next record", /* 30 */
138 "has v6 address", /* 38 */
140 "has optional information", /* 41 */
141 "has 42 record", /* 42 */
142 "has 43 record", /* 43 */
143 "has 44 record", /* 44 */
144 "has 45 record", /* 45 */
145 "has 46 record", /* 46 */
146 "has 47 record", /* 47 */
147 "has 48 record", /* 48 */
148 "has 49 record", /* 49 */
149 "has 50 record", /* 50 */
150 "has 51 record", /* 51 */
151 "has 52 record", /* 52 */
152 "has 53 record", /* 53 */
153 "has 54 record", /* 54 */
154 "has 55 record", /* 55 */
155 "has 56 record", /* 56 */
156 "has 57 record", /* 57 */
157 "has 58 record", /* 58 */
158 "has 59 record", /* 59 */
159 "has 60 record", /* 60 */
160 "has 61 record", /* 61 */
161 "has 62 record", /* 62 */
162 "has 63 record", /* 63 */
163 "has 64 record", /* 64 */
164 "has 65 record", /* 65 */
165 "has 66 record", /* 66 */
166 "has 67 record", /* 67 */
167 "has 68 record", /* 68 */
168 "has 69 record", /* 69 */
169 "has 70 record", /* 70 */
170 "has 71 record", /* 71 */
171 "has 72 record", /* 72 */
172 "has 73 record", /* 73 */
173 "has 74 record", /* 74 */
174 "has 75 record", /* 75 */
175 "has 76 record", /* 76 */
176 "has 77 record", /* 77 */
177 "has 78 record", /* 78 */
178 "has 79 record", /* 79 */
179 "has 80 record", /* 80 */
180 "has 81 record", /* 81 */
181 "has 82 record", /* 82 */
182 "has 83 record", /* 83 */
183 "has 84 record", /* 84 */
184 "has 85 record", /* 85 */
185 "has 86 record", /* 86 */
186 "has 87 record", /* 87 */
187 "has 88 record", /* 88 */
188 "has 89 record", /* 89 */
189 "has 90 record", /* 90 */
190 "has 91 record", /* 91 */
191 "has 92 record", /* 92 */
192 "has 93 record", /* 93 */
193 "has 94 record", /* 94 */
194 "has 95 record", /* 95 */
195 "has 96 record", /* 96 */
196 "has 97 record", /* 97 */
197 "has 98 record", /* 98 */
198 "has 99 record", /* 99 */
208 "Usage: host [-aCdlrTwv] [-c class] [-n] [-N ndots] [-t type] [-W time]\n"
209 " [-R number] hostname [server]\n"
210 " -a is equivalent to -v -t *\n"
211 " -c specifies query class for non-IN data\n"
212 " -C compares SOA records on authoritative nameservers\n"
213 " -d is equivalent to -v\n"
214 " -l lists all hosts in a domain, using AXFR\n"
215 " -i Use the old IN6.INT form of IPv6 reverse lookup\n"
216 " -N changes the number of dots allowed before root lookup is done\n"
217 " -r disables recursive processing\n"
218 " -R specifies number of retries for UDP packets\n"
219 " -t specifies the query type\n"
220 " -T enables TCP/IP mode\n"
221 " -v enables verbose output\n"
222 " -w specifies to wait forever for a reply\n"
223 " -W specifies how long to wait for a reply\n", stderr);
228 dighost_shutdown(void) {
233 received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
240 char fromtext[ISC_SOCKADDR_FORMATSIZE];
241 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
242 result = isc_time_now(&now);
243 check_result(result, "isc_time_now");
244 diff = (int) isc_time_microdiff(&now, &query->time_sent);
245 printf("Received %u bytes from %s in %d ms\n",
246 bytes, fromtext, diff/1000);
251 trying(char *frm, dig_lookup_t *lookup) {
255 printf("Trying \"%s\"\n", frm);
259 say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
262 isc_buffer_t *b = NULL;
263 char namestr[DNS_NAME_FORMATSIZE];
266 unsigned int bufsize = BUFSIZ;
268 dns_name_format(name, namestr, sizeof(namestr));
270 result = isc_buffer_allocate(mctx, &b, bufsize);
271 check_result(result, "isc_buffer_allocate");
272 result = dns_rdata_totext(rdata, NULL, b);
273 if (result == ISC_R_NOSPACE) {
278 check_result(result, "dns_rdata_totext");
279 isc_buffer_usedregion(b, &r);
280 if (query->lookup->identify_previous_line) {
281 printf("Nameserver %s:\n\t",
284 printf("%s %s %.*s", namestr,
285 msg, (int)r.length, (char *)r.base);
286 if (query->lookup->identify) {
287 printf(" on server %s", query->servname);
295 printsection(dns_message_t *msg, dns_section_t sectionid,
296 const char *section_name, isc_boolean_t headers,
299 dns_name_t *name, *print_name;
300 dns_rdataset_t *rdataset;
301 dns_rdata_t rdata = DNS_RDATA_INIT;
303 isc_result_t result, loopresult;
305 dns_name_t empty_name;
308 isc_boolean_t no_rdata;
311 if (sectionid == DNS_SECTION_QUESTION)
314 no_rdata = ISC_FALSE;
317 printf(";; %s SECTION:\n", section_name);
319 dns_name_init(&empty_name, NULL);
321 result = dns_message_firstname(msg, sectionid);
322 if (result == ISC_R_NOMORE)
323 return (ISC_R_SUCCESS);
324 else if (result != ISC_R_SUCCESS)
329 dns_message_currentname(msg, sectionid, &name);
331 isc_buffer_init(&target, t, sizeof(t));
335 for (rdataset = ISC_LIST_HEAD(name->list);
337 rdataset = ISC_LIST_NEXT(rdataset, link)) {
338 if (query->lookup->rdtype == dns_rdatatype_axfr &&
339 !((!list_addresses &&
340 (list_type == dns_rdatatype_any ||
341 rdataset->type == list_type)) ||
343 (rdataset->type == dns_rdatatype_a ||
344 rdataset->type == dns_rdatatype_aaaa ||
345 rdataset->type == dns_rdatatype_ns ||
346 rdataset->type == dns_rdatatype_ptr))))
349 result = dns_rdataset_totext(rdataset,
354 if (result != ISC_R_SUCCESS)
358 print_name = &empty_name;
362 UNUSED(first); /* Shut up compiler. */
365 loopresult = dns_rdataset_first(rdataset);
366 while (loopresult == ISC_R_SUCCESS) {
367 dns_rdataset_current(rdataset, &rdata);
368 if (rdata.type <= 103)
369 rtt = rtypetext[rdata.type];
370 else if (rdata.type == 249)
372 else if (rdata.type == 250)
376 say_message(print_name, rtt,
378 dns_rdata_reset(&rdata);
380 dns_rdataset_next(rdataset);
385 isc_buffer_usedregion(&target, &r);
387 printf(";%.*s", (int)r.length,
390 printf("%.*s", (int)r.length, (char *)r.base);
393 result = dns_message_nextname(msg, sectionid);
394 if (result == ISC_R_NOMORE)
396 else if (result != ISC_R_SUCCESS)
400 return (ISC_R_SUCCESS);
404 printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
405 const char *set_name, isc_boolean_t headers)
414 printf(";; %s SECTION:\n", set_name);
416 isc_buffer_init(&target, t, sizeof(t));
418 result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
420 if (result != ISC_R_SUCCESS)
422 isc_buffer_usedregion(&target, &r);
423 printf("%.*s", (int)r.length, (char *)r.base);
425 return (ISC_R_SUCCESS);
429 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
430 isc_boolean_t did_flag = ISC_FALSE;
431 dns_rdataset_t *opt, *tsig = NULL;
432 dns_name_t *tsigname;
433 isc_result_t result = ISC_R_SUCCESS;
438 char sockstr[ISC_SOCKADDR_FORMATSIZE];
440 printf("Using domain server:\n");
441 printf("Name: %s\n", query->servname);
442 isc_sockaddr_format(&query->sockaddr, sockstr,
444 printf("Address: %s\n", sockstr);
445 printf("Aliases: \n\n");
448 if (msg->rcode != 0) {
449 char namestr[DNS_NAME_FORMATSIZE];
450 dns_name_format(query->lookup->name, namestr, sizeof(namestr));
451 printf("Host %s not found: %d(%s)\n", namestr,
452 msg->rcode, rcodetext[msg->rcode]);
453 return (ISC_R_SUCCESS);
456 printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
457 opcodetext[msg->opcode], rcodetext[msg->rcode],
459 printf(";; flags: ");
460 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
464 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
465 printf("%saa", did_flag ? " " : "");
468 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
469 printf("%stc", did_flag ? " " : "");
472 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
473 printf("%srd", did_flag ? " " : "");
476 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
477 printf("%sra", did_flag ? " " : "");
480 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
481 printf("%sad", did_flag ? " " : "");
484 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
485 printf("%scd", did_flag ? " " : "");
488 printf("; QUERY: %u, ANSWER: %u, "
489 "AUTHORITY: %u, ADDITIONAL: %u\n",
490 msg->counts[DNS_SECTION_QUESTION],
491 msg->counts[DNS_SECTION_ANSWER],
492 msg->counts[DNS_SECTION_AUTHORITY],
493 msg->counts[DNS_SECTION_ADDITIONAL]);
494 opt = dns_message_getopt(msg);
496 printf(";; EDNS: version: %u, udp=%u\n",
497 (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
498 (unsigned int)opt->rdclass);
500 tsig = dns_message_gettsig(msg, &tsigname);
502 printf(";; PSEUDOSECTIONS: TSIG\n");
504 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
507 result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
509 if (result != ISC_R_SUCCESS)
512 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
515 result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
516 ISC_TF(!short_form), query);
517 if (result != ISC_R_SUCCESS)
521 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
524 result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
526 if (result != ISC_R_SUCCESS)
529 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
532 result = printsection(msg, DNS_SECTION_ADDITIONAL,
533 "ADDITIONAL", ISC_TRUE, query);
534 if (result != ISC_R_SUCCESS)
537 if ((tsig != NULL) && !short_form) {
539 result = printrdata(msg, tsig, tsigname,
540 "PSEUDOSECTION TSIG", ISC_TRUE);
541 if (result != ISC_R_SUCCESS)
551 parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
552 char hostname[MXNAME];
554 dig_lookup_t *lookup;
558 isc_result_t result = ISC_R_SUCCESS;
559 dns_rdatatype_t rdtype;
560 dns_rdataclass_t rdclass;
562 UNUSED(is_batchfile);
564 lookup = make_empty_lookup();
566 while ((c = isc_commandline_parse(argc, argv, "ilvwrdt:c:aTCN:R:W:Dn"))
570 lookup->tcp_mode = ISC_TRUE;
571 lookup->rdtype = dns_rdatatype_axfr;
572 lookup->rdtypeset = ISC_TRUE;
577 short_form = ISC_FALSE;
580 lookup->recurse = ISC_FALSE;
583 tr.base = isc_commandline_argument;
584 tr.length = strlen(isc_commandline_argument);
585 result = dns_rdatatype_fromtext(&rdtype,
586 (isc_textregion_t *)&tr);
588 if (result != ISC_R_SUCCESS) {
590 fatal("invalid type: %s\n",
591 isc_commandline_argument);
593 if (!lookup->rdtypeset ||
594 lookup->rdtype != dns_rdatatype_axfr)
595 lookup->rdtype = rdtype;
596 if (rdtype == dns_rdatatype_axfr) {
598 list_type = dns_rdatatype_any;
599 short_form = ISC_FALSE;
600 lookup->tcp_mode = ISC_TRUE;
603 list_addresses = ISC_FALSE;
606 tr.base = isc_commandline_argument;
607 tr.length = strlen(isc_commandline_argument);
608 result = dns_rdataclass_fromtext(&rdclass,
609 (isc_textregion_t *)&tr);
611 if (result != ISC_R_SUCCESS) {
613 fatal("invalid class: %s\n",
614 isc_commandline_argument);
616 lookup->rdclass = rdclass;
617 lookup->rdclassset = ISC_TRUE;
621 if (!lookup->rdtypeset ||
622 lookup->rdtype != dns_rdatatype_axfr)
623 lookup->rdtype = dns_rdatatype_any;
624 list_type = dns_rdatatype_any;
625 list_addresses = ISC_FALSE;
626 lookup->rdtypeset = ISC_TRUE;
627 short_form = ISC_FALSE;
630 lookup->ip6_int = ISC_TRUE;
636 * The timer routines are coded such that
637 * timeout==MAXINT doesn't enable the timer
642 timeout = atoi(isc_commandline_argument);
647 tries = atoi(isc_commandline_argument);
652 lookup->tcp_mode = ISC_TRUE;
655 debug("showing all SOAs");
656 lookup->rdtype = dns_rdatatype_ns;
657 lookup->rdtypeset = ISC_TRUE;
658 lookup->rdclass = dns_rdataclass_in;
659 lookup->rdclassset = ISC_TRUE;
660 lookup->ns_search_only = ISC_TRUE;
661 lookup->trace_root = ISC_TRUE;
662 lookup->identify_previous_line = ISC_TRUE;
665 debug("setting NDOTS to %s",
666 isc_commandline_argument);
667 ndots = atoi(isc_commandline_argument);
670 debugging = ISC_TRUE;
674 if (isc_commandline_index >= argc) {
677 strncpy(hostname, argv[isc_commandline_index], sizeof(hostname));
678 hostname[sizeof(hostname)-1]=0;
679 if (argc > isc_commandline_index + 1) {
680 srv = make_server(argv[isc_commandline_index+1]);
681 debug("server is %s", srv->servername);
682 ISC_LIST_APPEND(server_list, srv, link);
683 listed_server = ISC_TRUE;
686 lookup->pending = ISC_FALSE;
687 if (get_reverse(store, hostname, lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS)
689 strncpy(lookup->textname, store, sizeof(lookup->textname));
690 lookup->textname[sizeof(lookup->textname)-1] = 0;
691 lookup->rdtype = dns_rdatatype_ptr;
692 lookup->rdtypeset = ISC_TRUE;
694 strncpy(lookup->textname, hostname, sizeof(lookup->textname));
695 lookup->textname[sizeof(lookup->textname)-1]=0;
697 lookup->new_search = ISC_TRUE;
698 ISC_LIST_APPEND(lookup_list, lookup, link);
700 usesearch = ISC_TRUE;
704 main(int argc, char **argv) {
707 ISC_LIST_INIT(lookup_list);
708 ISC_LIST_INIT(server_list);
709 ISC_LIST_INIT(search_list);
715 result = isc_app_start();
716 check_result(result, "isc_app_start");
718 parse_args(ISC_FALSE, argc, argv);
720 result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
721 check_result(result, "isc_app_onrun");