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