Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.3 / bin / check / named-checkconf.c
1 /*
2  * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2002  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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-checkconf.c,v 1.12.12.11 2006/03/02 00:37:20 marka Exp $ */
19
20 #include <config.h>
21
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25
26 #include <isc/commandline.h>
27 #include <isc/dir.h>
28 #include <isc/entropy.h>
29 #include <isc/hash.h>
30 #include <isc/log.h>
31 #include <isc/mem.h>
32 #include <isc/result.h>
33 #include <isc/string.h>
34 #include <isc/util.h>
35
36 #include <isccfg/namedconf.h>
37
38 #include <bind9/check.h>
39
40 #include <dns/fixedname.h>
41 #include <dns/log.h>
42 #include <dns/result.h>
43
44 #include "check-tool.h"
45
46 isc_log_t *logc = NULL;
47
48 #define CHECK(r)\
49         do { \
50                 result = (r); \
51                 if (result != ISC_R_SUCCESS) \
52                         goto cleanup; \
53         } while (0)
54
55 static void
56 usage(void) {
57         fprintf(stderr, "usage: named-checkconf [-j] [-v] [-z] [-t directory] "
58                 "[named.conf]\n");
59         exit(1);
60 }
61
62 static isc_result_t
63 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
64         isc_result_t result;
65         const char *directory;
66
67         REQUIRE(strcasecmp("directory", clausename) == 0);
68
69         UNUSED(arg);
70         UNUSED(clausename);
71
72         /*
73          * Change directory.
74          */
75         directory = cfg_obj_asstring(obj);
76         result = isc_dir_chdir(directory);
77         if (result != ISC_R_SUCCESS) {
78                 cfg_obj_log(obj, logc, ISC_LOG_ERROR,
79                             "change directory to '%s' failed: %s\n",
80                             directory, isc_result_totext(result));
81                 return (result);
82         }
83
84         return (ISC_R_SUCCESS);
85 }
86
87 static isc_result_t
88 configure_zone(const char *vclass, const char *view,
89                const cfg_obj_t *zconfig, isc_mem_t *mctx)
90 {
91         isc_result_t result;
92         const char *zclass;
93         const char *zname;
94         const char *zfile;
95         const cfg_obj_t *zoptions = NULL;
96         const cfg_obj_t *classobj = NULL;
97         const cfg_obj_t *typeobj = NULL;
98         const cfg_obj_t *fileobj = NULL;
99         const cfg_obj_t *dbobj = NULL;
100
101         zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
102         classobj = cfg_tuple_get(zconfig, "class");
103         if (!cfg_obj_isstring(classobj))
104                 zclass = vclass;
105         else
106                 zclass = cfg_obj_asstring(classobj);
107         zoptions = cfg_tuple_get(zconfig, "options");
108         cfg_map_get(zoptions, "type", &typeobj);
109         if (typeobj == NULL)
110                 return (ISC_R_FAILURE);
111         if (strcasecmp(cfg_obj_asstring(typeobj), "master") != 0)
112                 return (ISC_R_SUCCESS);
113         cfg_map_get(zoptions, "database", &dbobj);
114         if (dbobj != NULL)
115                 return (ISC_R_SUCCESS);
116         cfg_map_get(zoptions, "file", &fileobj);
117         if (fileobj == NULL)
118                 return (ISC_R_FAILURE);
119         zfile = cfg_obj_asstring(fileobj);
120         result = load_zone(mctx, zname, zfile, zclass, NULL);
121         if (result != ISC_R_SUCCESS)
122                 fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass,
123                         dns_result_totext(result));
124         return(result);
125 }
126
127 static isc_result_t
128 configure_view(const char *vclass, const char *view, const cfg_obj_t *config,
129                const cfg_obj_t *vconfig, isc_mem_t *mctx)
130 {
131         const cfg_listelt_t *element;
132         const cfg_obj_t *voptions;
133         const cfg_obj_t *zonelist;
134         isc_result_t result = ISC_R_SUCCESS;
135         isc_result_t tresult;
136
137         voptions = NULL;
138         if (vconfig != NULL)
139                 voptions = cfg_tuple_get(vconfig, "options");
140
141         zonelist = NULL;
142         if (voptions != NULL)
143                 (void)cfg_map_get(voptions, "zone", &zonelist);
144         else
145                 (void)cfg_map_get(config, "zone", &zonelist);
146
147         for (element = cfg_list_first(zonelist);
148              element != NULL;
149              element = cfg_list_next(element))
150         {
151                 const cfg_obj_t *zconfig = cfg_listelt_value(element);
152                 tresult = configure_zone(vclass, view, zconfig, mctx);
153                 if (tresult != ISC_R_SUCCESS)
154                         result = tresult;
155         }
156         return (result);
157 }
158
159
160 static isc_result_t
161 load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) {
162         const cfg_listelt_t *element;
163         const cfg_obj_t *classobj;
164         const cfg_obj_t *views;
165         const cfg_obj_t *vconfig;
166         const char *vclass;
167         isc_result_t result = ISC_R_SUCCESS;
168         isc_result_t tresult;
169
170         views = NULL;
171
172         (void)cfg_map_get(config, "view", &views);
173         for (element = cfg_list_first(views);
174              element != NULL;
175              element = cfg_list_next(element))
176         {
177                 const char *vname;
178
179                 vclass = "IN";
180                 vconfig = cfg_listelt_value(element);
181                 if (vconfig != NULL) {
182                         classobj = cfg_tuple_get(vconfig, "class");
183                         if (cfg_obj_isstring(classobj))
184                                 vclass = cfg_obj_asstring(classobj);
185                 }
186                 vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
187                 tresult = configure_view(vclass, vname, config, vconfig, mctx);
188                 if (tresult != ISC_R_SUCCESS)
189                         result = tresult;
190         }
191
192         if (views == NULL) {
193                 tresult = configure_view("IN", "_default", config, NULL, mctx);
194                 if (tresult != ISC_R_SUCCESS)
195                         result = tresult;
196         }
197         return (result);
198 }
199
200 int
201 main(int argc, char **argv) {
202         int c;
203         cfg_parser_t *parser = NULL;
204         cfg_obj_t *config = NULL;
205         const char *conffile = NULL;
206         isc_mem_t *mctx = NULL;
207         isc_result_t result;
208         int exit_status = 0;
209         isc_entropy_t *ectx = NULL;
210         isc_boolean_t load_zones = ISC_FALSE;
211         
212         while ((c = isc_commandline_parse(argc, argv, "djt:vz")) != EOF) {
213                 switch (c) {
214                 case 'd':
215                         debug++;
216                         break;
217
218                 case 'j':
219                         nomerge = ISC_FALSE;
220                         break;
221
222                 case 't':
223                         result = isc_dir_chroot(isc_commandline_argument);
224                         if (result != ISC_R_SUCCESS) {
225                                 fprintf(stderr, "isc_dir_chroot: %s\n",
226                                         isc_result_totext(result));
227                                 exit(1);
228                         }
229                         result = isc_dir_chdir("/");
230                         if (result != ISC_R_SUCCESS) {
231                                 fprintf(stderr, "isc_dir_chdir: %s\n",
232                                         isc_result_totext(result));
233                                 exit(1);
234                         }
235                         break;
236
237                 case 'v':
238                         printf(VERSION "\n");
239                         exit(0);
240
241                 case 'z':
242                         load_zones = ISC_TRUE;
243                         break;
244
245                 default:
246                         usage();
247                 }
248         }
249
250         if (argv[isc_commandline_index] != NULL)
251                 conffile = argv[isc_commandline_index];
252         if (conffile == NULL || conffile[0] == '\0')
253                 conffile = NAMED_CONFFILE;
254
255         RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
256
257         RUNTIME_CHECK(setup_logging(mctx, &logc) == ISC_R_SUCCESS);
258
259         RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
260         RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
261                       == ISC_R_SUCCESS);
262
263         dns_result_register();
264
265         RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS);
266
267         cfg_parser_setcallback(parser, directory_callback, NULL);
268
269         if (cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config) !=
270             ISC_R_SUCCESS)
271                 exit(1);
272
273         result = bind9_check_namedconf(config, logc, mctx);
274         if (result != ISC_R_SUCCESS)
275                 exit_status = 1;
276
277         if (result == ISC_R_SUCCESS && load_zones) {
278                 dns_log_init(logc);
279                 dns_log_setcontext(logc);
280                 result = load_zones_fromconfig(config, mctx);
281                 if (result != ISC_R_SUCCESS)
282                         exit_status = 1;
283         }
284
285         cfg_obj_destroy(parser, &config);
286
287         cfg_parser_destroy(&parser);
288
289         isc_log_destroy(&logc);
290
291         isc_hash_destroy();
292         isc_entropy_detach(&ectx);
293
294         isc_mem_destroy(&mctx);
295
296         return (exit_status);
297 }