/contrib/bind9/bin/dig/host.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 884 lines · 778 code · 73 blank · 33 comment · 149 complexity · 81f3762451f4100d0055f8a639c5ff30 MD5 · raw file

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