named-checkconf.c revision 143731
1/* 2 * Copyright (C) 2004, 2005 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.9 2005/03/03 06:33:38 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 46isc_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 55static void 56usage(void) { 57 fprintf(stderr, "usage: named-checkconf [-j] [-v] [-z] [-t directory] " 58 "[named.conf]\n"); 59 exit(1); 60} 61 62static isc_result_t 63directory_callback(const char *clausename, cfg_obj_t *obj, void *arg) { 64 isc_result_t result; 65 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 87static isc_result_t 88configure_zone(const char *vclass, const char *view, cfg_obj_t *zconfig, 89 isc_mem_t *mctx) 90{ 91 isc_result_t result; 92 const char *zclass; 93 const char *zname; 94 const char *zfile; 95 cfg_obj_t *zoptions = NULL; 96 cfg_obj_t *classobj = NULL; 97 cfg_obj_t *typeobj = NULL; 98 cfg_obj_t *fileobj = NULL; 99 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 127static isc_result_t 128configure_view(const char *vclass, const char *view, cfg_obj_t *config, 129 cfg_obj_t *vconfig, isc_mem_t *mctx) 130{ 131 cfg_listelt_t *element; 132 cfg_obj_t *voptions; 133 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 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 160static isc_result_t 161load_zones_fromconfig(cfg_obj_t *config, isc_mem_t *mctx) { 162 cfg_listelt_t *element; 163 cfg_obj_t *classobj; 164 cfg_obj_t *views; 165 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 200int 201main(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} 298