dig.c revision 254402
1305382Sbde/* 2305382Sbde * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") 3305382Sbde * Copyright (C) 2000-2003 Internet Software Consortium. 4305382Sbde * 5305382Sbde * Permission to use, copy, modify, and/or distribute this software for any 6305382Sbde * purpose with or without fee is hereby granted, provided that the above 7305382Sbde * copyright notice and this permission notice appear in all copies. 8305382Sbde * 9305382Sbde * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10305382Sbde * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11305382Sbde * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12305382Sbde * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13305382Sbde * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14305382Sbde * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15305382Sbde * PERFORMANCE OF THIS SOFTWARE. 16305382Sbde */ 17305382Sbde 18305382Sbde/* $Id: dig.c,v 1.237.124.4 2011/12/07 17:23:55 each Exp $ */ 19305382Sbde 20305382Sbde/*! \file */ 21305382Sbde 22305382Sbde#include <config.h> 23305382Sbde#include <stdlib.h> 24305382Sbde#include <time.h> 25305382Sbde#include <ctype.h> 26305382Sbde 27305382Sbde#include <isc/app.h> 28305382Sbde#include <isc/netaddr.h> 29305382Sbde#include <isc/parseint.h> 30305382Sbde#include <isc/print.h> 31305382Sbde#include <isc/string.h> 32305382Sbde#include <isc/util.h> 33305382Sbde#include <isc/task.h> 34305382Sbde 35305382Sbde#include <dns/byaddr.h> 36305382Sbde#include <dns/fixedname.h> 37305382Sbde#include <dns/masterdump.h> 38305382Sbde#include <dns/message.h> 39305382Sbde#include <dns/name.h> 40305382Sbde#include <dns/rdata.h> 41305382Sbde#include <dns/rdataset.h> 42305382Sbde#include <dns/rdatatype.h> 43305382Sbde#include <dns/rdataclass.h> 44305382Sbde#include <dns/result.h> 45305382Sbde#include <dns/tsig.h> 46305382Sbde 47305382Sbde#include <dig/dig.h> 48305382Sbde 49305382Sbde#define ADD_STRING(b, s) { \ 50305382Sbde if (strlen(s) >= isc_buffer_availablelength(b)) \ 51 return (ISC_R_NOSPACE); \ 52 else \ 53 isc_buffer_putstr(b, s); \ 54} 55 56#define DIG_MAX_ADDRESSES 20 57 58dig_lookup_t *default_lookup = NULL; 59 60static char *batchname = NULL; 61static FILE *batchfp = NULL; 62static char *argv0; 63static int addresscount = 0; 64 65static char domainopt[DNS_NAME_MAXTEXT]; 66 67static isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE, 68 ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE, 69 multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE, 70 onesoa = ISC_FALSE; 71 72/*% opcode text */ 73static const char * const opcodetext[] = { 74 "QUERY", 75 "IQUERY", 76 "STATUS", 77 "RESERVED3", 78 "NOTIFY", 79 "UPDATE", 80 "RESERVED6", 81 "RESERVED7", 82 "RESERVED8", 83 "RESERVED9", 84 "RESERVED10", 85 "RESERVED11", 86 "RESERVED12", 87 "RESERVED13", 88 "RESERVED14", 89 "RESERVED15" 90}; 91 92/*% return code text */ 93static const char * const rcodetext[] = { 94 "NOERROR", 95 "FORMERR", 96 "SERVFAIL", 97 "NXDOMAIN", 98 "NOTIMP", 99 "REFUSED", 100 "YXDOMAIN", 101 "YXRRSET", 102 "NXRRSET", 103 "NOTAUTH", 104 "NOTZONE", 105 "RESERVED11", 106 "RESERVED12", 107 "RESERVED13", 108 "RESERVED14", 109 "RESERVED15", 110 "BADVERS" 111}; 112 113/*% safe rcodetext[] */ 114static char * 115rcode_totext(dns_rcode_t rcode) 116{ 117 static char buf[sizeof("?65535")]; 118 union { 119 const char *consttext; 120 char *deconsttext; 121 } totext; 122 123 if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 124 snprintf(buf, sizeof(buf), "?%u", rcode); 125 totext.deconsttext = buf; 126 } else 127 totext.consttext = rcodetext[rcode]; 128 return totext.deconsttext; 129} 130 131/*% print usage */ 132static void 133print_usage(FILE *fp) { 134 fputs( 135"Usage: dig [@global-server] [domain] [q-type] [q-class] {q-opt}\n" 136" {global-d-opt} host [@local-server] {local-d-opt}\n" 137" [ host [@local-server] {local-d-opt} [...]]\n", fp); 138} 139 140ISC_PLATFORM_NORETURN_PRE static void 141usage(void) ISC_PLATFORM_NORETURN_POST; 142 143static void 144usage(void) { 145 print_usage(stderr); 146 fputs("\nUse \"dig -h\" (or \"dig -h | more\") " 147 "for complete list of options\n", stderr); 148 exit(1); 149} 150 151/*% version */ 152static void 153version(void) { 154 fputs("DiG " VERSION "\n", stderr); 155} 156 157/*% help */ 158static void 159help(void) { 160 print_usage(stdout); 161 fputs( 162"Where: domain is in the Domain Name System\n" 163" q-class is one of (in,hs,ch,...) [default: in]\n" 164" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n" 165" (Use ixfr=version for type ixfr)\n" 166" q-opt is one of:\n" 167" -x dot-notation (shortcut for reverse lookups)\n" 168" -i (use IP6.INT for IPv6 reverse lookups)\n" 169" -f filename (batch mode)\n" 170" -b address[#port] (bind to source address/port)\n" 171" -p port (specify port number)\n" 172" -q name (specify query name)\n" 173" -t type (specify query type)\n" 174" -c class (specify query class)\n" 175" -k keyfile (specify tsig key file)\n" 176" -y [hmac:]name:key (specify named base64 tsig key)\n" 177" -4 (use IPv4 query transport only)\n" 178" -6 (use IPv6 query transport only)\n" 179" -m (enable memory usage debugging)\n" 180" d-opt is of the form +keyword[=value], where keyword is:\n" 181" +[no]vc (TCP mode)\n" 182" +[no]tcp (TCP mode, alternate syntax)\n" 183" +time=### (Set query timeout) [5]\n" 184" +tries=### (Set number of UDP attempts) [3]\n" 185" +retry=### (Set number of UDP retries) [2]\n" 186" +domain=### (Set default domainname)\n" 187" +bufsize=### (Set EDNS0 Max UDP packet size)\n" 188" +ndots=### (Set NDOTS value)\n" 189" +[no]edns[=###] (Set EDNS version) [0]\n" 190" +[no]search (Set whether to use searchlist)\n" 191" +[no]showsearch (Search with intermediate results)\n" 192" +[no]defname (Ditto)\n" 193" +[no]recurse (Recursive mode)\n" 194" +[no]ignore (Don't revert to TCP for TC responses.)" 195"\n" 196" +[no]fail (Don't try next server on SERVFAIL)\n" 197" +[no]besteffort (Try to parse even illegal messages)\n" 198" +[no]aaonly (Set AA flag in query (+[no]aaflag))\n" 199" +[no]adflag (Set AD flag in query)\n" 200" +[no]cdflag (Set CD flag in query)\n" 201" +[no]cl (Control display of class in records)\n" 202" +[no]cmd (Control display of command line)\n" 203" +[no]comments (Control display of comment lines)\n" 204" +[no]question (Control display of question)\n" 205" +[no]answer (Control display of answer)\n" 206" +[no]authority (Control display of authority)\n" 207" +[no]additional (Control display of additional)\n" 208" +[no]stats (Control display of statistics)\n" 209" +[no]short (Disable everything except short\n" 210" form of answer)\n" 211" +[no]ttlid (Control display of ttls in records)\n" 212" +[no]all (Set or clear all display flags)\n" 213" +[no]qr (Print question before sending)\n" 214" +[no]nssearch (Search all authoritative nameservers)\n" 215" +[no]identify (ID responders in short answers)\n" 216" +[no]trace (Trace delegation down from root)\n" 217" +[no]dnssec (Request DNSSEC records)\n" 218" +[no]nsid (Request Name Server ID)\n" 219#ifdef DIG_SIGCHASE 220" +[no]sigchase (Chase DNSSEC signatures)\n" 221" +trusted-key=#### (Trusted Key when chasing DNSSEC sigs)\n" 222#if DIG_SIGCHASE_TD 223" +[no]topdown (Do DNSSEC validation top down mode)\n" 224#endif 225#endif 226" +[no]multiline (Print records in an expanded format)\n" 227" +[no]onesoa (AXFR prints only one soa record)\n" 228" global d-opts and servers (before host name) affect all queries.\n" 229" local d-opts and servers (after host name) affect only that lookup.\n" 230" -h (print help and exit)\n" 231" -v (print version and exit)\n", 232 stdout); 233} 234 235/*% 236 * Callback from dighost.c to print the received message. 237 */ 238void 239received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { 240 isc_uint64_t diff; 241 isc_time_t now; 242 time_t tnow; 243 struct tm tmnow; 244 char time_str[100]; 245 char fromtext[ISC_SOCKADDR_FORMATSIZE]; 246 247 isc_sockaddr_format(from, fromtext, sizeof(fromtext)); 248 249 TIME_NOW(&now); 250 251 if (query->lookup->stats && !short_form) { 252 diff = isc_time_microdiff(&now, &query->time_sent); 253 printf(";; Query time: %ld msec\n", (long int)diff/1000); 254 printf(";; SERVER: %s(%s)\n", fromtext, query->servname); 255 time(&tnow); 256 tmnow = *localtime(&tnow); 257 if (strftime(time_str, sizeof(time_str), 258 "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) 259 printf(";; WHEN: %s\n", time_str); 260 if (query->lookup->doing_xfr) { 261 printf(";; XFR size: %u records (messages %u, " 262 "bytes %" ISC_PRINT_QUADFORMAT "u)\n", 263 query->rr_count, query->msg_count, 264 query->byte_count); 265 } else { 266 printf(";; MSG SIZE rcvd: %u\n", bytes); 267 } 268 if (key != NULL) { 269 if (!validated) 270 puts(";; WARNING -- Some TSIG could not " 271 "be validated"); 272 } 273 if ((key == NULL) && (keysecret[0] != 0)) { 274 puts(";; WARNING -- TSIG key was not used."); 275 } 276 puts(""); 277 } else if (query->lookup->identify && !short_form) { 278 diff = isc_time_microdiff(&now, &query->time_sent); 279 printf(";; Received %" ISC_PRINT_QUADFORMAT "u bytes " 280 "from %s(%s) in %d ms\n\n", 281 query->lookup->doing_xfr ? 282 query->byte_count : (isc_uint64_t)bytes, 283 fromtext, query->userarg, 284 (int)diff/1000); 285 } 286} 287 288/* 289 * Callback from dighost.c to print that it is trying a server. 290 * Not used in dig. 291 * XXX print_trying 292 */ 293void 294trying(char *frm, dig_lookup_t *lookup) { 295 UNUSED(frm); 296 UNUSED(lookup); 297} 298 299/*% 300 * Internal print routine used to print short form replies. 301 */ 302static isc_result_t 303say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) { 304 isc_result_t result; 305 isc_uint64_t diff; 306 isc_time_t now; 307 char store[sizeof("12345678901234567890")]; 308 309 if (query->lookup->trace || query->lookup->ns_search_only) { 310 result = dns_rdatatype_totext(rdata->type, buf); 311 if (result != ISC_R_SUCCESS) 312 return (result); 313 ADD_STRING(buf, " "); 314 } 315 result = dns_rdata_totext(rdata, NULL, buf); 316 if (result == ISC_R_NOSPACE) 317 return (result); 318 check_result(result, "dns_rdata_totext"); 319 if (query->lookup->identify) { 320 TIME_NOW(&now); 321 diff = isc_time_microdiff(&now, &query->time_sent); 322 ADD_STRING(buf, " from server "); 323 ADD_STRING(buf, query->servname); 324 snprintf(store, 19, " in %d ms.", (int)diff/1000); 325 ADD_STRING(buf, store); 326 } 327 ADD_STRING(buf, "\n"); 328 return (ISC_R_SUCCESS); 329} 330 331/*% 332 * short_form message print handler. Calls above say_message() 333 */ 334static isc_result_t 335short_answer(dns_message_t *msg, dns_messagetextflag_t flags, 336 isc_buffer_t *buf, dig_query_t *query) 337{ 338 dns_name_t *name; 339 dns_rdataset_t *rdataset; 340 isc_result_t result, loopresult; 341 dns_name_t empty_name; 342 dns_rdata_t rdata = DNS_RDATA_INIT; 343 344 UNUSED(flags); 345 346 dns_name_init(&empty_name, NULL); 347 result = dns_message_firstname(msg, DNS_SECTION_ANSWER); 348 if (result == ISC_R_NOMORE) 349 return (ISC_R_SUCCESS); 350 else if (result != ISC_R_SUCCESS) 351 return (result); 352 353 for (;;) { 354 name = NULL; 355 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); 356 357 for (rdataset = ISC_LIST_HEAD(name->list); 358 rdataset != NULL; 359 rdataset = ISC_LIST_NEXT(rdataset, link)) { 360 loopresult = dns_rdataset_first(rdataset); 361 while (loopresult == ISC_R_SUCCESS) { 362 dns_rdataset_current(rdataset, &rdata); 363 result = say_message(&rdata, query, 364 buf); 365 if (result == ISC_R_NOSPACE) 366 return (result); 367 check_result(result, "say_message"); 368 loopresult = dns_rdataset_next(rdataset); 369 dns_rdata_reset(&rdata); 370 } 371 } 372 result = dns_message_nextname(msg, DNS_SECTION_ANSWER); 373 if (result == ISC_R_NOMORE) 374 break; 375 else if (result != ISC_R_SUCCESS) 376 return (result); 377 } 378 379 return (ISC_R_SUCCESS); 380} 381#ifdef DIG_SIGCHASE 382isc_result_t 383printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, 384 isc_buffer_t *target) 385{ 386 isc_result_t result; 387 dns_master_style_t *style = NULL; 388 unsigned int styleflags = 0; 389 390 if (rdataset == NULL || owner_name == NULL || target == NULL) 391 return(ISC_FALSE); 392 393 styleflags |= DNS_STYLEFLAG_REL_OWNER; 394 if (nottl) 395 styleflags |= DNS_STYLEFLAG_NO_TTL; 396 if (noclass) 397 styleflags |= DNS_STYLEFLAG_NO_CLASS; 398 if (multiline) { 399 styleflags |= DNS_STYLEFLAG_OMIT_OWNER; 400 styleflags |= DNS_STYLEFLAG_OMIT_CLASS; 401 styleflags |= DNS_STYLEFLAG_REL_DATA; 402 styleflags |= DNS_STYLEFLAG_OMIT_TTL; 403 styleflags |= DNS_STYLEFLAG_TTL; 404 styleflags |= DNS_STYLEFLAG_MULTILINE; 405 styleflags |= DNS_STYLEFLAG_COMMENT; 406 } 407 if (multiline || (nottl && noclass)) 408 result = dns_master_stylecreate(&style, styleflags, 409 24, 24, 24, 32, 80, 8, mctx); 410 else if (nottl || noclass) 411 result = dns_master_stylecreate(&style, styleflags, 412 24, 24, 32, 40, 80, 8, mctx); 413 else 414 result = dns_master_stylecreate(&style, styleflags, 415 24, 32, 40, 48, 80, 8, mctx); 416 check_result(result, "dns_master_stylecreate"); 417 418 result = dns_master_rdatasettotext(owner_name, rdataset, style, target); 419 420 if (style != NULL) 421 dns_master_styledestroy(&style, mctx); 422 423 return(result); 424} 425#endif 426 427/* 428 * Callback from dighost.c to print the reply from a server 429 */ 430isc_result_t 431printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { 432 isc_result_t result; 433 dns_messagetextflag_t flags; 434 isc_buffer_t *buf = NULL; 435 unsigned int len = OUTPUTBUF; 436 dns_master_style_t *style = NULL; 437 unsigned int styleflags = 0; 438 439 styleflags |= DNS_STYLEFLAG_REL_OWNER; 440 if (nottl) 441 styleflags |= DNS_STYLEFLAG_NO_TTL; 442 if (noclass) 443 styleflags |= DNS_STYLEFLAG_NO_CLASS; 444 if (multiline) { 445 styleflags |= DNS_STYLEFLAG_OMIT_OWNER; 446 styleflags |= DNS_STYLEFLAG_OMIT_CLASS; 447 styleflags |= DNS_STYLEFLAG_REL_DATA; 448 styleflags |= DNS_STYLEFLAG_OMIT_TTL; 449 styleflags |= DNS_STYLEFLAG_TTL; 450 styleflags |= DNS_STYLEFLAG_MULTILINE; 451 styleflags |= DNS_STYLEFLAG_COMMENT; 452 } 453 if (multiline || (nottl && noclass)) 454 result = dns_master_stylecreate(&style, styleflags, 455 24, 24, 24, 32, 80, 8, mctx); 456 else if (nottl || noclass) 457 result = dns_master_stylecreate(&style, styleflags, 458 24, 24, 32, 40, 80, 8, mctx); 459 else 460 result = dns_master_stylecreate(&style, styleflags, 461 24, 32, 40, 48, 80, 8, mctx); 462 check_result(result, "dns_master_stylecreate"); 463 464 if (query->lookup->cmdline[0] != 0) { 465 if (!short_form) 466 fputs(query->lookup->cmdline, stdout); 467 query->lookup->cmdline[0]=0; 468 } 469 debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders", 470 query->lookup->comments ? "comments" : "nocomments", 471 short_form ? "short_form" : "long_form"); 472 473 flags = 0; 474 if (!headers) { 475 flags |= DNS_MESSAGETEXTFLAG_NOHEADERS; 476 flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; 477 } 478 if (onesoa && query->lookup->rdtype == dns_rdatatype_axfr) 479 flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA : 480 DNS_MESSAGETEXTFLAG_OMITSOA; 481 if (!query->lookup->comments) 482 flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; 483 484 result = isc_buffer_allocate(mctx, &buf, len); 485 check_result(result, "isc_buffer_allocate"); 486 487 if (query->lookup->comments && !short_form) { 488 if (query->lookup->cmdline[0] != 0) 489 printf("; %s\n", query->lookup->cmdline); 490 if (msg == query->lookup->sendmsg) 491 printf(";; Sending:\n"); 492 else 493 printf(";; Got answer:\n"); 494 495 if (headers) { 496 printf(";; ->>HEADER<<- opcode: %s, status: %s, " 497 "id: %u\n", 498 opcodetext[msg->opcode], 499 rcode_totext(msg->rcode), 500 msg->id); 501 printf(";; flags:"); 502 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 503 printf(" qr"); 504 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) 505 printf(" aa"); 506 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) 507 printf(" tc"); 508 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) 509 printf(" rd"); 510 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) 511 printf(" ra"); 512 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) 513 printf(" ad"); 514 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) 515 printf(" cd"); 516 if ((msg->flags & 0x0040U) != 0) 517 printf("; MBZ: 0x4"); 518 519 printf("; QUERY: %u, ANSWER: %u, " 520 "AUTHORITY: %u, ADDITIONAL: %u\n", 521 msg->counts[DNS_SECTION_QUESTION], 522 msg->counts[DNS_SECTION_ANSWER], 523 msg->counts[DNS_SECTION_AUTHORITY], 524 msg->counts[DNS_SECTION_ADDITIONAL]); 525 526 if (msg != query->lookup->sendmsg && 527 (msg->flags & DNS_MESSAGEFLAG_RD) != 0 && 528 (msg->flags & DNS_MESSAGEFLAG_RA) == 0) 529 printf(";; WARNING: recursion requested " 530 "but not available\n"); 531 } 532 if (msg != query->lookup->sendmsg && 533 query->lookup->edns != -1 && msg->opt == NULL && 534 (msg->rcode == dns_rcode_formerr || 535 msg->rcode == dns_rcode_notimp)) 536 printf("\n;; WARNING: EDNS query returned status " 537 "%s - retry with '+noedns'\n", 538 rcode_totext(msg->rcode)); 539 if (msg != query->lookup->sendmsg && extrabytes != 0U) 540 printf(";; WARNING: Messages has %u extra byte%s at " 541 "end\n", extrabytes, extrabytes != 0 ? "s" : ""); 542 } 543 544repopulate_buffer: 545 546 if (query->lookup->comments && headers && !short_form) { 547 result = dns_message_pseudosectiontotext(msg, 548 DNS_PSEUDOSECTION_OPT, 549 style, flags, buf); 550 if (result == ISC_R_NOSPACE) { 551buftoosmall: 552 len += OUTPUTBUF; 553 isc_buffer_free(&buf); 554 result = isc_buffer_allocate(mctx, &buf, len); 555 if (result == ISC_R_SUCCESS) 556 goto repopulate_buffer; 557 else 558 goto cleanup; 559 } 560 check_result(result, 561 "dns_message_pseudosectiontotext"); 562 } 563 564 if (query->lookup->section_question && headers) { 565 if (!short_form) { 566 result = dns_message_sectiontotext(msg, 567 DNS_SECTION_QUESTION, 568 style, flags, buf); 569 if (result == ISC_R_NOSPACE) 570 goto buftoosmall; 571 check_result(result, "dns_message_sectiontotext"); 572 } 573 } 574 if (query->lookup->section_answer) { 575 if (!short_form) { 576 result = dns_message_sectiontotext(msg, 577 DNS_SECTION_ANSWER, 578 style, flags, buf); 579 if (result == ISC_R_NOSPACE) 580 goto buftoosmall; 581 check_result(result, "dns_message_sectiontotext"); 582 } else { 583 result = short_answer(msg, flags, buf, query); 584 if (result == ISC_R_NOSPACE) 585 goto buftoosmall; 586 check_result(result, "short_answer"); 587 } 588 } 589 if (query->lookup->section_authority) { 590 if (!short_form) { 591 result = dns_message_sectiontotext(msg, 592 DNS_SECTION_AUTHORITY, 593 style, flags, buf); 594 if (result == ISC_R_NOSPACE) 595 goto buftoosmall; 596 check_result(result, "dns_message_sectiontotext"); 597 } 598 } 599 if (query->lookup->section_additional) { 600 if (!short_form) { 601 result = dns_message_sectiontotext(msg, 602 DNS_SECTION_ADDITIONAL, 603 style, flags, buf); 604 if (result == ISC_R_NOSPACE) 605 goto buftoosmall; 606 check_result(result, "dns_message_sectiontotext"); 607 /* 608 * Only print the signature on the first record. 609 */ 610 if (headers) { 611 result = dns_message_pseudosectiontotext( 612 msg, 613 DNS_PSEUDOSECTION_TSIG, 614 style, flags, buf); 615 if (result == ISC_R_NOSPACE) 616 goto buftoosmall; 617 check_result(result, 618 "dns_message_pseudosectiontotext"); 619 result = dns_message_pseudosectiontotext( 620 msg, 621 DNS_PSEUDOSECTION_SIG0, 622 style, flags, buf); 623 if (result == ISC_R_NOSPACE) 624 goto buftoosmall; 625 check_result(result, 626 "dns_message_pseudosectiontotext"); 627 } 628 } 629 } 630 631 if (headers && query->lookup->comments && !short_form) 632 printf("\n"); 633 634 printf("%.*s", (int)isc_buffer_usedlength(buf), 635 (char *)isc_buffer_base(buf)); 636 isc_buffer_free(&buf); 637 638cleanup: 639 if (style != NULL) 640 dns_master_styledestroy(&style, mctx); 641 return (result); 642} 643 644/*% 645 * print the greeting message when the program first starts up. 646 */ 647static void 648printgreeting(int argc, char **argv, dig_lookup_t *lookup) { 649 int i; 650 int remaining; 651 static isc_boolean_t first = ISC_TRUE; 652 char append[MXNAME]; 653 654 if (printcmd) { 655 lookup->cmdline[sizeof(lookup->cmdline) - 1] = 0; 656 snprintf(lookup->cmdline, sizeof(lookup->cmdline), 657 "%s; <<>> DiG " VERSION " <<>>", 658 first?"\n":""); 659 i = 1; 660 while (i < argc) { 661 snprintf(append, sizeof(append), " %s", argv[i++]); 662 remaining = sizeof(lookup->cmdline) - 663 strlen(lookup->cmdline) - 1; 664 strncat(lookup->cmdline, append, remaining); 665 } 666 remaining = sizeof(lookup->cmdline) - 667 strlen(lookup->cmdline) - 1; 668 strncat(lookup->cmdline, "\n", remaining); 669 if (first && addresscount != 0) { 670 snprintf(append, sizeof(append), 671 "; (%d server%s found)\n", 672 addresscount, 673 addresscount > 1 ? "s" : ""); 674 remaining = sizeof(lookup->cmdline) - 675 strlen(lookup->cmdline) - 1; 676 strncat(lookup->cmdline, append, remaining); 677 } 678 if (first) { 679 snprintf(append, sizeof(append), 680 ";; global options:%s%s\n", 681 short_form ? " +short" : "", 682 printcmd ? " +cmd" : ""); 683 first = ISC_FALSE; 684 remaining = sizeof(lookup->cmdline) - 685 strlen(lookup->cmdline) - 1; 686 strncat(lookup->cmdline, append, remaining); 687 } 688 } 689} 690 691/*% 692 * We're not using isc_commandline_parse() here since the command line 693 * syntax of dig is quite a bit different from that which can be described 694 * by that routine. 695 * XXX doc options 696 */ 697 698static void 699plus_option(char *option, isc_boolean_t is_batchfile, 700 dig_lookup_t *lookup) 701{ 702 isc_result_t result; 703 char option_store[256]; 704 char *cmd, *value, *ptr; 705 isc_uint32_t num; 706 isc_boolean_t state = ISC_TRUE; 707#ifdef DIG_SIGCHASE 708 size_t n; 709#endif 710 711 strncpy(option_store, option, sizeof(option_store)); 712 option_store[sizeof(option_store)-1]=0; 713 ptr = option_store; 714 cmd = next_token(&ptr,"="); 715 if (cmd == NULL) { 716 printf(";; Invalid option %s\n", option_store); 717 return; 718 } 719 value = ptr; 720 if (strncasecmp(cmd, "no", 2)==0) { 721 cmd += 2; 722 state = ISC_FALSE; 723 } 724 725#define FULLCHECK(A) \ 726 do { \ 727 size_t _l = strlen(cmd); \ 728 if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ 729 goto invalid_option; \ 730 } while (0) 731#define FULLCHECK2(A, B) \ 732 do { \ 733 size_t _l = strlen(cmd); \ 734 if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \ 735 (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \ 736 goto invalid_option; \ 737 } while (0) 738 739 switch (cmd[0]) { 740 case 'a': 741 switch (cmd[1]) { 742 case 'a': /* aaonly / aaflag */ 743 FULLCHECK2("aaonly", "aaflag"); 744 lookup->aaonly = state; 745 break; 746 case 'd': 747 switch (cmd[2]) { 748 case 'd': /* additional */ 749 FULLCHECK("additional"); 750 lookup->section_additional = state; 751 break; 752 case 'f': /* adflag */ 753 case '\0': /* +ad is a synonym for +adflag */ 754 FULLCHECK("adflag"); 755 lookup->adflag = state; 756 break; 757 default: 758 goto invalid_option; 759 } 760 break; 761 case 'l': /* all */ 762 FULLCHECK("all"); 763 lookup->section_question = state; 764 lookup->section_authority = state; 765 lookup->section_answer = state; 766 lookup->section_additional = state; 767 lookup->comments = state; 768 lookup->stats = state; 769 printcmd = state; 770 break; 771 case 'n': /* answer */ 772 FULLCHECK("answer"); 773 lookup->section_answer = state; 774 break; 775 case 'u': /* authority */ 776 FULLCHECK("authority"); 777 lookup->section_authority = state; 778 break; 779 default: 780 goto invalid_option; 781 } 782 break; 783 case 'b': 784 switch (cmd[1]) { 785 case 'e':/* besteffort */ 786 FULLCHECK("besteffort"); 787 lookup->besteffort = state; 788 break; 789 case 'u':/* bufsize */ 790 FULLCHECK("bufsize"); 791 if (value == NULL) 792 goto need_value; 793 if (!state) 794 goto invalid_option; 795 result = parse_uint(&num, value, COMMSIZE, 796 "buffer size"); 797 if (result != ISC_R_SUCCESS) 798 fatal("Couldn't parse buffer size"); 799 lookup->udpsize = num; 800 break; 801 default: 802 goto invalid_option; 803 } 804 break; 805 case 'c': 806 switch (cmd[1]) { 807 case 'd':/* cdflag */ 808 switch (cmd[2]) { 809 case 'f': /* cdflag */ 810 case '\0': /* +cd is a synonym for +cdflag */ 811 FULLCHECK("cdflag"); 812 lookup->cdflag = state; 813 break; 814 default: 815 goto invalid_option; 816 } 817 break; 818 case 'l': /* cl */ 819 FULLCHECK("cl"); 820 noclass = ISC_TF(!state); 821 break; 822 case 'm': /* cmd */ 823 FULLCHECK("cmd"); 824 printcmd = state; 825 break; 826 case 'o': /* comments */ 827 FULLCHECK("comments"); 828 lookup->comments = state; 829 if (lookup == default_lookup) 830 pluscomm = state; 831 break; 832 default: 833 goto invalid_option; 834 } 835 break; 836 case 'd': 837 switch (cmd[1]) { 838 case 'e': /* defname */ 839 FULLCHECK("defname"); 840 if (!lookup->trace) { 841 usesearch = state; 842 } 843 break; 844 case 'n': /* dnssec */ 845 FULLCHECK("dnssec"); 846 if (state && lookup->edns == -1) 847 lookup->edns = 0; 848 lookup->dnssec = state; 849 break; 850 case 'o': /* domain */ 851 FULLCHECK("domain"); 852 if (value == NULL) 853 goto need_value; 854 if (!state) 855 goto invalid_option; 856 strncpy(domainopt, value, sizeof(domainopt)); 857 domainopt[sizeof(domainopt)-1] = '\0'; 858 break; 859 default: 860 goto invalid_option; 861 } 862 break; 863 case 'e': 864 FULLCHECK("edns"); 865 if (!state) { 866 lookup->edns = -1; 867 break; 868 } 869 if (value == NULL) { 870 lookup->edns = 0; 871 break; 872 } 873 result = parse_uint(&num, value, 255, "edns"); 874 if (result != ISC_R_SUCCESS) 875 fatal("Couldn't parse edns"); 876 lookup->edns = num; 877 break; 878 case 'f': /* fail */ 879 FULLCHECK("fail"); 880 lookup->servfail_stops = state; 881 break; 882 case 'i': 883 switch (cmd[1]) { 884 case 'd': /* identify */ 885 FULLCHECK("identify"); 886 lookup->identify = state; 887 break; 888 case 'g': /* ignore */ 889 default: /* Inherits default for compatibility */ 890 FULLCHECK("ignore"); 891 lookup->ignore = ISC_TRUE; 892 } 893 break; 894 case 'm': /* multiline */ 895 FULLCHECK("multiline"); 896 multiline = state; 897 break; 898 case 'n': 899 switch (cmd[1]) { 900 case 'd': /* ndots */ 901 FULLCHECK("ndots"); 902 if (value == NULL) 903 goto need_value; 904 if (!state) 905 goto invalid_option; 906 result = parse_uint(&num, value, MAXNDOTS, "ndots"); 907 if (result != ISC_R_SUCCESS) 908 fatal("Couldn't parse ndots"); 909 ndots = num; 910 break; 911 case 's': 912 switch (cmd[2]) { 913 case 'i': /* nsid */ 914 FULLCHECK("nsid"); 915 if (state && lookup->edns == -1) 916 lookup->edns = 0; 917 lookup->nsid = state; 918 break; 919 case 's': /* nssearch */ 920 FULLCHECK("nssearch"); 921 lookup->ns_search_only = state; 922 if (state) { 923 lookup->trace_root = ISC_TRUE; 924 lookup->recurse = ISC_TRUE; 925 lookup->identify = ISC_TRUE; 926 lookup->stats = ISC_FALSE; 927 lookup->comments = ISC_FALSE; 928 lookup->section_additional = ISC_FALSE; 929 lookup->section_authority = ISC_FALSE; 930 lookup->section_question = ISC_FALSE; 931 lookup->rdtype = dns_rdatatype_ns; 932 lookup->rdtypeset = ISC_TRUE; 933 short_form = ISC_TRUE; 934 } 935 break; 936 default: 937 goto invalid_option; 938 } 939 break; 940 default: 941 goto invalid_option; 942 } 943 break; 944 case 'o': 945 FULLCHECK("onesoa"); 946 onesoa = state; 947 break; 948 case 'q': 949 switch (cmd[1]) { 950 case 'r': /* qr */ 951 FULLCHECK("qr"); 952 qr = state; 953 break; 954 case 'u': /* question */ 955 FULLCHECK("question"); 956 lookup->section_question = state; 957 if (lookup == default_lookup) 958 plusquest = state; 959 break; 960 default: 961 goto invalid_option; 962 } 963 break; 964 case 'r': 965 switch (cmd[1]) { 966 case 'e': 967 switch (cmd[2]) { 968 case 'c': /* recurse */ 969 FULLCHECK("recurse"); 970 lookup->recurse = state; 971 break; 972 case 't': /* retry / retries */ 973 FULLCHECK2("retry", "retries"); 974 if (value == NULL) 975 goto need_value; 976 if (!state) 977 goto invalid_option; 978 result = parse_uint(&lookup->retries, value, 979 MAXTRIES - 1, "retries"); 980 if (result != ISC_R_SUCCESS) 981 fatal("Couldn't parse retries"); 982 lookup->retries++; 983 break; 984 default: 985 goto invalid_option; 986 } 987 break; 988 default: 989 goto invalid_option; 990 } 991 break; 992 case 's': 993 switch (cmd[1]) { 994 case 'e': /* search */ 995 FULLCHECK("search"); 996 if (!lookup->trace) { 997 usesearch = state; 998 } 999 break; 1000 case 'h': 1001 if (cmd[2] != 'o') 1002 goto invalid_option; 1003 switch (cmd[3]) { 1004 case 'r': /* short */ 1005 FULLCHECK("short"); 1006 short_form = state; 1007 if (state) { 1008 printcmd = ISC_FALSE; 1009 lookup->section_additional = ISC_FALSE; 1010 lookup->section_answer = ISC_TRUE; 1011 lookup->section_authority = ISC_FALSE; 1012 lookup->section_question = ISC_FALSE; 1013 lookup->comments = ISC_FALSE; 1014 lookup->stats = ISC_FALSE; 1015 } 1016 break; 1017 case 'w': /* showsearch */ 1018 FULLCHECK("showsearch"); 1019 if (!lookup->trace) { 1020 showsearch = state; 1021 usesearch = state; 1022 } 1023 break; 1024 default: 1025 goto invalid_option; 1026 } 1027 break; 1028#ifdef DIG_SIGCHASE 1029 case 'i': /* sigchase */ 1030 FULLCHECK("sigchase"); 1031 lookup->sigchase = state; 1032 if (lookup->sigchase) 1033 lookup->dnssec = ISC_TRUE; 1034 break; 1035#endif 1036 case 't': /* stats */ 1037 FULLCHECK("stats"); 1038 lookup->stats = state; 1039 break; 1040 default: 1041 goto invalid_option; 1042 } 1043 break; 1044 case 't': 1045 switch (cmd[1]) { 1046 case 'c': /* tcp */ 1047 FULLCHECK("tcp"); 1048 if (!is_batchfile) 1049 lookup->tcp_mode = state; 1050 break; 1051 case 'i': /* timeout */ 1052 FULLCHECK("timeout"); 1053 if (value == NULL) 1054 goto need_value; 1055 if (!state) 1056 goto invalid_option; 1057 result = parse_uint(&timeout, value, MAXTIMEOUT, 1058 "timeout"); 1059 if (result != ISC_R_SUCCESS) 1060 fatal("Couldn't parse timeout"); 1061 if (timeout == 0) 1062 timeout = 1; 1063 break; 1064#if DIG_SIGCHASE_TD 1065 case 'o': /* topdown */ 1066 FULLCHECK("topdown"); 1067 lookup->do_topdown = state; 1068 break; 1069#endif 1070 case 'r': 1071 switch (cmd[2]) { 1072 case 'a': /* trace */ 1073 FULLCHECK("trace"); 1074 lookup->trace = state; 1075 lookup->trace_root = state; 1076 if (state) { 1077 lookup->recurse = ISC_FALSE; 1078 lookup->identify = ISC_TRUE; 1079 lookup->comments = ISC_FALSE; 1080 lookup->stats = ISC_FALSE; 1081 lookup->section_additional = ISC_FALSE; 1082 lookup->section_authority = ISC_TRUE; 1083 lookup->section_question = ISC_FALSE; 1084 usesearch = ISC_FALSE; 1085 } 1086 break; 1087 case 'i': /* tries */ 1088 FULLCHECK("tries"); 1089 if (value == NULL) 1090 goto need_value; 1091 if (!state) 1092 goto invalid_option; 1093 result = parse_uint(&lookup->retries, value, 1094 MAXTRIES, "tries"); 1095 if (result != ISC_R_SUCCESS) 1096 fatal("Couldn't parse tries"); 1097 if (lookup->retries == 0) 1098 lookup->retries = 1; 1099 break; 1100#ifdef DIG_SIGCHASE 1101 case 'u': /* trusted-key */ 1102 FULLCHECK("trusted-key"); 1103 if (value == NULL) 1104 goto need_value; 1105 if (!state) 1106 goto invalid_option; 1107 n = strlcpy(trustedkey, ptr, 1108 sizeof(trustedkey)); 1109 if (n >= sizeof(trustedkey)) 1110 fatal("trusted key too large"); 1111 break; 1112#endif 1113 default: 1114 goto invalid_option; 1115 } 1116 break; 1117 case 't': /* ttlid */ 1118 FULLCHECK("ttlid"); 1119 nottl = ISC_TF(!state); 1120 break; 1121 default: 1122 goto invalid_option; 1123 } 1124 break; 1125 case 'v': 1126 FULLCHECK("vc"); 1127 if (!is_batchfile) 1128 lookup->tcp_mode = state; 1129 break; 1130 default: 1131 invalid_option: 1132 need_value: 1133 fprintf(stderr, "Invalid option: +%s\n", 1134 option); 1135 usage(); 1136 } 1137 return; 1138} 1139 1140/*% 1141 * #ISC_TRUE returned if value was used 1142 */ 1143static const char *single_dash_opts = "46dhimnv"; 1144static const char *dash_opts = "46bcdfhikmnptvyx"; 1145static isc_boolean_t 1146dash_option(char *option, char *next, dig_lookup_t **lookup, 1147 isc_boolean_t *open_type_class, isc_boolean_t *need_clone, 1148 isc_boolean_t config_only, int argc, char **argv, 1149 isc_boolean_t *firstarg) 1150{ 1151 char opt, *value, *ptr, *ptr2, *ptr3; 1152 isc_result_t result; 1153 isc_boolean_t value_from_next; 1154 isc_textregion_t tr; 1155 dns_rdatatype_t rdtype; 1156 dns_rdataclass_t rdclass; 1157 char textname[MXNAME]; 1158 struct in_addr in4; 1159 struct in6_addr in6; 1160 in_port_t srcport; 1161 char *hash, *cmd; 1162 isc_uint32_t num; 1163 1164 while (strpbrk(option, single_dash_opts) == &option[0]) { 1165 /* 1166 * Since the -[46dhimnv] options do not take an argument, 1167 * account for them (in any number and/or combination) 1168 * if they appear as the first character(s) of a q-opt. 1169 */ 1170 opt = option[0]; 1171 switch (opt) { 1172 case '4': 1173 if (have_ipv4) { 1174 isc_net_disableipv6(); 1175 have_ipv6 = ISC_FALSE; 1176 } else { 1177 fatal("can't find IPv4 networking"); 1178 /* NOTREACHED */ 1179 return (ISC_FALSE); 1180 } 1181 break; 1182 case '6': 1183 if (have_ipv6) { 1184 isc_net_disableipv4(); 1185 have_ipv4 = ISC_FALSE; 1186 } else { 1187 fatal("can't find IPv6 networking"); 1188 /* NOTREACHED */ 1189 return (ISC_FALSE); 1190 } 1191 break; 1192 case 'd': 1193 ptr = strpbrk(&option[1], dash_opts); 1194 if (ptr != &option[1]) { 1195 cmd = option; 1196 FULLCHECK("debug"); 1197 debugging = ISC_TRUE; 1198 return (ISC_FALSE); 1199 } else 1200 debugging = ISC_TRUE; 1201 break; 1202 case 'h': 1203 help(); 1204 exit(0); 1205 break; 1206 case 'i': 1207 ip6_int = ISC_TRUE; 1208 break; 1209 case 'm': /* memdebug */ 1210 /* memdebug is handled in preparse_args() */ 1211 break; 1212 case 'n': 1213 /* deprecated */ 1214 break; 1215 case 'v': 1216 version(); 1217 exit(0); 1218 break; 1219 } 1220 if (strlen(option) > 1U) 1221 option = &option[1]; 1222 else 1223 return (ISC_FALSE); 1224 } 1225 opt = option[0]; 1226 if (strlen(option) > 1U) { 1227 value_from_next = ISC_FALSE; 1228 value = &option[1]; 1229 } else { 1230 value_from_next = ISC_TRUE; 1231 value = next; 1232 } 1233 if (value == NULL) 1234 goto invalid_option; 1235 switch (opt) { 1236 case 'b': 1237 hash = strchr(value, '#'); 1238 if (hash != NULL) { 1239 result = parse_uint(&num, hash + 1, MAXPORT, 1240 "port number"); 1241 if (result != ISC_R_SUCCESS) 1242 fatal("Couldn't parse port number"); 1243 srcport = num; 1244 *hash = '\0'; 1245 } else 1246 srcport = 0; 1247 if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) { 1248 isc_sockaddr_fromin6(&bind_address, &in6, srcport); 1249 isc_net_disableipv4(); 1250 } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) { 1251 isc_sockaddr_fromin(&bind_address, &in4, srcport); 1252 isc_net_disableipv6(); 1253 } else { 1254 if (hash != NULL) 1255 *hash = '#'; 1256 fatal("invalid address %s", value); 1257 } 1258 if (hash != NULL) 1259 *hash = '#'; 1260 specified_source = ISC_TRUE; 1261 return (value_from_next); 1262 case 'c': 1263 if ((*lookup)->rdclassset) { 1264 fprintf(stderr, ";; Warning, extra class option\n"); 1265 } 1266 *open_type_class = ISC_FALSE; 1267 tr.base = value; 1268 tr.length = strlen(value); 1269 result = dns_rdataclass_fromtext(&rdclass, 1270 (isc_textregion_t *)&tr); 1271 if (result == ISC_R_SUCCESS) { 1272 (*lookup)->rdclass = rdclass; 1273 (*lookup)->rdclassset = ISC_TRUE; 1274 } else 1275 fprintf(stderr, ";; Warning, ignoring " 1276 "invalid class %s\n", 1277 value); 1278 return (value_from_next); 1279 case 'f': 1280 batchname = value; 1281 return (value_from_next); 1282 case 'k': 1283 strncpy(keyfile, value, sizeof(keyfile)); 1284 keyfile[sizeof(keyfile)-1]=0; 1285 return (value_from_next); 1286 case 'p': 1287 result = parse_uint(&num, value, MAXPORT, "port number"); 1288 if (result != ISC_R_SUCCESS) 1289 fatal("Couldn't parse port number"); 1290 port = num; 1291 return (value_from_next); 1292 case 'q': 1293 if (!config_only) { 1294 if (*need_clone) 1295 (*lookup) = clone_lookup(default_lookup, 1296 ISC_TRUE); 1297 *need_clone = ISC_TRUE; 1298 strncpy((*lookup)->textname, value, 1299 sizeof((*lookup)->textname)); 1300 (*lookup)->textname[sizeof((*lookup)->textname)-1]=0; 1301 (*lookup)->trace_root = ISC_TF((*lookup)->trace || 1302 (*lookup)->ns_search_only); 1303 (*lookup)->new_search = ISC_TRUE; 1304 if (*firstarg) { 1305 printgreeting(argc, argv, *lookup); 1306 *firstarg = ISC_FALSE; 1307 } 1308 ISC_LIST_APPEND(lookup_list, (*lookup), link); 1309 debug("looking up %s", (*lookup)->textname); 1310 } 1311 return (value_from_next); 1312 case 't': 1313 *open_type_class = ISC_FALSE; 1314 if (strncasecmp(value, "ixfr=", 5) == 0) { 1315 rdtype = dns_rdatatype_ixfr; 1316 result = ISC_R_SUCCESS; 1317 } else { 1318 tr.base = value; 1319 tr.length = strlen(value); 1320 result = dns_rdatatype_fromtext(&rdtype, 1321 (isc_textregion_t *)&tr); 1322 if (result == ISC_R_SUCCESS && 1323 rdtype == dns_rdatatype_ixfr) { 1324 result = DNS_R_UNKNOWN; 1325 } 1326 } 1327 if (result == ISC_R_SUCCESS) { 1328 if ((*lookup)->rdtypeset) { 1329 fprintf(stderr, ";; Warning, " 1330 "extra type option\n"); 1331 } 1332 if (rdtype == dns_rdatatype_ixfr) { 1333 isc_uint32_t serial; 1334 (*lookup)->rdtype = dns_rdatatype_ixfr; 1335 (*lookup)->rdtypeset = ISC_TRUE; 1336 result = parse_uint(&serial, &value[5], 1337 MAXSERIAL, "serial number"); 1338 if (result != ISC_R_SUCCESS) 1339 fatal("Couldn't parse serial number"); 1340 (*lookup)->ixfr_serial = serial; 1341 (*lookup)->section_question = plusquest; 1342 (*lookup)->comments = pluscomm; 1343 (*lookup)->tcp_mode = ISC_TRUE; 1344 } else { 1345 (*lookup)->rdtype = rdtype; 1346 (*lookup)->rdtypeset = ISC_TRUE; 1347 if (rdtype == dns_rdatatype_axfr) { 1348 (*lookup)->section_question = plusquest; 1349 (*lookup)->comments = pluscomm; 1350 } 1351 (*lookup)->ixfr_serial = ISC_FALSE; 1352 } 1353 } else 1354 fprintf(stderr, ";; Warning, ignoring " 1355 "invalid type %s\n", 1356 value); 1357 return (value_from_next); 1358 case 'y': 1359 ptr = next_token(&value,":"); /* hmac type or name */ 1360 if (ptr == NULL) { 1361 usage(); 1362 } 1363 ptr2 = next_token(&value, ":"); /* name or secret */ 1364 if (ptr2 == NULL) 1365 usage(); 1366 ptr3 = next_token(&value,":"); /* secret or NULL */ 1367 if (ptr3 != NULL) { 1368 parse_hmac(ptr); 1369 ptr = ptr2; 1370 ptr2 = ptr3; 1371 } else { 1372 hmacname = DNS_TSIG_HMACMD5_NAME; 1373 digestbits = 0; 1374 } 1375 strncpy(keynametext, ptr, sizeof(keynametext)); 1376 keynametext[sizeof(keynametext)-1]=0; 1377 strncpy(keysecret, ptr2, sizeof(keysecret)); 1378 keysecret[sizeof(keysecret)-1]=0; 1379 return (value_from_next); 1380 case 'x': 1381 if (*need_clone) 1382 *lookup = clone_lookup(default_lookup, ISC_TRUE); 1383 *need_clone = ISC_TRUE; 1384 if (get_reverse(textname, sizeof(textname), value, 1385 ip6_int, ISC_FALSE) == ISC_R_SUCCESS) { 1386 strncpy((*lookup)->textname, textname, 1387 sizeof((*lookup)->textname)); 1388 debug("looking up %s", (*lookup)->textname); 1389 (*lookup)->trace_root = ISC_TF((*lookup)->trace || 1390 (*lookup)->ns_search_only); 1391 (*lookup)->ip6_int = ip6_int; 1392 if (!(*lookup)->rdtypeset) 1393 (*lookup)->rdtype = dns_rdatatype_ptr; 1394 if (!(*lookup)->rdclassset) 1395 (*lookup)->rdclass = dns_rdataclass_in; 1396 (*lookup)->new_search = ISC_TRUE; 1397 if (*firstarg) { 1398 printgreeting(argc, argv, *lookup); 1399 *firstarg = ISC_FALSE; 1400 } 1401 ISC_LIST_APPEND(lookup_list, *lookup, link); 1402 } else { 1403 fprintf(stderr, "Invalid IP address %s\n", value); 1404 exit(1); 1405 } 1406 return (value_from_next); 1407 invalid_option: 1408 default: 1409 fprintf(stderr, "Invalid option: -%s\n", option); 1410 usage(); 1411 } 1412 /* NOTREACHED */ 1413 return (ISC_FALSE); 1414} 1415 1416/*% 1417 * Because we may be trying to do memory allocation recording, we're going 1418 * to need to parse the arguments for the -m *before* we start the main 1419 * argument parsing routine. 1420 * 1421 * I'd prefer not to have to do this, but I am not quite sure how else to 1422 * fix the problem. Argument parsing in dig involves memory allocation 1423 * by its nature, so it can't be done in the main argument parser. 1424 */ 1425static void 1426preparse_args(int argc, char **argv) { 1427 int rc; 1428 char **rv; 1429 char *option; 1430 1431 rc = argc; 1432 rv = argv; 1433 for (rc--, rv++; rc > 0; rc--, rv++) { 1434 if (rv[0][0] != '-') 1435 continue; 1436 option = &rv[0][1]; 1437 while (strpbrk(option, single_dash_opts) == &option[0]) { 1438 if (option[0] == 'm') { 1439 memdebugging = ISC_TRUE; 1440 isc_mem_debugging = ISC_MEM_DEBUGTRACE | 1441 ISC_MEM_DEBUGRECORD; 1442 return; 1443 } 1444 option = &option[1]; 1445 } 1446 } 1447} 1448 1449static void 1450parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only, 1451 int argc, char **argv) { 1452 isc_result_t result; 1453 isc_textregion_t tr; 1454 isc_boolean_t firstarg = ISC_TRUE; 1455 dig_lookup_t *lookup = NULL; 1456 dns_rdatatype_t rdtype; 1457 dns_rdataclass_t rdclass; 1458 isc_boolean_t open_type_class = ISC_TRUE; 1459 char batchline[MXNAME]; 1460 int bargc; 1461 char *bargv[64]; 1462 int rc; 1463 char **rv; 1464#ifndef NOPOSIX 1465 char *homedir; 1466 char rcfile[256]; 1467#endif 1468 char *input; 1469 int i; 1470 isc_boolean_t need_clone = ISC_TRUE; 1471 1472 /* 1473 * The semantics for parsing the args is a bit complex; if 1474 * we don't have a host yet, make the arg apply globally, 1475 * otherwise make it apply to the latest host. This is 1476 * a bit different than the previous versions, but should 1477 * form a consistent user interface. 1478 * 1479 * First, create a "default lookup" which won't actually be used 1480 * anywhere, except for cloning into new lookups 1481 */ 1482 1483 debug("parse_args()"); 1484 if (!is_batchfile) { 1485 debug("making new lookup"); 1486 default_lookup = make_empty_lookup(); 1487 1488#ifndef NOPOSIX 1489 /* 1490 * Treat ${HOME}/.digrc as a special batchfile 1491 */ 1492 INSIST(batchfp == NULL); 1493 homedir = getenv("HOME"); 1494 if (homedir != NULL) { 1495 unsigned int n; 1496 n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc", 1497 homedir); 1498 if (n < sizeof(rcfile)) 1499 batchfp = fopen(rcfile, "r"); 1500 } 1501 if (batchfp != NULL) { 1502 while (fgets(batchline, sizeof(batchline), 1503 batchfp) != 0) { 1504 debug("config line %s", batchline); 1505 bargc = 1; 1506 input = batchline; 1507 bargv[bargc] = next_token(&input, " \t\r\n"); 1508 while ((bargv[bargc] != NULL) && 1509 (bargc < 62)) { 1510 bargc++; 1511 bargv[bargc] = 1512 next_token(&input, " \t\r\n"); 1513 } 1514 1515 bargv[0] = argv[0]; 1516 argv0 = argv[0]; 1517 1518 for(i = 0; i < bargc; i++) 1519 debug(".digrc argv %d: %s", 1520 i, bargv[i]); 1521 parse_args(ISC_TRUE, ISC_TRUE, bargc, 1522 (char **)bargv); 1523 } 1524 fclose(batchfp); 1525 } 1526#endif 1527 } 1528 1529 if (is_batchfile && !config_only) { 1530 /* Processing '-f batchfile'. */ 1531 lookup = clone_lookup(default_lookup, ISC_TRUE); 1532 need_clone = ISC_FALSE; 1533 } else 1534 lookup = default_lookup; 1535 1536 rc = argc; 1537 rv = argv; 1538 for (rc--, rv++; rc > 0; rc--, rv++) { 1539 debug("main parsing %s", rv[0]); 1540 if (strncmp(rv[0], "%", 1) == 0) 1541 break; 1542 if (strncmp(rv[0], "@", 1) == 0) { 1543 addresscount = getaddresses(lookup, &rv[0][1], NULL); 1544 } else if (rv[0][0] == '+') { 1545 plus_option(&rv[0][1], is_batchfile, 1546 lookup); 1547 } else if (rv[0][0] == '-') { 1548 if (rc <= 1) { 1549 if (dash_option(&rv[0][1], NULL, 1550 &lookup, &open_type_class, 1551 &need_clone, config_only, 1552 argc, argv, &firstarg)) { 1553 rc--; 1554 rv++; 1555 } 1556 } else { 1557 if (dash_option(&rv[0][1], rv[1], 1558 &lookup, &open_type_class, 1559 &need_clone, config_only, 1560 argc, argv, &firstarg)) { 1561 rc--; 1562 rv++; 1563 } 1564 } 1565 } else { 1566 /* 1567 * Anything which isn't an option 1568 */ 1569 if (open_type_class) { 1570 if (strncasecmp(rv[0], "ixfr=", 5) == 0) { 1571 rdtype = dns_rdatatype_ixfr; 1572 result = ISC_R_SUCCESS; 1573 } else { 1574 tr.base = rv[0]; 1575 tr.length = strlen(rv[0]); 1576 result = dns_rdatatype_fromtext(&rdtype, 1577 (isc_textregion_t *)&tr); 1578 if (result == ISC_R_SUCCESS && 1579 rdtype == dns_rdatatype_ixfr) { 1580 fprintf(stderr, ";; Warning, " 1581 "ixfr requires a " 1582 "serial number\n"); 1583 continue; 1584 } 1585 } 1586 if (result == ISC_R_SUCCESS) { 1587 if (lookup->rdtypeset) { 1588 fprintf(stderr, ";; Warning, " 1589 "extra type option\n"); 1590 } 1591 if (rdtype == dns_rdatatype_ixfr) { 1592 isc_uint32_t serial; 1593 lookup->rdtype = 1594 dns_rdatatype_ixfr; 1595 lookup->rdtypeset = ISC_TRUE; 1596 result = parse_uint(&serial, 1597 &rv[0][5], 1598 MAXSERIAL, 1599 "serial number"); 1600 if (result != ISC_R_SUCCESS) 1601 fatal("Couldn't parse " 1602 "serial number"); 1603 lookup->ixfr_serial = serial; 1604 lookup->section_question = 1605 plusquest; 1606 lookup->comments = pluscomm; 1607 lookup->tcp_mode = ISC_TRUE; 1608 } else { 1609 lookup->rdtype = rdtype; 1610 lookup->rdtypeset = ISC_TRUE; 1611 if (rdtype == 1612 dns_rdatatype_axfr) { 1613 lookup->section_question = 1614 plusquest; 1615 lookup->comments = pluscomm; 1616 } 1617 lookup->ixfr_serial = ISC_FALSE; 1618 } 1619 continue; 1620 } 1621 result = dns_rdataclass_fromtext(&rdclass, 1622 (isc_textregion_t *)&tr); 1623 if (result == ISC_R_SUCCESS) { 1624 if (lookup->rdclassset) { 1625 fprintf(stderr, ";; Warning, " 1626 "extra class option\n"); 1627 } 1628 lookup->rdclass = rdclass; 1629 lookup->rdclassset = ISC_TRUE; 1630 continue; 1631 } 1632 } 1633 1634 if (!config_only) { 1635 if (need_clone) 1636 lookup = clone_lookup(default_lookup, 1637 ISC_TRUE); 1638 need_clone = ISC_TRUE; 1639 strncpy(lookup->textname, rv[0], 1640 sizeof(lookup->textname)); 1641 lookup->textname[sizeof(lookup->textname)-1]=0; 1642 lookup->trace_root = ISC_TF(lookup->trace || 1643 lookup->ns_search_only); 1644 lookup->new_search = ISC_TRUE; 1645 if (firstarg) { 1646 printgreeting(argc, argv, lookup); 1647 firstarg = ISC_FALSE; 1648 } 1649 ISC_LIST_APPEND(lookup_list, lookup, link); 1650 debug("looking up %s", lookup->textname); 1651 } 1652 /* XXX Error message */ 1653 } 1654 } 1655 1656 /* 1657 * If we have a batchfile, seed the lookup list with the 1658 * first entry, then trust the callback in dighost_shutdown 1659 * to get the rest 1660 */ 1661 if ((batchname != NULL) && !(is_batchfile)) { 1662 if (strcmp(batchname, "-") == 0) 1663 batchfp = stdin; 1664 else 1665 batchfp = fopen(batchname, "r"); 1666 if (batchfp == NULL) { 1667 perror(batchname); 1668 if (exitcode < 8) 1669 exitcode = 8; 1670 fatal("couldn't open specified batch file"); 1671 } 1672 /* XXX Remove code dup from shutdown code */ 1673 next_line: 1674 if (fgets(batchline, sizeof(batchline), batchfp) != 0) { 1675 bargc = 1; 1676 debug("batch line %s", batchline); 1677 if (batchline[0] == '\r' || batchline[0] == '\n' 1678 || batchline[0] == '#' || batchline[0] == ';') 1679 goto next_line; 1680 input = batchline; 1681 bargv[bargc] = next_token(&input, " \t\r\n"); 1682 while ((bargv[bargc] != NULL) && (bargc < 14)) { 1683 bargc++; 1684 bargv[bargc] = next_token(&input, " \t\r\n"); 1685 } 1686 1687 bargv[0] = argv[0]; 1688 argv0 = argv[0]; 1689 1690 for(i = 0; i < bargc; i++) 1691 debug("batch argv %d: %s", i, bargv[i]); 1692 parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv); 1693 return; 1694 } 1695 return; 1696 } 1697 /* 1698 * If no lookup specified, search for root 1699 */ 1700 if ((lookup_list.head == NULL) && !config_only) { 1701 if (need_clone) 1702 lookup = clone_lookup(default_lookup, ISC_TRUE); 1703 need_clone = ISC_TRUE; 1704 lookup->trace_root = ISC_TF(lookup->trace || 1705 lookup->ns_search_only); 1706 lookup->new_search = ISC_TRUE; 1707 strcpy(lookup->textname, "."); 1708 lookup->rdtype = dns_rdatatype_ns; 1709 lookup->rdtypeset = ISC_TRUE; 1710 if (firstarg) { 1711 printgreeting(argc, argv, lookup); 1712 firstarg = ISC_FALSE; 1713 } 1714 ISC_LIST_APPEND(lookup_list, lookup, link); 1715 } 1716 if (!need_clone) 1717 destroy_lookup(lookup); 1718} 1719 1720/* 1721 * Callback from dighost.c to allow program-specific shutdown code. 1722 * Here, we're possibly reading from a batch file, then shutting down 1723 * for real if there's nothing in the batch file to read. 1724 */ 1725void 1726dighost_shutdown(void) { 1727 char batchline[MXNAME]; 1728 int bargc; 1729 char *bargv[16]; 1730 char *input; 1731 int i; 1732 1733 if (batchname == NULL) { 1734 isc_app_shutdown(); 1735 return; 1736 } 1737 1738 fflush(stdout); 1739 if (feof(batchfp)) { 1740 batchname = NULL; 1741 isc_app_shutdown(); 1742 if (batchfp != stdin) 1743 fclose(batchfp); 1744 return; 1745 } 1746 1747 if (fgets(batchline, sizeof(batchline), batchfp) != 0) { 1748 debug("batch line %s", batchline); 1749 bargc = 1; 1750 input = batchline; 1751 bargv[bargc] = next_token(&input, " \t\r\n"); 1752 while ((bargv[bargc] != NULL) && (bargc < 14)) { 1753 bargc++; 1754 bargv[bargc] = next_token(&input, " \t\r\n"); 1755 } 1756 1757 bargv[0] = argv0; 1758 1759 for(i = 0; i < bargc; i++) 1760 debug("batch argv %d: %s", i, bargv[i]); 1761 parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv); 1762 start_lookup(); 1763 } else { 1764 batchname = NULL; 1765 if (batchfp != stdin) 1766 fclose(batchfp); 1767 isc_app_shutdown(); 1768 return; 1769 } 1770} 1771 1772/*% Main processing routine for dig */ 1773int 1774main(int argc, char **argv) { 1775 isc_result_t result; 1776 1777 ISC_LIST_INIT(lookup_list); 1778 ISC_LIST_INIT(server_list); 1779 ISC_LIST_INIT(search_list); 1780 1781 debug("main()"); 1782 preparse_args(argc, argv); 1783 progname = argv[0]; 1784 result = isc_app_start(); 1785 check_result(result, "isc_app_start"); 1786 setup_libs(); 1787 parse_args(ISC_FALSE, ISC_FALSE, argc, argv); 1788 setup_system(); 1789 if (domainopt[0] != '\0') { 1790 set_search_domain(domainopt); 1791 usesearch = ISC_TRUE; 1792 } 1793 result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); 1794 check_result(result, "isc_app_onrun"); 1795 isc_app_run(); 1796 destroy_lookup(default_lookup); 1797 if (batchname != NULL) { 1798 if (batchfp != stdin) 1799 fclose(batchfp); 1800 batchname = NULL; 1801 } 1802#ifdef DIG_SIGCHASE 1803 clean_trustedkey(); 1804#endif 1805 cancel_all(); 1806 destroy_libs(); 1807 isc_app_finish(); 1808 return (exitcode); 1809} 1810