nslookup.c revision 135446
1/* 2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: nslookup.c,v 1.90.2.4.2.7 2004/08/18 23:25:58 marka Exp $ */ 19 20#include <config.h> 21 22#include <stdlib.h> 23 24#include <isc/app.h> 25#include <isc/buffer.h> 26#include <isc/commandline.h> 27#include <isc/event.h> 28#include <isc/parseint.h> 29#include <isc/string.h> 30#include <isc/timer.h> 31#include <isc/util.h> 32#include <isc/task.h> 33#include <isc/netaddr.h> 34 35#include <dns/message.h> 36#include <dns/name.h> 37#include <dns/fixedname.h> 38#include <dns/rdata.h> 39#include <dns/rdataclass.h> 40#include <dns/rdataset.h> 41#include <dns/rdatastruct.h> 42#include <dns/rdatatype.h> 43#include <dns/byaddr.h> 44 45#include <dig/dig.h> 46 47extern ISC_LIST(dig_lookup_t) lookup_list; 48extern dig_serverlist_t server_list; 49extern ISC_LIST(dig_searchlist_t) search_list; 50 51extern isc_boolean_t usesearch, debugging; 52extern in_port_t port; 53extern unsigned int timeout; 54extern isc_mem_t *mctx; 55extern int tries; 56extern int lookup_counter; 57extern isc_task_t *global_task; 58extern char *progname; 59 60static isc_boolean_t short_form = ISC_TRUE, 61 tcpmode = ISC_FALSE, 62 identify = ISC_FALSE, stats = ISC_TRUE, 63 comments = ISC_TRUE, section_question = ISC_TRUE, 64 section_answer = ISC_TRUE, section_authority = ISC_TRUE, 65 section_additional = ISC_TRUE, recurse = ISC_TRUE, 66 aaonly = ISC_FALSE; 67static isc_boolean_t in_use = ISC_FALSE; 68static char defclass[MXRD] = "IN"; 69static char deftype[MXRD] = "A"; 70static isc_event_t *global_event = NULL; 71 72static char domainopt[DNS_NAME_MAXTEXT]; 73 74static const char *rcodetext[] = { 75 "NOERROR", 76 "FORMERR", 77 "SERVFAIL", 78 "NXDOMAIN", 79 "NOTIMP", 80 "REFUSED", 81 "YXDOMAIN", 82 "YXRRSET", 83 "NXRRSET", 84 "NOTAUTH", 85 "NOTZONE", 86 "RESERVED11", 87 "RESERVED12", 88 "RESERVED13", 89 "RESERVED14", 90 "RESERVED15", 91 "BADVERS" 92}; 93 94static const char *rtypetext[] = { 95 "rtype_0 = ", /* 0 */ 96 "internet address = ", /* 1 */ 97 "nameserver = ", /* 2 */ 98 "md = ", /* 3 */ 99 "mf = ", /* 4 */ 100 "canonical name = ", /* 5 */ 101 "soa = ", /* 6 */ 102 "mb = ", /* 7 */ 103 "mg = ", /* 8 */ 104 "mr = ", /* 9 */ 105 "rtype_10 = ", /* 10 */ 106 "protocol = ", /* 11 */ 107 "name = ", /* 12 */ 108 "hinfo = ", /* 13 */ 109 "minfo = ", /* 14 */ 110 "mail exchanger = ", /* 15 */ 111 "text = ", /* 16 */ 112 "rp = ", /* 17 */ 113 "afsdb = ", /* 18 */ 114 "x25 address = ", /* 19 */ 115 "isdn address = ", /* 20 */ 116 "rt = ", /* 21 */ 117 "nsap = ", /* 22 */ 118 "nsap_ptr = ", /* 23 */ 119 "signature = ", /* 24 */ 120 "key = ", /* 25 */ 121 "px = ", /* 26 */ 122 "gpos = ", /* 27 */ 123 "has AAAA address ", /* 28 */ 124 "loc = ", /* 29 */ 125 "next = ", /* 30 */ 126 "rtype_31 = ", /* 31 */ 127 "rtype_32 = ", /* 32 */ 128 "service = ", /* 33 */ 129 "rtype_34 = ", /* 34 */ 130 "naptr = ", /* 35 */ 131 "kx = ", /* 36 */ 132 "cert = ", /* 37 */ 133 "v6 address = ", /* 38 */ 134 "dname = ", /* 39 */ 135 "rtype_40 = ", /* 40 */ 136 "optional = " /* 41 */ 137}; 138 139#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0])) 140 141static void flush_lookup_list(void); 142static void getinput(isc_task_t *task, isc_event_t *event); 143 144void 145dighost_shutdown(void) { 146 isc_event_t *event = global_event; 147 148 flush_lookup_list(); 149 debug("dighost_shutdown()"); 150 151 if (!in_use) { 152 isc_app_shutdown(); 153 return; 154 } 155 156 isc_task_send(global_task, &event); 157} 158 159static void 160printsoa(dns_rdata_t *rdata) { 161 dns_rdata_soa_t soa; 162 isc_result_t result; 163 char namebuf[DNS_NAME_FORMATSIZE]; 164 165 result = dns_rdata_tostruct(rdata, &soa, NULL); 166 check_result(result, "dns_rdata_tostruct"); 167 168 dns_name_format(&soa.origin, namebuf, sizeof(namebuf)); 169 printf("\torigin = %s\n", namebuf); 170 dns_name_format(&soa.contact, namebuf, sizeof(namebuf)); 171 printf("\tmail addr = %s\n", namebuf); 172 printf("\tserial = %u\n", soa.serial); 173 printf("\trefresh = %u\n", soa.refresh); 174 printf("\tretry = %u\n", soa.retry); 175 printf("\texpire = %u\n", soa.expire); 176 printf("\tminimum = %u\n", soa.minimum); 177 dns_rdata_freestruct(&soa); 178} 179 180static void 181printa(dns_rdata_t *rdata) { 182 isc_result_t result; 183 char text[sizeof("255.255.255.255")]; 184 isc_buffer_t b; 185 186 isc_buffer_init(&b, text, sizeof(text)); 187 result = dns_rdata_totext(rdata, NULL, &b); 188 check_result(result, "dns_rdata_totext"); 189 printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b), 190 (char *)isc_buffer_base(&b)); 191} 192#ifdef DIG_SIGCHASE 193/* Just for compatibility : not use in host program */ 194isc_result_t 195printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, 196 isc_buffer_t *target) 197{ 198 UNUSED(owner_name); 199 UNUSED(rdataset); 200 UNUSED(target); 201 return(ISC_FALSE); 202} 203#endif 204static void 205printrdata(dns_rdata_t *rdata) { 206 isc_result_t result; 207 isc_buffer_t *b = NULL; 208 unsigned int size = 1024; 209 isc_boolean_t done = ISC_FALSE; 210 211 if (rdata->type < N_KNOWN_RRTYPES) 212 printf("%s", rtypetext[rdata->type]); 213 else 214 printf("rdata_%d = ", rdata->type); 215 216 while (!done) { 217 result = isc_buffer_allocate(mctx, &b, size); 218 if (result != ISC_R_SUCCESS) 219 check_result(result, "isc_buffer_allocate"); 220 result = dns_rdata_totext(rdata, NULL, b); 221 if (result == ISC_R_SUCCESS) { 222 printf("%.*s\n", (int)isc_buffer_usedlength(b), 223 (char *)isc_buffer_base(b)); 224 done = ISC_TRUE; 225 } else if (result != ISC_R_NOSPACE) 226 check_result(result, "dns_rdata_totext"); 227 isc_buffer_free(&b); 228 size *= 2; 229 } 230} 231 232static isc_result_t 233printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers, 234 dns_section_t section) { 235 isc_result_t result, loopresult; 236 dns_name_t *name; 237 dns_rdataset_t *rdataset = NULL; 238 dns_rdata_t rdata = DNS_RDATA_INIT; 239 char namebuf[DNS_NAME_FORMATSIZE]; 240 241 UNUSED(query); 242 UNUSED(headers); 243 244 debug("printsection()"); 245 246 result = dns_message_firstname(msg, section); 247 if (result == ISC_R_NOMORE) 248 return (ISC_R_SUCCESS); 249 else if (result != ISC_R_SUCCESS) 250 return (result); 251 for (;;) { 252 name = NULL; 253 dns_message_currentname(msg, section, 254 &name); 255 for (rdataset = ISC_LIST_HEAD(name->list); 256 rdataset != NULL; 257 rdataset = ISC_LIST_NEXT(rdataset, link)) { 258 loopresult = dns_rdataset_first(rdataset); 259 while (loopresult == ISC_R_SUCCESS) { 260 dns_rdataset_current(rdataset, &rdata); 261 switch (rdata.type) { 262 case dns_rdatatype_a: 263 if (section != DNS_SECTION_ANSWER) 264 goto def_short_section; 265 dns_name_format(name, namebuf, 266 sizeof(namebuf)); 267 printf("Name:\t%s\n", namebuf); 268 printa(&rdata); 269 break; 270 case dns_rdatatype_soa: 271 dns_name_format(name, namebuf, 272 sizeof(namebuf)); 273 printf("%s\n", namebuf); 274 printsoa(&rdata); 275 break; 276 default: 277 def_short_section: 278 dns_name_format(name, namebuf, 279 sizeof(namebuf)); 280 printf("%s\t", namebuf); 281 printrdata(&rdata); 282 break; 283 } 284 dns_rdata_reset(&rdata); 285 loopresult = dns_rdataset_next(rdataset); 286 } 287 } 288 result = dns_message_nextname(msg, section); 289 if (result == ISC_R_NOMORE) 290 break; 291 else if (result != ISC_R_SUCCESS) { 292 return (result); 293 } 294 } 295 return (ISC_R_SUCCESS); 296} 297 298static isc_result_t 299detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers, 300 dns_section_t section) { 301 isc_result_t result, loopresult; 302 dns_name_t *name; 303 dns_rdataset_t *rdataset = NULL; 304 dns_rdata_t rdata = DNS_RDATA_INIT; 305 char namebuf[DNS_NAME_FORMATSIZE]; 306 307 UNUSED(query); 308 309 debug("detailsection()"); 310 311 if (headers) { 312 switch (section) { 313 case DNS_SECTION_QUESTION: 314 puts(" QUESTIONS:"); 315 break; 316 case DNS_SECTION_ANSWER: 317 puts(" ANSWERS:"); 318 break; 319 case DNS_SECTION_AUTHORITY: 320 puts(" AUTHORITY RECORDS:"); 321 break; 322 case DNS_SECTION_ADDITIONAL: 323 puts(" ADDITIONAL RECORDS:"); 324 break; 325 } 326 } 327 328 result = dns_message_firstname(msg, section); 329 if (result == ISC_R_NOMORE) 330 return (ISC_R_SUCCESS); 331 else if (result != ISC_R_SUCCESS) 332 return (result); 333 for (;;) { 334 name = NULL; 335 dns_message_currentname(msg, section, 336 &name); 337 for (rdataset = ISC_LIST_HEAD(name->list); 338 rdataset != NULL; 339 rdataset = ISC_LIST_NEXT(rdataset, link)) { 340 if (section == DNS_SECTION_QUESTION) { 341 dns_name_format(name, namebuf, 342 sizeof(namebuf)); 343 printf("\t%s, ", namebuf); 344 dns_rdatatype_format(rdataset->type, 345 namebuf, 346 sizeof(namebuf)); 347 printf("type = %s, ", namebuf); 348 dns_rdataclass_format(rdataset->rdclass, 349 namebuf, 350 sizeof(namebuf)); 351 printf("class = %s\n", namebuf); 352 } 353 loopresult = dns_rdataset_first(rdataset); 354 while (loopresult == ISC_R_SUCCESS) { 355 dns_rdataset_current(rdataset, &rdata); 356 357 dns_name_format(name, namebuf, 358 sizeof(namebuf)); 359 printf(" -> %s\n", namebuf); 360 361 switch (rdata.type) { 362 case dns_rdatatype_soa: 363 printsoa(&rdata); 364 break; 365 default: 366 printf("\t"); 367 printrdata(&rdata); 368 } 369 dns_rdata_reset(&rdata); 370 loopresult = dns_rdataset_next(rdataset); 371 } 372 } 373 result = dns_message_nextname(msg, section); 374 if (result == ISC_R_NOMORE) 375 break; 376 else if (result != ISC_R_SUCCESS) { 377 return (result); 378 } 379 } 380 return (ISC_R_SUCCESS); 381} 382 383void 384received(int bytes, isc_sockaddr_t *from, dig_query_t *query) 385{ 386 UNUSED(bytes); 387 UNUSED(from); 388 UNUSED(query); 389} 390 391void 392trying(char *frm, dig_lookup_t *lookup) { 393 UNUSED(frm); 394 UNUSED(lookup); 395 396} 397 398isc_result_t 399printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { 400 char servtext[ISC_SOCKADDR_FORMATSIZE]; 401 402 debug("printmessage()"); 403 404 isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext)); 405 printf("Server:\t\t%s\n", query->servname); 406 printf("Address:\t%s\n", servtext); 407 408 puts(""); 409 410 if (!short_form) { 411 isc_boolean_t headers = ISC_TRUE; 412 puts("------------"); 413 /* detailheader(query, msg);*/ 414 detailsection(query, msg, headers, DNS_SECTION_QUESTION); 415 detailsection(query, msg, headers, DNS_SECTION_ANSWER); 416 detailsection(query, msg, headers, DNS_SECTION_AUTHORITY); 417 detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL); 418 puts("------------"); 419 } 420 421 if (msg->rcode != 0) { 422 char nametext[DNS_NAME_FORMATSIZE]; 423 dns_name_format(query->lookup->name, 424 nametext, sizeof(nametext)); 425 printf("** server can't find %s: %s\n", nametext, 426 rcodetext[msg->rcode]); 427 debug("returning with rcode == 0"); 428 return (ISC_R_SUCCESS); 429 } 430 431 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) 432 puts("Non-authoritative answer:"); 433 if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) 434 printsection(query, msg, headers, DNS_SECTION_ANSWER); 435 else 436 printf("*** Can't find %s: No answer\n", 437 query->lookup->textname); 438 439 if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) && 440 (query->lookup->rdtype != dns_rdatatype_a)) { 441 puts("\nAuthoritative answers can be found from:"); 442 printsection(query, msg, headers, 443 DNS_SECTION_AUTHORITY); 444 printsection(query, msg, headers, 445 DNS_SECTION_ADDITIONAL); 446 } 447 return (ISC_R_SUCCESS); 448} 449 450static void 451show_settings(isc_boolean_t full, isc_boolean_t serv_only) { 452 dig_server_t *srv; 453 isc_sockaddr_t sockaddr; 454 dig_searchlist_t *listent; 455 456 srv = ISC_LIST_HEAD(server_list); 457 458 while (srv != NULL) { 459 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 460 461 get_address(srv->servername, port, &sockaddr); 462 isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr)); 463 printf("Default server: %s\nAddress: %s\n", 464 srv->servername, sockstr); 465 if (!full) 466 return; 467 srv = ISC_LIST_NEXT(srv, link); 468 } 469 if (serv_only) 470 return; 471 printf("\nSet options:\n"); 472 printf(" %s\t\t\t%s\t\t%s\n", 473 tcpmode ? "vc" : "novc", 474 short_form ? "nodebug" : "debug", 475 debugging ? "d2" : "nod2"); 476 printf(" %s\t\t%s\n", 477 usesearch ? "search" : "nosearch", 478 recurse ? "recurse" : "norecurse"); 479 printf(" timeout = %d\t\tretry = %d\tport = %d\n", 480 timeout, tries, port); 481 printf(" querytype = %-8s\tclass = %s\n", deftype, defclass); 482 printf(" srchlist = "); 483 for (listent = ISC_LIST_HEAD(search_list); 484 listent != NULL; 485 listent = ISC_LIST_NEXT(listent, link)) { 486 printf("%s", listent->origin); 487 if (ISC_LIST_NEXT(listent, link) != NULL) 488 printf("/"); 489 } 490 printf("\n"); 491} 492 493static isc_boolean_t 494testtype(char *typetext) { 495 isc_result_t result; 496 isc_textregion_t tr; 497 dns_rdatatype_t rdtype; 498 499 tr.base = typetext; 500 tr.length = strlen(typetext); 501 result = dns_rdatatype_fromtext(&rdtype, &tr); 502 if (result == ISC_R_SUCCESS) 503 return (ISC_TRUE); 504 else { 505 printf("unknown query type: %s\n", typetext); 506 return (ISC_FALSE); 507 } 508} 509 510static isc_boolean_t 511testclass(char *typetext) { 512 isc_result_t result; 513 isc_textregion_t tr; 514 dns_rdataclass_t rdclass; 515 516 tr.base = typetext; 517 tr.length = strlen(typetext); 518 result = dns_rdataclass_fromtext(&rdclass, &tr); 519 if (result == ISC_R_SUCCESS) 520 return (ISC_TRUE); 521 else { 522 printf("unknown query class: %s\n", typetext); 523 return (ISC_FALSE); 524 } 525} 526 527static void 528safecpy(char *dest, char *src, int size) { 529 strncpy(dest, src, size); 530 dest[size-1] = 0; 531} 532 533static isc_result_t 534parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, 535 const char *desc) { 536 isc_uint32_t n; 537 isc_result_t result = isc_parse_uint32(&n, value, 10); 538 if (result == ISC_R_SUCCESS && n > max) 539 result = ISC_R_RANGE; 540 if (result != ISC_R_SUCCESS) { 541 printf("invalid %s '%s': %s\n", desc, 542 value, isc_result_totext(result)); 543 return result; 544 } 545 *uip = n; 546 return (ISC_R_SUCCESS); 547} 548 549static void 550set_port(const char *value) { 551 isc_uint32_t n; 552 isc_result_t result = parse_uint(&n, value, 65535, "port"); 553 if (result == ISC_R_SUCCESS) 554 port = (isc_uint16_t) n; 555} 556 557static void 558set_timeout(const char *value) { 559 isc_uint32_t n; 560 isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout"); 561 if (result == ISC_R_SUCCESS) 562 timeout = n; 563} 564 565static void 566set_tries(const char *value) { 567 isc_uint32_t n; 568 isc_result_t result = parse_uint(&n, value, INT_MAX, "tries"); 569 if (result == ISC_R_SUCCESS) 570 tries = n; 571} 572 573static void 574setoption(char *opt) { 575 if (strncasecmp(opt, "all", 4) == 0) { 576 show_settings(ISC_TRUE, ISC_FALSE); 577 } else if (strncasecmp(opt, "class=", 6) == 0) { 578 if (testclass(&opt[6])) 579 safecpy(defclass, &opt[6], sizeof(defclass)); 580 } else if (strncasecmp(opt, "cl=", 3) == 0) { 581 if (testclass(&opt[3])) 582 safecpy(defclass, &opt[3], sizeof(defclass)); 583 } else if (strncasecmp(opt, "type=", 5) == 0) { 584 if (testtype(&opt[5])) 585 safecpy(deftype, &opt[5], sizeof(deftype)); 586 } else if (strncasecmp(opt, "ty=", 3) == 0) { 587 if (testtype(&opt[3])) 588 safecpy(deftype, &opt[3], sizeof(deftype)); 589 } else if (strncasecmp(opt, "querytype=", 10) == 0) { 590 if (testtype(&opt[10])) 591 safecpy(deftype, &opt[10], sizeof(deftype)); 592 } else if (strncasecmp(opt, "query=", 6) == 0) { 593 if (testtype(&opt[6])) 594 safecpy(deftype, &opt[6], sizeof(deftype)); 595 } else if (strncasecmp(opt, "qu=", 3) == 0) { 596 if (testtype(&opt[3])) 597 safecpy(deftype, &opt[3], sizeof(deftype)); 598 } else if (strncasecmp(opt, "q=", 2) == 0) { 599 if (testtype(&opt[2])) 600 safecpy(deftype, &opt[2], sizeof(deftype)); 601 } else if (strncasecmp(opt, "domain=", 7) == 0) { 602 safecpy(domainopt, &opt[7], sizeof(domainopt)); 603 set_search_domain(domainopt); 604 usesearch = ISC_TRUE; 605 } else if (strncasecmp(opt, "do=", 3) == 0) { 606 safecpy(domainopt, &opt[3], sizeof(domainopt)); 607 set_search_domain(domainopt); 608 usesearch = ISC_TRUE; 609 } else if (strncasecmp(opt, "port=", 5) == 0) { 610 set_port(&opt[5]); 611 } else if (strncasecmp(opt, "po=", 3) == 0) { 612 set_port(&opt[3]); 613 } else if (strncasecmp(opt, "timeout=", 8) == 0) { 614 set_timeout(&opt[8]); 615 } else if (strncasecmp(opt, "t=", 2) == 0) { 616 set_timeout(&opt[2]); 617 } else if (strncasecmp(opt, "rec", 3) == 0) { 618 recurse = ISC_TRUE; 619 } else if (strncasecmp(opt, "norec", 5) == 0) { 620 recurse = ISC_FALSE; 621 } else if (strncasecmp(opt, "retry=", 6) == 0) { 622 set_tries(&opt[6]); 623 } else if (strncasecmp(opt, "ret=", 4) == 0) { 624 set_tries(&opt[4]); 625 } else if (strncasecmp(opt, "def", 3) == 0) { 626 usesearch = ISC_TRUE; 627 } else if (strncasecmp(opt, "nodef", 5) == 0) { 628 usesearch = ISC_FALSE; 629 } else if (strncasecmp(opt, "vc", 3) == 0) { 630 tcpmode = ISC_TRUE; 631 } else if (strncasecmp(opt, "novc", 5) == 0) { 632 tcpmode = ISC_FALSE; 633 } else if (strncasecmp(opt, "deb", 3) == 0) { 634 short_form = ISC_FALSE; 635 } else if (strncasecmp(opt, "nodeb", 5) == 0) { 636 short_form = ISC_TRUE; 637 } else if (strncasecmp(opt, "d2", 2) == 0) { 638 debugging = ISC_TRUE; 639 } else if (strncasecmp(opt, "nod2", 4) == 0) { 640 debugging = ISC_FALSE; 641 } else if (strncasecmp(opt, "search", 3) == 0) { 642 usesearch = ISC_TRUE; 643 } else if (strncasecmp(opt, "nosearch", 5) == 0) { 644 usesearch = ISC_FALSE; 645 } else if (strncasecmp(opt, "sil", 3) == 0) { 646 /* deprecation_msg = ISC_FALSE; */ 647 } else { 648 printf("*** Invalid option: %s\n", opt); 649 } 650} 651 652static void 653addlookup(char *opt) { 654 dig_lookup_t *lookup; 655 isc_result_t result; 656 isc_textregion_t tr; 657 dns_rdatatype_t rdtype; 658 dns_rdataclass_t rdclass; 659 char store[MXNAME]; 660 661 debug("addlookup()"); 662 tr.base = deftype; 663 tr.length = strlen(deftype); 664 result = dns_rdatatype_fromtext(&rdtype, &tr); 665 if (result != ISC_R_SUCCESS) { 666 printf("unknown query type: %s\n", deftype); 667 rdclass = dns_rdatatype_a; 668 } 669 tr.base = defclass; 670 tr.length = strlen(defclass); 671 result = dns_rdataclass_fromtext(&rdclass, &tr); 672 if (result != ISC_R_SUCCESS) { 673 printf("unknown query class: %s\n", defclass); 674 rdclass = dns_rdataclass_in; 675 } 676 lookup = make_empty_lookup(); 677 if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE) 678 == ISC_R_SUCCESS) { 679 safecpy(lookup->textname, store, sizeof(lookup->textname)); 680 lookup->rdtype = dns_rdatatype_ptr; 681 lookup->rdtypeset = ISC_TRUE; 682 } else { 683 safecpy(lookup->textname, opt, sizeof(lookup->textname)); 684 lookup->rdtype = rdtype; 685 lookup->rdtypeset = ISC_TRUE; 686 } 687 lookup->rdclass = rdclass; 688 lookup->rdclassset = ISC_TRUE; 689 lookup->trace = ISC_FALSE; 690 lookup->trace_root = lookup->trace; 691 lookup->ns_search_only = ISC_FALSE; 692 lookup->identify = identify; 693 lookup->recurse = recurse; 694 lookup->aaonly = aaonly; 695 lookup->retries = tries; 696 lookup->udpsize = 0; 697 lookup->comments = comments; 698 lookup->tcp_mode = tcpmode; 699 lookup->stats = stats; 700 lookup->section_question = section_question; 701 lookup->section_answer = section_answer; 702 lookup->section_authority = section_authority; 703 lookup->section_additional = section_additional; 704 lookup->new_search = ISC_TRUE; 705 ISC_LIST_INIT(lookup->q); 706 ISC_LINK_INIT(lookup, link); 707 ISC_LIST_APPEND(lookup_list, lookup, link); 708 lookup->origin = NULL; 709 ISC_LIST_INIT(lookup->my_server_list); 710 debug("looking up %s", lookup->textname); 711} 712 713static void 714get_next_command(void) { 715 char *buf; 716 char *ptr, *arg; 717 char *input; 718 719 fflush(stdout); 720 buf = isc_mem_allocate(mctx, COMMSIZE); 721 if (buf == NULL) 722 fatal("memory allocation failure"); 723 fputs("> ", stderr); 724 isc_app_block(); 725 ptr = fgets(buf, COMMSIZE, stdin); 726 isc_app_unblock(); 727 if (ptr == NULL) { 728 in_use = ISC_FALSE; 729 goto cleanup; 730 } 731 input = buf; 732 ptr = next_token(&input, " \t\r\n"); 733 if (ptr == NULL) 734 goto cleanup; 735 arg = next_token(&input, " \t\r\n"); 736 if ((strcasecmp(ptr, "set") == 0) && 737 (arg != NULL)) 738 setoption(arg); 739 else if ((strcasecmp(ptr, "server") == 0) || 740 (strcasecmp(ptr, "lserver") == 0)) { 741 set_nameserver(arg); 742 show_settings(ISC_TRUE, ISC_TRUE); 743 } else if (strcasecmp(ptr, "exit") == 0) { 744 in_use = ISC_FALSE; 745 goto cleanup; 746 } else if (strcasecmp(ptr, "help") == 0 || 747 strcasecmp(ptr, "?") == 0) { 748 printf("The '%s' command is not yet implemented.\n", ptr); 749 goto cleanup; 750 } else if (strcasecmp(ptr, "finger") == 0 || 751 strcasecmp(ptr, "root") == 0 || 752 strcasecmp(ptr, "ls") == 0 || 753 strcasecmp(ptr, "view") == 0) { 754 printf("The '%s' command is not implemented.\n", ptr); 755 goto cleanup; 756 } else 757 addlookup(ptr); 758 cleanup: 759 isc_mem_free(mctx, buf); 760} 761 762static void 763parse_args(int argc, char **argv) { 764 isc_boolean_t have_lookup = ISC_FALSE; 765 766 usesearch = ISC_TRUE; 767 for (argc--, argv++; argc > 0; argc--, argv++) { 768 debug("main parsing %s", argv[0]); 769 if (argv[0][0] == '-') { 770 if (argv[0][1] != 0) 771 setoption(&argv[0][1]); 772 else 773 have_lookup = ISC_TRUE; 774 } else { 775 if (!have_lookup) { 776 have_lookup = ISC_TRUE; 777 in_use = ISC_TRUE; 778 addlookup(argv[0]); 779 } 780 else 781 set_nameserver(argv[0]); 782 } 783 } 784} 785 786static void 787flush_lookup_list(void) { 788 dig_lookup_t *l, *lp; 789 dig_query_t *q, *qp; 790 dig_server_t *s, *sp; 791 792 lookup_counter = 0; 793 l = ISC_LIST_HEAD(lookup_list); 794 while (l != NULL) { 795 q = ISC_LIST_HEAD(l->q); 796 while (q != NULL) { 797 if (q->sock != NULL) { 798 isc_socket_cancel(q->sock, NULL, 799 ISC_SOCKCANCEL_ALL); 800 isc_socket_detach(&q->sock); 801 } 802 if (ISC_LINK_LINKED(&q->recvbuf, link)) 803 ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf, 804 link); 805 if (ISC_LINK_LINKED(&q->lengthbuf, link)) 806 ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf, 807 link); 808 isc_buffer_invalidate(&q->recvbuf); 809 isc_buffer_invalidate(&q->lengthbuf); 810 qp = q; 811 q = ISC_LIST_NEXT(q, link); 812 ISC_LIST_DEQUEUE(l->q, qp, link); 813 isc_mem_free(mctx, qp); 814 } 815 s = ISC_LIST_HEAD(l->my_server_list); 816 while (s != NULL) { 817 sp = s; 818 s = ISC_LIST_NEXT(s, link); 819 ISC_LIST_DEQUEUE(l->my_server_list, sp, link); 820 isc_mem_free(mctx, sp); 821 822 } 823 if (l->sendmsg != NULL) 824 dns_message_destroy(&l->sendmsg); 825 if (l->timer != NULL) 826 isc_timer_detach(&l->timer); 827 lp = l; 828 l = ISC_LIST_NEXT(l, link); 829 ISC_LIST_DEQUEUE(lookup_list, lp, link); 830 isc_mem_free(mctx, lp); 831 } 832} 833 834static void 835getinput(isc_task_t *task, isc_event_t *event) { 836 UNUSED(task); 837 if (global_event == NULL) 838 global_event = event; 839 while (in_use) { 840 get_next_command(); 841 if (ISC_LIST_HEAD(lookup_list) != NULL) { 842 start_lookup(); 843 return; 844 } 845 } 846 isc_app_shutdown(); 847} 848 849int 850main(int argc, char **argv) { 851 isc_result_t result; 852 853 ISC_LIST_INIT(lookup_list); 854 ISC_LIST_INIT(server_list); 855 ISC_LIST_INIT(search_list); 856 857 result = isc_app_start(); 858 check_result(result, "isc_app_start"); 859 860 setup_libs(); 861 progname = argv[0]; 862 863 parse_args(argc, argv); 864 865 setup_system(); 866 if (domainopt[0] != '\0') 867 set_search_domain(domainopt); 868 if (in_use) 869 result = isc_app_onrun(mctx, global_task, onrun_callback, 870 NULL); 871 else 872 result = isc_app_onrun(mctx, global_task, getinput, NULL); 873 check_result(result, "isc_app_onrun"); 874 in_use = ISC_TF(!in_use); 875 876 (void)isc_app_run(); 877 878 puts(""); 879 debug("done, and starting to shut down"); 880 if (global_event != NULL) 881 isc_event_free(&global_event); 882 cancel_all(); 883 destroy_libs(); 884 isc_app_finish(); 885 886 return (0); 887} 888