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