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