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