2 * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
18 /* $Id: named-checkzone.c,v 1.61 2010-09-07 23:46:59 tbox Exp $ */
27 #include <isc/commandline.h>
29 #include <isc/entropy.h>
33 #include <isc/socket.h>
34 #include <isc/string.h>
36 #include <isc/timer.h>
40 #include <dns/fixedname.h>
42 #include <dns/masterdump.h>
44 #include <dns/rdataclass.h>
45 #include <dns/rdataset.h>
46 #include <dns/result.h>
47 #include <dns/types.h>
50 #include "check-tool.h"
53 static isc_mem_t *mctx = NULL;
54 static isc_entropy_t *ectx = NULL;
55 dns_zone_t *zone = NULL;
56 dns_zonetype_t zonetype = dns_zone_master;
57 static int dumpzone = 0;
58 static const char *output_filename;
59 static char *prog_name = NULL;
60 static const dns_master_style_t *outputstyle = NULL;
61 static enum { progmode_check, progmode_compile } progmode;
63 #define ERRRET(result, function) \
65 if (result != ISC_R_SUCCESS) { \
67 fprintf(stderr, "%s() returned %s\n", \
68 function, dns_result_totext(result)); \
73 ISC_PLATFORM_NORETURN_PRE static void
74 usage(void) ISC_PLATFORM_NORETURN_POST;
79 "usage: %s [-djqvD] [-c class] "
80 "[-f inputformat] [-F outputformat] "
81 "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
82 "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
83 "[-r (ignore|warn|fail)] "
84 "[-i (full|full-sibling|local|local-sibling|none)] "
85 "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
87 "%s zonename filename\n",
89 progmode == progmode_check ? "[-o filename]" : "-o filename");
96 dns_zone_detach(&zone);
100 /*% main processing routine */
102 main(int argc, char **argv) {
105 char *filename = NULL;
106 isc_log_t *lctx = NULL;
108 char classname_in[] = "IN";
109 char *classname = classname_in;
110 const char *workdir = NULL;
111 const char *inputformatstr = NULL;
112 const char *outputformatstr = NULL;
113 dns_masterformat_t inputformat = dns_masterformat_text;
114 dns_masterformat_t outputformat = dns_masterformat_text;
115 FILE *errout = stdout;
117 outputstyle = &dns_master_style_full;
119 prog_name = strrchr(argv[0], '/');
120 if (prog_name == NULL)
121 prog_name = strrchr(argv[0], '\\');
122 if (prog_name != NULL)
127 * Libtool doesn't preserve the program name prior to final
128 * installation. Remove the libtool prefix ("lt-").
130 if (strncmp(prog_name, "lt-", 3) == 0)
134 (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
136 if (PROGCMP("named-checkzone"))
137 progmode = progmode_check;
138 else if (PROGCMP("named-compilezone"))
139 progmode = progmode_compile;
143 /* Compilation specific defaults */
144 if (progmode == progmode_compile) {
145 zone_options |= (DNS_ZONEOPT_CHECKNS |
146 DNS_ZONEOPT_FATALNS |
147 DNS_ZONEOPT_CHECKDUPRR |
148 DNS_ZONEOPT_CHECKNAMES |
149 DNS_ZONEOPT_CHECKNAMESFAIL |
150 DNS_ZONEOPT_CHECKWILDCARD);
152 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
154 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
156 isc_commandline_errprint = ISC_FALSE;
158 while ((c = isc_commandline_parse(argc, argv,
159 "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:W:"))
163 classname = isc_commandline_argument;
171 if (ARGCMP("full")) {
172 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
173 DNS_ZONEOPT_CHECKSIBLING;
174 docheckmx = ISC_TRUE;
175 docheckns = ISC_TRUE;
176 dochecksrv = ISC_TRUE;
177 } else if (ARGCMP("full-sibling")) {
178 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
179 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
180 docheckmx = ISC_TRUE;
181 docheckns = ISC_TRUE;
182 dochecksrv = ISC_TRUE;
183 } else if (ARGCMP("local")) {
184 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
185 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
186 docheckmx = ISC_FALSE;
187 docheckns = ISC_FALSE;
188 dochecksrv = ISC_FALSE;
189 } else if (ARGCMP("local-sibling")) {
190 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
191 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
192 docheckmx = ISC_FALSE;
193 docheckns = ISC_FALSE;
194 dochecksrv = ISC_FALSE;
195 } else if (ARGCMP("none")) {
196 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
197 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
198 docheckmx = ISC_FALSE;
199 docheckns = ISC_FALSE;
200 dochecksrv = ISC_FALSE;
202 fprintf(stderr, "invalid argument to -i: %s\n",
203 isc_commandline_argument);
209 inputformatstr = isc_commandline_argument;
213 outputformatstr = isc_commandline_argument;
221 if (ARGCMP("warn")) {
222 zone_options |= DNS_ZONEOPT_CHECKNAMES;
223 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
224 } else if (ARGCMP("fail")) {
225 zone_options |= DNS_ZONEOPT_CHECKNAMES |
226 DNS_ZONEOPT_CHECKNAMESFAIL;
227 } else if (ARGCMP("ignore")) {
228 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
229 DNS_ZONEOPT_CHECKNAMESFAIL);
231 fprintf(stderr, "invalid argument to -k: %s\n",
232 isc_commandline_argument);
238 if (ARGCMP("ignore")) {
239 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
240 DNS_ZONEOPT_FATALNS);
241 } else if (ARGCMP("warn")) {
242 zone_options |= DNS_ZONEOPT_CHECKNS;
243 zone_options &= ~DNS_ZONEOPT_FATALNS;
244 } else if (ARGCMP("fail")) {
245 zone_options |= DNS_ZONEOPT_CHECKNS|
248 fprintf(stderr, "invalid argument to -n: %s\n",
249 isc_commandline_argument);
255 if (ARGCMP("warn")) {
256 zone_options |= DNS_ZONEOPT_CHECKMX;
257 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
258 } else if (ARGCMP("fail")) {
259 zone_options |= DNS_ZONEOPT_CHECKMX |
260 DNS_ZONEOPT_CHECKMXFAIL;
261 } else if (ARGCMP("ignore")) {
262 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
263 DNS_ZONEOPT_CHECKMXFAIL);
265 fprintf(stderr, "invalid argument to -m: %s\n",
266 isc_commandline_argument);
272 output_filename = isc_commandline_argument;
280 if (ARGCMP("warn")) {
281 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
282 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
283 } else if (ARGCMP("fail")) {
284 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
285 DNS_ZONEOPT_CHECKDUPRRFAIL;
286 } else if (ARGCMP("ignore")) {
287 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
288 DNS_ZONEOPT_CHECKDUPRRFAIL);
290 fprintf(stderr, "invalid argument to -r: %s\n",
291 isc_commandline_argument);
298 outputstyle = &dns_master_style_full;
299 else if (ARGCMP("relative")) {
300 outputstyle = &dns_master_style_default;
303 "unknown or unsupported style: %s\n",
304 isc_commandline_argument);
310 result = isc_dir_chroot(isc_commandline_argument);
311 if (result != ISC_R_SUCCESS) {
312 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
313 isc_commandline_argument,
314 isc_result_totext(result));
320 printf(VERSION "\n");
324 workdir = isc_commandline_argument;
332 if (ARGCMP("fail")) {
333 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
334 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
335 } else if (ARGCMP("warn")) {
336 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
337 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
338 } else if (ARGCMP("ignore")) {
339 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
340 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
342 fprintf(stderr, "invalid argument to -M: %s\n",
343 isc_commandline_argument);
349 if (ARGCMP("fail")) {
350 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
351 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
352 } else if (ARGCMP("warn")) {
353 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
354 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
355 } else if (ARGCMP("ignore")) {
356 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
357 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
359 fprintf(stderr, "invalid argument to -S: %s\n",
360 isc_commandline_argument);
367 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
368 else if (ARGCMP("ignore"))
369 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
373 if (isc_commandline_option != '?')
374 fprintf(stderr, "%s: invalid argument -%c\n",
375 prog_name, isc_commandline_option);
380 fprintf(stderr, "%s: unhandled option -%c\n",
381 prog_name, isc_commandline_option);
386 if (workdir != NULL) {
387 result = isc_dir_chdir(workdir);
388 if (result != ISC_R_SUCCESS) {
389 fprintf(stderr, "isc_dir_chdir: %s: %s\n",
390 workdir, isc_result_totext(result));
395 if (inputformatstr != NULL) {
396 if (strcasecmp(inputformatstr, "text") == 0)
397 inputformat = dns_masterformat_text;
398 else if (strcasecmp(inputformatstr, "raw") == 0)
399 inputformat = dns_masterformat_raw;
401 fprintf(stderr, "unknown file format: %s\n",
407 if (outputformatstr != NULL) {
408 if (strcasecmp(outputformatstr, "text") == 0)
409 outputformat = dns_masterformat_text;
410 else if (strcasecmp(outputformatstr, "raw") == 0)
411 outputformat = dns_masterformat_raw;
413 fprintf(stderr, "unknown file format: %s\n",
419 if (progmode == progmode_compile) {
420 dumpzone = 1; /* always dump */
421 if (output_filename == NULL) {
423 "output file required, but not specified\n");
428 if (output_filename != NULL)
432 * If we are outputing to stdout then send the informational
436 (output_filename == NULL ||
437 strcmp(output_filename, "-") == 0 ||
438 strcmp(output_filename, "/dev/fd/1") == 0 ||
439 strcmp(output_filename, "/dev/stdout") == 0))
442 if (isc_commandline_index + 2 != argc)
449 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
451 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
453 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
454 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
457 dns_result_register();
459 origin = argv[isc_commandline_index++];
460 filename = argv[isc_commandline_index++];
461 result = load_zone(mctx, origin, filename, inputformat, classname,
464 if (result == ISC_R_SUCCESS && dumpzone) {
465 if (!quiet && progmode == progmode_compile) {
466 fprintf(errout, "dump zone to %s...", output_filename);
469 result = dump_zone(origin, zone, output_filename,
470 outputformat, outputstyle);
471 if (!quiet && progmode == progmode_compile)
472 fprintf(errout, "done\n");
475 if (!quiet && result == ISC_R_SUCCESS)
476 fprintf(errout, "OK\n");
479 isc_log_destroy(&lctx);
481 isc_entropy_detach(&ectx);
482 isc_mem_destroy(&mctx);
486 return ((result == ISC_R_SUCCESS) ? 0 : 1);