host.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2007, 2009-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
00019 
00020 #include <config.h>
00021 #include <stdlib.h>
00022 #include <limits.h>
00023 
00024 #ifdef HAVE_LOCALE_H
00025 #include <locale.h>
00026 #endif
00027 
00028 #ifdef WITH_IDN
00029 #include <idn/result.h>
00030 #include <idn/log.h>
00031 #include <idn/resconf.h>
00032 #include <idn/api.h>
00033 #endif
00034 
00035 #include <isc/app.h>
00036 #include <isc/commandline.h>
00037 #include <isc/netaddr.h>
00038 #include <isc/print.h>
00039 #include <isc/string.h>
00040 #include <isc/util.h>
00041 #include <isc/task.h>
00042 #include <isc/stdlib.h>
00043 
00044 #include <dns/byaddr.h>
00045 #include <dns/fixedname.h>
00046 #include <dns/message.h>
00047 #include <dns/name.h>
00048 #include <dns/rdata.h>
00049 #include <dns/rdataclass.h>
00050 #include <dns/rdataset.h>
00051 #include <dns/rdatatype.h>
00052 #include <dns/rdatastruct.h>
00053 
00054 #include <dig/dig.h>
00055 
00056 static isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE;
00057 static isc_boolean_t default_lookups = ISC_TRUE;
00058 static int seen_error = -1;
00059 static isc_boolean_t list_addresses = ISC_TRUE;
00060 static dns_rdatatype_t list_type = dns_rdatatype_a;
00061 static isc_boolean_t printed_server = ISC_FALSE;
00062 
00063 static const char *opcodetext[] = {
00064         "QUERY",
00065         "IQUERY",
00066         "STATUS",
00067         "RESERVED3",
00068         "NOTIFY",
00069         "UPDATE",
00070         "RESERVED6",
00071         "RESERVED7",
00072         "RESERVED8",
00073         "RESERVED9",
00074         "RESERVED10",
00075         "RESERVED11",
00076         "RESERVED12",
00077         "RESERVED13",
00078         "RESERVED14",
00079         "RESERVED15"
00080 };
00081 
00082 static const char *rcodetext[] = {
00083         "NOERROR",
00084         "FORMERR",
00085         "SERVFAIL",
00086         "NXDOMAIN",
00087         "NOTIMP",
00088         "REFUSED",
00089         "YXDOMAIN",
00090         "YXRRSET",
00091         "NXRRSET",
00092         "NOTAUTH",
00093         "NOTZONE",
00094         "RESERVED11",
00095         "RESERVED12",
00096         "RESERVED13",
00097         "RESERVED14",
00098         "RESERVED15",
00099         "BADVERS"
00100 };
00101 
00102 struct rtype {
00103         unsigned int type;
00104         const char *text;
00105 };
00106 
00107 struct rtype rtypes[] = {
00108         { 1,    "has address" },
00109         { 2,    "name server" },
00110         { 5,    "is an alias for" },
00111         { 11,   "has well known services" },
00112         { 12,   "domain name pointer" },
00113         { 13,   "host information" },
00114         { 15,   "mail is handled by" },
00115         { 16,   "descriptive text" },
00116         { 19,   "x25 address" },
00117         { 20,   "ISDN address" },
00118         { 24,   "has signature" },
00119         { 25,   "has key" },
00120         { 28,   "has IPv6 address" },
00121         { 29,   "location" },
00122         { 0, NULL }
00123 };
00124 
00125 static char *
00126 rcode_totext(dns_rcode_t rcode)
00127 {
00128         static char buf[sizeof("?65535")];
00129         union {
00130                 const char *consttext;
00131                 char *deconsttext;
00132         } totext;
00133 
00134         if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
00135                 snprintf(buf, sizeof(buf), "?%u", rcode);
00136                 totext.deconsttext = buf;
00137         } else
00138                 totext.consttext = rcodetext[rcode];
00139         return totext.deconsttext;
00140 }
00141 
00142 ISC_PLATFORM_NORETURN_PRE static void
00143 show_usage(void) ISC_PLATFORM_NORETURN_POST;
00144 
00145 static void
00146 show_usage(void) {
00147         fputs(
00148 "Usage: host [-aCdlriTwv] [-c class] [-N ndots] [-t type] [-W time]\n"
00149 "            [-R number] [-m flag] hostname [server]\n"
00150 "       -a is equivalent to -v -t ANY\n"
00151 "       -c specifies query class for non-IN data\n"
00152 "       -C compares SOA records on authoritative nameservers\n"
00153 "       -d is equivalent to -v\n"
00154 "       -l lists all hosts in a domain, using AXFR\n"
00155 "       -i IP6.INT reverse lookups\n"
00156 "       -N changes the number of dots allowed before root lookup is done\n"
00157 "       -r disables recursive processing\n"
00158 "       -R specifies number of retries for UDP packets\n"
00159 "       -s a SERVFAIL response should stop query\n"
00160 "       -t specifies the query type\n"
00161 "       -T enables TCP/IP mode\n"
00162 "       -v enables verbose output\n"
00163 "       -w specifies to wait forever for a reply\n"
00164 "       -W specifies how long to wait for a reply\n"
00165 "       -4 use IPv4 query transport only\n"
00166 "       -6 use IPv6 query transport only\n"
00167 "       -m set memory debugging flag (trace|record|usage)\n"
00168 "       -V print version number and exit\n", stderr);
00169         exit(1);
00170 }
00171 
00172 void
00173 dighost_shutdown(void) {
00174         isc_app_shutdown();
00175 }
00176 
00177 void
00178 received(int bytes, isc_sockaddr_t *from, dig_query_t *query) {
00179         isc_time_t now;
00180         int diff;
00181 
00182         if (!short_form) {
00183                 char fromtext[ISC_SOCKADDR_FORMATSIZE];
00184                 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
00185                 TIME_NOW(&now);
00186                 diff = (int) isc_time_microdiff(&now, &query->time_sent);
00187                 printf("Received %u bytes from %s in %d ms\n",
00188                        bytes, fromtext, diff/1000);
00189         }
00190 }
00191 
00192 void
00193 trying(char *frm, dig_lookup_t *lookup) {
00194         UNUSED(lookup);
00195 
00196         if (!short_form)
00197                 printf("Trying \"%s\"\n", frm);
00198 }
00199 
00200 static void
00201 say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
00202             dig_query_t *query)
00203 {
00204         isc_buffer_t *b = NULL;
00205         char namestr[DNS_NAME_FORMATSIZE];
00206         isc_region_t r;
00207         isc_result_t result;
00208         unsigned int bufsize = BUFSIZ;
00209 
00210         dns_name_format(name, namestr, sizeof(namestr));
00211  retry:
00212         result = isc_buffer_allocate(mctx, &b, bufsize);
00213         check_result(result, "isc_buffer_allocate");
00214         result = dns_rdata_totext(rdata, NULL, b);
00215         if (result == ISC_R_NOSPACE) {
00216                 isc_buffer_free(&b);
00217                 bufsize *= 2;
00218                 goto retry;
00219         }
00220         check_result(result, "dns_rdata_totext");
00221         isc_buffer_usedregion(b, &r);
00222         if (query->lookup->identify_previous_line) {
00223                 printf("Nameserver %s:\n\t",
00224                         query->servname);
00225         }
00226         printf("%s %s %.*s", namestr,
00227                msg, (int)r.length, (char *)r.base);
00228         if (query->lookup->identify) {
00229                 printf(" on server %s", query->servname);
00230         }
00231         printf("\n");
00232         isc_buffer_free(&b);
00233 }
00234 #ifdef DIG_SIGCHASE
00235 /* Just for compatibility : not use in host program */
00236 isc_result_t
00237 printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
00238               isc_buffer_t *target)
00239 {
00240   UNUSED(owner_name);
00241   UNUSED(rdataset);
00242   UNUSED(target);
00243   return(ISC_FALSE);
00244 }
00245 #endif
00246 static isc_result_t
00247 printsection(dns_message_t *msg, dns_section_t sectionid,
00248              const char *section_name, isc_boolean_t headers,
00249              dig_query_t *query)
00250 {
00251         dns_name_t *name, *print_name;
00252         dns_rdataset_t *rdataset;
00253         dns_rdata_t rdata = DNS_RDATA_INIT;
00254         isc_buffer_t target;
00255         isc_result_t result, loopresult;
00256         isc_region_t r;
00257         dns_name_t empty_name;
00258         char tbuf[4096];
00259         isc_boolean_t first;
00260         isc_boolean_t no_rdata;
00261 
00262         if (sectionid == DNS_SECTION_QUESTION)
00263                 no_rdata = ISC_TRUE;
00264         else
00265                 no_rdata = ISC_FALSE;
00266 
00267         if (headers)
00268                 printf(";; %s SECTION:\n", section_name);
00269 
00270         dns_name_init(&empty_name, NULL);
00271 
00272         result = dns_message_firstname(msg, sectionid);
00273         if (result == ISC_R_NOMORE)
00274                 return (ISC_R_SUCCESS);
00275         else if (result != ISC_R_SUCCESS)
00276                 return (result);
00277 
00278         for (;;) {
00279                 name = NULL;
00280                 dns_message_currentname(msg, sectionid, &name);
00281 
00282                 isc_buffer_init(&target, tbuf, sizeof(tbuf));
00283                 first = ISC_TRUE;
00284                 print_name = name;
00285 
00286                 for (rdataset = ISC_LIST_HEAD(name->list);
00287                      rdataset != NULL;
00288                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
00289                         if (query->lookup->rdtype == dns_rdatatype_axfr &&
00290                             !((!list_addresses &&
00291                                (list_type == dns_rdatatype_any ||
00292                                 rdataset->type == list_type)) ||
00293                               (list_addresses &&
00294                                (rdataset->type == dns_rdatatype_a ||
00295                                 rdataset->type == dns_rdatatype_aaaa ||
00296                                 rdataset->type == dns_rdatatype_ns ||
00297                                 rdataset->type == dns_rdatatype_ptr))))
00298                                 continue;
00299                         if (!short_form) {
00300                                 result = dns_rdataset_totext(rdataset,
00301                                                              print_name,
00302                                                              ISC_FALSE,
00303                                                              no_rdata,
00304                                                              &target);
00305                                 if (result != ISC_R_SUCCESS)
00306                                         return (result);
00307 #ifdef USEINITALWS
00308                                 if (first) {
00309                                         print_name = &empty_name;
00310                                         first = ISC_FALSE;
00311                                 }
00312 #else
00313                                 UNUSED(first); /* Shut up compiler. */
00314 #endif
00315                         } else {
00316                                 loopresult = dns_rdataset_first(rdataset);
00317                                 while (loopresult == ISC_R_SUCCESS) {
00318                                         struct rtype *t;
00319                                         const char *rtt;
00320                                         char typebuf[DNS_RDATATYPE_FORMATSIZE];
00321                                         char typebuf2[DNS_RDATATYPE_FORMATSIZE
00322                                                      + 20];
00323                                         dns_rdataset_current(rdataset, &rdata);
00324 
00325                                         for (t = rtypes; t->text != NULL; t++) {
00326                                                 if (t->type == rdata.type) {
00327                                                         rtt = t->text;
00328                                                         goto found;
00329                                                 }
00330                                         }
00331 
00332                                         dns_rdatatype_format(rdata.type,
00333                                                              typebuf,
00334                                                              sizeof(typebuf));
00335                                         snprintf(typebuf2, sizeof(typebuf2),
00336                                                  "has %s record", typebuf);
00337                                         rtt = typebuf2;
00338                                 found:
00339                                         say_message(print_name, rtt,
00340                                                     &rdata, query);
00341                                         dns_rdata_reset(&rdata);
00342                                         loopresult =
00343                                                 dns_rdataset_next(rdataset);
00344                                 }
00345                         }
00346                 }
00347                 if (!short_form) {
00348                         isc_buffer_usedregion(&target, &r);
00349                         if (no_rdata)
00350                                 printf(";%.*s", (int)r.length,
00351                                        (char *)r.base);
00352                         else
00353                                 printf("%.*s", (int)r.length, (char *)r.base);
00354                 }
00355 
00356                 result = dns_message_nextname(msg, sectionid);
00357                 if (result == ISC_R_NOMORE)
00358                         break;
00359                 else if (result != ISC_R_SUCCESS)
00360                         return (result);
00361         }
00362 
00363         return (ISC_R_SUCCESS);
00364 }
00365 
00366 static isc_result_t
00367 printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
00368            const char *set_name, isc_boolean_t headers)
00369 {
00370         isc_buffer_t target;
00371         isc_result_t result;
00372         isc_region_t r;
00373         char tbuf[4096];
00374 
00375         UNUSED(msg);
00376         if (headers)
00377                 printf(";; %s SECTION:\n", set_name);
00378 
00379         isc_buffer_init(&target, tbuf, sizeof(tbuf));
00380 
00381         result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
00382                                      &target);
00383         if (result != ISC_R_SUCCESS)
00384                 return (result);
00385         isc_buffer_usedregion(&target, &r);
00386         printf("%.*s", (int)r.length, (char *)r.base);
00387 
00388         return (ISC_R_SUCCESS);
00389 }
00390 
00391 static void
00392 chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
00393         isc_result_t result;
00394         dns_rdataset_t *rdataset;
00395         dns_rdata_cname_t cname;
00396         dns_rdata_t rdata = DNS_RDATA_INIT;
00397         unsigned int i = msg->counts[DNS_SECTION_ANSWER];
00398 
00399         while (i-- > 0) {
00400                 rdataset = NULL;
00401                 result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
00402                                               dns_rdatatype_cname, 0, NULL,
00403                                               &rdataset);
00404                 if (result != ISC_R_SUCCESS)
00405                         return;
00406                 result = dns_rdataset_first(rdataset);
00407                 check_result(result, "dns_rdataset_first");
00408                 dns_rdata_reset(&rdata);
00409                 dns_rdataset_current(rdataset, &rdata);
00410                 result = dns_rdata_tostruct(&rdata, &cname, NULL);
00411                 check_result(result, "dns_rdata_tostruct");
00412                 dns_name_copy(&cname.cname, qname, NULL);
00413                 dns_rdata_freestruct(&cname);
00414         }
00415 }
00416 
00417 isc_result_t
00418 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
00419         isc_boolean_t did_flag = ISC_FALSE;
00420         dns_rdataset_t *opt, *tsig = NULL;
00421         dns_name_t *tsigname;
00422         isc_result_t result = ISC_R_SUCCESS;
00423         int force_error;
00424 
00425         UNUSED(headers);
00426 
00427         /*
00428          * We get called multiple times.
00429          * Preserve any existing error status.
00430          */
00431         force_error = (seen_error == 1) ? 1 : 0;
00432         seen_error = 1;
00433         if (listed_server && !printed_server) {
00434                 char sockstr[ISC_SOCKADDR_FORMATSIZE];
00435 
00436                 printf("Using domain server:\n");
00437                 printf("Name: %s\n", query->userarg);
00438                 isc_sockaddr_format(&query->sockaddr, sockstr,
00439                                     sizeof(sockstr));
00440                 printf("Address: %s\n", sockstr);
00441                 printf("Aliases: \n\n");
00442                 printed_server = ISC_TRUE;
00443         }
00444 
00445         if (msg->rcode != 0) {
00446                 char namestr[DNS_NAME_FORMATSIZE];
00447                 dns_name_format(query->lookup->name, namestr, sizeof(namestr));
00448 
00449                 if (query->lookup->identify_previous_line)
00450                         printf("Nameserver %s:\n\t%s not found: %d(%s)\n",
00451                                query->servname,
00452                                (msg->rcode != dns_rcode_nxdomain) ? namestr :
00453                                query->lookup->textname, msg->rcode,
00454                                rcode_totext(msg->rcode));
00455                 else
00456                         printf("Host %s not found: %d(%s)\n",
00457                                (msg->rcode != dns_rcode_nxdomain) ? namestr :
00458                                query->lookup->textname, msg->rcode,
00459                                rcode_totext(msg->rcode));
00460                 return (ISC_R_SUCCESS);
00461         }
00462 
00463         if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
00464                 char namestr[DNS_NAME_FORMATSIZE];
00465                 dig_lookup_t *lookup;
00466                 dns_fixedname_t fixed;
00467                 dns_name_t *name;
00468 
00469                 /* Add AAAA and MX lookups. */
00470                 dns_fixedname_init(&fixed);
00471                 name = dns_fixedname_name(&fixed);
00472                 dns_name_copy(query->lookup->name, name, NULL);
00473                 chase_cnamechain(msg, name);
00474                 dns_name_format(name, namestr, sizeof(namestr));
00475                 lookup = clone_lookup(query->lookup, ISC_FALSE);
00476                 if (lookup != NULL) {
00477                         strncpy(lookup->textname, namestr,
00478                                 sizeof(lookup->textname));
00479                         lookup->textname[sizeof(lookup->textname)-1] = 0;
00480                         lookup->rdtype = dns_rdatatype_aaaa;
00481                         lookup->rdtypeset = ISC_TRUE;
00482                         lookup->origin = NULL;
00483                         lookup->retries = tries;
00484                         ISC_LIST_APPEND(lookup_list, lookup, link);
00485                 }
00486                 lookup = clone_lookup(query->lookup, ISC_FALSE);
00487                 if (lookup != NULL) {
00488                         strncpy(lookup->textname, namestr,
00489                                 sizeof(lookup->textname));
00490                         lookup->textname[sizeof(lookup->textname)-1] = 0;
00491                         lookup->rdtype = dns_rdatatype_mx;
00492                         lookup->rdtypeset = ISC_TRUE;
00493                         lookup->origin = NULL;
00494                         lookup->retries = tries;
00495                         ISC_LIST_APPEND(lookup_list, lookup, link);
00496                 }
00497         }
00498 
00499         if (!short_form) {
00500                 printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
00501                        opcodetext[msg->opcode], rcode_totext(msg->rcode),
00502                        msg->id);
00503                 printf(";; flags: ");
00504                 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
00505                         printf("qr");
00506                         did_flag = ISC_TRUE;
00507                 }
00508                 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
00509                         printf("%saa", did_flag ? " " : "");
00510                         did_flag = ISC_TRUE;
00511                 }
00512                 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
00513                         printf("%stc", did_flag ? " " : "");
00514                         did_flag = ISC_TRUE;
00515                 }
00516                 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
00517                         printf("%srd", did_flag ? " " : "");
00518                         did_flag = ISC_TRUE;
00519                 }
00520                 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
00521                         printf("%sra", did_flag ? " " : "");
00522                         did_flag = ISC_TRUE;
00523                 }
00524                 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
00525                         printf("%sad", did_flag ? " " : "");
00526                         did_flag = ISC_TRUE;
00527                 }
00528                 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
00529                         printf("%scd", did_flag ? " " : "");
00530                         did_flag = ISC_TRUE;
00531                         POST(did_flag);
00532                 }
00533                 printf("; QUERY: %u, ANSWER: %u, "
00534                        "AUTHORITY: %u, ADDITIONAL: %u\n",
00535                        msg->counts[DNS_SECTION_QUESTION],
00536                        msg->counts[DNS_SECTION_ANSWER],
00537                        msg->counts[DNS_SECTION_AUTHORITY],
00538                        msg->counts[DNS_SECTION_ADDITIONAL]);
00539                 opt = dns_message_getopt(msg);
00540                 if (opt != NULL)
00541                         printf(";; EDNS: version: %u, udp=%u\n",
00542                                (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
00543                                (unsigned int)opt->rdclass);
00544                 tsigname = NULL;
00545                 tsig = dns_message_gettsig(msg, &tsigname);
00546                 if (tsig != NULL)
00547                         printf(";; PSEUDOSECTIONS: TSIG\n");
00548         }
00549         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
00550             !short_form) {
00551                 printf("\n");
00552                 result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
00553                                       ISC_TRUE, query);
00554                 if (result != ISC_R_SUCCESS)
00555                         return (result);
00556         }
00557         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
00558                 if (!short_form)
00559                         printf("\n");
00560                 result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
00561                                       ISC_TF(!short_form), query);
00562                 if (result != ISC_R_SUCCESS)
00563                         return (result);
00564         }
00565 
00566         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
00567             !short_form) {
00568                 printf("\n");
00569                 result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
00570                                       ISC_TRUE, query);
00571                 if (result != ISC_R_SUCCESS)
00572                         return (result);
00573         }
00574         if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
00575             !short_form) {
00576                 printf("\n");
00577                 result = printsection(msg, DNS_SECTION_ADDITIONAL,
00578                                       "ADDITIONAL", ISC_TRUE, query);
00579                 if (result != ISC_R_SUCCESS)
00580                         return (result);
00581         }
00582         if ((tsig != NULL) && !short_form) {
00583                 printf("\n");
00584                 result = printrdata(msg, tsig, tsigname,
00585                                     "PSEUDOSECTION TSIG", ISC_TRUE);
00586                 if (result != ISC_R_SUCCESS)
00587                         return (result);
00588         }
00589         if (!short_form)
00590                 printf("\n");
00591 
00592         if (short_form && !default_lookups &&
00593             ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
00594                 char namestr[DNS_NAME_FORMATSIZE];
00595                 char typestr[DNS_RDATATYPE_FORMATSIZE];
00596                 dns_name_format(query->lookup->name, namestr, sizeof(namestr));
00597                 dns_rdatatype_format(query->lookup->rdtype, typestr,
00598                                      sizeof(typestr));
00599                 printf("%s has no %s record\n", namestr, typestr);
00600         }
00601         seen_error = force_error;
00602         return (result);
00603 }
00604 
00605 static const char * optstring = "46ac:dilnm:rst:vVwCDN:R:TW:";
00606 
00607 /*% version */
00608 static void
00609 version(void) {
00610         fputs("host " VERSION "\n", stderr);
00611 }
00612 
00613 static void
00614 pre_parse_args(int argc, char **argv) {
00615         int c;
00616 
00617         while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
00618                 switch (c) {
00619                 case 'm':
00620                         memdebugging = ISC_TRUE;
00621                         if (strcasecmp("trace", isc_commandline_argument) == 0)
00622                                 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
00623                         else if (!strcasecmp("record",
00624                                              isc_commandline_argument) == 0)
00625                                 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
00626                         else if (strcasecmp("usage",
00627                                             isc_commandline_argument) == 0)
00628                                 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
00629                         break;
00630 
00631                 case '4': break;
00632                 case '6': break;
00633                 case 'a': break;
00634                 case 'c': break;
00635                 case 'd': break;
00636                 case 'i': break;
00637                 case 'l': break;
00638                 case 'n': break;
00639                 case 'r': break;
00640                 case 's': break;
00641                 case 't': break;
00642                 case 'v': break;
00643                 case 'V':
00644                           version();
00645                           exit(0);
00646                           break;
00647                 case 'w': break;
00648                 case 'C': break;
00649                 case 'D':
00650                         if (debugging)
00651                                 debugtiming = ISC_TRUE;
00652                         debugging = ISC_TRUE;
00653                         break;
00654                 case 'N': break;
00655                 case 'R': break;
00656                 case 'T': break;
00657                 case 'W': break;
00658                 default:
00659                         show_usage();
00660                 }
00661         }
00662         isc_commandline_reset = ISC_TRUE;
00663         isc_commandline_index = 1;
00664 }
00665 
00666 static void
00667 parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
00668         char hostname[MXNAME];
00669         dig_lookup_t *lookup;
00670         int c;
00671         char store[MXNAME];
00672         isc_textregion_t tr;
00673         isc_result_t result = ISC_R_SUCCESS;
00674         dns_rdatatype_t rdtype;
00675         dns_rdataclass_t rdclass;
00676         isc_uint32_t serial = 0;
00677 
00678         UNUSED(is_batchfile);
00679 
00680         lookup = make_empty_lookup();
00681 
00682         lookup->servfail_stops = ISC_FALSE;
00683         lookup->comments = ISC_FALSE;
00684         short_form = !verbose;
00685 
00686         while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
00687                 switch (c) {
00688                 case 'l':
00689                         lookup->tcp_mode = ISC_TRUE;
00690                         lookup->rdtype = dns_rdatatype_axfr;
00691                         lookup->rdtypeset = ISC_TRUE;
00692                         fatalexit = 3;
00693                         break;
00694                 case 'v':
00695                 case 'd':
00696                         short_form = ISC_FALSE;
00697                         break;
00698                 case 'r':
00699                         lookup->recurse = ISC_FALSE;
00700                         break;
00701                 case 't':
00702                         if (strncasecmp(isc_commandline_argument,
00703                                         "ixfr=", 5) == 0) {
00704                                 rdtype = dns_rdatatype_ixfr;
00705                                 /* XXXMPA add error checking */
00706                                 serial = strtoul(isc_commandline_argument + 5,
00707                                                  NULL, 10);
00708                                 result = ISC_R_SUCCESS;
00709                         } else {
00710                                 tr.base = isc_commandline_argument;
00711                                 tr.length = strlen(isc_commandline_argument);
00712                                 result = dns_rdatatype_fromtext(&rdtype,
00713                                                    (isc_textregion_t *)&tr);
00714                         }
00715 
00716                         if (result != ISC_R_SUCCESS) {
00717                                 fatalexit = 2;
00718                                 fatal("invalid type: %s\n",
00719                                       isc_commandline_argument);
00720                         }
00721                         if (!lookup->rdtypeset ||
00722                             lookup->rdtype != dns_rdatatype_axfr)
00723                                 lookup->rdtype = rdtype;
00724                         lookup->rdtypeset = ISC_TRUE;
00725 #ifdef WITH_IDN
00726                         idnoptions = 0;
00727 #endif
00728                         if (rdtype == dns_rdatatype_axfr) {
00729                                 /* -l -t any -v */
00730                                 list_type = dns_rdatatype_any;
00731                                 short_form = ISC_FALSE;
00732                                 lookup->tcp_mode = ISC_TRUE;
00733                         } else if (rdtype == dns_rdatatype_ixfr) {
00734                                 lookup->ixfr_serial = serial;
00735                                 lookup->tcp_mode = ISC_TRUE;
00736                                 list_type = rdtype;
00737 #ifdef WITH_IDN
00738                         } else if (rdtype == dns_rdatatype_a ||
00739                                    rdtype == dns_rdatatype_aaaa ||
00740                                    rdtype == dns_rdatatype_mx) {
00741                                 idnoptions = IDN_ASCCHECK;
00742                                 list_type = rdtype;
00743 #endif
00744                         } else
00745                                 list_type = rdtype;
00746                         list_addresses = ISC_FALSE;
00747                         default_lookups = ISC_FALSE;
00748                         break;
00749                 case 'c':
00750                         tr.base = isc_commandline_argument;
00751                         tr.length = strlen(isc_commandline_argument);
00752                         result = dns_rdataclass_fromtext(&rdclass,
00753                                                    (isc_textregion_t *)&tr);
00754 
00755                         if (result != ISC_R_SUCCESS) {
00756                                 fatalexit = 2;
00757                                 fatal("invalid class: %s\n",
00758                                       isc_commandline_argument);
00759                         } else {
00760                                 lookup->rdclass = rdclass;
00761                                 lookup->rdclassset = ISC_TRUE;
00762                         }
00763                         default_lookups = ISC_FALSE;
00764                         break;
00765                 case 'a':
00766                         if (!lookup->rdtypeset ||
00767                             lookup->rdtype != dns_rdatatype_axfr)
00768                                 lookup->rdtype = dns_rdatatype_any;
00769 #ifdef WITH_IDN
00770                         idnoptions = 0;
00771 #endif
00772                         list_type = dns_rdatatype_any;
00773                         list_addresses = ISC_FALSE;
00774                         lookup->rdtypeset = ISC_TRUE;
00775                         short_form = ISC_FALSE;
00776                         default_lookups = ISC_FALSE;
00777                         break;
00778                 case 'i':
00779                         lookup->ip6_int = ISC_TRUE;
00780                         break;
00781                 case 'n':
00782                         /* deprecated */
00783                         break;
00784                 case 'm':
00785                         /* Handled by pre_parse_args(). */
00786                         break;
00787                 case 'w':
00788                         /*
00789                          * The timer routines are coded such that
00790                          * timeout==MAXINT doesn't enable the timer
00791                          */
00792                         timeout = INT_MAX;
00793                         break;
00794                 case 'W':
00795                         timeout = atoi(isc_commandline_argument);
00796                         if (timeout < 1)
00797                                 timeout = 1;
00798                         break;
00799                 case 'R':
00800                         tries = atoi(isc_commandline_argument) + 1;
00801                         if (tries < 2)
00802                                 tries = 2;
00803                         break;
00804                 case 'T':
00805                         lookup->tcp_mode = ISC_TRUE;
00806                         break;
00807                 case 'C':
00808                         debug("showing all SOAs");
00809                         lookup->rdtype = dns_rdatatype_ns;
00810                         lookup->rdtypeset = ISC_TRUE;
00811                         lookup->rdclass = dns_rdataclass_in;
00812                         lookup->rdclassset = ISC_TRUE;
00813                         lookup->ns_search_only = ISC_TRUE;
00814                         lookup->trace_root = ISC_TRUE;
00815                         lookup->identify_previous_line = ISC_TRUE;
00816                         default_lookups = ISC_FALSE;
00817                         break;
00818                 case 'N':
00819                         debug("setting NDOTS to %s",
00820                               isc_commandline_argument);
00821                         ndots = atoi(isc_commandline_argument);
00822                         break;
00823                 case 'D':
00824                         /* Handled by pre_parse_args(). */
00825                         break;
00826                 case '4':
00827                         if (have_ipv4) {
00828                                 isc_net_disableipv6();
00829                                 have_ipv6 = ISC_FALSE;
00830                         } else
00831                                 fatal("can't find IPv4 networking");
00832                         break;
00833                 case '6':
00834                         if (have_ipv6) {
00835                                 isc_net_disableipv4();
00836                                 have_ipv4 = ISC_FALSE;
00837                         } else
00838                                 fatal("can't find IPv6 networking");
00839                         break;
00840                 case 's':
00841                         lookup->servfail_stops = ISC_TRUE;
00842                         break;
00843                 }
00844         }
00845 
00846         lookup->retries = tries;
00847 
00848         if (isc_commandline_index >= argc)
00849                 show_usage();
00850 
00851         strlcpy(hostname, argv[isc_commandline_index], sizeof(hostname));
00852 
00853         if (argc > isc_commandline_index + 1) {
00854                 set_nameserver(argv[isc_commandline_index+1]);
00855                 debug("server is %s", argv[isc_commandline_index+1]);
00856                 listed_server = ISC_TRUE;
00857         } else
00858                 check_ra = ISC_TRUE;
00859 
00860         lookup->pending = ISC_FALSE;
00861         if (get_reverse(store, sizeof(store), hostname,
00862                         lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) {
00863                 strncpy(lookup->textname, store, sizeof(lookup->textname));
00864                 lookup->textname[sizeof(lookup->textname)-1] = 0;
00865                 lookup->rdtype = dns_rdatatype_ptr;
00866                 lookup->rdtypeset = ISC_TRUE;
00867                 default_lookups = ISC_FALSE;
00868         } else {
00869                 strncpy(lookup->textname, hostname, sizeof(lookup->textname));
00870                 lookup->textname[sizeof(lookup->textname)-1]=0;
00871                 usesearch = ISC_TRUE;
00872         }
00873         lookup->new_search = ISC_TRUE;
00874         ISC_LIST_APPEND(lookup_list, lookup, link);
00875 }
00876 
00877 int
00878 main(int argc, char **argv) {
00879         isc_result_t result;
00880 
00881         tries = 2;
00882 
00883         ISC_LIST_INIT(lookup_list);
00884         ISC_LIST_INIT(server_list);
00885         ISC_LIST_INIT(search_list);
00886 
00887         fatalexit = 1;
00888 #ifdef WITH_IDN
00889         idnoptions = IDN_ASCCHECK;
00890 #endif
00891 
00892         debug("main()");
00893         progname = argv[0];
00894         pre_parse_args(argc, argv);
00895         result = isc_app_start();
00896         check_result(result, "isc_app_start");
00897         setup_libs();
00898         setup_system();
00899         parse_args(ISC_FALSE, argc, argv);
00900         if (keyfile[0] != 0)
00901                 setup_file_key();
00902         else if (keysecret[0] != 0)
00903                 setup_text_key();
00904         result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
00905         check_result(result, "isc_app_onrun");
00906         isc_app_run();
00907         cancel_all();
00908         destroy_libs();
00909         isc_app_finish();
00910         return ((seen_error == 0) ? 0 : 1);
00911 }

Generated on Tue Apr 28 17:40:53 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha