1 /* $NetBSD: named-checkconf.c,v 1.11 2015/07/08 17:28:54 christos Exp $ */
2
3 /*
4 * Copyright (C) 2004-2007, 2009-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /* Id: named-checkconf.c,v 1.56 2011/03/12 04:59:46 tbox Exp */
21
22 /*! \file */
23
24 #include <config.h>
25
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29
30 #include <isc/commandline.h>
31 #include <isc/dir.h>
32 #include <isc/entropy.h>
33 #include <isc/hash.h>
34 #include <isc/log.h>
35 #include <isc/mem.h>
36 #include <isc/result.h>
37 #include <isc/string.h>
38 #include <isc/util.h>
39
40 #include <isccfg/namedconf.h>
41
42 #include <bind9/check.h>
43
44 #include <dns/db.h>
45 #include <dns/fixedname.h>
46 #include <dns/log.h>
47 #include <dns/name.h>
48 #include <dns/rdataclass.h>
49 #include <dns/result.h>
50 #include <dns/rootns.h>
51 #include <dns/zone.h>
52
53 #include "check-tool.h"
54
55 static const char *program = "named-checkconf";
56
57 isc_log_t *logc = NULL;
58
59 #define CHECK(r)\
60 do { \
61 result = (r); \
62 if (result != ISC_R_SUCCESS) \
63 goto cleanup; \
64 } while (/*CONSTCOND*/0)
65
66 /*% usage */
67 ISC_PLATFORM_NORETURN_PRE static void
68 usage(void) ISC_PLATFORM_NORETURN_POST;
69
70 static void
usage(void)71 usage(void) {
72 fprintf(stderr, "usage: %s [-h] [-j] [-p] [-v] [-z] [-t directory] "
73 "[named.conf]\n", program);
74 exit(1);
75 }
76
77 /*% directory callback */
78 static isc_result_t
directory_callback(const char * clausename,const cfg_obj_t * obj,void * arg)79 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
80 isc_result_t result;
81 const char *directory;
82
83 REQUIRE(strcasecmp("directory", clausename) == 0);
84
85 UNUSED(arg);
86 UNUSED(clausename);
87
88 /*
89 * Change directory.
90 */
91 directory = cfg_obj_asstring(obj);
92 result = isc_dir_chdir(directory);
93 if (result != ISC_R_SUCCESS) {
94 cfg_obj_log(obj, logc, ISC_LOG_ERROR,
95 "change directory to '%s' failed: %s\n",
96 directory, isc_result_totext(result));
97 return (result);
98 }
99
100 return (ISC_R_SUCCESS);
101 }
102
103 static isc_boolean_t
get_maps(const cfg_obj_t ** maps,const char * name,const cfg_obj_t ** obj)104 get_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
105 int i;
106 for (i = 0;; i++) {
107 if (maps[i] == NULL)
108 return (ISC_FALSE);
109 if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
110 return (ISC_TRUE);
111 }
112 }
113
114 static isc_boolean_t
get_checknames(const cfg_obj_t ** maps,const cfg_obj_t ** obj)115 get_checknames(const cfg_obj_t **maps, const cfg_obj_t **obj) {
116 const cfg_listelt_t *element;
117 const cfg_obj_t *checknames;
118 const cfg_obj_t *type;
119 const cfg_obj_t *value;
120 isc_result_t result;
121 int i;
122
123 for (i = 0;; i++) {
124 if (maps[i] == NULL)
125 return (ISC_FALSE);
126 checknames = NULL;
127 result = cfg_map_get(maps[i], "check-names", &checknames);
128 if (result != ISC_R_SUCCESS)
129 continue;
130 if (checknames != NULL && !cfg_obj_islist(checknames)) {
131 *obj = checknames;
132 return (ISC_TRUE);
133 }
134 for (element = cfg_list_first(checknames);
135 element != NULL;
136 element = cfg_list_next(element)) {
137 value = cfg_listelt_value(element);
138 type = cfg_tuple_get(value, "type");
139 if (strcasecmp(cfg_obj_asstring(type), "master") != 0)
140 continue;
141 *obj = cfg_tuple_get(value, "mode");
142 return (ISC_TRUE);
143 }
144 }
145 }
146
147 static isc_result_t
configure_hint(const char * zfile,const char * zclass,isc_mem_t * mctx)148 configure_hint(const char *zfile, const char *zclass, isc_mem_t *mctx) {
149 isc_result_t result;
150 dns_db_t *db = NULL;
151 dns_rdataclass_t rdclass;
152 isc_textregion_t r;
153
154 if (zfile == NULL)
155 return (ISC_R_FAILURE);
156
157 DE_CONST(zclass, r.base);
158 r.length = strlen(zclass);
159 result = dns_rdataclass_fromtext(&rdclass, &r);
160 if (result != ISC_R_SUCCESS)
161 return (result);
162
163 result = dns_rootns_create(mctx, rdclass, zfile, &db);
164 if (result != ISC_R_SUCCESS)
165 return (result);
166
167 dns_db_detach(&db);
168 return (ISC_R_SUCCESS);
169 }
170
171 /*% configure the zone */
172 static isc_result_t
configure_zone(const char * vclass,const char * view,const cfg_obj_t * zconfig,const cfg_obj_t * vconfig,const cfg_obj_t * config,isc_mem_t * mctx)173 configure_zone(const char *vclass, const char *view,
174 const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
175 const cfg_obj_t *config, isc_mem_t *mctx)
176 {
177 int i = 0;
178 isc_result_t result;
179 const char *zclass;
180 const char *zname;
181 const char *zfile = NULL;
182 const cfg_obj_t *maps[4];
183 const cfg_obj_t *mastersobj = NULL;
184 const cfg_obj_t *zoptions = NULL;
185 const cfg_obj_t *classobj = NULL;
186 const cfg_obj_t *typeobj = NULL;
187 const cfg_obj_t *fileobj = NULL;
188 const cfg_obj_t *dlzobj = NULL;
189 const cfg_obj_t *dbobj = NULL;
190 const cfg_obj_t *obj = NULL;
191 const cfg_obj_t *fmtobj = NULL;
192 dns_masterformat_t masterformat;
193 dns_ttl_t maxttl = 0;
194
195 zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS;
196
197 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
198 classobj = cfg_tuple_get(zconfig, "class");
199 if (!cfg_obj_isstring(classobj))
200 zclass = vclass;
201 else
202 zclass = cfg_obj_asstring(classobj);
203
204 zoptions = cfg_tuple_get(zconfig, "options");
205 maps[i++] = zoptions;
206 if (vconfig != NULL)
207 maps[i++] = cfg_tuple_get(vconfig, "options");
208 if (config != NULL) {
209 cfg_map_get(config, "options", &obj);
210 if (obj != NULL)
211 maps[i++] = obj;
212 }
213 maps[i] = NULL;
214
215 cfg_map_get(zoptions, "type", &typeobj);
216 if (typeobj == NULL)
217 return (ISC_R_FAILURE);
218
219 /*
220 * Skip checks when using an alternate data source.
221 */
222 cfg_map_get(zoptions, "database", &dbobj);
223 if (dbobj != NULL &&
224 strcmp("rbt", cfg_obj_asstring(dbobj)) != 0 &&
225 strcmp("rbt64", cfg_obj_asstring(dbobj)) != 0)
226 return (ISC_R_SUCCESS);
227
228 cfg_map_get(zoptions, "dlz", &dlzobj);
229 if (dlzobj != NULL)
230 return (ISC_R_SUCCESS);
231
232 cfg_map_get(zoptions, "file", &fileobj);
233 if (fileobj != NULL)
234 zfile = cfg_obj_asstring(fileobj);
235
236 /*
237 * Check hints files for hint zones.
238 * Skip loading checks for any type other than
239 * master and redirect
240 */
241 if (strcasecmp(cfg_obj_asstring(typeobj), "hint") == 0)
242 return (configure_hint(zfile, zclass, mctx));
243 else if ((strcasecmp(cfg_obj_asstring(typeobj), "master") != 0) &&
244 (strcasecmp(cfg_obj_asstring(typeobj), "redirect") != 0))
245 return (ISC_R_SUCCESS);
246
247 /*
248 * Is the redirect zone configured as a slave?
249 */
250 if (strcasecmp(cfg_obj_asstring(typeobj), "redirect") == 0) {
251 cfg_map_get(zoptions, "masters", &mastersobj);
252 if (mastersobj != NULL)
253 return (ISC_R_SUCCESS);
254 }
255
256 if (zfile == NULL)
257 return (ISC_R_FAILURE);
258
259 obj = NULL;
260 if (get_maps(maps, "check-dup-records", &obj)) {
261 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
262 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
263 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
264 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
265 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
266 zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL;
267 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
268 zone_options &= ~DNS_ZONEOPT_CHECKDUPRR;
269 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
270 } else
271 INSIST(0);
272 } else {
273 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
274 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
275 }
276
277 obj = NULL;
278 if (get_maps(maps, "check-mx", &obj)) {
279 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
280 zone_options |= DNS_ZONEOPT_CHECKMX;
281 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
282 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
283 zone_options |= DNS_ZONEOPT_CHECKMX;
284 zone_options |= DNS_ZONEOPT_CHECKMXFAIL;
285 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
286 zone_options &= ~DNS_ZONEOPT_CHECKMX;
287 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
288 } else
289 INSIST(0);
290 } else {
291 zone_options |= DNS_ZONEOPT_CHECKMX;
292 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
293 }
294
295 obj = NULL;
296 if (get_maps(maps, "check-integrity", &obj)) {
297 if (cfg_obj_asboolean(obj))
298 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
299 else
300 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
301 } else
302 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
303
304 obj = NULL;
305 if (get_maps(maps, "check-mx-cname", &obj)) {
306 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
307 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
308 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
309 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
310 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
311 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
312 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
313 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
314 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
315 } else
316 INSIST(0);
317 } else {
318 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
319 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
320 }
321
322 obj = NULL;
323 if (get_maps(maps, "check-srv-cname", &obj)) {
324 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
325 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
326 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
327 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
328 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
329 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
330 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
331 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
332 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
333 } else
334 INSIST(0);
335 } else {
336 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
337 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
338 }
339
340 obj = NULL;
341 if (get_maps(maps, "check-sibling", &obj)) {
342 if (cfg_obj_asboolean(obj))
343 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
344 else
345 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
346 }
347
348 obj = NULL;
349 if (get_maps(maps, "check-spf", &obj)) {
350 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
351 zone_options |= DNS_ZONEOPT_CHECKSPF;
352 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
353 zone_options &= ~DNS_ZONEOPT_CHECKSPF;
354 } else
355 INSIST(0);
356 } else {
357 zone_options |= DNS_ZONEOPT_CHECKSPF;
358 }
359
360 obj = NULL;
361 if (get_checknames(maps, &obj)) {
362 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
363 zone_options |= DNS_ZONEOPT_CHECKNAMES;
364 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
365 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
366 zone_options |= DNS_ZONEOPT_CHECKNAMES;
367 zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL;
368 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
369 zone_options &= ~DNS_ZONEOPT_CHECKNAMES;
370 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
371 } else
372 INSIST(0);
373 } else {
374 zone_options |= DNS_ZONEOPT_CHECKNAMES;
375 zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL;
376 }
377
378 masterformat = dns_masterformat_text;
379 fmtobj = NULL;
380 if (get_maps(maps, "masterfile-format", &fmtobj)) {
381 const char *masterformatstr = cfg_obj_asstring(fmtobj);
382 if (strcasecmp(masterformatstr, "text") == 0)
383 masterformat = dns_masterformat_text;
384 else if (strcasecmp(masterformatstr, "raw") == 0)
385 masterformat = dns_masterformat_raw;
386 else if (strcasecmp(masterformatstr, "map") == 0)
387 masterformat = dns_masterformat_map;
388 else
389 INSIST(0);
390 }
391
392 obj = NULL;
393 if (get_maps(maps, "max-zone-ttl", &obj)) {
394 maxttl = cfg_obj_asuint32(obj);
395 zone_options2 |= DNS_ZONEOPT2_CHECKTTL;
396 }
397
398 result = load_zone(mctx, zname, zfile, masterformat,
399 zclass, maxttl, NULL);
400 if (result != ISC_R_SUCCESS)
401 fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass,
402 dns_result_totext(result));
403 return (result);
404 }
405
406 /*% configure a view */
407 static isc_result_t
configure_view(const char * vclass,const char * view,const cfg_obj_t * config,const cfg_obj_t * vconfig,isc_mem_t * mctx)408 configure_view(const char *vclass, const char *view, const cfg_obj_t *config,
409 const cfg_obj_t *vconfig, isc_mem_t *mctx)
410 {
411 const cfg_listelt_t *element;
412 const cfg_obj_t *voptions;
413 const cfg_obj_t *zonelist;
414 isc_result_t result = ISC_R_SUCCESS;
415 isc_result_t tresult;
416
417 voptions = NULL;
418 if (vconfig != NULL)
419 voptions = cfg_tuple_get(vconfig, "options");
420
421 zonelist = NULL;
422 if (voptions != NULL)
423 (void)cfg_map_get(voptions, "zone", &zonelist);
424 else
425 (void)cfg_map_get(config, "zone", &zonelist);
426
427 for (element = cfg_list_first(zonelist);
428 element != NULL;
429 element = cfg_list_next(element))
430 {
431 const cfg_obj_t *zconfig = cfg_listelt_value(element);
432 tresult = configure_zone(vclass, view, zconfig, vconfig,
433 config, mctx);
434 if (tresult != ISC_R_SUCCESS)
435 result = tresult;
436 }
437 return (result);
438 }
439
440
441 /*% load zones from the configuration */
442 static isc_result_t
load_zones_fromconfig(const cfg_obj_t * config,isc_mem_t * mctx)443 load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) {
444 const cfg_listelt_t *element;
445 const cfg_obj_t *classobj;
446 const cfg_obj_t *views;
447 const cfg_obj_t *vconfig;
448 const char *vclass;
449 isc_result_t result = ISC_R_SUCCESS;
450 isc_result_t tresult;
451
452 views = NULL;
453
454 (void)cfg_map_get(config, "view", &views);
455 for (element = cfg_list_first(views);
456 element != NULL;
457 element = cfg_list_next(element))
458 {
459 const char *vname;
460
461 vclass = "IN";
462 vconfig = cfg_listelt_value(element);
463 if (vconfig != NULL) {
464 classobj = cfg_tuple_get(vconfig, "class");
465 if (cfg_obj_isstring(classobj))
466 vclass = cfg_obj_asstring(classobj);
467 }
468 vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
469 tresult = configure_view(vclass, vname, config, vconfig, mctx);
470 if (tresult != ISC_R_SUCCESS)
471 result = tresult;
472 }
473
474 if (views == NULL) {
475 tresult = configure_view("IN", "_default", config, NULL, mctx);
476 if (tresult != ISC_R_SUCCESS)
477 result = tresult;
478 }
479 return (result);
480 }
481
482 static void
output(void * closure,const char * text,int textlen)483 output(void *closure, const char *text, int textlen) {
484 UNUSED(closure);
485 if (fwrite(text, 1, textlen, stdout) != (size_t)textlen) {
486 perror("fwrite");
487 exit(1);
488 }
489 }
490
491 /*% The main processing routine */
492 int
main(int argc,char ** argv)493 main(int argc, char **argv) {
494 int c;
495 cfg_parser_t *parser = NULL;
496 cfg_obj_t *config = NULL;
497 const char *conffile = NULL;
498 isc_mem_t *mctx = NULL;
499 isc_result_t result;
500 int exit_status = 0;
501 isc_entropy_t *ectx = NULL;
502 isc_boolean_t load_zones = ISC_FALSE;
503 isc_boolean_t print = ISC_FALSE;
504 unsigned int flags = 0;
505
506 isc__mem_register();
507 isc_commandline_errprint = ISC_FALSE;
508
509 /*
510 * Process memory debugging argument first.
511 */
512 #define CMDLINE_FLAGS "dhjm:t:pvxz"
513 while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
514 switch (c) {
515 case 'm':
516 if (strcasecmp(isc_commandline_argument, "record") == 0)
517 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
518 if (strcasecmp(isc_commandline_argument, "trace") == 0)
519 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
520 if (strcasecmp(isc_commandline_argument, "usage") == 0)
521 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
522 if (strcasecmp(isc_commandline_argument, "size") == 0)
523 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
524 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
525 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
526 break;
527 default:
528 break;
529 }
530 }
531 isc_commandline_reset = ISC_TRUE;
532
533 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
534
535 while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != EOF) {
536 switch (c) {
537 case 'd':
538 debug++;
539 break;
540
541 case 'j':
542 nomerge = ISC_FALSE;
543 break;
544
545 case 'm':
546 break;
547
548 case 't':
549 result = isc_dir_chroot(isc_commandline_argument);
550 if (result != ISC_R_SUCCESS) {
551 fprintf(stderr, "isc_dir_chroot: %s\n",
552 isc_result_totext(result));
553 exit(1);
554 }
555 break;
556
557 case 'p':
558 print = ISC_TRUE;
559 break;
560
561 case 'v':
562 printf(VERSION "\n");
563 exit(0);
564
565 case 'x':
566 flags |= CFG_PRINTER_XKEY;
567 break;
568
569 case 'z':
570 load_zones = ISC_TRUE;
571 docheckmx = ISC_FALSE;
572 docheckns = ISC_FALSE;
573 dochecksrv = ISC_FALSE;
574 break;
575
576 case '?':
577 if (isc_commandline_option != '?')
578 fprintf(stderr, "%s: invalid argument -%c\n",
579 program, isc_commandline_option);
580 /* FALLTHROUGH */
581 case 'h':
582 usage();
583
584 default:
585 fprintf(stderr, "%s: unhandled option -%c\n",
586 program, isc_commandline_option);
587 exit(1);
588 }
589 }
590
591 if (((flags & CFG_PRINTER_XKEY) != 0) && !print) {
592 fprintf(stderr, "%s: -x cannot be used without -p\n", program);
593 exit(1);
594 }
595
596 if (isc_commandline_index + 1 < argc)
597 usage();
598 if (argv[isc_commandline_index] != NULL)
599 conffile = argv[isc_commandline_index];
600 if (conffile == NULL || conffile[0] == '\0')
601 conffile = NAMED_CONFFILE;
602
603 #ifdef _WIN32
604 InitSockets();
605 #endif
606
607 RUNTIME_CHECK(setup_logging(mctx, stdout, &logc) == ISC_R_SUCCESS);
608
609 RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
610 RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
611 == ISC_R_SUCCESS);
612
613 dns_result_register();
614
615 RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS);
616
617 cfg_parser_setcallback(parser, directory_callback, NULL);
618
619 if (cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config) !=
620 ISC_R_SUCCESS)
621 exit(1);
622
623 result = bind9_check_namedconf(config, logc, mctx);
624 if (result != ISC_R_SUCCESS)
625 exit_status = 1;
626
627 if (result == ISC_R_SUCCESS && load_zones) {
628 result = load_zones_fromconfig(config, mctx);
629 if (result != ISC_R_SUCCESS)
630 exit_status = 1;
631 }
632
633 if (print && exit_status == 0)
634 cfg_printx(config, flags, output, NULL);
635 cfg_obj_destroy(parser, &config);
636
637 cfg_parser_destroy(&parser);
638
639 dns_name_destroy();
640
641 isc_log_destroy(&logc);
642
643 isc_hash_destroy();
644 isc_entropy_detach(&ectx);
645
646 isc_mem_destroy(&mctx);
647
648 #ifdef _WIN32
649 DestroySockets();
650 #endif
651
652 return (exit_status);
653 }
654