]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/bin/check/named-checkzone.c
Merge OpenBSM 1.1 alpha 2 from the OpenBSM vendor branch to head, both
[FreeBSD/FreeBSD.git] / contrib / bind9 / bin / check / named-checkzone.c
1 /*
2  * Copyright (C) 2004-2007  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.29.18.19 2007/08/28 07:19:55 tbox 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|local|none)] [-M (ignore|warn|fail)] "
81                 "[-S (ignore|warn|fail)] [-W (ignore|warn)] "
82                 "zonename filename\n", prog_name);
83         exit(1);
84 }
85
86 static void
87 destroy(void) {
88         if (zone != NULL)
89                 dns_zone_detach(&zone);
90         dns_name_destroy();
91 }
92
93 /*% main processing routine */
94 int
95 main(int argc, char **argv) {
96         int c;
97         char *origin = NULL;
98         char *filename = NULL;
99         isc_log_t *lctx = NULL;
100         isc_result_t result;
101         char classname_in[] = "IN";
102         char *classname = classname_in;
103         const char *workdir = NULL;
104         const char *inputformatstr = NULL;
105         const char *outputformatstr = NULL;
106         dns_masterformat_t inputformat = dns_masterformat_text;
107         dns_masterformat_t outputformat = dns_masterformat_text;
108
109         outputstyle = &dns_master_style_full;
110
111         prog_name = strrchr(argv[0], '/');
112         if (prog_name == NULL)
113                 prog_name = strrchr(argv[0], '\\');
114         if (prog_name != NULL)
115                 prog_name++;
116         else
117                 prog_name = argv[0];
118         /*
119          * Libtool doesn't preserve the program name prior to final
120          * installation.  Remove the libtool prefix ("lt-").
121          */
122         if (strncmp(prog_name, "lt-", 3) == 0)
123                 prog_name += 3;
124         if (strcmp(prog_name, "named-checkzone") == 0)
125                 progmode = progmode_check;
126         else if (strcmp(prog_name, "named-compilezone") == 0)
127                 progmode = progmode_compile;
128         else
129                 INSIST(0);
130
131         /* Compilation specific defaults */
132         if (progmode == progmode_compile) {
133                 zone_options |= (DNS_ZONEOPT_CHECKNS |
134                                  DNS_ZONEOPT_FATALNS |
135                                  DNS_ZONEOPT_CHECKNAMES |
136                                  DNS_ZONEOPT_CHECKNAMESFAIL |
137                                  DNS_ZONEOPT_CHECKWILDCARD);
138         }
139
140 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
141
142         while ((c = isc_commandline_parse(argc, argv,
143                                           "c:df:i:jk:m:n:qs:t:o:vw:DF:M:S:W:"))
144                != EOF) {
145                 switch (c) {
146                 case 'c':
147                         classname = isc_commandline_argument;
148                         break;
149
150                 case 'd':
151                         debug++;
152                         break;
153
154                 case 'i':
155                         if (ARGCMP("full")) {
156                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
157                                                 DNS_ZONEOPT_CHECKSIBLING;
158                                 docheckmx = ISC_TRUE;
159                                 docheckns = ISC_TRUE;
160                                 dochecksrv = ISC_TRUE;
161                         } else if (ARGCMP("full-sibling")) {
162                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
163                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
164                                 docheckmx = ISC_TRUE;
165                                 docheckns = ISC_TRUE;
166                                 dochecksrv = ISC_TRUE;
167                         } else if (ARGCMP("local")) {
168                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
169                                 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
170                                 docheckmx = ISC_FALSE;
171                                 docheckns = ISC_FALSE;
172                                 dochecksrv = ISC_FALSE;
173                         } else if (ARGCMP("local-sibling")) {
174                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
175                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
176                                 docheckmx = ISC_FALSE;
177                                 docheckns = ISC_FALSE;
178                                 dochecksrv = ISC_FALSE;
179                         } else if (ARGCMP("none")) {
180                                 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
181                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
182                                 docheckmx = ISC_FALSE;
183                                 docheckns = ISC_FALSE;
184                                 dochecksrv = ISC_FALSE;
185                         } else {
186                                 fprintf(stderr, "invalid argument to -i: %s\n",
187                                         isc_commandline_argument);
188                                 exit(1);
189                         }
190                         break;
191
192                 case 'f':
193                         inputformatstr = isc_commandline_argument;
194                         break;
195
196                 case 'F':
197                         outputformatstr = isc_commandline_argument;
198                         break;
199
200                 case 'j':
201                         nomerge = ISC_FALSE;
202                         break;
203
204                 case 'k':
205                         if (ARGCMP("warn")) {
206                                 zone_options |= DNS_ZONEOPT_CHECKNAMES;
207                                 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
208                         } else if (ARGCMP("fail")) {
209                                 zone_options |= DNS_ZONEOPT_CHECKNAMES |
210                                                 DNS_ZONEOPT_CHECKNAMESFAIL;
211                         } else if (ARGCMP("ignore")) {
212                                 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
213                                                   DNS_ZONEOPT_CHECKNAMESFAIL);
214                         } else {
215                                 fprintf(stderr, "invalid argument to -k: %s\n",
216                                         isc_commandline_argument);
217                                 exit(1);
218                         }
219                         break;
220
221                 case 'n':
222                         if (ARGCMP("ignore")) {
223                                 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
224                                                   DNS_ZONEOPT_FATALNS);
225                         } else if (ARGCMP("warn")) {
226                                 zone_options |= DNS_ZONEOPT_CHECKNS;
227                                 zone_options &= ~DNS_ZONEOPT_FATALNS;
228                         } else if (ARGCMP("fail")) {
229                                 zone_options |= DNS_ZONEOPT_CHECKNS|
230                                                 DNS_ZONEOPT_FATALNS;
231                         } else {
232                                 fprintf(stderr, "invalid argument to -n: %s\n",
233                                         isc_commandline_argument);
234                                 exit(1);
235                         }
236                         break;
237
238                 case 'm':
239                         if (ARGCMP("warn")) {
240                                 zone_options |= DNS_ZONEOPT_CHECKMX;
241                                 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
242                         } else if (ARGCMP("fail")) {
243                                 zone_options |= DNS_ZONEOPT_CHECKMX |
244                                                 DNS_ZONEOPT_CHECKMXFAIL;
245                         } else if (ARGCMP("ignore")) {
246                                 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
247                                                   DNS_ZONEOPT_CHECKMXFAIL);
248                         } else {
249                                 fprintf(stderr, "invalid argument to -m: %s\n",
250                                         isc_commandline_argument);
251                                 exit(1);
252                         }
253                         break;
254
255                 case 'q':
256                         quiet++;
257                         break;
258
259                 case 't':
260                         result = isc_dir_chroot(isc_commandline_argument);
261                         if (result != ISC_R_SUCCESS) {
262                                 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
263                                         isc_commandline_argument,
264                                         isc_result_totext(result));
265                                 exit(1);
266                         }
267                         result = isc_dir_chdir("/");
268                         if (result != ISC_R_SUCCESS) {
269                                 fprintf(stderr, "isc_dir_chdir: %s\n",
270                                         isc_result_totext(result));
271                                 exit(1);
272                         }
273                         break;
274
275                 case 's':
276                         if (ARGCMP("full"))
277                                 outputstyle = &dns_master_style_full;
278                         else if (ARGCMP("relative")) {
279                                 outputstyle = &dns_master_style_default;
280                         } else {
281                                 fprintf(stderr,
282                                         "unknown or unsupported style: %s\n",
283                                         isc_commandline_argument);
284                                 exit(1);
285                         }
286                         break;
287
288                 case 'o':
289                         output_filename = isc_commandline_argument;
290                         break;
291
292                 case 'v':
293                         printf(VERSION "\n");
294                         exit(0);
295
296                 case 'w':
297                         workdir = isc_commandline_argument;
298                         break;
299
300                 case 'D':
301                         dumpzone++;
302                         break;
303
304                 case 'M':
305                         if (ARGCMP("fail")) {
306                                 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
307                                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
308                         } else if (ARGCMP("warn")) {
309                                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
310                                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
311                         } else if (ARGCMP("ignore")) {
312                                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
313                                 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
314                         } else {
315                                 fprintf(stderr, "invalid argument to -M: %s\n",
316                                         isc_commandline_argument);
317                                 exit(1);
318                         }
319                         break;
320
321                 case 'S':
322                         if (ARGCMP("fail")) {
323                                 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
324                                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
325                         } else if (ARGCMP("warn")) {
326                                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
327                                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
328                         } else if (ARGCMP("ignore")) {
329                                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
330                                 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
331                         } else {
332                                 fprintf(stderr, "invalid argument to -S: %s\n",
333                                         isc_commandline_argument);
334                                 exit(1);
335                         }
336                         break;
337
338                 case 'W':
339                         if (ARGCMP("warn"))
340                                 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
341                         else if (ARGCMP("ignore"))
342                                 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
343                         break;
344
345                 default:
346                         usage();
347                 }
348         }
349
350         if (progmode == progmode_compile) {
351                 dumpzone = 1;   /* always dump */
352                 if (output_filename == NULL) {
353                         fprintf(stderr,
354                                 "output file required, but not specified\n");
355                         usage();
356                 }
357         }
358
359         if (workdir != NULL) {
360                 result = isc_dir_chdir(workdir);
361                 if (result != ISC_R_SUCCESS) {
362                         fprintf(stderr, "isc_dir_chdir: %s: %s\n",
363                                 workdir, isc_result_totext(result));
364                         exit(1);
365                 }
366         }
367
368         if (inputformatstr != NULL) {
369                 if (strcasecmp(inputformatstr, "text") == 0)
370                         inputformat = dns_masterformat_text;
371                 else if (strcasecmp(inputformatstr, "raw") == 0)
372                         inputformat = dns_masterformat_raw;
373                 else {
374                         fprintf(stderr, "unknown file format: %s\n",
375                             inputformatstr);
376                         exit(1);
377                 }
378         }
379
380         if (outputformatstr != NULL) {
381                 if (strcasecmp(outputformatstr, "text") == 0)
382                         outputformat = dns_masterformat_text;
383                 else if (strcasecmp(outputformatstr, "raw") == 0)
384                         outputformat = dns_masterformat_raw;
385                 else {
386                         fprintf(stderr, "unknown file format: %s\n",
387                                 outputformatstr);
388                         exit(1);
389                 }
390         }
391
392         if (isc_commandline_index + 2 > argc)
393                 usage();
394
395         RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
396         if (!quiet)
397                 RUNTIME_CHECK(setup_logging(mctx, &lctx) == ISC_R_SUCCESS);
398         RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
399         RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
400                       == ISC_R_SUCCESS);
401
402         dns_result_register();
403
404         origin = argv[isc_commandline_index++];
405         filename = argv[isc_commandline_index++];
406         result = load_zone(mctx, origin, filename, inputformat, classname,
407                            &zone);
408
409         if (result == ISC_R_SUCCESS && dumpzone) {
410                 if (!quiet && progmode == progmode_compile) {
411                         fprintf(stdout, "dump zone to %s...", output_filename);
412                         fflush(stdout);
413                 }
414                 result = dump_zone(origin, zone, output_filename,
415                                    outputformat, outputstyle);
416                 if (!quiet && progmode == progmode_compile)
417                         fprintf(stdout, "done\n");
418         }
419
420         if (!quiet && result == ISC_R_SUCCESS)
421                 fprintf(stdout, "OK\n");
422         destroy();
423         if (lctx != NULL)
424                 isc_log_destroy(&lctx);
425         isc_hash_destroy();
426         isc_entropy_detach(&ectx);
427         isc_mem_destroy(&mctx);
428         return ((result == ISC_R_SUCCESS) ? 0 : 1);
429 }