Annotation of src/usr.bin/dig/host.c, Revision 1.10
1.1 florian 1: /*
2: * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3: *
4: * Permission to use, copy, modify, and/or distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14: * PERFORMANCE OF THIS SOFTWARE.
15: */
16:
17: /*! \file */
18: #include <sys/cdefs.h>
19:
20: #include <err.h>
21: #include <limits.h>
22: #include <locale.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #include <unistd.h>
1.10 ! jsg 26: #include <time.h>
! 27: #include <stdint.h>
1.1 florian 28:
29: #include <isc/app.h>
30: #include <isc/util.h>
1.10 ! jsg 31: #include <isc/time.h>
1.1 florian 32:
33: #include <dns/fixedname.h>
34: #include <dns/message.h>
35: #include <dns/name.h>
36: #include <dns/rdata.h>
37: #include <dns/rdataclass.h>
38: #include <dns/rdataset.h>
39: #include <dns/rdatatype.h>
40: #include "rdatastruct.h"
41:
42: #include "dig.h"
43:
44: static isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE;
45: static isc_boolean_t default_lookups = ISC_TRUE;
46: static int seen_error = -1;
47: static isc_boolean_t list_addresses = ISC_TRUE;
48: static dns_rdatatype_t list_type = dns_rdatatype_a;
49: static isc_boolean_t printed_server = ISC_FALSE;
50: static isc_boolean_t ipv4only = ISC_FALSE, ipv6only = ISC_FALSE;
51:
52: static const char *opcodetext[] = {
53: "QUERY",
54: "IQUERY",
55: "STATUS",
56: "RESERVED3",
57: "NOTIFY",
58: "UPDATE",
59: "RESERVED6",
60: "RESERVED7",
61: "RESERVED8",
62: "RESERVED9",
63: "RESERVED10",
64: "RESERVED11",
65: "RESERVED12",
66: "RESERVED13",
67: "RESERVED14",
68: "RESERVED15"
69: };
70:
71: static const char *rcodetext[] = {
72: "NOERROR",
73: "FORMERR",
74: "SERVFAIL",
75: "NXDOMAIN",
76: "NOTIMP",
77: "REFUSED",
78: "YXDOMAIN",
79: "YXRRSET",
80: "NXRRSET",
81: "NOTAUTH",
82: "NOTZONE",
83: "RESERVED11",
84: "RESERVED12",
85: "RESERVED13",
86: "RESERVED14",
87: "RESERVED15",
88: "BADVERS"
89: };
90:
91: struct rtype {
92: unsigned int type;
93: const char *text;
94: };
95:
96: static struct rtype rtypes[] = {
97: { 1, "has address" },
98: { 2, "name server" },
99: { 5, "is an alias for" },
100: { 11, "has well known services" },
101: { 12, "domain name pointer" },
102: { 13, "host information" },
103: { 15, "mail is handled by" },
104: { 16, "descriptive text" },
105: { 19, "x25 address" },
106: { 20, "ISDN address" },
107: { 24, "has signature" },
108: { 25, "has key" },
109: { 28, "has IPv6 address" },
110: { 29, "location" },
111: { 0, NULL }
112: };
113:
114: static char *
115: rcode_totext(dns_rcode_t rcode)
116: {
117: static char buf[sizeof("?65535")];
118: union {
119: const char *consttext;
120: char *deconsttext;
121: } totext;
122:
123: if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
124: snprintf(buf, sizeof(buf), "?%u", rcode);
125: totext.deconsttext = buf;
126: } else
127: totext.consttext = rcodetext[rcode];
128: return totext.deconsttext;
129: }
130:
131: static __dead void
132: show_usage(void);
133:
134: static void
135: show_usage(void) {
136: fputs(
137: "usage: host [-46aCdilrsTVvw] [-c class] [-m flag] [-N ndots] [-R number]\n"
138: " [-t type] [-W wait] name [server]\n", stderr);
139: exit(1);
140: }
141:
142: static void
143: host_shutdown(void) {
144: (void) isc_app_shutdown();
145: }
146:
147: static void
148: received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
1.6 florian 149: struct timespec now;
1.1 florian 150: int diff;
151:
152: if (!short_form) {
153: char fromtext[ISC_SOCKADDR_FORMATSIZE];
154: isc_sockaddr_format(from, fromtext, sizeof(fromtext));
1.9 florian 155: clock_gettime(CLOCK_MONOTONIC, &now);
1.1 florian 156: diff = (int) isc_time_microdiff(&now, &query->time_sent);
157: printf("Received %u bytes from %s in %d ms\n",
158: bytes, fromtext, diff/1000);
159: }
160: }
161:
162: static void
163: trying(char *frm, dig_lookup_t *lookup) {
164: UNUSED(lookup);
165:
166: if (!short_form)
167: printf("Trying \"%s\"\n", frm);
168: }
169:
170: static void
171: say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
172: dig_query_t *query)
173: {
174: isc_buffer_t *b = NULL;
175: char namestr[DNS_NAME_FORMATSIZE];
176: isc_region_t r;
177: isc_result_t result;
178: unsigned int bufsize = BUFSIZ;
179:
180: dns_name_format(name, namestr, sizeof(namestr));
181: retry:
182: result = isc_buffer_allocate(&b, bufsize);
183: check_result(result, "isc_buffer_allocate");
184: result = dns_rdata_totext(rdata, NULL, b);
185: if (result == ISC_R_NOSPACE) {
186: isc_buffer_free(&b);
187: bufsize *= 2;
188: goto retry;
189: }
190: check_result(result, "dns_rdata_totext");
191: isc_buffer_usedregion(b, &r);
192: if (query->lookup->identify_previous_line) {
193: printf("Nameserver %s:\n\t",
194: query->servname);
195: }
196: printf("%s %s %.*s", namestr,
197: msg, (int)r.length, (char *)r.base);
198: if (query->lookup->identify) {
199: printf(" on server %s", query->servname);
200: }
201: printf("\n");
202: isc_buffer_free(&b);
203: }
204: static isc_result_t
205: printsection(dns_message_t *msg, dns_section_t sectionid,
206: const char *section_name, isc_boolean_t headers,
207: dig_query_t *query)
208: {
209: dns_name_t *name, *print_name;
210: dns_rdataset_t *rdataset;
211: dns_rdata_t rdata = DNS_RDATA_INIT;
212: isc_buffer_t target;
213: isc_result_t result, loopresult;
214: isc_region_t r;
215: dns_name_t empty_name;
216: char tbuf[4096];
217: isc_boolean_t first;
218: isc_boolean_t no_rdata;
219:
220: if (sectionid == DNS_SECTION_QUESTION)
221: no_rdata = ISC_TRUE;
222: else
223: no_rdata = ISC_FALSE;
224:
225: if (headers)
226: printf(";; %s SECTION:\n", section_name);
227:
228: dns_name_init(&empty_name, NULL);
229:
230: result = dns_message_firstname(msg, sectionid);
231: if (result == ISC_R_NOMORE)
232: return (ISC_R_SUCCESS);
233: else if (result != ISC_R_SUCCESS)
234: return (result);
235:
236: for (;;) {
237: name = NULL;
238: dns_message_currentname(msg, sectionid, &name);
239:
240: isc_buffer_init(&target, tbuf, sizeof(tbuf));
241: first = ISC_TRUE;
242: print_name = name;
243:
244: for (rdataset = ISC_LIST_HEAD(name->list);
245: rdataset != NULL;
246: rdataset = ISC_LIST_NEXT(rdataset, link)) {
247: if (query->lookup->rdtype == dns_rdatatype_axfr &&
248: !((!list_addresses &&
249: (list_type == dns_rdatatype_any ||
250: rdataset->type == list_type)) ||
251: (list_addresses &&
252: (rdataset->type == dns_rdatatype_a ||
253: rdataset->type == dns_rdatatype_aaaa ||
254: rdataset->type == dns_rdatatype_ns ||
255: rdataset->type == dns_rdatatype_ptr))))
256: continue;
257: if (!short_form) {
258: result = dns_rdataset_totext(rdataset,
259: print_name,
260: ISC_FALSE,
261: no_rdata,
262: &target);
263: if (result != ISC_R_SUCCESS)
264: return (result);
265: UNUSED(first); /* Shut up compiler. */
266: } else {
267: loopresult = dns_rdataset_first(rdataset);
268: while (loopresult == ISC_R_SUCCESS) {
269: struct rtype *t;
270: const char *rtt;
271: char typebuf[DNS_RDATATYPE_FORMATSIZE];
272: char typebuf2[DNS_RDATATYPE_FORMATSIZE
273: + 20];
274: dns_rdataset_current(rdataset, &rdata);
275:
276: for (t = rtypes; t->text != NULL; t++) {
277: if (t->type == rdata.type) {
278: rtt = t->text;
279: goto found;
280: }
281: }
282:
283: dns_rdatatype_format(rdata.type,
284: typebuf,
285: sizeof(typebuf));
286: snprintf(typebuf2, sizeof(typebuf2),
287: "has %s record", typebuf);
288: rtt = typebuf2;
289: found:
290: say_message(print_name, rtt,
291: &rdata, query);
292: dns_rdata_reset(&rdata);
293: loopresult =
294: dns_rdataset_next(rdataset);
295: }
296: }
297: }
298: if (!short_form) {
299: isc_buffer_usedregion(&target, &r);
300: if (no_rdata)
301: printf(";%.*s", (int)r.length,
302: (char *)r.base);
303: else
304: printf("%.*s", (int)r.length, (char *)r.base);
305: }
306:
307: result = dns_message_nextname(msg, sectionid);
308: if (result == ISC_R_NOMORE)
309: break;
310: else if (result != ISC_R_SUCCESS)
311: return (result);
312: }
313:
314: return (ISC_R_SUCCESS);
315: }
316:
317: static isc_result_t
318: printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
319: const char *set_name, isc_boolean_t headers)
320: {
321: isc_buffer_t target;
322: isc_result_t result;
323: isc_region_t r;
324: char tbuf[4096];
325:
326: UNUSED(msg);
327: if (headers)
328: printf(";; %s SECTION:\n", set_name);
329:
330: isc_buffer_init(&target, tbuf, sizeof(tbuf));
331:
332: result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
333: &target);
334: if (result != ISC_R_SUCCESS)
335: return (result);
336: isc_buffer_usedregion(&target, &r);
337: printf("%.*s", (int)r.length, (char *)r.base);
338:
339: return (ISC_R_SUCCESS);
340: }
341:
342: static void
343: chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
344: isc_result_t result;
345: dns_rdataset_t *rdataset;
346: dns_rdata_cname_t cname;
347: dns_rdata_t rdata = DNS_RDATA_INIT;
348: unsigned int i = msg->counts[DNS_SECTION_ANSWER];
349:
350: while (i-- > 0) {
351: rdataset = NULL;
352: result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
353: dns_rdatatype_cname, 0, NULL,
354: &rdataset);
355: if (result != ISC_R_SUCCESS)
356: return;
357: result = dns_rdataset_first(rdataset);
358: check_result(result, "dns_rdataset_first");
359: dns_rdata_reset(&rdata);
360: dns_rdataset_current(rdataset, &rdata);
361: result = dns_rdata_tostruct(&rdata, &cname);
362: check_result(result, "dns_rdata_tostruct");
363: dns_name_copy(&cname.cname, qname, NULL);
364: dns_rdata_freestruct(&cname);
365: }
366: }
367:
368: static isc_result_t
369: printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
370: isc_boolean_t did_flag = ISC_FALSE;
371: dns_rdataset_t *opt, *tsig = NULL;
372: dns_name_t *tsigname;
373: isc_result_t result = ISC_R_SUCCESS;
374: int force_error;
375:
376: UNUSED(headers);
377:
378: /*
379: * We get called multiple times.
380: * Preserve any existing error status.
381: */
382: force_error = (seen_error == 1) ? 1 : 0;
383: seen_error = 1;
384: if (listed_server && !printed_server) {
385: char sockstr[ISC_SOCKADDR_FORMATSIZE];
386:
387: printf("Using domain server:\n");
388: printf("Name: %s\n", query->userarg);
389: isc_sockaddr_format(&query->sockaddr, sockstr,
390: sizeof(sockstr));
391: printf("Address: %s\n", sockstr);
392: printf("Aliases: \n\n");
393: printed_server = ISC_TRUE;
394: }
395:
396: if (msg->rcode != 0) {
397: char namestr[DNS_NAME_FORMATSIZE];
398: dns_name_format(query->lookup->name, namestr, sizeof(namestr));
399:
400: if (query->lookup->identify_previous_line)
401: printf("Nameserver %s:\n\t%s not found: %d(%s)\n",
402: query->servname,
403: (msg->rcode != dns_rcode_nxdomain) ? namestr :
404: query->lookup->textname, msg->rcode,
405: rcode_totext(msg->rcode));
406: else
407: printf("Host %s not found: %d(%s)\n",
408: (msg->rcode != dns_rcode_nxdomain) ? namestr :
409: query->lookup->textname, msg->rcode,
410: rcode_totext(msg->rcode));
411: return (ISC_R_SUCCESS);
412: }
413:
414: if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
415: char namestr[DNS_NAME_FORMATSIZE];
416: dig_lookup_t *lookup;
417: dns_fixedname_t fixed;
418: dns_name_t *name;
419:
420: /* Add AAAA and MX lookups. */
421: dns_fixedname_init(&fixed);
422: name = dns_fixedname_name(&fixed);
423: dns_name_copy(query->lookup->name, name, NULL);
424: chase_cnamechain(msg, name);
425: dns_name_format(name, namestr, sizeof(namestr));
426: lookup = clone_lookup(query->lookup, ISC_FALSE);
427: if (lookup != NULL) {
428: strlcpy(lookup->textname, namestr,
429: sizeof(lookup->textname));
430: lookup->rdtype = dns_rdatatype_aaaa;
431: lookup->rdtypeset = ISC_TRUE;
432: lookup->origin = NULL;
433: lookup->retries = tries;
434: ISC_LIST_APPEND(lookup_list, lookup, link);
435: }
436: lookup = clone_lookup(query->lookup, ISC_FALSE);
437: if (lookup != NULL) {
438: strlcpy(lookup->textname, namestr,
439: sizeof(lookup->textname));
440: lookup->rdtype = dns_rdatatype_mx;
441: lookup->rdtypeset = ISC_TRUE;
442: lookup->origin = NULL;
443: lookup->retries = tries;
444: ISC_LIST_APPEND(lookup_list, lookup, link);
445: }
446: }
447:
448: if (!short_form) {
449: printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
450: opcodetext[msg->opcode], rcode_totext(msg->rcode),
451: msg->id);
452: printf(";; flags: ");
453: if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
454: printf("qr");
455: did_flag = ISC_TRUE;
456: }
457: if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
458: printf("%saa", did_flag ? " " : "");
459: did_flag = ISC_TRUE;
460: }
461: if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
462: printf("%stc", did_flag ? " " : "");
463: did_flag = ISC_TRUE;
464: }
465: if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
466: printf("%srd", did_flag ? " " : "");
467: did_flag = ISC_TRUE;
468: }
469: if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
470: printf("%sra", did_flag ? " " : "");
471: did_flag = ISC_TRUE;
472: }
473: if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
474: printf("%sad", did_flag ? " " : "");
475: did_flag = ISC_TRUE;
476: }
477: if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
478: printf("%scd", did_flag ? " " : "");
479: did_flag = ISC_TRUE;
480: POST(did_flag);
481: }
482: printf("; QUERY: %u, ANSWER: %u, "
483: "AUTHORITY: %u, ADDITIONAL: %u\n",
484: msg->counts[DNS_SECTION_QUESTION],
485: msg->counts[DNS_SECTION_ANSWER],
486: msg->counts[DNS_SECTION_AUTHORITY],
487: msg->counts[DNS_SECTION_ADDITIONAL]);
488: opt = dns_message_getopt(msg);
489: if (opt != NULL)
490: printf(";; EDNS: version: %u, udp=%u\n",
491: (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
492: (unsigned int)opt->rdclass);
493: tsigname = NULL;
494: tsig = dns_message_gettsig(msg, &tsigname);
495: if (tsig != NULL)
496: printf(";; PSEUDOSECTIONS: TSIG\n");
497: }
498: if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
499: !short_form) {
500: printf("\n");
501: result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
502: ISC_TRUE, query);
503: if (result != ISC_R_SUCCESS)
504: return (result);
505: }
506: if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
507: if (!short_form)
508: printf("\n");
509: result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
510: ISC_TF(!short_form), query);
511: if (result != ISC_R_SUCCESS)
512: return (result);
513: }
514:
515: if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
516: !short_form) {
517: printf("\n");
518: result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
519: ISC_TRUE, query);
520: if (result != ISC_R_SUCCESS)
521: return (result);
522: }
523: if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
524: !short_form) {
525: printf("\n");
526: result = printsection(msg, DNS_SECTION_ADDITIONAL,
527: "ADDITIONAL", ISC_TRUE, query);
528: if (result != ISC_R_SUCCESS)
529: return (result);
530: }
531: if ((tsig != NULL) && !short_form) {
532: printf("\n");
533: result = printrdata(msg, tsig, tsigname,
534: "PSEUDOSECTION TSIG", ISC_TRUE);
535: if (result != ISC_R_SUCCESS)
536: return (result);
537: }
538: if (!short_form)
539: printf("\n");
540:
541: if (short_form && !default_lookups &&
542: ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
543: char namestr[DNS_NAME_FORMATSIZE];
544: char typestr[DNS_RDATATYPE_FORMATSIZE];
545: dns_name_format(query->lookup->name, namestr, sizeof(namestr));
546: dns_rdatatype_format(query->lookup->rdtype, typestr,
547: sizeof(typestr));
548: printf("%s has no %s record\n", namestr, typestr);
549: }
550: seen_error = force_error;
551: return (result);
552: }
553:
554: static const char * optstring = "46ac:dilnrst:vVwCDN:R:TW:";
555:
556: /*% version */
557: static void
558: version(void) {
559: fputs("host " VERSION "\n", stderr);
560: }
561:
562: static void
563: pre_parse_args(int argc, char **argv) {
564: int c;
565:
566: while ((c = getopt(argc, argv, optstring)) != -1) {
567: switch (c) {
568: case '4':
569: if (ipv6only)
570: fatal("only one of -4 and -6 allowed");
571: ipv4only = ISC_TRUE;
572: break;
573: case '6':
574: if (ipv4only)
575: fatal("only one of -4 and -6 allowed");
576: ipv6only = ISC_TRUE;
577: break;
578: case 'a': break;
579: case 'c': break;
580: case 'd': break;
581: case 'i': break;
582: case 'l': break;
583: case 'n': break;
584: case 'r': break;
585: case 's': break;
586: case 't': break;
587: case 'v': break;
588: case 'V':
589: version();
590: exit(0);
591: break;
592: case 'w': break;
593: case 'C': break;
594: case 'D':
595: if (debugging)
596: debugtiming = ISC_TRUE;
597: debugging = ISC_TRUE;
598: break;
599: case 'N': break;
600: case 'R': break;
601: case 'T': break;
602: case 'W': break;
603: default:
604: show_usage();
605: }
606: }
607: optind = 1;
608: optreset = 1;
609: }
610:
611: static void
612: parse_args(int argc, char **argv) {
613: char hostname[MXNAME];
614: dig_lookup_t *lookup;
615: int c;
616: char store[MXNAME];
617: isc_textregion_t tr;
618: isc_result_t result = ISC_R_SUCCESS;
619: dns_rdatatype_t rdtype;
620: dns_rdataclass_t rdclass;
621: uint32_t serial = 0;
622: const char *errstr;
623:
624: lookup = make_empty_lookup();
625:
626: lookup->servfail_stops = ISC_FALSE;
627: lookup->comments = ISC_FALSE;
628:
629: while ((c = getopt(argc, argv, optstring)) != -1) {
630: switch (c) {
631: case 'l':
632: lookup->tcp_mode = ISC_TRUE;
633: lookup->rdtype = dns_rdatatype_axfr;
634: lookup->rdtypeset = ISC_TRUE;
635: fatalexit = 3;
636: break;
637: case 'v':
638: case 'd':
639: short_form = ISC_FALSE;
640: break;
641: case 'r':
642: lookup->recurse = ISC_FALSE;
643: break;
644: case 't':
645: if (strncasecmp(optarg, "ixfr=", 5) == 0) {
646: rdtype = dns_rdatatype_ixfr;
647: /* XXXMPA add error checking */
648: serial = strtoul(optarg + 5,
649: NULL, 10);
650: result = ISC_R_SUCCESS;
651: } else {
652: tr.base = optarg;
653: tr.length = strlen(optarg);
654: result = dns_rdatatype_fromtext(&rdtype,
655: (isc_textregion_t *)&tr);
656: }
657:
658: if (result != ISC_R_SUCCESS) {
659: fatalexit = 2;
660: fatal("invalid type: %s\n", optarg);
661: }
662: if (!lookup->rdtypeset ||
663: lookup->rdtype != dns_rdatatype_axfr)
664: lookup->rdtype = rdtype;
665: lookup->rdtypeset = ISC_TRUE;
666: if (rdtype == dns_rdatatype_axfr) {
667: /* -l -t any -v */
668: list_type = dns_rdatatype_any;
669: short_form = ISC_FALSE;
670: lookup->tcp_mode = ISC_TRUE;
671: } else if (rdtype == dns_rdatatype_ixfr) {
672: lookup->ixfr_serial = serial;
673: lookup->tcp_mode = ISC_TRUE;
674: list_type = rdtype;
675: } else
676: list_type = rdtype;
677: list_addresses = ISC_FALSE;
678: default_lookups = ISC_FALSE;
679: break;
680: case 'c':
681: tr.base = optarg;
682: tr.length = strlen(optarg);
683: result = dns_rdataclass_fromtext(&rdclass,
684: (isc_textregion_t *)&tr);
685:
686: if (result != ISC_R_SUCCESS) {
687: fatalexit = 2;
688: fatal("invalid class: %s\n", optarg);
689: } else {
690: lookup->rdclass = rdclass;
691: lookup->rdclassset = ISC_TRUE;
692: }
693: default_lookups = ISC_FALSE;
694: break;
695: case 'a':
696: if (!lookup->rdtypeset ||
697: lookup->rdtype != dns_rdatatype_axfr)
698: lookup->rdtype = dns_rdatatype_any;
699: list_type = dns_rdatatype_any;
700: list_addresses = ISC_FALSE;
701: lookup->rdtypeset = ISC_TRUE;
702: short_form = ISC_FALSE;
703: default_lookups = ISC_FALSE;
704: break;
705: case 'i':
706: lookup->ip6_int = ISC_TRUE;
707: break;
708: case 'n':
709: /* deprecated */
710: break;
711: case 'm':
712: /* Handled by pre_parse_args(). */
713: break;
714: case 'w':
715: /*
716: * The timer routines are coded such that
717: * timeout==MAXINT doesn't enable the timer
718: */
719: timeout = INT_MAX;
720: break;
721: case 'W':
722: timeout = strtonum(optarg, 0, INT_MAX, &errstr);
723: if (errstr != NULL)
724: errx(1, "timeout is %s: %s", errstr, optarg);
725: if (timeout < 1)
726: timeout = 1;
727: break;
728: case 'R':
729: tries = strtonum(optarg, INT_MIN, INT_MAX - 1, &errstr);
730: if (errstr != NULL)
731: errx(1, "retries is %s: %s", errstr, optarg);
732: tries++;
733: if (tries < 2)
734: tries = 2;
735: break;
736: case 'T':
737: lookup->tcp_mode = ISC_TRUE;
738: break;
739: case 'C':
740: debug("showing all SOAs");
741: lookup->rdtype = dns_rdatatype_ns;
742: lookup->rdtypeset = ISC_TRUE;
743: lookup->rdclass = dns_rdataclass_in;
744: lookup->rdclassset = ISC_TRUE;
745: lookup->ns_search_only = ISC_TRUE;
746: lookup->trace_root = ISC_TRUE;
747: lookup->identify_previous_line = ISC_TRUE;
748: default_lookups = ISC_FALSE;
749: break;
750: case 'N':
751: debug("setting NDOTS to %s", optarg);
752: ndots = strtonum(optarg, 0, INT_MAX, &errstr);
753: if (errstr != NULL)
754: errx(1, "ndots is %s: %s", errstr, optarg);
755: break;
756: case 'D':
757: /* Handled by pre_parse_args(). */
758: break;
759: case '4':
760: /* Handled by pre_parse_args(). */
761: break;
762: case '6':
763: /* Handled by pre_parse_args(). */
764: break;
765: case 's':
766: lookup->servfail_stops = ISC_TRUE;
767: break;
768: default:
769: show_usage();
770: }
771: }
772:
773: lookup->retries = tries;
774:
775: argc -= optind;
776: argv += optind;
777:
778: if (argc == 0)
779: show_usage();
780:
1.5 florian 781: strlcpy(hostname, argv[0], sizeof(hostname));
1.1 florian 782:
1.5 florian 783: if (argc >= 2) {
784: set_nameserver(argv[1]);
1.1 florian 785: debug("server is %s", *argv + 1);
786: listed_server = ISC_TRUE;
787: } else
788: check_ra = ISC_TRUE;
789:
790: lookup->pending = ISC_FALSE;
791: if (get_reverse(store, sizeof(store), hostname,
792: lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) {
793: strlcpy(lookup->textname, store, sizeof(lookup->textname));
794: lookup->rdtype = dns_rdatatype_ptr;
795: lookup->rdtypeset = ISC_TRUE;
796: default_lookups = ISC_FALSE;
797: } else {
798: strlcpy(lookup->textname, hostname, sizeof(lookup->textname));
799: usesearch = ISC_TRUE;
800: }
801: lookup->new_search = ISC_TRUE;
802: ISC_LIST_APPEND(lookup_list, lookup, link);
803: }
804:
805: int
806: host_main(int argc, char **argv) {
807: isc_result_t result;
808:
809: tries = 2;
810:
811: ISC_LIST_INIT(lookup_list);
812: ISC_LIST_INIT(server_list);
1.4 florian 813: ISC_LIST_INIT(root_hints_server_list);
1.1 florian 814: ISC_LIST_INIT(search_list);
815:
816: fatalexit = 1;
817:
818: /* setup dighost callbacks */
819: dighost_printmessage = printmessage;
820: dighost_received = received;
821: dighost_trying = trying;
822: dighost_shutdown = host_shutdown;
823:
824: debug("main()");
825: progname = argv[0];
826: pre_parse_args(argc, argv);
827: result = isc_app_start();
828: check_result(result, "isc_app_start");
829:
830: if (pledge("stdio rpath inet dns", NULL) == -1) {
831: perror("pledge");
832: exit(1);
833: }
834:
835: setup_libs();
836:
837: if (pledge("stdio inet dns", NULL) == -1) {
838: perror("pledge");
839: exit(1);
840: }
841:
842: parse_args(argc, argv);
843: setup_system(ipv4only, ipv6only);
844: result = isc_app_onrun(global_task, onrun_callback, NULL);
845: check_result(result, "isc_app_onrun");
846: isc_app_run();
847: cancel_all();
848: destroy_libs();
849: return ((seen_error == 0) ? 0 : 1);
850: }