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