1135446Strhodes/* 2262706Serwin * Copyright (C) 2004-2007, 2009-2014 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2002 Internet Software Consortium. 4135446Strhodes * 5186462Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18254897Serwin/* $Id: named-checkconf.c,v 1.56 2011/03/12 04:59:46 tbox Exp $ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24135446Strhodes#include <errno.h> 25135446Strhodes#include <stdlib.h> 26135446Strhodes#include <stdio.h> 27135446Strhodes 28135446Strhodes#include <isc/commandline.h> 29135446Strhodes#include <isc/dir.h> 30143731Sdougb#include <isc/entropy.h> 31143731Sdougb#include <isc/hash.h> 32135446Strhodes#include <isc/log.h> 33135446Strhodes#include <isc/mem.h> 34135446Strhodes#include <isc/result.h> 35135446Strhodes#include <isc/string.h> 36135446Strhodes#include <isc/util.h> 37135446Strhodes 38135446Strhodes#include <isccfg/namedconf.h> 39135446Strhodes 40135446Strhodes#include <bind9/check.h> 41135446Strhodes 42262706Serwin#include <dns/db.h> 43143731Sdougb#include <dns/fixedname.h> 44135446Strhodes#include <dns/log.h> 45170222Sdougb#include <dns/name.h> 46262706Serwin#include <dns/rdataclass.h> 47135446Strhodes#include <dns/result.h> 48262706Serwin#include <dns/rootns.h> 49170222Sdougb#include <dns/zone.h> 50135446Strhodes 51135446Strhodes#include "check-tool.h" 52135446Strhodes 53193149Sdougbstatic const char *program = "named-checkconf"; 54193149Sdougb 55135446Strhodesisc_log_t *logc = NULL; 56135446Strhodes 57135446Strhodes#define CHECK(r)\ 58135446Strhodes do { \ 59135446Strhodes result = (r); \ 60135446Strhodes if (result != ISC_R_SUCCESS) \ 61135446Strhodes goto cleanup; \ 62135446Strhodes } while (0) 63135446Strhodes 64170222Sdougb/*% usage */ 65224092SdougbISC_PLATFORM_NORETURN_PRE static void 66224092Sdougbusage(void) ISC_PLATFORM_NORETURN_POST; 67224092Sdougb 68135446Strhodesstatic void 69135446Strhodesusage(void) { 70224092Sdougb fprintf(stderr, "usage: %s [-h] [-j] [-p] [-v] [-z] [-t directory] " 71193149Sdougb "[named.conf]\n", program); 72193149Sdougb exit(1); 73135446Strhodes} 74135446Strhodes 75170222Sdougb/*% directory callback */ 76135446Strhodesstatic isc_result_t 77165071Sdougbdirectory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 78135446Strhodes isc_result_t result; 79165071Sdougb const char *directory; 80135446Strhodes 81135446Strhodes REQUIRE(strcasecmp("directory", clausename) == 0); 82135446Strhodes 83135446Strhodes UNUSED(arg); 84135446Strhodes UNUSED(clausename); 85135446Strhodes 86135446Strhodes /* 87135446Strhodes * Change directory. 88135446Strhodes */ 89135446Strhodes directory = cfg_obj_asstring(obj); 90135446Strhodes result = isc_dir_chdir(directory); 91135446Strhodes if (result != ISC_R_SUCCESS) { 92135446Strhodes cfg_obj_log(obj, logc, ISC_LOG_ERROR, 93135446Strhodes "change directory to '%s' failed: %s\n", 94135446Strhodes directory, isc_result_totext(result)); 95135446Strhodes return (result); 96135446Strhodes } 97135446Strhodes 98135446Strhodes return (ISC_R_SUCCESS); 99135446Strhodes} 100135446Strhodes 101170222Sdougbstatic isc_boolean_t 102170222Sdougbget_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) { 103170222Sdougb int i; 104170222Sdougb for (i = 0;; i++) { 105170222Sdougb if (maps[i] == NULL) 106170222Sdougb return (ISC_FALSE); 107170222Sdougb if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) 108170222Sdougb return (ISC_TRUE); 109170222Sdougb } 110170222Sdougb} 111170222Sdougb 112170222Sdougbstatic isc_boolean_t 113170222Sdougbget_checknames(const cfg_obj_t **maps, const cfg_obj_t **obj) { 114170222Sdougb const cfg_listelt_t *element; 115170222Sdougb const cfg_obj_t *checknames; 116170222Sdougb const cfg_obj_t *type; 117170222Sdougb const cfg_obj_t *value; 118170222Sdougb isc_result_t result; 119170222Sdougb int i; 120170222Sdougb 121170222Sdougb for (i = 0;; i++) { 122170222Sdougb if (maps[i] == NULL) 123170222Sdougb return (ISC_FALSE); 124170222Sdougb checknames = NULL; 125170222Sdougb result = cfg_map_get(maps[i], "check-names", &checknames); 126170222Sdougb if (result != ISC_R_SUCCESS) 127170222Sdougb continue; 128170222Sdougb if (checknames != NULL && !cfg_obj_islist(checknames)) { 129170222Sdougb *obj = checknames; 130170222Sdougb return (ISC_TRUE); 131170222Sdougb } 132170222Sdougb for (element = cfg_list_first(checknames); 133170222Sdougb element != NULL; 134170222Sdougb element = cfg_list_next(element)) { 135170222Sdougb value = cfg_listelt_value(element); 136170222Sdougb type = cfg_tuple_get(value, "type"); 137170222Sdougb if (strcasecmp(cfg_obj_asstring(type), "master") != 0) 138170222Sdougb continue; 139170222Sdougb *obj = cfg_tuple_get(value, "mode"); 140170222Sdougb return (ISC_TRUE); 141170222Sdougb } 142170222Sdougb } 143170222Sdougb} 144170222Sdougb 145135446Strhodesstatic isc_result_t 146170222Sdougbconfig_get(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) { 147170222Sdougb int i; 148170222Sdougb 149170222Sdougb for (i = 0;; i++) { 150170222Sdougb if (maps[i] == NULL) 151170222Sdougb return (ISC_R_NOTFOUND); 152170222Sdougb if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) 153170222Sdougb return (ISC_R_SUCCESS); 154170222Sdougb } 155170222Sdougb} 156170222Sdougb 157262706Serwinstatic isc_result_t 158262706Serwinconfigure_hint(const char *zfile, const char *zclass, isc_mem_t *mctx) { 159262706Serwin isc_result_t result; 160262706Serwin dns_db_t *db = NULL; 161262706Serwin dns_rdataclass_t rdclass; 162262706Serwin isc_textregion_t r; 163262706Serwin 164262706Serwin if (zfile == NULL) 165262706Serwin return (ISC_R_FAILURE); 166262706Serwin 167262706Serwin DE_CONST(zclass, r.base); 168262706Serwin r.length = strlen(zclass); 169262706Serwin result = dns_rdataclass_fromtext(&rdclass, &r); 170262706Serwin if (result != ISC_R_SUCCESS) 171262706Serwin return (result); 172262706Serwin 173262706Serwin result = dns_rootns_create(mctx, rdclass, zfile, &db); 174262706Serwin if (result != ISC_R_SUCCESS) 175262706Serwin return (result); 176262706Serwin 177262706Serwin dns_db_detach(&db); 178262706Serwin return (ISC_R_SUCCESS); 179262706Serwin} 180262706Serwin 181170222Sdougb/*% configure the zone */ 182170222Sdougbstatic isc_result_t 183165071Sdougbconfigure_zone(const char *vclass, const char *view, 184170222Sdougb const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, 185170222Sdougb const cfg_obj_t *config, isc_mem_t *mctx) 186135446Strhodes{ 187170222Sdougb int i = 0; 188135446Strhodes isc_result_t result; 189135446Strhodes const char *zclass; 190135446Strhodes const char *zname; 191262706Serwin const char *zfile = NULL; 192170222Sdougb const cfg_obj_t *maps[4]; 193165071Sdougb const cfg_obj_t *zoptions = NULL; 194165071Sdougb const cfg_obj_t *classobj = NULL; 195165071Sdougb const cfg_obj_t *typeobj = NULL; 196165071Sdougb const cfg_obj_t *fileobj = NULL; 197165071Sdougb const cfg_obj_t *dbobj = NULL; 198170222Sdougb const cfg_obj_t *obj = NULL; 199170222Sdougb const cfg_obj_t *fmtobj = NULL; 200170222Sdougb dns_masterformat_t masterformat; 201135446Strhodes 202170222Sdougb zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS; 203170222Sdougb 204135446Strhodes zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 205135446Strhodes classobj = cfg_tuple_get(zconfig, "class"); 206193149Sdougb if (!cfg_obj_isstring(classobj)) 207193149Sdougb zclass = vclass; 208193149Sdougb else 209135446Strhodes zclass = cfg_obj_asstring(classobj); 210170222Sdougb 211135446Strhodes zoptions = cfg_tuple_get(zconfig, "options"); 212170222Sdougb maps[i++] = zoptions; 213170222Sdougb if (vconfig != NULL) 214170222Sdougb maps[i++] = cfg_tuple_get(vconfig, "options"); 215170222Sdougb if (config != NULL) { 216170222Sdougb cfg_map_get(config, "options", &obj); 217170222Sdougb if (obj != NULL) 218170222Sdougb maps[i++] = obj; 219170222Sdougb } 220225361Sdougb maps[i] = NULL; 221170222Sdougb 222135446Strhodes cfg_map_get(zoptions, "type", &typeobj); 223135446Strhodes if (typeobj == NULL) 224135446Strhodes return (ISC_R_FAILURE); 225262706Serwin 226262706Serwin cfg_map_get(zoptions, "file", &fileobj); 227262706Serwin if (fileobj != NULL) 228262706Serwin zfile = cfg_obj_asstring(fileobj); 229262706Serwin 230262706Serwin /* 231262706Serwin * Check hints files for hint zones. 232262706Serwin * Skip loading checks for any type other than 233262706Serwin * master and redirect 234262706Serwin */ 235262706Serwin if (strcasecmp(cfg_obj_asstring(typeobj), "hint") == 0) 236262706Serwin return (configure_hint(zfile, zclass, mctx)); 237262706Serwin else if ((strcasecmp(cfg_obj_asstring(typeobj), "master") != 0) && 238262706Serwin (strcasecmp(cfg_obj_asstring(typeobj), "redirect") != 0)) 239135446Strhodes return (ISC_R_SUCCESS); 240262706Serwin 241262706Serwin if (zfile == NULL) 242262706Serwin return (ISC_R_FAILURE); 243262706Serwin 244193149Sdougb cfg_map_get(zoptions, "database", &dbobj); 245193149Sdougb if (dbobj != NULL) 246193149Sdougb return (ISC_R_SUCCESS); 247170222Sdougb 248170222Sdougb obj = NULL; 249224092Sdougb if (get_maps(maps, "check-dup-records", &obj)) { 250224092Sdougb if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 251224092Sdougb zone_options |= DNS_ZONEOPT_CHECKDUPRR; 252224092Sdougb zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; 253224092Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 254224092Sdougb zone_options |= DNS_ZONEOPT_CHECKDUPRR; 255224092Sdougb zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL; 256224092Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 257224092Sdougb zone_options &= ~DNS_ZONEOPT_CHECKDUPRR; 258224092Sdougb zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; 259224092Sdougb } else 260224092Sdougb INSIST(0); 261224092Sdougb } else { 262224092Sdougb zone_options |= DNS_ZONEOPT_CHECKDUPRR; 263224092Sdougb zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; 264224092Sdougb } 265224092Sdougb 266224092Sdougb obj = NULL; 267170222Sdougb if (get_maps(maps, "check-mx", &obj)) { 268170222Sdougb if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 269170222Sdougb zone_options |= DNS_ZONEOPT_CHECKMX; 270170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; 271170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 272170222Sdougb zone_options |= DNS_ZONEOPT_CHECKMX; 273170222Sdougb zone_options |= DNS_ZONEOPT_CHECKMXFAIL; 274170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 275170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKMX; 276170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; 277170222Sdougb } else 278170222Sdougb INSIST(0); 279170222Sdougb } else { 280170222Sdougb zone_options |= DNS_ZONEOPT_CHECKMX; 281170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; 282170222Sdougb } 283170222Sdougb 284170222Sdougb obj = NULL; 285170222Sdougb if (get_maps(maps, "check-integrity", &obj)) { 286170222Sdougb if (cfg_obj_asboolean(obj)) 287170222Sdougb zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; 288170222Sdougb else 289170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY; 290186462Sdougb } else 291186462Sdougb zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; 292170222Sdougb 293170222Sdougb obj = NULL; 294170222Sdougb if (get_maps(maps, "check-mx-cname", &obj)) { 295170222Sdougb if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 296170222Sdougb zone_options |= DNS_ZONEOPT_WARNMXCNAME; 297170222Sdougb zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; 298170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 299170222Sdougb zone_options &= ~DNS_ZONEOPT_WARNMXCNAME; 300170222Sdougb zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; 301170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 302170222Sdougb zone_options |= DNS_ZONEOPT_WARNMXCNAME; 303170222Sdougb zone_options |= DNS_ZONEOPT_IGNOREMXCNAME; 304170222Sdougb } else 305170222Sdougb INSIST(0); 306170222Sdougb } else { 307170222Sdougb zone_options |= DNS_ZONEOPT_WARNMXCNAME; 308170222Sdougb zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; 309170222Sdougb } 310170222Sdougb 311170222Sdougb obj = NULL; 312170222Sdougb if (get_maps(maps, "check-srv-cname", &obj)) { 313170222Sdougb if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 314170222Sdougb zone_options |= DNS_ZONEOPT_WARNSRVCNAME; 315170222Sdougb zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; 316170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 317170222Sdougb zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME; 318170222Sdougb zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; 319170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 320170222Sdougb zone_options |= DNS_ZONEOPT_WARNSRVCNAME; 321170222Sdougb zone_options |= DNS_ZONEOPT_IGNORESRVCNAME; 322170222Sdougb } else 323170222Sdougb INSIST(0); 324170222Sdougb } else { 325170222Sdougb zone_options |= DNS_ZONEOPT_WARNSRVCNAME; 326170222Sdougb zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; 327170222Sdougb } 328170222Sdougb 329170222Sdougb obj = NULL; 330170222Sdougb if (get_maps(maps, "check-sibling", &obj)) { 331170222Sdougb if (cfg_obj_asboolean(obj)) 332170222Sdougb zone_options |= DNS_ZONEOPT_CHECKSIBLING; 333170222Sdougb else 334170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; 335170222Sdougb } 336170222Sdougb 337170222Sdougb obj = NULL; 338254402Serwin if (get_maps(maps, "check-spf", &obj)) { 339254402Serwin if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 340254402Serwin zone_options |= DNS_ZONEOPT_CHECKSPF; 341254402Serwin } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 342254402Serwin zone_options &= ~DNS_ZONEOPT_CHECKSPF; 343254402Serwin } else 344254402Serwin INSIST(0); 345254402Serwin } else { 346254402Serwin zone_options |= DNS_ZONEOPT_CHECKSPF; 347254402Serwin } 348254402Serwin 349254402Serwin obj = NULL; 350170222Sdougb if (get_checknames(maps, &obj)) { 351170222Sdougb if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 352170222Sdougb zone_options |= DNS_ZONEOPT_CHECKNAMES; 353170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; 354170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 355170222Sdougb zone_options |= DNS_ZONEOPT_CHECKNAMES; 356170222Sdougb zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; 357170222Sdougb } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 358170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKNAMES; 359170222Sdougb zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; 360170222Sdougb } else 361170222Sdougb INSIST(0); 362170222Sdougb } else { 363193149Sdougb zone_options |= DNS_ZONEOPT_CHECKNAMES; 364193149Sdougb zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; 365170222Sdougb } 366170222Sdougb 367170222Sdougb masterformat = dns_masterformat_text; 368170222Sdougb fmtobj = NULL; 369170222Sdougb result = config_get(maps, "masterfile-format", &fmtobj); 370170222Sdougb if (result == ISC_R_SUCCESS) { 371170222Sdougb const char *masterformatstr = cfg_obj_asstring(fmtobj); 372170222Sdougb if (strcasecmp(masterformatstr, "text") == 0) 373170222Sdougb masterformat = dns_masterformat_text; 374170222Sdougb else if (strcasecmp(masterformatstr, "raw") == 0) 375170222Sdougb masterformat = dns_masterformat_raw; 376170222Sdougb else 377170222Sdougb INSIST(0); 378170222Sdougb } 379170222Sdougb 380170222Sdougb result = load_zone(mctx, zname, zfile, masterformat, zclass, NULL); 381135446Strhodes if (result != ISC_R_SUCCESS) 382135446Strhodes fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass, 383135446Strhodes dns_result_totext(result)); 384262706Serwin return (result); 385135446Strhodes} 386135446Strhodes 387170222Sdougb/*% configure a view */ 388135446Strhodesstatic isc_result_t 389165071Sdougbconfigure_view(const char *vclass, const char *view, const cfg_obj_t *config, 390165071Sdougb const cfg_obj_t *vconfig, isc_mem_t *mctx) 391135446Strhodes{ 392165071Sdougb const cfg_listelt_t *element; 393165071Sdougb const cfg_obj_t *voptions; 394165071Sdougb const cfg_obj_t *zonelist; 395135446Strhodes isc_result_t result = ISC_R_SUCCESS; 396135446Strhodes isc_result_t tresult; 397135446Strhodes 398135446Strhodes voptions = NULL; 399135446Strhodes if (vconfig != NULL) 400135446Strhodes voptions = cfg_tuple_get(vconfig, "options"); 401135446Strhodes 402135446Strhodes zonelist = NULL; 403135446Strhodes if (voptions != NULL) 404135446Strhodes (void)cfg_map_get(voptions, "zone", &zonelist); 405135446Strhodes else 406135446Strhodes (void)cfg_map_get(config, "zone", &zonelist); 407135446Strhodes 408135446Strhodes for (element = cfg_list_first(zonelist); 409135446Strhodes element != NULL; 410135446Strhodes element = cfg_list_next(element)) 411135446Strhodes { 412165071Sdougb const cfg_obj_t *zconfig = cfg_listelt_value(element); 413170222Sdougb tresult = configure_zone(vclass, view, zconfig, vconfig, 414170222Sdougb config, mctx); 415135446Strhodes if (tresult != ISC_R_SUCCESS) 416135446Strhodes result = tresult; 417135446Strhodes } 418135446Strhodes return (result); 419135446Strhodes} 420135446Strhodes 421135446Strhodes 422170222Sdougb/*% load zones from the configuration */ 423135446Strhodesstatic isc_result_t 424165071Sdougbload_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) { 425165071Sdougb const cfg_listelt_t *element; 426165071Sdougb const cfg_obj_t *classobj; 427165071Sdougb const cfg_obj_t *views; 428165071Sdougb const cfg_obj_t *vconfig; 429135446Strhodes const char *vclass; 430135446Strhodes isc_result_t result = ISC_R_SUCCESS; 431135446Strhodes isc_result_t tresult; 432135446Strhodes 433135446Strhodes views = NULL; 434135446Strhodes 435135446Strhodes (void)cfg_map_get(config, "view", &views); 436135446Strhodes for (element = cfg_list_first(views); 437135446Strhodes element != NULL; 438135446Strhodes element = cfg_list_next(element)) 439135446Strhodes { 440135446Strhodes const char *vname; 441135446Strhodes 442135446Strhodes vclass = "IN"; 443135446Strhodes vconfig = cfg_listelt_value(element); 444135446Strhodes if (vconfig != NULL) { 445135446Strhodes classobj = cfg_tuple_get(vconfig, "class"); 446135446Strhodes if (cfg_obj_isstring(classobj)) 447135446Strhodes vclass = cfg_obj_asstring(classobj); 448135446Strhodes } 449135446Strhodes vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 450135446Strhodes tresult = configure_view(vclass, vname, config, vconfig, mctx); 451135446Strhodes if (tresult != ISC_R_SUCCESS) 452135446Strhodes result = tresult; 453135446Strhodes } 454135446Strhodes 455135446Strhodes if (views == NULL) { 456135446Strhodes tresult = configure_view("IN", "_default", config, NULL, mctx); 457135446Strhodes if (tresult != ISC_R_SUCCESS) 458135446Strhodes result = tresult; 459135446Strhodes } 460135446Strhodes return (result); 461135446Strhodes} 462135446Strhodes 463224092Sdougbstatic void 464224092Sdougboutput(void *closure, const char *text, int textlen) { 465224092Sdougb UNUSED(closure); 466224092Sdougb if (fwrite(text, 1, textlen, stdout) != (size_t)textlen) { 467224092Sdougb perror("fwrite"); 468224092Sdougb exit(1); 469224092Sdougb } 470224092Sdougb} 471224092Sdougb 472170222Sdougb/*% The main processing routine */ 473135446Strhodesint 474135446Strhodesmain(int argc, char **argv) { 475135446Strhodes int c; 476135446Strhodes cfg_parser_t *parser = NULL; 477135446Strhodes cfg_obj_t *config = NULL; 478135446Strhodes const char *conffile = NULL; 479135446Strhodes isc_mem_t *mctx = NULL; 480135446Strhodes isc_result_t result; 481135446Strhodes int exit_status = 0; 482143731Sdougb isc_entropy_t *ectx = NULL; 483135446Strhodes isc_boolean_t load_zones = ISC_FALSE; 484224092Sdougb isc_boolean_t print = ISC_FALSE; 485262706Serwin unsigned int flags = 0; 486193149Sdougb 487193149Sdougb isc_commandline_errprint = ISC_FALSE; 488193149Sdougb 489262706Serwin while ((c = isc_commandline_parse(argc, argv, "dhjt:pvxz")) != EOF) { 490135446Strhodes switch (c) { 491135446Strhodes case 'd': 492135446Strhodes debug++; 493135446Strhodes break; 494135446Strhodes 495135446Strhodes case 'j': 496135446Strhodes nomerge = ISC_FALSE; 497135446Strhodes break; 498135446Strhodes 499135446Strhodes case 't': 500135446Strhodes result = isc_dir_chroot(isc_commandline_argument); 501135446Strhodes if (result != ISC_R_SUCCESS) { 502135446Strhodes fprintf(stderr, "isc_dir_chroot: %s\n", 503135446Strhodes isc_result_totext(result)); 504135446Strhodes exit(1); 505135446Strhodes } 506135446Strhodes break; 507135446Strhodes 508224092Sdougb case 'p': 509224092Sdougb print = ISC_TRUE; 510224092Sdougb break; 511224092Sdougb 512135446Strhodes case 'v': 513135446Strhodes printf(VERSION "\n"); 514135446Strhodes exit(0); 515135446Strhodes 516262706Serwin case 'x': 517262706Serwin flags |= CFG_PRINTER_XKEY; 518262706Serwin break; 519262706Serwin 520135446Strhodes case 'z': 521135446Strhodes load_zones = ISC_TRUE; 522170222Sdougb docheckmx = ISC_FALSE; 523170222Sdougb docheckns = ISC_FALSE; 524170222Sdougb dochecksrv = ISC_FALSE; 525135446Strhodes break; 526135446Strhodes 527193149Sdougb case '?': 528193149Sdougb if (isc_commandline_option != '?') 529193149Sdougb fprintf(stderr, "%s: invalid argument -%c\n", 530193149Sdougb program, isc_commandline_option); 531254402Serwin /* FALLTHROUGH */ 532193149Sdougb case 'h': 533193149Sdougb usage(); 534193149Sdougb 535135446Strhodes default: 536193149Sdougb fprintf(stderr, "%s: unhandled option -%c\n", 537193149Sdougb program, isc_commandline_option); 538193149Sdougb exit(1); 539135446Strhodes } 540135446Strhodes } 541135446Strhodes 542262706Serwin if (((flags & CFG_PRINTER_XKEY) != 0) && !print) { 543262706Serwin fprintf(stderr, "%s: -x cannot be used without -p\n", program); 544262706Serwin exit(1); 545262706Serwin } 546262706Serwin 547193149Sdougb if (isc_commandline_index + 1 < argc) 548193149Sdougb usage(); 549135446Strhodes if (argv[isc_commandline_index] != NULL) 550135446Strhodes conffile = argv[isc_commandline_index]; 551135446Strhodes if (conffile == NULL || conffile[0] == '\0') 552135446Strhodes conffile = NAMED_CONFFILE; 553135446Strhodes 554216175Sdougb#ifdef _WIN32 555216175Sdougb InitSockets(); 556216175Sdougb#endif 557216175Sdougb 558135446Strhodes RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); 559135446Strhodes 560193149Sdougb RUNTIME_CHECK(setup_logging(mctx, stdout, &logc) == ISC_R_SUCCESS); 561135446Strhodes 562143731Sdougb RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS); 563143731Sdougb RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE) 564143731Sdougb == ISC_R_SUCCESS); 565143731Sdougb 566135446Strhodes dns_result_register(); 567135446Strhodes 568135446Strhodes RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS); 569135446Strhodes 570135446Strhodes cfg_parser_setcallback(parser, directory_callback, NULL); 571135446Strhodes 572135446Strhodes if (cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config) != 573135446Strhodes ISC_R_SUCCESS) 574135446Strhodes exit(1); 575135446Strhodes 576135446Strhodes result = bind9_check_namedconf(config, logc, mctx); 577135446Strhodes if (result != ISC_R_SUCCESS) 578135446Strhodes exit_status = 1; 579135446Strhodes 580135446Strhodes if (result == ISC_R_SUCCESS && load_zones) { 581135446Strhodes result = load_zones_fromconfig(config, mctx); 582135446Strhodes if (result != ISC_R_SUCCESS) 583135446Strhodes exit_status = 1; 584135446Strhodes } 585135446Strhodes 586224092Sdougb if (print && exit_status == 0) 587262706Serwin cfg_printx(config, flags, output, NULL); 588135446Strhodes cfg_obj_destroy(parser, &config); 589135446Strhodes 590135446Strhodes cfg_parser_destroy(&parser); 591135446Strhodes 592170222Sdougb dns_name_destroy(); 593170222Sdougb 594135446Strhodes isc_log_destroy(&logc); 595135446Strhodes 596143731Sdougb isc_hash_destroy(); 597143731Sdougb isc_entropy_detach(&ectx); 598143731Sdougb 599135446Strhodes isc_mem_destroy(&mctx); 600135446Strhodes 601216175Sdougb#ifdef _WIN32 602216175Sdougb DestroySockets(); 603216175Sdougb#endif 604216175Sdougb 605135446Strhodes return (exit_status); 606135446Strhodes} 607