nslookup.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-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 #include <config.h>
00019 
00020 #include <stdlib.h>
00021 #include <unistd.h>
00022 
00023 #include <isc/app.h>
00024 #include <isc/buffer.h>
00025 #include <isc/commandline.h>
00026 #include <isc/event.h>
00027 #include <isc/parseint.h>
00028 #include <isc/print.h>
00029 #include <isc/string.h>
00030 #include <isc/timer.h>
00031 #include <isc/util.h>
00032 #include <isc/task.h>
00033 #include <isc/netaddr.h>
00034 
00035 #include <dns/message.h>
00036 #include <dns/name.h>
00037 #include <dns/fixedname.h>
00038 #include <dns/rdata.h>
00039 #include <dns/rdataclass.h>
00040 #include <dns/rdataset.h>
00041 #include <dns/rdatastruct.h>
00042 #include <dns/rdatatype.h>
00043 #include <dns/byaddr.h>
00044 
00045 #include <dig/dig.h>
00046 
00047 #if defined(HAVE_READLINE)
00048 #include <readline/readline.h>
00049 #include <readline/history.h>
00050 #endif
00051 
00052 static isc_boolean_t short_form = ISC_TRUE,
00053         tcpmode = ISC_FALSE,
00054         identify = ISC_FALSE, stats = ISC_TRUE,
00055         comments = ISC_TRUE, section_question = ISC_TRUE,
00056         section_answer = ISC_TRUE, section_authority = ISC_TRUE,
00057         section_additional = ISC_TRUE, recurse = ISC_TRUE,
00058         aaonly = ISC_FALSE, nofail = ISC_TRUE;
00059 
00060 static isc_boolean_t interactive;
00061 
00062 static isc_boolean_t in_use = ISC_FALSE;
00063 static char defclass[MXRD] = "IN";
00064 static char deftype[MXRD] = "A";
00065 static isc_event_t *global_event = NULL;
00066 static int query_error = 1, print_error = 0;
00067 
00068 static char domainopt[DNS_NAME_MAXTEXT];
00069 
00070 static const char *rcodetext[] = {
00071         "NOERROR",
00072         "FORMERR",
00073         "SERVFAIL",
00074         "NXDOMAIN",
00075         "NOTIMP",
00076         "REFUSED",
00077         "YXDOMAIN",
00078         "YXRRSET",
00079         "NXRRSET",
00080         "NOTAUTH",
00081         "NOTZONE",
00082         "RESERVED11",
00083         "RESERVED12",
00084         "RESERVED13",
00085         "RESERVED14",
00086         "RESERVED15",
00087         "BADVERS"
00088 };
00089 
00090 static const char *rtypetext[] = {
00091         "rtype_0 = ",                   /* 0 */
00092         "internet address = ",          /* 1 */
00093         "nameserver = ",                /* 2 */
00094         "md = ",                        /* 3 */
00095         "mf = ",                        /* 4 */
00096         "canonical name = ",            /* 5 */
00097         "soa = ",                       /* 6 */
00098         "mb = ",                        /* 7 */
00099         "mg = ",                        /* 8 */
00100         "mr = ",                        /* 9 */
00101         "rtype_10 = ",                  /* 10 */
00102         "protocol = ",                  /* 11 */
00103         "name = ",                      /* 12 */
00104         "hinfo = ",                     /* 13 */
00105         "minfo = ",                     /* 14 */
00106         "mail exchanger = ",            /* 15 */
00107         "text = ",                      /* 16 */
00108         "rp = ",                        /* 17 */
00109         "afsdb = ",                     /* 18 */
00110         "x25 address = ",               /* 19 */
00111         "isdn address = ",              /* 20 */
00112         "rt = ",                        /* 21 */
00113         "nsap = ",                      /* 22 */
00114         "nsap_ptr = ",                  /* 23 */
00115         "signature = ",                 /* 24 */
00116         "key = ",                       /* 25 */
00117         "px = ",                        /* 26 */
00118         "gpos = ",                      /* 27 */
00119         "has AAAA address ",            /* 28 */
00120         "loc = ",                       /* 29 */
00121         "next = ",                      /* 30 */
00122         "rtype_31 = ",                  /* 31 */
00123         "rtype_32 = ",                  /* 32 */
00124         "service = ",                   /* 33 */
00125         "rtype_34 = ",                  /* 34 */
00126         "naptr = ",                     /* 35 */
00127         "kx = ",                        /* 36 */
00128         "cert = ",                      /* 37 */
00129         "v6 address = ",                /* 38 */
00130         "dname = ",                     /* 39 */
00131         "rtype_40 = ",                  /* 40 */
00132         "optional = "                   /* 41 */
00133 };
00134 
00135 #define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
00136 
00137 static void flush_lookup_list(void);
00138 static void getinput(isc_task_t *task, isc_event_t *event);
00139 
00140 static char *
00141 rcode_totext(dns_rcode_t rcode)
00142 {
00143         static char buf[sizeof("?65535")];
00144         union {
00145                 const char *consttext;
00146                 char *deconsttext;
00147         } totext;
00148 
00149         if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
00150                 snprintf(buf, sizeof(buf), "?%u", rcode);
00151                 totext.deconsttext = buf;
00152         } else
00153                 totext.consttext = rcodetext[rcode];
00154         return totext.deconsttext;
00155 }
00156 
00157 void
00158 dighost_shutdown(void) {
00159         isc_event_t *event = global_event;
00160 
00161         flush_lookup_list();
00162         debug("dighost_shutdown()");
00163 
00164         if (!in_use) {
00165                 isc_app_shutdown();
00166                 return;
00167         }
00168 
00169         isc_task_send(global_task, &event);
00170 }
00171 
00172 static void
00173 printsoa(dns_rdata_t *rdata) {
00174         dns_rdata_soa_t soa;
00175         isc_result_t result;
00176         char namebuf[DNS_NAME_FORMATSIZE];
00177 
00178         result = dns_rdata_tostruct(rdata, &soa, NULL);
00179         check_result(result, "dns_rdata_tostruct");
00180 
00181         dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
00182         printf("\torigin = %s\n", namebuf);
00183         dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
00184         printf("\tmail addr = %s\n", namebuf);
00185         printf("\tserial = %u\n", soa.serial);
00186         printf("\trefresh = %u\n", soa.refresh);
00187         printf("\tretry = %u\n", soa.retry);
00188         printf("\texpire = %u\n", soa.expire);
00189         printf("\tminimum = %u\n", soa.minimum);
00190         dns_rdata_freestruct(&soa);
00191 }
00192 
00193 static void
00194 printa(dns_rdata_t *rdata) {
00195         isc_result_t result;
00196         char text[sizeof("255.255.255.255")];
00197         isc_buffer_t b;
00198 
00199         isc_buffer_init(&b, text, sizeof(text));
00200         result = dns_rdata_totext(rdata, NULL, &b);
00201         check_result(result, "dns_rdata_totext");
00202         printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
00203                (char *)isc_buffer_base(&b));
00204 }
00205 #ifdef DIG_SIGCHASE
00206 /* Just for compatibility : not use in host program */
00207 isc_result_t
00208 printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
00209               isc_buffer_t *target)
00210 {
00211         UNUSED(owner_name);
00212         UNUSED(rdataset);
00213         UNUSED(target);
00214         return(ISC_FALSE);
00215 }
00216 #endif
00217 static void
00218 printrdata(dns_rdata_t *rdata) {
00219         isc_result_t result;
00220         isc_buffer_t *b = NULL;
00221         unsigned int size = 1024;
00222         isc_boolean_t done = ISC_FALSE;
00223 
00224         if (rdata->type < N_KNOWN_RRTYPES)
00225                 printf("%s", rtypetext[rdata->type]);
00226         else
00227                 printf("rdata_%d = ", rdata->type);
00228 
00229         while (!done) {
00230                 result = isc_buffer_allocate(mctx, &b, size);
00231                 if (result != ISC_R_SUCCESS)
00232                         check_result(result, "isc_buffer_allocate");
00233                 result = dns_rdata_totext(rdata, NULL, b);
00234                 if (result == ISC_R_SUCCESS) {
00235                         printf("%.*s\n", (int)isc_buffer_usedlength(b),
00236                                (char *)isc_buffer_base(b));
00237                         done = ISC_TRUE;
00238                 } else if (result != ISC_R_NOSPACE)
00239                         check_result(result, "dns_rdata_totext");
00240                 isc_buffer_free(&b);
00241                 size *= 2;
00242         }
00243 }
00244 
00245 static isc_result_t
00246 printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
00247              dns_section_t section) {
00248         isc_result_t result, loopresult;
00249         dns_name_t *name;
00250         dns_rdataset_t *rdataset = NULL;
00251         dns_rdata_t rdata = DNS_RDATA_INIT;
00252         char namebuf[DNS_NAME_FORMATSIZE];
00253 
00254         UNUSED(query);
00255         UNUSED(headers);
00256 
00257         debug("printsection()");
00258 
00259         result = dns_message_firstname(msg, section);
00260         if (result == ISC_R_NOMORE)
00261                 return (ISC_R_SUCCESS);
00262         else if (result != ISC_R_SUCCESS)
00263                 return (result);
00264         for (;;) {
00265                 name = NULL;
00266                 dns_message_currentname(msg, section,
00267                                         &name);
00268                 for (rdataset = ISC_LIST_HEAD(name->list);
00269                      rdataset != NULL;
00270                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
00271                         loopresult = dns_rdataset_first(rdataset);
00272                         while (loopresult == ISC_R_SUCCESS) {
00273                                 dns_rdataset_current(rdataset, &rdata);
00274                                 switch (rdata.type) {
00275                                 case dns_rdatatype_a:
00276                                         if (section != DNS_SECTION_ANSWER)
00277                                                 goto def_short_section;
00278                                         dns_name_format(name, namebuf,
00279                                                         sizeof(namebuf));
00280                                         printf("Name:\t%s\n", namebuf);
00281                                         printa(&rdata);
00282                                         break;
00283                                 case dns_rdatatype_soa:
00284                                         dns_name_format(name, namebuf,
00285                                                         sizeof(namebuf));
00286                                         printf("%s\n", namebuf);
00287                                         printsoa(&rdata);
00288                                         break;
00289                                 default:
00290                                 def_short_section:
00291                                         dns_name_format(name, namebuf,
00292                                                         sizeof(namebuf));
00293                                         printf("%s\t", namebuf);
00294                                         printrdata(&rdata);
00295                                         break;
00296                                 }
00297                                 dns_rdata_reset(&rdata);
00298                                 loopresult = dns_rdataset_next(rdataset);
00299                         }
00300                 }
00301                 result = dns_message_nextname(msg, section);
00302                 if (result == ISC_R_NOMORE)
00303                         break;
00304                 else if (result != ISC_R_SUCCESS) {
00305                         return (result);
00306                 }
00307         }
00308         return (ISC_R_SUCCESS);
00309 }
00310 
00311 static isc_result_t
00312 detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
00313              dns_section_t section) {
00314         isc_result_t result, loopresult;
00315         dns_name_t *name;
00316         dns_rdataset_t *rdataset = NULL;
00317         dns_rdata_t rdata = DNS_RDATA_INIT;
00318         char namebuf[DNS_NAME_FORMATSIZE];
00319 
00320         UNUSED(query);
00321 
00322         debug("detailsection()");
00323 
00324         if (headers) {
00325                 switch (section) {
00326                 case DNS_SECTION_QUESTION:
00327                         puts("    QUESTIONS:");
00328                         break;
00329                 case DNS_SECTION_ANSWER:
00330                         puts("    ANSWERS:");
00331                         break;
00332                 case DNS_SECTION_AUTHORITY:
00333                         puts("    AUTHORITY RECORDS:");
00334                         break;
00335                 case DNS_SECTION_ADDITIONAL:
00336                         puts("    ADDITIONAL RECORDS:");
00337                         break;
00338                 }
00339         }
00340 
00341         result = dns_message_firstname(msg, section);
00342         if (result == ISC_R_NOMORE)
00343                 return (ISC_R_SUCCESS);
00344         else if (result != ISC_R_SUCCESS)
00345                 return (result);
00346         for (;;) {
00347                 name = NULL;
00348                 dns_message_currentname(msg, section,
00349                                         &name);
00350                 for (rdataset = ISC_LIST_HEAD(name->list);
00351                      rdataset != NULL;
00352                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
00353                         if (section == DNS_SECTION_QUESTION) {
00354                                 dns_name_format(name, namebuf,
00355                                                 sizeof(namebuf));
00356                                 printf("\t%s, ", namebuf);
00357                                 dns_rdatatype_format(rdataset->type,
00358                                                      namebuf,
00359                                                      sizeof(namebuf));
00360                                 printf("type = %s, ", namebuf);
00361                                 dns_rdataclass_format(rdataset->rdclass,
00362                                                       namebuf,
00363                                                       sizeof(namebuf));
00364                                 printf("class = %s\n", namebuf);
00365                         }
00366                         loopresult = dns_rdataset_first(rdataset);
00367                         while (loopresult == ISC_R_SUCCESS) {
00368                                 dns_rdataset_current(rdataset, &rdata);
00369 
00370                                 dns_name_format(name, namebuf,
00371                                                 sizeof(namebuf));
00372                                 printf("    ->  %s\n", namebuf);
00373 
00374                                 switch (rdata.type) {
00375                                 case dns_rdatatype_soa:
00376                                         printsoa(&rdata);
00377                                         break;
00378                                 default:
00379                                         printf("\t");
00380                                         printrdata(&rdata);
00381                                 }
00382                                 dns_rdata_reset(&rdata);
00383                                 printf("\tttl = %u\n", rdataset->ttl);
00384                                 loopresult = dns_rdataset_next(rdataset);
00385                         }
00386                 }
00387                 result = dns_message_nextname(msg, section);
00388                 if (result == ISC_R_NOMORE)
00389                         break;
00390                 else if (result != ISC_R_SUCCESS) {
00391                         return (result);
00392                 }
00393         }
00394         return (ISC_R_SUCCESS);
00395 }
00396 
00397 void
00398 received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
00399 {
00400         UNUSED(bytes);
00401         UNUSED(from);
00402         UNUSED(query);
00403 }
00404 
00405 void
00406 trying(char *frm, dig_lookup_t *lookup) {
00407         UNUSED(frm);
00408         UNUSED(lookup);
00409 
00410 }
00411 
00412 isc_result_t
00413 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
00414         char servtext[ISC_SOCKADDR_FORMATSIZE];
00415 
00416         /* I've we've gotten this far, we've reached a server. */
00417         query_error = 0;
00418 
00419         debug("printmessage()");
00420 
00421         isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
00422         printf("Server:\t\t%s\n", query->userarg);
00423         printf("Address:\t%s\n", servtext);
00424 
00425         puts("");
00426 
00427         if (!short_form) {
00428                 puts("------------");
00429                 /*              detailheader(query, msg);*/
00430                 detailsection(query, msg, ISC_TRUE, DNS_SECTION_QUESTION);
00431                 detailsection(query, msg, ISC_TRUE, DNS_SECTION_ANSWER);
00432                 detailsection(query, msg, ISC_TRUE, DNS_SECTION_AUTHORITY);
00433                 detailsection(query, msg, ISC_TRUE, DNS_SECTION_ADDITIONAL);
00434                 puts("------------");
00435         }
00436 
00437         if (msg->rcode != 0) {
00438                 char nametext[DNS_NAME_FORMATSIZE];
00439                 dns_name_format(query->lookup->name,
00440                                 nametext, sizeof(nametext));
00441                 printf("** server can't find %s: %s\n",
00442                        nametext, rcode_totext(msg->rcode));
00443                 debug("returning with rcode == 0");
00444 
00445                 /* the lookup failed */
00446                 print_error |= 1;
00447                 return (ISC_R_SUCCESS);
00448         }
00449 
00450         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
00451                 puts("Non-authoritative answer:");
00452         if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
00453                 printsection(query, msg, headers, DNS_SECTION_ANSWER);
00454         else
00455                 printf("*** Can't find %s: No answer\n",
00456                        query->lookup->textname);
00457 
00458         if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
00459             (query->lookup->rdtype != dns_rdatatype_a)) {
00460                 puts("\nAuthoritative answers can be found from:");
00461                 printsection(query, msg, headers,
00462                              DNS_SECTION_AUTHORITY);
00463                 printsection(query, msg, headers,
00464                              DNS_SECTION_ADDITIONAL);
00465         }
00466         return (ISC_R_SUCCESS);
00467 }
00468 
00469 static void
00470 show_settings(isc_boolean_t full, isc_boolean_t serv_only) {
00471         dig_server_t *srv;
00472         isc_sockaddr_t sockaddr;
00473         dig_searchlist_t *listent;
00474         isc_result_t result;
00475 
00476         srv = ISC_LIST_HEAD(server_list);
00477 
00478         while (srv != NULL) {
00479                 char sockstr[ISC_SOCKADDR_FORMATSIZE];
00480 
00481                 result = get_address(srv->servername, port, &sockaddr);
00482                 check_result(result, "get_address");
00483 
00484                 isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
00485                 printf("Default server: %s\nAddress: %s\n",
00486                         srv->userarg, sockstr);
00487                 if (!full)
00488                         return;
00489                 srv = ISC_LIST_NEXT(srv, link);
00490         }
00491         if (serv_only)
00492                 return;
00493         printf("\nSet options:\n");
00494         printf("  %s\t\t\t%s\t\t%s\n",
00495                tcpmode ? "vc" : "novc",
00496                short_form ? "nodebug" : "debug",
00497                debugging ? "d2" : "nod2");
00498         printf("  %s\t\t%s\n",
00499                usesearch ? "search" : "nosearch",
00500                recurse ? "recurse" : "norecurse");
00501         printf("  timeout = %d\t\tretry = %d\tport = %d\tndots = %d\n",
00502                timeout, tries, port, ndots);
00503         printf("  querytype = %-8s\tclass = %s\n", deftype, defclass);
00504         printf("  srchlist = ");
00505         for (listent = ISC_LIST_HEAD(search_list);
00506              listent != NULL;
00507              listent = ISC_LIST_NEXT(listent, link)) {
00508                      printf("%s", listent->origin);
00509                      if (ISC_LIST_NEXT(listent, link) != NULL)
00510                              printf("/");
00511         }
00512         printf("\n");
00513 }
00514 
00515 static isc_boolean_t
00516 testtype(char *typetext) {
00517         isc_result_t result;
00518         isc_textregion_t tr;
00519         dns_rdatatype_t rdtype;
00520 
00521         tr.base = typetext;
00522         tr.length = strlen(typetext);
00523         result = dns_rdatatype_fromtext(&rdtype, &tr);
00524         if (result == ISC_R_SUCCESS)
00525                 return (ISC_TRUE);
00526         else {
00527                 printf("unknown query type: %s\n", typetext);
00528                 return (ISC_FALSE);
00529         }
00530 }
00531 
00532 static isc_boolean_t
00533 testclass(char *typetext) {
00534         isc_result_t result;
00535         isc_textregion_t tr;
00536         dns_rdataclass_t rdclass;
00537 
00538         tr.base = typetext;
00539         tr.length = strlen(typetext);
00540         result = dns_rdataclass_fromtext(&rdclass, &tr);
00541         if (result == ISC_R_SUCCESS)
00542                 return (ISC_TRUE);
00543         else {
00544                 printf("unknown query class: %s\n", typetext);
00545                 return (ISC_FALSE);
00546         }
00547 }
00548 
00549 static void
00550 set_port(const char *value) {
00551         isc_uint32_t n;
00552         isc_result_t result = parse_uint(&n, value, 65535, "port");
00553         if (result == ISC_R_SUCCESS)
00554                 port = (isc_uint16_t) n;
00555 }
00556 
00557 static void
00558 set_timeout(const char *value) {
00559         isc_uint32_t n;
00560         isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
00561         if (result == ISC_R_SUCCESS)
00562                 timeout = n;
00563 }
00564 
00565 static void
00566 set_tries(const char *value) {
00567         isc_uint32_t n;
00568         isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
00569         if (result == ISC_R_SUCCESS)
00570                 tries = n;
00571 }
00572 
00573 static void
00574 set_ndots(const char *value) {
00575         isc_uint32_t n;
00576         isc_result_t result = parse_uint(&n, value, 128, "ndots");
00577         if (result == ISC_R_SUCCESS)
00578                 ndots = n;
00579 }
00580 
00581 static void
00582 version(void) {
00583         fputs("nslookup " VERSION "\n", stderr);
00584 }
00585 
00586 static void
00587 setoption(char *opt) {
00588         if (strncasecmp(opt, "all", 3) == 0) {
00589                 show_settings(ISC_TRUE, ISC_FALSE);
00590         } else if (strncasecmp(opt, "class=", 6) == 0) {
00591                 if (testclass(&opt[6]))
00592                         strlcpy(defclass, &opt[6], sizeof(defclass));
00593         } else if (strncasecmp(opt, "cl=", 3) == 0) {
00594                 if (testclass(&opt[3]))
00595                         strlcpy(defclass, &opt[3], sizeof(defclass));
00596         } else if (strncasecmp(opt, "type=", 5) == 0) {
00597                 if (testtype(&opt[5]))
00598                         strlcpy(deftype, &opt[5], sizeof(deftype));
00599         } else if (strncasecmp(opt, "ty=", 3) == 0) {
00600                 if (testtype(&opt[3]))
00601                         strlcpy(deftype, &opt[3], sizeof(deftype));
00602         } else if (strncasecmp(opt, "querytype=", 10) == 0) {
00603                 if (testtype(&opt[10]))
00604                         strlcpy(deftype, &opt[10], sizeof(deftype));
00605         } else if (strncasecmp(opt, "query=", 6) == 0) {
00606                 if (testtype(&opt[6]))
00607                         strlcpy(deftype, &opt[6], sizeof(deftype));
00608         } else if (strncasecmp(opt, "qu=", 3) == 0) {
00609                 if (testtype(&opt[3]))
00610                         strlcpy(deftype, &opt[3], sizeof(deftype));
00611         } else if (strncasecmp(opt, "q=", 2) == 0) {
00612                 if (testtype(&opt[2]))
00613                         strlcpy(deftype, &opt[2], sizeof(deftype));
00614         } else if (strncasecmp(opt, "domain=", 7) == 0) {
00615                 strlcpy(domainopt, &opt[7], sizeof(domainopt));
00616                 set_search_domain(domainopt);
00617                 usesearch = ISC_TRUE;
00618         } else if (strncasecmp(opt, "do=", 3) == 0) {
00619                 strlcpy(domainopt, &opt[3], sizeof(domainopt));
00620                 set_search_domain(domainopt);
00621                 usesearch = ISC_TRUE;
00622         } else if (strncasecmp(opt, "port=", 5) == 0) {
00623                 set_port(&opt[5]);
00624         } else if (strncasecmp(opt, "po=", 3) == 0) {
00625                 set_port(&opt[3]);
00626         } else if (strncasecmp(opt, "timeout=", 8) == 0) {
00627                 set_timeout(&opt[8]);
00628         } else if (strncasecmp(opt, "t=", 2) == 0) {
00629                 set_timeout(&opt[2]);
00630         } else if (strncasecmp(opt, "rec", 3) == 0) {
00631                 recurse = ISC_TRUE;
00632         } else if (strncasecmp(opt, "norec", 5) == 0) {
00633                 recurse = ISC_FALSE;
00634         } else if (strncasecmp(opt, "retry=", 6) == 0) {
00635                 set_tries(&opt[6]);
00636         } else if (strncasecmp(opt, "ret=", 4) == 0) {
00637                 set_tries(&opt[4]);
00638         } else if (strncasecmp(opt, "def", 3) == 0) {
00639                 usesearch = ISC_TRUE;
00640         } else if (strncasecmp(opt, "nodef", 5) == 0) {
00641                 usesearch = ISC_FALSE;
00642         } else if (strncasecmp(opt, "vc", 3) == 0) {
00643                 tcpmode = ISC_TRUE;
00644         } else if (strncasecmp(opt, "novc", 5) == 0) {
00645                 tcpmode = ISC_FALSE;
00646         } else if (strncasecmp(opt, "deb", 3) == 0) {
00647                 short_form = ISC_FALSE;
00648                 showsearch = ISC_TRUE;
00649         } else if (strncasecmp(opt, "nodeb", 5) == 0) {
00650                 short_form = ISC_TRUE;
00651                 showsearch = ISC_FALSE;
00652         } else if (strncasecmp(opt, "d2", 2) == 0) {
00653                 debugging = ISC_TRUE;
00654         } else if (strncasecmp(opt, "nod2", 4) == 0) {
00655                 debugging = ISC_FALSE;
00656         } else if (strncasecmp(opt, "search", 3) == 0) {
00657                 usesearch = ISC_TRUE;
00658         } else if (strncasecmp(opt, "nosearch", 5) == 0) {
00659                 usesearch = ISC_FALSE;
00660         } else if (strncasecmp(opt, "sil", 3) == 0) {
00661                 /* deprecation_msg = ISC_FALSE; */
00662         } else if (strncasecmp(opt, "fail", 3) == 0) {
00663                 nofail=ISC_FALSE;
00664         } else if (strncasecmp(opt, "nofail", 3) == 0) {
00665                 nofail=ISC_TRUE;
00666         } else if (strncasecmp(opt, "ndots=", 6) == 0) {
00667                 set_ndots(&opt[6]);
00668         } else {
00669                 printf("*** Invalid option: %s\n", opt);
00670         }
00671 }
00672 
00673 static void
00674 addlookup(char *opt) {
00675         dig_lookup_t *lookup;
00676         isc_result_t result;
00677         isc_textregion_t tr;
00678         dns_rdatatype_t rdtype;
00679         dns_rdataclass_t rdclass;
00680         char store[MXNAME];
00681 
00682         debug("addlookup()");
00683         tr.base = deftype;
00684         tr.length = strlen(deftype);
00685         result = dns_rdatatype_fromtext(&rdtype, &tr);
00686         if (result != ISC_R_SUCCESS) {
00687                 printf("unknown query type: %s\n", deftype);
00688                 rdclass = dns_rdatatype_a;
00689         }
00690         tr.base = defclass;
00691         tr.length = strlen(defclass);
00692         result = dns_rdataclass_fromtext(&rdclass, &tr);
00693         if (result != ISC_R_SUCCESS) {
00694                 printf("unknown query class: %s\n", defclass);
00695                 rdclass = dns_rdataclass_in;
00696         }
00697         lookup = make_empty_lookup();
00698         if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
00699             == ISC_R_SUCCESS) {
00700                 strlcpy(lookup->textname, store, sizeof(lookup->textname));
00701                 lookup->rdtype = dns_rdatatype_ptr;
00702                 lookup->rdtypeset = ISC_TRUE;
00703         } else {
00704                 strlcpy(lookup->textname, opt, sizeof(lookup->textname));
00705                 lookup->rdtype = rdtype;
00706                 lookup->rdtypeset = ISC_TRUE;
00707         }
00708         lookup->rdclass = rdclass;
00709         lookup->rdclassset = ISC_TRUE;
00710         lookup->trace = ISC_FALSE;
00711         lookup->trace_root = lookup->trace;
00712         lookup->ns_search_only = ISC_FALSE;
00713         lookup->identify = identify;
00714         lookup->recurse = recurse;
00715         lookup->aaonly = aaonly;
00716         lookup->retries = tries;
00717         lookup->udpsize = 0;
00718         lookup->comments = comments;
00719         lookup->tcp_mode = tcpmode;
00720         lookup->stats = stats;
00721         lookup->section_question = section_question;
00722         lookup->section_answer = section_answer;
00723         lookup->section_authority = section_authority;
00724         lookup->section_additional = section_additional;
00725         lookup->new_search = ISC_TRUE;
00726         if (nofail)
00727                 lookup->servfail_stops = ISC_FALSE;
00728         ISC_LIST_INIT(lookup->q);
00729         ISC_LINK_INIT(lookup, link);
00730         ISC_LIST_APPEND(lookup_list, lookup, link);
00731         lookup->origin = NULL;
00732         ISC_LIST_INIT(lookup->my_server_list);
00733         debug("looking up %s", lookup->textname);
00734 }
00735 
00736 static void
00737 do_next_command(char *input) {
00738         char *ptr, *arg;
00739 
00740         ptr = next_token(&input, " \t\r\n");
00741         if (ptr == NULL)
00742                 return;
00743         arg = next_token(&input, " \t\r\n");
00744         if ((strcasecmp(ptr, "set") == 0) &&
00745             (arg != NULL))
00746                 setoption(arg);
00747         else if ((strcasecmp(ptr, "server") == 0) ||
00748                  (strcasecmp(ptr, "lserver") == 0)) {
00749                 isc_app_block();
00750                 set_nameserver(arg);
00751                 check_ra = ISC_FALSE;
00752                 isc_app_unblock();
00753                 show_settings(ISC_TRUE, ISC_TRUE);
00754         } else if (strcasecmp(ptr, "exit") == 0) {
00755                 in_use = ISC_FALSE;
00756         } else if (strcasecmp(ptr, "help") == 0 ||
00757                    strcasecmp(ptr, "?") == 0) {
00758                 printf("The '%s' command is not yet implemented.\n", ptr);
00759         } else if (strcasecmp(ptr, "finger") == 0 ||
00760                    strcasecmp(ptr, "root") == 0 ||
00761                    strcasecmp(ptr, "ls") == 0 ||
00762                    strcasecmp(ptr, "view") == 0) {
00763                 printf("The '%s' command is not implemented.\n", ptr);
00764         } else
00765                 addlookup(ptr);
00766 }
00767 
00768 static void
00769 get_next_command(void) {
00770         char *buf;
00771         char *ptr;
00772 
00773         fflush(stdout);
00774         buf = isc_mem_allocate(mctx, COMMSIZE);
00775         if (buf == NULL)
00776                 fatal("memory allocation failure");
00777         isc_app_block();
00778         if (interactive) {
00779 #ifdef HAVE_READLINE
00780                 ptr = readline("> ");
00781                 if (ptr != NULL)
00782                         add_history(ptr);
00783 #else
00784                 fputs("> ", stderr);
00785                 fflush(stderr);
00786                 ptr = fgets(buf, COMMSIZE, stdin);
00787 #endif
00788         } else
00789                 ptr = fgets(buf, COMMSIZE, stdin);
00790         isc_app_unblock();
00791         if (ptr == NULL) {
00792                 in_use = ISC_FALSE;
00793         } else
00794                 do_next_command(ptr);
00795 #ifdef HAVE_READLINE
00796         if (interactive)
00797                 free(ptr);
00798 #endif
00799         isc_mem_free(mctx, buf);
00800 }
00801 
00802 static void
00803 parse_args(int argc, char **argv) {
00804         isc_boolean_t have_lookup = ISC_FALSE;
00805 
00806         usesearch = ISC_TRUE;
00807         for (argc--, argv++; argc > 0; argc--, argv++) {
00808                 debug("main parsing %s", argv[0]);
00809                 if (argv[0][0] == '-') {
00810                         if (strncasecmp(argv[0], "-ver", 4) == 0) {
00811                                 version();
00812                                 exit(0);
00813                         } else if (argv[0][1] != 0) {
00814                                 setoption(&argv[0][1]);
00815                         } else
00816                                 have_lookup = ISC_TRUE;
00817                 } else {
00818                         if (!have_lookup) {
00819                                 have_lookup = ISC_TRUE;
00820                                 in_use = ISC_TRUE;
00821                                 addlookup(argv[0]);
00822                         } else {
00823                                 set_nameserver(argv[0]);
00824                                 check_ra = ISC_FALSE;
00825                         }
00826                 }
00827         }
00828 }
00829 
00830 static void
00831 flush_lookup_list(void) {
00832         dig_lookup_t *l, *lp;
00833         dig_query_t *q, *qp;
00834         dig_server_t *s, *sp;
00835 
00836         lookup_counter = 0;
00837         l = ISC_LIST_HEAD(lookup_list);
00838         while (l != NULL) {
00839                 q = ISC_LIST_HEAD(l->q);
00840                 while (q != NULL) {
00841                         if (q->sock != NULL) {
00842                                 isc_socket_cancel(q->sock, NULL,
00843                                                   ISC_SOCKCANCEL_ALL);
00844                                 isc_socket_detach(&q->sock);
00845                         }
00846                         if (ISC_LINK_LINKED(&q->recvbuf, link))
00847                                 ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
00848                                                  link);
00849                         if (ISC_LINK_LINKED(&q->lengthbuf, link))
00850                                 ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
00851                                                  link);
00852                         isc_buffer_invalidate(&q->recvbuf);
00853                         isc_buffer_invalidate(&q->lengthbuf);
00854                         qp = q;
00855                         q = ISC_LIST_NEXT(q, link);
00856                         ISC_LIST_DEQUEUE(l->q, qp, link);
00857                         isc_mem_free(mctx, qp);
00858                 }
00859                 s = ISC_LIST_HEAD(l->my_server_list);
00860                 while (s != NULL) {
00861                         sp = s;
00862                         s = ISC_LIST_NEXT(s, link);
00863                         ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
00864                         isc_mem_free(mctx, sp);
00865 
00866                 }
00867                 if (l->sendmsg != NULL)
00868                         dns_message_destroy(&l->sendmsg);
00869                 if (l->timer != NULL)
00870                         isc_timer_detach(&l->timer);
00871                 lp = l;
00872                 l = ISC_LIST_NEXT(l, link);
00873                 ISC_LIST_DEQUEUE(lookup_list, lp, link);
00874                 isc_mem_free(mctx, lp);
00875         }
00876 }
00877 
00878 static void
00879 getinput(isc_task_t *task, isc_event_t *event) {
00880         UNUSED(task);
00881         if (global_event == NULL)
00882                 global_event = event;
00883         while (in_use) {
00884                 get_next_command();
00885                 if (ISC_LIST_HEAD(lookup_list) != NULL) {
00886                         start_lookup();
00887                         return;
00888                 }
00889         }
00890         isc_app_shutdown();
00891 }
00892 
00893 int
00894 main(int argc, char **argv) {
00895         isc_result_t result;
00896 
00897         interactive = ISC_TF(isatty(0));
00898 
00899         ISC_LIST_INIT(lookup_list);
00900         ISC_LIST_INIT(server_list);
00901         ISC_LIST_INIT(search_list);
00902 
00903         check_ra = ISC_TRUE;
00904 
00905         result = isc_app_start();
00906         check_result(result, "isc_app_start");
00907 
00908         setup_libs();
00909         progname = argv[0];
00910 
00911         setup_system();
00912         parse_args(argc, argv);
00913         if (keyfile[0] != 0)
00914                 setup_file_key();
00915         else if (keysecret[0] != 0)
00916                 setup_text_key();
00917         if (domainopt[0] != '\0')
00918                 set_search_domain(domainopt);
00919         if (in_use)
00920                 result = isc_app_onrun(mctx, global_task, onrun_callback,
00921                                        NULL);
00922         else
00923                 result = isc_app_onrun(mctx, global_task, getinput, NULL);
00924         check_result(result, "isc_app_onrun");
00925         in_use = ISC_TF(!in_use);
00926 
00927         (void)isc_app_run();
00928 
00929         puts("");
00930         debug("done, and starting to shut down");
00931         if (global_event != NULL)
00932                 isc_event_free(&global_event);
00933         cancel_all();
00934         destroy_libs();
00935         isc_app_finish();
00936 
00937         return (query_error | print_error);
00938 }

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