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