2 * Copyright (C) 2004-2011 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.62.2 2011/12/22 23:45:54 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 isc_boolean_t logdump = ISC_FALSE;
116 FILE *errout = stdout;
118 outputstyle = &dns_master_style_full;
120 prog_name = strrchr(argv[0], '/');
121 if (prog_name == NULL)
122 prog_name = strrchr(argv[0], '\\');
123 if (prog_name != NULL)
128 * Libtool doesn't preserve the program name prior to final
129 * installation. Remove the libtool prefix ("lt-").
131 if (strncmp(prog_name, "lt-", 3) == 0)
135 (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
137 if (PROGCMP("named-checkzone"))
138 progmode = progmode_check;
139 else if (PROGCMP("named-compilezone"))
140 progmode = progmode_compile;
144 /* Compilation specific defaults */
145 if (progmode == progmode_compile) {
146 zone_options |= (DNS_ZONEOPT_CHECKNS |
147 DNS_ZONEOPT_FATALNS |
148 DNS_ZONEOPT_CHECKDUPRR |
149 DNS_ZONEOPT_CHECKNAMES |
150 DNS_ZONEOPT_CHECKNAMESFAIL |
151 DNS_ZONEOPT_CHECKWILDCARD);
153 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
155 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
157 isc_commandline_errprint = ISC_FALSE;
159 while ((c = isc_commandline_parse(argc, argv,
160 "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:W:"))
164 classname = isc_commandline_argument;
172 if (ARGCMP("full")) {
173 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
174 DNS_ZONEOPT_CHECKSIBLING;
175 docheckmx = ISC_TRUE;
176 docheckns = ISC_TRUE;
177 dochecksrv = ISC_TRUE;
178 } else if (ARGCMP("full-sibling")) {
179 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
180 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
181 docheckmx = ISC_TRUE;
182 docheckns = ISC_TRUE;
183 dochecksrv = ISC_TRUE;
184 } else if (ARGCMP("local")) {
185 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
186 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
187 docheckmx = ISC_FALSE;
188 docheckns = ISC_FALSE;
189 dochecksrv = ISC_FALSE;
190 } else if (ARGCMP("local-sibling")) {
191 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
192 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
193 docheckmx = ISC_FALSE;
194 docheckns = ISC_FALSE;
195 dochecksrv = ISC_FALSE;
196 } else if (ARGCMP("none")) {
197 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
198 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
199 docheckmx = ISC_FALSE;
200 docheckns = ISC_FALSE;
201 dochecksrv = ISC_FALSE;
203 fprintf(stderr, "invalid argument to -i: %s\n",
204 isc_commandline_argument);
210 inputformatstr = isc_commandline_argument;
214 outputformatstr = isc_commandline_argument;
222 if (ARGCMP("warn")) {
223 zone_options |= DNS_ZONEOPT_CHECKNAMES;
224 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
225 } else if (ARGCMP("fail")) {
226 zone_options |= DNS_ZONEOPT_CHECKNAMES |
227 DNS_ZONEOPT_CHECKNAMESFAIL;
228 } else if (ARGCMP("ignore")) {
229 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
230 DNS_ZONEOPT_CHECKNAMESFAIL);
232 fprintf(stderr, "invalid argument to -k: %s\n",
233 isc_commandline_argument);
239 if (ARGCMP("ignore")) {
240 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
241 DNS_ZONEOPT_FATALNS);
242 } else if (ARGCMP("warn")) {
243 zone_options |= DNS_ZONEOPT_CHECKNS;
244 zone_options &= ~DNS_ZONEOPT_FATALNS;
245 } else if (ARGCMP("fail")) {
246 zone_options |= DNS_ZONEOPT_CHECKNS|
249 fprintf(stderr, "invalid argument to -n: %s\n",
250 isc_commandline_argument);
256 if (ARGCMP("warn")) {
257 zone_options |= DNS_ZONEOPT_CHECKMX;
258 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
259 } else if (ARGCMP("fail")) {
260 zone_options |= DNS_ZONEOPT_CHECKMX |
261 DNS_ZONEOPT_CHECKMXFAIL;
262 } else if (ARGCMP("ignore")) {
263 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
264 DNS_ZONEOPT_CHECKMXFAIL);
266 fprintf(stderr, "invalid argument to -m: %s\n",
267 isc_commandline_argument);
273 output_filename = isc_commandline_argument;
281 if (ARGCMP("warn")) {
282 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
283 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
284 } else if (ARGCMP("fail")) {
285 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
286 DNS_ZONEOPT_CHECKDUPRRFAIL;
287 } else if (ARGCMP("ignore")) {
288 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
289 DNS_ZONEOPT_CHECKDUPRRFAIL);
291 fprintf(stderr, "invalid argument to -r: %s\n",
292 isc_commandline_argument);
299 outputstyle = &dns_master_style_full;
300 else if (ARGCMP("relative")) {
301 outputstyle = &dns_master_style_default;
304 "unknown or unsupported style: %s\n",
305 isc_commandline_argument);
311 result = isc_dir_chroot(isc_commandline_argument);
312 if (result != ISC_R_SUCCESS) {
313 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
314 isc_commandline_argument,
315 isc_result_totext(result));
321 printf(VERSION "\n");
325 workdir = isc_commandline_argument;
333 if (ARGCMP("fail")) {
334 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
335 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
336 } else if (ARGCMP("warn")) {
337 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
338 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
339 } else if (ARGCMP("ignore")) {
340 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
341 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
343 fprintf(stderr, "invalid argument to -M: %s\n",
344 isc_commandline_argument);
350 if (ARGCMP("fail")) {
351 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
352 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
353 } else if (ARGCMP("warn")) {
354 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
355 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
356 } else if (ARGCMP("ignore")) {
357 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
358 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
360 fprintf(stderr, "invalid argument to -S: %s\n",
361 isc_commandline_argument);
368 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
369 else if (ARGCMP("ignore"))
370 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
374 if (isc_commandline_option != '?')
375 fprintf(stderr, "%s: invalid argument -%c\n",
376 prog_name, isc_commandline_option);
381 fprintf(stderr, "%s: unhandled option -%c\n",
382 prog_name, isc_commandline_option);
387 if (workdir != NULL) {
388 result = isc_dir_chdir(workdir);
389 if (result != ISC_R_SUCCESS) {
390 fprintf(stderr, "isc_dir_chdir: %s: %s\n",
391 workdir, isc_result_totext(result));
396 if (inputformatstr != NULL) {
397 if (strcasecmp(inputformatstr, "text") == 0)
398 inputformat = dns_masterformat_text;
399 else if (strcasecmp(inputformatstr, "raw") == 0)
400 inputformat = dns_masterformat_raw;
402 fprintf(stderr, "unknown file format: %s\n",
408 if (outputformatstr != NULL) {
409 if (strcasecmp(outputformatstr, "text") == 0)
410 outputformat = dns_masterformat_text;
411 else if (strcasecmp(outputformatstr, "raw") == 0)
412 outputformat = dns_masterformat_raw;
414 fprintf(stderr, "unknown file format: %s\n",
420 if (progmode == progmode_compile) {
421 dumpzone = 1; /* always dump */
423 if (output_filename == NULL) {
425 "output file required, but not specified\n");
430 if (output_filename != NULL)
434 * If we are outputing to stdout then send the informational
438 (output_filename == NULL ||
439 strcmp(output_filename, "-") == 0 ||
440 strcmp(output_filename, "/dev/fd/1") == 0 ||
441 strcmp(output_filename, "/dev/stdout") == 0)) {
446 if (isc_commandline_index + 2 != argc)
453 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
455 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
457 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
458 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
461 dns_result_register();
463 origin = argv[isc_commandline_index++];
464 filename = argv[isc_commandline_index++];
465 result = load_zone(mctx, origin, filename, inputformat, classname,
468 if (result == ISC_R_SUCCESS && dumpzone) {
470 fprintf(errout, "dump zone to %s...", output_filename);
473 result = dump_zone(origin, zone, output_filename,
474 outputformat, outputstyle);
476 fprintf(errout, "done\n");
479 if (!quiet && result == ISC_R_SUCCESS)
480 fprintf(errout, "OK\n");
483 isc_log_destroy(&lctx);
485 isc_entropy_detach(&ectx);
486 isc_mem_destroy(&mctx);
490 return ((result == ISC_R_SUCCESS) ? 0 : 1);