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