2 * Copyright (C) 2004-2013 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_CHECKSPF |
149 DNS_ZONEOPT_CHECKDUPRR |
150 DNS_ZONEOPT_CHECKNAMES |
151 DNS_ZONEOPT_CHECKNAMESFAIL |
152 DNS_ZONEOPT_CHECKWILDCARD);
154 zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
155 DNS_ZONEOPT_CHECKSPF);
157 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
159 isc_commandline_errprint = ISC_FALSE;
161 while ((c = isc_commandline_parse(argc, argv,
162 "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
166 classname = isc_commandline_argument;
174 if (ARGCMP("full")) {
175 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
176 DNS_ZONEOPT_CHECKSIBLING;
177 docheckmx = ISC_TRUE;
178 docheckns = ISC_TRUE;
179 dochecksrv = ISC_TRUE;
180 } else if (ARGCMP("full-sibling")) {
181 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
182 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
183 docheckmx = ISC_TRUE;
184 docheckns = ISC_TRUE;
185 dochecksrv = ISC_TRUE;
186 } else if (ARGCMP("local")) {
187 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
188 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
189 docheckmx = ISC_FALSE;
190 docheckns = ISC_FALSE;
191 dochecksrv = ISC_FALSE;
192 } else if (ARGCMP("local-sibling")) {
193 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
194 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
195 docheckmx = ISC_FALSE;
196 docheckns = ISC_FALSE;
197 dochecksrv = ISC_FALSE;
198 } else if (ARGCMP("none")) {
199 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
200 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
201 docheckmx = ISC_FALSE;
202 docheckns = ISC_FALSE;
203 dochecksrv = ISC_FALSE;
205 fprintf(stderr, "invalid argument to -i: %s\n",
206 isc_commandline_argument);
212 inputformatstr = isc_commandline_argument;
216 outputformatstr = isc_commandline_argument;
224 if (ARGCMP("warn")) {
225 zone_options |= DNS_ZONEOPT_CHECKNAMES;
226 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
227 } else if (ARGCMP("fail")) {
228 zone_options |= DNS_ZONEOPT_CHECKNAMES |
229 DNS_ZONEOPT_CHECKNAMESFAIL;
230 } else if (ARGCMP("ignore")) {
231 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
232 DNS_ZONEOPT_CHECKNAMESFAIL);
234 fprintf(stderr, "invalid argument to -k: %s\n",
235 isc_commandline_argument);
241 if (ARGCMP("ignore")) {
242 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
243 DNS_ZONEOPT_FATALNS);
244 } else if (ARGCMP("warn")) {
245 zone_options |= DNS_ZONEOPT_CHECKNS;
246 zone_options &= ~DNS_ZONEOPT_FATALNS;
247 } else if (ARGCMP("fail")) {
248 zone_options |= DNS_ZONEOPT_CHECKNS|
251 fprintf(stderr, "invalid argument to -n: %s\n",
252 isc_commandline_argument);
258 if (ARGCMP("warn")) {
259 zone_options |= DNS_ZONEOPT_CHECKMX;
260 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
261 } else if (ARGCMP("fail")) {
262 zone_options |= DNS_ZONEOPT_CHECKMX |
263 DNS_ZONEOPT_CHECKMXFAIL;
264 } else if (ARGCMP("ignore")) {
265 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
266 DNS_ZONEOPT_CHECKMXFAIL);
268 fprintf(stderr, "invalid argument to -m: %s\n",
269 isc_commandline_argument);
275 output_filename = isc_commandline_argument;
283 if (ARGCMP("warn")) {
284 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
285 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
286 } else if (ARGCMP("fail")) {
287 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
288 DNS_ZONEOPT_CHECKDUPRRFAIL;
289 } else if (ARGCMP("ignore")) {
290 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
291 DNS_ZONEOPT_CHECKDUPRRFAIL);
293 fprintf(stderr, "invalid argument to -r: %s\n",
294 isc_commandline_argument);
301 outputstyle = &dns_master_style_full;
302 else if (ARGCMP("relative")) {
303 outputstyle = &dns_master_style_default;
306 "unknown or unsupported style: %s\n",
307 isc_commandline_argument);
313 result = isc_dir_chroot(isc_commandline_argument);
314 if (result != ISC_R_SUCCESS) {
315 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
316 isc_commandline_argument,
317 isc_result_totext(result));
323 printf(VERSION "\n");
327 workdir = isc_commandline_argument;
335 if (ARGCMP("fail")) {
336 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
337 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
338 } else if (ARGCMP("warn")) {
339 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
340 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
341 } else if (ARGCMP("ignore")) {
342 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
343 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
345 fprintf(stderr, "invalid argument to -M: %s\n",
346 isc_commandline_argument);
352 if (ARGCMP("fail")) {
353 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
354 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
355 } else if (ARGCMP("warn")) {
356 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
357 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
358 } else if (ARGCMP("ignore")) {
359 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
360 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
362 fprintf(stderr, "invalid argument to -S: %s\n",
363 isc_commandline_argument);
369 if (ARGCMP("warn")) {
370 zone_options |= DNS_ZONEOPT_CHECKSPF;
371 } else if (ARGCMP("ignore")) {
372 zone_options &= ~DNS_ZONEOPT_CHECKSPF;
374 fprintf(stderr, "invalid argument to -T: %s\n",
375 isc_commandline_argument);
382 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
383 else if (ARGCMP("ignore"))
384 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
388 if (isc_commandline_option != '?')
389 fprintf(stderr, "%s: invalid argument -%c\n",
390 prog_name, isc_commandline_option);
396 fprintf(stderr, "%s: unhandled option -%c\n",
397 prog_name, isc_commandline_option);
402 if (workdir != NULL) {
403 result = isc_dir_chdir(workdir);
404 if (result != ISC_R_SUCCESS) {
405 fprintf(stderr, "isc_dir_chdir: %s: %s\n",
406 workdir, isc_result_totext(result));
411 if (inputformatstr != NULL) {
412 if (strcasecmp(inputformatstr, "text") == 0)
413 inputformat = dns_masterformat_text;
414 else if (strcasecmp(inputformatstr, "raw") == 0)
415 inputformat = dns_masterformat_raw;
417 fprintf(stderr, "unknown file format: %s\n",
423 if (outputformatstr != NULL) {
424 if (strcasecmp(outputformatstr, "text") == 0)
425 outputformat = dns_masterformat_text;
426 else if (strcasecmp(outputformatstr, "raw") == 0)
427 outputformat = dns_masterformat_raw;
429 fprintf(stderr, "unknown file format: %s\n",
435 if (progmode == progmode_compile) {
436 dumpzone = 1; /* always dump */
438 if (output_filename == NULL) {
440 "output file required, but not specified\n");
445 if (output_filename != NULL)
449 * If we are outputing to stdout then send the informational
453 (output_filename == NULL ||
454 strcmp(output_filename, "-") == 0 ||
455 strcmp(output_filename, "/dev/fd/1") == 0 ||
456 strcmp(output_filename, "/dev/stdout") == 0)) {
461 if (isc_commandline_index + 2 != argc)
468 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
470 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
472 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
473 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
476 dns_result_register();
478 origin = argv[isc_commandline_index++];
479 filename = argv[isc_commandline_index++];
480 result = load_zone(mctx, origin, filename, inputformat, classname,
483 if (result == ISC_R_SUCCESS && dumpzone) {
485 fprintf(errout, "dump zone to %s...", output_filename);
488 result = dump_zone(origin, zone, output_filename,
489 outputformat, outputstyle);
491 fprintf(errout, "done\n");
494 if (!quiet && result == ISC_R_SUCCESS)
495 fprintf(errout, "OK\n");
498 isc_log_destroy(&lctx);
500 isc_entropy_detach(&ectx);
501 isc_mem_destroy(&mctx);
505 return ((result == ISC_R_SUCCESS) ? 0 : 1);