No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / check / named-checkzone.c
blob40b18ed8257ea43cd07ca735c5cee898d9b80d79
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: named-checkzone.c,v 1.59 2009/12/04 22:06:37 tbox Exp */
22 /*! \file */
24 #include <config.h>
26 #include <stdlib.h>
28 #include <isc/app.h>
29 #include <isc/commandline.h>
30 #include <isc/dir.h>
31 #include <isc/entropy.h>
32 #include <isc/hash.h>
33 #include <isc/log.h>
34 #include <isc/mem.h>
35 #include <isc/socket.h>
36 #include <isc/string.h>
37 #include <isc/task.h>
38 #include <isc/timer.h>
39 #include <isc/util.h>
41 #include <dns/db.h>
42 #include <dns/fixedname.h>
43 #include <dns/log.h>
44 #include <dns/masterdump.h>
45 #include <dns/name.h>
46 #include <dns/rdataclass.h>
47 #include <dns/rdataset.h>
48 #include <dns/result.h>
49 #include <dns/types.h>
50 #include <dns/zone.h>
52 #include "check-tool.h"
54 static int quiet = 0;
55 static isc_mem_t *mctx = NULL;
56 static isc_entropy_t *ectx = NULL;
57 dns_zone_t *zone = NULL;
58 dns_zonetype_t zonetype = dns_zone_master;
59 static int dumpzone = 0;
60 static const char *output_filename;
61 static char *prog_name = NULL;
62 static const dns_master_style_t *outputstyle = NULL;
63 static enum { progmode_check, progmode_compile } progmode;
65 #define ERRRET(result, function) \
66 do { \
67 if (result != ISC_R_SUCCESS) { \
68 if (!quiet) \
69 fprintf(stderr, "%s() returned %s\n", \
70 function, dns_result_totext(result)); \
71 return (result); \
72 } \
73 } while (0)
75 ISC_PLATFORM_NORETURN_PRE static void
76 usage(void) ISC_PLATFORM_NORETURN_POST;
78 static void
79 usage(void) {
80 fprintf(stderr,
81 "usage: %s [-djqvD] [-c class] "
82 "[-f inputformat] [-F outputformat] "
83 "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
84 "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
85 "[-r (ignore|warn|fail)] "
86 "[-i (full|full-sibling|local|local-sibling|none)] "
87 "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
88 "[-W (ignore|warn)] "
89 "%s zonename filename\n",
90 prog_name,
91 progmode == progmode_check ? "[-o filename]" : "-o filename");
92 exit(1);
95 static void
96 destroy(void) {
97 if (zone != NULL)
98 dns_zone_detach(&zone);
99 dns_name_destroy();
102 /*% main processing routine */
104 main(int argc, char **argv) {
105 int c;
106 char *origin = NULL;
107 char *filename = NULL;
108 isc_log_t *lctx = NULL;
109 isc_result_t result;
110 char classname_in[] = "IN";
111 char *classname = classname_in;
112 const char *workdir = NULL;
113 const char *inputformatstr = NULL;
114 const char *outputformatstr = NULL;
115 dns_masterformat_t inputformat = dns_masterformat_text;
116 dns_masterformat_t outputformat = dns_masterformat_text;
117 FILE *errout = stdout;
119 outputstyle = &dns_master_style_full;
121 prog_name = strrchr(argv[0], '/');
122 if (prog_name == NULL)
123 prog_name = strrchr(argv[0], '\\');
124 if (prog_name != NULL)
125 prog_name++;
126 else
127 prog_name = argv[0];
129 * Libtool doesn't preserve the program name prior to final
130 * installation. Remove the libtool prefix ("lt-").
132 if (strncmp(prog_name, "lt-", 3) == 0)
133 prog_name += 3;
135 #define PROGCMP(X) \
136 (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
138 if (PROGCMP("named-checkzone"))
139 progmode = progmode_check;
140 else if (PROGCMP("named-compilezone"))
141 progmode = progmode_compile;
142 else
143 INSIST(0);
145 /* Compilation specific defaults */
146 if (progmode == progmode_compile) {
147 zone_options |= (DNS_ZONEOPT_CHECKNS |
148 DNS_ZONEOPT_FATALNS |
149 DNS_ZONEOPT_CHECKDUPRR |
150 DNS_ZONEOPT_CHECKNAMES |
151 DNS_ZONEOPT_CHECKNAMESFAIL |
152 DNS_ZONEOPT_CHECKWILDCARD);
153 } else
154 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
156 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
158 isc_commandline_errprint = ISC_FALSE;
160 while ((c = isc_commandline_parse(argc, argv,
161 "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:W:"))
162 != EOF) {
163 switch (c) {
164 case 'c':
165 classname = isc_commandline_argument;
166 break;
168 case 'd':
169 debug++;
170 break;
172 case 'i':
173 if (ARGCMP("full")) {
174 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
175 DNS_ZONEOPT_CHECKSIBLING;
176 docheckmx = ISC_TRUE;
177 docheckns = ISC_TRUE;
178 dochecksrv = ISC_TRUE;
179 } else if (ARGCMP("full-sibling")) {
180 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
181 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
182 docheckmx = ISC_TRUE;
183 docheckns = ISC_TRUE;
184 dochecksrv = ISC_TRUE;
185 } else if (ARGCMP("local")) {
186 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
187 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
188 docheckmx = ISC_FALSE;
189 docheckns = ISC_FALSE;
190 dochecksrv = ISC_FALSE;
191 } else if (ARGCMP("local-sibling")) {
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("none")) {
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 {
204 fprintf(stderr, "invalid argument to -i: %s\n",
205 isc_commandline_argument);
206 exit(1);
208 break;
210 case 'f':
211 inputformatstr = isc_commandline_argument;
212 break;
214 case 'F':
215 outputformatstr = isc_commandline_argument;
216 break;
218 case 'j':
219 nomerge = ISC_FALSE;
220 break;
222 case 'k':
223 if (ARGCMP("warn")) {
224 zone_options |= DNS_ZONEOPT_CHECKNAMES;
225 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
226 } else if (ARGCMP("fail")) {
227 zone_options |= DNS_ZONEOPT_CHECKNAMES |
228 DNS_ZONEOPT_CHECKNAMESFAIL;
229 } else if (ARGCMP("ignore")) {
230 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
231 DNS_ZONEOPT_CHECKNAMESFAIL);
232 } else {
233 fprintf(stderr, "invalid argument to -k: %s\n",
234 isc_commandline_argument);
235 exit(1);
237 break;
239 case 'n':
240 if (ARGCMP("ignore")) {
241 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
242 DNS_ZONEOPT_FATALNS);
243 } else if (ARGCMP("warn")) {
244 zone_options |= DNS_ZONEOPT_CHECKNS;
245 zone_options &= ~DNS_ZONEOPT_FATALNS;
246 } else if (ARGCMP("fail")) {
247 zone_options |= DNS_ZONEOPT_CHECKNS|
248 DNS_ZONEOPT_FATALNS;
249 } else {
250 fprintf(stderr, "invalid argument to -n: %s\n",
251 isc_commandline_argument);
252 exit(1);
254 break;
256 case 'm':
257 if (ARGCMP("warn")) {
258 zone_options |= DNS_ZONEOPT_CHECKMX;
259 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
260 } else if (ARGCMP("fail")) {
261 zone_options |= DNS_ZONEOPT_CHECKMX |
262 DNS_ZONEOPT_CHECKMXFAIL;
263 } else if (ARGCMP("ignore")) {
264 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
265 DNS_ZONEOPT_CHECKMXFAIL);
266 } else {
267 fprintf(stderr, "invalid argument to -m: %s\n",
268 isc_commandline_argument);
269 exit(1);
271 break;
273 case 'o':
274 output_filename = isc_commandline_argument;
275 break;
277 case 'q':
278 quiet++;
279 break;
281 case 'r':
282 if (ARGCMP("warn")) {
283 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
284 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
285 } else if (ARGCMP("fail")) {
286 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
287 DNS_ZONEOPT_CHECKDUPRRFAIL;
288 } else if (ARGCMP("ignore")) {
289 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
290 DNS_ZONEOPT_CHECKDUPRRFAIL);
291 } else {
292 fprintf(stderr, "invalid argument to -r: %s\n",
293 isc_commandline_argument);
294 exit(1);
296 break;
298 case 's':
299 if (ARGCMP("full"))
300 outputstyle = &dns_master_style_full;
301 else if (ARGCMP("relative")) {
302 outputstyle = &dns_master_style_default;
303 } else {
304 fprintf(stderr,
305 "unknown or unsupported style: %s\n",
306 isc_commandline_argument);
307 exit(1);
309 break;
311 case 't':
312 result = isc_dir_chroot(isc_commandline_argument);
313 if (result != ISC_R_SUCCESS) {
314 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
315 isc_commandline_argument,
316 isc_result_totext(result));
317 exit(1);
319 break;
321 case 'v':
322 printf(VERSION "\n");
323 exit(0);
325 case 'w':
326 workdir = isc_commandline_argument;
327 break;
329 case 'D':
330 dumpzone++;
331 break;
333 case 'M':
334 if (ARGCMP("fail")) {
335 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
336 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
337 } else if (ARGCMP("warn")) {
338 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
339 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
340 } else if (ARGCMP("ignore")) {
341 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
342 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
343 } else {
344 fprintf(stderr, "invalid argument to -M: %s\n",
345 isc_commandline_argument);
346 exit(1);
348 break;
350 case 'S':
351 if (ARGCMP("fail")) {
352 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
353 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
354 } else if (ARGCMP("warn")) {
355 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
356 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
357 } else if (ARGCMP("ignore")) {
358 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
359 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
360 } else {
361 fprintf(stderr, "invalid argument to -S: %s\n",
362 isc_commandline_argument);
363 exit(1);
365 break;
367 case 'W':
368 if (ARGCMP("warn"))
369 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
370 else if (ARGCMP("ignore"))
371 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
372 break;
374 case '?':
375 if (isc_commandline_option != '?')
376 fprintf(stderr, "%s: invalid argument -%c\n",
377 prog_name, isc_commandline_option);
378 case 'h':
379 usage();
381 default:
382 fprintf(stderr, "%s: unhandled option -%c\n",
383 prog_name, isc_commandline_option);
384 exit(1);
388 if (workdir != NULL) {
389 result = isc_dir_chdir(workdir);
390 if (result != ISC_R_SUCCESS) {
391 fprintf(stderr, "isc_dir_chdir: %s: %s\n",
392 workdir, isc_result_totext(result));
393 exit(1);
397 if (inputformatstr != NULL) {
398 if (strcasecmp(inputformatstr, "text") == 0)
399 inputformat = dns_masterformat_text;
400 else if (strcasecmp(inputformatstr, "raw") == 0)
401 inputformat = dns_masterformat_raw;
402 else {
403 fprintf(stderr, "unknown file format: %s\n",
404 inputformatstr);
405 exit(1);
409 if (outputformatstr != NULL) {
410 if (strcasecmp(outputformatstr, "text") == 0)
411 outputformat = dns_masterformat_text;
412 else if (strcasecmp(outputformatstr, "raw") == 0)
413 outputformat = dns_masterformat_raw;
414 else {
415 fprintf(stderr, "unknown file format: %s\n",
416 outputformatstr);
417 exit(1);
421 if (progmode == progmode_compile) {
422 dumpzone = 1; /* always dump */
423 if (output_filename == NULL) {
424 fprintf(stderr,
425 "output file required, but not specified\n");
426 usage();
430 if (output_filename != NULL)
431 dumpzone = 1;
434 * If we are outputing to stdout then send the informational
435 * output to stderr.
437 if (dumpzone &&
438 (output_filename == NULL ||
439 strcmp(output_filename, "-") == 0 ||
440 strcmp(output_filename, "/dev/fd/1") == 0 ||
441 strcmp(output_filename, "/dev/stdout") == 0))
442 errout = stderr;
444 if (isc_commandline_index + 2 != argc)
445 usage();
447 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
448 if (!quiet)
449 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
450 == ISC_R_SUCCESS);
451 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
452 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
453 == ISC_R_SUCCESS);
455 dns_result_register();
457 origin = argv[isc_commandline_index++];
458 filename = argv[isc_commandline_index++];
459 result = load_zone(mctx, origin, filename, inputformat, classname,
460 &zone);
462 if (result == ISC_R_SUCCESS && dumpzone) {
463 if (!quiet && progmode == progmode_compile) {
464 fprintf(errout, "dump zone to %s...", output_filename);
465 fflush(errout);
467 result = dump_zone(origin, zone, output_filename,
468 outputformat, outputstyle);
469 if (!quiet && progmode == progmode_compile)
470 fprintf(errout, "done\n");
473 if (!quiet && result == ISC_R_SUCCESS)
474 fprintf(errout, "OK\n");
475 destroy();
476 if (lctx != NULL)
477 isc_log_destroy(&lctx);
478 isc_hash_destroy();
479 isc_entropy_detach(&ectx);
480 isc_mem_destroy(&mctx);
481 return ((result == ISC_R_SUCCESS) ? 0 : 1);