00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 = ",
00092 "internet address = ",
00093 "nameserver = ",
00094 "md = ",
00095 "mf = ",
00096 "canonical name = ",
00097 "soa = ",
00098 "mb = ",
00099 "mg = ",
00100 "mr = ",
00101 "rtype_10 = ",
00102 "protocol = ",
00103 "name = ",
00104 "hinfo = ",
00105 "minfo = ",
00106 "mail exchanger = ",
00107 "text = ",
00108 "rp = ",
00109 "afsdb = ",
00110 "x25 address = ",
00111 "isdn address = ",
00112 "rt = ",
00113 "nsap = ",
00114 "nsap_ptr = ",
00115 "signature = ",
00116 "key = ",
00117 "px = ",
00118 "gpos = ",
00119 "has AAAA address ",
00120 "loc = ",
00121 "next = ",
00122 "rtype_31 = ",
00123 "rtype_32 = ",
00124 "service = ",
00125 "rtype_34 = ",
00126 "naptr = ",
00127 "kx = ",
00128 "cert = ",
00129 "v6 address = ",
00130 "dname = ",
00131 "rtype_40 = ",
00132 "optional = "
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
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
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
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
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
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 }