2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2002 Internet Software Consortium.
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.
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.
18 /* $Id: named-checkconf.c,v 1.28.18.14 2006/02/28 03:10:47 marka Exp $ */
28 #include <isc/commandline.h>
30 #include <isc/entropy.h>
34 #include <isc/result.h>
35 #include <isc/string.h>
38 #include <isccfg/namedconf.h>
40 #include <bind9/check.h>
42 #include <dns/fixedname.h>
45 #include <dns/result.h>
48 #include "check-tool.h"
50 isc_log_t
*logc
= NULL
;
55 if (result != ISC_R_SUCCESS) \
62 fprintf(stderr
, "usage: named-checkconf [-j] [-v] [-z] [-t directory] "
67 /*% directory callback */
69 directory_callback(const char *clausename
, const cfg_obj_t
*obj
, void *arg
) {
71 const char *directory
;
73 REQUIRE(strcasecmp("directory", clausename
) == 0);
81 directory
= cfg_obj_asstring(obj
);
82 result
= isc_dir_chdir(directory
);
83 if (result
!= ISC_R_SUCCESS
) {
84 cfg_obj_log(obj
, logc
, ISC_LOG_ERROR
,
85 "change directory to '%s' failed: %s\n",
86 directory
, isc_result_totext(result
));
90 return (ISC_R_SUCCESS
);
94 get_maps(const cfg_obj_t
**maps
, const char *name
, const cfg_obj_t
**obj
) {
99 if (cfg_map_get(maps
[i
], name
, obj
) == ISC_R_SUCCESS
)
105 get_checknames(const cfg_obj_t
**maps
, const cfg_obj_t
**obj
) {
106 const cfg_listelt_t
*element
;
107 const cfg_obj_t
*checknames
;
108 const cfg_obj_t
*type
;
109 const cfg_obj_t
*value
;
117 result
= cfg_map_get(maps
[i
], "check-names", &checknames
);
118 if (result
!= ISC_R_SUCCESS
)
120 if (checknames
!= NULL
&& !cfg_obj_islist(checknames
)) {
124 for (element
= cfg_list_first(checknames
);
126 element
= cfg_list_next(element
)) {
127 value
= cfg_listelt_value(element
);
128 type
= cfg_tuple_get(value
, "type");
129 if (strcasecmp(cfg_obj_asstring(type
), "master") != 0)
131 *obj
= cfg_tuple_get(value
, "mode");
138 config_get(const cfg_obj_t
**maps
, const char *name
, const cfg_obj_t
**obj
) {
143 return (ISC_R_NOTFOUND
);
144 if (cfg_map_get(maps
[i
], name
, obj
) == ISC_R_SUCCESS
)
145 return (ISC_R_SUCCESS
);
149 /*% configure the zone */
151 configure_zone(const char *vclass
, const char *view
,
152 const cfg_obj_t
*zconfig
, const cfg_obj_t
*vconfig
,
153 const cfg_obj_t
*config
, isc_mem_t
*mctx
)
160 const cfg_obj_t
*maps
[4];
161 const cfg_obj_t
*zoptions
= NULL
;
162 const cfg_obj_t
*classobj
= NULL
;
163 const cfg_obj_t
*typeobj
= NULL
;
164 const cfg_obj_t
*fileobj
= NULL
;
165 const cfg_obj_t
*dbobj
= NULL
;
166 const cfg_obj_t
*obj
= NULL
;
167 const cfg_obj_t
*fmtobj
= NULL
;
168 dns_masterformat_t masterformat
;
170 zone_options
= DNS_ZONEOPT_CHECKNS
| DNS_ZONEOPT_MANYERRORS
;
172 zname
= cfg_obj_asstring(cfg_tuple_get(zconfig
, "name"));
173 classobj
= cfg_tuple_get(zconfig
, "class");
174 if (!cfg_obj_isstring(classobj
))
177 zclass
= cfg_obj_asstring(classobj
);
179 zoptions
= cfg_tuple_get(zconfig
, "options");
180 maps
[i
++] = zoptions
;
182 maps
[i
++] = cfg_tuple_get(vconfig
, "options");
183 if (config
!= NULL
) {
184 cfg_map_get(config
, "options", &obj
);
190 cfg_map_get(zoptions
, "type", &typeobj
);
192 return (ISC_R_FAILURE
);
193 if (strcasecmp(cfg_obj_asstring(typeobj
), "master") != 0)
194 return (ISC_R_SUCCESS
);
195 cfg_map_get(zoptions
, "database", &dbobj
);
197 return (ISC_R_SUCCESS
);
198 cfg_map_get(zoptions
, "file", &fileobj
);
200 return (ISC_R_FAILURE
);
201 zfile
= cfg_obj_asstring(fileobj
);
204 if (get_maps(maps
, "check-mx", &obj
)) {
205 if (strcasecmp(cfg_obj_asstring(obj
), "warn") == 0) {
206 zone_options
|= DNS_ZONEOPT_CHECKMX
;
207 zone_options
&= ~DNS_ZONEOPT_CHECKMXFAIL
;
208 } else if (strcasecmp(cfg_obj_asstring(obj
), "fail") == 0) {
209 zone_options
|= DNS_ZONEOPT_CHECKMX
;
210 zone_options
|= DNS_ZONEOPT_CHECKMXFAIL
;
211 } else if (strcasecmp(cfg_obj_asstring(obj
), "ignore") == 0) {
212 zone_options
&= ~DNS_ZONEOPT_CHECKMX
;
213 zone_options
&= ~DNS_ZONEOPT_CHECKMXFAIL
;
217 zone_options
|= DNS_ZONEOPT_CHECKMX
;
218 zone_options
&= ~DNS_ZONEOPT_CHECKMXFAIL
;
222 if (get_maps(maps
, "check-integrity", &obj
)) {
223 if (cfg_obj_asboolean(obj
))
224 zone_options
|= DNS_ZONEOPT_CHECKINTEGRITY
;
226 zone_options
&= ~DNS_ZONEOPT_CHECKINTEGRITY
;
230 if (get_maps(maps
, "check-mx-cname", &obj
)) {
231 if (strcasecmp(cfg_obj_asstring(obj
), "warn") == 0) {
232 zone_options
|= DNS_ZONEOPT_WARNMXCNAME
;
233 zone_options
&= ~DNS_ZONEOPT_IGNOREMXCNAME
;
234 } else if (strcasecmp(cfg_obj_asstring(obj
), "fail") == 0) {
235 zone_options
&= ~DNS_ZONEOPT_WARNMXCNAME
;
236 zone_options
&= ~DNS_ZONEOPT_IGNOREMXCNAME
;
237 } else if (strcasecmp(cfg_obj_asstring(obj
), "ignore") == 0) {
238 zone_options
|= DNS_ZONEOPT_WARNMXCNAME
;
239 zone_options
|= DNS_ZONEOPT_IGNOREMXCNAME
;
243 zone_options
|= DNS_ZONEOPT_WARNMXCNAME
;
244 zone_options
&= ~DNS_ZONEOPT_IGNOREMXCNAME
;
248 if (get_maps(maps
, "check-srv-cname", &obj
)) {
249 if (strcasecmp(cfg_obj_asstring(obj
), "warn") == 0) {
250 zone_options
|= DNS_ZONEOPT_WARNSRVCNAME
;
251 zone_options
&= ~DNS_ZONEOPT_IGNORESRVCNAME
;
252 } else if (strcasecmp(cfg_obj_asstring(obj
), "fail") == 0) {
253 zone_options
&= ~DNS_ZONEOPT_WARNSRVCNAME
;
254 zone_options
&= ~DNS_ZONEOPT_IGNORESRVCNAME
;
255 } else if (strcasecmp(cfg_obj_asstring(obj
), "ignore") == 0) {
256 zone_options
|= DNS_ZONEOPT_WARNSRVCNAME
;
257 zone_options
|= DNS_ZONEOPT_IGNORESRVCNAME
;
261 zone_options
|= DNS_ZONEOPT_WARNSRVCNAME
;
262 zone_options
&= ~DNS_ZONEOPT_IGNORESRVCNAME
;
266 if (get_maps(maps
, "check-sibling", &obj
)) {
267 if (cfg_obj_asboolean(obj
))
268 zone_options
|= DNS_ZONEOPT_CHECKSIBLING
;
270 zone_options
&= ~DNS_ZONEOPT_CHECKSIBLING
;
274 if (get_checknames(maps
, &obj
)) {
275 if (strcasecmp(cfg_obj_asstring(obj
), "warn") == 0) {
276 zone_options
|= DNS_ZONEOPT_CHECKNAMES
;
277 zone_options
&= ~DNS_ZONEOPT_CHECKNAMESFAIL
;
278 } else if (strcasecmp(cfg_obj_asstring(obj
), "fail") == 0) {
279 zone_options
|= DNS_ZONEOPT_CHECKNAMES
;
280 zone_options
|= DNS_ZONEOPT_CHECKNAMESFAIL
;
281 } else if (strcasecmp(cfg_obj_asstring(obj
), "ignore") == 0) {
282 zone_options
&= ~DNS_ZONEOPT_CHECKNAMES
;
283 zone_options
&= ~DNS_ZONEOPT_CHECKNAMESFAIL
;
287 zone_options
|= DNS_ZONEOPT_CHECKNAMES
;
288 zone_options
|= DNS_ZONEOPT_CHECKNAMESFAIL
;
291 masterformat
= dns_masterformat_text
;
293 result
= config_get(maps
, "masterfile-format", &fmtobj
);
294 if (result
== ISC_R_SUCCESS
) {
295 const char *masterformatstr
= cfg_obj_asstring(fmtobj
);
296 if (strcasecmp(masterformatstr
, "text") == 0)
297 masterformat
= dns_masterformat_text
;
298 else if (strcasecmp(masterformatstr
, "raw") == 0)
299 masterformat
= dns_masterformat_raw
;
304 result
= load_zone(mctx
, zname
, zfile
, masterformat
, zclass
, NULL
);
305 if (result
!= ISC_R_SUCCESS
)
306 fprintf(stderr
, "%s/%s/%s: %s\n", view
, zname
, zclass
,
307 dns_result_totext(result
));
311 /*% configure a view */
313 configure_view(const char *vclass
, const char *view
, const cfg_obj_t
*config
,
314 const cfg_obj_t
*vconfig
, isc_mem_t
*mctx
)
316 const cfg_listelt_t
*element
;
317 const cfg_obj_t
*voptions
;
318 const cfg_obj_t
*zonelist
;
319 isc_result_t result
= ISC_R_SUCCESS
;
320 isc_result_t tresult
;
324 voptions
= cfg_tuple_get(vconfig
, "options");
327 if (voptions
!= NULL
)
328 (void)cfg_map_get(voptions
, "zone", &zonelist
);
330 (void)cfg_map_get(config
, "zone", &zonelist
);
332 for (element
= cfg_list_first(zonelist
);
334 element
= cfg_list_next(element
))
336 const cfg_obj_t
*zconfig
= cfg_listelt_value(element
);
337 tresult
= configure_zone(vclass
, view
, zconfig
, vconfig
,
339 if (tresult
!= ISC_R_SUCCESS
)
346 /*% load zones from the configuration */
348 load_zones_fromconfig(const cfg_obj_t
*config
, isc_mem_t
*mctx
) {
349 const cfg_listelt_t
*element
;
350 const cfg_obj_t
*classobj
;
351 const cfg_obj_t
*views
;
352 const cfg_obj_t
*vconfig
;
354 isc_result_t result
= ISC_R_SUCCESS
;
355 isc_result_t tresult
;
359 (void)cfg_map_get(config
, "view", &views
);
360 for (element
= cfg_list_first(views
);
362 element
= cfg_list_next(element
))
367 vconfig
= cfg_listelt_value(element
);
368 if (vconfig
!= NULL
) {
369 classobj
= cfg_tuple_get(vconfig
, "class");
370 if (cfg_obj_isstring(classobj
))
371 vclass
= cfg_obj_asstring(classobj
);
373 vname
= cfg_obj_asstring(cfg_tuple_get(vconfig
, "name"));
374 tresult
= configure_view(vclass
, vname
, config
, vconfig
, mctx
);
375 if (tresult
!= ISC_R_SUCCESS
)
380 tresult
= configure_view("IN", "_default", config
, NULL
, mctx
);
381 if (tresult
!= ISC_R_SUCCESS
)
387 /*% The main processing routine */
389 main(int argc
, char **argv
) {
391 cfg_parser_t
*parser
= NULL
;
392 cfg_obj_t
*config
= NULL
;
393 const char *conffile
= NULL
;
394 isc_mem_t
*mctx
= NULL
;
397 isc_entropy_t
*ectx
= NULL
;
398 isc_boolean_t load_zones
= ISC_FALSE
;
400 while ((c
= isc_commandline_parse(argc
, argv
, "djt:vz")) != EOF
) {
411 result
= isc_dir_chroot(isc_commandline_argument
);
412 if (result
!= ISC_R_SUCCESS
) {
413 fprintf(stderr
, "isc_dir_chroot: %s\n",
414 isc_result_totext(result
));
417 result
= isc_dir_chdir("/");
418 if (result
!= ISC_R_SUCCESS
) {
419 fprintf(stderr
, "isc_dir_chdir: %s\n",
420 isc_result_totext(result
));
426 printf(VERSION
"\n");
430 load_zones
= ISC_TRUE
;
431 docheckmx
= ISC_FALSE
;
432 docheckns
= ISC_FALSE
;
433 dochecksrv
= ISC_FALSE
;
441 if (argv
[isc_commandline_index
] != NULL
)
442 conffile
= argv
[isc_commandline_index
];
443 if (conffile
== NULL
|| conffile
[0] == '\0')
444 conffile
= NAMED_CONFFILE
;
446 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx
) == ISC_R_SUCCESS
);
448 RUNTIME_CHECK(setup_logging(mctx
, &logc
) == ISC_R_SUCCESS
);
450 RUNTIME_CHECK(isc_entropy_create(mctx
, &ectx
) == ISC_R_SUCCESS
);
451 RUNTIME_CHECK(isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
)
454 dns_result_register();
456 RUNTIME_CHECK(cfg_parser_create(mctx
, logc
, &parser
) == ISC_R_SUCCESS
);
458 cfg_parser_setcallback(parser
, directory_callback
, NULL
);
460 if (cfg_parse_file(parser
, conffile
, &cfg_type_namedconf
, &config
) !=
464 result
= bind9_check_namedconf(config
, logc
, mctx
);
465 if (result
!= ISC_R_SUCCESS
)
468 if (result
== ISC_R_SUCCESS
&& load_zones
) {
469 result
= load_zones_fromconfig(config
, mctx
);
470 if (result
!= ISC_R_SUCCESS
)
474 cfg_obj_destroy(parser
, &config
);
476 cfg_parser_destroy(&parser
);
480 isc_log_destroy(&logc
);
483 isc_entropy_detach(&ectx
);
485 isc_mem_destroy(&mctx
);
487 return (exit_status
);