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