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