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