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");