bind - Removed version tag from contrib directory and updated README.DRAGONFLY.
[dragonfly.git] / contrib / bind / bin / check / named-checkzone.c
1 /*
2  * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
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.
8  *
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.
16  */
17
18 /* $Id: named-checkzone.c,v 1.49.130.5 2009/05/29 02:18:32 marka Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <stdlib.h>
25
26 #include <isc/app.h>
27 #include <isc/commandline.h>
28 #include <isc/dir.h>
29 #include <isc/entropy.h>
30 #include <isc/hash.h>
31 #include <isc/log.h>
32 #include <isc/mem.h>
33 #include <isc/socket.h>
34 #include <isc/string.h>
35 #include <isc/task.h>
36 #include <isc/timer.h>
37 #include <isc/util.h>
38
39 #include <dns/db.h>
40 #include <dns/fixedname.h>
41 #include <dns/log.h>
42 #include <dns/masterdump.h>
43 #include <dns/name.h>
44 #include <dns/rdataclass.h>
45 #include <dns/rdataset.h>
46 #include <dns/result.h>
47 #include <dns/types.h>
48 #include <dns/zone.h>
49
50 #include "check-tool.h"
51
52 static int quiet = 0;
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;
62
63 #define ERRRET(result, function) \
64         do { \
65                 if (result != ISC_R_SUCCESS) { \
66                         if (!quiet) \
67                                 fprintf(stderr, "%s() returned %s\n", \
68                                         function, dns_result_totext(result)); \
69                         return (result); \
70                 } \
71         } while (0)
72
73 static void
74 usage(void) {
75         fprintf(stderr,
76                 "usage: %s [-djqvD] [-c class] [-o output] "
77                 "[-f inputformat] [-F outputformat] "
78                 "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
79                 "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
80                 "[-i (full|full-sibling|local|local-sibling|none)] "
81                 "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
82                 "[-W (ignore|warn)] "
83                 "zonename filename\n", prog_name);
84         exit(1);
85 }
86
87 static void
88 destroy(void) {
89         if (zone != NULL)
90                 dns_zone_detach(&zone);
91         dns_name_destroy();
92 }
93
94 /*% main processing routine */
95 int
96 main(int argc, char **argv) {
97         int c;
98         char *origin = NULL;
99         char *filename = NULL;
100         isc_log_t *lctx = NULL;
101         isc_result_t result;
102         char classname_in[] = "IN";
103         char *classname = classname_in;
104         const char *workdir = NULL;
105         const char *inputformatstr = NULL;
106         const char *outputformatstr = NULL;
107         dns_masterformat_t inputformat = dns_masterformat_text;
108         dns_masterformat_t outputformat = dns_masterformat_text;
109         FILE *errout = stdout;
110
111         outputstyle = &dns_master_style_full;
112
113         prog_name = strrchr(argv[0], '/');
114         if (prog_name == NULL)
115                 prog_name = strrchr(argv[0], '\\');
116         if (prog_name != NULL)
117                 prog_name++;
118         else
119                 prog_name = argv[0];
120         /*
121          * Libtool doesn't preserve the program name prior to final
122          * installation.  Remove the libtool prefix ("lt-").
123          */
124         if (strncmp(prog_name, "lt-", 3) == 0)
125                 prog_name += 3;
126
127 #define PROGCMP(X) \
128         (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
129
130         if (PROGCMP("named-checkzone"))
131                 progmode = progmode_check;
132         else if (PROGCMP("named-compilezone"))
133                 progmode = progmode_compile;
134         else
135                 INSIST(0);
136
137         /* Compilation specific defaults */
138         if (progmode == progmode_compile) {
139                 zone_options |= (DNS_ZONEOPT_CHECKNS |
140                                  DNS_ZONEOPT_FATALNS |
141                                  DNS_ZONEOPT_CHECKNAMES |
142                                  DNS_ZONEOPT_CHECKNAMESFAIL |
143                                  DNS_ZONEOPT_CHECKWILDCARD);
144         }
145
146 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
147
148         isc_commandline_errprint = ISC_FALSE;
149
150         while ((c = isc_commandline_parse(argc, argv,
151                                          "c:df:hi:jk:m:n:qs:t:o:vw:DF:M:S:W:"))
152                != EOF) {
153                 switch (c) {
154                 case 'c':
155                         classname = isc_commandline_argument;
156                         break;
157
158                 case 'd':
159                         debug++;
160                         break;
161
162                 case 'i':
163                         if (ARGCMP("full")) {
164                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
165                                                 DNS_ZONEOPT_CHECKSIBLING;
166                                 docheckmx = ISC_TRUE;
167                                 docheckns = ISC_TRUE;
168                                 dochecksrv = ISC_TRUE;
169                         } else if (ARGCMP("full-sibling")) {
170                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
171                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
172                                 docheckmx = ISC_TRUE;
173                                 docheckns = ISC_TRUE;
174                                 dochecksrv = ISC_TRUE;
175                         } else if (ARGCMP("local")) {
176                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
177                                 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
178                                 docheckmx = ISC_FALSE;
179                                 docheckns = ISC_FALSE;
180                                 dochecksrv = ISC_FALSE;
181                         } else if (ARGCMP("local-sibling")) {
182                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
183                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
184                                 docheckmx = ISC_FALSE;
185                                 docheckns = ISC_FALSE;
186                                 dochecksrv = ISC_FALSE;
187                         } else if (ARGCMP("none")) {
188                                 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
189                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
190                                 docheckmx = ISC_FALSE;
191                                 docheckns = ISC_FALSE;
192                                 dochecksrv = ISC_FALSE;
193                         } else {
194                                 fprintf(stderr, "invalid argument to -i: %s\n",
195                                         isc_commandline_argument);
196                                 exit(1);
197                         }
198                         break;
199
200                 case 'f':
201                         inputformatstr = isc_commandline_argument;
202                         break;
203
204                 case 'F':
205                         outputformatstr = isc_commandline_argument;
206                         break;
207
208                 case 'j':
209                         nomerge = ISC_FALSE;
210                         break;
211
212                 case 'k':
213                         if (ARGCMP("warn")) {
214                                 zone_options |= DNS_ZONEOPT_CHECKNAMES;
215                                 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
216                         } else if (ARGCMP("fail")) {
217                                 zone_options |= DNS_ZONEOPT_CHECKNAMES |
218                                                 DNS_ZONEOPT_CHECKNAMESFAIL;
219                         } else if (ARGCMP("ignore")) {
220                                 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
221                                                   DNS_ZONEOPT_CHECKNAMESFAIL);
222                         } else {
223                                 fprintf(stderr, "invalid argument to -k: %s\n",
224                                         isc_commandline_argument);
225                                 exit(1);
226                         }
227                         break;
228
229                 case 'n':
230                         if (ARGCMP("ignore")) {
231                                 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
232                                                   DNS_ZONEOPT_FATALNS);
233                         } else if (ARGCMP("warn")) {
234                                 zone_options |= DNS_ZONEOPT_CHECKNS;
235                                 zone_options &= ~DNS_ZONEOPT_FATALNS;
236                         } else if (ARGCMP("fail")) {
237                                 zone_options |= DNS_ZONEOPT_CHECKNS|
238                                                 DNS_ZONEOPT_FATALNS;
239                         } else {
240                                 fprintf(stderr, "invalid argument to -n: %s\n",
241                                         isc_commandline_argument);
242                                 exit(1);
243                         }
244                         break;
245
246                 case 'm':
247                         if (ARGCMP("warn")) {
248                                 zone_options |= DNS_ZONEOPT_CHECKMX;
249                                 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
250                         } else if (ARGCMP("fail")) {
251                                 zone_options |= DNS_ZONEOPT_CHECKMX |
252                                                 DNS_ZONEOPT_CHECKMXFAIL;
253                         } else if (ARGCMP("ignore")) {
254                                 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
255                                                   DNS_ZONEOPT_CHECKMXFAIL);
256                         } else {
257                                 fprintf(stderr, "invalid argument to -m: %s\n",
258                                         isc_commandline_argument);
259                                 exit(1);
260                         }
261                         break;
262
263                 case 'q':
264                         quiet++;
265                         break;
266
267                 case 't':
268                         result = isc_dir_chroot(isc_commandline_argument);
269                         if (result != ISC_R_SUCCESS) {
270                                 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
271                                         isc_commandline_argument,
272                                         isc_result_totext(result));
273                                 exit(1);
274                         }
275                         break;
276
277                 case 's':
278                         if (ARGCMP("full"))
279                                 outputstyle = &dns_master_style_full;
280                         else if (ARGCMP("relative")) {
281                                 outputstyle = &dns_master_style_default;
282                         } else {
283                                 fprintf(stderr,
284                                         "unknown or unsupported style: %s\n",
285                                         isc_commandline_argument);
286                                 exit(1);
287                         }
288                         break;
289
290                 case 'o':
291                         output_filename = isc_commandline_argument;
292                         break;
293
294                 case 'v':
295                         printf(VERSION "\n");
296                         exit(0);
297
298                 case 'w':
299                         workdir = isc_commandline_argument;
300                         break;
301
302                 case 'D':
303                         dumpzone++;
304                         break;
305
306                 case 'M':
307                         if (ARGCMP("fail")) {
308                                 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
309                                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
310                         } else if (ARGCMP("warn")) {
311                                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
312                                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
313                         } else if (ARGCMP("ignore")) {
314                                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
315                                 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
316                         } else {
317                                 fprintf(stderr, "invalid argument to -M: %s\n",
318                                         isc_commandline_argument);
319                                 exit(1);
320                         }
321                         break;
322
323                 case 'S':
324                         if (ARGCMP("fail")) {
325                                 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
326                                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
327                         } else if (ARGCMP("warn")) {
328                                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
329                                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
330                         } else if (ARGCMP("ignore")) {
331                                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
332                                 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
333                         } else {
334                                 fprintf(stderr, "invalid argument to -S: %s\n",
335                                         isc_commandline_argument);
336                                 exit(1);
337                         }
338                         break;
339
340                 case 'W':
341                         if (ARGCMP("warn"))
342                                 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
343                         else if (ARGCMP("ignore"))
344                                 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
345                         break;
346
347                 case '?':
348                         if (isc_commandline_option != '?')
349                                 fprintf(stderr, "%s: invalid argument -%c\n",
350                                         prog_name, isc_commandline_option);
351                 case 'h':
352                         usage();
353
354                 default:
355                         fprintf(stderr, "%s: unhandled option -%c\n",
356                                 prog_name, isc_commandline_option);
357                         exit(1);
358                 }
359         }
360
361         if (workdir != NULL) {
362                 result = isc_dir_chdir(workdir);
363                 if (result != ISC_R_SUCCESS) {
364                         fprintf(stderr, "isc_dir_chdir: %s: %s\n",
365                                 workdir, isc_result_totext(result));
366                         exit(1);
367                 }
368         }
369
370         if (inputformatstr != NULL) {
371                 if (strcasecmp(inputformatstr, "text") == 0)
372                         inputformat = dns_masterformat_text;
373                 else if (strcasecmp(inputformatstr, "raw") == 0)
374                         inputformat = dns_masterformat_raw;
375                 else {
376                         fprintf(stderr, "unknown file format: %s\n",
377                             inputformatstr);
378                         exit(1);
379                 }
380         }
381
382         if (outputformatstr != NULL) {
383                 if (strcasecmp(outputformatstr, "text") == 0)
384                         outputformat = dns_masterformat_text;
385                 else if (strcasecmp(outputformatstr, "raw") == 0)
386                         outputformat = dns_masterformat_raw;
387                 else {
388                         fprintf(stderr, "unknown file format: %s\n",
389                                 outputformatstr);
390                         exit(1);
391                 }
392         }
393
394         if (progmode == progmode_compile) {
395                 dumpzone = 1;   /* always dump */
396                 if (output_filename == NULL) {
397                         fprintf(stderr,
398                                 "output file required, but not specified\n");
399                         usage();
400                 }
401         }
402
403         if (output_filename != NULL)
404                 dumpzone = 1;
405
406         /*
407          * If we are outputing to stdout then send the informational
408          * output to stderr.
409          */
410         if (dumpzone &&
411             (output_filename == NULL ||
412              strcmp(output_filename, "-") == 0 ||
413              strcmp(output_filename, "/dev/fd/1") == 0 ||
414              strcmp(output_filename, "/dev/stdout") == 0))
415                 errout = stderr;
416
417         if (isc_commandline_index + 2 != argc)
418                 usage();
419
420         RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
421         if (!quiet)
422                 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
423                               == ISC_R_SUCCESS);
424         RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
425         RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
426                       == ISC_R_SUCCESS);
427
428         dns_result_register();
429
430         origin = argv[isc_commandline_index++];
431         filename = argv[isc_commandline_index++];
432         result = load_zone(mctx, origin, filename, inputformat, classname,
433                            &zone);
434
435         if (result == ISC_R_SUCCESS && dumpzone) {
436                 if (!quiet && progmode == progmode_compile) {
437                         fprintf(errout, "dump zone to %s...", output_filename);
438                         fflush(errout);
439                 }
440                 result = dump_zone(origin, zone, output_filename,
441                                    outputformat, outputstyle);
442                 if (!quiet && progmode == progmode_compile)
443                         fprintf(errout, "done\n");
444         }
445
446         if (!quiet && result == ISC_R_SUCCESS)
447                 fprintf(errout, "OK\n");
448         destroy();
449         if (lctx != NULL)
450                 isc_log_destroy(&lctx);
451         isc_hash_destroy();
452         isc_entropy_detach(&ectx);
453         isc_mem_destroy(&mctx);
454         return ((result == ISC_R_SUCCESS) ? 0 : 1);
455 }