1/* 2 * Copyright (C) 2004-2007, 2009-2013 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: host.c,v 1.127 2011/03/11 06:11:20 marka Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23#include <stdlib.h> 24#include <limits.h> 25 26#ifdef HAVE_LOCALE_H 27#include <locale.h> 28#endif 29 30#ifdef WITH_IDN 31#include <idn/result.h> 32#include <idn/log.h> 33#include <idn/resconf.h> 34#include <idn/api.h> 35#endif 36 37#include <isc/app.h> 38#include <isc/commandline.h> 39#include <isc/netaddr.h> 40#include <isc/print.h> 41#include <isc/string.h> 42#include <isc/util.h> 43#include <isc/task.h> 44#include <isc/stdlib.h> 45 46#include <dns/byaddr.h> 47#include <dns/fixedname.h> 48#include <dns/message.h> 49#include <dns/name.h> 50#include <dns/rdata.h> 51#include <dns/rdataclass.h> 52#include <dns/rdataset.h> 53#include <dns/rdatatype.h> 54#include <dns/rdatastruct.h> 55 56#include <dig/dig.h> 57 58static isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE; 59static isc_boolean_t default_lookups = ISC_TRUE; 60static int seen_error = -1; 61static isc_boolean_t list_addresses = ISC_TRUE; 62static dns_rdatatype_t list_type = dns_rdatatype_a; 63static isc_boolean_t printed_server = ISC_FALSE; 64 65static const char *opcodetext[] = { 66 "QUERY", 67 "IQUERY", 68 "STATUS", 69 "RESERVED3", 70 "NOTIFY", 71 "UPDATE", 72 "RESERVED6", 73 "RESERVED7", 74 "RESERVED8", 75 "RESERVED9", 76 "RESERVED10", 77 "RESERVED11", 78 "RESERVED12", 79 "RESERVED13", 80 "RESERVED14", 81 "RESERVED15" 82}; 83 84static const char *rcodetext[] = { 85 "NOERROR", 86 "FORMERR", 87 "SERVFAIL", 88 "NXDOMAIN", 89 "NOTIMP", 90 "REFUSED", 91 "YXDOMAIN", 92 "YXRRSET", 93 "NXRRSET", 94 "NOTAUTH", 95 "NOTZONE", 96 "RESERVED11", 97 "RESERVED12", 98 "RESERVED13", 99 "RESERVED14", 100 "RESERVED15", 101 "BADVERS" 102}; 103 104struct rtype { 105 unsigned int type; 106 const char *text; 107}; 108 109struct rtype rtypes[] = { 110 { 1, "has address" }, 111 { 2, "name server" }, 112 { 5, "is an alias for" }, 113 { 11, "has well known services" }, 114 { 12, "domain name pointer" }, 115 { 13, "host information" }, 116 { 15, "mail is handled by" }, 117 { 16, "descriptive text" }, 118 { 19, "x25 address" }, 119 { 20, "ISDN address" }, 120 { 24, "has signature" }, 121 { 25, "has key" }, 122 { 28, "has IPv6 address" }, 123 { 29, "location" }, 124 { 0, NULL } 125}; 126 127static char * 128rcode_totext(dns_rcode_t rcode) 129{ 130 static char buf[sizeof("?65535")]; 131 union { 132 const char *consttext; 133 char *deconsttext; 134 } totext; 135 136 if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 137 snprintf(buf, sizeof(buf), "?%u", rcode); 138 totext.deconsttext = buf; 139 } else 140 totext.consttext = rcodetext[rcode]; 141 return totext.deconsttext; 142} 143 144ISC_PLATFORM_NORETURN_PRE static void 145show_usage(void) ISC_PLATFORM_NORETURN_POST; 146 147static void 148show_usage(void) { 149 fputs( 150"Usage: host [-aCdlriTwv] [-c class] [-N ndots] [-t type] [-W time]\n" 151" [-R number] [-m flag] hostname [server]\n" 152" -a is equivalent to -v -t ANY\n" 153" -c specifies query class for non-IN data\n" 154" -C compares SOA records on authoritative nameservers\n" 155" -d is equivalent to -v\n" 156" -l lists all hosts in a domain, using AXFR\n" 157" -i IP6.INT reverse lookups\n" 158" -N changes the number of dots allowed before root lookup is done\n" 159" -r disables recursive processing\n" 160" -R specifies number of retries for UDP packets\n" 161" -s a SERVFAIL response should stop query\n" 162" -t specifies the query type\n" 163" -T enables TCP/IP mode\n" 164" -v enables verbose output\n" 165" -w specifies to wait forever for a reply\n" 166" -W specifies how long to wait for a reply\n" 167" -4 use IPv4 query transport only\n" 168" -6 use IPv6 query transport only\n" 169" -m set memory debugging flag (trace|record|usage)\n", stderr); 170 exit(1); 171} 172 173void 174dighost_shutdown(void) { 175 isc_app_shutdown(); 176} 177 178void 179received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { 180 isc_time_t now; 181 int diff; 182 183 if (!short_form) { 184 char fromtext[ISC_SOCKADDR_FORMATSIZE]; 185 isc_sockaddr_format(from, fromtext, sizeof(fromtext)); 186 TIME_NOW(&now); 187 diff = (int) isc_time_microdiff(&now, &query->time_sent); 188 printf("Received %u bytes from %s in %d ms\n", 189 bytes, fromtext, diff/1000); 190 } 191} 192 193void 194trying(char *frm, dig_lookup_t *lookup) { 195 UNUSED(lookup); 196 197 if (!short_form) 198 printf("Trying \"%s\"\n", frm); 199} 200 201static void 202say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata, 203 dig_query_t *query) 204{ 205 isc_buffer_t *b = NULL; 206 char namestr[DNS_NAME_FORMATSIZE]; 207 isc_region_t r; 208 isc_result_t result; 209 unsigned int bufsize = BUFSIZ; 210 211 dns_name_format(name, namestr, sizeof(namestr)); 212 retry: 213 result = isc_buffer_allocate(mctx, &b, bufsize); 214 check_result(result, "isc_buffer_allocate"); 215 result = dns_rdata_totext(rdata, NULL, b); 216 if (result == ISC_R_NOSPACE) { 217 isc_buffer_free(&b); 218 bufsize *= 2; 219 goto retry; 220 } 221 check_result(result, "dns_rdata_totext"); 222 isc_buffer_usedregion(b, &r); 223 if (query->lookup->identify_previous_line) { 224 printf("Nameserver %s:\n\t", 225 query->servname); 226 } 227 printf("%s %s %.*s", namestr, 228 msg, (int)r.length, (char *)r.base); 229 if (query->lookup->identify) { 230 printf(" on server %s", query->servname); 231 } 232 printf("\n"); 233 isc_buffer_free(&b); 234} 235#ifdef DIG_SIGCHASE 236/* Just for compatibility : not use in host program */ 237isc_result_t 238printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, 239 isc_buffer_t *target) 240{ 241 UNUSED(owner_name); 242 UNUSED(rdataset); 243 UNUSED(target); 244 return(ISC_FALSE); 245} 246#endif 247static isc_result_t 248printsection(dns_message_t *msg, dns_section_t sectionid, 249 const char *section_name, isc_boolean_t headers, 250 dig_query_t *query) 251{ 252 dns_name_t *name, *print_name; 253 dns_rdataset_t *rdataset; 254 dns_rdata_t rdata = DNS_RDATA_INIT; 255 isc_buffer_t target; 256 isc_result_t result, loopresult; 257 isc_region_t r; 258 dns_name_t empty_name; 259 char t[4096]; 260 isc_boolean_t first; 261 isc_boolean_t no_rdata; 262 263 if (sectionid == DNS_SECTION_QUESTION) 264 no_rdata = ISC_TRUE; 265 else 266 no_rdata = ISC_FALSE; 267 268 if (headers) 269 printf(";; %s SECTION:\n", section_name); 270 271 dns_name_init(&empty_name, NULL); 272 273 result = dns_message_firstname(msg, sectionid); 274 if (result == ISC_R_NOMORE) 275 return (ISC_R_SUCCESS); 276 else if (result != ISC_R_SUCCESS) 277 return (result); 278 279 for (;;) { 280 name = NULL; 281 dns_message_currentname(msg, sectionid, &name); 282 283 isc_buffer_init(&target, t, sizeof(t)); 284 first = ISC_TRUE; 285 print_name = name; 286 287 for (rdataset = ISC_LIST_HEAD(name->list); 288 rdataset != NULL; 289 rdataset = ISC_LIST_NEXT(rdataset, link)) { 290 if (query->lookup->rdtype == dns_rdatatype_axfr && 291 !((!list_addresses && 292 (list_type == dns_rdatatype_any || 293 rdataset->type == list_type)) || 294 (list_addresses && 295 (rdataset->type == dns_rdatatype_a || 296 rdataset->type == dns_rdatatype_aaaa || 297 rdataset->type == dns_rdatatype_ns || 298 rdataset->type == dns_rdatatype_ptr)))) 299 continue; 300 if (!short_form) { 301 result = dns_rdataset_totext(rdataset, 302 print_name, 303 ISC_FALSE, 304 no_rdata, 305 &target); 306 if (result != ISC_R_SUCCESS) 307 return (result); 308#ifdef USEINITALWS 309 if (first) { 310 print_name = &empty_name; 311 first = ISC_FALSE; 312 } 313#else 314 UNUSED(first); /* Shut up compiler. */ 315#endif 316 } else { 317 loopresult = dns_rdataset_first(rdataset); 318 while (loopresult == ISC_R_SUCCESS) { 319 struct rtype *t; 320 const char *rtt; 321 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 322 char typebuf2[DNS_RDATATYPE_FORMATSIZE 323 + 20]; 324 dns_rdataset_current(rdataset, &rdata); 325 326 for (t = rtypes; t->text != NULL; t++) { 327 if (t->type == rdata.type) { 328 rtt = t->text; 329 goto found; 330 } 331 } 332 333 dns_rdatatype_format(rdata.type, 334 typebuf, 335 sizeof(typebuf)); 336 snprintf(typebuf2, sizeof(typebuf2), 337 "has %s record", typebuf); 338 rtt = typebuf2; 339 found: 340 say_message(print_name, rtt, 341 &rdata, query); 342 dns_rdata_reset(&rdata); 343 loopresult = 344 dns_rdataset_next(rdataset); 345 } 346 } 347 } 348 if (!short_form) { 349 isc_buffer_usedregion(&target, &r); 350 if (no_rdata) 351 printf(";%.*s", (int)r.length, 352 (char *)r.base); 353 else 354 printf("%.*s", (int)r.length, (char *)r.base); 355 } 356 357 result = dns_message_nextname(msg, sectionid); 358 if (result == ISC_R_NOMORE) 359 break; 360 else if (result != ISC_R_SUCCESS) 361 return (result); 362 } 363 364 return (ISC_R_SUCCESS); 365} 366 367static isc_result_t 368printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner, 369 const char *set_name, isc_boolean_t headers) 370{ 371 isc_buffer_t target; 372 isc_result_t result; 373 isc_region_t r; 374 char t[4096]; 375 376 UNUSED(msg); 377 if (headers) 378 printf(";; %s SECTION:\n", set_name); 379 380 isc_buffer_init(&target, t, sizeof(t)); 381 382 result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, 383 &target); 384 if (result != ISC_R_SUCCESS) 385 return (result); 386 isc_buffer_usedregion(&target, &r); 387 printf("%.*s", (int)r.length, (char *)r.base); 388 389 return (ISC_R_SUCCESS); 390} 391 392static void 393chase_cnamechain(dns_message_t *msg, dns_name_t *qname) { 394 isc_result_t result; 395 dns_rdataset_t *rdataset; 396 dns_rdata_cname_t cname; 397 dns_rdata_t rdata = DNS_RDATA_INIT; 398 unsigned int i = msg->counts[DNS_SECTION_ANSWER]; 399 400 while (i-- > 0) { 401 rdataset = NULL; 402 result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname, 403 dns_rdatatype_cname, 0, NULL, 404 &rdataset); 405 if (result != ISC_R_SUCCESS) 406 return; 407 result = dns_rdataset_first(rdataset); 408 check_result(result, "dns_rdataset_first"); 409 dns_rdata_reset(&rdata); 410 dns_rdataset_current(rdataset, &rdata); 411 result = dns_rdata_tostruct(&rdata, &cname, NULL); 412 check_result(result, "dns_rdata_tostruct"); 413 dns_name_copy(&cname.cname, qname, NULL); 414 dns_rdata_freestruct(&cname); 415 } 416} 417 418isc_result_t 419printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { 420 isc_boolean_t did_flag = ISC_FALSE; 421 dns_rdataset_t *opt, *tsig = NULL; 422 dns_name_t *tsigname; 423 isc_result_t result = ISC_R_SUCCESS; 424 int force_error; 425 426 UNUSED(headers); 427 428 /* 429 * We get called multiple times. 430 * Preserve any existing error status. 431 */ 432 force_error = (seen_error == 1) ? 1 : 0; 433 seen_error = 1; 434 if (listed_server && !printed_server) { 435 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 436 437 printf("Using domain server:\n"); 438 printf("Name: %s\n", query->userarg); 439 isc_sockaddr_format(&query->sockaddr, sockstr, 440 sizeof(sockstr)); 441 printf("Address: %s\n", sockstr); 442 printf("Aliases: \n\n"); 443 printed_server = ISC_TRUE; 444 } 445 446 if (msg->rcode != 0) { 447 char namestr[DNS_NAME_FORMATSIZE]; 448 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 449 450 if (query->lookup->identify_previous_line) 451 printf("Nameserver %s:\n\t%s not found: %d(%s)\n", 452 query->servname, 453 (msg->rcode != dns_rcode_nxdomain) ? namestr : 454 query->lookup->textname, msg->rcode, 455 rcode_totext(msg->rcode)); 456 else 457 printf("Host %s not found: %d(%s)\n", 458 (msg->rcode != dns_rcode_nxdomain) ? namestr : 459 query->lookup->textname, msg->rcode, 460 rcode_totext(msg->rcode)); 461 return (ISC_R_SUCCESS); 462 } 463 464 if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) { 465 char namestr[DNS_NAME_FORMATSIZE]; 466 dig_lookup_t *lookup; 467 dns_fixedname_t fixed; 468 dns_name_t *name; 469 470 /* Add AAAA and MX lookups. */ 471 dns_fixedname_init(&fixed); 472 name = dns_fixedname_name(&fixed); 473 dns_name_copy(query->lookup->name, name, NULL); 474 chase_cnamechain(msg, name); 475 dns_name_format(name, namestr, sizeof(namestr)); 476 lookup = clone_lookup(query->lookup, ISC_FALSE); 477 if (lookup != NULL) { 478 strncpy(lookup->textname, namestr, 479 sizeof(lookup->textname)); 480 lookup->textname[sizeof(lookup->textname)-1] = 0; 481 lookup->rdtype = dns_rdatatype_aaaa; 482 lookup->rdtypeset = ISC_TRUE; 483 lookup->origin = NULL; 484 lookup->retries = tries; 485 ISC_LIST_APPEND(lookup_list, lookup, link); 486 } 487 lookup = clone_lookup(query->lookup, ISC_FALSE); 488 if (lookup != NULL) { 489 strncpy(lookup->textname, namestr, 490 sizeof(lookup->textname)); 491 lookup->textname[sizeof(lookup->textname)-1] = 0; 492 lookup->rdtype = dns_rdatatype_mx; 493 lookup->rdtypeset = ISC_TRUE; 494 lookup->origin = NULL; 495 lookup->retries = tries; 496 ISC_LIST_APPEND(lookup_list, lookup, link); 497 } 498 } 499 500 if (!short_form) { 501 printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n", 502 opcodetext[msg->opcode], rcode_totext(msg->rcode), 503 msg->id); 504 printf(";; flags: "); 505 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { 506 printf("qr"); 507 did_flag = ISC_TRUE; 508 } 509 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { 510 printf("%saa", did_flag ? " " : ""); 511 did_flag = ISC_TRUE; 512 } 513 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { 514 printf("%stc", did_flag ? " " : ""); 515 did_flag = ISC_TRUE; 516 } 517 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { 518 printf("%srd", did_flag ? " " : ""); 519 did_flag = ISC_TRUE; 520 } 521 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { 522 printf("%sra", did_flag ? " " : ""); 523 did_flag = ISC_TRUE; 524 } 525 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { 526 printf("%sad", did_flag ? " " : ""); 527 did_flag = ISC_TRUE; 528 } 529 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { 530 printf("%scd", did_flag ? " " : ""); 531 did_flag = ISC_TRUE; 532 POST(did_flag); 533 } 534 printf("; QUERY: %u, ANSWER: %u, " 535 "AUTHORITY: %u, ADDITIONAL: %u\n", 536 msg->counts[DNS_SECTION_QUESTION], 537 msg->counts[DNS_SECTION_ANSWER], 538 msg->counts[DNS_SECTION_AUTHORITY], 539 msg->counts[DNS_SECTION_ADDITIONAL]); 540 opt = dns_message_getopt(msg); 541 if (opt != NULL) 542 printf(";; EDNS: version: %u, udp=%u\n", 543 (unsigned int)((opt->ttl & 0x00ff0000) >> 16), 544 (unsigned int)opt->rdclass); 545 tsigname = NULL; 546 tsig = dns_message_gettsig(msg, &tsigname); 547 if (tsig != NULL) 548 printf(";; PSEUDOSECTIONS: TSIG\n"); 549 } 550 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && 551 !short_form) { 552 printf("\n"); 553 result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", 554 ISC_TRUE, query); 555 if (result != ISC_R_SUCCESS) 556 return (result); 557 } 558 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 559 if (!short_form) 560 printf("\n"); 561 result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", 562 ISC_TF(!short_form), query); 563 if (result != ISC_R_SUCCESS) 564 return (result); 565 } 566 567 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && 568 !short_form) { 569 printf("\n"); 570 result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", 571 ISC_TRUE, query); 572 if (result != ISC_R_SUCCESS) 573 return (result); 574 } 575 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && 576 !short_form) { 577 printf("\n"); 578 result = printsection(msg, DNS_SECTION_ADDITIONAL, 579 "ADDITIONAL", ISC_TRUE, query); 580 if (result != ISC_R_SUCCESS) 581 return (result); 582 } 583 if ((tsig != NULL) && !short_form) { 584 printf("\n"); 585 result = printrdata(msg, tsig, tsigname, 586 "PSEUDOSECTION TSIG", ISC_TRUE); 587 if (result != ISC_R_SUCCESS) 588 return (result); 589 } 590 if (!short_form) 591 printf("\n"); 592 593 if (short_form && !default_lookups && 594 ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 595 char namestr[DNS_NAME_FORMATSIZE]; 596 char typestr[DNS_RDATATYPE_FORMATSIZE]; 597 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 598 dns_rdatatype_format(query->lookup->rdtype, typestr, 599 sizeof(typestr)); 600 printf("%s has no %s record\n", namestr, typestr); 601 } 602 seen_error = force_error; 603 return (result); 604} 605 606static const char * optstring = "46ac:dilnm:rst:vwCDN:R:TW:"; 607 608static void 609pre_parse_args(int argc, char **argv) { 610 int c; 611 612 while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { 613 switch (c) { 614 case 'm': 615 memdebugging = ISC_TRUE; 616 if (strcasecmp("trace", isc_commandline_argument) == 0) 617 isc_mem_debugging |= ISC_MEM_DEBUGTRACE; 618 else if (!strcasecmp("record", 619 isc_commandline_argument) == 0) 620 isc_mem_debugging |= ISC_MEM_DEBUGRECORD; 621 else if (strcasecmp("usage", 622 isc_commandline_argument) == 0) 623 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; 624 break; 625 626 case '4': break; 627 case '6': break; 628 case 'a': break; 629 case 'c': break; 630 case 'd': break; 631 case 'i': break; 632 case 'l': break; 633 case 'n': break; 634 case 'r': break; 635 case 's': break; 636 case 't': break; 637 case 'v': break; 638 case 'w': break; 639 case 'C': break; 640 case 'D': 641 if (debugging) 642 debugtiming = ISC_TRUE; 643 debugging = ISC_TRUE; 644 break; 645 case 'N': break; 646 case 'R': break; 647 case 'T': break; 648 case 'W': break; 649 default: 650 show_usage(); 651 } 652 } 653 isc_commandline_reset = ISC_TRUE; 654 isc_commandline_index = 1; 655} 656 657static void 658parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { 659 char hostname[MXNAME]; 660 dig_lookup_t *lookup; 661 int c; 662 char store[MXNAME]; 663 isc_textregion_t tr; 664 isc_result_t result = ISC_R_SUCCESS; 665 dns_rdatatype_t rdtype; 666 dns_rdataclass_t rdclass; 667 isc_uint32_t serial = 0; 668 669 UNUSED(is_batchfile); 670 671 lookup = make_empty_lookup(); 672 673 lookup->servfail_stops = ISC_FALSE; 674 lookup->comments = ISC_FALSE; 675 676 while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { 677 switch (c) { 678 case 'l': 679 lookup->tcp_mode = ISC_TRUE; 680 lookup->rdtype = dns_rdatatype_axfr; 681 lookup->rdtypeset = ISC_TRUE; 682 fatalexit = 3; 683 break; 684 case 'v': 685 case 'd': 686 short_form = ISC_FALSE; 687 break; 688 case 'r': 689 lookup->recurse = ISC_FALSE; 690 break; 691 case 't': 692 if (strncasecmp(isc_commandline_argument, 693 "ixfr=", 5) == 0) { 694 rdtype = dns_rdatatype_ixfr; 695 /* XXXMPA add error checking */ 696 serial = strtoul(isc_commandline_argument + 5, 697 NULL, 10); 698 result = ISC_R_SUCCESS; 699 } else { 700 tr.base = isc_commandline_argument; 701 tr.length = strlen(isc_commandline_argument); 702 result = dns_rdatatype_fromtext(&rdtype, 703 (isc_textregion_t *)&tr); 704 } 705 706 if (result != ISC_R_SUCCESS) { 707 fatalexit = 2; 708 fatal("invalid type: %s\n", 709 isc_commandline_argument); 710 } 711 if (!lookup->rdtypeset || 712 lookup->rdtype != dns_rdatatype_axfr) 713 lookup->rdtype = rdtype; 714 lookup->rdtypeset = ISC_TRUE; 715#ifdef WITH_IDN 716 idnoptions = 0; 717#endif 718 if (rdtype == dns_rdatatype_axfr) { 719 /* -l -t any -v */ 720 list_type = dns_rdatatype_any; 721 short_form = ISC_FALSE; 722 lookup->tcp_mode = ISC_TRUE; 723 } else if (rdtype == dns_rdatatype_ixfr) { 724 lookup->ixfr_serial = serial; 725 lookup->tcp_mode = ISC_TRUE; 726 list_type = rdtype; 727#ifdef WITH_IDN 728 } else if (rdtype == dns_rdatatype_a || 729 rdtype == dns_rdatatype_aaaa || 730 rdtype == dns_rdatatype_mx) { 731 idnoptions = IDN_ASCCHECK; 732 list_type = rdtype; 733#endif 734 } else 735 list_type = rdtype; 736 list_addresses = ISC_FALSE; 737 default_lookups = ISC_FALSE; 738 break; 739 case 'c': 740 tr.base = isc_commandline_argument; 741 tr.length = strlen(isc_commandline_argument); 742 result = dns_rdataclass_fromtext(&rdclass, 743 (isc_textregion_t *)&tr); 744 745 if (result != ISC_R_SUCCESS) { 746 fatalexit = 2; 747 fatal("invalid class: %s\n", 748 isc_commandline_argument); 749 } else { 750 lookup->rdclass = rdclass; 751 lookup->rdclassset = ISC_TRUE; 752 } 753 default_lookups = ISC_FALSE; 754 break; 755 case 'a': 756 if (!lookup->rdtypeset || 757 lookup->rdtype != dns_rdatatype_axfr) 758 lookup->rdtype = dns_rdatatype_any; 759 list_type = dns_rdatatype_any; 760 list_addresses = ISC_FALSE; 761 lookup->rdtypeset = ISC_TRUE; 762 short_form = ISC_FALSE; 763 default_lookups = ISC_FALSE; 764 break; 765 case 'i': 766 lookup->ip6_int = ISC_TRUE; 767 break; 768 case 'n': 769 /* deprecated */ 770 break; 771 case 'm': 772 /* Handled by pre_parse_args(). */ 773 break; 774 case 'w': 775 /* 776 * The timer routines are coded such that 777 * timeout==MAXINT doesn't enable the timer 778 */ 779 timeout = INT_MAX; 780 break; 781 case 'W': 782 timeout = atoi(isc_commandline_argument); 783 if (timeout < 1) 784 timeout = 1; 785 break; 786 case 'R': 787 tries = atoi(isc_commandline_argument) + 1; 788 if (tries < 2) 789 tries = 2; 790 break; 791 case 'T': 792 lookup->tcp_mode = ISC_TRUE; 793 break; 794 case 'C': 795 debug("showing all SOAs"); 796 lookup->rdtype = dns_rdatatype_ns; 797 lookup->rdtypeset = ISC_TRUE; 798 lookup->rdclass = dns_rdataclass_in; 799 lookup->rdclassset = ISC_TRUE; 800 lookup->ns_search_only = ISC_TRUE; 801 lookup->trace_root = ISC_TRUE; 802 lookup->identify_previous_line = ISC_TRUE; 803 default_lookups = ISC_FALSE; 804 break; 805 case 'N': 806 debug("setting NDOTS to %s", 807 isc_commandline_argument); 808 ndots = atoi(isc_commandline_argument); 809 break; 810 case 'D': 811 /* Handled by pre_parse_args(). */ 812 break; 813 case '4': 814 if (have_ipv4) { 815 isc_net_disableipv6(); 816 have_ipv6 = ISC_FALSE; 817 } else 818 fatal("can't find IPv4 networking"); 819 break; 820 case '6': 821 if (have_ipv6) { 822 isc_net_disableipv4(); 823 have_ipv4 = ISC_FALSE; 824 } else 825 fatal("can't find IPv6 networking"); 826 break; 827 case 's': 828 lookup->servfail_stops = ISC_TRUE; 829 break; 830 } 831 } 832 833 lookup->retries = tries; 834 835 if (isc_commandline_index >= argc) 836 show_usage(); 837 838 strlcpy(hostname, argv[isc_commandline_index], sizeof(hostname)); 839 840 if (argc > isc_commandline_index + 1) { 841 set_nameserver(argv[isc_commandline_index+1]); 842 debug("server is %s", argv[isc_commandline_index+1]); 843 listed_server = ISC_TRUE; 844 } else 845 check_ra = ISC_TRUE; 846 847 lookup->pending = ISC_FALSE; 848 if (get_reverse(store, sizeof(store), hostname, 849 lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) { 850 strncpy(lookup->textname, store, sizeof(lookup->textname)); 851 lookup->textname[sizeof(lookup->textname)-1] = 0; 852 lookup->rdtype = dns_rdatatype_ptr; 853 lookup->rdtypeset = ISC_TRUE; 854 default_lookups = ISC_FALSE; 855 } else { 856 strncpy(lookup->textname, hostname, sizeof(lookup->textname)); 857 lookup->textname[sizeof(lookup->textname)-1]=0; 858 usesearch = ISC_TRUE; 859 } 860 lookup->new_search = ISC_TRUE; 861 ISC_LIST_APPEND(lookup_list, lookup, link); 862} 863 864int 865main(int argc, char **argv) { 866 isc_result_t result; 867 868 tries = 2; 869 870 ISC_LIST_INIT(lookup_list); 871 ISC_LIST_INIT(server_list); 872 ISC_LIST_INIT(search_list); 873 874 fatalexit = 1; 875#ifdef WITH_IDN 876 idnoptions = IDN_ASCCHECK; 877#endif 878 879 debug("main()"); 880 progname = argv[0]; 881 pre_parse_args(argc, argv); 882 result = isc_app_start(); 883 check_result(result, "isc_app_start"); 884 setup_libs(); 885 parse_args(ISC_FALSE, argc, argv); 886 setup_system(); 887 result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); 888 check_result(result, "isc_app_onrun"); 889 isc_app_run(); 890 cancel_all(); 891 destroy_libs(); 892 isc_app_finish(); 893 return ((seen_error == 0) ? 0 : 1); 894} 895