/contrib/bind9/bin/check/named-checkzone.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 491 lines · 408 code · 55 blank · 28 comment · 131 complexity · e2d01eb47c34f1a7c541271ee08e71b3 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-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: named-checkzone.c,v 1.61.62.2 2011/12/22 23:45:54 tbox Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <stdlib.h>
  21. #include <isc/app.h>
  22. #include <isc/commandline.h>
  23. #include <isc/dir.h>
  24. #include <isc/entropy.h>
  25. #include <isc/hash.h>
  26. #include <isc/log.h>
  27. #include <isc/mem.h>
  28. #include <isc/socket.h>
  29. #include <isc/string.h>
  30. #include <isc/task.h>
  31. #include <isc/timer.h>
  32. #include <isc/util.h>
  33. #include <dns/db.h>
  34. #include <dns/fixedname.h>
  35. #include <dns/log.h>
  36. #include <dns/masterdump.h>
  37. #include <dns/name.h>
  38. #include <dns/rdataclass.h>
  39. #include <dns/rdataset.h>
  40. #include <dns/result.h>
  41. #include <dns/types.h>
  42. #include <dns/zone.h>
  43. #include "check-tool.h"
  44. static int quiet = 0;
  45. static isc_mem_t *mctx = NULL;
  46. static isc_entropy_t *ectx = NULL;
  47. dns_zone_t *zone = NULL;
  48. dns_zonetype_t zonetype = dns_zone_master;
  49. static int dumpzone = 0;
  50. static const char *output_filename;
  51. static char *prog_name = NULL;
  52. static const dns_master_style_t *outputstyle = NULL;
  53. static enum { progmode_check, progmode_compile } progmode;
  54. #define ERRRET(result, function) \
  55. do { \
  56. if (result != ISC_R_SUCCESS) { \
  57. if (!quiet) \
  58. fprintf(stderr, "%s() returned %s\n", \
  59. function, dns_result_totext(result)); \
  60. return (result); \
  61. } \
  62. } while (0)
  63. ISC_PLATFORM_NORETURN_PRE static void
  64. usage(void) ISC_PLATFORM_NORETURN_POST;
  65. static void
  66. usage(void) {
  67. fprintf(stderr,
  68. "usage: %s [-djqvD] [-c class] "
  69. "[-f inputformat] [-F outputformat] "
  70. "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
  71. "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
  72. "[-r (ignore|warn|fail)] "
  73. "[-i (full|full-sibling|local|local-sibling|none)] "
  74. "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
  75. "[-W (ignore|warn)] "
  76. "%s zonename filename\n",
  77. prog_name,
  78. progmode == progmode_check ? "[-o filename]" : "-o filename");
  79. exit(1);
  80. }
  81. static void
  82. destroy(void) {
  83. if (zone != NULL)
  84. dns_zone_detach(&zone);
  85. dns_name_destroy();
  86. }
  87. /*% main processing routine */
  88. int
  89. main(int argc, char **argv) {
  90. int c;
  91. char *origin = NULL;
  92. char *filename = NULL;
  93. isc_log_t *lctx = NULL;
  94. isc_result_t result;
  95. char classname_in[] = "IN";
  96. char *classname = classname_in;
  97. const char *workdir = NULL;
  98. const char *inputformatstr = NULL;
  99. const char *outputformatstr = NULL;
  100. dns_masterformat_t inputformat = dns_masterformat_text;
  101. dns_masterformat_t outputformat = dns_masterformat_text;
  102. isc_boolean_t logdump = ISC_FALSE;
  103. FILE *errout = stdout;
  104. outputstyle = &dns_master_style_full;
  105. prog_name = strrchr(argv[0], '/');
  106. if (prog_name == NULL)
  107. prog_name = strrchr(argv[0], '\\');
  108. if (prog_name != NULL)
  109. prog_name++;
  110. else
  111. prog_name = argv[0];
  112. /*
  113. * Libtool doesn't preserve the program name prior to final
  114. * installation. Remove the libtool prefix ("lt-").
  115. */
  116. if (strncmp(prog_name, "lt-", 3) == 0)
  117. prog_name += 3;
  118. #define PROGCMP(X) \
  119. (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
  120. if (PROGCMP("named-checkzone"))
  121. progmode = progmode_check;
  122. else if (PROGCMP("named-compilezone"))
  123. progmode = progmode_compile;
  124. else
  125. INSIST(0);
  126. /* Compilation specific defaults */
  127. if (progmode == progmode_compile) {
  128. zone_options |= (DNS_ZONEOPT_CHECKNS |
  129. DNS_ZONEOPT_FATALNS |
  130. DNS_ZONEOPT_CHECKDUPRR |
  131. DNS_ZONEOPT_CHECKNAMES |
  132. DNS_ZONEOPT_CHECKNAMESFAIL |
  133. DNS_ZONEOPT_CHECKWILDCARD);
  134. } else
  135. zone_options |= DNS_ZONEOPT_CHECKDUPRR;
  136. #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
  137. isc_commandline_errprint = ISC_FALSE;
  138. while ((c = isc_commandline_parse(argc, argv,
  139. "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:W:"))
  140. != EOF) {
  141. switch (c) {
  142. case 'c':
  143. classname = isc_commandline_argument;
  144. break;
  145. case 'd':
  146. debug++;
  147. break;
  148. case 'i':
  149. if (ARGCMP("full")) {
  150. zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
  151. DNS_ZONEOPT_CHECKSIBLING;
  152. docheckmx = ISC_TRUE;
  153. docheckns = ISC_TRUE;
  154. dochecksrv = ISC_TRUE;
  155. } else if (ARGCMP("full-sibling")) {
  156. zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
  157. zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
  158. docheckmx = ISC_TRUE;
  159. docheckns = ISC_TRUE;
  160. dochecksrv = ISC_TRUE;
  161. } else if (ARGCMP("local")) {
  162. zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
  163. zone_options |= DNS_ZONEOPT_CHECKSIBLING;
  164. docheckmx = ISC_FALSE;
  165. docheckns = ISC_FALSE;
  166. dochecksrv = ISC_FALSE;
  167. } else if (ARGCMP("local-sibling")) {
  168. zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
  169. zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
  170. docheckmx = ISC_FALSE;
  171. docheckns = ISC_FALSE;
  172. dochecksrv = ISC_FALSE;
  173. } else if (ARGCMP("none")) {
  174. zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
  175. zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
  176. docheckmx = ISC_FALSE;
  177. docheckns = ISC_FALSE;
  178. dochecksrv = ISC_FALSE;
  179. } else {
  180. fprintf(stderr, "invalid argument to -i: %s\n",
  181. isc_commandline_argument);
  182. exit(1);
  183. }
  184. break;
  185. case 'f':
  186. inputformatstr = isc_commandline_argument;
  187. break;
  188. case 'F':
  189. outputformatstr = isc_commandline_argument;
  190. break;
  191. case 'j':
  192. nomerge = ISC_FALSE;
  193. break;
  194. case 'k':
  195. if (ARGCMP("warn")) {
  196. zone_options |= DNS_ZONEOPT_CHECKNAMES;
  197. zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
  198. } else if (ARGCMP("fail")) {
  199. zone_options |= DNS_ZONEOPT_CHECKNAMES |
  200. DNS_ZONEOPT_CHECKNAMESFAIL;
  201. } else if (ARGCMP("ignore")) {
  202. zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
  203. DNS_ZONEOPT_CHECKNAMESFAIL);
  204. } else {
  205. fprintf(stderr, "invalid argument to -k: %s\n",
  206. isc_commandline_argument);
  207. exit(1);
  208. }
  209. break;
  210. case 'n':
  211. if (ARGCMP("ignore")) {
  212. zone_options &= ~(DNS_ZONEOPT_CHECKNS|
  213. DNS_ZONEOPT_FATALNS);
  214. } else if (ARGCMP("warn")) {
  215. zone_options |= DNS_ZONEOPT_CHECKNS;
  216. zone_options &= ~DNS_ZONEOPT_FATALNS;
  217. } else if (ARGCMP("fail")) {
  218. zone_options |= DNS_ZONEOPT_CHECKNS|
  219. DNS_ZONEOPT_FATALNS;
  220. } else {
  221. fprintf(stderr, "invalid argument to -n: %s\n",
  222. isc_commandline_argument);
  223. exit(1);
  224. }
  225. break;
  226. case 'm':
  227. if (ARGCMP("warn")) {
  228. zone_options |= DNS_ZONEOPT_CHECKMX;
  229. zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
  230. } else if (ARGCMP("fail")) {
  231. zone_options |= DNS_ZONEOPT_CHECKMX |
  232. DNS_ZONEOPT_CHECKMXFAIL;
  233. } else if (ARGCMP("ignore")) {
  234. zone_options &= ~(DNS_ZONEOPT_CHECKMX |
  235. DNS_ZONEOPT_CHECKMXFAIL);
  236. } else {
  237. fprintf(stderr, "invalid argument to -m: %s\n",
  238. isc_commandline_argument);
  239. exit(1);
  240. }
  241. break;
  242. case 'o':
  243. output_filename = isc_commandline_argument;
  244. break;
  245. case 'q':
  246. quiet++;
  247. break;
  248. case 'r':
  249. if (ARGCMP("warn")) {
  250. zone_options |= DNS_ZONEOPT_CHECKDUPRR;
  251. zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
  252. } else if (ARGCMP("fail")) {
  253. zone_options |= DNS_ZONEOPT_CHECKDUPRR |
  254. DNS_ZONEOPT_CHECKDUPRRFAIL;
  255. } else if (ARGCMP("ignore")) {
  256. zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
  257. DNS_ZONEOPT_CHECKDUPRRFAIL);
  258. } else {
  259. fprintf(stderr, "invalid argument to -r: %s\n",
  260. isc_commandline_argument);
  261. exit(1);
  262. }
  263. break;
  264. case 's':
  265. if (ARGCMP("full"))
  266. outputstyle = &dns_master_style_full;
  267. else if (ARGCMP("relative")) {
  268. outputstyle = &dns_master_style_default;
  269. } else {
  270. fprintf(stderr,
  271. "unknown or unsupported style: %s\n",
  272. isc_commandline_argument);
  273. exit(1);
  274. }
  275. break;
  276. case 't':
  277. result = isc_dir_chroot(isc_commandline_argument);
  278. if (result != ISC_R_SUCCESS) {
  279. fprintf(stderr, "isc_dir_chroot: %s: %s\n",
  280. isc_commandline_argument,
  281. isc_result_totext(result));
  282. exit(1);
  283. }
  284. break;
  285. case 'v':
  286. printf(VERSION "\n");
  287. exit(0);
  288. case 'w':
  289. workdir = isc_commandline_argument;
  290. break;
  291. case 'D':
  292. dumpzone++;
  293. break;
  294. case 'M':
  295. if (ARGCMP("fail")) {
  296. zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
  297. zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
  298. } else if (ARGCMP("warn")) {
  299. zone_options |= DNS_ZONEOPT_WARNMXCNAME;
  300. zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
  301. } else if (ARGCMP("ignore")) {
  302. zone_options |= DNS_ZONEOPT_WARNMXCNAME;
  303. zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
  304. } else {
  305. fprintf(stderr, "invalid argument to -M: %s\n",
  306. isc_commandline_argument);
  307. exit(1);
  308. }
  309. break;
  310. case 'S':
  311. if (ARGCMP("fail")) {
  312. zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
  313. zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
  314. } else if (ARGCMP("warn")) {
  315. zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
  316. zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
  317. } else if (ARGCMP("ignore")) {
  318. zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
  319. zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
  320. } else {
  321. fprintf(stderr, "invalid argument to -S: %s\n",
  322. isc_commandline_argument);
  323. exit(1);
  324. }
  325. break;
  326. case 'W':
  327. if (ARGCMP("warn"))
  328. zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
  329. else if (ARGCMP("ignore"))
  330. zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
  331. break;
  332. case '?':
  333. if (isc_commandline_option != '?')
  334. fprintf(stderr, "%s: invalid argument -%c\n",
  335. prog_name, isc_commandline_option);
  336. case 'h':
  337. usage();
  338. default:
  339. fprintf(stderr, "%s: unhandled option -%c\n",
  340. prog_name, isc_commandline_option);
  341. exit(1);
  342. }
  343. }
  344. if (workdir != NULL) {
  345. result = isc_dir_chdir(workdir);
  346. if (result != ISC_R_SUCCESS) {
  347. fprintf(stderr, "isc_dir_chdir: %s: %s\n",
  348. workdir, isc_result_totext(result));
  349. exit(1);
  350. }
  351. }
  352. if (inputformatstr != NULL) {
  353. if (strcasecmp(inputformatstr, "text") == 0)
  354. inputformat = dns_masterformat_text;
  355. else if (strcasecmp(inputformatstr, "raw") == 0)
  356. inputformat = dns_masterformat_raw;
  357. else {
  358. fprintf(stderr, "unknown file format: %s\n",
  359. inputformatstr);
  360. exit(1);
  361. }
  362. }
  363. if (outputformatstr != NULL) {
  364. if (strcasecmp(outputformatstr, "text") == 0)
  365. outputformat = dns_masterformat_text;
  366. else if (strcasecmp(outputformatstr, "raw") == 0)
  367. outputformat = dns_masterformat_raw;
  368. else {
  369. fprintf(stderr, "unknown file format: %s\n",
  370. outputformatstr);
  371. exit(1);
  372. }
  373. }
  374. if (progmode == progmode_compile) {
  375. dumpzone = 1; /* always dump */
  376. logdump = !quiet;
  377. if (output_filename == NULL) {
  378. fprintf(stderr,
  379. "output file required, but not specified\n");
  380. usage();
  381. }
  382. }
  383. if (output_filename != NULL)
  384. dumpzone = 1;
  385. /*
  386. * If we are outputing to stdout then send the informational
  387. * output to stderr.
  388. */
  389. if (dumpzone &&
  390. (output_filename == NULL ||
  391. strcmp(output_filename, "-") == 0 ||
  392. strcmp(output_filename, "/dev/fd/1") == 0 ||
  393. strcmp(output_filename, "/dev/stdout") == 0)) {
  394. errout = stderr;
  395. logdump = ISC_FALSE;
  396. }
  397. if (isc_commandline_index + 2 != argc)
  398. usage();
  399. #ifdef _WIN32
  400. InitSockets();
  401. #endif
  402. RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
  403. if (!quiet)
  404. RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
  405. == ISC_R_SUCCESS);
  406. RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
  407. RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
  408. == ISC_R_SUCCESS);
  409. dns_result_register();
  410. origin = argv[isc_commandline_index++];
  411. filename = argv[isc_commandline_index++];
  412. result = load_zone(mctx, origin, filename, inputformat, classname,
  413. &zone);
  414. if (result == ISC_R_SUCCESS && dumpzone) {
  415. if (logdump) {
  416. fprintf(errout, "dump zone to %s...", output_filename);
  417. fflush(errout);
  418. }
  419. result = dump_zone(origin, zone, output_filename,
  420. outputformat, outputstyle);
  421. if (logdump)
  422. fprintf(errout, "done\n");
  423. }
  424. if (!quiet && result == ISC_R_SUCCESS)
  425. fprintf(errout, "OK\n");
  426. destroy();
  427. if (lctx != NULL)
  428. isc_log_destroy(&lctx);
  429. isc_hash_destroy();
  430. isc_entropy_detach(&ectx);
  431. isc_mem_destroy(&mctx);
  432. #ifdef _WIN32
  433. DestroySockets();
  434. #endif
  435. return ((result == ISC_R_SUCCESS) ? 0 : 1);
  436. }