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