host.c revision 135446
1279264Sdelphij/* 2238405Sjkim * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") 3238405Sjkim * Copyright (C) 2000-2003 Internet Software Consortium. 4238405Sjkim * 5238405Sjkim * Permission to use, copy, modify, and distribute this software for any 6238405Sjkim * purpose with or without fee is hereby granted, provided that the above 7238405Sjkim * copyright notice and this permission notice appear in all copies. 8238405Sjkim * 9238405Sjkim * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10238405Sjkim * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11238405Sjkim * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12238405Sjkim * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13238405Sjkim * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14238405Sjkim * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15238405Sjkim * PERFORMANCE OF THIS SOFTWARE. 16238405Sjkim */ 17238405Sjkim 18238405Sjkim/* $Id: host.c,v 1.76.2.5.2.9 2004/04/13 03:00:06 marka Exp $ */ 19238405Sjkim 20238405Sjkim#include <config.h> 21238405Sjkim#include <limits.h> 22238405Sjkim 23238405Sjkim#include <isc/app.h> 24238405Sjkim#include <isc/commandline.h> 25238405Sjkim#include <isc/netaddr.h> 26238405Sjkim#include <isc/print.h> 27238405Sjkim#include <isc/string.h> 28238405Sjkim#include <isc/util.h> 29238405Sjkim#include <isc/task.h> 30238405Sjkim#include <isc/stdlib.h> 31238405Sjkim 32238405Sjkim#include <dns/byaddr.h> 33238405Sjkim#include <dns/fixedname.h> 34238405Sjkim#include <dns/message.h> 35238405Sjkim#include <dns/name.h> 36238405Sjkim#include <dns/rdata.h> 37238405Sjkim#include <dns/rdataclass.h> 38238405Sjkim#include <dns/rdataset.h> 39238405Sjkim#include <dns/rdatatype.h> 40238405Sjkim 41279264Sdelphij#include <dig/dig.h> 42279264Sdelphij 43238405Sjkimextern ISC_LIST(dig_lookup_t) lookup_list; 44238405Sjkimextern dig_serverlist_t server_list; 45238405Sjkimextern ISC_LIST(dig_searchlist_t) search_list; 46238405Sjkim 47238405Sjkimextern isc_boolean_t have_ipv4, have_ipv6; 48238405Sjkimextern isc_boolean_t usesearch; 49238405Sjkimextern isc_boolean_t debugging; 50238405Sjkimextern unsigned int timeout; 51238405Sjkimextern isc_mem_t *mctx; 52238405Sjkimextern int ndots; 53279264Sdelphijextern int tries; 54279264Sdelphijextern char *progname; 55279264Sdelphijextern isc_task_t *global_task; 56238405Sjkimextern int fatalexit; 57279264Sdelphij 58279264Sdelphijstatic isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE; 59279264Sdelphijstatic isc_boolean_t default_lookups = ISC_TRUE; 60279264Sdelphijstatic int seen_error = -1; 61279264Sdelphijstatic isc_boolean_t list_addresses = ISC_TRUE; 62279264Sdelphijstatic dns_rdatatype_t list_type = dns_rdatatype_a; 63238405Sjkim 64279264Sdelphijstatic const char *opcodetext[] = { 65279264Sdelphij "QUERY", 66279264Sdelphij "IQUERY", 67279264Sdelphij "STATUS", 68279264Sdelphij "RESERVED3", 69238405Sjkim "NOTIFY", 70279264Sdelphij "UPDATE", 71238405Sjkim "RESERVED6", 72238405Sjkim "RESERVED7", 73238405Sjkim "RESERVED8", 74238405Sjkim "RESERVED9", 75238405Sjkim "RESERVED10", 76238405Sjkim "RESERVED11", 77238405Sjkim "RESERVED12", 78238405Sjkim "RESERVED13", 79238405Sjkim "RESERVED14", 80238405Sjkim "RESERVED15" 81238405Sjkim}; 82238405Sjkim 83238405Sjkimstatic const char *rcodetext[] = { 84238405Sjkim "NOERROR", 85238405Sjkim "FORMERR", 86238405Sjkim "SERVFAIL", 87238405Sjkim "NXDOMAIN", 88238405Sjkim "NOTIMP", 89238405Sjkim "REFUSED", 90238405Sjkim "YXDOMAIN", 91238405Sjkim "YXRRSET", 92238405Sjkim "NXRRSET", 93238405Sjkim "NOTAUTH", 94238405Sjkim "NOTZONE", 95238405Sjkim "RESERVED11", 96238405Sjkim "RESERVED12", 97238405Sjkim "RESERVED13", 98238405Sjkim "RESERVED14", 99238405Sjkim "RESERVED15", 100238405Sjkim "BADVERS" 101238405Sjkim}; 102238405Sjkim 103238405Sjkimstruct rtype { 104238405Sjkim unsigned int type; 105238405Sjkim const char *text; 106238405Sjkim}; 107238405Sjkim 108238405Sjkimstruct rtype rtypes[] = { 109238405Sjkim { 1, "has address" }, 110238405Sjkim { 2, "name server" }, 111238405Sjkim { 5, "is an alias for" }, 112238405Sjkim { 11, "has well known services" }, 113238405Sjkim { 12, "domain name pointer" }, 114238405Sjkim { 13, "host information" }, 115238405Sjkim { 15, "mail is handled by" }, 116238405Sjkim { 16, "descriptive text" }, 117238405Sjkim { 19, "x25 address" }, 118238405Sjkim { 20, "ISDN address" }, 119238405Sjkim { 24, "has signature" }, 120238405Sjkim { 25, "has key" }, 121238405Sjkim { 28, "has IPv6 address" }, 122238405Sjkim { 29, "location" }, 123238405Sjkim { 0, NULL } 124238405Sjkim}; 125238405Sjkim 126238405Sjkimstatic void 127238405Sjkimshow_usage(void) { 128238405Sjkim fputs( 129238405Sjkim"Usage: host [-aCdlriTwv] [-c class] [-N ndots] [-t type] [-W time]\n" 130238405Sjkim" [-R number] hostname [server]\n" 131238405Sjkim" -a is equivalent to -v -t *\n" 132238405Sjkim" -c specifies query class for non-IN data\n" 133238405Sjkim" -C compares SOA records on authoritative nameservers\n" 134238405Sjkim" -d is equivalent to -v\n" 135238405Sjkim" -l lists all hosts in a domain, using AXFR\n" 136279264Sdelphij" -i IP6.INT reverse lookups\n" 137238405Sjkim" -N changes the number of dots allowed before root lookup is done\n" 138238405Sjkim" -r disables recursive processing\n" 139238405Sjkim" -R specifies number of retries for UDP packets\n" 140238405Sjkim" -t specifies the query type\n" 141238405Sjkim" -T enables TCP/IP mode\n" 142238405Sjkim" -v enables verbose output\n" 143238405Sjkim" -w specifies to wait forever for a reply\n" 144238405Sjkim" -W specifies how long to wait for a reply\n" 145238405Sjkim" -4 use IPv4 query transport only\n" 146238405Sjkim" -6 use IPv6 query transport only\n", stderr); 147238405Sjkim exit(1); 148238405Sjkim} 149238405Sjkim 150238405Sjkimvoid 151238405Sjkimdighost_shutdown(void) { 152238405Sjkim isc_app_shutdown(); 153238405Sjkim} 154238405Sjkim 155238405Sjkimvoid 156238405Sjkimreceived(int bytes, isc_sockaddr_t *from, dig_query_t *query) { 157238405Sjkim isc_time_t now; 158238405Sjkim int diff; 159238405Sjkim 160238405Sjkim if (!short_form) { 161238405Sjkim char fromtext[ISC_SOCKADDR_FORMATSIZE]; 162238405Sjkim isc_sockaddr_format(from, fromtext, sizeof(fromtext)); 163238405Sjkim TIME_NOW(&now); 164238405Sjkim diff = (int) isc_time_microdiff(&now, &query->time_sent); 165238405Sjkim printf("Received %u bytes from %s in %d ms\n", 166238405Sjkim bytes, fromtext, diff/1000); 167238405Sjkim } 168238405Sjkim} 169238405Sjkim 170238405Sjkimvoid 171238405Sjkimtrying(char *frm, dig_lookup_t *lookup) { 172238405Sjkim UNUSED(lookup); 173238405Sjkim 174238405Sjkim if (!short_form) 175238405Sjkim printf("Trying \"%s\"\n", frm); 176238405Sjkim} 177238405Sjkim 178238405Sjkimstatic void 179238405Sjkimsay_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata, 180279264Sdelphij dig_query_t *query) 181279264Sdelphij{ 182279264Sdelphij isc_buffer_t *b = NULL; 183238405Sjkim char namestr[DNS_NAME_FORMATSIZE]; 184279264Sdelphij isc_region_t r; 185238405Sjkim isc_result_t result; 186238405Sjkim unsigned int bufsize = BUFSIZ; 187279264Sdelphij 188238405Sjkim dns_name_format(name, namestr, sizeof(namestr)); 189238405Sjkim retry: 190279264Sdelphij result = isc_buffer_allocate(mctx, &b, bufsize); 191238405Sjkim check_result(result, "isc_buffer_allocate"); 192238405Sjkim result = dns_rdata_totext(rdata, NULL, b); 193238405Sjkim if (result == ISC_R_NOSPACE) { 194279264Sdelphij isc_buffer_free(&b); 195238405Sjkim bufsize *= 2; 196238405Sjkim goto retry; 197279264Sdelphij } 198238405Sjkim check_result(result, "dns_rdata_totext"); 199238405Sjkim isc_buffer_usedregion(b, &r); 200238405Sjkim if (query->lookup->identify_previous_line) { 201238405Sjkim printf("Nameserver %s:\n\t", 202238405Sjkim query->servname); 203238405Sjkim } 204238405Sjkim printf("%s %s %.*s", namestr, 205238405Sjkim msg, (int)r.length, (char *)r.base); 206238405Sjkim if (query->lookup->identify) { 207238405Sjkim printf(" on server %s", query->servname); 208238405Sjkim } 209238405Sjkim printf("\n"); 210238405Sjkim isc_buffer_free(&b); 211238405Sjkim} 212238405Sjkim#ifdef DIG_SIGCHASE 213238405Sjkim/* Just for compatibility : not use in host program */ 214238405Sjkimisc_result_t 215238405Sjkimprintrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, 216238405Sjkim isc_buffer_t *target) 217238405Sjkim{ 218238405Sjkim UNUSED(owner_name); 219238405Sjkim UNUSED(rdataset); 220238405Sjkim UNUSED(target); 221279264Sdelphij return(ISC_FALSE); 222279264Sdelphij} 223238405Sjkim#endif 224238405Sjkimstatic isc_result_t 225238405Sjkimprintsection(dns_message_t *msg, dns_section_t sectionid, 226238405Sjkim const char *section_name, isc_boolean_t headers, 227246772Sjkim dig_query_t *query) 228238405Sjkim{ 229238405Sjkim dns_name_t *name, *print_name; 230238405Sjkim dns_rdataset_t *rdataset; 231238405Sjkim dns_rdata_t rdata = DNS_RDATA_INIT; 232 isc_buffer_t target; 233 isc_result_t result, loopresult; 234 isc_region_t r; 235 dns_name_t empty_name; 236 char t[4096]; 237 isc_boolean_t first; 238 isc_boolean_t no_rdata; 239 240 if (sectionid == DNS_SECTION_QUESTION) 241 no_rdata = ISC_TRUE; 242 else 243 no_rdata = ISC_FALSE; 244 245 if (headers) 246 printf(";; %s SECTION:\n", section_name); 247 248 dns_name_init(&empty_name, NULL); 249 250 result = dns_message_firstname(msg, sectionid); 251 if (result == ISC_R_NOMORE) 252 return (ISC_R_SUCCESS); 253 else if (result != ISC_R_SUCCESS) 254 return (result); 255 256 for (;;) { 257 name = NULL; 258 dns_message_currentname(msg, sectionid, &name); 259 260 isc_buffer_init(&target, t, sizeof(t)); 261 first = ISC_TRUE; 262 print_name = name; 263 264 for (rdataset = ISC_LIST_HEAD(name->list); 265 rdataset != NULL; 266 rdataset = ISC_LIST_NEXT(rdataset, link)) { 267 if (query->lookup->rdtype == dns_rdatatype_axfr && 268 !((!list_addresses && 269 (list_type == dns_rdatatype_any || 270 rdataset->type == list_type)) || 271 (list_addresses && 272 (rdataset->type == dns_rdatatype_a || 273 rdataset->type == dns_rdatatype_aaaa || 274 rdataset->type == dns_rdatatype_ns || 275 rdataset->type == dns_rdatatype_ptr)))) 276 continue; 277 if (!short_form) { 278 result = dns_rdataset_totext(rdataset, 279 print_name, 280 ISC_FALSE, 281 no_rdata, 282 &target); 283 if (result != ISC_R_SUCCESS) 284 return (result); 285#ifdef USEINITALWS 286 if (first) { 287 print_name = &empty_name; 288 first = ISC_FALSE; 289 } 290#else 291 UNUSED(first); /* Shut up compiler. */ 292#endif 293 } else { 294 loopresult = dns_rdataset_first(rdataset); 295 while (loopresult == ISC_R_SUCCESS) { 296 struct rtype *t; 297 const char *rtt; 298 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 299 char typebuf2[DNS_RDATATYPE_FORMATSIZE 300 + 20]; 301 dns_rdataset_current(rdataset, &rdata); 302 303 for (t = rtypes; t->text != NULL; t++) { 304 if (t->type == rdata.type) { 305 rtt = t->text; 306 goto found; 307 } 308 } 309 310 dns_rdatatype_format(rdata.type, 311 typebuf, 312 sizeof(typebuf)); 313 snprintf(typebuf2, sizeof(typebuf2), 314 "has %s record", typebuf); 315 rtt = typebuf2; 316 found: 317 say_message(print_name, rtt, 318 &rdata, query); 319 dns_rdata_reset(&rdata); 320 loopresult = 321 dns_rdataset_next(rdataset); 322 } 323 } 324 } 325 if (!short_form) { 326 isc_buffer_usedregion(&target, &r); 327 if (no_rdata) 328 printf(";%.*s", (int)r.length, 329 (char *)r.base); 330 else 331 printf("%.*s", (int)r.length, (char *)r.base); 332 } 333 334 result = dns_message_nextname(msg, sectionid); 335 if (result == ISC_R_NOMORE) 336 break; 337 else if (result != ISC_R_SUCCESS) 338 return (result); 339 } 340 341 return (ISC_R_SUCCESS); 342} 343 344static isc_result_t 345printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner, 346 const char *set_name, isc_boolean_t headers) 347{ 348 isc_buffer_t target; 349 isc_result_t result; 350 isc_region_t r; 351 char t[4096]; 352 353 UNUSED(msg); 354 if (headers) 355 printf(";; %s SECTION:\n", set_name); 356 357 isc_buffer_init(&target, t, sizeof(t)); 358 359 result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, 360 &target); 361 if (result != ISC_R_SUCCESS) 362 return (result); 363 isc_buffer_usedregion(&target, &r); 364 printf("%.*s", (int)r.length, (char *)r.base); 365 366 return (ISC_R_SUCCESS); 367} 368 369isc_result_t 370printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { 371 isc_boolean_t did_flag = ISC_FALSE; 372 dns_rdataset_t *opt, *tsig = NULL; 373 dns_name_t *tsigname; 374 isc_result_t result = ISC_R_SUCCESS; 375 int force_error; 376 377 UNUSED(headers); 378 379 /* 380 * We get called multiple times. 381 * Preserve any existing error status. 382 */ 383 force_error = (seen_error == 1) ? 1 : 0; 384 seen_error = 1; 385 if (listed_server) { 386 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 387 388 printf("Using domain server:\n"); 389 printf("Name: %s\n", query->servname); 390 isc_sockaddr_format(&query->sockaddr, sockstr, 391 sizeof(sockstr)); 392 printf("Address: %s\n", sockstr); 393 printf("Aliases: \n\n"); 394 } 395 396 if (msg->rcode != 0) { 397 char namestr[DNS_NAME_FORMATSIZE]; 398 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 399 printf("Host %s not found: %d(%s)\n", namestr, 400 msg->rcode, rcodetext[msg->rcode]); 401 return (ISC_R_SUCCESS); 402 } 403 404 if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) { 405 char namestr[DNS_NAME_FORMATSIZE]; 406 dig_lookup_t *lookup; 407 408 /* Add AAAA and MX lookups. */ 409 410 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 411 lookup = clone_lookup(query->lookup, ISC_FALSE); 412 if (lookup != NULL) { 413 strncpy(lookup->textname, namestr, 414 sizeof(lookup->textname)); 415 lookup->textname[sizeof(lookup->textname)-1] = 0; 416 lookup->rdtype = dns_rdatatype_aaaa; 417 lookup->rdtypeset = ISC_TRUE; 418 lookup->origin = NULL; 419 lookup->retries = tries; 420 ISC_LIST_APPEND(lookup_list, lookup, link); 421 } 422 lookup = clone_lookup(query->lookup, ISC_FALSE); 423 if (lookup != NULL) { 424 strncpy(lookup->textname, namestr, 425 sizeof(lookup->textname)); 426 lookup->textname[sizeof(lookup->textname)-1] = 0; 427 lookup->rdtype = dns_rdatatype_mx; 428 lookup->rdtypeset = ISC_TRUE; 429 lookup->origin = NULL; 430 lookup->retries = tries; 431 ISC_LIST_APPEND(lookup_list, lookup, link); 432 } 433 } 434 435 if (!short_form) { 436 printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n", 437 opcodetext[msg->opcode], rcodetext[msg->rcode], 438 msg->id); 439 printf(";; flags: "); 440 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { 441 printf("qr"); 442 did_flag = ISC_TRUE; 443 } 444 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { 445 printf("%saa", did_flag ? " " : ""); 446 did_flag = ISC_TRUE; 447 } 448 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { 449 printf("%stc", did_flag ? " " : ""); 450 did_flag = ISC_TRUE; 451 } 452 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { 453 printf("%srd", did_flag ? " " : ""); 454 did_flag = ISC_TRUE; 455 } 456 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { 457 printf("%sra", did_flag ? " " : ""); 458 did_flag = ISC_TRUE; 459 } 460 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { 461 printf("%sad", did_flag ? " " : ""); 462 did_flag = ISC_TRUE; 463 } 464 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { 465 printf("%scd", did_flag ? " " : ""); 466 did_flag = ISC_TRUE; 467 } 468 printf("; QUERY: %u, ANSWER: %u, " 469 "AUTHORITY: %u, ADDITIONAL: %u\n", 470 msg->counts[DNS_SECTION_QUESTION], 471 msg->counts[DNS_SECTION_ANSWER], 472 msg->counts[DNS_SECTION_AUTHORITY], 473 msg->counts[DNS_SECTION_ADDITIONAL]); 474 opt = dns_message_getopt(msg); 475 if (opt != NULL) 476 printf(";; EDNS: version: %u, udp=%u\n", 477 (unsigned int)((opt->ttl & 0x00ff0000) >> 16), 478 (unsigned int)opt->rdclass); 479 tsigname = NULL; 480 tsig = dns_message_gettsig(msg, &tsigname); 481 if (tsig != NULL) 482 printf(";; PSEUDOSECTIONS: TSIG\n"); 483 } 484 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && 485 !short_form) { 486 printf("\n"); 487 result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", 488 ISC_TRUE, query); 489 if (result != ISC_R_SUCCESS) 490 return (result); 491 } 492 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 493 if (!short_form) 494 printf("\n"); 495 result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", 496 ISC_TF(!short_form), query); 497 if (result != ISC_R_SUCCESS) 498 return (result); 499 } 500 501 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && 502 !short_form) { 503 printf("\n"); 504 result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", 505 ISC_TRUE, query); 506 if (result != ISC_R_SUCCESS) 507 return (result); 508 } 509 if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && 510 !short_form) { 511 printf("\n"); 512 result = printsection(msg, DNS_SECTION_ADDITIONAL, 513 "ADDITIONAL", ISC_TRUE, query); 514 if (result != ISC_R_SUCCESS) 515 return (result); 516 } 517 if ((tsig != NULL) && !short_form) { 518 printf("\n"); 519 result = printrdata(msg, tsig, tsigname, 520 "PSEUDOSECTION TSIG", ISC_TRUE); 521 if (result != ISC_R_SUCCESS) 522 return (result); 523 } 524 if (!short_form) 525 printf("\n"); 526 527 if (short_form && !default_lookups && 528 ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { 529 char namestr[DNS_NAME_FORMATSIZE]; 530 char typestr[DNS_RDATATYPE_FORMATSIZE]; 531 dns_name_format(query->lookup->name, namestr, sizeof(namestr)); 532 dns_rdatatype_format(query->lookup->rdtype, typestr, 533 sizeof(typestr)); 534 printf("%s has no %s record\n", namestr, typestr); 535 } 536 seen_error = force_error; 537 return (result); 538} 539 540static void 541parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { 542 char hostname[MXNAME]; 543 dig_lookup_t *lookup; 544 int c; 545 char store[MXNAME]; 546 isc_textregion_t tr; 547 isc_result_t result = ISC_R_SUCCESS; 548 dns_rdatatype_t rdtype; 549 dns_rdataclass_t rdclass; 550 isc_uint32_t serial = 0; 551 552 UNUSED(is_batchfile); 553 554 lookup = make_empty_lookup(); 555 556 while ((c = isc_commandline_parse(argc, argv, "lvwrdt:c:aTCN:R:W:Dni46")) 557 != EOF) { 558 switch (c) { 559 case 'l': 560 lookup->tcp_mode = ISC_TRUE; 561 lookup->rdtype = dns_rdatatype_axfr; 562 lookup->rdtypeset = ISC_TRUE; 563 fatalexit = 3; 564 break; 565 case 'v': 566 case 'd': 567 short_form = ISC_FALSE; 568 break; 569 case 'r': 570 lookup->recurse = ISC_FALSE; 571 break; 572 case 't': 573 if (strncasecmp(isc_commandline_argument, 574 "ixfr=", 5) == 0) { 575 rdtype = dns_rdatatype_ixfr; 576 /* XXXMPA add error checking */ 577 serial = strtoul(isc_commandline_argument + 5, 578 NULL, 10); 579 result = ISC_R_SUCCESS; 580 } else { 581 tr.base = isc_commandline_argument; 582 tr.length = strlen(isc_commandline_argument); 583 result = dns_rdatatype_fromtext(&rdtype, 584 (isc_textregion_t *)&tr); 585 } 586 587 if (result != ISC_R_SUCCESS) { 588 fatalexit = 2; 589 fatal("invalid type: %s\n", 590 isc_commandline_argument); 591 } 592 if (!lookup->rdtypeset || 593 lookup->rdtype != dns_rdatatype_axfr) 594 lookup->rdtype = rdtype; 595 lookup->rdtypeset = ISC_TRUE; 596 if (rdtype == dns_rdatatype_axfr) { 597 /* -l -t any -v */ 598 list_type = dns_rdatatype_any; 599 short_form = ISC_FALSE; 600 lookup->tcp_mode = ISC_TRUE; 601 } else if (rdtype == dns_rdatatype_ixfr) { 602 lookup->ixfr_serial = serial; 603 list_type = rdtype; 604 } else 605 list_type = rdtype; 606 list_addresses = ISC_FALSE; 607 break; 608 case 'c': 609 tr.base = isc_commandline_argument; 610 tr.length = strlen(isc_commandline_argument); 611 result = dns_rdataclass_fromtext(&rdclass, 612 (isc_textregion_t *)&tr); 613 614 if (result != ISC_R_SUCCESS) { 615 fatalexit = 2; 616 fatal("invalid class: %s\n", 617 isc_commandline_argument); 618 } else { 619 lookup->rdclass = rdclass; 620 lookup->rdclassset = ISC_TRUE; 621 } 622 default_lookups = ISC_FALSE; 623 break; 624 case 'a': 625 if (!lookup->rdtypeset || 626 lookup->rdtype != dns_rdatatype_axfr) 627 lookup->rdtype = dns_rdatatype_any; 628 list_type = dns_rdatatype_any; 629 list_addresses = ISC_FALSE; 630 lookup->rdtypeset = ISC_TRUE; 631 short_form = ISC_FALSE; 632 default_lookups = ISC_FALSE; 633 break; 634 case 'i': 635 lookup->ip6_int = ISC_TRUE; 636 break; 637 case 'n': 638 /* deprecated */ 639 break; 640 case 'w': 641 /* 642 * The timer routines are coded such that 643 * timeout==MAXINT doesn't enable the timer 644 */ 645 timeout = INT_MAX; 646 break; 647 case 'W': 648 timeout = atoi(isc_commandline_argument); 649 if (timeout < 1) 650 timeout = 1; 651 break; 652 case 'R': 653 tries = atoi(isc_commandline_argument) + 1; 654 if (tries < 2) 655 tries = 2; 656 break; 657 case 'T': 658 lookup->tcp_mode = ISC_TRUE; 659 break; 660 case 'C': 661 debug("showing all SOAs"); 662 lookup->rdtype = dns_rdatatype_ns; 663 lookup->rdtypeset = ISC_TRUE; 664 lookup->rdclass = dns_rdataclass_in; 665 lookup->rdclassset = ISC_TRUE; 666 lookup->ns_search_only = ISC_TRUE; 667 lookup->trace_root = ISC_TRUE; 668 lookup->identify_previous_line = ISC_TRUE; 669 default_lookups = ISC_FALSE; 670 break; 671 case 'N': 672 debug("setting NDOTS to %s", 673 isc_commandline_argument); 674 ndots = atoi(isc_commandline_argument); 675 break; 676 case 'D': 677 debugging = ISC_TRUE; 678 break; 679 case '4': 680 if (have_ipv4) { 681 isc_net_disableipv6(); 682 have_ipv6 = ISC_FALSE; 683 } else 684 fatal("can't find IPv4 networking"); 685 break; 686 case '6': 687 if (have_ipv6) { 688 isc_net_disableipv4(); 689 have_ipv4 = ISC_FALSE; 690 } else 691 fatal("can't find IPv6 networking"); 692 break; 693 } 694 } 695 696 lookup->retries = tries; 697 698 if (isc_commandline_index >= argc) 699 show_usage(); 700 701 strncpy(hostname, argv[isc_commandline_index], sizeof(hostname)); 702 hostname[sizeof(hostname)-1]=0; 703 if (argc > isc_commandline_index + 1) { 704 set_nameserver(argv[isc_commandline_index+1]); 705 debug("server is %s", argv[isc_commandline_index+1]); 706 listed_server = ISC_TRUE; 707 } 708 709 lookup->pending = ISC_FALSE; 710 if (get_reverse(store, sizeof(store), hostname, 711 lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) { 712 strncpy(lookup->textname, store, sizeof(lookup->textname)); 713 lookup->textname[sizeof(lookup->textname)-1] = 0; 714 lookup->rdtype = dns_rdatatype_ptr; 715 lookup->rdtypeset = ISC_TRUE; 716 default_lookups = ISC_FALSE; 717 } else { 718 strncpy(lookup->textname, hostname, sizeof(lookup->textname)); 719 lookup->textname[sizeof(lookup->textname)-1]=0; 720 } 721 lookup->new_search = ISC_TRUE; 722 ISC_LIST_APPEND(lookup_list, lookup, link); 723 724 usesearch = ISC_TRUE; 725} 726 727int 728main(int argc, char **argv) { 729 isc_result_t result; 730 731 tries = 2; 732 733 ISC_LIST_INIT(lookup_list); 734 ISC_LIST_INIT(server_list); 735 ISC_LIST_INIT(search_list); 736 737 fatalexit = 1; 738 739 debug("main()"); 740 progname = argv[0]; 741 result = isc_app_start(); 742 check_result(result, "isc_app_start"); 743 setup_libs(); 744 parse_args(ISC_FALSE, argc, argv); 745 setup_system(); 746 result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); 747 check_result(result, "isc_app_onrun"); 748 isc_app_run(); 749 cancel_all(); 750 destroy_libs(); 751 isc_app_finish(); 752 return ((seen_error == 0) ? 0 : 1); 753} 754 755