etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / check / named-checkzone.c
bloba292012d1425bcbdc2faa31b81ee93277f39141c
1 /* $NetBSD: named-checkzone.c,v 1.7 2014/12/10 04:37:51 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2014 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.65.32.2 2012/02/07 02:45:21 each 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/master.h>
45 #include <dns/masterdump.h>
46 #include <dns/name.h>
47 #include <dns/rdataclass.h>
48 #include <dns/rdataset.h>
49 #include <dns/result.h>
50 #include <dns/types.h>
51 #include <dns/zone.h>
53 #include "check-tool.h"
55 static int quiet = 0;
56 static isc_mem_t *mctx = NULL;
57 static isc_entropy_t *ectx = NULL;
58 dns_zone_t *zone = NULL;
59 dns_zonetype_t zonetype = dns_zone_master;
60 static int dumpzone = 0;
61 static const char *output_filename;
62 static char *prog_name = NULL;
63 static const dns_master_style_t *outputstyle = NULL;
64 static enum { progmode_check, progmode_compile } progmode;
66 #define ERRRET(result, function) \
67 do { \
68 if (result != ISC_R_SUCCESS) { \
69 if (!quiet) \
70 fprintf(stderr, "%s() returned %s\n", \
71 function, dns_result_totext(result)); \
72 return (result); \
73 } \
74 } while (/*CONSTCOND*/0)
76 ISC_PLATFORM_NORETURN_PRE static void
77 usage(void) ISC_PLATFORM_NORETURN_POST;
79 static void
80 usage(void) {
81 fprintf(stderr,
82 "usage: %s [-djqvD] [-c class] "
83 "[-f inputformat] [-F outputformat] [-J filename] "
84 "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
85 "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
86 "[-r (ignore|warn|fail)] "
87 "[-i (full|full-sibling|local|local-sibling|none)] "
88 "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
89 "[-W (ignore|warn)] "
90 "%s zonename filename\n",
91 prog_name,
92 progmode == progmode_check ? "[-o filename]" : "-o filename");
93 exit(1);
96 static void
97 destroy(void) {
98 if (zone != NULL)
99 dns_zone_detach(&zone);
100 dns_name_destroy();
103 /*% main processing routine */
105 main(int argc, char **argv) {
106 int c;
107 char *origin = NULL;
108 char *filename = NULL;
109 isc_log_t *lctx = NULL;
110 isc_result_t result;
111 char classname_in[] = "IN";
112 char *classname = classname_in;
113 const char *workdir = NULL;
114 const char *inputformatstr = NULL;
115 const char *outputformatstr = NULL;
116 dns_masterformat_t inputformat = dns_masterformat_text;
117 dns_masterformat_t outputformat = dns_masterformat_text;
118 dns_masterrawheader_t header;
119 isc_uint32_t rawversion = 1, serialnum = 0;
120 dns_ttl_t maxttl = 0;
121 isc_boolean_t snset = ISC_FALSE;
122 isc_boolean_t logdump = ISC_FALSE;
123 FILE *errout = stdout;
124 char *endp;
127 * Uncomment the following line if memory debugging is needed:
128 * isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
131 outputstyle = &dns_master_style_full;
133 prog_name = strrchr(argv[0], '/');
134 if (prog_name == NULL)
135 prog_name = strrchr(argv[0], '\\');
136 if (prog_name != NULL)
137 prog_name++;
138 else
139 prog_name = argv[0];
141 * Libtool doesn't preserve the program name prior to final
142 * installation. Remove the libtool prefix ("lt-").
144 if (strncmp(prog_name, "lt-", 3) == 0)
145 prog_name += 3;
147 #define PROGCMP(X) \
148 (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
150 if (PROGCMP("named-checkzone"))
151 progmode = progmode_check;
152 else if (PROGCMP("named-compilezone"))
153 progmode = progmode_compile;
154 else
155 INSIST(0);
157 /* Compilation specific defaults */
158 if (progmode == progmode_compile) {
159 zone_options |= (DNS_ZONEOPT_CHECKNS |
160 DNS_ZONEOPT_FATALNS |
161 DNS_ZONEOPT_CHECKSPF |
162 DNS_ZONEOPT_CHECKDUPRR |
163 DNS_ZONEOPT_CHECKNAMES |
164 DNS_ZONEOPT_CHECKNAMESFAIL |
165 DNS_ZONEOPT_CHECKWILDCARD);
166 } else
167 zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
168 DNS_ZONEOPT_CHECKSPF);
170 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
172 isc_commandline_errprint = ISC_FALSE;
174 while ((c = isc_commandline_parse(argc, argv,
175 "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
176 != EOF) {
177 switch (c) {
178 case 'c':
179 classname = isc_commandline_argument;
180 break;
182 case 'd':
183 debug++;
184 break;
186 case 'i':
187 if (ARGCMP("full")) {
188 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
189 DNS_ZONEOPT_CHECKSIBLING;
190 docheckmx = ISC_TRUE;
191 docheckns = ISC_TRUE;
192 dochecksrv = ISC_TRUE;
193 } else if (ARGCMP("full-sibling")) {
194 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
195 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
196 docheckmx = ISC_TRUE;
197 docheckns = ISC_TRUE;
198 dochecksrv = ISC_TRUE;
199 } else if (ARGCMP("local")) {
200 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
201 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
202 docheckmx = ISC_FALSE;
203 docheckns = ISC_FALSE;
204 dochecksrv = ISC_FALSE;
205 } else if (ARGCMP("local-sibling")) {
206 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
207 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
208 docheckmx = ISC_FALSE;
209 docheckns = ISC_FALSE;
210 dochecksrv = ISC_FALSE;
211 } else if (ARGCMP("none")) {
212 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
213 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
214 docheckmx = ISC_FALSE;
215 docheckns = ISC_FALSE;
216 dochecksrv = ISC_FALSE;
217 } else {
218 fprintf(stderr, "invalid argument to -i: %s\n",
219 isc_commandline_argument);
220 exit(1);
222 break;
224 case 'f':
225 inputformatstr = isc_commandline_argument;
226 break;
228 case 'F':
229 outputformatstr = isc_commandline_argument;
230 break;
232 case 'j':
233 nomerge = ISC_FALSE;
234 break;
236 case 'J':
237 journal = isc_commandline_argument;
238 nomerge = ISC_FALSE;
239 break;
241 case 'k':
242 if (ARGCMP("warn")) {
243 zone_options |= DNS_ZONEOPT_CHECKNAMES;
244 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
245 } else if (ARGCMP("fail")) {
246 zone_options |= DNS_ZONEOPT_CHECKNAMES |
247 DNS_ZONEOPT_CHECKNAMESFAIL;
248 } else if (ARGCMP("ignore")) {
249 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
250 DNS_ZONEOPT_CHECKNAMESFAIL);
251 } else {
252 fprintf(stderr, "invalid argument to -k: %s\n",
253 isc_commandline_argument);
254 exit(1);
256 break;
258 case 'L':
259 snset = ISC_TRUE;
260 endp = NULL;
261 serialnum = strtol(isc_commandline_argument, &endp, 0);
262 if (*endp != '\0') {
263 fprintf(stderr, "source serial number "
264 "must be numeric");
265 exit(1);
267 break;
269 case 'l':
270 zone_options2 |= DNS_ZONEOPT2_CHECKTTL;
271 endp = NULL;
272 maxttl = strtol(isc_commandline_argument, &endp, 0);
273 if (*endp != '\0') {
274 fprintf(stderr, "maximum TTL "
275 "must be numeric");
276 exit(1);
278 break;
281 case 'n':
282 if (ARGCMP("ignore")) {
283 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
284 DNS_ZONEOPT_FATALNS);
285 } else if (ARGCMP("warn")) {
286 zone_options |= DNS_ZONEOPT_CHECKNS;
287 zone_options &= ~DNS_ZONEOPT_FATALNS;
288 } else if (ARGCMP("fail")) {
289 zone_options |= DNS_ZONEOPT_CHECKNS|
290 DNS_ZONEOPT_FATALNS;
291 } else {
292 fprintf(stderr, "invalid argument to -n: %s\n",
293 isc_commandline_argument);
294 exit(1);
296 break;
298 case 'm':
299 if (ARGCMP("warn")) {
300 zone_options |= DNS_ZONEOPT_CHECKMX;
301 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
302 } else if (ARGCMP("fail")) {
303 zone_options |= DNS_ZONEOPT_CHECKMX |
304 DNS_ZONEOPT_CHECKMXFAIL;
305 } else if (ARGCMP("ignore")) {
306 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
307 DNS_ZONEOPT_CHECKMXFAIL);
308 } else {
309 fprintf(stderr, "invalid argument to -m: %s\n",
310 isc_commandline_argument);
311 exit(1);
313 break;
315 case 'o':
316 output_filename = isc_commandline_argument;
317 break;
319 case 'q':
320 quiet++;
321 break;
323 case 'r':
324 if (ARGCMP("warn")) {
325 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
326 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
327 } else if (ARGCMP("fail")) {
328 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
329 DNS_ZONEOPT_CHECKDUPRRFAIL;
330 } else if (ARGCMP("ignore")) {
331 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
332 DNS_ZONEOPT_CHECKDUPRRFAIL);
333 } else {
334 fprintf(stderr, "invalid argument to -r: %s\n",
335 isc_commandline_argument);
336 exit(1);
338 break;
340 case 's':
341 if (ARGCMP("full"))
342 outputstyle = &dns_master_style_full;
343 else if (ARGCMP("relative")) {
344 outputstyle = &dns_master_style_default;
345 } else {
346 fprintf(stderr,
347 "unknown or unsupported style: %s\n",
348 isc_commandline_argument);
349 exit(1);
351 break;
353 case 't':
354 result = isc_dir_chroot(isc_commandline_argument);
355 if (result != ISC_R_SUCCESS) {
356 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
357 isc_commandline_argument,
358 isc_result_totext(result));
359 exit(1);
361 break;
363 case 'v':
364 printf(VERSION "\n");
365 exit(0);
367 case 'w':
368 workdir = isc_commandline_argument;
369 break;
371 case 'D':
372 dumpzone++;
373 break;
375 case 'M':
376 if (ARGCMP("fail")) {
377 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
378 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
379 } else if (ARGCMP("warn")) {
380 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
381 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
382 } else if (ARGCMP("ignore")) {
383 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
384 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
385 } else {
386 fprintf(stderr, "invalid argument to -M: %s\n",
387 isc_commandline_argument);
388 exit(1);
390 break;
392 case 'S':
393 if (ARGCMP("fail")) {
394 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
395 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
396 } else if (ARGCMP("warn")) {
397 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
398 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
399 } else if (ARGCMP("ignore")) {
400 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
401 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
402 } else {
403 fprintf(stderr, "invalid argument to -S: %s\n",
404 isc_commandline_argument);
405 exit(1);
407 break;
409 case 'T':
410 if (ARGCMP("warn")) {
411 zone_options |= DNS_ZONEOPT_CHECKSPF;
412 } else if (ARGCMP("ignore")) {
413 zone_options &= ~DNS_ZONEOPT_CHECKSPF;
414 } else {
415 fprintf(stderr, "invalid argument to -T: %s\n",
416 isc_commandline_argument);
417 exit(1);
419 break;
421 case 'W':
422 if (ARGCMP("warn"))
423 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
424 else if (ARGCMP("ignore"))
425 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
426 break;
428 case '?':
429 if (isc_commandline_option != '?')
430 fprintf(stderr, "%s: invalid argument -%c\n",
431 prog_name, isc_commandline_option);
432 /* FALLTHROUGH */
433 case 'h':
434 usage();
436 default:
437 fprintf(stderr, "%s: unhandled option -%c\n",
438 prog_name, isc_commandline_option);
439 exit(1);
443 if (workdir != NULL) {
444 result = isc_dir_chdir(workdir);
445 if (result != ISC_R_SUCCESS) {
446 fprintf(stderr, "isc_dir_chdir: %s: %s\n",
447 workdir, isc_result_totext(result));
448 exit(1);
452 if (inputformatstr != NULL) {
453 if (strcasecmp(inputformatstr, "text") == 0)
454 inputformat = dns_masterformat_text;
455 else if (strcasecmp(inputformatstr, "raw") == 0)
456 inputformat = dns_masterformat_raw;
457 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
458 inputformat = dns_masterformat_raw;
459 fprintf(stderr,
460 "WARNING: input format raw, version ignored\n");
461 } else if (strcasecmp(inputformatstr, "map") == 0) {
462 inputformat = dns_masterformat_map;
463 } else {
464 fprintf(stderr, "unknown file format: %s\n",
465 inputformatstr);
466 exit(1);
470 if (outputformatstr != NULL) {
471 if (strcasecmp(outputformatstr, "text") == 0) {
472 outputformat = dns_masterformat_text;
473 } else if (strcasecmp(outputformatstr, "raw") == 0) {
474 outputformat = dns_masterformat_raw;
475 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
476 char *end;
478 outputformat = dns_masterformat_raw;
479 rawversion = strtol(outputformatstr + 4, &end, 10);
480 if (end == outputformatstr + 4 || *end != '\0' ||
481 rawversion > 1U) {
482 fprintf(stderr,
483 "unknown raw format version\n");
484 exit(1);
486 } else if (strcasecmp(outputformatstr, "map") == 0) {
487 outputformat = dns_masterformat_map;
488 } else {
489 fprintf(stderr, "unknown file format: %s\n",
490 outputformatstr);
491 exit(1);
495 if (progmode == progmode_compile) {
496 dumpzone = 1; /* always dump */
497 logdump = !quiet;
498 if (output_filename == NULL) {
499 fprintf(stderr,
500 "output file required, but not specified\n");
501 usage();
505 if (output_filename != NULL)
506 dumpzone = 1;
509 * If we are outputing to stdout then send the informational
510 * output to stderr.
512 if (dumpzone &&
513 (output_filename == NULL ||
514 strcmp(output_filename, "-") == 0 ||
515 strcmp(output_filename, "/dev/fd/1") == 0 ||
516 strcmp(output_filename, "/dev/stdout") == 0)) {
517 errout = stderr;
518 logdump = ISC_FALSE;
521 if (isc_commandline_index + 2 != argc)
522 usage();
524 #ifdef _WIN32
525 InitSockets();
526 #endif
528 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
529 if (!quiet)
530 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
531 == ISC_R_SUCCESS);
532 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
533 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
534 == ISC_R_SUCCESS);
536 dns_result_register();
538 origin = argv[isc_commandline_index++];
539 filename = argv[isc_commandline_index++];
540 result = load_zone(mctx, origin, filename, inputformat, classname,
541 maxttl, &zone);
543 if (snset) {
544 dns_master_initrawheader(&header);
545 header.flags = DNS_MASTERRAW_SOURCESERIALSET;
546 header.sourceserial = serialnum;
547 dns_zone_setrawdata(zone, &header);
550 if (result == ISC_R_SUCCESS && dumpzone) {
551 if (logdump) {
552 fprintf(errout, "dump zone to %s...", output_filename);
553 fflush(errout);
555 result = dump_zone(origin, zone, output_filename,
556 outputformat, outputstyle, rawversion);
557 if (logdump)
558 fprintf(errout, "done\n");
561 if (!quiet && result == ISC_R_SUCCESS)
562 fprintf(errout, "OK\n");
563 destroy();
564 if (lctx != NULL)
565 isc_log_destroy(&lctx);
566 isc_hash_destroy();
567 isc_entropy_detach(&ectx);
568 isc_mem_destroy(&mctx);
569 #ifdef _WIN32
570 DestroySockets();
571 #endif
572 return ((result == ISC_R_SUCCESS) ? 0 : 1);