host.c revision 225361
1/* 2 * Copyright (C) 2004-2007, 2009-2011 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.124.40.3 2011-03-11 06:46:59 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 printf("Host %s not found: %d(%s)\n", 450 (msg->rcode != dns_rcode_nxdomain) ? namestr : 451 query->lookup->textname, msg->rcode, 452 rcode_totext(msg->rcode)); 453 return (ISC_R_SUCCESS); 454 } 455 456 if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) { 457 char namestr[DNS_NAME_FORMATSIZE]; 458 dig_lookup_t *lookup; 459 dns_fixedname_t fixed; 460 dns_name_t *name; 461 462 /* Add AAAA and MX lookups. */ 463 dns_fixedname_init(&fixed); 464 name = dns_fixedname_name(&fixed); 465 dns_name_copy(query->lookup->name, name, NULL); 466 chase_cnamechain(msg, name); 467 dns_name_format(name, namestr, sizeof(namestr)); 468 lookup = clone_lookup(query->lookup, ISC_FALSE); 469 if (lookup != NULL) { 470 strncpy(lookup->textname, namestr, 471 sizeof(lookup->textname)); 472 lookup->textname[sizeof(lookup->textname)-1] = 0; 473 lookup->rdtype = dns_rdatatype_aaaa; 474 lookup->rdtypeset = ISC_TRUE; 475 lookup->origin = NULL; 476 lookup->retries = tries; 477 ISC_LIST_APPEND(lookup_list, lookup, link); 478 } 479 lookup = clone_lookup(query->lookup, ISC_FALSE); 480 if (lookup != NULL) { 481 strncpy(lookup->textname, namestr, 482 sizeof(lookup->textname)); 483 lookup->textname[sizeof(lookup->textname)-1] = 0; 484 lookup->rdtype = dns_rdatatype_mx; 485 lookup->rdtypeset = ISC_TRUE; 486 lookup->origin = NULL; 487 lookup->retries = tries; 488 ISC_LIST_APPEND(lookup_list, lookup, link); 489 } 490 } 491 492 if (!short_form) { 493 printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n", 494 opcodetext[msg->opcode], rcode_totext(msg->rcode), 495 msg->id); 496 printf(";; flags: "); 497 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { 498 printf("qr"); 499 did_flag = ISC_TRUE; 500 } 501 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { 502 printf("%saa", did_flag ? " " : ""); 503 did_flag = ISC_TRUE; 504 } 505 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { 506 printf("%stc", did_flag ? " " : ""); 507 did_flag = ISC_TRUE; 508 } 509 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { 510 printf("%srd", did_flag ? " " : ""); 511 did_flag = ISC_TRUE; 512 } 513 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { 514 printf("%sra", did_flag ? " " : ""); 515 did_flag = ISC_TRUE; 516 } 517 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { 518 printf("%sad", did_flag ? " " : ""); 519 did_flag = ISC_TRUE; 520 } 521 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { 522 printf("%scd", did_flag ? " " : ""); 523 did_flag = ISC_TRUE; 524 POST(did_flag); 525 } 526 printf("; QUERY: %u, ANSWER: %u, " 527 "AUTHORITY: %u, ADDITIONAL: %u\n", 528 msg->counts[DNS_SECTION_QUESTION], 529 msg->counts[DNS_SECTION_ANSWER], 530 msg->counts[DNS_SECTION_AUTHORITY], 531 msg->counts[DNS_SECTION_ADDITIONAL]); 532 opt = dns_message_getopt(msg); 533 if (opt != NULL) 534 printf(";; EDNS: version: %u, udp=%u\n", 535 (unsigned int)((opt->ttl & 0x00ff0000) >> 16), 536 (unsigned int)opt->rdclass); 537 tsigname = NULL; 538 tsig = dns_message_gettsig(msg, &tsigname); 539 if (tsig != NULL) 540 printf(";; PSEUDOSECTIONS: TSIG\n"); 541 } 542 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && 543 !short_form) { 544 printf("\n"); 545 result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", 546 ISC_TRUE, query); 547 if (result != ISC_R_SUCCESS) 548 return (result); 549 } 550 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 551 if (!short_form) 552 printf("\n"); 553 result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", 554 ISC_TF(!short_form), query); 555 if (result != ISC_R_SUCCESS) 556 return (result); 557 } 558 559 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && 560 !short_form) { 561 printf("\n"); 562 result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", 563 ISC_TRUE, query); 564 if (result != ISC_R_SUCCESS) 565 return (result); 566 } 567 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && 568 !short_form) { 569 printf("\n"); 570 result = printsection(msg, DNS_SECTION_ADDITIONAL, 571 "ADDITIONAL", ISC_TRUE, query); 572 if (result != ISC_R_SUCCESS) 573 return (result); 574 } 575 if ((tsig != NULL) && !short_form) { 576 printf("\n"); 577 result = printrdata(msg, tsig, tsigname, 578 "PSEUDOSECTION TSIG", ISC_TRUE); 579 if (result != ISC_R_SUCCESS) 580 return (result); 581 } 582 if (!short_form) 583 printf("\n"); 584 585 if (short_form && !default_lookups && 586 ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 587 char namestr[DNS_NAME_FORMATSIZE]; 588 char typestr[DNS_RDATATYPE_FORMATSIZE]; 589 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 590 dns_rdatatype_format(query->lookup->rdtype, typestr, 591 sizeof(typestr)); 592 printf("%s has no %s record\n", namestr, typestr); 593 } 594 seen_error = force_error; 595 return (result); 596} 597 598static const char * optstring = "46ac:dilnm:rst:vwCDN:R:TW:"; 599 600static void 601pre_parse_args(int argc, char **argv) { 602 int c; 603 604 while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { 605 switch (c) { 606 case 'm': 607 memdebugging = ISC_TRUE; 608 if (strcasecmp("trace", isc_commandline_argument) == 0) 609 isc_mem_debugging |= ISC_MEM_DEBUGTRACE; 610 else if (!strcasecmp("record", 611 isc_commandline_argument) == 0) 612 isc_mem_debugging |= ISC_MEM_DEBUGRECORD; 613 else if (strcasecmp("usage", 614 isc_commandline_argument) == 0) 615 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; 616 break; 617 618 case '4': break; 619 case '6': break; 620 case 'a': break; 621 case 'c': break; 622 case 'd': break; 623 case 'i': break; 624 case 'l': break; 625 case 'n': break; 626 case 'r': break; 627 case 's': break; 628 case 't': break; 629 case 'v': break; 630 case 'w': break; 631 case 'C': break; 632 case 'D': 633 debugging = ISC_TRUE; 634 break; 635 case 'N': break; 636 case 'R': break; 637 case 'T': break; 638 case 'W': break; 639 default: 640 show_usage(); 641 } 642 } 643 isc_commandline_reset = ISC_TRUE; 644 isc_commandline_index = 1; 645} 646 647static void 648parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { 649 char hostname[MXNAME]; 650 dig_lookup_t *lookup; 651 int c; 652 char store[MXNAME]; 653 isc_textregion_t tr; 654 isc_result_t result = ISC_R_SUCCESS; 655 dns_rdatatype_t rdtype; 656 dns_rdataclass_t rdclass; 657 isc_uint32_t serial = 0; 658 659 UNUSED(is_batchfile); 660 661 lookup = make_empty_lookup(); 662 663 lookup->servfail_stops = ISC_FALSE; 664 lookup->comments = ISC_FALSE; 665 666 while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { 667 switch (c) { 668 case 'l': 669 lookup->tcp_mode = ISC_TRUE; 670 lookup->rdtype = dns_rdatatype_axfr; 671 lookup->rdtypeset = ISC_TRUE; 672 fatalexit = 3; 673 break; 674 case 'v': 675 case 'd': 676 short_form = ISC_FALSE; 677 break; 678 case 'r': 679 lookup->recurse = ISC_FALSE; 680 break; 681 case 't': 682 if (strncasecmp(isc_commandline_argument, 683 "ixfr=", 5) == 0) { 684 rdtype = dns_rdatatype_ixfr; 685 /* XXXMPA add error checking */ 686 serial = strtoul(isc_commandline_argument + 5, 687 NULL, 10); 688 result = ISC_R_SUCCESS; 689 } else { 690 tr.base = isc_commandline_argument; 691 tr.length = strlen(isc_commandline_argument); 692 result = dns_rdatatype_fromtext(&rdtype, 693 (isc_textregion_t *)&tr); 694 } 695 696 if (result != ISC_R_SUCCESS) { 697 fatalexit = 2; 698 fatal("invalid type: %s\n", 699 isc_commandline_argument); 700 } 701 if (!lookup->rdtypeset || 702 lookup->rdtype != dns_rdatatype_axfr) 703 lookup->rdtype = rdtype; 704 lookup->rdtypeset = ISC_TRUE; 705#ifdef WITH_IDN 706 idnoptions = 0; 707#endif 708 if (rdtype == dns_rdatatype_axfr) { 709 /* -l -t any -v */ 710 list_type = dns_rdatatype_any; 711 short_form = ISC_FALSE; 712 lookup->tcp_mode = ISC_TRUE; 713 } else if (rdtype == dns_rdatatype_ixfr) { 714 lookup->ixfr_serial = serial; 715 lookup->tcp_mode = ISC_TRUE; 716 list_type = rdtype; 717#ifdef WITH_IDN 718 } else if (rdtype == dns_rdatatype_a || 719 rdtype == dns_rdatatype_aaaa || 720 rdtype == dns_rdatatype_mx) { 721 idnoptions = IDN_ASCCHECK; 722 list_type = rdtype; 723#endif 724 } else 725 list_type = rdtype; 726 list_addresses = ISC_FALSE; 727 default_lookups = ISC_FALSE; 728 break; 729 case 'c': 730 tr.base = isc_commandline_argument; 731 tr.length = strlen(isc_commandline_argument); 732 result = dns_rdataclass_fromtext(&rdclass, 733 (isc_textregion_t *)&tr); 734 735 if (result != ISC_R_SUCCESS) { 736 fatalexit = 2; 737 fatal("invalid class: %s\n", 738 isc_commandline_argument); 739 } else { 740 lookup->rdclass = rdclass; 741 lookup->rdclassset = ISC_TRUE; 742 } 743 default_lookups = ISC_FALSE; 744 break; 745 case 'a': 746 if (!lookup->rdtypeset || 747 lookup->rdtype != dns_rdatatype_axfr) 748 lookup->rdtype = dns_rdatatype_any; 749 list_type = dns_rdatatype_any; 750 list_addresses = ISC_FALSE; 751 lookup->rdtypeset = ISC_TRUE; 752 short_form = ISC_FALSE; 753 default_lookups = ISC_FALSE; 754 break; 755 case 'i': 756 lookup->ip6_int = ISC_TRUE; 757 break; 758 case 'n': 759 /* deprecated */ 760 break; 761 case 'm': 762 /* Handled by pre_parse_args(). */ 763 break; 764 case 'w': 765 /* 766 * The timer routines are coded such that 767 * timeout==MAXINT doesn't enable the timer 768 */ 769 timeout = INT_MAX; 770 break; 771 case 'W': 772 timeout = atoi(isc_commandline_argument); 773 if (timeout < 1) 774 timeout = 1; 775 break; 776 case 'R': 777 tries = atoi(isc_commandline_argument) + 1; 778 if (tries < 2) 779 tries = 2; 780 break; 781 case 'T': 782 lookup->tcp_mode = ISC_TRUE; 783 break; 784 case 'C': 785 debug("showing all SOAs"); 786 lookup->rdtype = dns_rdatatype_ns; 787 lookup->rdtypeset = ISC_TRUE; 788 lookup->rdclass = dns_rdataclass_in; 789 lookup->rdclassset = ISC_TRUE; 790 lookup->ns_search_only = ISC_TRUE; 791 lookup->trace_root = ISC_TRUE; 792 lookup->identify_previous_line = ISC_TRUE; 793 default_lookups = ISC_FALSE; 794 break; 795 case 'N': 796 debug("setting NDOTS to %s", 797 isc_commandline_argument); 798 ndots = atoi(isc_commandline_argument); 799 break; 800 case 'D': 801 /* Handled by pre_parse_args(). */ 802 break; 803 case '4': 804 if (have_ipv4) { 805 isc_net_disableipv6(); 806 have_ipv6 = ISC_FALSE; 807 } else 808 fatal("can't find IPv4 networking"); 809 break; 810 case '6': 811 if (have_ipv6) { 812 isc_net_disableipv4(); 813 have_ipv4 = ISC_FALSE; 814 } else 815 fatal("can't find IPv6 networking"); 816 break; 817 case 's': 818 lookup->servfail_stops = ISC_TRUE; 819 break; 820 } 821 } 822 823 lookup->retries = tries; 824 825 if (isc_commandline_index >= argc) 826 show_usage(); 827 828 strlcpy(hostname, argv[isc_commandline_index], sizeof(hostname)); 829 830 if (argc > isc_commandline_index + 1) { 831 set_nameserver(argv[isc_commandline_index+1]); 832 debug("server is %s", argv[isc_commandline_index+1]); 833 listed_server = ISC_TRUE; 834 } else 835 check_ra = ISC_TRUE; 836 837 lookup->pending = ISC_FALSE; 838 if (get_reverse(store, sizeof(store), hostname, 839 lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) { 840 strncpy(lookup->textname, store, sizeof(lookup->textname)); 841 lookup->textname[sizeof(lookup->textname)-1] = 0; 842 lookup->rdtype = dns_rdatatype_ptr; 843 lookup->rdtypeset = ISC_TRUE; 844 default_lookups = ISC_FALSE; 845 } else { 846 strncpy(lookup->textname, hostname, sizeof(lookup->textname)); 847 lookup->textname[sizeof(lookup->textname)-1]=0; 848 usesearch = ISC_TRUE; 849 } 850 lookup->new_search = ISC_TRUE; 851 ISC_LIST_APPEND(lookup_list, lookup, link); 852} 853 854int 855main(int argc, char **argv) { 856 isc_result_t result; 857 858 tries = 2; 859 860 ISC_LIST_INIT(lookup_list); 861 ISC_LIST_INIT(server_list); 862 ISC_LIST_INIT(search_list); 863 864 fatalexit = 1; 865#ifdef WITH_IDN 866 idnoptions = IDN_ASCCHECK; 867#endif 868 869 debug("main()"); 870 progname = argv[0]; 871 pre_parse_args(argc, argv); 872 result = isc_app_start(); 873 check_result(result, "isc_app_start"); 874 setup_libs(); 875 parse_args(ISC_FALSE, argc, argv); 876 setup_system(); 877 result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); 878 check_result(result, "isc_app_onrun"); 879 isc_app_run(); 880 cancel_all(); 881 destroy_libs(); 882 isc_app_finish(); 883 return ((seen_error == 0) ? 0 : 1); 884} 885