host.c revision 174187
1/* 2 * Copyright (C) 2004-2007 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.94.18.19 2007/08/28 07:19:55 tbox 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 void 128show_usage(void) { 129 fputs( 130"Usage: host [-aCdlriTwv] [-c class] [-N ndots] [-t type] [-W time]\n" 131" [-R number] [-m flag] hostname [server]\n" 132" -a is equivalent to -v -t ANY\n" 133" -c specifies query class for non-IN data\n" 134" -C compares SOA records on authoritative nameservers\n" 135" -d is equivalent to -v\n" 136" -l lists all hosts in a domain, using AXFR\n" 137" -i IP6.INT reverse lookups\n" 138" -N changes the number of dots allowed before root lookup is done\n" 139" -r disables recursive processing\n" 140" -R specifies number of retries for UDP packets\n" 141" -s a SERVFAIL response should stop query\n" 142" -t specifies the query type\n" 143" -T enables TCP/IP mode\n" 144" -v enables verbose output\n" 145" -w specifies to wait forever for a reply\n" 146" -W specifies how long to wait for a reply\n" 147" -4 use IPv4 query transport only\n" 148" -6 use IPv6 query transport only\n" 149" -m set memory debugging flag (trace|record|usage)\n", stderr); 150 exit(1); 151} 152 153void 154dighost_shutdown(void) { 155 isc_app_shutdown(); 156} 157 158void 159received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { 160 isc_time_t now; 161 int diff; 162 163 if (!short_form) { 164 char fromtext[ISC_SOCKADDR_FORMATSIZE]; 165 isc_sockaddr_format(from, fromtext, sizeof(fromtext)); 166 TIME_NOW(&now); 167 diff = (int) isc_time_microdiff(&now, &query->time_sent); 168 printf("Received %u bytes from %s in %d ms\n", 169 bytes, fromtext, diff/1000); 170 } 171} 172 173void 174trying(char *frm, dig_lookup_t *lookup) { 175 UNUSED(lookup); 176 177 if (!short_form) 178 printf("Trying \"%s\"\n", frm); 179} 180 181static void 182say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata, 183 dig_query_t *query) 184{ 185 isc_buffer_t *b = NULL; 186 char namestr[DNS_NAME_FORMATSIZE]; 187 isc_region_t r; 188 isc_result_t result; 189 unsigned int bufsize = BUFSIZ; 190 191 dns_name_format(name, namestr, sizeof(namestr)); 192 retry: 193 result = isc_buffer_allocate(mctx, &b, bufsize); 194 check_result(result, "isc_buffer_allocate"); 195 result = dns_rdata_totext(rdata, NULL, b); 196 if (result == ISC_R_NOSPACE) { 197 isc_buffer_free(&b); 198 bufsize *= 2; 199 goto retry; 200 } 201 check_result(result, "dns_rdata_totext"); 202 isc_buffer_usedregion(b, &r); 203 if (query->lookup->identify_previous_line) { 204 printf("Nameserver %s:\n\t", 205 query->servname); 206 } 207 printf("%s %s %.*s", namestr, 208 msg, (int)r.length, (char *)r.base); 209 if (query->lookup->identify) { 210 printf(" on server %s", query->servname); 211 } 212 printf("\n"); 213 isc_buffer_free(&b); 214} 215#ifdef DIG_SIGCHASE 216/* Just for compatibility : not use in host program */ 217isc_result_t 218printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, 219 isc_buffer_t *target) 220{ 221 UNUSED(owner_name); 222 UNUSED(rdataset); 223 UNUSED(target); 224 return(ISC_FALSE); 225} 226#endif 227static isc_result_t 228printsection(dns_message_t *msg, dns_section_t sectionid, 229 const char *section_name, isc_boolean_t headers, 230 dig_query_t *query) 231{ 232 dns_name_t *name, *print_name; 233 dns_rdataset_t *rdataset; 234 dns_rdata_t rdata = DNS_RDATA_INIT; 235 isc_buffer_t target; 236 isc_result_t result, loopresult; 237 isc_region_t r; 238 dns_name_t empty_name; 239 char t[4096]; 240 isc_boolean_t first; 241 isc_boolean_t no_rdata; 242 243 if (sectionid == DNS_SECTION_QUESTION) 244 no_rdata = ISC_TRUE; 245 else 246 no_rdata = ISC_FALSE; 247 248 if (headers) 249 printf(";; %s SECTION:\n", section_name); 250 251 dns_name_init(&empty_name, NULL); 252 253 result = dns_message_firstname(msg, sectionid); 254 if (result == ISC_R_NOMORE) 255 return (ISC_R_SUCCESS); 256 else if (result != ISC_R_SUCCESS) 257 return (result); 258 259 for (;;) { 260 name = NULL; 261 dns_message_currentname(msg, sectionid, &name); 262 263 isc_buffer_init(&target, t, sizeof(t)); 264 first = ISC_TRUE; 265 print_name = name; 266 267 for (rdataset = ISC_LIST_HEAD(name->list); 268 rdataset != NULL; 269 rdataset = ISC_LIST_NEXT(rdataset, link)) { 270 if (query->lookup->rdtype == dns_rdatatype_axfr && 271 !((!list_addresses && 272 (list_type == dns_rdatatype_any || 273 rdataset->type == list_type)) || 274 (list_addresses && 275 (rdataset->type == dns_rdatatype_a || 276 rdataset->type == dns_rdatatype_aaaa || 277 rdataset->type == dns_rdatatype_ns || 278 rdataset->type == dns_rdatatype_ptr)))) 279 continue; 280 if (!short_form) { 281 result = dns_rdataset_totext(rdataset, 282 print_name, 283 ISC_FALSE, 284 no_rdata, 285 &target); 286 if (result != ISC_R_SUCCESS) 287 return (result); 288#ifdef USEINITALWS 289 if (first) { 290 print_name = &empty_name; 291 first = ISC_FALSE; 292 } 293#else 294 UNUSED(first); /* Shut up compiler. */ 295#endif 296 } else { 297 loopresult = dns_rdataset_first(rdataset); 298 while (loopresult == ISC_R_SUCCESS) { 299 struct rtype *t; 300 const char *rtt; 301 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 302 char typebuf2[DNS_RDATATYPE_FORMATSIZE 303 + 20]; 304 dns_rdataset_current(rdataset, &rdata); 305 306 for (t = rtypes; t->text != NULL; t++) { 307 if (t->type == rdata.type) { 308 rtt = t->text; 309 goto found; 310 } 311 } 312 313 dns_rdatatype_format(rdata.type, 314 typebuf, 315 sizeof(typebuf)); 316 snprintf(typebuf2, sizeof(typebuf2), 317 "has %s record", typebuf); 318 rtt = typebuf2; 319 found: 320 say_message(print_name, rtt, 321 &rdata, query); 322 dns_rdata_reset(&rdata); 323 loopresult = 324 dns_rdataset_next(rdataset); 325 } 326 } 327 } 328 if (!short_form) { 329 isc_buffer_usedregion(&target, &r); 330 if (no_rdata) 331 printf(";%.*s", (int)r.length, 332 (char *)r.base); 333 else 334 printf("%.*s", (int)r.length, (char *)r.base); 335 } 336 337 result = dns_message_nextname(msg, sectionid); 338 if (result == ISC_R_NOMORE) 339 break; 340 else if (result != ISC_R_SUCCESS) 341 return (result); 342 } 343 344 return (ISC_R_SUCCESS); 345} 346 347static isc_result_t 348printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner, 349 const char *set_name, isc_boolean_t headers) 350{ 351 isc_buffer_t target; 352 isc_result_t result; 353 isc_region_t r; 354 char t[4096]; 355 356 UNUSED(msg); 357 if (headers) 358 printf(";; %s SECTION:\n", set_name); 359 360 isc_buffer_init(&target, t, sizeof(t)); 361 362 result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, 363 &target); 364 if (result != ISC_R_SUCCESS) 365 return (result); 366 isc_buffer_usedregion(&target, &r); 367 printf("%.*s", (int)r.length, (char *)r.base); 368 369 return (ISC_R_SUCCESS); 370} 371 372static void 373chase_cnamechain(dns_message_t *msg, dns_name_t *qname) { 374 isc_result_t result; 375 dns_rdataset_t *rdataset; 376 dns_rdata_cname_t cname; 377 dns_rdata_t rdata = DNS_RDATA_INIT; 378 unsigned int i = msg->counts[DNS_SECTION_ANSWER]; 379 380 while (i-- > 0) { 381 rdataset = NULL; 382 result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname, 383 dns_rdatatype_cname, 0, NULL, 384 &rdataset); 385 if (result != ISC_R_SUCCESS) 386 return; 387 result = dns_rdataset_first(rdataset); 388 check_result(result, "dns_rdataset_first"); 389 dns_rdata_reset(&rdata); 390 dns_rdataset_current(rdataset, &rdata); 391 result = dns_rdata_tostruct(&rdata, &cname, NULL); 392 check_result(result, "dns_rdata_tostruct"); 393 dns_name_copy(&cname.cname, qname, NULL); 394 dns_rdata_freestruct(&cname); 395 } 396} 397 398isc_result_t 399printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { 400 isc_boolean_t did_flag = ISC_FALSE; 401 dns_rdataset_t *opt, *tsig = NULL; 402 dns_name_t *tsigname; 403 isc_result_t result = ISC_R_SUCCESS; 404 int force_error; 405 406 UNUSED(headers); 407 408 /* 409 * We get called multiple times. 410 * Preserve any existing error status. 411 */ 412 force_error = (seen_error == 1) ? 1 : 0; 413 seen_error = 1; 414 if (listed_server && !printed_server) { 415 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 416 417 printf("Using domain server:\n"); 418 printf("Name: %s\n", query->userarg); 419 isc_sockaddr_format(&query->sockaddr, sockstr, 420 sizeof(sockstr)); 421 printf("Address: %s\n", sockstr); 422 printf("Aliases: \n\n"); 423 printed_server = ISC_TRUE; 424 } 425 426 if (msg->rcode != 0) { 427 char namestr[DNS_NAME_FORMATSIZE]; 428 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 429 printf("Host %s not found: %d(%s)\n", 430 (msg->rcode != dns_rcode_nxdomain) ? namestr : 431 query->lookup->textname, msg->rcode, 432 rcodetext[msg->rcode]); 433 return (ISC_R_SUCCESS); 434 } 435 436 if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) { 437 char namestr[DNS_NAME_FORMATSIZE]; 438 dig_lookup_t *lookup; 439 dns_fixedname_t fixed; 440 dns_name_t *name; 441 442 /* Add AAAA and MX lookups. */ 443 dns_fixedname_init(&fixed); 444 name = dns_fixedname_name(&fixed); 445 dns_name_copy(query->lookup->name, name, NULL); 446 chase_cnamechain(msg, name); 447 dns_name_format(name, namestr, sizeof(namestr)); 448 lookup = clone_lookup(query->lookup, ISC_FALSE); 449 if (lookup != NULL) { 450 strncpy(lookup->textname, namestr, 451 sizeof(lookup->textname)); 452 lookup->textname[sizeof(lookup->textname)-1] = 0; 453 lookup->rdtype = dns_rdatatype_aaaa; 454 lookup->rdtypeset = ISC_TRUE; 455 lookup->origin = NULL; 456 lookup->retries = tries; 457 ISC_LIST_APPEND(lookup_list, lookup, link); 458 } 459 lookup = clone_lookup(query->lookup, ISC_FALSE); 460 if (lookup != NULL) { 461 strncpy(lookup->textname, namestr, 462 sizeof(lookup->textname)); 463 lookup->textname[sizeof(lookup->textname)-1] = 0; 464 lookup->rdtype = dns_rdatatype_mx; 465 lookup->rdtypeset = ISC_TRUE; 466 lookup->origin = NULL; 467 lookup->retries = tries; 468 ISC_LIST_APPEND(lookup_list, lookup, link); 469 } 470 } 471 472 if (!short_form) { 473 printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n", 474 opcodetext[msg->opcode], rcodetext[msg->rcode], 475 msg->id); 476 printf(";; flags: "); 477 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { 478 printf("qr"); 479 did_flag = ISC_TRUE; 480 } 481 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { 482 printf("%saa", did_flag ? " " : ""); 483 did_flag = ISC_TRUE; 484 } 485 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { 486 printf("%stc", did_flag ? " " : ""); 487 did_flag = ISC_TRUE; 488 } 489 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { 490 printf("%srd", did_flag ? " " : ""); 491 did_flag = ISC_TRUE; 492 } 493 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { 494 printf("%sra", did_flag ? " " : ""); 495 did_flag = ISC_TRUE; 496 } 497 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { 498 printf("%sad", did_flag ? " " : ""); 499 did_flag = ISC_TRUE; 500 } 501 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { 502 printf("%scd", did_flag ? " " : ""); 503 did_flag = ISC_TRUE; 504 } 505 printf("; QUERY: %u, ANSWER: %u, " 506 "AUTHORITY: %u, ADDITIONAL: %u\n", 507 msg->counts[DNS_SECTION_QUESTION], 508 msg->counts[DNS_SECTION_ANSWER], 509 msg->counts[DNS_SECTION_AUTHORITY], 510 msg->counts[DNS_SECTION_ADDITIONAL]); 511 opt = dns_message_getopt(msg); 512 if (opt != NULL) 513 printf(";; EDNS: version: %u, udp=%u\n", 514 (unsigned int)((opt->ttl & 0x00ff0000) >> 16), 515 (unsigned int)opt->rdclass); 516 tsigname = NULL; 517 tsig = dns_message_gettsig(msg, &tsigname); 518 if (tsig != NULL) 519 printf(";; PSEUDOSECTIONS: TSIG\n"); 520 } 521 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && 522 !short_form) { 523 printf("\n"); 524 result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", 525 ISC_TRUE, query); 526 if (result != ISC_R_SUCCESS) 527 return (result); 528 } 529 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 530 if (!short_form) 531 printf("\n"); 532 result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", 533 ISC_TF(!short_form), query); 534 if (result != ISC_R_SUCCESS) 535 return (result); 536 } 537 538 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && 539 !short_form) { 540 printf("\n"); 541 result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", 542 ISC_TRUE, query); 543 if (result != ISC_R_SUCCESS) 544 return (result); 545 } 546 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && 547 !short_form) { 548 printf("\n"); 549 result = printsection(msg, DNS_SECTION_ADDITIONAL, 550 "ADDITIONAL", ISC_TRUE, query); 551 if (result != ISC_R_SUCCESS) 552 return (result); 553 } 554 if ((tsig != NULL) && !short_form) { 555 printf("\n"); 556 result = printrdata(msg, tsig, tsigname, 557 "PSEUDOSECTION TSIG", ISC_TRUE); 558 if (result != ISC_R_SUCCESS) 559 return (result); 560 } 561 if (!short_form) 562 printf("\n"); 563 564 if (short_form && !default_lookups && 565 ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 566 char namestr[DNS_NAME_FORMATSIZE]; 567 char typestr[DNS_RDATATYPE_FORMATSIZE]; 568 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 569 dns_rdatatype_format(query->lookup->rdtype, typestr, 570 sizeof(typestr)); 571 printf("%s has no %s record\n", namestr, typestr); 572 } 573 seen_error = force_error; 574 return (result); 575} 576 577static const char * optstring = "46ac:dilnm:rst:vwCDN:R:TW:"; 578 579static void 580pre_parse_args(int argc, char **argv) { 581 int c; 582 583 while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { 584 switch (c) { 585 case 'm': 586 memdebugging = ISC_TRUE; 587 if (strcasecmp("trace", isc_commandline_argument) == 0) 588 isc_mem_debugging |= ISC_MEM_DEBUGTRACE; 589 else if (!strcasecmp("record", 590 isc_commandline_argument) == 0) 591 isc_mem_debugging |= ISC_MEM_DEBUGRECORD; 592 else if (strcasecmp("usage", 593 isc_commandline_argument) == 0) 594 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; 595 break; 596 597 case '4': break; 598 case '6': break; 599 case 'a': break; 600 case 'c': break; 601 case 'd': break; 602 case 'i': break; 603 case 'l': break; 604 case 'n': break; 605 case 'r': break; 606 case 's': break; 607 case 't': break; 608 case 'v': break; 609 case 'w': break; 610 case 'C': break; 611 case 'D': break; 612 case 'N': break; 613 case 'R': break; 614 case 'T': break; 615 case 'W': break; 616 default: 617 show_usage(); 618 } 619 } 620 isc_commandline_reset = ISC_TRUE; 621 isc_commandline_index = 1; 622} 623 624static void 625parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { 626 char hostname[MXNAME]; 627 dig_lookup_t *lookup; 628 int c; 629 char store[MXNAME]; 630 isc_textregion_t tr; 631 isc_result_t result = ISC_R_SUCCESS; 632 dns_rdatatype_t rdtype; 633 dns_rdataclass_t rdclass; 634 isc_uint32_t serial = 0; 635 636 UNUSED(is_batchfile); 637 638 lookup = make_empty_lookup(); 639 640 lookup->servfail_stops = ISC_FALSE; 641 lookup->comments = ISC_FALSE; 642 643 while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { 644 switch (c) { 645 case 'l': 646 lookup->tcp_mode = ISC_TRUE; 647 lookup->rdtype = dns_rdatatype_axfr; 648 lookup->rdtypeset = ISC_TRUE; 649 fatalexit = 3; 650 break; 651 case 'v': 652 case 'd': 653 short_form = ISC_FALSE; 654 break; 655 case 'r': 656 lookup->recurse = ISC_FALSE; 657 break; 658 case 't': 659 if (strncasecmp(isc_commandline_argument, 660 "ixfr=", 5) == 0) { 661 rdtype = dns_rdatatype_ixfr; 662 /* XXXMPA add error checking */ 663 serial = strtoul(isc_commandline_argument + 5, 664 NULL, 10); 665 result = ISC_R_SUCCESS; 666 } else { 667 tr.base = isc_commandline_argument; 668 tr.length = strlen(isc_commandline_argument); 669 result = dns_rdatatype_fromtext(&rdtype, 670 (isc_textregion_t *)&tr); 671 } 672 673 if (result != ISC_R_SUCCESS) { 674 fatalexit = 2; 675 fatal("invalid type: %s\n", 676 isc_commandline_argument); 677 } 678 if (!lookup->rdtypeset || 679 lookup->rdtype != dns_rdatatype_axfr) 680 lookup->rdtype = rdtype; 681 lookup->rdtypeset = ISC_TRUE; 682#ifdef WITH_IDN 683 idnoptions = 0; 684#endif 685 if (rdtype == dns_rdatatype_axfr) { 686 /* -l -t any -v */ 687 list_type = dns_rdatatype_any; 688 short_form = ISC_FALSE; 689 lookup->tcp_mode = ISC_TRUE; 690 } else if (rdtype == dns_rdatatype_ixfr) { 691 lookup->ixfr_serial = serial; 692 list_type = rdtype; 693#ifdef WITH_IDN 694 } else if (rdtype == dns_rdatatype_a || 695 rdtype == dns_rdatatype_aaaa || 696 rdtype == dns_rdatatype_mx) { 697 idnoptions = IDN_ASCCHECK; 698 list_type = rdtype; 699#endif 700 } else 701 list_type = rdtype; 702 list_addresses = ISC_FALSE; 703 default_lookups = ISC_FALSE; 704 break; 705 case 'c': 706 tr.base = isc_commandline_argument; 707 tr.length = strlen(isc_commandline_argument); 708 result = dns_rdataclass_fromtext(&rdclass, 709 (isc_textregion_t *)&tr); 710 711 if (result != ISC_R_SUCCESS) { 712 fatalexit = 2; 713 fatal("invalid class: %s\n", 714 isc_commandline_argument); 715 } else { 716 lookup->rdclass = rdclass; 717 lookup->rdclassset = ISC_TRUE; 718 } 719 default_lookups = ISC_FALSE; 720 break; 721 case 'a': 722 if (!lookup->rdtypeset || 723 lookup->rdtype != dns_rdatatype_axfr) 724 lookup->rdtype = dns_rdatatype_any; 725 list_type = dns_rdatatype_any; 726 list_addresses = ISC_FALSE; 727 lookup->rdtypeset = ISC_TRUE; 728 short_form = ISC_FALSE; 729 default_lookups = ISC_FALSE; 730 break; 731 case 'i': 732 lookup->ip6_int = ISC_TRUE; 733 break; 734 case 'n': 735 /* deprecated */ 736 break; 737 case 'm': 738 /* Handled by pre_parse_args(). */ 739 break; 740 case 'w': 741 /* 742 * The timer routines are coded such that 743 * timeout==MAXINT doesn't enable the timer 744 */ 745 timeout = INT_MAX; 746 break; 747 case 'W': 748 timeout = atoi(isc_commandline_argument); 749 if (timeout < 1) 750 timeout = 1; 751 break; 752 case 'R': 753 tries = atoi(isc_commandline_argument) + 1; 754 if (tries < 2) 755 tries = 2; 756 break; 757 case 'T': 758 lookup->tcp_mode = ISC_TRUE; 759 break; 760 case 'C': 761 debug("showing all SOAs"); 762 lookup->rdtype = dns_rdatatype_ns; 763 lookup->rdtypeset = ISC_TRUE; 764 lookup->rdclass = dns_rdataclass_in; 765 lookup->rdclassset = ISC_TRUE; 766 lookup->ns_search_only = ISC_TRUE; 767 lookup->trace_root = ISC_TRUE; 768 lookup->identify_previous_line = ISC_TRUE; 769 default_lookups = ISC_FALSE; 770 break; 771 case 'N': 772 debug("setting NDOTS to %s", 773 isc_commandline_argument); 774 ndots = atoi(isc_commandline_argument); 775 break; 776 case 'D': 777 debugging = ISC_TRUE; 778 break; 779 case '4': 780 if (have_ipv4) { 781 isc_net_disableipv6(); 782 have_ipv6 = ISC_FALSE; 783 } else 784 fatal("can't find IPv4 networking"); 785 break; 786 case '6': 787 if (have_ipv6) { 788 isc_net_disableipv4(); 789 have_ipv4 = ISC_FALSE; 790 } else 791 fatal("can't find IPv6 networking"); 792 break; 793 case 's': 794 lookup->servfail_stops = ISC_TRUE; 795 break; 796 } 797 } 798 799 lookup->retries = tries; 800 801 if (isc_commandline_index >= argc) 802 show_usage(); 803 804 strncpy(hostname, argv[isc_commandline_index], sizeof(hostname)); 805 hostname[sizeof(hostname)-1]=0; 806 if (argc > isc_commandline_index + 1) { 807 set_nameserver(argv[isc_commandline_index+1]); 808 debug("server is %s", argv[isc_commandline_index+1]); 809 listed_server = ISC_TRUE; 810 } else 811 check_ra = ISC_TRUE; 812 813 lookup->pending = ISC_FALSE; 814 if (get_reverse(store, sizeof(store), hostname, 815 lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) { 816 strncpy(lookup->textname, store, sizeof(lookup->textname)); 817 lookup->textname[sizeof(lookup->textname)-1] = 0; 818 lookup->rdtype = dns_rdatatype_ptr; 819 lookup->rdtypeset = ISC_TRUE; 820 default_lookups = ISC_FALSE; 821 } else { 822 strncpy(lookup->textname, hostname, sizeof(lookup->textname)); 823 lookup->textname[sizeof(lookup->textname)-1]=0; 824 } 825 lookup->new_search = ISC_TRUE; 826 ISC_LIST_APPEND(lookup_list, lookup, link); 827 828 usesearch = ISC_TRUE; 829} 830 831int 832main(int argc, char **argv) { 833 isc_result_t result; 834 835 tries = 2; 836 837 ISC_LIST_INIT(lookup_list); 838 ISC_LIST_INIT(server_list); 839 ISC_LIST_INIT(search_list); 840 841 fatalexit = 1; 842#ifdef WITH_IDN 843 idnoptions = IDN_ASCCHECK; 844#endif 845 846 debug("main()"); 847 progname = argv[0]; 848 pre_parse_args(argc, argv); 849 result = isc_app_start(); 850 check_result(result, "isc_app_start"); 851 setup_libs(); 852 parse_args(ISC_FALSE, argc, argv); 853 setup_system(); 854 result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); 855 check_result(result, "isc_app_onrun"); 856 isc_app_run(); 857 cancel_all(); 858 destroy_libs(); 859 isc_app_finish(); 860 return ((seen_error == 0) ? 0 : 1); 861} 862