]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/bin/dig/host.c
This commit was generated by cvs2svn to compensate for changes in r151513,
[FreeBSD/FreeBSD.git] / contrib / bind9 / bin / dig / host.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.76.2.5.2.10 2004/09/06 01:33:05 marka Exp $ */
19
20 #include <config.h>
21 #include <limits.h>
22
23 #include <isc/app.h>
24 #include <isc/commandline.h>
25 #include <isc/netaddr.h>
26 #include <isc/print.h>
27 #include <isc/string.h>
28 #include <isc/util.h>
29 #include <isc/task.h>
30 #include <isc/stdlib.h>
31
32 #include <dns/byaddr.h>
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/dig.h>
42
43 extern ISC_LIST(dig_lookup_t) lookup_list;
44 extern dig_serverlist_t server_list;
45 extern ISC_LIST(dig_searchlist_t) search_list;
46
47 extern isc_boolean_t have_ipv4, have_ipv6;
48 extern isc_boolean_t usesearch;
49 extern isc_boolean_t debugging;
50 extern unsigned int timeout;
51 extern isc_mem_t *mctx;
52 extern int ndots;
53 extern int tries;
54 extern char *progname;
55 extern isc_task_t *global_task;
56 extern int fatalexit;
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
64 static const char *opcodetext[] = {
65         "QUERY",
66         "IQUERY",
67         "STATUS",
68         "RESERVED3",
69         "NOTIFY",
70         "UPDATE",
71         "RESERVED6",
72         "RESERVED7",
73         "RESERVED8",
74         "RESERVED9",
75         "RESERVED10",
76         "RESERVED11",
77         "RESERVED12",
78         "RESERVED13",
79         "RESERVED14",
80         "RESERVED15"
81 };
82
83 static const char *rcodetext[] = {
84         "NOERROR",
85         "FORMERR",
86         "SERVFAIL",
87         "NXDOMAIN",
88         "NOTIMP",
89         "REFUSED",
90         "YXDOMAIN",
91         "YXRRSET",
92         "NXRRSET",
93         "NOTAUTH",
94         "NOTZONE",
95         "RESERVED11",
96         "RESERVED12",
97         "RESERVED13",
98         "RESERVED14",
99         "RESERVED15",
100         "BADVERS"
101 };
102
103 struct rtype {
104         unsigned int type;
105         const char *text;
106 };
107
108 struct rtype rtypes[] = {
109         { 1,    "has address" },
110         { 2,    "name server" },
111         { 5,    "is an alias for" },
112         { 11,   "has well known services" },
113         { 12,   "domain name pointer" },
114         { 13,   "host information" },
115         { 15,   "mail is handled by" },
116         { 16,   "descriptive text" },
117         { 19,   "x25 address" },
118         { 20,   "ISDN address" },
119         { 24,   "has signature" },
120         { 25,   "has key" },
121         { 28,   "has IPv6 address" },
122         { 29,   "location" },
123         { 0, NULL }
124 };
125
126 static void
127 show_usage(void) {
128         fputs(
129 "Usage: host [-aCdlriTwv] [-c class] [-N ndots] [-t type] [-W time]\n"
130 "            [-R number] hostname [server]\n"
131 "       -a is equivalent to -v -t *\n"
132 "       -c specifies query class for non-IN data\n"
133 "       -C compares SOA records on authoritative nameservers\n"
134 "       -d is equivalent to -v\n"
135 "       -l lists all hosts in a domain, using AXFR\n"
136 "       -i IP6.INT reverse lookups\n"
137 "       -N changes the number of dots allowed before root lookup is done\n"
138 "       -r disables recursive processing\n"
139 "       -R specifies number of retries for UDP packets\n"
140 "       -t specifies the query type\n"
141 "       -T enables TCP/IP mode\n"
142 "       -v enables verbose output\n"
143 "       -w specifies to wait forever for a reply\n"
144 "       -W specifies how long to wait for a reply\n"
145 "       -4 use IPv4 query transport only\n"
146 "       -6 use IPv6 query transport only\n", stderr);
147         exit(1);
148 }
149
150 void
151 dighost_shutdown(void) {
152         isc_app_shutdown();
153 }
154
155 void
156 received(int bytes, isc_sockaddr_t *from, dig_query_t *query) {
157         isc_time_t now;
158         int diff;
159
160         if (!short_form) {
161                 char fromtext[ISC_SOCKADDR_FORMATSIZE];
162                 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
163                 TIME_NOW(&now);
164                 diff = (int) isc_time_microdiff(&now, &query->time_sent);
165                 printf("Received %u bytes from %s in %d ms\n",
166                        bytes, fromtext, diff/1000);
167         }
168 }
169
170 void
171 trying(char *frm, dig_lookup_t *lookup) {
172         UNUSED(lookup);
173
174         if (!short_form)
175                 printf("Trying \"%s\"\n", frm);
176 }
177
178 static void
179 say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
180             dig_query_t *query)
181 {
182         isc_buffer_t *b = NULL;
183         char namestr[DNS_NAME_FORMATSIZE];
184         isc_region_t r;
185         isc_result_t result;
186         unsigned int bufsize = BUFSIZ;
187
188         dns_name_format(name, namestr, sizeof(namestr));
189  retry:
190         result = isc_buffer_allocate(mctx, &b, bufsize);
191         check_result(result, "isc_buffer_allocate");
192         result = dns_rdata_totext(rdata, NULL, b);
193         if (result == ISC_R_NOSPACE) {
194                 isc_buffer_free(&b);
195                 bufsize *= 2;
196                 goto retry;
197         }
198         check_result(result, "dns_rdata_totext");
199         isc_buffer_usedregion(b, &r);
200         if (query->lookup->identify_previous_line) {
201                 printf("Nameserver %s:\n\t",
202                         query->servname);
203         }
204         printf("%s %s %.*s", namestr,
205                msg, (int)r.length, (char *)r.base);
206         if (query->lookup->identify) {
207                 printf(" on server %s", query->servname);
208         }
209         printf("\n");
210         isc_buffer_free(&b);
211 }
212 #ifdef DIG_SIGCHASE
213 /* Just for compatibility : not use in host program */
214 isc_result_t
215 printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
216               isc_buffer_t *target)
217 {
218   UNUSED(owner_name);
219   UNUSED(rdataset);
220   UNUSED(target);
221   return(ISC_FALSE);
222 }
223 #endif
224 static isc_result_t
225 printsection(dns_message_t *msg, dns_section_t sectionid,
226              const char *section_name, isc_boolean_t headers,
227              dig_query_t *query)
228 {
229         dns_name_t *name, *print_name;
230         dns_rdataset_t *rdataset;
231         dns_rdata_t rdata = DNS_RDATA_INIT;
232         isc_buffer_t target;
233         isc_result_t result, loopresult;
234         isc_region_t r;
235         dns_name_t empty_name;
236         char t[4096];
237         isc_boolean_t first;
238         isc_boolean_t no_rdata;
239
240         if (sectionid == DNS_SECTION_QUESTION)
241                 no_rdata = ISC_TRUE;
242         else
243                 no_rdata = ISC_FALSE;
244
245         if (headers)
246                 printf(";; %s SECTION:\n", section_name);
247
248         dns_name_init(&empty_name, NULL);
249
250         result = dns_message_firstname(msg, sectionid);
251         if (result == ISC_R_NOMORE)
252                 return (ISC_R_SUCCESS);
253         else if (result != ISC_R_SUCCESS)
254                 return (result);
255
256         for (;;) {
257                 name = NULL;
258                 dns_message_currentname(msg, sectionid, &name);
259
260                 isc_buffer_init(&target, t, sizeof(t));
261                 first = ISC_TRUE;
262                 print_name = name;
263
264                 for (rdataset = ISC_LIST_HEAD(name->list);
265                      rdataset != NULL;
266                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
267                         if (query->lookup->rdtype == dns_rdatatype_axfr &&
268                             !((!list_addresses &&
269                                (list_type == dns_rdatatype_any ||
270                                 rdataset->type == list_type)) ||
271                               (list_addresses &&
272                                (rdataset->type == dns_rdatatype_a ||
273                                 rdataset->type == dns_rdatatype_aaaa ||
274                                 rdataset->type == dns_rdatatype_ns ||
275                                 rdataset->type == dns_rdatatype_ptr))))
276                                 continue;
277                         if (!short_form) {
278                                 result = dns_rdataset_totext(rdataset,
279                                                              print_name,
280                                                              ISC_FALSE,
281                                                              no_rdata,
282                                                              &target);
283                                 if (result != ISC_R_SUCCESS)
284                                         return (result);
285 #ifdef USEINITALWS
286                                 if (first) {
287                                         print_name = &empty_name;
288                                         first = ISC_FALSE;
289                                 }
290 #else
291                                 UNUSED(first); /* Shut up compiler. */
292 #endif
293                         } else {
294                                 loopresult = dns_rdataset_first(rdataset);
295                                 while (loopresult == ISC_R_SUCCESS) {
296                                         struct rtype *t;
297                                         const char *rtt;
298                                         char typebuf[DNS_RDATATYPE_FORMATSIZE];
299                                         char typebuf2[DNS_RDATATYPE_FORMATSIZE
300                                                      + 20];
301                                         dns_rdataset_current(rdataset, &rdata);
302
303                                         for (t = rtypes; t->text != NULL; t++) {
304                                                 if (t->type == rdata.type) {
305                                                         rtt = t->text;
306                                                         goto found;
307                                                 }
308                                         }
309
310                                         dns_rdatatype_format(rdata.type,
311                                                              typebuf,
312                                                              sizeof(typebuf));
313                                         snprintf(typebuf2, sizeof(typebuf2),
314                                                  "has %s record", typebuf);
315                                         rtt = typebuf2;
316                                 found:
317                                         say_message(print_name, rtt,
318                                                     &rdata, query);
319                                         dns_rdata_reset(&rdata);
320                                         loopresult =
321                                                 dns_rdataset_next(rdataset);
322                                 }
323                         }
324                 }
325                 if (!short_form) {
326                         isc_buffer_usedregion(&target, &r);
327                         if (no_rdata)
328                                 printf(";%.*s", (int)r.length,
329                                        (char *)r.base);
330                         else
331                                 printf("%.*s", (int)r.length, (char *)r.base);
332                 }
333
334                 result = dns_message_nextname(msg, sectionid);
335                 if (result == ISC_R_NOMORE)
336                         break;
337                 else if (result != ISC_R_SUCCESS)
338                         return (result);
339         }
340
341         return (ISC_R_SUCCESS);
342 }
343
344 static isc_result_t
345 printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
346            const char *set_name, isc_boolean_t headers)
347 {
348         isc_buffer_t target;
349         isc_result_t result;
350         isc_region_t r;
351         char t[4096];
352
353         UNUSED(msg);
354         if (headers)
355                 printf(";; %s SECTION:\n", set_name);
356
357         isc_buffer_init(&target, t, sizeof(t));
358
359         result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
360                                      &target);
361         if (result != ISC_R_SUCCESS)
362                 return (result);
363         isc_buffer_usedregion(&target, &r);
364         printf("%.*s", (int)r.length, (char *)r.base);
365
366         return (ISC_R_SUCCESS);
367 }
368
369 isc_result_t
370 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
371         isc_boolean_t did_flag = ISC_FALSE;
372         dns_rdataset_t *opt, *tsig = NULL;
373         dns_name_t *tsigname;
374         isc_result_t result = ISC_R_SUCCESS;
375         int force_error;
376
377         UNUSED(headers);
378
379         /*
380          * We get called multiple times.
381          * Preserve any existing error status.
382          */
383         force_error = (seen_error == 1) ? 1 : 0;
384         seen_error = 1;
385         if (listed_server) {
386                 char sockstr[ISC_SOCKADDR_FORMATSIZE];
387
388                 printf("Using domain server:\n");
389                 printf("Name: %s\n", query->userarg);
390                 isc_sockaddr_format(&query->sockaddr, sockstr,
391                                     sizeof(sockstr));
392                 printf("Address: %s\n", sockstr);
393                 printf("Aliases: \n\n");
394         }
395
396         if (msg->rcode != 0) {
397                 char namestr[DNS_NAME_FORMATSIZE];
398                 dns_name_format(query->lookup->name, namestr, sizeof(namestr));
399                 printf("Host %s not found: %d(%s)\n", namestr,
400                        msg->rcode, rcodetext[msg->rcode]);
401                 return (ISC_R_SUCCESS);
402         }
403
404         if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
405                 char namestr[DNS_NAME_FORMATSIZE];
406                 dig_lookup_t *lookup;
407
408                 /* Add AAAA and MX lookups. */
409
410                 dns_name_format(query->lookup->name, namestr, sizeof(namestr));
411                 lookup = clone_lookup(query->lookup, ISC_FALSE);
412                 if (lookup != NULL) {
413                         strncpy(lookup->textname, namestr,
414                                 sizeof(lookup->textname));
415                         lookup->textname[sizeof(lookup->textname)-1] = 0;
416                         lookup->rdtype = dns_rdatatype_aaaa;
417                         lookup->rdtypeset = ISC_TRUE;
418                         lookup->origin = NULL;
419                         lookup->retries = tries;
420                         ISC_LIST_APPEND(lookup_list, lookup, link);
421                 }
422                 lookup = clone_lookup(query->lookup, ISC_FALSE);
423                 if (lookup != NULL) {
424                         strncpy(lookup->textname, namestr,
425                                 sizeof(lookup->textname));
426                         lookup->textname[sizeof(lookup->textname)-1] = 0;
427                         lookup->rdtype = dns_rdatatype_mx;
428                         lookup->rdtypeset = ISC_TRUE;
429                         lookup->origin = NULL;
430                         lookup->retries = tries;
431                         ISC_LIST_APPEND(lookup_list, lookup, link);
432                 }
433         }
434
435         if (!short_form) {
436                 printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
437                        opcodetext[msg->opcode], rcodetext[msg->rcode],
438                        msg->id);
439                 printf(";; flags: ");
440                 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
441                         printf("qr");
442                         did_flag = ISC_TRUE;
443                 }
444                 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
445                         printf("%saa", did_flag ? " " : "");
446                         did_flag = ISC_TRUE;
447                 }
448                 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
449                         printf("%stc", did_flag ? " " : "");
450                         did_flag = ISC_TRUE;
451                 }
452                 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
453                         printf("%srd", did_flag ? " " : "");
454                         did_flag = ISC_TRUE;
455                 }
456                 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
457                         printf("%sra", did_flag ? " " : "");
458                         did_flag = ISC_TRUE;
459                 }
460                 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
461                         printf("%sad", did_flag ? " " : "");
462                         did_flag = ISC_TRUE;
463                 }
464                 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
465                         printf("%scd", did_flag ? " " : "");
466                         did_flag = ISC_TRUE;
467                 }
468                 printf("; QUERY: %u, ANSWER: %u, "
469                        "AUTHORITY: %u, ADDITIONAL: %u\n",
470                        msg->counts[DNS_SECTION_QUESTION],
471                        msg->counts[DNS_SECTION_ANSWER],
472                        msg->counts[DNS_SECTION_AUTHORITY],
473                        msg->counts[DNS_SECTION_ADDITIONAL]);
474                 opt = dns_message_getopt(msg);
475                 if (opt != NULL)
476                         printf(";; EDNS: version: %u, udp=%u\n",
477                                (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
478                                (unsigned int)opt->rdclass);
479                 tsigname = NULL;
480                 tsig = dns_message_gettsig(msg, &tsigname);
481                 if (tsig != NULL)
482                         printf(";; PSEUDOSECTIONS: TSIG\n");
483         }
484         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
485             !short_form) {
486                 printf("\n");
487                 result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
488                                       ISC_TRUE, query);
489                 if (result != ISC_R_SUCCESS)
490                         return (result);
491         }
492         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
493                 if (!short_form)
494                         printf("\n");
495                 result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
496                                       ISC_TF(!short_form), query);
497                 if (result != ISC_R_SUCCESS)
498                         return (result);
499         }
500
501         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
502             !short_form) {
503                 printf("\n");
504                 result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
505                                       ISC_TRUE, query);
506                 if (result != ISC_R_SUCCESS)
507                         return (result);
508         }
509         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
510             !short_form) {
511                 printf("\n");
512                 result = printsection(msg, DNS_SECTION_ADDITIONAL,
513                                       "ADDITIONAL", ISC_TRUE, query);
514                 if (result != ISC_R_SUCCESS)
515                         return (result);
516         }
517         if ((tsig != NULL) && !short_form) {
518                 printf("\n");
519                 result = printrdata(msg, tsig, tsigname,
520                                     "PSEUDOSECTION TSIG", ISC_TRUE);
521                 if (result != ISC_R_SUCCESS)
522                         return (result);
523         }
524         if (!short_form)
525                 printf("\n");
526
527         if (short_form && !default_lookups &&
528             ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
529                 char namestr[DNS_NAME_FORMATSIZE];
530                 char typestr[DNS_RDATATYPE_FORMATSIZE];
531                 dns_name_format(query->lookup->name, namestr, sizeof(namestr));
532                 dns_rdatatype_format(query->lookup->rdtype, typestr,
533                                      sizeof(typestr));
534                 printf("%s has no %s record\n", namestr, typestr);
535         }
536         seen_error = force_error;
537         return (result);
538 }
539
540 static void
541 parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
542         char hostname[MXNAME];
543         dig_lookup_t *lookup;
544         int c;
545         char store[MXNAME];
546         isc_textregion_t tr;
547         isc_result_t result = ISC_R_SUCCESS;
548         dns_rdatatype_t rdtype;
549         dns_rdataclass_t rdclass;
550         isc_uint32_t serial = 0;
551
552         UNUSED(is_batchfile);
553
554         lookup = make_empty_lookup();
555
556         while ((c = isc_commandline_parse(argc, argv, "lvwrdt:c:aTCN:R:W:Dni46"))
557                != EOF) {
558                 switch (c) {
559                 case 'l':
560                         lookup->tcp_mode = ISC_TRUE;
561                         lookup->rdtype = dns_rdatatype_axfr;
562                         lookup->rdtypeset = ISC_TRUE;
563                         fatalexit = 3;
564                         break;
565                 case 'v':
566                 case 'd':
567                         short_form = ISC_FALSE;
568                         break;
569                 case 'r':
570                         lookup->recurse = ISC_FALSE;
571                         break;
572                 case 't':
573                         if (strncasecmp(isc_commandline_argument,
574                                         "ixfr=", 5) == 0) {
575                                 rdtype = dns_rdatatype_ixfr;
576                                 /* XXXMPA add error checking */
577                                 serial = strtoul(isc_commandline_argument + 5,
578                                                  NULL, 10);
579                                 result = ISC_R_SUCCESS;
580                         } else {
581                                 tr.base = isc_commandline_argument;
582                                 tr.length = strlen(isc_commandline_argument);
583                                 result = dns_rdatatype_fromtext(&rdtype,
584                                                    (isc_textregion_t *)&tr);
585                         }
586
587                         if (result != ISC_R_SUCCESS) {
588                                 fatalexit = 2;
589                                 fatal("invalid type: %s\n",
590                                       isc_commandline_argument);
591                         }
592                         if (!lookup->rdtypeset ||
593                             lookup->rdtype != dns_rdatatype_axfr)
594                                 lookup->rdtype = rdtype;
595                         lookup->rdtypeset = ISC_TRUE;
596                         if (rdtype == dns_rdatatype_axfr) {
597                                 /* -l -t any -v */
598                                 list_type = dns_rdatatype_any;
599                                 short_form = ISC_FALSE;
600                                 lookup->tcp_mode = ISC_TRUE;
601                         } else if (rdtype == dns_rdatatype_ixfr) {
602                                 lookup->ixfr_serial = serial;
603                                 list_type = rdtype;
604                         } else
605                                 list_type = rdtype;
606                         list_addresses = ISC_FALSE;
607                         break;
608                 case 'c':
609                         tr.base = isc_commandline_argument;
610                         tr.length = strlen(isc_commandline_argument);
611                         result = dns_rdataclass_fromtext(&rdclass,
612                                                    (isc_textregion_t *)&tr);
613
614                         if (result != ISC_R_SUCCESS) {
615                                 fatalexit = 2;
616                                 fatal("invalid class: %s\n",
617                                       isc_commandline_argument);
618                         } else {
619                                 lookup->rdclass = rdclass;
620                                 lookup->rdclassset = ISC_TRUE;
621                         }
622                         default_lookups = ISC_FALSE;
623                         break;
624                 case 'a':
625                         if (!lookup->rdtypeset ||
626                             lookup->rdtype != dns_rdatatype_axfr)
627                                 lookup->rdtype = dns_rdatatype_any;
628                         list_type = dns_rdatatype_any;
629                         list_addresses = ISC_FALSE;
630                         lookup->rdtypeset = ISC_TRUE;
631                         short_form = ISC_FALSE;
632                         default_lookups = ISC_FALSE;
633                         break;
634                 case 'i':
635                         lookup->ip6_int = ISC_TRUE;
636                         break;
637                 case 'n':
638                         /* deprecated */
639                         break;
640                 case 'w':
641                         /*
642                          * The timer routines are coded such that
643                          * timeout==MAXINT doesn't enable the timer
644                          */
645                         timeout = INT_MAX;
646                         break;
647                 case 'W':
648                         timeout = atoi(isc_commandline_argument);
649                         if (timeout < 1)
650                                 timeout = 1;
651                         break;
652                 case 'R':
653                         tries = atoi(isc_commandline_argument) + 1;
654                         if (tries < 2)
655                                 tries = 2;
656                         break;
657                 case 'T':
658                         lookup->tcp_mode = ISC_TRUE;
659                         break;
660                 case 'C':
661                         debug("showing all SOAs");
662                         lookup->rdtype = dns_rdatatype_ns;
663                         lookup->rdtypeset = ISC_TRUE;
664                         lookup->rdclass = dns_rdataclass_in;
665                         lookup->rdclassset = ISC_TRUE;
666                         lookup->ns_search_only = ISC_TRUE;
667                         lookup->trace_root = ISC_TRUE;
668                         lookup->identify_previous_line = ISC_TRUE;
669                         default_lookups = ISC_FALSE;
670                         break;
671                 case 'N':
672                         debug("setting NDOTS to %s",
673                               isc_commandline_argument);
674                         ndots = atoi(isc_commandline_argument);
675                         break;
676                 case 'D':
677                         debugging = ISC_TRUE;
678                         break;
679                 case '4':
680                         if (have_ipv4) {
681                                 isc_net_disableipv6();
682                                 have_ipv6 = ISC_FALSE;
683                         } else
684                                 fatal("can't find IPv4 networking");
685                         break;
686                 case '6':
687                         if (have_ipv6) {
688                                 isc_net_disableipv4();
689                                 have_ipv4 = ISC_FALSE;
690                         } else
691                                 fatal("can't find IPv6 networking");
692                         break;
693                 }
694         }
695
696         lookup->retries = tries;
697
698         if (isc_commandline_index >= argc)
699                 show_usage();
700
701         strncpy(hostname, argv[isc_commandline_index], sizeof(hostname));
702         hostname[sizeof(hostname)-1]=0;
703         if (argc > isc_commandline_index + 1) {
704                 set_nameserver(argv[isc_commandline_index+1]);
705                 debug("server is %s", argv[isc_commandline_index+1]);
706                 listed_server = ISC_TRUE;
707         }
708
709         lookup->pending = ISC_FALSE;
710         if (get_reverse(store, sizeof(store), hostname,
711                         lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) {
712                 strncpy(lookup->textname, store, sizeof(lookup->textname));
713                 lookup->textname[sizeof(lookup->textname)-1] = 0;
714                 lookup->rdtype = dns_rdatatype_ptr;
715                 lookup->rdtypeset = ISC_TRUE;
716                 default_lookups = ISC_FALSE;
717         } else {
718                 strncpy(lookup->textname, hostname, sizeof(lookup->textname));
719                 lookup->textname[sizeof(lookup->textname)-1]=0;
720         }
721         lookup->new_search = ISC_TRUE;
722         ISC_LIST_APPEND(lookup_list, lookup, link);
723
724         usesearch = ISC_TRUE;
725 }
726
727 int
728 main(int argc, char **argv) {
729         isc_result_t result;
730
731         tries = 2;
732
733         ISC_LIST_INIT(lookup_list);
734         ISC_LIST_INIT(server_list);
735         ISC_LIST_INIT(search_list);
736         
737         fatalexit = 1;
738
739         debug("main()");
740         progname = argv[0];
741         result = isc_app_start();
742         check_result(result, "isc_app_start");
743         setup_libs();
744         parse_args(ISC_FALSE, argc, argv);
745         setup_system();
746         result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
747         check_result(result, "isc_app_onrun");
748         isc_app_run();
749         cancel_all();
750         destroy_libs();
751         isc_app_finish();
752         return ((seen_error == 0) ? 0 : 1);
753 }
754