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.65 2011/12/22 17:29:22 each 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/master.h>
43 #include <dns/masterdump.h>
45 #include <dns/rdataclass.h>
46 #include <dns/rdataset.h>
47 #include <dns/result.h>
48 #include <dns/types.h>
51 #include "check-tool.h"
54 static isc_mem_t *mctx = NULL;
55 static isc_entropy_t *ectx = NULL;
56 dns_zone_t *zone = NULL;
57 dns_zonetype_t zonetype = dns_zone_master;
58 static int dumpzone = 0;
59 static const char *output_filename;
60 static char *prog_name = NULL;
61 static const dns_master_style_t *outputstyle = NULL;
62 static enum { progmode_check, progmode_compile } progmode;
64 #define ERRRET(result, function) \
66 if (result != ISC_R_SUCCESS) { \
68 fprintf(stderr, "%s() returned %s\n", \
69 function, dns_result_totext(result)); \
74 ISC_PLATFORM_NORETURN_PRE static void
75 usage(void) ISC_PLATFORM_NORETURN_POST;
80 "usage: %s [-djqvD] [-c class] "
81 "[-f inputformat] [-F outputformat] "
82 "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
83 "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
84 "[-r (ignore|warn|fail)] "
85 "[-i (full|full-sibling|local|local-sibling|none)] "
86 "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
88 "%s zonename filename\n",
90 progmode == progmode_check ? "[-o filename]" : "-o filename");
97 dns_zone_detach(&zone);
101 /*% main processing routine */
103 main(int argc, char **argv) {
106 char *filename = NULL;
107 isc_log_t *lctx = NULL;
109 char classname_in[] = "IN";
110 char *classname = classname_in;
111 const char *workdir = NULL;
112 const char *inputformatstr = NULL;
113 const char *outputformatstr = NULL;
114 dns_masterformat_t inputformat = dns_masterformat_text;
115 dns_masterformat_t outputformat = dns_masterformat_text;
116 dns_masterrawheader_t header;
117 isc_uint32_t rawversion = 1, serialnum = 0;
118 isc_boolean_t snset = ISC_FALSE;
119 isc_boolean_t logdump = ISC_FALSE;
120 FILE *errout = stdout;
123 outputstyle = &dns_master_style_full;
125 prog_name = strrchr(argv[0], '/');
126 if (prog_name == NULL)
127 prog_name = strrchr(argv[0], '\\');
128 if (prog_name != NULL)
133 * Libtool doesn't preserve the program name prior to final
134 * installation. Remove the libtool prefix ("lt-").
136 if (strncmp(prog_name, "lt-", 3) == 0)
140 (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
142 if (PROGCMP("named-checkzone"))
143 progmode = progmode_check;
144 else if (PROGCMP("named-compilezone"))
145 progmode = progmode_compile;
149 /* Compilation specific defaults */
150 if (progmode == progmode_compile) {
151 zone_options |= (DNS_ZONEOPT_CHECKNS |
152 DNS_ZONEOPT_FATALNS |
153 DNS_ZONEOPT_CHECKSPF |
154 DNS_ZONEOPT_CHECKDUPRR |
155 DNS_ZONEOPT_CHECKNAMES |
156 DNS_ZONEOPT_CHECKNAMESFAIL |
157 DNS_ZONEOPT_CHECKWILDCARD);
159 zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
160 DNS_ZONEOPT_CHECKSPF);
162 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
164 isc_commandline_errprint = ISC_FALSE;
166 while ((c = isc_commandline_parse(argc, argv,
167 "c:df:hi:jk:L:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
171 classname = isc_commandline_argument;
179 if (ARGCMP("full")) {
180 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
181 DNS_ZONEOPT_CHECKSIBLING;
182 docheckmx = ISC_TRUE;
183 docheckns = ISC_TRUE;
184 dochecksrv = ISC_TRUE;
185 } else if (ARGCMP("full-sibling")) {
186 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
187 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
188 docheckmx = ISC_TRUE;
189 docheckns = ISC_TRUE;
190 dochecksrv = ISC_TRUE;
191 } else if (ARGCMP("local")) {
192 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
193 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
194 docheckmx = ISC_FALSE;
195 docheckns = ISC_FALSE;
196 dochecksrv = ISC_FALSE;
197 } else if (ARGCMP("local-sibling")) {
198 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
199 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
200 docheckmx = ISC_FALSE;
201 docheckns = ISC_FALSE;
202 dochecksrv = ISC_FALSE;
203 } else if (ARGCMP("none")) {
204 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
205 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
206 docheckmx = ISC_FALSE;
207 docheckns = ISC_FALSE;
208 dochecksrv = ISC_FALSE;
210 fprintf(stderr, "invalid argument to -i: %s\n",
211 isc_commandline_argument);
217 inputformatstr = isc_commandline_argument;
221 outputformatstr = isc_commandline_argument;
229 if (ARGCMP("warn")) {
230 zone_options |= DNS_ZONEOPT_CHECKNAMES;
231 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
232 } else if (ARGCMP("fail")) {
233 zone_options |= DNS_ZONEOPT_CHECKNAMES |
234 DNS_ZONEOPT_CHECKNAMESFAIL;
235 } else if (ARGCMP("ignore")) {
236 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
237 DNS_ZONEOPT_CHECKNAMESFAIL);
239 fprintf(stderr, "invalid argument to -k: %s\n",
240 isc_commandline_argument);
248 serialnum = strtol(isc_commandline_argument, &endp, 0);
250 fprintf(stderr, "source serial number "
257 if (ARGCMP("ignore")) {
258 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
259 DNS_ZONEOPT_FATALNS);
260 } else if (ARGCMP("warn")) {
261 zone_options |= DNS_ZONEOPT_CHECKNS;
262 zone_options &= ~DNS_ZONEOPT_FATALNS;
263 } else if (ARGCMP("fail")) {
264 zone_options |= DNS_ZONEOPT_CHECKNS|
267 fprintf(stderr, "invalid argument to -n: %s\n",
268 isc_commandline_argument);
274 if (ARGCMP("warn")) {
275 zone_options |= DNS_ZONEOPT_CHECKMX;
276 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
277 } else if (ARGCMP("fail")) {
278 zone_options |= DNS_ZONEOPT_CHECKMX |
279 DNS_ZONEOPT_CHECKMXFAIL;
280 } else if (ARGCMP("ignore")) {
281 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
282 DNS_ZONEOPT_CHECKMXFAIL);
284 fprintf(stderr, "invalid argument to -m: %s\n",
285 isc_commandline_argument);
291 output_filename = isc_commandline_argument;
299 if (ARGCMP("warn")) {
300 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
301 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
302 } else if (ARGCMP("fail")) {
303 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
304 DNS_ZONEOPT_CHECKDUPRRFAIL;
305 } else if (ARGCMP("ignore")) {
306 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
307 DNS_ZONEOPT_CHECKDUPRRFAIL);
309 fprintf(stderr, "invalid argument to -r: %s\n",
310 isc_commandline_argument);
317 outputstyle = &dns_master_style_full;
318 else if (ARGCMP("relative")) {
319 outputstyle = &dns_master_style_default;
322 "unknown or unsupported style: %s\n",
323 isc_commandline_argument);
329 result = isc_dir_chroot(isc_commandline_argument);
330 if (result != ISC_R_SUCCESS) {
331 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
332 isc_commandline_argument,
333 isc_result_totext(result));
339 printf(VERSION "\n");
343 workdir = isc_commandline_argument;
351 if (ARGCMP("fail")) {
352 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
353 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
354 } else if (ARGCMP("warn")) {
355 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
356 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
357 } else if (ARGCMP("ignore")) {
358 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
359 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
361 fprintf(stderr, "invalid argument to -M: %s\n",
362 isc_commandline_argument);
368 if (ARGCMP("fail")) {
369 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
370 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
371 } else if (ARGCMP("warn")) {
372 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
373 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
374 } else if (ARGCMP("ignore")) {
375 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
376 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
378 fprintf(stderr, "invalid argument to -S: %s\n",
379 isc_commandline_argument);
385 if (ARGCMP("warn")) {
386 zone_options |= DNS_ZONEOPT_CHECKSPF;
387 } else if (ARGCMP("ignore")) {
388 zone_options &= ~DNS_ZONEOPT_CHECKSPF;
390 fprintf(stderr, "invalid argument to -T: %s\n",
391 isc_commandline_argument);
398 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
399 else if (ARGCMP("ignore"))
400 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
404 if (isc_commandline_option != '?')
405 fprintf(stderr, "%s: invalid argument -%c\n",
406 prog_name, isc_commandline_option);
412 fprintf(stderr, "%s: unhandled option -%c\n",
413 prog_name, isc_commandline_option);
418 if (workdir != NULL) {
419 result = isc_dir_chdir(workdir);
420 if (result != ISC_R_SUCCESS) {
421 fprintf(stderr, "isc_dir_chdir: %s: %s\n",
422 workdir, isc_result_totext(result));
427 if (inputformatstr != NULL) {
428 if (strcasecmp(inputformatstr, "text") == 0)
429 inputformat = dns_masterformat_text;
430 else if (strcasecmp(inputformatstr, "raw") == 0)
431 inputformat = dns_masterformat_raw;
432 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
433 inputformat = dns_masterformat_raw;
435 "WARNING: input format raw, version ignored\n");
437 fprintf(stderr, "unknown file format: %s\n",
443 if (outputformatstr != NULL) {
444 if (strcasecmp(outputformatstr, "text") == 0) {
445 outputformat = dns_masterformat_text;
446 } else if (strcasecmp(outputformatstr, "raw") == 0) {
447 outputformat = dns_masterformat_raw;
448 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
451 outputformat = dns_masterformat_raw;
452 rawversion = strtol(outputformatstr + 4, &end, 10);
453 if (end == outputformatstr + 4 || *end != '\0' ||
456 "unknown raw format version\n");
460 fprintf(stderr, "unknown file format: %s\n",
466 if (progmode == progmode_compile) {
467 dumpzone = 1; /* always dump */
469 if (output_filename == NULL) {
471 "output file required, but not specified\n");
476 if (output_filename != NULL)
480 * If we are outputing to stdout then send the informational
484 (output_filename == NULL ||
485 strcmp(output_filename, "-") == 0 ||
486 strcmp(output_filename, "/dev/fd/1") == 0 ||
487 strcmp(output_filename, "/dev/stdout") == 0)) {
492 if (isc_commandline_index + 2 != argc)
499 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
501 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
503 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
504 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
507 dns_result_register();
509 origin = argv[isc_commandline_index++];
510 filename = argv[isc_commandline_index++];
511 result = load_zone(mctx, origin, filename, inputformat, classname,
515 dns_master_initrawheader(&header);
516 header.flags = DNS_MASTERRAW_SOURCESERIALSET;
517 header.sourceserial = serialnum;
518 dns_zone_setrawdata(zone, &header);
521 if (result == ISC_R_SUCCESS && dumpzone) {
523 fprintf(errout, "dump zone to %s...", output_filename);
526 result = dump_zone(origin, zone, output_filename,
527 outputformat, outputstyle, rawversion);
529 fprintf(errout, "done\n");
532 if (!quiet && result == ISC_R_SUCCESS)
533 fprintf(errout, "OK\n");
536 isc_log_destroy(&lctx);
538 isc_entropy_detach(&ectx);
539 isc_mem_destroy(&mctx);
543 return ((result == ISC_R_SUCCESS) ? 0 : 1);