server.c revision 254897
1198160Srrs/* 2198160Srrs * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") 3198160Srrs * Copyright (C) 1999-2003 Internet Software Consortium. 4198160Srrs * 5198160Srrs * Permission to use, copy, modify, and/or distribute this software for any 6198160Srrs * purpose with or without fee is hereby granted, provided that the above 7198160Srrs * copyright notice and this permission notice appear in all copies. 8198160Srrs * 9198160Srrs * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10198160Srrs * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11198160Srrs * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12198160Srrs * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13198160Srrs * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14198160Srrs * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15198160Srrs * PERFORMANCE OF THIS SOFTWARE. 16198160Srrs */ 17198160Srrs 18198160Srrs/* $Id$ */ 19198160Srrs 20198160Srrs/*! \file */ 21198160Srrs 22198160Srrs#include <config.h> 23198160Srrs 24198160Srrs#include <stdlib.h> 25198160Srrs#include <unistd.h> 26198160Srrs#include <limits.h> 27198160Srrs#include <ctype.h> 28198160Srrs#include <sys/types.h> 29202066Simp#include <sys/stat.h> 30202066Simp 31198160Srrs#include <isc/app.h> 32202066Simp#include <isc/base64.h> 33202066Simp#include <isc/dir.h> 34202066Simp#include <isc/entropy.h> 35198160Srrs#include <isc/file.h> 36198160Srrs#include <isc/hash.h> 37198160Srrs#include <isc/hex.h> 38198160Srrs#include <isc/httpd.h> 39198160Srrs#include <isc/lex.h> 40198160Srrs#include <isc/parseint.h> 41198160Srrs#include <isc/portset.h> 42198160Srrs#include <isc/print.h> 43211994Sjchandra#include <isc/refcount.h> 44198160Srrs#include <isc/resource.h> 45198160Srrs#include <isc/sha2.h> 46198160Srrs#include <isc/socket.h> 47198160Srrs#include <isc/stat.h> 48198160Srrs#include <isc/stats.h> 49198160Srrs#include <isc/stdio.h> 50198160Srrs#include <isc/string.h> 51198607Srrs#include <isc/task.h> 52198607Srrs#include <isc/timer.h> 53198607Srrs#include <isc/util.h> 54198607Srrs#include <isc/xml.h> 55211994Sjchandra 56211994Sjchandra#include <isccfg/namedconf.h> 57211994Sjchandra 58198607Srrs#include <bind9/check.h> 59198607Srrs 60198607Srrs#include <dns/acache.h> 61211994Sjchandra#include <dns/adb.h> 62198607Srrs#include <dns/cache.h> 63202066Simp#include <dns/db.h> 64202066Simp#include <dns/dispatch.h> 65198607Srrs#include <dns/dlz.h> 66198160Srrs#include <dns/dns64.h> 67198160Srrs#include <dns/forward.h> 68198625Srrs#include <dns/journal.h> 69198625Srrs#include <dns/keytable.h> 70198625Srrs#include <dns/keyvalues.h> 71198160Srrs#include <dns/lib.h> 72199090Srrs#include <dns/master.h> 73198625Srrs#include <dns/masterdump.h> 74198625Srrs#include <dns/order.h> 75199090Srrs#include <dns/peer.h> 76198625Srrs#include <dns/portlist.h> 77198625Srrs#include <dns/private.h> 78198160Srrs#include <dns/rbt.h> 79198625Srrs#include <dns/rdataclass.h> 80198160Srrs#include <dns/rdataset.h> 81211923Sjchandra#include <dns/rdatastruct.h> 82211923Sjchandra#include <dns/resolver.h> 83211923Sjchandra#include <dns/rootns.h> 84211923Sjchandra#include <dns/secalg.h> 85211923Sjchandra#include <dns/stats.h> 86211923Sjchandra#include <dns/tkey.h> 87211923Sjchandra#include <dns/tsig.h> 88211923Sjchandra#include <dns/view.h> 89211923Sjchandra#include <dns/zone.h> 90211923Sjchandra#include <dns/zt.h> 91211923Sjchandra 92211923Sjchandra#include <dst/dst.h> 93211923Sjchandra#include <dst/result.h> 94211923Sjchandra 95198160Srrs#include <named/client.h> 96198160Srrs#include <named/config.h> 97212102Sjchandra#include <named/control.h> 98211811Sjchandra#include <named/interfacemgr.h> 99198160Srrs#include <named/log.h> 100211946Sjchandra#include <named/logconf.h> 101198160Srrs#include <named/lwresd.h> 102211946Sjchandra#include <named/main.h> 103198625Srrs#include <named/os.h> 104211811Sjchandra#include <named/server.h> 105211811Sjchandra#include <named/statschannel.h> 106212248Sjchandra#include <named/tkeyconf.h> 107211946Sjchandra#include <named/tsigconf.h> 108198625Srrs#include <named/zoneconf.h> 109199090Srrs#ifdef HAVE_LIBSCF 110199089Srrs#include <named/ns_smf_globals.h> 111209808Sjchandra#include <stdlib.h> 112211811Sjchandra#endif 113211811Sjchandra 114212248Sjchandra#ifndef PATH_MAX 115211946Sjchandra#define PATH_MAX 1024 116211811Sjchandra#endif 117211811Sjchandra 118212248Sjchandra#ifndef SIZE_MAX 119211946Sjchandra#define SIZE_MAX ((size_t)-1) 120211923Sjchandra#endif 121211923Sjchandra 122212248Sjchandra/*% 123198625Srrs * Check an operation for failure. Assumes that the function 124198625Srrs * using it has a 'result' variable and a 'cleanup' label. 125198160Srrs */ 126198160Srrs#define CHECK(op) \ 127198160Srrs do { result = (op); \ 128198160Srrs if (result != ISC_R_SUCCESS) goto cleanup; \ 129198625Srrs } while (0) 130198160Srrs 131198160Srrs#define CHECKM(op, msg) \ 132212102Sjchandra do { result = (op); \ 133198160Srrs if (result != ISC_R_SUCCESS) { \ 134198160Srrs isc_log_write(ns_g_lctx, \ 135198160Srrs NS_LOGCATEGORY_GENERAL, \ 136198160Srrs NS_LOGMODULE_SERVER, \ 137198160Srrs ISC_LOG_ERROR, \ 138198160Srrs "%s: %s", msg, \ 139198625Srrs isc_result_totext(result)); \ 140198625Srrs goto cleanup; \ 141198160Srrs } \ 142198625Srrs } while (0) \ 143198160Srrs 144198625Srrs#define CHECKMF(op, msg, file) \ 145198625Srrs do { result = (op); \ 146198160Srrs if (result != ISC_R_SUCCESS) { \ 147198625Srrs isc_log_write(ns_g_lctx, \ 148198160Srrs NS_LOGCATEGORY_GENERAL, \ 149198625Srrs NS_LOGMODULE_SERVER, \ 150198625Srrs ISC_LOG_ERROR, \ 151198625Srrs "%s '%s': %s", msg, file, \ 152198160Srrs isc_result_totext(result)); \ 153198160Srrs goto cleanup; \ 154212102Sjchandra } \ 155198625Srrs } while (0) \ 156198160Srrs 157198625Srrs#define CHECKFATAL(op, msg) \ 158198160Srrs do { result = (op); \ 159198625Srrs if (result != ISC_R_SUCCESS) \ 160198160Srrs fatal(msg, result); \ 161198160Srrs } while (0) \ 162198160Srrs 163212102Sjchandra/*% 164209808Sjchandra * Maximum ADB size for views that share a cache. Use this limit to suppress 165204577Srrs * the total of memory footprint, which should be the main reason for sharing 166212102Sjchandra * a cache. Only effective when a finite max-cache-size is specified. 167209808Sjchandra * This is currently defined to be 8MB. 168198160Srrs */ 169212102Sjchandra#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U 170211923Sjchandra 171211923Sjchandrastruct ns_dispatch { 172198160Srrs isc_sockaddr_t addr; 173198625Srrs unsigned int dispatchgen; 174198160Srrs dns_dispatch_t *dispatch; 175198160Srrs ISC_LINK(struct ns_dispatch) link; 176198160Srrs}; 177198160Srrs 178198160Srrsstruct ns_cache { 179198625Srrs dns_cache_t *cache; 180198160Srrs dns_view_t *primaryview; 181198160Srrs isc_boolean_t needflush; 182198160Srrs isc_boolean_t adbsizeadjusted; 183198625Srrs ISC_LINK(ns_cache_t) link; 184198160Srrs}; 185198625Srrs 186198625Srrsstruct dumpcontext { 187211946Sjchandra isc_mem_t *mctx; 188198625Srrs isc_boolean_t dumpcache; 189198160Srrs isc_boolean_t dumpzones; 190198160Srrs FILE *fp; 191198160Srrs ISC_LIST(struct viewlistentry) viewlist; 192198160Srrs struct viewlistentry *view; 193198160Srrs struct zonelistentry *zone; 194198160Srrs dns_dumpctx_t *mdctx; 195198160Srrs dns_db_t *db; 196198160Srrs dns_db_t *cache; 197198625Srrs isc_task_t *task; 198198160Srrs dns_dbversion_t *version; 199198625Srrs}; 200198160Srrs 201198160Srrsstruct viewlistentry { 202198160Srrs dns_view_t *view; 203198160Srrs ISC_LINK(struct viewlistentry) link; 204198160Srrs ISC_LIST(struct zonelistentry) zonelist; 205198160Srrs}; 206198160Srrs 207211946Sjchandrastruct zonelistentry { 208198625Srrs dns_zone_t *zone; 209198160Srrs ISC_LINK(struct zonelistentry) link; 210198625Srrs}; 211198160Srrs 212198160Srrs/*% 213198160Srrs * Configuration context to retain for each view that allows 214216390Sjchandra * new zones to be added at runtime. 215208165Srrs */ 216212763Sjchandrastruct cfg_context { 217198625Srrs isc_mem_t * mctx; 218198160Srrs cfg_parser_t * parser; 219198160Srrs cfg_obj_t * config; 220198625Srrs cfg_parser_t * nzparser; 221198160Srrs cfg_obj_t * nzconfig; 222198160Srrs cfg_aclconfctx_t * actx; 223198160Srrs}; 224211923Sjchandra 225211923Sjchandra/*% 226211923Sjchandra * Holds state information for the initial zone loading process. 227198160Srrs * Uses the isc_refcount structure to count the number of views 228198160Srrs * with pending zone loads, dereferencing as each view finishes. 229198160Srrs */ 230198160Srrstypedef struct { 231198160Srrs ns_server_t *server; 232198160Srrs isc_refcount_t refs; 233198160Srrs} ns_zoneload_t; 234198160Srrs 235198160Srrs/* 236198160Srrs * These zones should not leak onto the Internet. 237198160Srrs */ 238198160Srrsconst char *empty_zones[] = { 239198160Srrs /* RFC 1918 */ 240198160Srrs "10.IN-ADDR.ARPA", 241198160Srrs "16.172.IN-ADDR.ARPA", 242198160Srrs "17.172.IN-ADDR.ARPA", 243198160Srrs "18.172.IN-ADDR.ARPA", 244198160Srrs "19.172.IN-ADDR.ARPA", 245198160Srrs "20.172.IN-ADDR.ARPA", 246198160Srrs "21.172.IN-ADDR.ARPA", 247198160Srrs "22.172.IN-ADDR.ARPA", 248204137Srrs "23.172.IN-ADDR.ARPA", 249204137Srrs "24.172.IN-ADDR.ARPA", 250204137Srrs "25.172.IN-ADDR.ARPA", 251204137Srrs "26.172.IN-ADDR.ARPA", 252198160Srrs "27.172.IN-ADDR.ARPA", 253204137Srrs "28.172.IN-ADDR.ARPA", 254204137Srrs "29.172.IN-ADDR.ARPA", 255204137Srrs "30.172.IN-ADDR.ARPA", 256204137Srrs "31.172.IN-ADDR.ARPA", 257198160Srrs "168.192.IN-ADDR.ARPA", 258198625Srrs 259198160Srrs /* RFC 6598 */ 260198160Srrs "64.100.IN-ADDR.ARPA", 261198160Srrs "65.100.IN-ADDR.ARPA", 262198160Srrs "66.100.IN-ADDR.ARPA", 263198160Srrs "67.100.IN-ADDR.ARPA", 264198160Srrs "68.100.IN-ADDR.ARPA", 265211946Sjchandra "69.100.IN-ADDR.ARPA", 266211946Sjchandra "70.100.IN-ADDR.ARPA", 267198160Srrs "71.100.IN-ADDR.ARPA", 268211946Sjchandra "72.100.IN-ADDR.ARPA", 269211946Sjchandra "73.100.IN-ADDR.ARPA", 270211946Sjchandra "74.100.IN-ADDR.ARPA", 271211946Sjchandra "75.100.IN-ADDR.ARPA", 272211946Sjchandra "76.100.IN-ADDR.ARPA", 273211946Sjchandra "77.100.IN-ADDR.ARPA", 274211946Sjchandra "78.100.IN-ADDR.ARPA", 275211946Sjchandra "79.100.IN-ADDR.ARPA", 276211946Sjchandra "80.100.IN-ADDR.ARPA", 277211946Sjchandra "81.100.IN-ADDR.ARPA", 278211946Sjchandra "82.100.IN-ADDR.ARPA", 279198160Srrs "83.100.IN-ADDR.ARPA", 280198160Srrs "84.100.IN-ADDR.ARPA", 281198160Srrs "85.100.IN-ADDR.ARPA", 282198160Srrs "86.100.IN-ADDR.ARPA", 283198160Srrs "87.100.IN-ADDR.ARPA", 284211946Sjchandra "88.100.IN-ADDR.ARPA", 285211946Sjchandra "89.100.IN-ADDR.ARPA", 286211946Sjchandra "90.100.IN-ADDR.ARPA", 287211946Sjchandra "91.100.IN-ADDR.ARPA", 288211946Sjchandra "92.100.IN-ADDR.ARPA", 289211946Sjchandra "93.100.IN-ADDR.ARPA", 290211946Sjchandra "94.100.IN-ADDR.ARPA", 291211946Sjchandra "95.100.IN-ADDR.ARPA", 292211946Sjchandra "96.100.IN-ADDR.ARPA", 293211946Sjchandra "97.100.IN-ADDR.ARPA", 294211946Sjchandra "98.100.IN-ADDR.ARPA", 295211946Sjchandra "99.100.IN-ADDR.ARPA", 296211946Sjchandra "100.100.IN-ADDR.ARPA", 297211946Sjchandra "101.100.IN-ADDR.ARPA", 298211946Sjchandra "102.100.IN-ADDR.ARPA", 299211946Sjchandra "103.100.IN-ADDR.ARPA", 300211946Sjchandra "104.100.IN-ADDR.ARPA", 301211946Sjchandra "105.100.IN-ADDR.ARPA", 302198160Srrs "106.100.IN-ADDR.ARPA", 303198160Srrs "107.100.IN-ADDR.ARPA", 304198160Srrs "108.100.IN-ADDR.ARPA", 305211946Sjchandra "109.100.IN-ADDR.ARPA", 306198160Srrs "110.100.IN-ADDR.ARPA", 307198160Srrs "111.100.IN-ADDR.ARPA", 308198160Srrs "112.100.IN-ADDR.ARPA", 309212550Sjchandra "113.100.IN-ADDR.ARPA", 310198160Srrs "114.100.IN-ADDR.ARPA", 311198160Srrs "115.100.IN-ADDR.ARPA", 312198160Srrs "116.100.IN-ADDR.ARPA", 313198160Srrs "117.100.IN-ADDR.ARPA", 314198160Srrs "118.100.IN-ADDR.ARPA", 315198160Srrs "119.100.IN-ADDR.ARPA", 316198160Srrs "120.100.IN-ADDR.ARPA", 317198625Srrs "121.100.IN-ADDR.ARPA", 318198160Srrs "122.100.IN-ADDR.ARPA", 319198160Srrs "123.100.IN-ADDR.ARPA", 320198160Srrs "124.100.IN-ADDR.ARPA", 321198160Srrs "125.100.IN-ADDR.ARPA", 322 "126.100.IN-ADDR.ARPA", 323 "127.100.IN-ADDR.ARPA", 324 325 /* RFC 5735 and RFC 5737 */ 326 "0.IN-ADDR.ARPA", /* THIS NETWORK */ 327 "127.IN-ADDR.ARPA", /* LOOPBACK */ 328 "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ 329 "2.0.192.IN-ADDR.ARPA", /* TEST NET */ 330 "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ 331 "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ 332 "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ 333 334 /* Local IPv6 Unicast Addresses */ 335 "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", 336 "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", 337 /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ 338 "D.F.IP6.ARPA", 339 "8.E.F.IP6.ARPA", /* LINK LOCAL */ 340 "9.E.F.IP6.ARPA", /* LINK LOCAL */ 341 "A.E.F.IP6.ARPA", /* LINK LOCAL */ 342 "B.E.F.IP6.ARPA", /* LINK LOCAL */ 343 344 /* Example Prefix, RFC 3849. */ 345 "8.B.D.0.1.0.0.2.IP6.ARPA", 346 347 NULL 348}; 349 350ISC_PLATFORM_NORETURN_PRE static void 351fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST; 352 353static void 354ns_server_reload(isc_task_t *task, isc_event_t *event); 355 356static isc_result_t 357ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 358 cfg_aclconfctx_t *actx, 359 isc_mem_t *mctx, ns_listenelt_t **target); 360static isc_result_t 361ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 362 cfg_aclconfctx_t *actx, 363 isc_mem_t *mctx, ns_listenlist_t **target); 364 365static isc_result_t 366configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 367 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype); 368 369static isc_result_t 370configure_alternates(const cfg_obj_t *config, dns_view_t *view, 371 const cfg_obj_t *alternates); 372 373static isc_result_t 374configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 375 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 376 cfg_aclconfctx_t *aclconf, isc_boolean_t added); 377 378static isc_result_t 379add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); 380 381static void 382end_reserved_dispatches(ns_server_t *server, isc_boolean_t all); 383 384static void 385newzone_cfgctx_destroy(void **cfgp); 386 387/*% 388 * Configure a single view ACL at '*aclp'. Get its configuration from 389 * 'vconfig' (for per-view configuration) and maybe from 'config' 390 */ 391static isc_result_t 392configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, 393 const char *aclname, const char *acltuplename, 394 cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp) 395{ 396 isc_result_t result; 397 const cfg_obj_t *maps[3]; 398 const cfg_obj_t *aclobj = NULL; 399 int i = 0; 400 401 if (*aclp != NULL) 402 dns_acl_detach(aclp); 403 if (vconfig != NULL) 404 maps[i++] = cfg_tuple_get(vconfig, "options"); 405 if (config != NULL) { 406 const cfg_obj_t *options = NULL; 407 (void)cfg_map_get(config, "options", &options); 408 if (options != NULL) 409 maps[i++] = options; 410 } 411 maps[i] = NULL; 412 413 (void)ns_config_get(maps, aclname, &aclobj); 414 if (aclobj == NULL) 415 /* 416 * No value available. *aclp == NULL. 417 */ 418 return (ISC_R_SUCCESS); 419 420 if (acltuplename != NULL) { 421 /* 422 * If the ACL is given in an optional tuple, retrieve it. 423 * The parser should have ensured that a valid object be 424 * returned. 425 */ 426 aclobj = cfg_tuple_get(aclobj, acltuplename); 427 } 428 429 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, 430 actx, mctx, 0, aclp); 431 432 return (result); 433} 434 435/*% 436 * Configure a sortlist at '*aclp'. Essentially the same as 437 * configure_view_acl() except it calls cfg_acl_fromconfig with a 438 * nest_level value of 2. 439 */ 440static isc_result_t 441configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, 442 cfg_aclconfctx_t *actx, isc_mem_t *mctx, 443 dns_acl_t **aclp) 444{ 445 isc_result_t result; 446 const cfg_obj_t *maps[3]; 447 const cfg_obj_t *aclobj = NULL; 448 int i = 0; 449 450 if (*aclp != NULL) 451 dns_acl_detach(aclp); 452 if (vconfig != NULL) 453 maps[i++] = cfg_tuple_get(vconfig, "options"); 454 if (config != NULL) { 455 const cfg_obj_t *options = NULL; 456 (void)cfg_map_get(config, "options", &options); 457 if (options != NULL) 458 maps[i++] = options; 459 } 460 maps[i] = NULL; 461 462 (void)ns_config_get(maps, "sortlist", &aclobj); 463 if (aclobj == NULL) 464 return (ISC_R_SUCCESS); 465 466 /* 467 * Use a nest level of 3 for the "top level" of the sortlist; 468 * this means each entry in the top three levels will be stored 469 * as lists of separate, nested ACLs, rather than merged together 470 * into IP tables as is usually done with ACLs. 471 */ 472 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, 473 actx, mctx, 3, aclp); 474 475 return (result); 476} 477 478static isc_result_t 479configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, 480 const char *confname, const char *conftuplename, 481 isc_mem_t *mctx, dns_rbt_t **rbtp) 482{ 483 isc_result_t result; 484 const cfg_obj_t *maps[3]; 485 const cfg_obj_t *obj = NULL; 486 const cfg_listelt_t *element; 487 int i = 0; 488 dns_fixedname_t fixed; 489 dns_name_t *name; 490 isc_buffer_t b; 491 const char *str; 492 const cfg_obj_t *nameobj; 493 494 if (*rbtp != NULL) 495 dns_rbt_destroy(rbtp); 496 if (vconfig != NULL) 497 maps[i++] = cfg_tuple_get(vconfig, "options"); 498 if (config != NULL) { 499 const cfg_obj_t *options = NULL; 500 (void)cfg_map_get(config, "options", &options); 501 if (options != NULL) 502 maps[i++] = options; 503 } 504 maps[i] = NULL; 505 506 (void)ns_config_get(maps, confname, &obj); 507 if (obj == NULL) 508 /* 509 * No value available. *rbtp == NULL. 510 */ 511 return (ISC_R_SUCCESS); 512 513 if (conftuplename != NULL) { 514 obj = cfg_tuple_get(obj, conftuplename); 515 if (cfg_obj_isvoid(obj)) 516 return (ISC_R_SUCCESS); 517 } 518 519 result = dns_rbt_create(mctx, NULL, NULL, rbtp); 520 if (result != ISC_R_SUCCESS) 521 return (result); 522 523 dns_fixedname_init(&fixed); 524 name = dns_fixedname_name(&fixed); 525 for (element = cfg_list_first(obj); 526 element != NULL; 527 element = cfg_list_next(element)) { 528 nameobj = cfg_listelt_value(element); 529 str = cfg_obj_asstring(nameobj); 530 isc_buffer_constinit(&b, str, strlen(str)); 531 isc_buffer_add(&b, strlen(str)); 532 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 533 /* 534 * We don't need the node data, but need to set dummy data to 535 * avoid a partial match with an empty node. For example, if 536 * we have foo.example.com and bar.example.com, we'd get a match 537 * for baz.example.com, which is not the expected result. 538 * We simply use (void *)1 as the dummy data. 539 */ 540 result = dns_rbt_addname(*rbtp, name, (void *)1); 541 if (result != ISC_R_SUCCESS) { 542 cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR, 543 "failed to add %s for %s: %s", 544 str, confname, isc_result_totext(result)); 545 goto cleanup; 546 } 547 548 } 549 550 return (result); 551 552 cleanup: 553 dns_rbt_destroy(rbtp); 554 return (result); 555 556} 557 558static isc_result_t 559dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, 560 isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx) 561{ 562 dns_rdataclass_t viewclass; 563 dns_rdata_dnskey_t keystruct; 564 isc_uint32_t flags, proto, alg; 565 const char *keystr, *keynamestr; 566 unsigned char keydata[4096]; 567 isc_buffer_t keydatabuf; 568 unsigned char rrdata[4096]; 569 isc_buffer_t rrdatabuf; 570 isc_region_t r; 571 dns_fixedname_t fkeyname; 572 dns_name_t *keyname; 573 isc_buffer_t namebuf; 574 isc_result_t result; 575 dst_key_t *dstkey = NULL; 576 577 INSIST(target != NULL && *target == NULL); 578 579 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); 580 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); 581 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); 582 keyname = dns_fixedname_name(&fkeyname); 583 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 584 585 if (managed) { 586 const char *initmethod; 587 initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); 588 589 if (strcasecmp(initmethod, "initial-key") != 0) { 590 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 591 "managed key '%s': " 592 "invalid initialization method '%s'", 593 keynamestr, initmethod); 594 result = ISC_R_FAILURE; 595 goto cleanup; 596 } 597 } 598 599 if (vconfig == NULL) 600 viewclass = dns_rdataclass_in; 601 else { 602 const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); 603 CHECK(ns_config_getclass(classobj, dns_rdataclass_in, 604 &viewclass)); 605 } 606 keystruct.common.rdclass = viewclass; 607 keystruct.common.rdtype = dns_rdatatype_dnskey; 608 /* 609 * The key data in keystruct is not dynamically allocated. 610 */ 611 keystruct.mctx = NULL; 612 613 ISC_LINK_INIT(&keystruct.common, link); 614 615 if (flags > 0xffff) 616 CHECKM(ISC_R_RANGE, "key flags"); 617 if (proto > 0xff) 618 CHECKM(ISC_R_RANGE, "key protocol"); 619 if (alg > 0xff) 620 CHECKM(ISC_R_RANGE, "key algorithm"); 621 keystruct.flags = (isc_uint16_t)flags; 622 keystruct.protocol = (isc_uint8_t)proto; 623 keystruct.algorithm = (isc_uint8_t)alg; 624 625 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); 626 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 627 628 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); 629 CHECK(isc_base64_decodestring(keystr, &keydatabuf)); 630 isc_buffer_usedregion(&keydatabuf, &r); 631 keystruct.datalen = r.length; 632 keystruct.data = r.base; 633 634 if ((keystruct.algorithm == DST_ALG_RSASHA1 || 635 keystruct.algorithm == DST_ALG_RSAMD5) && 636 r.length > 1 && r.base[0] == 1 && r.base[1] == 3) 637 cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, 638 "%s key '%s' has a weak exponent", 639 managed ? "managed" : "trusted", 640 keynamestr); 641 642 CHECK(dns_rdata_fromstruct(NULL, 643 keystruct.common.rdclass, 644 keystruct.common.rdtype, 645 &keystruct, &rrdatabuf)); 646 dns_fixedname_init(&fkeyname); 647 isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr)); 648 isc_buffer_add(&namebuf, strlen(keynamestr)); 649 CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL)); 650 CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, 651 mctx, &dstkey)); 652 653 *target = dstkey; 654 return (ISC_R_SUCCESS); 655 656 cleanup: 657 if (result == DST_R_NOCRYPTO) { 658 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 659 "ignoring %s key for '%s': no crypto support", 660 managed ? "managed" : "trusted", 661 keynamestr); 662 } else if (result == DST_R_UNSUPPORTEDALG) { 663 cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, 664 "skipping %s key for '%s': %s", 665 managed ? "managed" : "trusted", 666 keynamestr, isc_result_totext(result)); 667 } else { 668 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 669 "configuring %s key for '%s': %s", 670 managed ? "managed" : "trusted", 671 keynamestr, isc_result_totext(result)); 672 result = ISC_R_FAILURE; 673 } 674 675 if (dstkey != NULL) 676 dst_key_free(&dstkey); 677 678 return (result); 679} 680 681static isc_result_t 682load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig, 683 dns_view_t *view, isc_boolean_t managed, 684 dns_name_t *keyname, isc_mem_t *mctx) 685{ 686 const cfg_listelt_t *elt, *elt2; 687 const cfg_obj_t *key, *keylist; 688 dst_key_t *dstkey = NULL; 689 isc_result_t result; 690 dns_keytable_t *secroots = NULL; 691 692 CHECK(dns_view_getsecroots(view, &secroots)); 693 694 for (elt = cfg_list_first(keys); 695 elt != NULL; 696 elt = cfg_list_next(elt)) { 697 keylist = cfg_listelt_value(elt); 698 699 for (elt2 = cfg_list_first(keylist); 700 elt2 != NULL; 701 elt2 = cfg_list_next(elt2)) { 702 key = cfg_listelt_value(elt2); 703 result = dstkey_fromconfig(vconfig, key, managed, 704 &dstkey, mctx); 705 if (result == DST_R_UNSUPPORTEDALG) { 706 result = ISC_R_SUCCESS; 707 continue; 708 } 709 if (result != ISC_R_SUCCESS) 710 goto cleanup; 711 712 /* 713 * If keyname was specified, we only add that key. 714 */ 715 if (keyname != NULL && 716 !dns_name_equal(keyname, dst_key_name(dstkey))) 717 { 718 dst_key_free(&dstkey); 719 continue; 720 } 721 722 CHECK(dns_keytable_add(secroots, managed, &dstkey)); 723 } 724 } 725 726 cleanup: 727 if (dstkey != NULL) 728 dst_key_free(&dstkey); 729 if (secroots != NULL) 730 dns_keytable_detach(&secroots); 731 if (result == DST_R_NOCRYPTO) 732 result = ISC_R_SUCCESS; 733 return (result); 734} 735 736/*% 737 * Configure DNSSEC keys for a view. 738 * 739 * The per-view configuration values and the server-global defaults are read 740 * from 'vconfig' and 'config'. 741 */ 742static isc_result_t 743configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, 744 const cfg_obj_t *config, const cfg_obj_t *bindkeys, 745 isc_boolean_t auto_dlv, isc_boolean_t auto_root, 746 isc_mem_t *mctx) 747{ 748 isc_result_t result = ISC_R_SUCCESS; 749 const cfg_obj_t *view_keys = NULL; 750 const cfg_obj_t *global_keys = NULL; 751 const cfg_obj_t *view_managed_keys = NULL; 752 const cfg_obj_t *global_managed_keys = NULL; 753 const cfg_obj_t *maps[4]; 754 const cfg_obj_t *voptions = NULL; 755 const cfg_obj_t *options = NULL; 756 const cfg_obj_t *obj = NULL; 757 const char *directory; 758 int i = 0; 759 760 /* We don't need trust anchors for the _bind view */ 761 if (strcmp(view->name, "_bind") == 0 && 762 view->rdclass == dns_rdataclass_chaos) { 763 return (ISC_R_SUCCESS); 764 } 765 766 if (vconfig != NULL) { 767 voptions = cfg_tuple_get(vconfig, "options"); 768 if (voptions != NULL) { 769 (void) cfg_map_get(voptions, "trusted-keys", 770 &view_keys); 771 (void) cfg_map_get(voptions, "managed-keys", 772 &view_managed_keys); 773 maps[i++] = voptions; 774 } 775 } 776 777 if (config != NULL) { 778 (void)cfg_map_get(config, "trusted-keys", &global_keys); 779 (void)cfg_map_get(config, "managed-keys", &global_managed_keys); 780 (void)cfg_map_get(config, "options", &options); 781 if (options != NULL) { 782 maps[i++] = options; 783 } 784 } 785 786 maps[i++] = ns_g_defaults; 787 maps[i] = NULL; 788 789 result = dns_view_initsecroots(view, mctx); 790 if (result != ISC_R_SUCCESS) { 791 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 792 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 793 "couldn't create keytable"); 794 return (ISC_R_UNEXPECTED); 795 } 796 797 if (auto_dlv && view->rdclass == dns_rdataclass_in) { 798 const cfg_obj_t *builtin_keys = NULL; 799 const cfg_obj_t *builtin_managed_keys = NULL; 800 801 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, 802 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 803 "using built-in DLV key for view %s", 804 view->name); 805 806 /* 807 * If bind.keys exists, it overrides the managed-keys 808 * clause hard-coded in ns_g_config. 809 */ 810 if (bindkeys != NULL) { 811 (void)cfg_map_get(bindkeys, "trusted-keys", 812 &builtin_keys); 813 (void)cfg_map_get(bindkeys, "managed-keys", 814 &builtin_managed_keys); 815 } else { 816 (void)cfg_map_get(ns_g_config, "trusted-keys", 817 &builtin_keys); 818 (void)cfg_map_get(ns_g_config, "managed-keys", 819 &builtin_managed_keys); 820 } 821 822 if (builtin_keys != NULL) 823 CHECK(load_view_keys(builtin_keys, vconfig, view, 824 ISC_FALSE, view->dlv, mctx)); 825 if (builtin_managed_keys != NULL) 826 CHECK(load_view_keys(builtin_managed_keys, vconfig, 827 view, ISC_TRUE, view->dlv, mctx)); 828 } 829 830 if (auto_root && view->rdclass == dns_rdataclass_in) { 831 const cfg_obj_t *builtin_keys = NULL; 832 const cfg_obj_t *builtin_managed_keys = NULL; 833 834 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, 835 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 836 "using built-in root key for view %s", 837 view->name); 838 839 /* 840 * If bind.keys exists, it overrides the managed-keys 841 * clause hard-coded in ns_g_config. 842 */ 843 if (bindkeys != NULL) { 844 (void)cfg_map_get(bindkeys, "trusted-keys", 845 &builtin_keys); 846 (void)cfg_map_get(bindkeys, "managed-keys", 847 &builtin_managed_keys); 848 } else { 849 (void)cfg_map_get(ns_g_config, "trusted-keys", 850 &builtin_keys); 851 (void)cfg_map_get(ns_g_config, "managed-keys", 852 &builtin_managed_keys); 853 } 854 855 if (builtin_keys != NULL) 856 CHECK(load_view_keys(builtin_keys, vconfig, view, 857 ISC_FALSE, dns_rootname, mctx)); 858 if (builtin_managed_keys != NULL) 859 CHECK(load_view_keys(builtin_managed_keys, vconfig, 860 view, ISC_TRUE, dns_rootname, 861 mctx)); 862 } 863 864 CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE, 865 NULL, mctx)); 866 CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE, 867 NULL, mctx)); 868 869 if (view->rdclass == dns_rdataclass_in) { 870 CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE, 871 NULL, mctx)); 872 CHECK(load_view_keys(global_managed_keys, vconfig, view, 873 ISC_TRUE, NULL, mctx)); 874 } 875 876 /* 877 * Add key zone for managed-keys. 878 */ 879 obj = NULL; 880 (void)ns_config_get(maps, "managed-keys-directory", &obj); 881 directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); 882 if (directory != NULL) 883 result = isc_file_isdirectory(directory); 884 if (result != ISC_R_SUCCESS) { 885 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, 886 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 887 "invalid managed-keys-directory %s: %s", 888 directory, isc_result_totext(result)); 889 goto cleanup; 890 891 } 892 CHECK(add_keydata_zone(view, directory, ns_g_mctx)); 893 894 cleanup: 895 return (result); 896} 897 898static isc_result_t 899mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { 900 const cfg_listelt_t *element; 901 const cfg_obj_t *obj; 902 const char *str; 903 dns_fixedname_t fixed; 904 dns_name_t *name; 905 isc_boolean_t value; 906 isc_result_t result; 907 isc_buffer_t b; 908 909 dns_fixedname_init(&fixed); 910 name = dns_fixedname_name(&fixed); 911 for (element = cfg_list_first(mbs); 912 element != NULL; 913 element = cfg_list_next(element)) 914 { 915 obj = cfg_listelt_value(element); 916 str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 917 isc_buffer_constinit(&b, str, strlen(str)); 918 isc_buffer_add(&b, strlen(str)); 919 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 920 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 921 CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 922 } 923 924 result = ISC_R_SUCCESS; 925 926 cleanup: 927 return (result); 928} 929 930/*% 931 * Get a dispatch appropriate for the resolver of a given view. 932 */ 933static isc_result_t 934get_view_querysource_dispatch(const cfg_obj_t **maps, 935 int af, dns_dispatch_t **dispatchp, 936 isc_boolean_t is_firstview) 937{ 938 isc_result_t result = ISC_R_FAILURE; 939 dns_dispatch_t *disp; 940 isc_sockaddr_t sa; 941 unsigned int attrs, attrmask; 942 const cfg_obj_t *obj = NULL; 943 unsigned int maxdispatchbuffers; 944 945 switch (af) { 946 case AF_INET: 947 result = ns_config_get(maps, "query-source", &obj); 948 INSIST(result == ISC_R_SUCCESS); 949 break; 950 case AF_INET6: 951 result = ns_config_get(maps, "query-source-v6", &obj); 952 INSIST(result == ISC_R_SUCCESS); 953 break; 954 default: 955 INSIST(0); 956 } 957 958 sa = *(cfg_obj_assockaddr(obj)); 959 INSIST(isc_sockaddr_pf(&sa) == af); 960 961 /* 962 * If we don't support this address family, we're done! 963 */ 964 switch (af) { 965 case AF_INET: 966 result = isc_net_probeipv4(); 967 break; 968 case AF_INET6: 969 result = isc_net_probeipv6(); 970 break; 971 default: 972 INSIST(0); 973 } 974 if (result != ISC_R_SUCCESS) 975 return (ISC_R_SUCCESS); 976 977 /* 978 * Try to find a dispatcher that we can share. 979 */ 980 attrs = 0; 981 attrs |= DNS_DISPATCHATTR_UDP; 982 switch (af) { 983 case AF_INET: 984 attrs |= DNS_DISPATCHATTR_IPV4; 985 break; 986 case AF_INET6: 987 attrs |= DNS_DISPATCHATTR_IPV6; 988 break; 989 } 990 if (isc_sockaddr_getport(&sa) == 0) { 991 attrs |= DNS_DISPATCHATTR_EXCLUSIVE; 992 maxdispatchbuffers = 4096; 993 } else { 994 INSIST(obj != NULL); 995 if (is_firstview) { 996 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO, 997 "using specific query-source port " 998 "suppresses port randomization and can be " 999 "insecure."); 1000 } 1001 maxdispatchbuffers = 1000; 1002 } 1003 1004 attrmask = 0; 1005 attrmask |= DNS_DISPATCHATTR_UDP; 1006 attrmask |= DNS_DISPATCHATTR_TCP; 1007 attrmask |= DNS_DISPATCHATTR_IPV4; 1008 attrmask |= DNS_DISPATCHATTR_IPV6; 1009 1010 disp = NULL; 1011 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 1012 ns_g_taskmgr, &sa, 4096, 1013 maxdispatchbuffers, 32768, 16411, 16433, 1014 attrs, attrmask, &disp); 1015 if (result != ISC_R_SUCCESS) { 1016 isc_sockaddr_t any; 1017 char buf[ISC_SOCKADDR_FORMATSIZE]; 1018 1019 switch (af) { 1020 case AF_INET: 1021 isc_sockaddr_any(&any); 1022 break; 1023 case AF_INET6: 1024 isc_sockaddr_any6(&any); 1025 break; 1026 } 1027 if (isc_sockaddr_equal(&sa, &any)) 1028 return (ISC_R_SUCCESS); 1029 isc_sockaddr_format(&sa, buf, sizeof(buf)); 1030 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1031 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 1032 "could not get query source dispatcher (%s)", 1033 buf); 1034 return (result); 1035 } 1036 1037 *dispatchp = disp; 1038 1039 return (ISC_R_SUCCESS); 1040} 1041 1042static isc_result_t 1043configure_order(dns_order_t *order, const cfg_obj_t *ent) { 1044 dns_rdataclass_t rdclass; 1045 dns_rdatatype_t rdtype; 1046 const cfg_obj_t *obj; 1047 dns_fixedname_t fixed; 1048 unsigned int mode = 0; 1049 const char *str; 1050 isc_buffer_t b; 1051 isc_result_t result; 1052 isc_boolean_t addroot; 1053 1054 result = ns_config_getclass(cfg_tuple_get(ent, "class"), 1055 dns_rdataclass_any, &rdclass); 1056 if (result != ISC_R_SUCCESS) 1057 return (result); 1058 1059 result = ns_config_gettype(cfg_tuple_get(ent, "type"), 1060 dns_rdatatype_any, &rdtype); 1061 if (result != ISC_R_SUCCESS) 1062 return (result); 1063 1064 obj = cfg_tuple_get(ent, "name"); 1065 if (cfg_obj_isstring(obj)) 1066 str = cfg_obj_asstring(obj); 1067 else 1068 str = "*"; 1069 addroot = ISC_TF(strcmp(str, "*") == 0); 1070 isc_buffer_constinit(&b, str, strlen(str)); 1071 isc_buffer_add(&b, strlen(str)); 1072 dns_fixedname_init(&fixed); 1073 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, 1074 dns_rootname, 0, NULL); 1075 if (result != ISC_R_SUCCESS) 1076 return (result); 1077 1078 obj = cfg_tuple_get(ent, "ordering"); 1079 INSIST(cfg_obj_isstring(obj)); 1080 str = cfg_obj_asstring(obj); 1081 if (!strcasecmp(str, "fixed")) 1082 mode = DNS_RDATASETATTR_FIXEDORDER; 1083 else if (!strcasecmp(str, "random")) 1084 mode = DNS_RDATASETATTR_RANDOMIZE; 1085 else if (!strcasecmp(str, "cyclic")) 1086 mode = 0; 1087 else 1088 INSIST(0); 1089 1090 /* 1091 * "*" should match everything including the root (BIND 8 compat). 1092 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 1093 * explicit entry for "." when the name is "*". 1094 */ 1095 if (addroot) { 1096 result = dns_order_add(order, dns_rootname, 1097 rdtype, rdclass, mode); 1098 if (result != ISC_R_SUCCESS) 1099 return (result); 1100 } 1101 1102 return (dns_order_add(order, dns_fixedname_name(&fixed), 1103 rdtype, rdclass, mode)); 1104} 1105 1106static isc_result_t 1107configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 1108 isc_netaddr_t na; 1109 dns_peer_t *peer; 1110 const cfg_obj_t *obj; 1111 const char *str; 1112 isc_result_t result; 1113 unsigned int prefixlen; 1114 1115 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); 1116 1117 peer = NULL; 1118 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); 1119 if (result != ISC_R_SUCCESS) 1120 return (result); 1121 1122 obj = NULL; 1123 (void)cfg_map_get(cpeer, "bogus", &obj); 1124 if (obj != NULL) 1125 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 1126 1127 obj = NULL; 1128 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 1129 if (obj != NULL) 1130 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 1131 1132 obj = NULL; 1133 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 1134 if (obj != NULL) 1135 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 1136 1137 obj = NULL; 1138 (void)cfg_map_get(cpeer, "request-nsid", &obj); 1139 if (obj != NULL) 1140 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); 1141 1142 obj = NULL; 1143 (void)cfg_map_get(cpeer, "edns", &obj); 1144 if (obj != NULL) 1145 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 1146 1147 obj = NULL; 1148 (void)cfg_map_get(cpeer, "edns-udp-size", &obj); 1149 if (obj != NULL) { 1150 isc_uint32_t udpsize = cfg_obj_asuint32(obj); 1151 if (udpsize < 512) 1152 udpsize = 512; 1153 if (udpsize > 4096) 1154 udpsize = 4096; 1155 CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize)); 1156 } 1157 1158 obj = NULL; 1159 (void)cfg_map_get(cpeer, "max-udp-size", &obj); 1160 if (obj != NULL) { 1161 isc_uint32_t udpsize = cfg_obj_asuint32(obj); 1162 if (udpsize < 512) 1163 udpsize = 512; 1164 if (udpsize > 4096) 1165 udpsize = 4096; 1166 CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize)); 1167 } 1168 1169 obj = NULL; 1170 (void)cfg_map_get(cpeer, "transfers", &obj); 1171 if (obj != NULL) 1172 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 1173 1174 obj = NULL; 1175 (void)cfg_map_get(cpeer, "transfer-format", &obj); 1176 if (obj != NULL) { 1177 str = cfg_obj_asstring(obj); 1178 if (strcasecmp(str, "many-answers") == 0) 1179 CHECK(dns_peer_settransferformat(peer, 1180 dns_many_answers)); 1181 else if (strcasecmp(str, "one-answer") == 0) 1182 CHECK(dns_peer_settransferformat(peer, 1183 dns_one_answer)); 1184 else 1185 INSIST(0); 1186 } 1187 1188 obj = NULL; 1189 (void)cfg_map_get(cpeer, "keys", &obj); 1190 if (obj != NULL) { 1191 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 1192 if (result != ISC_R_SUCCESS) 1193 goto cleanup; 1194 } 1195 1196 obj = NULL; 1197 if (na.family == AF_INET) 1198 (void)cfg_map_get(cpeer, "transfer-source", &obj); 1199 else 1200 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 1201 if (obj != NULL) { 1202 result = dns_peer_settransfersource(peer, 1203 cfg_obj_assockaddr(obj)); 1204 if (result != ISC_R_SUCCESS) 1205 goto cleanup; 1206 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 1207 } 1208 1209 obj = NULL; 1210 if (na.family == AF_INET) 1211 (void)cfg_map_get(cpeer, "notify-source", &obj); 1212 else 1213 (void)cfg_map_get(cpeer, "notify-source-v6", &obj); 1214 if (obj != NULL) { 1215 result = dns_peer_setnotifysource(peer, 1216 cfg_obj_assockaddr(obj)); 1217 if (result != ISC_R_SUCCESS) 1218 goto cleanup; 1219 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 1220 } 1221 1222 obj = NULL; 1223 if (na.family == AF_INET) 1224 (void)cfg_map_get(cpeer, "query-source", &obj); 1225 else 1226 (void)cfg_map_get(cpeer, "query-source-v6", &obj); 1227 if (obj != NULL) { 1228 result = dns_peer_setquerysource(peer, 1229 cfg_obj_assockaddr(obj)); 1230 if (result != ISC_R_SUCCESS) 1231 goto cleanup; 1232 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 1233 } 1234 1235 *peerp = peer; 1236 return (ISC_R_SUCCESS); 1237 1238 cleanup: 1239 dns_peer_detach(&peer); 1240 return (result); 1241} 1242 1243static isc_result_t 1244disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1245 isc_result_t result; 1246 const cfg_obj_t *algorithms; 1247 const cfg_listelt_t *element; 1248 const char *str; 1249 dns_fixedname_t fixed; 1250 dns_name_t *name; 1251 isc_buffer_t b; 1252 1253 dns_fixedname_init(&fixed); 1254 name = dns_fixedname_name(&fixed); 1255 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1256 isc_buffer_constinit(&b, str, strlen(str)); 1257 isc_buffer_add(&b, strlen(str)); 1258 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1259 1260 algorithms = cfg_tuple_get(disabled, "algorithms"); 1261 for (element = cfg_list_first(algorithms); 1262 element != NULL; 1263 element = cfg_list_next(element)) 1264 { 1265 isc_textregion_t r; 1266 dns_secalg_t alg; 1267 1268 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); 1269 r.length = strlen(r.base); 1270 1271 result = dns_secalg_fromtext(&alg, &r); 1272 if (result != ISC_R_SUCCESS) { 1273 isc_uint8_t ui; 1274 result = isc_parse_uint8(&ui, r.base, 10); 1275 alg = ui; 1276 } 1277 if (result != ISC_R_SUCCESS) { 1278 cfg_obj_log(cfg_listelt_value(element), 1279 ns_g_lctx, ISC_LOG_ERROR, 1280 "invalid algorithm"); 1281 CHECK(result); 1282 } 1283 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 1284 } 1285 cleanup: 1286 return (result); 1287} 1288 1289static isc_boolean_t 1290on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { 1291 const cfg_listelt_t *element; 1292 dns_fixedname_t fixed; 1293 dns_name_t *name; 1294 isc_result_t result; 1295 const cfg_obj_t *value; 1296 const char *str; 1297 isc_buffer_t b; 1298 1299 dns_fixedname_init(&fixed); 1300 name = dns_fixedname_name(&fixed); 1301 1302 for (element = cfg_list_first(disablelist); 1303 element != NULL; 1304 element = cfg_list_next(element)) 1305 { 1306 value = cfg_listelt_value(element); 1307 str = cfg_obj_asstring(value); 1308 isc_buffer_constinit(&b, str, strlen(str)); 1309 isc_buffer_add(&b, strlen(str)); 1310 result = dns_name_fromtext(name, &b, dns_rootname, 1311 0, NULL); 1312 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1313 if (dns_name_equal(name, zonename)) 1314 return (ISC_TRUE); 1315 } 1316 return (ISC_FALSE); 1317} 1318 1319static void 1320check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv, 1321 isc_mem_t *mctx) 1322{ 1323 char **argv = NULL; 1324 unsigned int i; 1325 isc_result_t result; 1326 1327 result = dns_zone_getdbtype(*zonep, &argv, mctx); 1328 if (result != ISC_R_SUCCESS) { 1329 dns_zone_detach(zonep); 1330 return; 1331 } 1332 1333 /* 1334 * Check that all the arguments match. 1335 */ 1336 for (i = 0; i < dbtypec; i++) 1337 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { 1338 dns_zone_detach(zonep); 1339 break; 1340 } 1341 1342 /* 1343 * Check that there are not extra arguments. 1344 */ 1345 if (i == dbtypec && argv[i] != NULL) 1346 dns_zone_detach(zonep); 1347 isc_mem_free(mctx, argv); 1348} 1349 1350static isc_result_t 1351setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { 1352 isc_result_t result; 1353 isc_stats_t *zoneqrystats; 1354 1355 dns_zone_setstatlevel(zone, level); 1356 1357 zoneqrystats = NULL; 1358 if (level == dns_zonestat_full) { 1359 result = isc_stats_create(mctx, &zoneqrystats, 1360 dns_nsstatscounter_max); 1361 if (result != ISC_R_SUCCESS) 1362 return (result); 1363 } 1364 dns_zone_setrequeststats(zone, zoneqrystats); 1365 if (zoneqrystats != NULL) 1366 isc_stats_detach(&zoneqrystats); 1367 1368 return (ISC_R_SUCCESS); 1369} 1370 1371static ns_cache_t * 1372cachelist_find(ns_cachelist_t *cachelist, const char *cachename) { 1373 ns_cache_t *nsc; 1374 1375 for (nsc = ISC_LIST_HEAD(*cachelist); 1376 nsc != NULL; 1377 nsc = ISC_LIST_NEXT(nsc, link)) { 1378 if (strcmp(dns_cache_getname(nsc->cache), cachename) == 0) 1379 return (nsc); 1380 } 1381 1382 return (NULL); 1383} 1384 1385static isc_boolean_t 1386cache_reusable(dns_view_t *originview, dns_view_t *view, 1387 isc_boolean_t new_zero_no_soattl) 1388{ 1389 if (originview->checknames != view->checknames || 1390 dns_resolver_getzeronosoattl(originview->resolver) != 1391 new_zero_no_soattl || 1392 originview->acceptexpired != view->acceptexpired || 1393 originview->enablevalidation != view->enablevalidation || 1394 originview->maxcachettl != view->maxcachettl || 1395 originview->maxncachettl != view->maxncachettl) { 1396 return (ISC_FALSE); 1397 } 1398 1399 return (ISC_TRUE); 1400} 1401 1402static isc_boolean_t 1403cache_sharable(dns_view_t *originview, dns_view_t *view, 1404 isc_boolean_t new_zero_no_soattl, 1405 unsigned int new_cleaning_interval, 1406 isc_uint64_t new_max_cache_size) 1407{ 1408 /* 1409 * If the cache cannot even reused for the same view, it cannot be 1410 * shared with other views. 1411 */ 1412 if (!cache_reusable(originview, view, new_zero_no_soattl)) 1413 return (ISC_FALSE); 1414 1415 /* 1416 * Check other cache related parameters that must be consistent among 1417 * the sharing views. 1418 */ 1419 if (dns_cache_getcleaninginterval(originview->cache) != 1420 new_cleaning_interval || 1421 dns_cache_getcachesize(originview->cache) != new_max_cache_size) { 1422 return (ISC_FALSE); 1423 } 1424 1425 return (ISC_TRUE); 1426} 1427 1428/* 1429 * Callback from DLZ configure when the driver sets up a writeable zone 1430 */ 1431static isc_result_t 1432dlzconfigure_callback(dns_view_t *view, dns_zone_t *zone) { 1433 dns_name_t *origin = dns_zone_getorigin(zone); 1434 dns_rdataclass_t zclass = view->rdclass; 1435 isc_result_t result; 1436 1437 result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone); 1438 if (result != ISC_R_SUCCESS) 1439 return (result); 1440 dns_zone_setstats(zone, ns_g_server->zonestats); 1441 1442 return (ns_zone_configure_writeable_dlz(view->dlzdatabase, 1443 zone, zclass, origin)); 1444} 1445 1446static isc_result_t 1447dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, 1448 unsigned int prefixlen, const char *server, 1449 const char *contact) 1450{ 1451 char *cp; 1452 char reverse[48+sizeof("ip6.arpa.")]; 1453 const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." }; 1454 const char *sep = ": view "; 1455 const char *viewname = view->name; 1456 const unsigned char *s6; 1457 dns_fixedname_t fixed; 1458 dns_name_t *name; 1459 dns_zone_t *zone = NULL; 1460 int dns64_dbtypec = 4; 1461 isc_buffer_t b; 1462 isc_result_t result; 1463 1464 REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || 1465 prefixlen == 56 || prefixlen == 64 || prefixlen == 96); 1466 1467 if (!strcmp(viewname, "_default")) { 1468 sep = ""; 1469 viewname = ""; 1470 } 1471 1472 /* 1473 * Construct the reverse name of the zone. 1474 */ 1475 cp = reverse; 1476 s6 = na->type.in6.s6_addr; 1477 while (prefixlen > 0) { 1478 prefixlen -= 8; 1479 sprintf(cp, "%x.%x.", s6[prefixlen/8] & 0xf, 1480 (s6[prefixlen/8] >> 4) & 0xf); 1481 cp += 4; 1482 } 1483 strcat(cp, "ip6.arpa."); 1484 1485 /* 1486 * Create the actual zone. 1487 */ 1488 if (server != NULL) 1489 dns64_dbtype[2] = server; 1490 if (contact != NULL) 1491 dns64_dbtype[3] = contact; 1492 dns_fixedname_init(&fixed); 1493 name = dns_fixedname_name(&fixed); 1494 isc_buffer_constinit(&b, reverse, strlen(reverse)); 1495 isc_buffer_add(&b, strlen(reverse)); 1496 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1497 CHECK(dns_zone_create(&zone, mctx)); 1498 CHECK(dns_zone_setorigin(zone, name)); 1499 dns_zone_setview(zone, view); 1500 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 1501 dns_zone_setclass(zone, view->rdclass); 1502 dns_zone_settype(zone, dns_zone_master); 1503 dns_zone_setstats(zone, ns_g_server->zonestats); 1504 CHECK(dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype)); 1505 if (view->queryacl != NULL) 1506 dns_zone_setqueryacl(zone, view->queryacl); 1507 if (view->queryonacl != NULL) 1508 dns_zone_setqueryonacl(zone, view->queryonacl); 1509 dns_zone_setdialup(zone, dns_dialuptype_no); 1510 dns_zone_setnotifytype(zone, dns_notifytype_no); 1511 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); 1512 CHECK(setquerystats(zone, mctx, dns_zonestat_none)); /* XXXMPA */ 1513 CHECK(dns_view_addzone(view, zone)); 1514 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 1515 ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep, 1516 viewname, reverse); 1517 1518cleanup: 1519 if (zone != NULL) 1520 dns_zone_detach(&zone); 1521 return (result); 1522} 1523 1524static isc_result_t 1525configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 1526 const char *str, const char *msg) 1527{ 1528 isc_result_t result; 1529 1530 result = dns_name_fromstring(name, str, DNS_NAME_DOWNCASE, view->mctx); 1531 if (result != ISC_R_SUCCESS) 1532 cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, 1533 "invalid %s '%s'", msg, str); 1534 return (result); 1535} 1536 1537static isc_result_t 1538configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 1539 const char *str, const dns_name_t *origin) 1540{ 1541 isc_result_t result; 1542 1543 result = dns_name_fromstring2(name, str, origin, DNS_NAME_DOWNCASE, 1544 view->mctx); 1545 if (result != ISC_R_SUCCESS) 1546 cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, 1547 "invalid zone '%s'", str); 1548 return (result); 1549} 1550 1551static isc_result_t 1552configure_rpz(dns_view_t *view, const cfg_listelt_t *element, 1553 isc_boolean_t recursive_only_def, dns_ttl_t ttl_def) 1554{ 1555 const cfg_obj_t *rpz_obj, *obj; 1556 const char *str; 1557 dns_rpz_zone_t *old, *new; 1558 isc_result_t result; 1559 1560 rpz_obj = cfg_listelt_value(element); 1561 1562 new = isc_mem_get(view->mctx, sizeof(*new)); 1563 if (new == NULL) { 1564 cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, 1565 "no memory for response policy zones"); 1566 return (ISC_R_NOMEMORY); 1567 } 1568 1569 memset(new, 0, sizeof(*new)); 1570 dns_name_init(&new->origin, NULL); 1571 dns_name_init(&new->nsdname, NULL); 1572 dns_name_init(&new->passthru, NULL); 1573 dns_name_init(&new->cname, NULL); 1574 ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link); 1575 1576 obj = cfg_tuple_get(rpz_obj, "recursive-only"); 1577 if (cfg_obj_isvoid(obj)) { 1578 new->recursive_only = recursive_only_def; 1579 } else { 1580 new->recursive_only = cfg_obj_asboolean(obj); 1581 } 1582 if (!new->recursive_only) 1583 view->rpz_recursive_only = ISC_FALSE; 1584 1585 obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 1586 if (cfg_obj_isuint32(obj)) { 1587 new->max_policy_ttl = cfg_obj_asuint32(obj); 1588 } else { 1589 new->max_policy_ttl = ttl_def; 1590 } 1591 1592 str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); 1593 result = configure_rpz_name(view, rpz_obj, &new->origin, str, "zone"); 1594 if (result != ISC_R_SUCCESS) 1595 return (result); 1596 if (dns_name_equal(&new->origin, dns_rootname)) { 1597 cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, 1598 "invalid zone name '%s'", str); 1599 return (DNS_R_EMPTYLABEL); 1600 } 1601 for (old = ISC_LIST_HEAD(view->rpz_zones); 1602 old != new; 1603 old = ISC_LIST_NEXT(old, link)) { 1604 ++new->num; 1605 if (dns_name_equal(&old->origin, &new->origin)) { 1606 cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, 1607 "duplicate '%s'", str); 1608 result = DNS_R_DUPLICATE; 1609 return (result); 1610 } 1611 } 1612 1613 result = configure_rpz_name2(view, rpz_obj, &new->nsdname, 1614 DNS_RPZ_NSDNAME_ZONE, &new->origin); 1615 if (result != ISC_R_SUCCESS) 1616 return (result); 1617 1618 result = configure_rpz_name(view, rpz_obj, &new->passthru, 1619 DNS_RPZ_PASSTHRU_ZONE, "zone"); 1620 if (result != ISC_R_SUCCESS) 1621 return (result); 1622 1623 obj = cfg_tuple_get(rpz_obj, "policy"); 1624 if (cfg_obj_isvoid(obj)) { 1625 new->policy = DNS_RPZ_POLICY_GIVEN; 1626 } else { 1627 str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 1628 new->policy = dns_rpz_str2policy(str); 1629 INSIST(new->policy != DNS_RPZ_POLICY_ERROR); 1630 if (new->policy == DNS_RPZ_POLICY_CNAME) { 1631 str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); 1632 result = configure_rpz_name(view, rpz_obj, &new->cname, 1633 str, "cname"); 1634 if (result != ISC_R_SUCCESS) 1635 return (result); 1636 } 1637 } 1638 1639 return (ISC_R_SUCCESS); 1640} 1641 1642/* 1643 * Configure 'view' according to 'vconfig', taking defaults from 'config' 1644 * where values are missing in 'vconfig'. 1645 * 1646 * When configuring the default view, 'vconfig' will be NULL and the 1647 * global defaults in 'config' used exclusively. 1648 */ 1649static isc_result_t 1650configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 1651 ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys, 1652 isc_mem_t *mctx, cfg_aclconfctx_t *actx, 1653 isc_boolean_t need_hints) 1654{ 1655 const cfg_obj_t *maps[4]; 1656 const cfg_obj_t *cfgmaps[3]; 1657 const cfg_obj_t *optionmaps[3]; 1658 const cfg_obj_t *options = NULL; 1659 const cfg_obj_t *voptions = NULL; 1660 const cfg_obj_t *forwardtype; 1661 const cfg_obj_t *forwarders; 1662 const cfg_obj_t *alternates; 1663 const cfg_obj_t *zonelist; 1664 const cfg_obj_t *dlz; 1665 unsigned int dlzargc; 1666 char **dlzargv; 1667 const cfg_obj_t *disabled; 1668 const cfg_obj_t *obj; 1669 const cfg_listelt_t *element; 1670 in_port_t port; 1671 dns_cache_t *cache = NULL; 1672 isc_result_t result; 1673 unsigned int cleaning_interval; 1674 size_t max_cache_size; 1675 size_t max_acache_size; 1676 size_t max_adb_size; 1677 isc_uint32_t lame_ttl; 1678 dns_tsig_keyring_t *ring = NULL; 1679 dns_view_t *pview = NULL; /* Production view */ 1680 isc_mem_t *cmctx = NULL, *hmctx = NULL; 1681 dns_dispatch_t *dispatch4 = NULL; 1682 dns_dispatch_t *dispatch6 = NULL; 1683 isc_boolean_t reused_cache = ISC_FALSE; 1684 isc_boolean_t shared_cache = ISC_FALSE; 1685 int i = 0, j = 0, k = 0; 1686 const char *str; 1687 const char *cachename = NULL; 1688 dns_order_t *order = NULL; 1689 isc_uint32_t udpsize; 1690 isc_uint32_t maxbits; 1691 unsigned int resopts = 0; 1692 dns_zone_t *zone = NULL; 1693 isc_uint32_t max_clients_per_query; 1694 const char *sep = ": view "; 1695 const char *viewname = view->name; 1696 const char *forview = " for view "; 1697 isc_boolean_t empty_zones_enable; 1698 const cfg_obj_t *disablelist = NULL; 1699 isc_stats_t *resstats = NULL; 1700 dns_stats_t *resquerystats = NULL; 1701 isc_boolean_t auto_dlv = ISC_FALSE; 1702 isc_boolean_t auto_root = ISC_FALSE; 1703 ns_cache_t *nsc; 1704 isc_boolean_t zero_no_soattl; 1705 dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; 1706 unsigned int query_timeout, ndisp; 1707 struct cfg_context *nzctx; 1708 dns_rpz_zone_t *rpz; 1709 1710 REQUIRE(DNS_VIEW_VALID(view)); 1711 1712 if (config != NULL) 1713 (void)cfg_map_get(config, "options", &options); 1714 1715 /* 1716 * maps: view options, options, defaults 1717 * cfgmaps: view options, config 1718 * optionmaps: view options, options 1719 */ 1720 if (vconfig != NULL) { 1721 voptions = cfg_tuple_get(vconfig, "options"); 1722 maps[i++] = voptions; 1723 optionmaps[j++] = voptions; 1724 cfgmaps[k++] = voptions; 1725 } 1726 if (options != NULL) { 1727 maps[i++] = options; 1728 optionmaps[j++] = options; 1729 } 1730 1731 maps[i++] = ns_g_defaults; 1732 maps[i] = NULL; 1733 optionmaps[j] = NULL; 1734 if (config != NULL) 1735 cfgmaps[k++] = config; 1736 cfgmaps[k] = NULL; 1737 1738 if (!strcmp(viewname, "_default")) { 1739 sep = ""; 1740 viewname = ""; 1741 forview = ""; 1742 POST(forview); 1743 } 1744 1745 /* 1746 * Set the view's port number for outgoing queries. 1747 */ 1748 CHECKM(ns_config_getport(config, &port), "port"); 1749 dns_view_setdstport(view, port); 1750 1751 /* 1752 * Create additional cache for this view and zones under the view 1753 * if explicitly enabled. 1754 * XXX950 default to on. 1755 */ 1756 obj = NULL; 1757 (void)ns_config_get(maps, "acache-enable", &obj); 1758 if (obj != NULL && cfg_obj_asboolean(obj)) { 1759 cmctx = NULL; 1760 CHECK(isc_mem_create(0, 0, &cmctx)); 1761 CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr, 1762 ns_g_timermgr)); 1763 isc_mem_setname(cmctx, "acache", NULL); 1764 isc_mem_detach(&cmctx); 1765 } 1766 if (view->acache != NULL) { 1767 obj = NULL; 1768 result = ns_config_get(maps, "acache-cleaning-interval", &obj); 1769 INSIST(result == ISC_R_SUCCESS); 1770 dns_acache_setcleaninginterval(view->acache, 1771 cfg_obj_asuint32(obj) * 60); 1772 1773 obj = NULL; 1774 result = ns_config_get(maps, "max-acache-size", &obj); 1775 INSIST(result == ISC_R_SUCCESS); 1776 if (cfg_obj_isstring(obj)) { 1777 str = cfg_obj_asstring(obj); 1778 INSIST(strcasecmp(str, "unlimited") == 0); 1779 max_acache_size = ISC_UINT32_MAX; 1780 } else { 1781 isc_resourcevalue_t value; 1782 value = cfg_obj_asuint64(obj); 1783 if (value > SIZE_MAX) { 1784 cfg_obj_log(obj, ns_g_lctx, 1785 ISC_LOG_WARNING, 1786 "'max-acache-size " 1787 "%" ISC_PRINT_QUADFORMAT "u' " 1788 "is too large for this " 1789 "system; reducing to %lu", 1790 value, (unsigned long)SIZE_MAX); 1791 value = SIZE_MAX; 1792 } 1793 max_acache_size = (size_t) value; 1794 } 1795 dns_acache_setcachesize(view->acache, max_acache_size); 1796 } 1797 1798 CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx, 1799 ns_g_mctx, &view->queryacl)); 1800 if (view->queryacl == NULL) { 1801 CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", 1802 NULL, actx, ns_g_mctx, 1803 &view->queryacl)); 1804 } 1805 1806 /* 1807 * Make the list of response policy zone names for a view that 1808 * is used for real lookups and so cares about hints. 1809 */ 1810 obj = NULL; 1811 if (view->rdclass == dns_rdataclass_in && need_hints && 1812 ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) { 1813 const cfg_obj_t *rpz_obj; 1814 isc_boolean_t recursive_only_def; 1815 dns_ttl_t ttl_def; 1816 1817 rpz_obj = cfg_tuple_get(obj, "recursive-only"); 1818 if (!cfg_obj_isvoid(rpz_obj) && 1819 !cfg_obj_asboolean(rpz_obj)) 1820 recursive_only_def = ISC_FALSE; 1821 else 1822 recursive_only_def = ISC_TRUE; 1823 1824 rpz_obj = cfg_tuple_get(obj, "break-dnssec"); 1825 if (!cfg_obj_isvoid(rpz_obj) && 1826 cfg_obj_asboolean(rpz_obj)) 1827 view->rpz_break_dnssec = ISC_TRUE; 1828 else 1829 view->rpz_break_dnssec = ISC_FALSE; 1830 1831 rpz_obj = cfg_tuple_get(obj, "max-policy-ttl"); 1832 if (cfg_obj_isuint32(rpz_obj)) 1833 ttl_def = cfg_obj_asuint32(rpz_obj); 1834 else 1835 ttl_def = DNS_RPZ_MAX_TTL_DEFAULT; 1836 1837 rpz_obj = cfg_tuple_get(obj, "min-ns-dots"); 1838 if (cfg_obj_isuint32(rpz_obj)) 1839 view->rpz_min_ns_labels = cfg_obj_asuint32(rpz_obj) + 1; 1840 else 1841 view->rpz_min_ns_labels = 2; 1842 1843 element = cfg_list_first(cfg_tuple_get(obj, "zone list")); 1844 while (element != NULL) { 1845 result = configure_rpz(view, element, 1846 recursive_only_def, ttl_def); 1847 if (result != ISC_R_SUCCESS) 1848 goto cleanup; 1849 element = cfg_list_next(element); 1850 } 1851 } 1852 1853 /* 1854 * Configure the zones. 1855 */ 1856 zonelist = NULL; 1857 if (voptions != NULL) 1858 (void)cfg_map_get(voptions, "zone", &zonelist); 1859 else 1860 (void)cfg_map_get(config, "zone", &zonelist); 1861 1862 /* 1863 * Load zone configuration 1864 */ 1865 for (element = cfg_list_first(zonelist); 1866 element != NULL; 1867 element = cfg_list_next(element)) 1868 { 1869 const cfg_obj_t *zconfig = cfg_listelt_value(element); 1870 CHECK(configure_zone(config, zconfig, vconfig, mctx, view, 1871 actx, ISC_FALSE)); 1872 } 1873 1874 for (rpz = ISC_LIST_HEAD(view->rpz_zones); 1875 rpz != NULL; 1876 rpz = ISC_LIST_NEXT(rpz, link)) 1877 { 1878 if (!rpz->defined) { 1879 char namebuf[DNS_NAME_FORMATSIZE]; 1880 1881 dns_name_format(&rpz->origin, namebuf, sizeof(namebuf)); 1882 cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, 1883 "'%s' is not a master or slave zone", 1884 namebuf); 1885 result = ISC_R_NOTFOUND; 1886 goto cleanup; 1887 } 1888 } 1889 1890 /* 1891 * If we're allowing added zones, then load zone configuration 1892 * from the newzone file for zones that were added during previous 1893 * runs. 1894 */ 1895 nzctx = view->new_zone_config; 1896 if (nzctx != NULL && nzctx->nzconfig != NULL) { 1897 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1898 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 1899 "loading additional zones for view '%s'", 1900 view->name); 1901 1902 zonelist = NULL; 1903 cfg_map_get(nzctx->nzconfig, "zone", &zonelist); 1904 1905 for (element = cfg_list_first(zonelist); 1906 element != NULL; 1907 element = cfg_list_next(element)) 1908 { 1909 const cfg_obj_t *zconfig = cfg_listelt_value(element); 1910 CHECK(configure_zone(config, zconfig, vconfig, 1911 mctx, view, actx, 1912 ISC_TRUE)); 1913 } 1914 } 1915 1916 /* 1917 * Create Dynamically Loadable Zone driver. 1918 */ 1919 dlz = NULL; 1920 if (voptions != NULL) 1921 (void)cfg_map_get(voptions, "dlz", &dlz); 1922 else 1923 (void)cfg_map_get(config, "dlz", &dlz); 1924 1925 obj = NULL; 1926 if (dlz != NULL) { 1927 (void)cfg_map_get(cfg_tuple_get(dlz, "options"), 1928 "database", &obj); 1929 if (obj != NULL) { 1930 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 1931 if (s == NULL) { 1932 result = ISC_R_NOMEMORY; 1933 goto cleanup; 1934 } 1935 1936 result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv); 1937 if (result != ISC_R_SUCCESS) { 1938 isc_mem_free(mctx, s); 1939 goto cleanup; 1940 } 1941 1942 obj = cfg_tuple_get(dlz, "name"); 1943 result = dns_dlzcreate(mctx, cfg_obj_asstring(obj), 1944 dlzargv[0], dlzargc, dlzargv, 1945 &view->dlzdatabase); 1946 isc_mem_free(mctx, s); 1947 isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); 1948 if (result != ISC_R_SUCCESS) 1949 goto cleanup; 1950 1951 /* 1952 * If the dlz backend supports configuration, 1953 * then call its configure method now. 1954 */ 1955 result = dns_dlzconfigure(view, dlzconfigure_callback); 1956 if (result != ISC_R_SUCCESS) 1957 goto cleanup; 1958 } 1959 } 1960 1961 /* 1962 * Obtain configuration parameters that affect the decision of whether 1963 * we can reuse/share an existing cache. 1964 */ 1965 obj = NULL; 1966 result = ns_config_get(maps, "cleaning-interval", &obj); 1967 INSIST(result == ISC_R_SUCCESS); 1968 cleaning_interval = cfg_obj_asuint32(obj) * 60; 1969 1970 obj = NULL; 1971 result = ns_config_get(maps, "max-cache-size", &obj); 1972 INSIST(result == ISC_R_SUCCESS); 1973 if (cfg_obj_isstring(obj)) { 1974 str = cfg_obj_asstring(obj); 1975 INSIST(strcasecmp(str, "unlimited") == 0); 1976 max_cache_size = ISC_UINT32_MAX; 1977 } else { 1978 isc_resourcevalue_t value; 1979 value = cfg_obj_asuint64(obj); 1980 if (value > SIZE_MAX) { 1981 cfg_obj_log(obj, ns_g_lctx, 1982 ISC_LOG_WARNING, 1983 "'max-cache-size " 1984 "%" ISC_PRINT_QUADFORMAT "u' " 1985 "is too large for this " 1986 "system; reducing to %lu", 1987 value, (unsigned long)SIZE_MAX); 1988 value = SIZE_MAX; 1989 } 1990 max_cache_size = (size_t) value; 1991 } 1992 1993 /* Check-names. */ 1994 obj = NULL; 1995 result = ns_checknames_get(maps, "response", &obj); 1996 INSIST(result == ISC_R_SUCCESS); 1997 1998 str = cfg_obj_asstring(obj); 1999 if (strcasecmp(str, "fail") == 0) { 2000 resopts |= DNS_RESOLVER_CHECKNAMES | 2001 DNS_RESOLVER_CHECKNAMESFAIL; 2002 view->checknames = ISC_TRUE; 2003 } else if (strcasecmp(str, "warn") == 0) { 2004 resopts |= DNS_RESOLVER_CHECKNAMES; 2005 view->checknames = ISC_FALSE; 2006 } else if (strcasecmp(str, "ignore") == 0) { 2007 view->checknames = ISC_FALSE; 2008 } else 2009 INSIST(0); 2010 2011 obj = NULL; 2012 result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj); 2013 INSIST(result == ISC_R_SUCCESS); 2014 zero_no_soattl = cfg_obj_asboolean(obj); 2015 2016 obj = NULL; 2017 result = ns_config_get(maps, "dns64", &obj); 2018 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && 2019 strcmp(view->name, "_meta")) { 2020 const cfg_listelt_t *element; 2021 isc_netaddr_t na, suffix, *sp; 2022 unsigned int prefixlen; 2023 const char *server, *contact; 2024 const cfg_obj_t *myobj; 2025 2026 myobj = NULL; 2027 result = ns_config_get(maps, "dns64-server", &myobj); 2028 if (result == ISC_R_SUCCESS) 2029 server = cfg_obj_asstring(myobj); 2030 else 2031 server = NULL; 2032 2033 myobj = NULL; 2034 result = ns_config_get(maps, "dns64-contact", &myobj); 2035 if (result == ISC_R_SUCCESS) 2036 contact = cfg_obj_asstring(myobj); 2037 else 2038 contact = NULL; 2039 2040 for (element = cfg_list_first(obj); 2041 element != NULL; 2042 element = cfg_list_next(element)) 2043 { 2044 const cfg_obj_t *map = cfg_listelt_value(element); 2045 dns_dns64_t *dns64 = NULL; 2046 unsigned int dns64options = 0; 2047 2048 cfg_obj_asnetprefix(cfg_map_getname(map), &na, 2049 &prefixlen); 2050 2051 obj = NULL; 2052 (void)cfg_map_get(map, "suffix", &obj); 2053 if (obj != NULL) { 2054 sp = &suffix; 2055 isc_netaddr_fromsockaddr(sp, 2056 cfg_obj_assockaddr(obj)); 2057 } else 2058 sp = NULL; 2059 2060 clients = mapped = excluded = NULL; 2061 obj = NULL; 2062 (void)cfg_map_get(map, "clients", &obj); 2063 if (obj != NULL) { 2064 result = cfg_acl_fromconfig(obj, config, 2065 ns_g_lctx, actx, 2066 mctx, 0, &clients); 2067 if (result != ISC_R_SUCCESS) 2068 goto cleanup; 2069 } 2070 obj = NULL; 2071 (void)cfg_map_get(map, "mapped", &obj); 2072 if (obj != NULL) { 2073 result = cfg_acl_fromconfig(obj, config, 2074 ns_g_lctx, actx, 2075 mctx, 0, &mapped); 2076 if (result != ISC_R_SUCCESS) 2077 goto cleanup; 2078 } 2079 obj = NULL; 2080 (void)cfg_map_get(map, "exclude", &obj); 2081 if (obj != NULL) { 2082 result = cfg_acl_fromconfig(obj, config, 2083 ns_g_lctx, actx, 2084 mctx, 0, &excluded); 2085 if (result != ISC_R_SUCCESS) 2086 goto cleanup; 2087 } 2088 2089 obj = NULL; 2090 (void)cfg_map_get(map, "recursive-only", &obj); 2091 if (obj != NULL && cfg_obj_asboolean(obj)) 2092 dns64options |= DNS_DNS64_RECURSIVE_ONLY; 2093 2094 obj = NULL; 2095 (void)cfg_map_get(map, "break-dnssec", &obj); 2096 if (obj != NULL && cfg_obj_asboolean(obj)) 2097 dns64options |= DNS_DNS64_BREAK_DNSSEC; 2098 2099 result = dns_dns64_create(mctx, &na, prefixlen, sp, 2100 clients, mapped, excluded, 2101 dns64options, &dns64); 2102 if (result != ISC_R_SUCCESS) 2103 goto cleanup; 2104 dns_dns64_append(&view->dns64, dns64); 2105 view->dns64cnt++; 2106 result = dns64_reverse(view, mctx, &na, prefixlen, 2107 server, contact); 2108 if (result != ISC_R_SUCCESS) 2109 goto cleanup; 2110 if (clients != NULL) 2111 dns_acl_detach(&clients); 2112 if (mapped != NULL) 2113 dns_acl_detach(&mapped); 2114 if (excluded != NULL) 2115 dns_acl_detach(&excluded); 2116 } 2117 } 2118 2119 obj = NULL; 2120 result = ns_config_get(maps, "dnssec-accept-expired", &obj); 2121 INSIST(result == ISC_R_SUCCESS); 2122 view->acceptexpired = cfg_obj_asboolean(obj); 2123 2124 obj = NULL; 2125 result = ns_config_get(maps, "dnssec-validation", &obj); 2126 INSIST(result == ISC_R_SUCCESS); 2127 if (cfg_obj_isboolean(obj)) { 2128 view->enablevalidation = cfg_obj_asboolean(obj); 2129 } else { 2130 /* If dnssec-validation is not boolean, it must be "auto" */ 2131 view->enablevalidation = ISC_TRUE; 2132 auto_root = ISC_TRUE; 2133 } 2134 2135 obj = NULL; 2136 result = ns_config_get(maps, "max-cache-ttl", &obj); 2137 INSIST(result == ISC_R_SUCCESS); 2138 view->maxcachettl = cfg_obj_asuint32(obj); 2139 2140 obj = NULL; 2141 result = ns_config_get(maps, "max-ncache-ttl", &obj); 2142 INSIST(result == ISC_R_SUCCESS); 2143 view->maxncachettl = cfg_obj_asuint32(obj); 2144 if (view->maxncachettl > 7 * 24 * 3600) 2145 view->maxncachettl = 7 * 24 * 3600; 2146 2147 /* 2148 * Configure the view's cache. 2149 * 2150 * First, check to see if there are any attach-cache options. If yes, 2151 * attempt to lookup an existing cache at attach it to the view. If 2152 * there is not one, then try to reuse an existing cache if possible; 2153 * otherwise create a new cache. 2154 * 2155 * Note that the ADB is not preserved or shared in either case. 2156 * 2157 * When a matching view is found, the associated statistics are also 2158 * retrieved and reused. 2159 * 2160 * XXX Determining when it is safe to reuse or share a cache is tricky. 2161 * When the view's configuration changes, the cached data may become 2162 * invalid because it reflects our old view of the world. We check 2163 * some of the configuration parameters that could invalidate the cache 2164 * or otherwise make it unsharable, but there are other configuration 2165 * options that should be checked. For example, if a view uses a 2166 * forwarder, changes in the forwarder configuration may invalidate 2167 * the cache. At the moment, it's the administrator's responsibility to 2168 * ensure these configuration options don't invalidate reusing/sharing. 2169 */ 2170 obj = NULL; 2171 result = ns_config_get(maps, "attach-cache", &obj); 2172 if (result == ISC_R_SUCCESS) 2173 cachename = cfg_obj_asstring(obj); 2174 else 2175 cachename = view->name; 2176 cache = NULL; 2177 nsc = cachelist_find(cachelist, cachename); 2178 if (nsc != NULL) { 2179 if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, 2180 cleaning_interval, max_cache_size)) { 2181 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2182 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 2183 "views %s and %s can't share the cache " 2184 "due to configuration parameter mismatch", 2185 nsc->primaryview->name, view->name); 2186 result = ISC_R_FAILURE; 2187 goto cleanup; 2188 } 2189 dns_cache_attach(nsc->cache, &cache); 2190 shared_cache = ISC_TRUE; 2191 } else { 2192 if (strcmp(cachename, view->name) == 0) { 2193 result = dns_viewlist_find(&ns_g_server->viewlist, 2194 cachename, view->rdclass, 2195 &pview); 2196 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 2197 goto cleanup; 2198 if (pview != NULL) { 2199 if (!cache_reusable(pview, view, 2200 zero_no_soattl)) { 2201 isc_log_write(ns_g_lctx, 2202 NS_LOGCATEGORY_GENERAL, 2203 NS_LOGMODULE_SERVER, 2204 ISC_LOG_DEBUG(1), 2205 "cache cannot be reused " 2206 "for view %s due to " 2207 "configuration parameter " 2208 "mismatch", view->name); 2209 } else { 2210 INSIST(pview->cache != NULL); 2211 isc_log_write(ns_g_lctx, 2212 NS_LOGCATEGORY_GENERAL, 2213 NS_LOGMODULE_SERVER, 2214 ISC_LOG_DEBUG(3), 2215 "reusing existing cache"); 2216 reused_cache = ISC_TRUE; 2217 dns_cache_attach(pview->cache, &cache); 2218 } 2219 dns_view_getresstats(pview, &resstats); 2220 dns_view_getresquerystats(pview, 2221 &resquerystats); 2222 dns_view_detach(&pview); 2223 } 2224 } 2225 if (cache == NULL) { 2226 /* 2227 * Create a cache with the desired name. This normally 2228 * equals the view name, but may also be a forward 2229 * reference to a view that share the cache with this 2230 * view but is not yet configured. If it is not the 2231 * view name but not a forward reference either, then it 2232 * is simply a named cache that is not shared. 2233 * 2234 * We use two separate memory contexts for the 2235 * cache, for the main cache memory and the heap 2236 * memory. 2237 */ 2238 CHECK(isc_mem_create(0, 0, &cmctx)); 2239 isc_mem_setname(cmctx, "cache", NULL); 2240 CHECK(isc_mem_create(0, 0, &hmctx)); 2241 isc_mem_setname(hmctx, "cache_heap", NULL); 2242 CHECK(dns_cache_create3(cmctx, hmctx, ns_g_taskmgr, 2243 ns_g_timermgr, view->rdclass, 2244 cachename, "rbt", 0, NULL, 2245 &cache)); 2246 isc_mem_detach(&cmctx); 2247 isc_mem_detach(&hmctx); 2248 } 2249 nsc = isc_mem_get(mctx, sizeof(*nsc)); 2250 if (nsc == NULL) { 2251 result = ISC_R_NOMEMORY; 2252 goto cleanup; 2253 } 2254 nsc->cache = NULL; 2255 dns_cache_attach(cache, &nsc->cache); 2256 nsc->primaryview = view; 2257 nsc->needflush = ISC_FALSE; 2258 nsc->adbsizeadjusted = ISC_FALSE; 2259 ISC_LINK_INIT(nsc, link); 2260 ISC_LIST_APPEND(*cachelist, nsc, link); 2261 } 2262 dns_view_setcache2(view, cache, shared_cache); 2263 2264 /* 2265 * cache-file cannot be inherited if views are present, but this 2266 * should be caught by the configuration checking stage. 2267 */ 2268 obj = NULL; 2269 result = ns_config_get(maps, "cache-file", &obj); 2270 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { 2271 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj))); 2272 if (!reused_cache && !shared_cache) 2273 CHECK(dns_cache_load(cache)); 2274 } 2275 2276 dns_cache_setcleaninginterval(cache, cleaning_interval); 2277 dns_cache_setcachesize(cache, max_cache_size); 2278 2279 dns_cache_detach(&cache); 2280 2281 /* 2282 * Resolver. 2283 * 2284 * XXXRTH Hardwired number of tasks. 2285 */ 2286 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, 2287 ISC_TF(ISC_LIST_PREV(view, link) 2288 == NULL))); 2289 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, 2290 ISC_TF(ISC_LIST_PREV(view, link) 2291 == NULL))); 2292 if (dispatch4 == NULL && dispatch6 == NULL) { 2293 UNEXPECTED_ERROR(__FILE__, __LINE__, 2294 "unable to obtain neither an IPv4 nor" 2295 " an IPv6 dispatch"); 2296 result = ISC_R_UNEXPECTED; 2297 goto cleanup; 2298 } 2299 2300 ndisp = 4 * ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH); 2301 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, ndisp, 2302 ns_g_socketmgr, ns_g_timermgr, 2303 resopts, ns_g_dispatchmgr, 2304 dispatch4, dispatch6)); 2305 2306 if (resstats == NULL) { 2307 CHECK(isc_stats_create(mctx, &resstats, 2308 dns_resstatscounter_max)); 2309 } 2310 dns_view_setresstats(view, resstats); 2311 if (resquerystats == NULL) 2312 CHECK(dns_rdatatypestats_create(mctx, &resquerystats)); 2313 dns_view_setresquerystats(view, resquerystats); 2314 2315 /* 2316 * Set the ADB cache size to 1/8th of the max-cache-size or 2317 * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. 2318 */ 2319 max_adb_size = 0; 2320 if (max_cache_size != 0U) { 2321 max_adb_size = max_cache_size / 8; 2322 if (max_adb_size == 0U) 2323 max_adb_size = 1; /* Force minimum. */ 2324 if (view != nsc->primaryview && 2325 max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) { 2326 max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; 2327 if (!nsc->adbsizeadjusted) { 2328 dns_adb_setadbsize(nsc->primaryview->adb, 2329 MAX_ADB_SIZE_FOR_CACHESHARE); 2330 nsc->adbsizeadjusted = ISC_TRUE; 2331 } 2332 } 2333 } 2334 dns_adb_setadbsize(view->adb, max_adb_size); 2335 2336 /* 2337 * Set resolver's lame-ttl. 2338 */ 2339 obj = NULL; 2340 result = ns_config_get(maps, "lame-ttl", &obj); 2341 INSIST(result == ISC_R_SUCCESS); 2342 lame_ttl = cfg_obj_asuint32(obj); 2343 if (lame_ttl > 1800) 2344 lame_ttl = 1800; 2345 dns_resolver_setlamettl(view->resolver, lame_ttl); 2346 2347 /* 2348 * Set the resolver's query timeout. 2349 */ 2350 obj = NULL; 2351 result = ns_config_get(maps, "resolver-query-timeout", &obj); 2352 INSIST(result == ISC_R_SUCCESS); 2353 query_timeout = cfg_obj_asuint32(obj); 2354 dns_resolver_settimeout(view->resolver, query_timeout); 2355 2356 /* Specify whether to use 0-TTL for negative response for SOA query */ 2357 dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); 2358 2359 /* 2360 * Set the resolver's EDNS UDP size. 2361 */ 2362 obj = NULL; 2363 result = ns_config_get(maps, "edns-udp-size", &obj); 2364 INSIST(result == ISC_R_SUCCESS); 2365 udpsize = cfg_obj_asuint32(obj); 2366 if (udpsize < 512) 2367 udpsize = 512; 2368 if (udpsize > 4096) 2369 udpsize = 4096; 2370 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize); 2371 2372 /* 2373 * Set the maximum UDP response size. 2374 */ 2375 obj = NULL; 2376 result = ns_config_get(maps, "max-udp-size", &obj); 2377 INSIST(result == ISC_R_SUCCESS); 2378 udpsize = cfg_obj_asuint32(obj); 2379 if (udpsize < 512) 2380 udpsize = 512; 2381 if (udpsize > 4096) 2382 udpsize = 4096; 2383 view->maxudp = udpsize; 2384 2385 /* 2386 * Set the maximum rsa exponent bits. 2387 */ 2388 obj = NULL; 2389 result = ns_config_get(maps, "max-rsa-exponent-size", &obj); 2390 INSIST(result == ISC_R_SUCCESS); 2391 maxbits = cfg_obj_asuint32(obj); 2392 if (maxbits != 0 && maxbits < 35) 2393 maxbits = 35; 2394 if (maxbits > 4096) 2395 maxbits = 4096; 2396 view->maxbits = maxbits; 2397 2398 /* 2399 * Set supported DNSSEC algorithms. 2400 */ 2401 dns_resolver_reset_algorithms(view->resolver); 2402 disabled = NULL; 2403 (void)ns_config_get(maps, "disable-algorithms", &disabled); 2404 if (disabled != NULL) { 2405 for (element = cfg_list_first(disabled); 2406 element != NULL; 2407 element = cfg_list_next(element)) 2408 CHECK(disable_algorithms(cfg_listelt_value(element), 2409 view->resolver)); 2410 } 2411 2412 /* 2413 * A global or view "forwarders" option, if present, 2414 * creates an entry for "." in the forwarding table. 2415 */ 2416 forwardtype = NULL; 2417 forwarders = NULL; 2418 (void)ns_config_get(maps, "forward", &forwardtype); 2419 (void)ns_config_get(maps, "forwarders", &forwarders); 2420 if (forwarders != NULL) 2421 CHECK(configure_forward(config, view, dns_rootname, 2422 forwarders, forwardtype)); 2423 2424 /* 2425 * Dual Stack Servers. 2426 */ 2427 alternates = NULL; 2428 (void)ns_config_get(maps, "dual-stack-servers", &alternates); 2429 if (alternates != NULL) 2430 CHECK(configure_alternates(config, view, alternates)); 2431 2432 /* 2433 * We have default hints for class IN if we need them. 2434 */ 2435 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) 2436 dns_view_sethints(view, ns_g_server->in_roothints); 2437 2438 /* 2439 * If we still have no hints, this is a non-IN view with no 2440 * "hints zone" configured. Issue a warning, except if this 2441 * is a root server. Root servers never need to consult 2442 * their hints, so it's no point requiring users to configure 2443 * them. 2444 */ 2445 if (view->hints == NULL) { 2446 dns_zone_t *rootzone = NULL; 2447 (void)dns_view_findzone(view, dns_rootname, &rootzone); 2448 if (rootzone != NULL) { 2449 dns_zone_detach(&rootzone); 2450 need_hints = ISC_FALSE; 2451 } 2452 if (need_hints) 2453 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2454 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 2455 "no root hints for view '%s'", 2456 view->name); 2457 } 2458 2459 /* 2460 * Configure the view's TSIG keys. 2461 */ 2462 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 2463 if (ns_g_server->sessionkey != NULL) { 2464 CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname, 2465 ns_g_server->sessionkey)); 2466 } 2467 dns_view_setkeyring(view, ring); 2468 dns_tsigkeyring_detach(&ring); 2469 2470 /* 2471 * See if we can re-use a dynamic key ring. 2472 */ 2473 result = dns_viewlist_find(&ns_g_server->viewlist, view->name, 2474 view->rdclass, &pview); 2475 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 2476 goto cleanup; 2477 if (pview != NULL) { 2478 dns_view_getdynamickeyring(pview, &ring); 2479 if (ring != NULL) 2480 dns_view_setdynamickeyring(view, ring); 2481 dns_tsigkeyring_detach(&ring); 2482 dns_view_detach(&pview); 2483 } else 2484 dns_view_restorekeyring(view); 2485 2486 /* 2487 * Configure the view's peer list. 2488 */ 2489 { 2490 const cfg_obj_t *peers = NULL; 2491 const cfg_listelt_t *element; 2492 dns_peerlist_t *newpeers = NULL; 2493 2494 (void)ns_config_get(cfgmaps, "server", &peers); 2495 CHECK(dns_peerlist_new(mctx, &newpeers)); 2496 for (element = cfg_list_first(peers); 2497 element != NULL; 2498 element = cfg_list_next(element)) 2499 { 2500 const cfg_obj_t *cpeer = cfg_listelt_value(element); 2501 dns_peer_t *peer; 2502 2503 CHECK(configure_peer(cpeer, mctx, &peer)); 2504 dns_peerlist_addpeer(newpeers, peer); 2505 dns_peer_detach(&peer); 2506 } 2507 dns_peerlist_detach(&view->peers); 2508 view->peers = newpeers; /* Transfer ownership. */ 2509 } 2510 2511 /* 2512 * Configure the views rrset-order. 2513 */ 2514 { 2515 const cfg_obj_t *rrsetorder = NULL; 2516 const cfg_listelt_t *element; 2517 2518 (void)ns_config_get(maps, "rrset-order", &rrsetorder); 2519 CHECK(dns_order_create(mctx, &order)); 2520 for (element = cfg_list_first(rrsetorder); 2521 element != NULL; 2522 element = cfg_list_next(element)) 2523 { 2524 const cfg_obj_t *ent = cfg_listelt_value(element); 2525 2526 CHECK(configure_order(order, ent)); 2527 } 2528 if (view->order != NULL) 2529 dns_order_detach(&view->order); 2530 dns_order_attach(order, &view->order); 2531 dns_order_detach(&order); 2532 } 2533 /* 2534 * Copy the aclenv object. 2535 */ 2536 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv); 2537 2538 /* 2539 * Configure the "match-clients" and "match-destinations" ACL. 2540 */ 2541 CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, actx, 2542 ns_g_mctx, &view->matchclients)); 2543 CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL, 2544 actx, ns_g_mctx, &view->matchdestinations)); 2545 2546 /* 2547 * Configure the "match-recursive-only" option. 2548 */ 2549 obj = NULL; 2550 (void)ns_config_get(maps, "match-recursive-only", &obj); 2551 if (obj != NULL && cfg_obj_asboolean(obj)) 2552 view->matchrecursiveonly = ISC_TRUE; 2553 else 2554 view->matchrecursiveonly = ISC_FALSE; 2555 2556 /* 2557 * Configure other configurable data. 2558 */ 2559 obj = NULL; 2560 result = ns_config_get(maps, "recursion", &obj); 2561 INSIST(result == ISC_R_SUCCESS); 2562 view->recursion = cfg_obj_asboolean(obj); 2563 2564 obj = NULL; 2565 result = ns_config_get(maps, "auth-nxdomain", &obj); 2566 INSIST(result == ISC_R_SUCCESS); 2567 view->auth_nxdomain = cfg_obj_asboolean(obj); 2568 2569 obj = NULL; 2570 result = ns_config_get(maps, "minimal-responses", &obj); 2571 INSIST(result == ISC_R_SUCCESS); 2572 view->minimalresponses = cfg_obj_asboolean(obj); 2573 2574 obj = NULL; 2575 result = ns_config_get(maps, "transfer-format", &obj); 2576 INSIST(result == ISC_R_SUCCESS); 2577 str = cfg_obj_asstring(obj); 2578 if (strcasecmp(str, "many-answers") == 0) 2579 view->transfer_format = dns_many_answers; 2580 else if (strcasecmp(str, "one-answer") == 0) 2581 view->transfer_format = dns_one_answer; 2582 else 2583 INSIST(0); 2584 2585 /* 2586 * Set sources where additional data and CNAME/DNAME 2587 * targets for authoritative answers may be found. 2588 */ 2589 obj = NULL; 2590 result = ns_config_get(maps, "additional-from-auth", &obj); 2591 INSIST(result == ISC_R_SUCCESS); 2592 view->additionalfromauth = cfg_obj_asboolean(obj); 2593 if (view->recursion && ! view->additionalfromauth) { 2594 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 2595 "'additional-from-auth no' is only supported " 2596 "with 'recursion no'"); 2597 view->additionalfromauth = ISC_TRUE; 2598 } 2599 2600 obj = NULL; 2601 result = ns_config_get(maps, "additional-from-cache", &obj); 2602 INSIST(result == ISC_R_SUCCESS); 2603 view->additionalfromcache = cfg_obj_asboolean(obj); 2604 if (view->recursion && ! view->additionalfromcache) { 2605 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 2606 "'additional-from-cache no' is only supported " 2607 "with 'recursion no'"); 2608 view->additionalfromcache = ISC_TRUE; 2609 } 2610 2611 /* 2612 * Set "allow-query-cache", "allow-query-cache-on", 2613 * "allow-recursion", and "allow-recursion-on" acls if 2614 * configured in named.conf. 2615 */ 2616 CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL, 2617 actx, ns_g_mctx, &view->cacheacl)); 2618 CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL, 2619 actx, ns_g_mctx, &view->cacheonacl)); 2620 if (view->cacheonacl == NULL) 2621 CHECK(configure_view_acl(NULL, ns_g_config, 2622 "allow-query-cache-on", NULL, actx, 2623 ns_g_mctx, &view->cacheonacl)); 2624 if (strcmp(view->name, "_bind") != 0) { 2625 CHECK(configure_view_acl(vconfig, config, "allow-recursion", 2626 NULL, actx, ns_g_mctx, 2627 &view->recursionacl)); 2628 CHECK(configure_view_acl(vconfig, config, "allow-recursion-on", 2629 NULL, actx, ns_g_mctx, 2630 &view->recursiononacl)); 2631 } 2632 2633 /* 2634 * "allow-query-cache" inherits from "allow-recursion" if set, 2635 * otherwise from "allow-query" if set. 2636 * "allow-recursion" inherits from "allow-query-cache" if set, 2637 * otherwise from "allow-query" if set. 2638 */ 2639 if (view->cacheacl == NULL && view->recursionacl != NULL) 2640 dns_acl_attach(view->recursionacl, &view->cacheacl); 2641 /* 2642 * XXXEACH: This call to configure_view_acl() is redundant. We 2643 * are leaving it as it is because we are making a minimal change 2644 * for a patch release. In the future this should be changed to 2645 * dns_acl_attach(view->queryacl, &view->cacheacl). 2646 */ 2647 if (view->cacheacl == NULL && view->recursion) 2648 CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, 2649 actx, ns_g_mctx, &view->cacheacl)); 2650 if (view->recursion && 2651 view->recursionacl == NULL && view->cacheacl != NULL) 2652 dns_acl_attach(view->cacheacl, &view->recursionacl); 2653 2654 /* 2655 * Set default "allow-recursion", "allow-recursion-on" and 2656 * "allow-query-cache" acls. 2657 */ 2658 if (view->recursionacl == NULL && view->recursion) 2659 CHECK(configure_view_acl(NULL, ns_g_config, 2660 "allow-recursion", NULL, 2661 actx, ns_g_mctx, 2662 &view->recursionacl)); 2663 if (view->recursiononacl == NULL && view->recursion) 2664 CHECK(configure_view_acl(NULL, ns_g_config, 2665 "allow-recursion-on", NULL, 2666 actx, ns_g_mctx, 2667 &view->recursiononacl)); 2668 if (view->cacheacl == NULL) { 2669 if (view->recursion) 2670 CHECK(configure_view_acl(NULL, ns_g_config, 2671 "allow-query-cache", NULL, 2672 actx, ns_g_mctx, 2673 &view->cacheacl)); 2674 else 2675 CHECK(dns_acl_none(mctx, &view->cacheacl)); 2676 } 2677 2678 /* 2679 * Filter setting on addresses in the answer section. 2680 */ 2681 CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses", 2682 "acl", actx, ns_g_mctx, &view->denyansweracl)); 2683 CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", 2684 "except-from", ns_g_mctx, 2685 &view->answeracl_exclude)); 2686 2687 /* 2688 * Filter setting on names (CNAME/DNAME targets) in the answer section. 2689 */ 2690 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 2691 "name", ns_g_mctx, 2692 &view->denyanswernames)); 2693 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 2694 "except-from", ns_g_mctx, 2695 &view->answernames_exclude)); 2696 2697 /* 2698 * Configure sortlist, if set 2699 */ 2700 CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx, 2701 &view->sortlist)); 2702 2703 /* 2704 * Configure default allow-transfer, allow-notify, allow-update 2705 * and allow-update-forwarding ACLs, if set, so they can be 2706 * inherited by zones. 2707 */ 2708 if (view->notifyacl == NULL) 2709 CHECK(configure_view_acl(NULL, ns_g_config, 2710 "allow-notify", NULL, actx, 2711 ns_g_mctx, &view->notifyacl)); 2712 if (view->transferacl == NULL) 2713 CHECK(configure_view_acl(NULL, ns_g_config, 2714 "allow-transfer", NULL, actx, 2715 ns_g_mctx, &view->transferacl)); 2716 if (view->updateacl == NULL) 2717 CHECK(configure_view_acl(NULL, ns_g_config, 2718 "allow-update", NULL, actx, 2719 ns_g_mctx, &view->updateacl)); 2720 if (view->upfwdacl == NULL) 2721 CHECK(configure_view_acl(NULL, ns_g_config, 2722 "allow-update-forwarding", NULL, actx, 2723 ns_g_mctx, &view->upfwdacl)); 2724 2725 obj = NULL; 2726 result = ns_config_get(maps, "provide-ixfr", &obj); 2727 INSIST(result == ISC_R_SUCCESS); 2728 view->provideixfr = cfg_obj_asboolean(obj); 2729 2730 obj = NULL; 2731 result = ns_config_get(maps, "request-nsid", &obj); 2732 INSIST(result == ISC_R_SUCCESS); 2733 view->requestnsid = cfg_obj_asboolean(obj); 2734 2735 obj = NULL; 2736 result = ns_config_get(maps, "max-clients-per-query", &obj); 2737 INSIST(result == ISC_R_SUCCESS); 2738 max_clients_per_query = cfg_obj_asuint32(obj); 2739 2740 obj = NULL; 2741 result = ns_config_get(maps, "clients-per-query", &obj); 2742 INSIST(result == ISC_R_SUCCESS); 2743 dns_resolver_setclientsperquery(view->resolver, 2744 cfg_obj_asuint32(obj), 2745 max_clients_per_query); 2746 2747#ifdef ALLOW_FILTER_AAAA_ON_V4 2748 obj = NULL; 2749 result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); 2750 INSIST(result == ISC_R_SUCCESS); 2751 if (cfg_obj_isboolean(obj)) { 2752 if (cfg_obj_asboolean(obj)) 2753 view->v4_aaaa = dns_v4_aaaa_filter; 2754 else 2755 view->v4_aaaa = dns_v4_aaaa_ok; 2756 } else { 2757 const char *v4_aaaastr = cfg_obj_asstring(obj); 2758 if (strcasecmp(v4_aaaastr, "break-dnssec") == 0) 2759 view->v4_aaaa = dns_v4_aaaa_break_dnssec; 2760 else 2761 INSIST(0); 2762 } 2763 CHECK(configure_view_acl(vconfig, config, "filter-aaaa", NULL, 2764 actx, ns_g_mctx, &view->v4_aaaa_acl)); 2765#endif 2766 2767 obj = NULL; 2768 result = ns_config_get(maps, "dnssec-enable", &obj); 2769 INSIST(result == ISC_R_SUCCESS); 2770 view->enablednssec = cfg_obj_asboolean(obj); 2771 2772 obj = NULL; 2773 result = ns_config_get(optionmaps, "dnssec-lookaside", &obj); 2774 if (result == ISC_R_SUCCESS) { 2775 /* If set to "auto", use the version from the defaults */ 2776 const cfg_obj_t *dlvobj; 2777 const char *dom; 2778 dlvobj = cfg_listelt_value(cfg_list_first(obj)); 2779 dom = cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain")); 2780 if (cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) { 2781 /* If "no", skip; if "auto", use global default */ 2782 if (!strcasecmp(dom, "no")) 2783 result = ISC_R_NOTFOUND; 2784 else if (!strcasecmp(dom, "auto")) { 2785 auto_dlv = ISC_TRUE; 2786 obj = NULL; 2787 result = cfg_map_get(ns_g_defaults, 2788 "dnssec-lookaside", &obj); 2789 } 2790 } 2791 } 2792 2793 if (result == ISC_R_SUCCESS) { 2794 for (element = cfg_list_first(obj); 2795 element != NULL; 2796 element = cfg_list_next(element)) 2797 { 2798 const char *str; 2799 isc_buffer_t b; 2800 dns_name_t *dlv; 2801 2802 obj = cfg_listelt_value(element); 2803 str = cfg_obj_asstring(cfg_tuple_get(obj, 2804 "trust-anchor")); 2805 isc_buffer_constinit(&b, str, strlen(str)); 2806 isc_buffer_add(&b, strlen(str)); 2807 dlv = dns_fixedname_name(&view->dlv_fixed); 2808 CHECK(dns_name_fromtext(dlv, &b, dns_rootname, 2809 DNS_NAME_DOWNCASE, NULL)); 2810 view->dlv = dns_fixedname_name(&view->dlv_fixed); 2811 } 2812 } else 2813 view->dlv = NULL; 2814 2815 /* 2816 * For now, there is only one kind of trusted keys, the 2817 * "security roots". 2818 */ 2819 CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, 2820 auto_dlv, auto_root, mctx)); 2821 dns_resolver_resetmustbesecure(view->resolver); 2822 obj = NULL; 2823 result = ns_config_get(maps, "dnssec-must-be-secure", &obj); 2824 if (result == ISC_R_SUCCESS) 2825 CHECK(mustbesecure(obj, view->resolver)); 2826 2827 obj = NULL; 2828 result = ns_config_get(maps, "preferred-glue", &obj); 2829 if (result == ISC_R_SUCCESS) { 2830 str = cfg_obj_asstring(obj); 2831 if (strcasecmp(str, "a") == 0) 2832 view->preferred_glue = dns_rdatatype_a; 2833 else if (strcasecmp(str, "aaaa") == 0) 2834 view->preferred_glue = dns_rdatatype_aaaa; 2835 else 2836 view->preferred_glue = 0; 2837 } else 2838 view->preferred_glue = 0; 2839 2840 obj = NULL; 2841 result = ns_config_get(maps, "root-delegation-only", &obj); 2842 if (result == ISC_R_SUCCESS) { 2843 dns_view_setrootdelonly(view, ISC_TRUE); 2844 if (!cfg_obj_isvoid(obj)) { 2845 dns_fixedname_t fixed; 2846 dns_name_t *name; 2847 isc_buffer_t b; 2848 const char *str; 2849 const cfg_obj_t *exclude; 2850 2851 dns_fixedname_init(&fixed); 2852 name = dns_fixedname_name(&fixed); 2853 for (element = cfg_list_first(obj); 2854 element != NULL; 2855 element = cfg_list_next(element)) { 2856 exclude = cfg_listelt_value(element); 2857 str = cfg_obj_asstring(exclude); 2858 isc_buffer_constinit(&b, str, strlen(str)); 2859 isc_buffer_add(&b, strlen(str)); 2860 CHECK(dns_name_fromtext(name, &b, dns_rootname, 2861 0, NULL)); 2862 CHECK(dns_view_excludedelegationonly(view, 2863 name)); 2864 } 2865 } 2866 } else 2867 dns_view_setrootdelonly(view, ISC_FALSE); 2868 2869 /* 2870 * Setup automatic empty zones. If recursion is off then 2871 * they are disabled by default. 2872 */ 2873 obj = NULL; 2874 (void)ns_config_get(maps, "empty-zones-enable", &obj); 2875 (void)ns_config_get(maps, "disable-empty-zone", &disablelist); 2876 if (obj == NULL && disablelist == NULL && 2877 view->rdclass == dns_rdataclass_in) { 2878 empty_zones_enable = view->recursion; 2879 } else if (view->rdclass == dns_rdataclass_in) { 2880 if (obj != NULL) 2881 empty_zones_enable = cfg_obj_asboolean(obj); 2882 else 2883 empty_zones_enable = view->recursion; 2884 } else { 2885 empty_zones_enable = ISC_FALSE; 2886 } 2887 if (empty_zones_enable && !lwresd_g_useresolvconf) { 2888 const char *empty; 2889 int empty_zone = 0; 2890 dns_fixedname_t fixed; 2891 dns_name_t *name; 2892 isc_buffer_t buffer; 2893 const char *str; 2894 char server[DNS_NAME_FORMATSIZE + 1]; 2895 char contact[DNS_NAME_FORMATSIZE + 1]; 2896 const char *empty_dbtype[4] = 2897 { "_builtin", "empty", NULL, NULL }; 2898 int empty_dbtypec = 4; 2899 dns_zonestat_level_t statlevel; 2900 2901 dns_fixedname_init(&fixed); 2902 name = dns_fixedname_name(&fixed); 2903 2904 obj = NULL; 2905 result = ns_config_get(maps, "empty-server", &obj); 2906 if (result == ISC_R_SUCCESS) { 2907 str = cfg_obj_asstring(obj); 2908 isc_buffer_constinit(&buffer, str, strlen(str)); 2909 isc_buffer_add(&buffer, strlen(str)); 2910 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 2911 NULL)); 2912 isc_buffer_init(&buffer, server, sizeof(server) - 1); 2913 CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); 2914 server[isc_buffer_usedlength(&buffer)] = 0; 2915 empty_dbtype[2] = server; 2916 } else 2917 empty_dbtype[2] = "@"; 2918 2919 obj = NULL; 2920 result = ns_config_get(maps, "empty-contact", &obj); 2921 if (result == ISC_R_SUCCESS) { 2922 str = cfg_obj_asstring(obj); 2923 isc_buffer_constinit(&buffer, str, strlen(str)); 2924 isc_buffer_add(&buffer, strlen(str)); 2925 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 2926 NULL)); 2927 isc_buffer_init(&buffer, contact, sizeof(contact) - 1); 2928 CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); 2929 contact[isc_buffer_usedlength(&buffer)] = 0; 2930 empty_dbtype[3] = contact; 2931 } else 2932 empty_dbtype[3] = "."; 2933 2934 obj = NULL; 2935 result = ns_config_get(maps, "zone-statistics", &obj); 2936 INSIST(result == ISC_R_SUCCESS); 2937 if (cfg_obj_isboolean(obj)) { 2938 if (cfg_obj_asboolean(obj)) 2939 statlevel = dns_zonestat_full; 2940 else 2941 statlevel = dns_zonestat_terse; /* XXX */ 2942 } else { 2943 const char *levelstr = cfg_obj_asstring(obj); 2944 if (strcasecmp(levelstr, "full") == 0) 2945 statlevel = dns_zonestat_full; 2946 else if (strcasecmp(levelstr, "terse") == 0) 2947 statlevel = dns_zonestat_terse; 2948 else if (strcasecmp(levelstr, "none") == 0) 2949 statlevel = dns_zonestat_none; 2950 else 2951 INSIST(0); 2952 } 2953 2954 for (empty = empty_zones[empty_zone]; 2955 empty != NULL; 2956 empty = empty_zones[++empty_zone]) 2957 { 2958 dns_forwarders_t *forwarders = NULL; 2959 dns_view_t *pview = NULL; 2960 2961 isc_buffer_constinit(&buffer, empty, strlen(empty)); 2962 isc_buffer_add(&buffer, strlen(empty)); 2963 /* 2964 * Look for zone on drop list. 2965 */ 2966 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 2967 NULL)); 2968 if (disablelist != NULL && 2969 on_disable_list(disablelist, name)) 2970 continue; 2971 2972 /* 2973 * This zone already exists. 2974 */ 2975 (void)dns_view_findzone(view, name, &zone); 2976 if (zone != NULL) { 2977 dns_zone_detach(&zone); 2978 continue; 2979 } 2980 2981 /* 2982 * If we would forward this name don't add a 2983 * empty zone for it. 2984 */ 2985 result = dns_fwdtable_find(view->fwdtable, name, 2986 &forwarders); 2987 if (result == ISC_R_SUCCESS && 2988 forwarders->fwdpolicy == dns_fwdpolicy_only) 2989 continue; 2990 2991 /* 2992 * See if we can re-use a existing zone. 2993 */ 2994 result = dns_viewlist_find(&ns_g_server->viewlist, 2995 view->name, view->rdclass, 2996 &pview); 2997 if (result != ISC_R_NOTFOUND && 2998 result != ISC_R_SUCCESS) 2999 goto cleanup; 3000 3001 if (pview != NULL) { 3002 (void)dns_view_findzone(pview, name, &zone); 3003 dns_view_detach(&pview); 3004 if (zone != NULL) 3005 check_dbtype(&zone, empty_dbtypec, 3006 empty_dbtype, mctx); 3007 if (zone != NULL) { 3008 dns_zone_setview(zone, view); 3009 CHECK(dns_view_addzone(view, zone)); 3010 CHECK(setquerystats(zone, mctx, 3011 statlevel)); 3012 dns_zone_detach(&zone); 3013 continue; 3014 } 3015 } 3016 3017 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, 3018 &zone)); 3019 CHECK(dns_zone_setorigin(zone, name)); 3020 dns_zone_setview(zone, view); 3021 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, 3022 zone)); 3023 dns_zone_setclass(zone, view->rdclass); 3024 dns_zone_settype(zone, dns_zone_master); 3025 dns_zone_setstats(zone, ns_g_server->zonestats); 3026 CHECK(dns_zone_setdbtype(zone, empty_dbtypec, 3027 empty_dbtype)); 3028 if (view->queryacl != NULL) 3029 dns_zone_setqueryacl(zone, view->queryacl); 3030 if (view->queryonacl != NULL) 3031 dns_zone_setqueryonacl(zone, view->queryonacl); 3032 dns_zone_setdialup(zone, dns_dialuptype_no); 3033 dns_zone_setnotifytype(zone, dns_notifytype_no); 3034 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, 3035 ISC_TRUE); 3036 CHECK(setquerystats(zone, mctx, statlevel)); 3037 CHECK(dns_view_addzone(view, zone)); 3038 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3039 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3040 "automatic empty zone%s%s: %s", 3041 sep, viewname, empty); 3042 dns_zone_detach(&zone); 3043 } 3044 } 3045 3046 result = ISC_R_SUCCESS; 3047 3048 cleanup: 3049 if (clients != NULL) 3050 dns_acl_detach(&clients); 3051 if (mapped != NULL) 3052 dns_acl_detach(&mapped); 3053 if (excluded != NULL) 3054 dns_acl_detach(&excluded); 3055 if (ring != NULL) 3056 dns_tsigkeyring_detach(&ring); 3057 if (zone != NULL) 3058 dns_zone_detach(&zone); 3059 if (dispatch4 != NULL) 3060 dns_dispatch_detach(&dispatch4); 3061 if (dispatch6 != NULL) 3062 dns_dispatch_detach(&dispatch6); 3063 if (resstats != NULL) 3064 isc_stats_detach(&resstats); 3065 if (resquerystats != NULL) 3066 dns_stats_detach(&resquerystats); 3067 if (order != NULL) 3068 dns_order_detach(&order); 3069 if (cmctx != NULL) 3070 isc_mem_detach(&cmctx); 3071 if (hmctx != NULL) 3072 isc_mem_detach(&hmctx); 3073 3074 if (cache != NULL) 3075 dns_cache_detach(&cache); 3076 3077 return (result); 3078} 3079 3080static isc_result_t 3081configure_hints(dns_view_t *view, const char *filename) { 3082 isc_result_t result; 3083 dns_db_t *db; 3084 3085 db = NULL; 3086 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 3087 if (result == ISC_R_SUCCESS) { 3088 dns_view_sethints(view, db); 3089 dns_db_detach(&db); 3090 } 3091 3092 return (result); 3093} 3094 3095static isc_result_t 3096configure_alternates(const cfg_obj_t *config, dns_view_t *view, 3097 const cfg_obj_t *alternates) 3098{ 3099 const cfg_obj_t *portobj; 3100 const cfg_obj_t *addresses; 3101 const cfg_listelt_t *element; 3102 isc_result_t result = ISC_R_SUCCESS; 3103 in_port_t port; 3104 3105 /* 3106 * Determine which port to send requests to. 3107 */ 3108 if (ns_g_lwresdonly && ns_g_port != 0) 3109 port = ns_g_port; 3110 else 3111 CHECKM(ns_config_getport(config, &port), "port"); 3112 3113 if (alternates != NULL) { 3114 portobj = cfg_tuple_get(alternates, "port"); 3115 if (cfg_obj_isuint32(portobj)) { 3116 isc_uint32_t val = cfg_obj_asuint32(portobj); 3117 if (val > ISC_UINT16_MAX) { 3118 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 3119 "port '%u' out of range", val); 3120 return (ISC_R_RANGE); 3121 } 3122 port = (in_port_t) val; 3123 } 3124 } 3125 3126 addresses = NULL; 3127 if (alternates != NULL) 3128 addresses = cfg_tuple_get(alternates, "addresses"); 3129 3130 for (element = cfg_list_first(addresses); 3131 element != NULL; 3132 element = cfg_list_next(element)) 3133 { 3134 const cfg_obj_t *alternate = cfg_listelt_value(element); 3135 isc_sockaddr_t sa; 3136 3137 if (!cfg_obj_issockaddr(alternate)) { 3138 dns_fixedname_t fixed; 3139 dns_name_t *name; 3140 const char *str = cfg_obj_asstring(cfg_tuple_get( 3141 alternate, "name")); 3142 isc_buffer_t buffer; 3143 in_port_t myport = port; 3144 3145 isc_buffer_constinit(&buffer, str, strlen(str)); 3146 isc_buffer_add(&buffer, strlen(str)); 3147 dns_fixedname_init(&fixed); 3148 name = dns_fixedname_name(&fixed); 3149 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 3150 NULL)); 3151 3152 portobj = cfg_tuple_get(alternate, "port"); 3153 if (cfg_obj_isuint32(portobj)) { 3154 isc_uint32_t val = cfg_obj_asuint32(portobj); 3155 if (val > ISC_UINT16_MAX) { 3156 cfg_obj_log(portobj, ns_g_lctx, 3157 ISC_LOG_ERROR, 3158 "port '%u' out of range", 3159 val); 3160 return (ISC_R_RANGE); 3161 } 3162 myport = (in_port_t) val; 3163 } 3164 CHECK(dns_resolver_addalternate(view->resolver, NULL, 3165 name, myport)); 3166 continue; 3167 } 3168 3169 sa = *cfg_obj_assockaddr(alternate); 3170 if (isc_sockaddr_getport(&sa) == 0) 3171 isc_sockaddr_setport(&sa, port); 3172 CHECK(dns_resolver_addalternate(view->resolver, &sa, 3173 NULL, 0)); 3174 } 3175 3176 cleanup: 3177 return (result); 3178} 3179 3180static isc_result_t 3181configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 3182 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype) 3183{ 3184 const cfg_obj_t *portobj; 3185 const cfg_obj_t *faddresses; 3186 const cfg_listelt_t *element; 3187 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 3188 isc_sockaddrlist_t addresses; 3189 isc_sockaddr_t *sa; 3190 isc_result_t result; 3191 in_port_t port; 3192 3193 ISC_LIST_INIT(addresses); 3194 3195 /* 3196 * Determine which port to send forwarded requests to. 3197 */ 3198 if (ns_g_lwresdonly && ns_g_port != 0) 3199 port = ns_g_port; 3200 else 3201 CHECKM(ns_config_getport(config, &port), "port"); 3202 3203 if (forwarders != NULL) { 3204 portobj = cfg_tuple_get(forwarders, "port"); 3205 if (cfg_obj_isuint32(portobj)) { 3206 isc_uint32_t val = cfg_obj_asuint32(portobj); 3207 if (val > ISC_UINT16_MAX) { 3208 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 3209 "port '%u' out of range", val); 3210 return (ISC_R_RANGE); 3211 } 3212 port = (in_port_t) val; 3213 } 3214 } 3215 3216 faddresses = NULL; 3217 if (forwarders != NULL) 3218 faddresses = cfg_tuple_get(forwarders, "addresses"); 3219 3220 for (element = cfg_list_first(faddresses); 3221 element != NULL; 3222 element = cfg_list_next(element)) 3223 { 3224 const cfg_obj_t *forwarder = cfg_listelt_value(element); 3225 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t)); 3226 if (sa == NULL) { 3227 result = ISC_R_NOMEMORY; 3228 goto cleanup; 3229 } 3230 *sa = *cfg_obj_assockaddr(forwarder); 3231 if (isc_sockaddr_getport(sa) == 0) 3232 isc_sockaddr_setport(sa, port); 3233 ISC_LINK_INIT(sa, link); 3234 ISC_LIST_APPEND(addresses, sa, link); 3235 } 3236 3237 if (ISC_LIST_EMPTY(addresses)) { 3238 if (forwardtype != NULL) 3239 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 3240 "no forwarders seen; disabling " 3241 "forwarding"); 3242 fwdpolicy = dns_fwdpolicy_none; 3243 } else { 3244 if (forwardtype == NULL) 3245 fwdpolicy = dns_fwdpolicy_first; 3246 else { 3247 const char *forwardstr = cfg_obj_asstring(forwardtype); 3248 if (strcasecmp(forwardstr, "first") == 0) 3249 fwdpolicy = dns_fwdpolicy_first; 3250 else if (strcasecmp(forwardstr, "only") == 0) 3251 fwdpolicy = dns_fwdpolicy_only; 3252 else 3253 INSIST(0); 3254 } 3255 } 3256 3257 result = dns_fwdtable_add(view->fwdtable, origin, &addresses, 3258 fwdpolicy); 3259 if (result != ISC_R_SUCCESS) { 3260 char namebuf[DNS_NAME_FORMATSIZE]; 3261 dns_name_format(origin, namebuf, sizeof(namebuf)); 3262 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 3263 "could not set up forwarding for domain '%s': %s", 3264 namebuf, isc_result_totext(result)); 3265 goto cleanup; 3266 } 3267 3268 result = ISC_R_SUCCESS; 3269 3270 cleanup: 3271 3272 while (!ISC_LIST_EMPTY(addresses)) { 3273 sa = ISC_LIST_HEAD(addresses); 3274 ISC_LIST_UNLINK(addresses, sa, link); 3275 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t)); 3276 } 3277 3278 return (result); 3279} 3280 3281static isc_result_t 3282get_viewinfo(const cfg_obj_t *vconfig, const char **namep, 3283 dns_rdataclass_t *classp) 3284{ 3285 isc_result_t result = ISC_R_SUCCESS; 3286 const char *viewname; 3287 dns_rdataclass_t viewclass; 3288 3289 REQUIRE(namep != NULL && *namep == NULL); 3290 REQUIRE(classp != NULL); 3291 3292 if (vconfig != NULL) { 3293 const cfg_obj_t *classobj = NULL; 3294 3295 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 3296 classobj = cfg_tuple_get(vconfig, "class"); 3297 result = ns_config_getclass(classobj, dns_rdataclass_in, 3298 &viewclass); 3299 } else { 3300 viewname = "_default"; 3301 viewclass = dns_rdataclass_in; 3302 } 3303 3304 *namep = viewname; 3305 *classp = viewclass; 3306 3307 return (result); 3308} 3309 3310/* 3311 * Find a view based on its configuration info and attach to it. 3312 * 3313 * If 'vconfig' is NULL, attach to the default view. 3314 */ 3315static isc_result_t 3316find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 3317 dns_view_t **viewp) 3318{ 3319 isc_result_t result; 3320 const char *viewname = NULL; 3321 dns_rdataclass_t viewclass; 3322 dns_view_t *view = NULL; 3323 3324 result = get_viewinfo(vconfig, &viewname, &viewclass); 3325 if (result != ISC_R_SUCCESS) 3326 return (result); 3327 3328 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 3329 if (result != ISC_R_SUCCESS) 3330 return (result); 3331 3332 *viewp = view; 3333 return (ISC_R_SUCCESS); 3334} 3335 3336/* 3337 * Create a new view and add it to the list. 3338 * 3339 * If 'vconfig' is NULL, create the default view. 3340 * 3341 * The view created is attached to '*viewp'. 3342 */ 3343static isc_result_t 3344create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 3345 dns_view_t **viewp) 3346{ 3347 isc_result_t result; 3348 const char *viewname = NULL; 3349 dns_rdataclass_t viewclass; 3350 dns_view_t *view = NULL; 3351 3352 result = get_viewinfo(vconfig, &viewname, &viewclass); 3353 if (result != ISC_R_SUCCESS) 3354 return (result); 3355 3356 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 3357 if (result == ISC_R_SUCCESS) 3358 return (ISC_R_EXISTS); 3359 if (result != ISC_R_NOTFOUND) 3360 return (result); 3361 INSIST(view == NULL); 3362 3363 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view); 3364 if (result != ISC_R_SUCCESS) 3365 return (result); 3366 3367 ISC_LIST_APPEND(*viewlist, view, link); 3368 dns_view_attach(view, viewp); 3369 return (ISC_R_SUCCESS); 3370} 3371 3372/* 3373 * Configure or reconfigure a zone. 3374 */ 3375static isc_result_t 3376configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 3377 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 3378 cfg_aclconfctx_t *aclconf, isc_boolean_t added) 3379{ 3380 dns_view_t *pview = NULL; /* Production view */ 3381 dns_zone_t *zone = NULL; /* New or reused zone */ 3382 dns_zone_t *raw = NULL; /* New or reused raw zone */ 3383 dns_zone_t *dupzone = NULL; 3384 const cfg_obj_t *options = NULL; 3385 const cfg_obj_t *zoptions = NULL; 3386 const cfg_obj_t *typeobj = NULL; 3387 const cfg_obj_t *forwarders = NULL; 3388 const cfg_obj_t *forwardtype = NULL; 3389 const cfg_obj_t *only = NULL; 3390 const cfg_obj_t *signing = NULL; 3391 isc_result_t result; 3392 isc_result_t tresult; 3393 isc_buffer_t buffer; 3394 dns_fixedname_t fixorigin; 3395 dns_name_t *origin; 3396 const char *zname; 3397 dns_rdataclass_t zclass; 3398 const char *ztypestr; 3399 isc_boolean_t is_rpz; 3400 dns_rpz_zone_t *rpz; 3401 3402 options = NULL; 3403 (void)cfg_map_get(config, "options", &options); 3404 3405 zoptions = cfg_tuple_get(zconfig, "options"); 3406 3407 /* 3408 * Get the zone origin as a dns_name_t. 3409 */ 3410 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 3411 isc_buffer_constinit(&buffer, zname, strlen(zname)); 3412 isc_buffer_add(&buffer, strlen(zname)); 3413 dns_fixedname_init(&fixorigin); 3414 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), 3415 &buffer, dns_rootname, 0, NULL)); 3416 origin = dns_fixedname_name(&fixorigin); 3417 3418 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), 3419 view->rdclass, &zclass)); 3420 if (zclass != view->rdclass) { 3421 const char *vname = NULL; 3422 if (vconfig != NULL) 3423 vname = cfg_obj_asstring(cfg_tuple_get(vconfig, 3424 "name")); 3425 else 3426 vname = "<default view>"; 3427 3428 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3429 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3430 "zone '%s': wrong class for view '%s'", 3431 zname, vname); 3432 result = ISC_R_FAILURE; 3433 goto cleanup; 3434 } 3435 3436 (void)cfg_map_get(zoptions, "type", &typeobj); 3437 if (typeobj == NULL) { 3438 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 3439 "zone '%s' 'type' not specified", zname); 3440 return (ISC_R_FAILURE); 3441 } 3442 ztypestr = cfg_obj_asstring(typeobj); 3443 3444 /* 3445 * "hints zones" aren't zones. If we've got one, 3446 * configure it and return. 3447 */ 3448 if (strcasecmp(ztypestr, "hint") == 0) { 3449 const cfg_obj_t *fileobj = NULL; 3450 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 3451 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3452 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3453 "zone '%s': 'file' not specified", 3454 zname); 3455 result = ISC_R_FAILURE; 3456 goto cleanup; 3457 } 3458 if (dns_name_equal(origin, dns_rootname)) { 3459 const char *hintsfile = cfg_obj_asstring(fileobj); 3460 3461 result = configure_hints(view, hintsfile); 3462 if (result != ISC_R_SUCCESS) { 3463 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3464 NS_LOGMODULE_SERVER, 3465 ISC_LOG_ERROR, 3466 "could not configure root hints " 3467 "from '%s': %s", hintsfile, 3468 isc_result_totext(result)); 3469 goto cleanup; 3470 } 3471 /* 3472 * Hint zones may also refer to delegation only points. 3473 */ 3474 only = NULL; 3475 tresult = cfg_map_get(zoptions, "delegation-only", 3476 &only); 3477 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) 3478 CHECK(dns_view_adddelegationonly(view, origin)); 3479 } else { 3480 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3481 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 3482 "ignoring non-root hint zone '%s'", 3483 zname); 3484 result = ISC_R_SUCCESS; 3485 } 3486 /* Skip ordinary zone processing. */ 3487 goto cleanup; 3488 } 3489 3490 /* 3491 * "forward zones" aren't zones either. Translate this syntax into 3492 * the appropriate selective forwarding configuration and return. 3493 */ 3494 if (strcasecmp(ztypestr, "forward") == 0) { 3495 forwardtype = NULL; 3496 forwarders = NULL; 3497 3498 (void)cfg_map_get(zoptions, "forward", &forwardtype); 3499 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 3500 result = configure_forward(config, view, origin, forwarders, 3501 forwardtype); 3502 goto cleanup; 3503 } 3504 3505 /* 3506 * "delegation-only zones" aren't zones either. 3507 */ 3508 if (strcasecmp(ztypestr, "delegation-only") == 0) { 3509 result = dns_view_adddelegationonly(view, origin); 3510 goto cleanup; 3511 } 3512 3513 /* 3514 * Redirect zones only require minimal configuration. 3515 */ 3516 if (strcasecmp(ztypestr, "redirect") == 0) { 3517 if (view->redirect != NULL) { 3518 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 3519 "redirect zone already exists"); 3520 result = ISC_R_EXISTS; 3521 goto cleanup; 3522 } 3523 result = dns_viewlist_find(&ns_g_server->viewlist, view->name, 3524 view->rdclass, &pview); 3525 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 3526 goto cleanup; 3527 if (pview != NULL && pview->redirect != NULL) { 3528 dns_zone_attach(pview->redirect, &zone); 3529 dns_zone_setview(zone, view); 3530 } else { 3531 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, 3532 &zone)); 3533 CHECK(dns_zone_setorigin(zone, origin)); 3534 dns_zone_setview(zone, view); 3535 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, 3536 zone)); 3537 dns_zone_setstats(zone, ns_g_server->zonestats); 3538 } 3539 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, 3540 zone, NULL)); 3541 dns_zone_attach(zone, &view->redirect); 3542 goto cleanup; 3543 } 3544 3545 /* 3546 * Check for duplicates in the new zone table. 3547 */ 3548 result = dns_view_findzone(view, origin, &dupzone); 3549 if (result == ISC_R_SUCCESS) { 3550 /* 3551 * We already have this zone! 3552 */ 3553 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 3554 "zone '%s' already exists", zname); 3555 dns_zone_detach(&dupzone); 3556 result = ISC_R_EXISTS; 3557 goto cleanup; 3558 } 3559 INSIST(dupzone == NULL); 3560 3561 /* 3562 * Note whether this is a response policy zone. 3563 */ 3564 is_rpz = ISC_FALSE; 3565 for (rpz = ISC_LIST_HEAD(view->rpz_zones); 3566 rpz != NULL; 3567 rpz = ISC_LIST_NEXT(rpz, link)) 3568 { 3569 if (dns_name_equal(&rpz->origin, origin)) { 3570 is_rpz = ISC_TRUE; 3571 rpz->defined = ISC_TRUE; 3572 break; 3573 } 3574 } 3575 3576 /* 3577 * See if we can reuse an existing zone. This is 3578 * only possible if all of these are true: 3579 * - The zone's view exists 3580 * - A zone with the right name exists in the view 3581 * - The zone is compatible with the config 3582 * options (e.g., an existing master zone cannot 3583 * be reused if the options specify a slave zone) 3584 * - The zone was and is or was not and is not a policy zone 3585 */ 3586 result = dns_viewlist_find(&ns_g_server->viewlist, view->name, 3587 view->rdclass, &pview); 3588 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 3589 goto cleanup; 3590 if (pview != NULL) 3591 result = dns_view_findzone(pview, origin, &zone); 3592 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 3593 goto cleanup; 3594 3595 if (zone != NULL && !ns_zone_reusable(zone, zconfig)) 3596 dns_zone_detach(&zone); 3597 3598 if (zone != NULL && is_rpz != dns_zone_get_rpz(zone)) 3599 dns_zone_detach(&zone); 3600 3601 if (zone != NULL) { 3602 /* 3603 * We found a reusable zone. Make it use the 3604 * new view. 3605 */ 3606 dns_zone_setview(zone, view); 3607 if (view->acache != NULL) 3608 dns_zone_setacache(zone, view->acache); 3609 } else { 3610 /* 3611 * We cannot reuse an existing zone, we have 3612 * to create a new one. 3613 */ 3614 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); 3615 CHECK(dns_zone_setorigin(zone, origin)); 3616 dns_zone_setview(zone, view); 3617 if (view->acache != NULL) 3618 dns_zone_setacache(zone, view->acache); 3619 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 3620 dns_zone_setstats(zone, ns_g_server->zonestats); 3621 } 3622 3623 if (is_rpz) { 3624 result = dns_zone_rpz_enable(zone); 3625 if (result != ISC_R_SUCCESS) { 3626 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3627 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3628 "zone '%s': incompatible" 3629 " masterfile-format or database" 3630 " for a response policy zone", 3631 zname); 3632 goto cleanup; 3633 } 3634 } 3635 3636 /* 3637 * If the zone contains a 'forwarders' statement, configure 3638 * selective forwarding. 3639 */ 3640 forwarders = NULL; 3641 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) 3642 { 3643 forwardtype = NULL; 3644 (void)cfg_map_get(zoptions, "forward", &forwardtype); 3645 CHECK(configure_forward(config, view, origin, forwarders, 3646 forwardtype)); 3647 } 3648 3649 /* 3650 * Stub and forward zones may also refer to delegation only points. 3651 */ 3652 only = NULL; 3653 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) 3654 { 3655 if (cfg_obj_asboolean(only)) 3656 CHECK(dns_view_adddelegationonly(view, origin)); 3657 } 3658 3659 /* 3660 * Mark whether the zone was originally added at runtime or not 3661 */ 3662 dns_zone_setadded(zone, added); 3663 3664 signing = NULL; 3665 if ((strcasecmp(ztypestr, "master") == 0 || 3666 strcasecmp(ztypestr, "slave") == 0) && 3667 cfg_map_get(zoptions, "inline-signing", &signing) == ISC_R_SUCCESS && 3668 cfg_obj_asboolean(signing)) 3669 { 3670 dns_zone_getraw(zone, &raw); 3671 if (raw == NULL) { 3672 CHECK(dns_zone_create(&raw, mctx)); 3673 CHECK(dns_zone_setorigin(raw, origin)); 3674 dns_zone_setview(raw, view); 3675 if (view->acache != NULL) 3676 dns_zone_setacache(raw, view->acache); 3677 dns_zone_setstats(raw, ns_g_server->zonestats); 3678 CHECK(dns_zone_link(zone, raw)); 3679 } 3680 } 3681 3682 /* 3683 * Configure the zone. 3684 */ 3685 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone, raw)); 3686 3687 /* 3688 * Add the zone to its view in the new view list. 3689 */ 3690 CHECK(dns_view_addzone(view, zone)); 3691 3692 /* 3693 * Ensure that zone keys are reloaded on reconfig 3694 */ 3695 if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) 3696 dns_zone_rekey(zone, ISC_FALSE); 3697 3698 cleanup: 3699 if (zone != NULL) 3700 dns_zone_detach(&zone); 3701 if (raw != NULL) 3702 dns_zone_detach(&raw); 3703 if (pview != NULL) 3704 dns_view_detach(&pview); 3705 3706 return (result); 3707} 3708 3709/* 3710 * Configure built-in zone for storing managed-key data. 3711 */ 3712 3713#define KEYZONE "managed-keys.bind" 3714#define MKEYS ".mkeys" 3715 3716static isc_result_t 3717add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { 3718 isc_result_t result; 3719 dns_view_t *pview = NULL; 3720 dns_zone_t *zone = NULL; 3721 dns_acl_t *none = NULL; 3722 char filename[PATH_MAX]; 3723 char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(MKEYS)]; 3724 int n; 3725 3726 REQUIRE(view != NULL); 3727 3728 /* See if we can re-use an existing keydata zone. */ 3729 result = dns_viewlist_find(&ns_g_server->viewlist, 3730 view->name, view->rdclass, 3731 &pview); 3732 if (result != ISC_R_NOTFOUND && 3733 result != ISC_R_SUCCESS) 3734 return (result); 3735 3736 if (pview != NULL && pview->managed_keys != NULL) { 3737 dns_zone_attach(pview->managed_keys, &view->managed_keys); 3738 dns_zone_setview(pview->managed_keys, view); 3739 dns_view_detach(&pview); 3740 dns_zone_synckeyzone(view->managed_keys); 3741 return (ISC_R_SUCCESS); 3742 } 3743 3744 /* No existing keydata zone was found; create one */ 3745 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); 3746 CHECK(dns_zone_setorigin(zone, dns_rootname)); 3747 3748 isc_sha256_data((void *)view->name, strlen(view->name), buffer); 3749 strcat(buffer, MKEYS); 3750 n = snprintf(filename, sizeof(filename), "%s%s%s", 3751 directory ? directory : "", directory ? "/" : "", 3752 strcmp(view->name, "_default") == 0 ? KEYZONE : buffer); 3753 if (n < 0 || (size_t)n >= sizeof(filename)) { 3754 result = (n < 0) ? ISC_R_FAILURE : ISC_R_NOSPACE; 3755 goto cleanup; 3756 } 3757 CHECK(dns_zone_setfile(zone, filename)); 3758 3759 dns_zone_setview(zone, view); 3760 dns_zone_settype(zone, dns_zone_key); 3761 dns_zone_setclass(zone, view->rdclass); 3762 3763 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 3764 3765 if (view->acache != NULL) 3766 dns_zone_setacache(zone, view->acache); 3767 3768 CHECK(dns_acl_none(mctx, &none)); 3769 dns_zone_setqueryacl(zone, none); 3770 dns_zone_setqueryonacl(zone, none); 3771 dns_acl_detach(&none); 3772 3773 dns_zone_setdialup(zone, dns_dialuptype_no); 3774 dns_zone_setnotifytype(zone, dns_notifytype_no); 3775 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); 3776 dns_zone_setjournalsize(zone, 0); 3777 3778 dns_zone_setstats(zone, ns_g_server->zonestats); 3779 CHECK(setquerystats(zone, mctx, dns_zonestat_none)); 3780 3781 if (view->managed_keys != NULL) 3782 dns_zone_detach(&view->managed_keys); 3783 dns_zone_attach(zone, &view->managed_keys); 3784 3785 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3786 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3787 "set up managed keys zone for view %s, file '%s'", 3788 view->name, filename); 3789 3790cleanup: 3791 if (zone != NULL) 3792 dns_zone_detach(&zone); 3793 if (none != NULL) 3794 dns_acl_detach(&none); 3795 3796 return (result); 3797} 3798 3799/* 3800 * Configure a single server quota. 3801 */ 3802static void 3803configure_server_quota(const cfg_obj_t **maps, const char *name, 3804 isc_quota_t *quota) 3805{ 3806 const cfg_obj_t *obj = NULL; 3807 isc_result_t result; 3808 3809 result = ns_config_get(maps, name, &obj); 3810 INSIST(result == ISC_R_SUCCESS); 3811 isc_quota_max(quota, cfg_obj_asuint32(obj)); 3812} 3813 3814/* 3815 * This function is called as soon as the 'directory' statement has been 3816 * parsed. This can be extended to support other options if necessary. 3817 */ 3818static isc_result_t 3819directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 3820 isc_result_t result; 3821 const char *directory; 3822 3823 REQUIRE(strcasecmp("directory", clausename) == 0); 3824 3825 UNUSED(arg); 3826 UNUSED(clausename); 3827 3828 /* 3829 * Change directory. 3830 */ 3831 directory = cfg_obj_asstring(obj); 3832 3833 if (! isc_file_ischdiridempotent(directory)) 3834 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 3835 "option 'directory' contains relative path '%s'", 3836 directory); 3837 3838 result = isc_dir_chdir(directory); 3839 if (result != ISC_R_SUCCESS) { 3840 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 3841 "change directory to '%s' failed: %s", 3842 directory, isc_result_totext(result)); 3843 return (result); 3844 } 3845 3846 return (ISC_R_SUCCESS); 3847} 3848 3849static void 3850scan_interfaces(ns_server_t *server, isc_boolean_t verbose) { 3851 isc_boolean_t match_mapped = server->aclenv.match_mapped; 3852 3853 ns_interfacemgr_scan(server->interfacemgr, verbose); 3854 /* 3855 * Update the "localhost" and "localnets" ACLs to match the 3856 * current set of network interfaces. 3857 */ 3858 dns_aclenv_copy(&server->aclenv, 3859 ns_interfacemgr_getaclenv(server->interfacemgr)); 3860 3861 server->aclenv.match_mapped = match_mapped; 3862} 3863 3864static isc_result_t 3865add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr, 3866 isc_boolean_t wcardport_ok) 3867{ 3868 ns_listenelt_t *lelt = NULL; 3869 dns_acl_t *src_acl = NULL; 3870 isc_result_t result; 3871 isc_sockaddr_t any_sa6; 3872 isc_netaddr_t netaddr; 3873 3874 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6); 3875 3876 isc_sockaddr_any6(&any_sa6); 3877 if (!isc_sockaddr_equal(&any_sa6, addr) && 3878 (wcardport_ok || isc_sockaddr_getport(addr) != 0)) { 3879 isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr); 3880 3881 result = dns_acl_create(mctx, 0, &src_acl); 3882 if (result != ISC_R_SUCCESS) 3883 return (result); 3884 3885 result = dns_iptable_addprefix(src_acl->iptable, 3886 &netaddr, 128, ISC_TRUE); 3887 if (result != ISC_R_SUCCESS) 3888 goto clean; 3889 3890 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr), 3891 src_acl, &lelt); 3892 if (result != ISC_R_SUCCESS) 3893 goto clean; 3894 ISC_LIST_APPEND(list->elts, lelt, link); 3895 } 3896 3897 return (ISC_R_SUCCESS); 3898 3899 clean: 3900 INSIST(lelt == NULL); 3901 dns_acl_detach(&src_acl); 3902 3903 return (result); 3904} 3905 3906/* 3907 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust() 3908 * to update the listening interfaces accordingly. 3909 * We currently only consider IPv6, because this only affects IPv6 wildcard 3910 * sockets. 3911 */ 3912static void 3913adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) { 3914 isc_result_t result; 3915 ns_listenlist_t *list = NULL; 3916 dns_view_t *view; 3917 dns_zone_t *zone, *next; 3918 isc_sockaddr_t addr, *addrp; 3919 3920 result = ns_listenlist_create(mctx, &list); 3921 if (result != ISC_R_SUCCESS) 3922 return; 3923 3924 for (view = ISC_LIST_HEAD(server->viewlist); 3925 view != NULL; 3926 view = ISC_LIST_NEXT(view, link)) { 3927 dns_dispatch_t *dispatch6; 3928 3929 dispatch6 = dns_resolver_dispatchv6(view->resolver); 3930 if (dispatch6 == NULL) 3931 continue; 3932 result = dns_dispatch_getlocaladdress(dispatch6, &addr); 3933 if (result != ISC_R_SUCCESS) 3934 goto fail; 3935 3936 /* 3937 * We always add non-wildcard address regardless of whether 3938 * the port is 'any' (the fourth arg is TRUE): if the port is 3939 * specific, we need to add it since it may conflict with a 3940 * listening interface; if it's zero, we'll dynamically open 3941 * query ports, and some of them may override an existing 3942 * wildcard IPv6 port. 3943 */ 3944 result = add_listenelt(mctx, list, &addr, ISC_TRUE); 3945 if (result != ISC_R_SUCCESS) 3946 goto fail; 3947 } 3948 3949 zone = NULL; 3950 for (result = dns_zone_first(server->zonemgr, &zone); 3951 result == ISC_R_SUCCESS; 3952 next = NULL, result = dns_zone_next(zone, &next), zone = next) { 3953 dns_view_t *zoneview; 3954 3955 /* 3956 * At this point the zone list may contain a stale zone 3957 * just removed from the configuration. To see the validity, 3958 * check if the corresponding view is in our current view list. 3959 * There may also be old zones that are still in the process 3960 * of shutting down and have detached from their old view 3961 * (zoneview == NULL). 3962 */ 3963 zoneview = dns_zone_getview(zone); 3964 if (zoneview == NULL) 3965 continue; 3966 for (view = ISC_LIST_HEAD(server->viewlist); 3967 view != NULL && view != zoneview; 3968 view = ISC_LIST_NEXT(view, link)) 3969 ; 3970 if (view == NULL) 3971 continue; 3972 3973 addrp = dns_zone_getnotifysrc6(zone); 3974 result = add_listenelt(mctx, list, addrp, ISC_FALSE); 3975 if (result != ISC_R_SUCCESS) 3976 goto fail; 3977 3978 addrp = dns_zone_getxfrsource6(zone); 3979 result = add_listenelt(mctx, list, addrp, ISC_FALSE); 3980 if (result != ISC_R_SUCCESS) 3981 goto fail; 3982 } 3983 3984 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE); 3985 3986 clean: 3987 ns_listenlist_detach(&list); 3988 return; 3989 3990 fail: 3991 /* 3992 * Even when we failed the procedure, most of other interfaces 3993 * should work correctly. We therefore just warn it. 3994 */ 3995 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3996 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 3997 "could not adjust the listen-on list; " 3998 "some interfaces may not work"); 3999 goto clean; 4000} 4001 4002/* 4003 * This event callback is invoked to do periodic network 4004 * interface scanning. 4005 */ 4006static void 4007interface_timer_tick(isc_task_t *task, isc_event_t *event) { 4008 isc_result_t result; 4009 ns_server_t *server = (ns_server_t *) event->ev_arg; 4010 INSIST(task == server->task); 4011 UNUSED(task); 4012 isc_event_free(&event); 4013 /* 4014 * XXX should scan interfaces unlocked and get exclusive access 4015 * only to replace ACLs. 4016 */ 4017 result = isc_task_beginexclusive(server->task); 4018 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4019 scan_interfaces(server, ISC_FALSE); 4020 isc_task_endexclusive(server->task); 4021} 4022 4023static void 4024heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) { 4025 ns_server_t *server = (ns_server_t *) event->ev_arg; 4026 dns_view_t *view; 4027 4028 UNUSED(task); 4029 isc_event_free(&event); 4030 view = ISC_LIST_HEAD(server->viewlist); 4031 while (view != NULL) { 4032 dns_view_dialup(view); 4033 view = ISC_LIST_NEXT(view, link); 4034 } 4035} 4036 4037static void 4038pps_timer_tick(isc_task_t *task, isc_event_t *event) { 4039 static unsigned int oldrequests = 0; 4040 unsigned int requests = ns_client_requests; 4041 4042 UNUSED(task); 4043 isc_event_free(&event); 4044 4045 /* 4046 * Don't worry about wrapping as the overflow result will be right. 4047 */ 4048 dns_pps = (requests - oldrequests) / 1200; 4049 oldrequests = requests; 4050} 4051 4052/* 4053 * Replace the current value of '*field', a dynamically allocated 4054 * string or NULL, with a dynamically allocated copy of the 4055 * null-terminated string pointed to by 'value', or NULL. 4056 */ 4057static isc_result_t 4058setstring(ns_server_t *server, char **field, const char *value) { 4059 char *copy; 4060 4061 if (value != NULL) { 4062 copy = isc_mem_strdup(server->mctx, value); 4063 if (copy == NULL) 4064 return (ISC_R_NOMEMORY); 4065 } else { 4066 copy = NULL; 4067 } 4068 4069 if (*field != NULL) 4070 isc_mem_free(server->mctx, *field); 4071 4072 *field = copy; 4073 return (ISC_R_SUCCESS); 4074} 4075 4076/* 4077 * Replace the current value of '*field', a dynamically allocated 4078 * string or NULL, with another dynamically allocated string 4079 * or NULL if whether 'obj' is a string or void value, respectively. 4080 */ 4081static isc_result_t 4082setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) { 4083 if (cfg_obj_isvoid(obj)) 4084 return (setstring(server, field, NULL)); 4085 else 4086 return (setstring(server, field, cfg_obj_asstring(obj))); 4087} 4088 4089static void 4090set_limit(const cfg_obj_t **maps, const char *configname, 4091 const char *description, isc_resource_t resourceid, 4092 isc_resourcevalue_t defaultvalue) 4093{ 4094 const cfg_obj_t *obj = NULL; 4095 const char *resource; 4096 isc_resourcevalue_t value; 4097 isc_result_t result; 4098 4099 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS) 4100 return; 4101 4102 if (cfg_obj_isstring(obj)) { 4103 resource = cfg_obj_asstring(obj); 4104 if (strcasecmp(resource, "unlimited") == 0) 4105 value = ISC_RESOURCE_UNLIMITED; 4106 else { 4107 INSIST(strcasecmp(resource, "default") == 0); 4108 value = defaultvalue; 4109 } 4110 } else 4111 value = cfg_obj_asuint64(obj); 4112 4113 result = isc_resource_setlimit(resourceid, value); 4114 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 4115 result == ISC_R_SUCCESS ? 4116 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING, 4117 "set maximum %s to %" ISC_PRINT_QUADFORMAT "u: %s", 4118 description, value, isc_result_totext(result)); 4119} 4120 4121#define SETLIMIT(cfgvar, resource, description) \ 4122 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \ 4123 ns_g_init ## resource) 4124 4125static void 4126set_limits(const cfg_obj_t **maps) { 4127 SETLIMIT("stacksize", stacksize, "stack size"); 4128 SETLIMIT("datasize", datasize, "data size"); 4129 SETLIMIT("coresize", coresize, "core size"); 4130 SETLIMIT("files", openfiles, "open files"); 4131} 4132 4133static void 4134portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, 4135 isc_boolean_t positive) 4136{ 4137 const cfg_listelt_t *element; 4138 4139 for (element = cfg_list_first(ports); 4140 element != NULL; 4141 element = cfg_list_next(element)) { 4142 const cfg_obj_t *obj = cfg_listelt_value(element); 4143 4144 if (cfg_obj_isuint32(obj)) { 4145 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 4146 4147 if (positive) 4148 isc_portset_add(portset, port); 4149 else 4150 isc_portset_remove(portset, port); 4151 } else { 4152 const cfg_obj_t *obj_loport, *obj_hiport; 4153 in_port_t loport, hiport; 4154 4155 obj_loport = cfg_tuple_get(obj, "loport"); 4156 loport = (in_port_t)cfg_obj_asuint32(obj_loport); 4157 obj_hiport = cfg_tuple_get(obj, "hiport"); 4158 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); 4159 4160 if (positive) 4161 isc_portset_addrange(portset, loport, hiport); 4162 else { 4163 isc_portset_removerange(portset, loport, 4164 hiport); 4165 } 4166 } 4167 } 4168} 4169 4170static isc_result_t 4171removed(dns_zone_t *zone, void *uap) { 4172 const char *type; 4173 4174 if (dns_zone_getview(zone) != uap) 4175 return (ISC_R_SUCCESS); 4176 4177 switch (dns_zone_gettype(zone)) { 4178 case dns_zone_master: 4179 type = "master"; 4180 break; 4181 case dns_zone_slave: 4182 type = "slave"; 4183 break; 4184 case dns_zone_stub: 4185 type = "stub"; 4186 break; 4187 case dns_zone_redirect: 4188 type = "redirect"; 4189 break; 4190 default: 4191 type = "other"; 4192 break; 4193 } 4194 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type); 4195 return (ISC_R_SUCCESS); 4196} 4197 4198static void 4199cleanup_session_key(ns_server_t *server, isc_mem_t *mctx) { 4200 if (server->session_keyfile != NULL) { 4201 isc_file_remove(server->session_keyfile); 4202 isc_mem_free(mctx, server->session_keyfile); 4203 server->session_keyfile = NULL; 4204 } 4205 4206 if (server->session_keyname != NULL) { 4207 if (dns_name_dynamic(server->session_keyname)) 4208 dns_name_free(server->session_keyname, mctx); 4209 isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); 4210 server->session_keyname = NULL; 4211 } 4212 4213 if (server->sessionkey != NULL) 4214 dns_tsigkey_detach(&server->sessionkey); 4215 4216 server->session_keyalg = DST_ALG_UNKNOWN; 4217 server->session_keybits = 0; 4218} 4219 4220static isc_result_t 4221generate_session_key(const char *filename, const char *keynamestr, 4222 dns_name_t *keyname, const char *algstr, 4223 dns_name_t *algname, unsigned int algtype, 4224 isc_uint16_t bits, isc_mem_t *mctx, 4225 dns_tsigkey_t **tsigkeyp) 4226{ 4227 isc_result_t result = ISC_R_SUCCESS; 4228 dst_key_t *key = NULL; 4229 isc_buffer_t key_txtbuffer; 4230 isc_buffer_t key_rawbuffer; 4231 char key_txtsecret[256]; 4232 char key_rawsecret[64]; 4233 isc_region_t key_rawregion; 4234 isc_stdtime_t now; 4235 dns_tsigkey_t *tsigkey = NULL; 4236 FILE *fp = NULL; 4237 4238 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4239 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4240 "generating session key for dynamic DNS"); 4241 4242 /* generate key */ 4243 result = dst_key_generate(keyname, algtype, bits, 1, 0, 4244 DNS_KEYPROTO_ANY, dns_rdataclass_in, 4245 mctx, &key); 4246 if (result != ISC_R_SUCCESS) 4247 return (result); 4248 4249 /* 4250 * Dump the key to the buffer for later use. Should be done before 4251 * we transfer the ownership of key to tsigkey. 4252 */ 4253 isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); 4254 CHECK(dst_key_tobuffer(key, &key_rawbuffer)); 4255 4256 isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); 4257 isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); 4258 CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); 4259 4260 /* Store the key in tsigkey. */ 4261 isc_stdtime_get(&now); 4262 CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key, 4263 ISC_FALSE, NULL, now, now, mctx, NULL, 4264 &tsigkey)); 4265 4266 /* Dump the key to the key file. */ 4267 fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, ISC_TRUE); 4268 if (fp == NULL) { 4269 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4270 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4271 "could not create %s", filename); 4272 result = ISC_R_NOPERM; 4273 goto cleanup; 4274 } 4275 4276 fprintf(fp, "key \"%s\" {\n" 4277 "\talgorithm %s;\n" 4278 "\tsecret \"%.*s\";\n};\n", keynamestr, algstr, 4279 (int) isc_buffer_usedlength(&key_txtbuffer), 4280 (char*) isc_buffer_base(&key_txtbuffer)); 4281 4282 RUNTIME_CHECK(isc_stdio_flush(fp) == ISC_R_SUCCESS); 4283 RUNTIME_CHECK(isc_stdio_close(fp) == ISC_R_SUCCESS); 4284 4285 dst_key_free(&key); 4286 4287 *tsigkeyp = tsigkey; 4288 4289 return (ISC_R_SUCCESS); 4290 4291 cleanup: 4292 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4293 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4294 "failed to generate session key " 4295 "for dynamic DNS: %s", isc_result_totext(result)); 4296 if (tsigkey != NULL) 4297 dns_tsigkey_detach(&tsigkey); 4298 if (key != NULL) 4299 dst_key_free(&key); 4300 4301 return (result); 4302} 4303 4304static isc_result_t 4305configure_session_key(const cfg_obj_t **maps, ns_server_t *server, 4306 isc_mem_t *mctx) 4307{ 4308 const char *keyfile, *keynamestr, *algstr; 4309 unsigned int algtype; 4310 dns_fixedname_t fname; 4311 dns_name_t *keyname, *algname; 4312 isc_buffer_t buffer; 4313 isc_uint16_t bits; 4314 const cfg_obj_t *obj; 4315 isc_boolean_t need_deleteold = ISC_FALSE; 4316 isc_boolean_t need_createnew = ISC_FALSE; 4317 isc_result_t result; 4318 4319 obj = NULL; 4320 result = ns_config_get(maps, "session-keyfile", &obj); 4321 if (result == ISC_R_SUCCESS) { 4322 if (cfg_obj_isvoid(obj)) 4323 keyfile = NULL; /* disable it */ 4324 else 4325 keyfile = cfg_obj_asstring(obj); 4326 } else 4327 keyfile = ns_g_defaultsessionkeyfile; 4328 4329 obj = NULL; 4330 result = ns_config_get(maps, "session-keyname", &obj); 4331 INSIST(result == ISC_R_SUCCESS); 4332 keynamestr = cfg_obj_asstring(obj); 4333 dns_fixedname_init(&fname); 4334 isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); 4335 isc_buffer_add(&buffer, strlen(keynamestr)); 4336 keyname = dns_fixedname_name(&fname); 4337 result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); 4338 if (result != ISC_R_SUCCESS) 4339 return (result); 4340 4341 obj = NULL; 4342 result = ns_config_get(maps, "session-keyalg", &obj); 4343 INSIST(result == ISC_R_SUCCESS); 4344 algstr = cfg_obj_asstring(obj); 4345 algname = NULL; 4346 result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits); 4347 if (result != ISC_R_SUCCESS) { 4348 const char *s = " (keeping current key)"; 4349 4350 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "session-keyalg: " 4351 "unsupported or unknown algorithm '%s'%s", 4352 algstr, 4353 server->session_keyfile != NULL ? s : ""); 4354 return (result); 4355 } 4356 4357 /* See if we need to (re)generate a new key. */ 4358 if (keyfile == NULL) { 4359 if (server->session_keyfile != NULL) 4360 need_deleteold = ISC_TRUE; 4361 } else if (server->session_keyfile == NULL) 4362 need_createnew = ISC_TRUE; 4363 else if (strcmp(keyfile, server->session_keyfile) != 0 || 4364 !dns_name_equal(server->session_keyname, keyname) || 4365 server->session_keyalg != algtype || 4366 server->session_keybits != bits) { 4367 need_deleteold = ISC_TRUE; 4368 need_createnew = ISC_TRUE; 4369 } 4370 4371 if (need_deleteold) { 4372 INSIST(server->session_keyfile != NULL); 4373 INSIST(server->session_keyname != NULL); 4374 INSIST(server->sessionkey != NULL); 4375 4376 cleanup_session_key(server, mctx); 4377 } 4378 4379 if (need_createnew) { 4380 INSIST(server->sessionkey == NULL); 4381 INSIST(server->session_keyfile == NULL); 4382 INSIST(server->session_keyname == NULL); 4383 INSIST(server->session_keyalg == DST_ALG_UNKNOWN); 4384 INSIST(server->session_keybits == 0); 4385 4386 server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); 4387 if (server->session_keyname == NULL) 4388 goto cleanup; 4389 dns_name_init(server->session_keyname, NULL); 4390 CHECK(dns_name_dup(keyname, mctx, server->session_keyname)); 4391 4392 server->session_keyfile = isc_mem_strdup(mctx, keyfile); 4393 if (server->session_keyfile == NULL) 4394 goto cleanup; 4395 4396 server->session_keyalg = algtype; 4397 server->session_keybits = bits; 4398 4399 CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr, 4400 algname, algtype, bits, mctx, 4401 &server->sessionkey)); 4402 } 4403 4404 return (result); 4405 4406 cleanup: 4407 cleanup_session_key(server, mctx); 4408 return (result); 4409} 4410 4411static isc_result_t 4412setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 4413 cfg_parser_t *parser, cfg_aclconfctx_t *actx) 4414{ 4415 isc_result_t result = ISC_R_SUCCESS; 4416 isc_boolean_t allow = ISC_FALSE; 4417 struct cfg_context *nzcfg = NULL; 4418 cfg_parser_t *nzparser = NULL; 4419 cfg_obj_t *nzconfig = NULL; 4420 const cfg_obj_t *maps[4]; 4421 const cfg_obj_t *options = NULL, *voptions = NULL; 4422 const cfg_obj_t *nz = NULL; 4423 int i = 0; 4424 4425 REQUIRE (config != NULL); 4426 4427 if (vconfig != NULL) 4428 voptions = cfg_tuple_get(vconfig, "options"); 4429 if (voptions != NULL) 4430 maps[i++] = voptions; 4431 result = cfg_map_get(config, "options", &options); 4432 if (result == ISC_R_SUCCESS) 4433 maps[i++] = options; 4434 maps[i++] = ns_g_defaults; 4435 maps[i] = NULL; 4436 4437 result = ns_config_get(maps, "allow-new-zones", &nz); 4438 if (result == ISC_R_SUCCESS) 4439 allow = cfg_obj_asboolean(nz); 4440 4441 if (!allow) { 4442 dns_view_setnewzones(view, ISC_FALSE, NULL, NULL); 4443 return (ISC_R_SUCCESS); 4444 } 4445 4446 nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); 4447 if (nzcfg == NULL) { 4448 dns_view_setnewzones(view, ISC_FALSE, NULL, NULL); 4449 return (ISC_R_NOMEMORY); 4450 } 4451 4452 dns_view_setnewzones(view, allow, nzcfg, newzone_cfgctx_destroy); 4453 4454 memset(nzcfg, 0, sizeof(*nzcfg)); 4455 isc_mem_attach(view->mctx, &nzcfg->mctx); 4456 cfg_obj_attach(config, &nzcfg->config); 4457 cfg_parser_attach(parser, &nzcfg->parser); 4458 cfg_aclconfctx_attach(actx, &nzcfg->actx); 4459 4460 /* 4461 * Attempt to create a parser and parse the newzones 4462 * file. If successful, preserve both; otherwise leave 4463 * them NULL. 4464 */ 4465 result = cfg_parser_create(view->mctx, ns_g_lctx, &nzparser); 4466 if (result == ISC_R_SUCCESS) 4467 result = cfg_parse_file(nzparser, view->new_zone_file, 4468 &cfg_type_newzones, &nzconfig); 4469 if (result == ISC_R_SUCCESS) { 4470 cfg_parser_attach(nzparser, &nzcfg->nzparser); 4471 cfg_obj_attach(nzconfig, &nzcfg->nzconfig); 4472 } 4473 4474 if (nzparser != NULL) { 4475 if (nzconfig != NULL) 4476 cfg_obj_destroy(nzparser, &nzconfig); 4477 cfg_parser_destroy(&nzparser); 4478 } 4479 4480 return (ISC_R_SUCCESS); 4481} 4482 4483static int 4484count_zones(const cfg_obj_t *conf) { 4485 const cfg_obj_t *zonelist = NULL; 4486 const cfg_listelt_t *element; 4487 int n = 0; 4488 4489 REQUIRE(conf != NULL); 4490 4491 cfg_map_get(conf, "zone", &zonelist); 4492 for (element = cfg_list_first(zonelist); 4493 element != NULL; 4494 element = cfg_list_next(element)) 4495 n++; 4496 4497 return (n); 4498} 4499 4500static isc_result_t 4501load_configuration(const char *filename, ns_server_t *server, 4502 isc_boolean_t first_time) 4503{ 4504 cfg_obj_t *config = NULL, *bindkeys = NULL; 4505 cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; 4506 const cfg_listelt_t *element; 4507 const cfg_obj_t *builtin_views; 4508 const cfg_obj_t *maps[3]; 4509 const cfg_obj_t *obj; 4510 const cfg_obj_t *options; 4511 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; 4512 const cfg_obj_t *views; 4513 dns_view_t *view = NULL; 4514 dns_view_t *view_next; 4515 dns_viewlist_t tmpviewlist; 4516 dns_viewlist_t viewlist, builtin_viewlist; 4517 in_port_t listen_port, udpport_low, udpport_high; 4518 int i; 4519 isc_interval_t interval; 4520 isc_portset_t *v4portset = NULL; 4521 isc_portset_t *v6portset = NULL; 4522 isc_resourcevalue_t nfiles; 4523 isc_result_t result; 4524 isc_uint32_t heartbeat_interval; 4525 isc_uint32_t interface_interval; 4526 isc_uint32_t reserved; 4527 isc_uint32_t udpsize; 4528 ns_cachelist_t cachelist, tmpcachelist; 4529 unsigned int maxsocks; 4530 ns_cache_t *nsc; 4531 struct cfg_context *nzctx; 4532 int num_zones = 0; 4533 isc_boolean_t exclusive = ISC_FALSE; 4534 4535 ISC_LIST_INIT(viewlist); 4536 ISC_LIST_INIT(builtin_viewlist); 4537 ISC_LIST_INIT(cachelist); 4538 4539 /* Create the ACL configuration context */ 4540 if (ns_g_aclconfctx != NULL) 4541 cfg_aclconfctx_detach(&ns_g_aclconfctx); 4542 CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx)); 4543 4544 /* 4545 * Parse the global default pseudo-config file. 4546 */ 4547 if (first_time) { 4548 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); 4549 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", 4550 &ns_g_defaults) == ISC_R_SUCCESS); 4551 } 4552 4553 /* 4554 * Parse the configuration file using the new config code. 4555 */ 4556 result = ISC_R_FAILURE; 4557 config = NULL; 4558 4559 /* 4560 * Unless this is lwresd with the -C option, parse the config file. 4561 */ 4562 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) { 4563 isc_log_write(ns_g_lctx, 4564 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 4565 ISC_LOG_INFO, "loading configuration from '%s'", 4566 filename); 4567 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); 4568 cfg_parser_setcallback(conf_parser, directory_callback, NULL); 4569 result = cfg_parse_file(conf_parser, filename, 4570 &cfg_type_namedconf, &config); 4571 } 4572 4573 /* 4574 * If this is lwresd with the -C option, or lwresd with no -C or -c 4575 * option where the above parsing failed, parse resolv.conf. 4576 */ 4577 if (ns_g_lwresdonly && 4578 (lwresd_g_useresolvconf || 4579 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND))) 4580 { 4581 isc_log_write(ns_g_lctx, 4582 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 4583 ISC_LOG_INFO, "loading configuration from '%s'", 4584 lwresd_g_resolvconffile); 4585 if (conf_parser != NULL) 4586 cfg_parser_destroy(&conf_parser); 4587 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); 4588 result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser, 4589 &config); 4590 } 4591 CHECK(result); 4592 4593 /* 4594 * Check the validity of the configuration. 4595 */ 4596 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx)); 4597 4598 /* 4599 * Fill in the maps array, used for resolving defaults. 4600 */ 4601 i = 0; 4602 options = NULL; 4603 result = cfg_map_get(config, "options", &options); 4604 if (result == ISC_R_SUCCESS) 4605 maps[i++] = options; 4606 maps[i++] = ns_g_defaults; 4607 maps[i] = NULL; 4608 4609 /* 4610 * If bind.keys exists, load it. If "dnssec-lookaside auto" 4611 * is turned on, the keys found there will be used as default 4612 * trust anchors. 4613 */ 4614 obj = NULL; 4615 result = ns_config_get(maps, "bindkeys-file", &obj); 4616 INSIST(result == ISC_R_SUCCESS); 4617 CHECKM(setstring(server, &server->bindkeysfile, 4618 cfg_obj_asstring(obj)), "strdup"); 4619 4620 if (access(server->bindkeysfile, R_OK) == 0) { 4621 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4622 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4623 "reading built-in trusted " 4624 "keys from file '%s'", server->bindkeysfile); 4625 4626 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, 4627 &bindkeys_parser)); 4628 4629 result = cfg_parse_file(bindkeys_parser, server->bindkeysfile, 4630 &cfg_type_bindkeys, &bindkeys); 4631 CHECK(result); 4632 } 4633 4634 /* Ensure exclusive access to configuration data. */ 4635 if (!exclusive) { 4636 result = isc_task_beginexclusive(server->task); 4637 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4638 exclusive = ISC_TRUE; 4639 } 4640 4641 /* 4642 * Set process limits, which (usually) needs to be done as root. 4643 */ 4644 set_limits(maps); 4645 4646 /* 4647 * Check if max number of open sockets that the system allows is 4648 * sufficiently large. Failing this condition is not necessarily fatal, 4649 * but may cause subsequent runtime failures for a busy recursive 4650 * server. 4651 */ 4652 result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks); 4653 if (result != ISC_R_SUCCESS) 4654 maxsocks = 0; 4655 result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles); 4656 if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) { 4657 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4658 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 4659 "max open files (%" ISC_PRINT_QUADFORMAT "u)" 4660 " is smaller than max sockets (%u)", 4661 nfiles, maxsocks); 4662 } 4663 4664 /* 4665 * Set the number of socket reserved for TCP, stdio etc. 4666 */ 4667 obj = NULL; 4668 result = ns_config_get(maps, "reserved-sockets", &obj); 4669 INSIST(result == ISC_R_SUCCESS); 4670 reserved = cfg_obj_asuint32(obj); 4671 if (maxsocks != 0) { 4672 if (maxsocks < 128U) /* Prevent underflow. */ 4673 reserved = 0; 4674 else if (reserved > maxsocks - 128U) /* Minimum UDP space. */ 4675 reserved = maxsocks - 128; 4676 } 4677 /* Minimum TCP/stdio space. */ 4678 if (reserved < 128U) 4679 reserved = 128; 4680 if (reserved + 128U > maxsocks && maxsocks != 0) { 4681 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4682 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 4683 "less than 128 UDP sockets available after " 4684 "applying 'reserved-sockets' and 'maxsockets'"); 4685 } 4686 isc__socketmgr_setreserved(ns_g_socketmgr, reserved); 4687 4688 /* 4689 * Configure various server options. 4690 */ 4691 configure_server_quota(maps, "transfers-out", &server->xfroutquota); 4692 configure_server_quota(maps, "tcp-clients", &server->tcpquota); 4693 configure_server_quota(maps, "recursive-clients", 4694 &server->recursionquota); 4695 if (server->recursionquota.max > 1000) 4696 isc_quota_soft(&server->recursionquota, 4697 server->recursionquota.max - 100); 4698 else 4699 isc_quota_soft(&server->recursionquota, 0); 4700 4701 CHECK(configure_view_acl(NULL, config, "blackhole", NULL, 4702 ns_g_aclconfctx, ns_g_mctx, 4703 &server->blackholeacl)); 4704 if (server->blackholeacl != NULL) 4705 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, 4706 server->blackholeacl); 4707 4708 obj = NULL; 4709 result = ns_config_get(maps, "match-mapped-addresses", &obj); 4710 INSIST(result == ISC_R_SUCCESS); 4711 server->aclenv.match_mapped = cfg_obj_asboolean(obj); 4712 4713 CHECKM(ns_statschannels_configure(ns_g_server, config, ns_g_aclconfctx), 4714 "configuring statistics server(s)"); 4715 4716 /* 4717 * Configure sets of UDP query source ports. 4718 */ 4719 CHECKM(isc_portset_create(ns_g_mctx, &v4portset), 4720 "creating UDP port set"); 4721 CHECKM(isc_portset_create(ns_g_mctx, &v6portset), 4722 "creating UDP port set"); 4723 4724 usev4ports = NULL; 4725 usev6ports = NULL; 4726 avoidv4ports = NULL; 4727 avoidv6ports = NULL; 4728 4729 (void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports); 4730 if (usev4ports != NULL) 4731 portset_fromconf(v4portset, usev4ports, ISC_TRUE); 4732 else { 4733 CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low, 4734 &udpport_high), 4735 "get the default UDP/IPv4 port range"); 4736 if (udpport_low == udpport_high) 4737 isc_portset_add(v4portset, udpport_low); 4738 else { 4739 isc_portset_addrange(v4portset, udpport_low, 4740 udpport_high); 4741 } 4742 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4743 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4744 "using default UDP/IPv4 port range: [%d, %d]", 4745 udpport_low, udpport_high); 4746 } 4747 (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); 4748 if (avoidv4ports != NULL) 4749 portset_fromconf(v4portset, avoidv4ports, ISC_FALSE); 4750 4751 (void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports); 4752 if (usev6ports != NULL) 4753 portset_fromconf(v6portset, usev6ports, ISC_TRUE); 4754 else { 4755 CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low, 4756 &udpport_high), 4757 "get the default UDP/IPv6 port range"); 4758 if (udpport_low == udpport_high) 4759 isc_portset_add(v6portset, udpport_low); 4760 else { 4761 isc_portset_addrange(v6portset, udpport_low, 4762 udpport_high); 4763 } 4764 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4765 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4766 "using default UDP/IPv6 port range: [%d, %d]", 4767 udpport_low, udpport_high); 4768 } 4769 (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); 4770 if (avoidv6ports != NULL) 4771 portset_fromconf(v6portset, avoidv6ports, ISC_FALSE); 4772 4773 dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset); 4774 4775 /* 4776 * Set the EDNS UDP size when we don't match a view. 4777 */ 4778 obj = NULL; 4779 result = ns_config_get(maps, "edns-udp-size", &obj); 4780 INSIST(result == ISC_R_SUCCESS); 4781 udpsize = cfg_obj_asuint32(obj); 4782 if (udpsize < 512) 4783 udpsize = 512; 4784 if (udpsize > 4096) 4785 udpsize = 4096; 4786 ns_g_udpsize = (isc_uint16_t)udpsize; 4787 4788 /* 4789 * Configure the zone manager. 4790 */ 4791 obj = NULL; 4792 result = ns_config_get(maps, "transfers-in", &obj); 4793 INSIST(result == ISC_R_SUCCESS); 4794 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 4795 4796 obj = NULL; 4797 result = ns_config_get(maps, "transfers-per-ns", &obj); 4798 INSIST(result == ISC_R_SUCCESS); 4799 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 4800 4801 obj = NULL; 4802 result = ns_config_get(maps, "serial-query-rate", &obj); 4803 INSIST(result == ISC_R_SUCCESS); 4804 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 4805 4806 /* 4807 * Determine which port to use for listening for incoming connections. 4808 */ 4809 if (ns_g_port != 0) 4810 listen_port = ns_g_port; 4811 else 4812 CHECKM(ns_config_getport(config, &listen_port), "port"); 4813 4814 /* 4815 * Find the listen queue depth. 4816 */ 4817 obj = NULL; 4818 result = ns_config_get(maps, "tcp-listen-queue", &obj); 4819 INSIST(result == ISC_R_SUCCESS); 4820 ns_g_listen = cfg_obj_asuint32(obj); 4821 if (ns_g_listen < 3) 4822 ns_g_listen = 3; 4823 4824 /* 4825 * Configure the interface manager according to the "listen-on" 4826 * statement. 4827 */ 4828 { 4829 const cfg_obj_t *clistenon = NULL; 4830 ns_listenlist_t *listenon = NULL; 4831 4832 clistenon = NULL; 4833 /* 4834 * Even though listen-on is present in the default 4835 * configuration, we can't use it here, since it isn't 4836 * used if we're in lwresd mode. This way is easier. 4837 */ 4838 if (options != NULL) 4839 (void)cfg_map_get(options, "listen-on", &clistenon); 4840 if (clistenon != NULL) { 4841 /* check return code? */ 4842 (void)ns_listenlist_fromconfig(clistenon, config, 4843 ns_g_aclconfctx, 4844 ns_g_mctx, &listenon); 4845 } else if (!ns_g_lwresdonly) { 4846 /* 4847 * Not specified, use default. 4848 */ 4849 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 4850 ISC_TRUE, &listenon)); 4851 } 4852 if (listenon != NULL) { 4853 ns_interfacemgr_setlistenon4(server->interfacemgr, 4854 listenon); 4855 ns_listenlist_detach(&listenon); 4856 } 4857 } 4858 /* 4859 * Ditto for IPv6. 4860 */ 4861 { 4862 const cfg_obj_t *clistenon = NULL; 4863 ns_listenlist_t *listenon = NULL; 4864 4865 if (options != NULL) 4866 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 4867 if (clistenon != NULL) { 4868 /* check return code? */ 4869 (void)ns_listenlist_fromconfig(clistenon, config, 4870 ns_g_aclconfctx, 4871 ns_g_mctx, &listenon); 4872 } else if (!ns_g_lwresdonly) { 4873 isc_boolean_t enable; 4874 /* 4875 * Not specified, use default. 4876 */ 4877 enable = ISC_TF(isc_net_probeipv4() != ISC_R_SUCCESS); 4878 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 4879 enable, &listenon)); 4880 } 4881 if (listenon != NULL) { 4882 ns_interfacemgr_setlistenon6(server->interfacemgr, 4883 listenon); 4884 ns_listenlist_detach(&listenon); 4885 } 4886 } 4887 4888 /* 4889 * Rescan the interface list to pick up changes in the 4890 * listen-on option. It's important that we do this before we try 4891 * to configure the query source, since the dispatcher we use might 4892 * be shared with an interface. 4893 */ 4894 scan_interfaces(server, ISC_TRUE); 4895 4896 /* 4897 * Arrange for further interface scanning to occur periodically 4898 * as specified by the "interface-interval" option. 4899 */ 4900 obj = NULL; 4901 result = ns_config_get(maps, "interface-interval", &obj); 4902 INSIST(result == ISC_R_SUCCESS); 4903 interface_interval = cfg_obj_asuint32(obj) * 60; 4904 if (interface_interval == 0) { 4905 CHECK(isc_timer_reset(server->interface_timer, 4906 isc_timertype_inactive, 4907 NULL, NULL, ISC_TRUE)); 4908 } else if (server->interface_interval != interface_interval) { 4909 isc_interval_set(&interval, interface_interval, 0); 4910 CHECK(isc_timer_reset(server->interface_timer, 4911 isc_timertype_ticker, 4912 NULL, &interval, ISC_FALSE)); 4913 } 4914 server->interface_interval = interface_interval; 4915 4916 /* 4917 * Configure the dialup heartbeat timer. 4918 */ 4919 obj = NULL; 4920 result = ns_config_get(maps, "heartbeat-interval", &obj); 4921 INSIST(result == ISC_R_SUCCESS); 4922 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 4923 if (heartbeat_interval == 0) { 4924 CHECK(isc_timer_reset(server->heartbeat_timer, 4925 isc_timertype_inactive, 4926 NULL, NULL, ISC_TRUE)); 4927 } else if (server->heartbeat_interval != heartbeat_interval) { 4928 isc_interval_set(&interval, heartbeat_interval, 0); 4929 CHECK(isc_timer_reset(server->heartbeat_timer, 4930 isc_timertype_ticker, 4931 NULL, &interval, ISC_FALSE)); 4932 } 4933 server->heartbeat_interval = heartbeat_interval; 4934 4935 isc_interval_set(&interval, 1200, 0); 4936 CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL, 4937 &interval, ISC_FALSE)); 4938 4939 /* 4940 * Write the PID file. 4941 */ 4942 obj = NULL; 4943 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) 4944 if (cfg_obj_isvoid(obj)) 4945 ns_os_writepidfile(NULL, first_time); 4946 else 4947 ns_os_writepidfile(cfg_obj_asstring(obj), first_time); 4948 else if (ns_g_lwresdonly) 4949 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); 4950 else 4951 ns_os_writepidfile(ns_g_defaultpidfile, first_time); 4952 4953 /* 4954 * Configure the server-wide session key. This must be done before 4955 * configure views because zone configuration may need to know 4956 * session-keyname. 4957 * 4958 * Failure of session key generation isn't fatal at this time; if it 4959 * turns out that a session key is really needed but doesn't exist, 4960 * we'll treat it as a fatal error then. 4961 */ 4962 (void)configure_session_key(maps, server, ns_g_mctx); 4963 4964 views = NULL; 4965 (void)cfg_map_get(config, "view", &views); 4966 4967 /* 4968 * Create the views and count all the configured zones in 4969 * order to correctly size the zone manager's task table. 4970 * (We only count zones for configured views; the built-in 4971 * "bind" view can be ignored as it only adds a negligible 4972 * number of zones.) 4973 * 4974 * If we're allowing new zones, we need to be able to find the 4975 * new zone file and count those as well. So we setup the new 4976 * zone configuration context, but otherwise view configuration 4977 * waits until after the zone manager's task list has been sized. 4978 */ 4979 for (element = cfg_list_first(views); 4980 element != NULL; 4981 element = cfg_list_next(element)) 4982 { 4983 cfg_obj_t *vconfig = cfg_listelt_value(element); 4984 const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options"); 4985 view = NULL; 4986 4987 CHECK(create_view(vconfig, &viewlist, &view)); 4988 INSIST(view != NULL); 4989 4990 num_zones += count_zones(voptions); 4991 CHECK(setup_newzones(view, config, vconfig, conf_parser, 4992 ns_g_aclconfctx)); 4993 4994 nzctx = view->new_zone_config; 4995 if (nzctx != NULL && nzctx->nzconfig != NULL) 4996 num_zones += count_zones(nzctx->nzconfig); 4997 4998 dns_view_detach(&view); 4999 } 5000 5001 /* 5002 * If there were no explicit views then we do the default 5003 * view here. 5004 */ 5005 if (views == NULL) { 5006 CHECK(create_view(NULL, &viewlist, &view)); 5007 INSIST(view != NULL); 5008 5009 num_zones = count_zones(config); 5010 5011 CHECK(setup_newzones(view, config, NULL, conf_parser, 5012 ns_g_aclconfctx)); 5013 5014 nzctx = view->new_zone_config; 5015 if (nzctx != NULL && nzctx->nzconfig != NULL) 5016 num_zones += count_zones(nzctx->nzconfig); 5017 5018 dns_view_detach(&view); 5019 } 5020 5021 /* 5022 * Zones have been counted; set the zone manager task pool size. 5023 */ 5024 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5025 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5026 "sizing zone task pool based on %d zones", num_zones); 5027 CHECK(dns_zonemgr_setsize(ns_g_server->zonemgr, num_zones)); 5028 5029 /* 5030 * Configure and freeze all explicit views. Explicit 5031 * views that have zones were already created at parsing 5032 * time, but views with no zones must be created here. 5033 */ 5034 for (element = cfg_list_first(views); 5035 element != NULL; 5036 element = cfg_list_next(element)) 5037 { 5038 cfg_obj_t *vconfig = cfg_listelt_value(element); 5039 5040 view = NULL; 5041 CHECK(find_view(vconfig, &viewlist, &view)); 5042 CHECK(configure_view(view, config, vconfig, 5043 &cachelist, bindkeys, ns_g_mctx, 5044 ns_g_aclconfctx, ISC_TRUE)); 5045 dns_view_freeze(view); 5046 dns_view_detach(&view); 5047 } 5048 5049 /* 5050 * Make sure we have a default view if and only if there 5051 * were no explicit views. 5052 */ 5053 if (views == NULL) { 5054 view = NULL; 5055 CHECK(find_view(NULL, &viewlist, &view)); 5056 CHECK(configure_view(view, config, NULL, 5057 &cachelist, bindkeys, 5058 ns_g_mctx, ns_g_aclconfctx, ISC_TRUE)); 5059 dns_view_freeze(view); 5060 dns_view_detach(&view); 5061 } 5062 5063 /* 5064 * Create (or recreate) the built-in views. 5065 */ 5066 builtin_views = NULL; 5067 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view", 5068 &builtin_views) == ISC_R_SUCCESS); 5069 for (element = cfg_list_first(builtin_views); 5070 element != NULL; 5071 element = cfg_list_next(element)) 5072 { 5073 cfg_obj_t *vconfig = cfg_listelt_value(element); 5074 5075 CHECK(create_view(vconfig, &builtin_viewlist, &view)); 5076 CHECK(configure_view(view, config, vconfig, 5077 &cachelist, bindkeys, 5078 ns_g_mctx, ns_g_aclconfctx, ISC_FALSE)); 5079 dns_view_freeze(view); 5080 dns_view_detach(&view); 5081 view = NULL; 5082 } 5083 5084 /* Now combine the two viewlists into one */ 5085 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 5086 5087 /* Swap our new view list with the production one. */ 5088 tmpviewlist = server->viewlist; 5089 server->viewlist = viewlist; 5090 viewlist = tmpviewlist; 5091 5092 /* Make the view list available to each of the views */ 5093 view = ISC_LIST_HEAD(server->viewlist); 5094 while (view != NULL) { 5095 view->viewlist = &server->viewlist; 5096 view = ISC_LIST_NEXT(view, link); 5097 } 5098 5099 /* Swap our new cache list with the production one. */ 5100 tmpcachelist = server->cachelist; 5101 server->cachelist = cachelist; 5102 cachelist = tmpcachelist; 5103 5104 /* Load the TKEY information from the configuration. */ 5105 if (options != NULL) { 5106 dns_tkeyctx_t *t = NULL; 5107 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, 5108 &t), 5109 "configuring TKEY"); 5110 if (server->tkeyctx != NULL) 5111 dns_tkeyctx_destroy(&server->tkeyctx); 5112 server->tkeyctx = t; 5113 } 5114 5115 /* 5116 * Bind the control port(s). 5117 */ 5118 CHECKM(ns_controls_configure(ns_g_server->controls, config, 5119 ns_g_aclconfctx), 5120 "binding control channel(s)"); 5121 5122 /* 5123 * Bind the lwresd port(s). 5124 */ 5125 CHECKM(ns_lwresd_configure(ns_g_mctx, config), 5126 "binding lightweight resolver ports"); 5127 5128 /* 5129 * Open the source of entropy. 5130 */ 5131 if (first_time) { 5132 obj = NULL; 5133 result = ns_config_get(maps, "random-device", &obj); 5134 if (result != ISC_R_SUCCESS) { 5135 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5136 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5137 "no source of entropy found"); 5138 } else { 5139 const char *randomdev = cfg_obj_asstring(obj); 5140 result = isc_entropy_createfilesource(ns_g_entropy, 5141 randomdev); 5142 if (result != ISC_R_SUCCESS) 5143 isc_log_write(ns_g_lctx, 5144 NS_LOGCATEGORY_GENERAL, 5145 NS_LOGMODULE_SERVER, 5146 ISC_LOG_INFO, 5147 "could not open entropy source " 5148 "%s: %s", 5149 randomdev, 5150 isc_result_totext(result)); 5151#ifdef PATH_RANDOMDEV 5152 if (ns_g_fallbackentropy != NULL) { 5153 if (result != ISC_R_SUCCESS) { 5154 isc_log_write(ns_g_lctx, 5155 NS_LOGCATEGORY_GENERAL, 5156 NS_LOGMODULE_SERVER, 5157 ISC_LOG_INFO, 5158 "using pre-chroot entropy source " 5159 "%s", 5160 PATH_RANDOMDEV); 5161 isc_entropy_detach(&ns_g_entropy); 5162 isc_entropy_attach(ns_g_fallbackentropy, 5163 &ns_g_entropy); 5164 } 5165 isc_entropy_detach(&ns_g_fallbackentropy); 5166 } 5167#endif 5168 } 5169 } 5170 5171 /* 5172 * Relinquish root privileges. 5173 */ 5174 if (first_time) 5175 ns_os_changeuser(); 5176 5177 /* 5178 * Check that the working directory is writable. 5179 */ 5180 if (access(".", W_OK) != 0) { 5181 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5182 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 5183 "the working directory is not writable"); 5184 } 5185 5186 /* 5187 * Configure the logging system. 5188 * 5189 * Do this after changing UID to make sure that any log 5190 * files specified in named.conf get created by the 5191 * unprivileged user, not root. 5192 */ 5193 if (ns_g_logstderr) { 5194 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5195 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5196 "ignoring config file logging " 5197 "statement due to -g option"); 5198 } else { 5199 const cfg_obj_t *logobj = NULL; 5200 isc_logconfig_t *logc = NULL; 5201 5202 CHECKM(isc_logconfig_create(ns_g_lctx, &logc), 5203 "creating new logging configuration"); 5204 5205 logobj = NULL; 5206 (void)cfg_map_get(config, "logging", &logobj); 5207 if (logobj != NULL) { 5208 CHECKM(ns_log_configure(logc, logobj), 5209 "configuring logging"); 5210 } else { 5211 CHECKM(ns_log_setdefaultchannels(logc), 5212 "setting up default logging channels"); 5213 CHECKM(ns_log_setunmatchedcategory(logc), 5214 "setting up default 'category unmatched'"); 5215 CHECKM(ns_log_setdefaultcategory(logc), 5216 "setting up default 'category default'"); 5217 } 5218 5219 result = isc_logconfig_use(ns_g_lctx, logc); 5220 if (result != ISC_R_SUCCESS) { 5221 isc_logconfig_destroy(&logc); 5222 CHECKM(result, "installing logging configuration"); 5223 } 5224 5225 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5226 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 5227 "now using logging configuration from " 5228 "config file"); 5229 } 5230 5231 /* 5232 * Set the default value of the query logging flag depending 5233 * whether a "queries" category has been defined. This is 5234 * a disgusting hack, but we need to do this for BIND 8 5235 * compatibility. 5236 */ 5237 if (first_time) { 5238 const cfg_obj_t *logobj = NULL; 5239 const cfg_obj_t *categories = NULL; 5240 5241 obj = NULL; 5242 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 5243 server->log_queries = cfg_obj_asboolean(obj); 5244 } else { 5245 5246 (void)cfg_map_get(config, "logging", &logobj); 5247 if (logobj != NULL) 5248 (void)cfg_map_get(logobj, "category", 5249 &categories); 5250 if (categories != NULL) { 5251 const cfg_listelt_t *element; 5252 for (element = cfg_list_first(categories); 5253 element != NULL; 5254 element = cfg_list_next(element)) 5255 { 5256 const cfg_obj_t *catobj; 5257 const char *str; 5258 5259 obj = cfg_listelt_value(element); 5260 catobj = cfg_tuple_get(obj, "name"); 5261 str = cfg_obj_asstring(catobj); 5262 if (strcasecmp(str, "queries") == 0) 5263 server->log_queries = ISC_TRUE; 5264 } 5265 } 5266 } 5267 } 5268 5269 5270 obj = NULL; 5271 if (options != NULL && 5272 cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) 5273 ns_g_memstatistics = cfg_obj_asboolean(obj); 5274 else 5275 ns_g_memstatistics = 5276 ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0); 5277 5278 obj = NULL; 5279 if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) 5280 ns_main_setmemstats(cfg_obj_asstring(obj)); 5281 else if (ns_g_memstatistics) 5282 ns_main_setmemstats("named.memstats"); 5283 else 5284 ns_main_setmemstats(NULL); 5285 5286 obj = NULL; 5287 result = ns_config_get(maps, "statistics-file", &obj); 5288 INSIST(result == ISC_R_SUCCESS); 5289 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)), 5290 "strdup"); 5291 5292 obj = NULL; 5293 result = ns_config_get(maps, "dump-file", &obj); 5294 INSIST(result == ISC_R_SUCCESS); 5295 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)), 5296 "strdup"); 5297 5298 obj = NULL; 5299 result = ns_config_get(maps, "secroots-file", &obj); 5300 INSIST(result == ISC_R_SUCCESS); 5301 CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)), 5302 "strdup"); 5303 5304 obj = NULL; 5305 result = ns_config_get(maps, "recursing-file", &obj); 5306 INSIST(result == ISC_R_SUCCESS); 5307 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), 5308 "strdup"); 5309 5310 obj = NULL; 5311 result = ns_config_get(maps, "version", &obj); 5312 if (result == ISC_R_SUCCESS) { 5313 CHECKM(setoptstring(server, &server->version, obj), "strdup"); 5314 server->version_set = ISC_TRUE; 5315 } else { 5316 server->version_set = ISC_FALSE; 5317 } 5318 5319 obj = NULL; 5320 result = ns_config_get(maps, "hostname", &obj); 5321 if (result == ISC_R_SUCCESS) { 5322 CHECKM(setoptstring(server, &server->hostname, obj), "strdup"); 5323 server->hostname_set = ISC_TRUE; 5324 } else { 5325 server->hostname_set = ISC_FALSE; 5326 } 5327 5328 obj = NULL; 5329 result = ns_config_get(maps, "server-id", &obj); 5330 server->server_usehostname = ISC_FALSE; 5331 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 5332 /* The parser translates "hostname" to ISC_TRUE */ 5333 server->server_usehostname = cfg_obj_asboolean(obj); 5334 result = setstring(server, &server->server_id, NULL); 5335 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5336 } else if (result == ISC_R_SUCCESS) { 5337 /* Found a quoted string */ 5338 CHECKM(setoptstring(server, &server->server_id, obj), "strdup"); 5339 } else { 5340 result = setstring(server, &server->server_id, NULL); 5341 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5342 } 5343 5344 obj = NULL; 5345 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj); 5346 if (result == ISC_R_SUCCESS) { 5347 server->flushonshutdown = cfg_obj_asboolean(obj); 5348 } else { 5349 server->flushonshutdown = ISC_FALSE; 5350 } 5351 5352 result = ISC_R_SUCCESS; 5353 5354 cleanup: 5355 if (v4portset != NULL) 5356 isc_portset_destroy(ns_g_mctx, &v4portset); 5357 5358 if (v6portset != NULL) 5359 isc_portset_destroy(ns_g_mctx, &v6portset); 5360 5361 if (conf_parser != NULL) { 5362 if (config != NULL) 5363 cfg_obj_destroy(conf_parser, &config); 5364 cfg_parser_destroy(&conf_parser); 5365 } 5366 5367 if (bindkeys_parser != NULL) { 5368 if (bindkeys != NULL) 5369 cfg_obj_destroy(bindkeys_parser, &bindkeys); 5370 cfg_parser_destroy(&bindkeys_parser); 5371 } 5372 5373 if (view != NULL) 5374 dns_view_detach(&view); 5375 5376 /* 5377 * This cleans up either the old production view list 5378 * or our temporary list depending on whether they 5379 * were swapped above or not. 5380 */ 5381 for (view = ISC_LIST_HEAD(viewlist); 5382 view != NULL; 5383 view = view_next) { 5384 view_next = ISC_LIST_NEXT(view, link); 5385 ISC_LIST_UNLINK(viewlist, view, link); 5386 if (result == ISC_R_SUCCESS && 5387 strcmp(view->name, "_bind") != 0) 5388 (void)dns_zt_apply(view->zonetable, ISC_FALSE, 5389 removed, view); 5390 dns_view_detach(&view); 5391 } 5392 5393 /* Same cleanup for cache list. */ 5394 while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { 5395 ISC_LIST_UNLINK(cachelist, nsc, link); 5396 dns_cache_detach(&nsc->cache); 5397 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 5398 } 5399 5400 /* 5401 * Adjust the listening interfaces in accordance with the source 5402 * addresses specified in views and zones. 5403 */ 5404 if (isc_net_probeipv6() == ISC_R_SUCCESS) 5405 adjust_interfaces(server, ns_g_mctx); 5406 5407 /* Relinquish exclusive access to configuration data. */ 5408 if (exclusive) 5409 isc_task_endexclusive(server->task); 5410 5411 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 5412 ISC_LOG_DEBUG(1), "load_configuration: %s", 5413 isc_result_totext(result)); 5414 5415 return (result); 5416} 5417 5418static isc_result_t 5419view_loaded(void *arg) { 5420 isc_result_t result; 5421 ns_zoneload_t *zl = (ns_zoneload_t *) arg; 5422 ns_server_t *server = zl->server; 5423 unsigned int refs; 5424 5425 5426 /* 5427 * Force zone maintenance. Do this after loading 5428 * so that we know when we need to force AXFR of 5429 * slave zones whose master files are missing. 5430 * 5431 * We use the zoneload reference counter to let us 5432 * know when all views are finished. 5433 */ 5434 isc_refcount_decrement(&zl->refs, &refs); 5435 if (refs != 0) 5436 return (ISC_R_SUCCESS); 5437 5438 isc_refcount_destroy(&zl->refs); 5439 isc_mem_put(server->mctx, zl, sizeof (*zl)); 5440 5441 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 5442 ISC_LOG_NOTICE, "all zones loaded"); 5443 CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), 5444 "forcing zone maintenance"); 5445 5446 ns_os_started(); 5447 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 5448 ISC_LOG_NOTICE, "running"); 5449 5450 return (ISC_R_SUCCESS); 5451} 5452 5453static isc_result_t 5454load_zones(ns_server_t *server) { 5455 isc_result_t result; 5456 dns_view_t *view; 5457 ns_zoneload_t *zl; 5458 unsigned int refs = 0; 5459 5460 zl = isc_mem_get(server->mctx, sizeof (*zl)); 5461 if (zl == NULL) 5462 return (ISC_R_NOMEMORY); 5463 zl->server = server; 5464 5465 result = isc_task_beginexclusive(server->task); 5466 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5467 5468 isc_refcount_init(&zl->refs, 1); 5469 5470 /* 5471 * Schedule zones to be loaded from disk. 5472 */ 5473 for (view = ISC_LIST_HEAD(server->viewlist); 5474 view != NULL; 5475 view = ISC_LIST_NEXT(view, link)) 5476 { 5477 if (view->managed_keys != NULL) { 5478 result = dns_zone_load(view->managed_keys); 5479 if (result != ISC_R_SUCCESS && 5480 result != DNS_R_UPTODATE && 5481 result != DNS_R_CONTINUE) 5482 goto cleanup; 5483 } 5484 if (view->redirect != NULL) { 5485 result = dns_zone_load(view->redirect); 5486 if (result != ISC_R_SUCCESS && 5487 result != DNS_R_UPTODATE && 5488 result != DNS_R_CONTINUE) 5489 goto cleanup; 5490 } 5491 5492 /* 5493 * 'dns_view_asyncload' calls view_loaded if there are no 5494 * zones. 5495 */ 5496 isc_refcount_increment(&zl->refs, NULL); 5497 CHECK(dns_view_asyncload(view, view_loaded, zl)); 5498 } 5499 5500 cleanup: 5501 isc_refcount_decrement(&zl->refs, &refs); 5502 if (refs == 0) { 5503 isc_refcount_destroy(&zl->refs); 5504 isc_mem_put(server->mctx, zl, sizeof (*zl)); 5505 } else { 5506 /* 5507 * Place the task manager into privileged mode. This 5508 * ensures that after we leave task-exclusive mode, no 5509 * other tasks will be able to run except for the ones 5510 * that are loading zones. 5511 */ 5512 isc_taskmgr_setmode(ns_g_taskmgr, isc_taskmgrmode_privileged); 5513 } 5514 5515 isc_task_endexclusive(server->task); 5516 return (result); 5517} 5518 5519static isc_result_t 5520load_new_zones(ns_server_t *server, isc_boolean_t stop) { 5521 isc_result_t result; 5522 dns_view_t *view; 5523 5524 result = isc_task_beginexclusive(server->task); 5525 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5526 5527 /* 5528 * Load zone data from disk. 5529 */ 5530 for (view = ISC_LIST_HEAD(server->viewlist); 5531 view != NULL; 5532 view = ISC_LIST_NEXT(view, link)) 5533 { 5534 CHECK(dns_view_loadnew(view, stop)); 5535 5536 /* Load managed-keys data */ 5537 if (view->managed_keys != NULL) 5538 CHECK(dns_zone_loadnew(view->managed_keys)); 5539 if (view->redirect != NULL) 5540 CHECK(dns_zone_loadnew(view->redirect)); 5541 } 5542 5543 /* 5544 * Resume zone XFRs. 5545 */ 5546 dns_zonemgr_resumexfrs(server->zonemgr); 5547 cleanup: 5548 isc_task_endexclusive(server->task); 5549 return (result); 5550} 5551 5552static void 5553run_server(isc_task_t *task, isc_event_t *event) { 5554 isc_result_t result; 5555 ns_server_t *server = (ns_server_t *)event->ev_arg; 5556 5557 INSIST(task == server->task); 5558 5559 isc_event_free(&event); 5560 5561 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy, 5562 &ns_g_dispatchmgr), 5563 "creating dispatch manager"); 5564 5565 dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats); 5566 5567 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr, 5568 ns_g_socketmgr, ns_g_dispatchmgr, 5569 &server->interfacemgr), 5570 "creating interface manager"); 5571 5572 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 5573 NULL, NULL, server->task, 5574 interface_timer_tick, 5575 server, &server->interface_timer), 5576 "creating interface timer"); 5577 5578 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 5579 NULL, NULL, server->task, 5580 heartbeat_timer_tick, 5581 server, &server->heartbeat_timer), 5582 "creating heartbeat timer"); 5583 5584 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 5585 NULL, NULL, server->task, pps_timer_tick, 5586 server, &server->pps_timer), 5587 "creating pps timer"); 5588 5589 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser), 5590 "creating default configuration parser"); 5591 5592 if (ns_g_lwresdonly) 5593 CHECKFATAL(load_configuration(lwresd_g_conffile, server, 5594 ISC_TRUE), 5595 "loading configuration"); 5596 else 5597 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE), 5598 "loading configuration"); 5599 5600 isc_hash_init(); 5601 5602 CHECKFATAL(load_zones(server), "loading zones"); 5603} 5604 5605void 5606ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) { 5607 5608 REQUIRE(NS_SERVER_VALID(server)); 5609 5610 server->flushonshutdown = flush; 5611} 5612 5613static void 5614shutdown_server(isc_task_t *task, isc_event_t *event) { 5615 isc_result_t result; 5616 dns_view_t *view, *view_next; 5617 ns_server_t *server = (ns_server_t *)event->ev_arg; 5618 isc_boolean_t flush = server->flushonshutdown; 5619 ns_cache_t *nsc; 5620 5621 UNUSED(task); 5622 INSIST(task == server->task); 5623 5624 result = isc_task_beginexclusive(server->task); 5625 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5626 5627 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 5628 ISC_LOG_INFO, "shutting down%s", 5629 flush ? ": flushing changes" : ""); 5630 5631 ns_statschannels_shutdown(server); 5632 ns_controls_shutdown(server->controls); 5633 end_reserved_dispatches(server, ISC_TRUE); 5634 cleanup_session_key(server, server->mctx); 5635 5636 if (ns_g_aclconfctx != NULL) 5637 cfg_aclconfctx_detach(&ns_g_aclconfctx); 5638 5639 cfg_obj_destroy(ns_g_parser, &ns_g_config); 5640 cfg_parser_destroy(&ns_g_parser); 5641 5642 for (view = ISC_LIST_HEAD(server->viewlist); 5643 view != NULL; 5644 view = view_next) { 5645 view_next = ISC_LIST_NEXT(view, link); 5646 ISC_LIST_UNLINK(server->viewlist, view, link); 5647 if (flush) 5648 dns_view_flushanddetach(&view); 5649 else 5650 dns_view_detach(&view); 5651 } 5652 5653 while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { 5654 ISC_LIST_UNLINK(server->cachelist, nsc, link); 5655 dns_cache_detach(&nsc->cache); 5656 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 5657 } 5658 5659 isc_timer_detach(&server->interface_timer); 5660 isc_timer_detach(&server->heartbeat_timer); 5661 isc_timer_detach(&server->pps_timer); 5662 5663 ns_interfacemgr_shutdown(server->interfacemgr); 5664 ns_interfacemgr_detach(&server->interfacemgr); 5665 5666 dns_dispatchmgr_destroy(&ns_g_dispatchmgr); 5667 5668 dns_zonemgr_shutdown(server->zonemgr); 5669 5670 if (ns_g_sessionkey != NULL) { 5671 dns_tsigkey_detach(&ns_g_sessionkey); 5672 dns_name_free(&ns_g_sessionkeyname, server->mctx); 5673 } 5674 5675 if (server->blackholeacl != NULL) 5676 dns_acl_detach(&server->blackholeacl); 5677 5678 dns_db_detach(&server->in_roothints); 5679 5680 isc_task_endexclusive(server->task); 5681 5682 isc_task_detach(&server->task); 5683 5684 isc_event_free(&event); 5685} 5686 5687void 5688ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { 5689 isc_result_t result; 5690 ns_server_t *server = isc_mem_get(mctx, sizeof(*server)); 5691 5692 if (server == NULL) 5693 fatal("allocating server object", ISC_R_NOMEMORY); 5694 5695 server->mctx = mctx; 5696 server->task = NULL; 5697 5698 /* Initialize configuration data with default values. */ 5699 5700 result = isc_quota_init(&server->xfroutquota, 10); 5701 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5702 result = isc_quota_init(&server->tcpquota, 10); 5703 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5704 result = isc_quota_init(&server->recursionquota, 100); 5705 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5706 5707 result = dns_aclenv_init(mctx, &server->aclenv); 5708 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5709 5710 /* Initialize server data structures. */ 5711 server->zonemgr = NULL; 5712 server->interfacemgr = NULL; 5713 ISC_LIST_INIT(server->viewlist); 5714 server->in_roothints = NULL; 5715 server->blackholeacl = NULL; 5716 5717 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 5718 &server->in_roothints), 5719 "setting up root hints"); 5720 5721 CHECKFATAL(isc_mutex_init(&server->reload_event_lock), 5722 "initializing reload event lock"); 5723 server->reload_event = 5724 isc_event_allocate(ns_g_mctx, server, 5725 NS_EVENT_RELOAD, 5726 ns_server_reload, 5727 server, 5728 sizeof(isc_event_t)); 5729 CHECKFATAL(server->reload_event == NULL ? 5730 ISC_R_NOMEMORY : ISC_R_SUCCESS, 5731 "allocating reload event"); 5732 5733 CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy, 5734 ns_g_engine, ISC_ENTROPY_GOODONLY), 5735 "initializing DST"); 5736 5737 server->tkeyctx = NULL; 5738 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy, 5739 &server->tkeyctx), 5740 "creating TKEY context"); 5741 5742 /* 5743 * Setup the server task, which is responsible for coordinating 5744 * startup and shutdown of the server, as well as all exclusive 5745 * tasks. 5746 */ 5747 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task), 5748 "creating server task"); 5749 isc_task_setname(server->task, "server", server); 5750 isc_taskmgr_setexcltask(ns_g_taskmgr, server->task); 5751 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server), 5752 "isc_task_onshutdown"); 5753 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server), 5754 "isc_app_onrun"); 5755 5756 server->interface_timer = NULL; 5757 server->heartbeat_timer = NULL; 5758 server->pps_timer = NULL; 5759 5760 server->interface_interval = 0; 5761 server->heartbeat_interval = 0; 5762 5763 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, 5764 ns_g_socketmgr, &server->zonemgr), 5765 "dns_zonemgr_create"); 5766 CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000), 5767 "dns_zonemgr_setsize"); 5768 5769 server->statsfile = isc_mem_strdup(server->mctx, "named.stats"); 5770 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 5771 "isc_mem_strdup"); 5772 server->nsstats = NULL; 5773 server->rcvquerystats = NULL; 5774 server->opcodestats = NULL; 5775 server->zonestats = NULL; 5776 server->resolverstats = NULL; 5777 server->sockstats = NULL; 5778 CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats, 5779 isc_sockstatscounter_max), 5780 "isc_stats_create"); 5781 isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats); 5782 5783 server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys"); 5784 CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY : 5785 ISC_R_SUCCESS, 5786 "isc_mem_strdup"); 5787 5788 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db"); 5789 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 5790 "isc_mem_strdup"); 5791 5792 server->secrootsfile = isc_mem_strdup(server->mctx, "named.secroots"); 5793 CHECKFATAL(server->secrootsfile == NULL ? ISC_R_NOMEMORY : 5794 ISC_R_SUCCESS, 5795 "isc_mem_strdup"); 5796 5797 server->recfile = isc_mem_strdup(server->mctx, "named.recursing"); 5798 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 5799 "isc_mem_strdup"); 5800 5801 server->hostname_set = ISC_FALSE; 5802 server->hostname = NULL; 5803 server->version_set = ISC_FALSE; 5804 server->version = NULL; 5805 server->server_usehostname = ISC_FALSE; 5806 server->server_id = NULL; 5807 5808 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->nsstats, 5809 dns_nsstatscounter_max), 5810 "dns_stats_create (server)"); 5811 5812 CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx, 5813 &server->rcvquerystats), 5814 "dns_stats_create (rcvquery)"); 5815 5816 CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats), 5817 "dns_stats_create (opcode)"); 5818 5819 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats, 5820 dns_zonestatscounter_max), 5821 "dns_stats_create (zone)"); 5822 5823 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats, 5824 dns_resstatscounter_max), 5825 "dns_stats_create (resolver)"); 5826 5827 server->flushonshutdown = ISC_FALSE; 5828 server->log_queries = ISC_FALSE; 5829 5830 server->controls = NULL; 5831 CHECKFATAL(ns_controls_create(server, &server->controls), 5832 "ns_controls_create"); 5833 server->dispatchgen = 0; 5834 ISC_LIST_INIT(server->dispatches); 5835 5836 ISC_LIST_INIT(server->statschannels); 5837 5838 ISC_LIST_INIT(server->cachelist); 5839 5840 server->sessionkey = NULL; 5841 server->session_keyfile = NULL; 5842 server->session_keyname = NULL; 5843 server->session_keyalg = DST_ALG_UNKNOWN; 5844 server->session_keybits = 0; 5845 5846 server->magic = NS_SERVER_MAGIC; 5847 *serverp = server; 5848} 5849 5850void 5851ns_server_destroy(ns_server_t **serverp) { 5852 ns_server_t *server = *serverp; 5853 REQUIRE(NS_SERVER_VALID(server)); 5854 5855 ns_controls_destroy(&server->controls); 5856 5857 isc_stats_detach(&server->nsstats); 5858 dns_stats_detach(&server->rcvquerystats); 5859 dns_stats_detach(&server->opcodestats); 5860 isc_stats_detach(&server->zonestats); 5861 isc_stats_detach(&server->resolverstats); 5862 isc_stats_detach(&server->sockstats); 5863 5864 isc_mem_free(server->mctx, server->statsfile); 5865 isc_mem_free(server->mctx, server->bindkeysfile); 5866 isc_mem_free(server->mctx, server->dumpfile); 5867 isc_mem_free(server->mctx, server->secrootsfile); 5868 isc_mem_free(server->mctx, server->recfile); 5869 5870 if (server->version != NULL) 5871 isc_mem_free(server->mctx, server->version); 5872 if (server->hostname != NULL) 5873 isc_mem_free(server->mctx, server->hostname); 5874 if (server->server_id != NULL) 5875 isc_mem_free(server->mctx, server->server_id); 5876 5877 if (server->zonemgr != NULL) 5878 dns_zonemgr_detach(&server->zonemgr); 5879 5880 if (server->tkeyctx != NULL) 5881 dns_tkeyctx_destroy(&server->tkeyctx); 5882 5883 dst_lib_destroy(); 5884 5885 isc_event_free(&server->reload_event); 5886 5887 INSIST(ISC_LIST_EMPTY(server->viewlist)); 5888 INSIST(ISC_LIST_EMPTY(server->cachelist)); 5889 5890 dns_aclenv_destroy(&server->aclenv); 5891 5892 isc_quota_destroy(&server->recursionquota); 5893 isc_quota_destroy(&server->tcpquota); 5894 isc_quota_destroy(&server->xfroutquota); 5895 5896 server->magic = 0; 5897 isc_mem_put(server->mctx, server, sizeof(*server)); 5898 *serverp = NULL; 5899} 5900 5901static void 5902fatal(const char *msg, isc_result_t result) { 5903 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 5904 ISC_LOG_CRITICAL, "%s: %s", msg, 5905 isc_result_totext(result)); 5906 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 5907 ISC_LOG_CRITICAL, "exiting (due to fatal error)"); 5908 exit(1); 5909} 5910 5911static void 5912start_reserved_dispatches(ns_server_t *server) { 5913 5914 REQUIRE(NS_SERVER_VALID(server)); 5915 5916 server->dispatchgen++; 5917} 5918 5919static void 5920end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) { 5921 ns_dispatch_t *dispatch, *nextdispatch; 5922 5923 REQUIRE(NS_SERVER_VALID(server)); 5924 5925 for (dispatch = ISC_LIST_HEAD(server->dispatches); 5926 dispatch != NULL; 5927 dispatch = nextdispatch) { 5928 nextdispatch = ISC_LIST_NEXT(dispatch, link); 5929 if (!all && server->dispatchgen == dispatch-> dispatchgen) 5930 continue; 5931 ISC_LIST_UNLINK(server->dispatches, dispatch, link); 5932 dns_dispatch_detach(&dispatch->dispatch); 5933 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 5934 } 5935} 5936 5937void 5938ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) { 5939 ns_dispatch_t *dispatch; 5940 in_port_t port; 5941 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 5942 isc_result_t result; 5943 unsigned int attrs, attrmask; 5944 5945 REQUIRE(NS_SERVER_VALID(server)); 5946 5947 port = isc_sockaddr_getport(addr); 5948 if (port == 0 || port >= 1024) 5949 return; 5950 5951 for (dispatch = ISC_LIST_HEAD(server->dispatches); 5952 dispatch != NULL; 5953 dispatch = ISC_LIST_NEXT(dispatch, link)) { 5954 if (isc_sockaddr_equal(&dispatch->addr, addr)) 5955 break; 5956 } 5957 if (dispatch != NULL) { 5958 dispatch->dispatchgen = server->dispatchgen; 5959 return; 5960 } 5961 5962 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch)); 5963 if (dispatch == NULL) { 5964 result = ISC_R_NOMEMORY; 5965 goto cleanup; 5966 } 5967 5968 dispatch->addr = *addr; 5969 dispatch->dispatchgen = server->dispatchgen; 5970 dispatch->dispatch = NULL; 5971 5972 attrs = 0; 5973 attrs |= DNS_DISPATCHATTR_UDP; 5974 switch (isc_sockaddr_pf(addr)) { 5975 case AF_INET: 5976 attrs |= DNS_DISPATCHATTR_IPV4; 5977 break; 5978 case AF_INET6: 5979 attrs |= DNS_DISPATCHATTR_IPV6; 5980 break; 5981 default: 5982 result = ISC_R_NOTIMPLEMENTED; 5983 goto cleanup; 5984 } 5985 attrmask = 0; 5986 attrmask |= DNS_DISPATCHATTR_UDP; 5987 attrmask |= DNS_DISPATCHATTR_TCP; 5988 attrmask |= DNS_DISPATCHATTR_IPV4; 5989 attrmask |= DNS_DISPATCHATTR_IPV6; 5990 5991 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 5992 ns_g_taskmgr, &dispatch->addr, 4096, 5993 1000, 32768, 16411, 16433, 5994 attrs, attrmask, &dispatch->dispatch); 5995 if (result != ISC_R_SUCCESS) 5996 goto cleanup; 5997 5998 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link); 5999 6000 return; 6001 6002 cleanup: 6003 if (dispatch != NULL) 6004 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 6005 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 6006 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6007 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 6008 "unable to create dispatch for reserved port %s: %s", 6009 addrbuf, isc_result_totext(result)); 6010} 6011 6012 6013static isc_result_t 6014loadconfig(ns_server_t *server) { 6015 isc_result_t result; 6016 start_reserved_dispatches(server); 6017 result = load_configuration(ns_g_lwresdonly ? 6018 lwresd_g_conffile : ns_g_conffile, 6019 server, ISC_FALSE); 6020 if (result == ISC_R_SUCCESS) { 6021 end_reserved_dispatches(server, ISC_FALSE); 6022 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6023 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6024 "reloading configuration succeeded"); 6025 } else { 6026 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6027 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 6028 "reloading configuration failed: %s", 6029 isc_result_totext(result)); 6030 } 6031 return (result); 6032} 6033 6034static isc_result_t 6035reload(ns_server_t *server) { 6036 isc_result_t result; 6037 CHECK(loadconfig(server)); 6038 6039 result = load_zones(server); 6040 if (result == ISC_R_SUCCESS) 6041 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6042 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6043 "reloading zones succeeded"); 6044 else 6045 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6046 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 6047 "reloading zones failed: %s", 6048 isc_result_totext(result)); 6049 6050 cleanup: 6051 return (result); 6052} 6053 6054static void 6055reconfig(ns_server_t *server) { 6056 isc_result_t result; 6057 CHECK(loadconfig(server)); 6058 6059 result = load_new_zones(server, ISC_FALSE); 6060 if (result == ISC_R_SUCCESS) 6061 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6062 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6063 "any newly configured zones are now loaded"); 6064 else 6065 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6066 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 6067 "loading new zones failed: %s", 6068 isc_result_totext(result)); 6069 6070 cleanup: ; 6071} 6072 6073/* 6074 * Handle a reload event (from SIGHUP). 6075 */ 6076static void 6077ns_server_reload(isc_task_t *task, isc_event_t *event) { 6078 ns_server_t *server = (ns_server_t *)event->ev_arg; 6079 6080 INSIST(task = server->task); 6081 UNUSED(task); 6082 6083 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6084 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6085 "received SIGHUP signal to reload zones"); 6086 (void)reload(server); 6087 6088 LOCK(&server->reload_event_lock); 6089 INSIST(server->reload_event == NULL); 6090 server->reload_event = event; 6091 UNLOCK(&server->reload_event_lock); 6092} 6093 6094void 6095ns_server_reloadwanted(ns_server_t *server) { 6096 LOCK(&server->reload_event_lock); 6097 if (server->reload_event != NULL) 6098 isc_task_send(server->task, &server->reload_event); 6099 UNLOCK(&server->reload_event_lock); 6100} 6101 6102static char * 6103next_token(char **stringp, const char *delim) { 6104 char *res; 6105 6106 do { 6107 res = strsep(stringp, delim); 6108 if (res == NULL) 6109 break; 6110 } while (*res == '\0'); 6111 return (res); 6112} 6113 6114/* 6115 * Find the zone specified in the control channel command 'args', 6116 * if any. If a zone is specified, point '*zonep' at it, otherwise 6117 * set '*zonep' to NULL. 6118 */ 6119static isc_result_t 6120zone_from_args(ns_server_t *server, char *args, const char *zonetxt, 6121 dns_zone_t **zonep, const char **zonename, isc_boolean_t skip) 6122{ 6123 char *input, *ptr; 6124 char *classtxt; 6125 const char *viewtxt = NULL; 6126 dns_fixedname_t name; 6127 isc_result_t result; 6128 isc_buffer_t buf; 6129 dns_view_t *view = NULL; 6130 dns_rdataclass_t rdclass; 6131 6132 REQUIRE(zonep != NULL && *zonep == NULL); 6133 REQUIRE(zonename == NULL || *zonename == NULL); 6134 6135 input = args; 6136 6137 if (skip) { 6138 /* Skip the command name. */ 6139 ptr = next_token(&input, " \t"); 6140 if (ptr == NULL) 6141 return (ISC_R_UNEXPECTEDEND); 6142 } 6143 6144 /* Look for the zone name. */ 6145 if (zonetxt == NULL) 6146 zonetxt = next_token(&input, " \t"); 6147 if (zonetxt == NULL) 6148 return (ISC_R_SUCCESS); 6149 if (zonename != NULL) 6150 *zonename = zonetxt; 6151 6152 /* Look for the optional class name. */ 6153 classtxt = next_token(&input, " \t"); 6154 if (classtxt != NULL) { 6155 /* Look for the optional view name. */ 6156 viewtxt = next_token(&input, " \t"); 6157 } 6158 6159 isc_buffer_constinit(&buf, zonetxt, strlen(zonetxt)); 6160 isc_buffer_add(&buf, strlen(zonetxt)); 6161 dns_fixedname_init(&name); 6162 result = dns_name_fromtext(dns_fixedname_name(&name), 6163 &buf, dns_rootname, 0, NULL); 6164 if (result != ISC_R_SUCCESS) 6165 goto fail1; 6166 6167 if (classtxt != NULL) { 6168 isc_textregion_t r; 6169 r.base = classtxt; 6170 r.length = strlen(classtxt); 6171 result = dns_rdataclass_fromtext(&rdclass, &r); 6172 if (result != ISC_R_SUCCESS) 6173 goto fail1; 6174 } else 6175 rdclass = dns_rdataclass_in; 6176 6177 if (viewtxt == NULL) { 6178 result = dns_viewlist_findzone(&server->viewlist, 6179 dns_fixedname_name(&name), 6180 ISC_TF(classtxt == NULL), 6181 rdclass, zonep); 6182 } else { 6183 result = dns_viewlist_find(&server->viewlist, viewtxt, 6184 rdclass, &view); 6185 if (result != ISC_R_SUCCESS) 6186 goto fail1; 6187 6188 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name), 6189 0, NULL, zonep); 6190 dns_view_detach(&view); 6191 } 6192 6193 /* Partial match? */ 6194 if (result != ISC_R_SUCCESS && *zonep != NULL) 6195 dns_zone_detach(zonep); 6196 if (result == DNS_R_PARTIALMATCH) 6197 result = ISC_R_NOTFOUND; 6198 fail1: 6199 return (result); 6200} 6201 6202/* 6203 * Act on a "retransfer" command from the command channel. 6204 */ 6205isc_result_t 6206ns_server_retransfercommand(ns_server_t *server, char *args) { 6207 isc_result_t result; 6208 dns_zone_t *zone = NULL; 6209 dns_zone_t *raw = NULL; 6210 dns_zonetype_t type; 6211 6212 result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); 6213 if (result != ISC_R_SUCCESS) 6214 return (result); 6215 if (zone == NULL) 6216 return (ISC_R_UNEXPECTEDEND); 6217 dns_zone_getraw(zone, &raw); 6218 if (raw != NULL) { 6219 dns_zone_detach(&zone); 6220 dns_zone_attach(raw, &zone); 6221 dns_zone_detach(&raw); 6222 } 6223 type = dns_zone_gettype(zone); 6224 if (type == dns_zone_slave || type == dns_zone_stub) 6225 dns_zone_forcereload(zone); 6226 else 6227 result = ISC_R_NOTFOUND; 6228 dns_zone_detach(&zone); 6229 return (result); 6230} 6231 6232/* 6233 * Act on a "reload" command from the command channel. 6234 */ 6235isc_result_t 6236ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 6237 isc_result_t result; 6238 dns_zone_t *zone = NULL; 6239 dns_zonetype_t type; 6240 const char *msg = NULL; 6241 6242 result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); 6243 if (result != ISC_R_SUCCESS) 6244 return (result); 6245 if (zone == NULL) { 6246 result = reload(server); 6247 if (result == ISC_R_SUCCESS) 6248 msg = "server reload successful"; 6249 } else { 6250 type = dns_zone_gettype(zone); 6251 if (type == dns_zone_slave || type == dns_zone_stub) { 6252 dns_zone_refresh(zone); 6253 dns_zone_detach(&zone); 6254 msg = "zone refresh queued"; 6255 } else { 6256 result = dns_zone_load(zone); 6257 dns_zone_detach(&zone); 6258 switch (result) { 6259 case ISC_R_SUCCESS: 6260 msg = "zone reload successful"; 6261 break; 6262 case DNS_R_CONTINUE: 6263 msg = "zone reload queued"; 6264 result = ISC_R_SUCCESS; 6265 break; 6266 case DNS_R_UPTODATE: 6267 msg = "zone reload up-to-date"; 6268 result = ISC_R_SUCCESS; 6269 break; 6270 default: 6271 /* failure message will be generated by rndc */ 6272 break; 6273 } 6274 } 6275 } 6276 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) 6277 isc_buffer_putmem(text, (const unsigned char *)msg, 6278 strlen(msg) + 1); 6279 return (result); 6280} 6281 6282/* 6283 * Act on a "reconfig" command from the command channel. 6284 */ 6285isc_result_t 6286ns_server_reconfigcommand(ns_server_t *server, char *args) { 6287 UNUSED(args); 6288 6289 reconfig(server); 6290 return (ISC_R_SUCCESS); 6291} 6292 6293/* 6294 * Act on a "notify" command from the command channel. 6295 */ 6296isc_result_t 6297ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) { 6298 isc_result_t result; 6299 dns_zone_t *zone = NULL; 6300 const unsigned char msg[] = "zone notify queued"; 6301 6302 result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); 6303 if (result != ISC_R_SUCCESS) 6304 return (result); 6305 if (zone == NULL) 6306 return (ISC_R_UNEXPECTEDEND); 6307 6308 dns_zone_notify(zone); 6309 dns_zone_detach(&zone); 6310 if (sizeof(msg) <= isc_buffer_availablelength(text)) 6311 isc_buffer_putmem(text, msg, sizeof(msg)); 6312 6313 return (ISC_R_SUCCESS); 6314} 6315 6316/* 6317 * Act on a "refresh" command from the command channel. 6318 */ 6319isc_result_t 6320ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 6321 isc_result_t result; 6322 dns_zone_t *zone = NULL; 6323 const unsigned char msg1[] = "zone refresh queued"; 6324 const unsigned char msg2[] = "not a slave or stub zone"; 6325 dns_zonetype_t type; 6326 6327 result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); 6328 if (result != ISC_R_SUCCESS) 6329 return (result); 6330 if (zone == NULL) 6331 return (ISC_R_UNEXPECTEDEND); 6332 6333 type = dns_zone_gettype(zone); 6334 if (type == dns_zone_slave || type == dns_zone_stub) { 6335 dns_zone_refresh(zone); 6336 dns_zone_detach(&zone); 6337 if (sizeof(msg1) <= isc_buffer_availablelength(text)) 6338 isc_buffer_putmem(text, msg1, sizeof(msg1)); 6339 return (ISC_R_SUCCESS); 6340 } 6341 6342 dns_zone_detach(&zone); 6343 if (sizeof(msg2) <= isc_buffer_availablelength(text)) 6344 isc_buffer_putmem(text, msg2, sizeof(msg2)); 6345 return (ISC_R_FAILURE); 6346} 6347 6348isc_result_t 6349ns_server_togglequerylog(ns_server_t *server, char *args) { 6350 isc_boolean_t value; 6351 char *ptr; 6352 6353 /* Skip the command name. */ 6354 ptr = next_token(&args, " \t"); 6355 if (ptr == NULL) 6356 return (ISC_R_UNEXPECTEDEND); 6357 6358 ptr = next_token(&args, " \t"); 6359 if (ptr == NULL) 6360 value = server->log_queries ? ISC_FALSE : ISC_TRUE; 6361 else if (strcasecmp(ptr, "yes") == 0 || strcasecmp(ptr, "on") == 0) 6362 value = ISC_TRUE; 6363 else if (strcasecmp(ptr, "no") == 0 || strcasecmp(ptr, "off") == 0) 6364 value = ISC_FALSE; 6365 else 6366 return (ISC_R_NOTFOUND); 6367 6368 if (server->log_queries == value) 6369 return (ISC_R_SUCCESS); 6370 6371 server->log_queries = value; 6372 6373 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6374 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6375 "query logging is now %s", 6376 server->log_queries ? "on" : "off"); 6377 return (ISC_R_SUCCESS); 6378} 6379 6380static isc_result_t 6381ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 6382 cfg_aclconfctx_t *actx, 6383 isc_mem_t *mctx, ns_listenlist_t **target) 6384{ 6385 isc_result_t result; 6386 const cfg_listelt_t *element; 6387 ns_listenlist_t *dlist = NULL; 6388 6389 REQUIRE(target != NULL && *target == NULL); 6390 6391 result = ns_listenlist_create(mctx, &dlist); 6392 if (result != ISC_R_SUCCESS) 6393 return (result); 6394 6395 for (element = cfg_list_first(listenlist); 6396 element != NULL; 6397 element = cfg_list_next(element)) 6398 { 6399 ns_listenelt_t *delt = NULL; 6400 const cfg_obj_t *listener = cfg_listelt_value(element); 6401 result = ns_listenelt_fromconfig(listener, config, actx, 6402 mctx, &delt); 6403 if (result != ISC_R_SUCCESS) 6404 goto cleanup; 6405 ISC_LIST_APPEND(dlist->elts, delt, link); 6406 } 6407 *target = dlist; 6408 return (ISC_R_SUCCESS); 6409 6410 cleanup: 6411 ns_listenlist_detach(&dlist); 6412 return (result); 6413} 6414 6415/* 6416 * Create a listen list from the corresponding configuration 6417 * data structure. 6418 */ 6419static isc_result_t 6420ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 6421 cfg_aclconfctx_t *actx, 6422 isc_mem_t *mctx, ns_listenelt_t **target) 6423{ 6424 isc_result_t result; 6425 const cfg_obj_t *portobj; 6426 in_port_t port; 6427 ns_listenelt_t *delt = NULL; 6428 REQUIRE(target != NULL && *target == NULL); 6429 6430 portobj = cfg_tuple_get(listener, "port"); 6431 if (!cfg_obj_isuint32(portobj)) { 6432 if (ns_g_port != 0) { 6433 port = ns_g_port; 6434 } else { 6435 result = ns_config_getport(config, &port); 6436 if (result != ISC_R_SUCCESS) 6437 return (result); 6438 } 6439 } else { 6440 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { 6441 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 6442 "port value '%u' is out of range", 6443 cfg_obj_asuint32(portobj)); 6444 return (ISC_R_RANGE); 6445 } 6446 port = (in_port_t)cfg_obj_asuint32(portobj); 6447 } 6448 6449 result = ns_listenelt_create(mctx, port, NULL, &delt); 6450 if (result != ISC_R_SUCCESS) 6451 return (result); 6452 6453 result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), 6454 config, ns_g_lctx, actx, mctx, 0, 6455 &delt->acl); 6456 if (result != ISC_R_SUCCESS) { 6457 ns_listenelt_destroy(delt); 6458 return (result); 6459 } 6460 *target = delt; 6461 return (ISC_R_SUCCESS); 6462} 6463 6464isc_result_t 6465ns_server_dumpstats(ns_server_t *server) { 6466 isc_result_t result; 6467 FILE *fp = NULL; 6468 6469 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 6470 "could not open statistics dump file", server->statsfile); 6471 6472 result = ns_stats_dump(server, fp); 6473 6474 cleanup: 6475 if (fp != NULL) 6476 (void)isc_stdio_close(fp); 6477 if (result == ISC_R_SUCCESS) 6478 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6479 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6480 "dumpstats complete"); 6481 else 6482 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6483 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 6484 "dumpstats failed: %s", 6485 dns_result_totext(result)); 6486 return (result); 6487} 6488 6489static isc_result_t 6490add_zone_tolist(dns_zone_t *zone, void *uap) { 6491 struct dumpcontext *dctx = uap; 6492 struct zonelistentry *zle; 6493 6494 zle = isc_mem_get(dctx->mctx, sizeof *zle); 6495 if (zle == NULL) 6496 return (ISC_R_NOMEMORY); 6497 zle->zone = NULL; 6498 dns_zone_attach(zone, &zle->zone); 6499 ISC_LINK_INIT(zle, link); 6500 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 6501 return (ISC_R_SUCCESS); 6502} 6503 6504static isc_result_t 6505add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 6506 struct viewlistentry *vle; 6507 isc_result_t result = ISC_R_SUCCESS; 6508 6509 /* 6510 * Prevent duplicate views. 6511 */ 6512 for (vle = ISC_LIST_HEAD(dctx->viewlist); 6513 vle != NULL; 6514 vle = ISC_LIST_NEXT(vle, link)) 6515 if (vle->view == view) 6516 return (ISC_R_SUCCESS); 6517 6518 vle = isc_mem_get(dctx->mctx, sizeof *vle); 6519 if (vle == NULL) 6520 return (ISC_R_NOMEMORY); 6521 vle->view = NULL; 6522 dns_view_attach(view, &vle->view); 6523 ISC_LINK_INIT(vle, link); 6524 ISC_LIST_INIT(vle->zonelist); 6525 ISC_LIST_APPEND(dctx->viewlist, vle, link); 6526 if (dctx->dumpzones) 6527 result = dns_zt_apply(view->zonetable, ISC_TRUE, 6528 add_zone_tolist, dctx); 6529 return (result); 6530} 6531 6532static void 6533dumpcontext_destroy(struct dumpcontext *dctx) { 6534 struct viewlistentry *vle; 6535 struct zonelistentry *zle; 6536 6537 vle = ISC_LIST_HEAD(dctx->viewlist); 6538 while (vle != NULL) { 6539 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 6540 zle = ISC_LIST_HEAD(vle->zonelist); 6541 while (zle != NULL) { 6542 ISC_LIST_UNLINK(vle->zonelist, zle, link); 6543 dns_zone_detach(&zle->zone); 6544 isc_mem_put(dctx->mctx, zle, sizeof *zle); 6545 zle = ISC_LIST_HEAD(vle->zonelist); 6546 } 6547 dns_view_detach(&vle->view); 6548 isc_mem_put(dctx->mctx, vle, sizeof *vle); 6549 vle = ISC_LIST_HEAD(dctx->viewlist); 6550 } 6551 if (dctx->version != NULL) 6552 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE); 6553 if (dctx->db != NULL) 6554 dns_db_detach(&dctx->db); 6555 if (dctx->cache != NULL) 6556 dns_db_detach(&dctx->cache); 6557 if (dctx->task != NULL) 6558 isc_task_detach(&dctx->task); 6559 if (dctx->fp != NULL) 6560 (void)isc_stdio_close(dctx->fp); 6561 if (dctx->mdctx != NULL) 6562 dns_dumpctx_detach(&dctx->mdctx); 6563 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 6564} 6565 6566static void 6567dumpdone(void *arg, isc_result_t result) { 6568 struct dumpcontext *dctx = arg; 6569 char buf[1024+32]; 6570 const dns_master_style_t *style; 6571 6572 if (result != ISC_R_SUCCESS) 6573 goto cleanup; 6574 if (dctx->mdctx != NULL) 6575 dns_dumpctx_detach(&dctx->mdctx); 6576 if (dctx->view == NULL) { 6577 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 6578 if (dctx->view == NULL) 6579 goto done; 6580 INSIST(dctx->zone == NULL); 6581 } else 6582 goto resume; 6583 nextview: 6584 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 6585 resume: 6586 if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { 6587 fprintf(dctx->fp, 6588 ";\n; Cache of view '%s' is shared as '%s'\n", 6589 dctx->view->view->name, 6590 dns_cache_getname(dctx->view->view->cache)); 6591 } else if (dctx->zone == NULL && dctx->cache == NULL && 6592 dctx->dumpcache) 6593 { 6594 style = &dns_master_style_cache; 6595 /* start cache dump */ 6596 if (dctx->view->view->cachedb != NULL) 6597 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 6598 if (dctx->cache != NULL) { 6599 fprintf(dctx->fp, 6600 ";\n; Cache dump of view '%s' (cache %s)\n;\n", 6601 dctx->view->view->name, 6602 dns_cache_getname(dctx->view->view->cache)); 6603 result = dns_master_dumptostreaminc(dctx->mctx, 6604 dctx->cache, NULL, 6605 style, dctx->fp, 6606 dctx->task, 6607 dumpdone, dctx, 6608 &dctx->mdctx); 6609 if (result == DNS_R_CONTINUE) 6610 return; 6611 if (result == ISC_R_NOTIMPLEMENTED) 6612 fprintf(dctx->fp, "; %s\n", 6613 dns_result_totext(result)); 6614 else if (result != ISC_R_SUCCESS) 6615 goto cleanup; 6616 } 6617 } 6618 if (dctx->cache != NULL) { 6619 dns_adb_dump(dctx->view->view->adb, dctx->fp); 6620 dns_resolver_printbadcache(dctx->view->view->resolver, 6621 dctx->fp); 6622 dns_db_detach(&dctx->cache); 6623 } 6624 if (dctx->dumpzones) { 6625 style = &dns_master_style_full; 6626 nextzone: 6627 if (dctx->version != NULL) 6628 dns_db_closeversion(dctx->db, &dctx->version, 6629 ISC_FALSE); 6630 if (dctx->db != NULL) 6631 dns_db_detach(&dctx->db); 6632 if (dctx->zone == NULL) 6633 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 6634 else 6635 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 6636 if (dctx->zone != NULL) { 6637 /* start zone dump */ 6638 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 6639 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 6640 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 6641 if (result != ISC_R_SUCCESS) { 6642 fprintf(dctx->fp, "; %s\n", 6643 dns_result_totext(result)); 6644 goto nextzone; 6645 } 6646 dns_db_currentversion(dctx->db, &dctx->version); 6647 result = dns_master_dumptostreaminc(dctx->mctx, 6648 dctx->db, 6649 dctx->version, 6650 style, dctx->fp, 6651 dctx->task, 6652 dumpdone, dctx, 6653 &dctx->mdctx); 6654 if (result == DNS_R_CONTINUE) 6655 return; 6656 if (result == ISC_R_NOTIMPLEMENTED) { 6657 fprintf(dctx->fp, "; %s\n", 6658 dns_result_totext(result)); 6659 result = ISC_R_SUCCESS; 6660 POST(result); 6661 goto nextzone; 6662 } 6663 if (result != ISC_R_SUCCESS) 6664 goto cleanup; 6665 } 6666 } 6667 if (dctx->view != NULL) 6668 dctx->view = ISC_LIST_NEXT(dctx->view, link); 6669 if (dctx->view != NULL) 6670 goto nextview; 6671 done: 6672 fprintf(dctx->fp, "; Dump complete\n"); 6673 result = isc_stdio_flush(dctx->fp); 6674 if (result == ISC_R_SUCCESS) 6675 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6676 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6677 "dumpdb complete"); 6678 cleanup: 6679 if (result != ISC_R_SUCCESS) 6680 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6681 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 6682 "dumpdb failed: %s", dns_result_totext(result)); 6683 dumpcontext_destroy(dctx); 6684} 6685 6686isc_result_t 6687ns_server_dumpdb(ns_server_t *server, char *args) { 6688 struct dumpcontext *dctx = NULL; 6689 dns_view_t *view; 6690 isc_result_t result; 6691 char *ptr; 6692 const char *sep; 6693 6694 /* Skip the command name. */ 6695 ptr = next_token(&args, " \t"); 6696 if (ptr == NULL) 6697 return (ISC_R_UNEXPECTEDEND); 6698 6699 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 6700 if (dctx == NULL) 6701 return (ISC_R_NOMEMORY); 6702 6703 dctx->mctx = server->mctx; 6704 dctx->dumpcache = ISC_TRUE; 6705 dctx->dumpzones = ISC_FALSE; 6706 dctx->fp = NULL; 6707 ISC_LIST_INIT(dctx->viewlist); 6708 dctx->view = NULL; 6709 dctx->zone = NULL; 6710 dctx->cache = NULL; 6711 dctx->mdctx = NULL; 6712 dctx->db = NULL; 6713 dctx->cache = NULL; 6714 dctx->task = NULL; 6715 dctx->version = NULL; 6716 isc_task_attach(server->task, &dctx->task); 6717 6718 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 6719 "could not open dump file", server->dumpfile); 6720 6721 sep = (args == NULL) ? "" : ": "; 6722 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6723 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6724 "dumpdb started%s%s", sep, (args != NULL) ? args : ""); 6725 6726 ptr = next_token(&args, " \t"); 6727 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 6728 dctx->dumpzones = ISC_TRUE; 6729 dctx->dumpcache = ISC_TRUE; 6730 ptr = next_token(&args, " \t"); 6731 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 6732 dctx->dumpzones = ISC_FALSE; 6733 dctx->dumpcache = ISC_TRUE; 6734 ptr = next_token(&args, " \t"); 6735 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 6736 dctx->dumpzones = ISC_TRUE; 6737 dctx->dumpcache = ISC_FALSE; 6738 ptr = next_token(&args, " \t"); 6739 } 6740 6741 nextview: 6742 for (view = ISC_LIST_HEAD(server->viewlist); 6743 view != NULL; 6744 view = ISC_LIST_NEXT(view, link)) 6745 { 6746 if (ptr != NULL && strcmp(view->name, ptr) != 0) 6747 continue; 6748 CHECK(add_view_tolist(dctx, view)); 6749 } 6750 if (ptr != NULL) { 6751 ptr = next_token(&args, " \t"); 6752 if (ptr != NULL) 6753 goto nextview; 6754 } 6755 dumpdone(dctx, ISC_R_SUCCESS); 6756 return (ISC_R_SUCCESS); 6757 6758 cleanup: 6759 if (dctx != NULL) 6760 dumpcontext_destroy(dctx); 6761 return (result); 6762} 6763 6764isc_result_t 6765ns_server_dumpsecroots(ns_server_t *server, char *args) { 6766 dns_view_t *view; 6767 dns_keytable_t *secroots = NULL; 6768 isc_result_t result; 6769 char *ptr; 6770 FILE *fp = NULL; 6771 isc_time_t now; 6772 char tbuf[64]; 6773 6774 /* Skip the command name. */ 6775 ptr = next_token(&args, " \t"); 6776 if (ptr == NULL) 6777 return (ISC_R_UNEXPECTEDEND); 6778 6779 ptr = next_token(&args, " \t"); 6780 6781 CHECKMF(isc_stdio_open(server->secrootsfile, "w", &fp), 6782 "could not open secroots dump file", server->secrootsfile); 6783 TIME_NOW(&now); 6784 isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); 6785 fprintf(fp, "%s\n", tbuf); 6786 6787 do { 6788 for (view = ISC_LIST_HEAD(server->viewlist); 6789 view != NULL; 6790 view = ISC_LIST_NEXT(view, link)) 6791 { 6792 if (ptr != NULL && strcmp(view->name, ptr) != 0) 6793 continue; 6794 if (secroots != NULL) 6795 dns_keytable_detach(&secroots); 6796 result = dns_view_getsecroots(view, &secroots); 6797 if (result == ISC_R_NOTFOUND) { 6798 result = ISC_R_SUCCESS; 6799 continue; 6800 } 6801 fprintf(fp, "\n Start view %s\n\n", view->name); 6802 result = dns_keytable_dump(secroots, fp); 6803 if (result != ISC_R_SUCCESS) 6804 fprintf(fp, " dumpsecroots failed: %s\n", 6805 isc_result_totext(result)); 6806 } 6807 if (ptr != NULL) 6808 ptr = next_token(&args, " \t"); 6809 } while (ptr != NULL); 6810 6811 cleanup: 6812 if (secroots != NULL) 6813 dns_keytable_detach(&secroots); 6814 if (fp != NULL) 6815 (void)isc_stdio_close(fp); 6816 if (result == ISC_R_SUCCESS) 6817 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6818 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6819 "dumpsecroots complete"); 6820 else 6821 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6822 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 6823 "dumpsecroots failed: %s", 6824 dns_result_totext(result)); 6825 return (result); 6826} 6827 6828isc_result_t 6829ns_server_dumprecursing(ns_server_t *server) { 6830 FILE *fp = NULL; 6831 isc_result_t result; 6832 6833 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 6834 "could not open dump file", server->recfile); 6835 fprintf(fp,";\n; Recursing Queries\n;\n"); 6836 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 6837 fprintf(fp, "; Dump complete\n"); 6838 6839 cleanup: 6840 if (fp != NULL) 6841 result = isc_stdio_close(fp); 6842 if (result == ISC_R_SUCCESS) 6843 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6844 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6845 "dumprecursing complete"); 6846 else 6847 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6848 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 6849 "dumprecursing failed: %s", 6850 dns_result_totext(result)); 6851 return (result); 6852} 6853 6854isc_result_t 6855ns_server_setdebuglevel(ns_server_t *server, char *args) { 6856 char *ptr; 6857 char *levelstr; 6858 char *endp; 6859 long newlevel; 6860 6861 UNUSED(server); 6862 6863 /* Skip the command name. */ 6864 ptr = next_token(&args, " \t"); 6865 if (ptr == NULL) 6866 return (ISC_R_UNEXPECTEDEND); 6867 6868 /* Look for the new level name. */ 6869 levelstr = next_token(&args, " \t"); 6870 if (levelstr == NULL) { 6871 if (ns_g_debuglevel < 99) 6872 ns_g_debuglevel++; 6873 } else { 6874 newlevel = strtol(levelstr, &endp, 10); 6875 if (*endp != '\0' || newlevel < 0 || newlevel > 99) 6876 return (ISC_R_RANGE); 6877 ns_g_debuglevel = (unsigned int)newlevel; 6878 } 6879 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); 6880 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 6881 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 6882 "debug level is now %d", ns_g_debuglevel); 6883 return (ISC_R_SUCCESS); 6884} 6885 6886isc_result_t 6887ns_server_validation(ns_server_t *server, char *args) { 6888 char *ptr, *viewname; 6889 dns_view_t *view; 6890 isc_boolean_t changed = ISC_FALSE; 6891 isc_result_t result; 6892 isc_boolean_t enable; 6893 6894 /* Skip the command name. */ 6895 ptr = next_token(&args, " \t"); 6896 if (ptr == NULL) 6897 return (ISC_R_UNEXPECTEDEND); 6898 6899 /* Find out what we are to do. */ 6900 ptr = next_token(&args, " \t"); 6901 if (ptr == NULL) 6902 return (ISC_R_UNEXPECTEDEND); 6903 6904 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 6905 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 6906 enable = ISC_TRUE; 6907 else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 6908 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 6909 enable = ISC_FALSE; 6910 else 6911 return (DNS_R_SYNTAX); 6912 6913 /* Look for the view name. */ 6914 viewname = next_token(&args, " \t"); 6915 6916 result = isc_task_beginexclusive(server->task); 6917 RUNTIME_CHECK(result == ISC_R_SUCCESS); 6918 for (view = ISC_LIST_HEAD(server->viewlist); 6919 view != NULL; 6920 view = ISC_LIST_NEXT(view, link)) 6921 { 6922 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 6923 continue; 6924 result = dns_view_flushcache(view); 6925 if (result != ISC_R_SUCCESS) 6926 goto out; 6927 view->enablevalidation = enable; 6928 changed = ISC_TRUE; 6929 } 6930 if (changed) 6931 result = ISC_R_SUCCESS; 6932 else 6933 result = ISC_R_FAILURE; 6934 out: 6935 isc_task_endexclusive(server->task); 6936 return (result); 6937} 6938 6939isc_result_t 6940ns_server_flushcache(ns_server_t *server, char *args) { 6941 char *ptr, *viewname; 6942 dns_view_t *view; 6943 isc_boolean_t flushed; 6944 isc_boolean_t found; 6945 isc_result_t result; 6946 ns_cache_t *nsc; 6947 6948 /* Skip the command name. */ 6949 ptr = next_token(&args, " \t"); 6950 if (ptr == NULL) 6951 return (ISC_R_UNEXPECTEDEND); 6952 6953 /* Look for the view name. */ 6954 viewname = next_token(&args, " \t"); 6955 6956 result = isc_task_beginexclusive(server->task); 6957 RUNTIME_CHECK(result == ISC_R_SUCCESS); 6958 flushed = ISC_TRUE; 6959 found = ISC_FALSE; 6960 6961 /* 6962 * Flushing a cache is tricky when caches are shared by multiple views. 6963 * We first identify which caches should be flushed in the local cache 6964 * list, flush these caches, and then update other views that refer to 6965 * the flushed cache DB. 6966 */ 6967 if (viewname != NULL) { 6968 /* 6969 * Mark caches that need to be flushed. This is an O(#view^2) 6970 * operation in the very worst case, but should be normally 6971 * much more lightweight because only a few (most typically just 6972 * one) views will match. 6973 */ 6974 for (view = ISC_LIST_HEAD(server->viewlist); 6975 view != NULL; 6976 view = ISC_LIST_NEXT(view, link)) 6977 { 6978 if (strcasecmp(viewname, view->name) != 0) 6979 continue; 6980 found = ISC_TRUE; 6981 for (nsc = ISC_LIST_HEAD(server->cachelist); 6982 nsc != NULL; 6983 nsc = ISC_LIST_NEXT(nsc, link)) { 6984 if (nsc->cache == view->cache) 6985 break; 6986 } 6987 INSIST(nsc != NULL); 6988 nsc->needflush = ISC_TRUE; 6989 } 6990 } else 6991 found = ISC_TRUE; 6992 6993 /* Perform flush */ 6994 for (nsc = ISC_LIST_HEAD(server->cachelist); 6995 nsc != NULL; 6996 nsc = ISC_LIST_NEXT(nsc, link)) { 6997 if (viewname != NULL && !nsc->needflush) 6998 continue; 6999 nsc->needflush = ISC_TRUE; 7000 result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE); 7001 if (result != ISC_R_SUCCESS) { 7002 flushed = ISC_FALSE; 7003 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7004 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 7005 "flushing cache in view '%s' failed: %s", 7006 nsc->primaryview->name, 7007 isc_result_totext(result)); 7008 } 7009 } 7010 7011 /* 7012 * Fix up views that share a flushed cache: let the views update the 7013 * cache DB they're referring to. This could also be an expensive 7014 * operation, but should typically be marginal: the inner loop is only 7015 * necessary for views that share a cache, and if there are many such 7016 * views the number of shared cache should normally be small. 7017 * A worst case is that we have n views and n/2 caches, each shared by 7018 * two views. Then this will be a O(n^2/4) operation. 7019 */ 7020 for (view = ISC_LIST_HEAD(server->viewlist); 7021 view != NULL; 7022 view = ISC_LIST_NEXT(view, link)) 7023 { 7024 if (!dns_view_iscacheshared(view)) 7025 continue; 7026 for (nsc = ISC_LIST_HEAD(server->cachelist); 7027 nsc != NULL; 7028 nsc = ISC_LIST_NEXT(nsc, link)) { 7029 if (!nsc->needflush || nsc->cache != view->cache) 7030 continue; 7031 result = dns_view_flushcache2(view, ISC_TRUE); 7032 if (result != ISC_R_SUCCESS) { 7033 flushed = ISC_FALSE; 7034 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7035 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 7036 "fixing cache in view '%s' " 7037 "failed: %s", view->name, 7038 isc_result_totext(result)); 7039 } 7040 } 7041 } 7042 7043 /* Cleanup the cache list. */ 7044 for (nsc = ISC_LIST_HEAD(server->cachelist); 7045 nsc != NULL; 7046 nsc = ISC_LIST_NEXT(nsc, link)) { 7047 nsc->needflush = ISC_FALSE; 7048 } 7049 7050 if (flushed && found) { 7051 if (viewname != NULL) 7052 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7053 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7054 "flushing cache in view '%s' succeeded", 7055 viewname); 7056 else 7057 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7058 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7059 "flushing caches in all views succeeded"); 7060 result = ISC_R_SUCCESS; 7061 } else { 7062 if (!found) { 7063 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7064 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 7065 "flushing cache in view '%s' failed: " 7066 "view not found", viewname); 7067 result = ISC_R_NOTFOUND; 7068 } else 7069 result = ISC_R_FAILURE; 7070 } 7071 isc_task_endexclusive(server->task); 7072 return (result); 7073} 7074 7075isc_result_t 7076ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) { 7077 char *ptr, *target, *viewname; 7078 dns_view_t *view; 7079 isc_boolean_t flushed; 7080 isc_boolean_t found; 7081 isc_result_t result; 7082 isc_buffer_t b; 7083 dns_fixedname_t fixed; 7084 dns_name_t *name; 7085 7086 /* Skip the command name. */ 7087 ptr = next_token(&args, " \t"); 7088 if (ptr == NULL) 7089 return (ISC_R_UNEXPECTEDEND); 7090 7091 /* Find the domain name to flush. */ 7092 target = next_token(&args, " \t"); 7093 if (target == NULL) 7094 return (ISC_R_UNEXPECTEDEND); 7095 7096 isc_buffer_constinit(&b, target, strlen(target)); 7097 isc_buffer_add(&b, strlen(target)); 7098 dns_fixedname_init(&fixed); 7099 name = dns_fixedname_name(&fixed); 7100 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 7101 if (result != ISC_R_SUCCESS) 7102 return (result); 7103 7104 /* Look for the view name. */ 7105 viewname = next_token(&args, " \t"); 7106 7107 result = isc_task_beginexclusive(server->task); 7108 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7109 flushed = ISC_TRUE; 7110 found = ISC_FALSE; 7111 for (view = ISC_LIST_HEAD(server->viewlist); 7112 view != NULL; 7113 view = ISC_LIST_NEXT(view, link)) 7114 { 7115 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 7116 continue; 7117 found = ISC_TRUE; 7118 /* 7119 * It's a little inefficient to try flushing name for all views 7120 * if some of the views share a single cache. But since the 7121 * operation is lightweight we prefer simplicity here. 7122 */ 7123 result = dns_view_flushnode(view, name, tree); 7124 if (result != ISC_R_SUCCESS) { 7125 flushed = ISC_FALSE; 7126 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7127 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 7128 "flushing %s '%s' in cache view '%s' " 7129 "failed: %s", 7130 tree ? "tree" : "name", 7131 target, view->name, 7132 isc_result_totext(result)); 7133 } 7134 } 7135 if (flushed && found) { 7136 if (viewname != NULL) 7137 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7138 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7139 "flushing %s '%s' in cache view '%s' " 7140 "succeeded", 7141 tree ? "tree" : "name", 7142 target, viewname); 7143 else 7144 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7145 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7146 "flushing %s '%s' in all cache views " 7147 "succeeded", 7148 tree ? "tree" : "name", 7149 target); 7150 result = ISC_R_SUCCESS; 7151 } else { 7152 if (!found) 7153 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7154 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 7155 "flushing %s '%s' in cache view '%s' " 7156 "failed: view not found", 7157 tree ? "tree" : "name", 7158 target, viewname); 7159 result = ISC_R_FAILURE; 7160 } 7161 isc_task_endexclusive(server->task); 7162 return (result); 7163} 7164 7165isc_result_t 7166ns_server_status(ns_server_t *server, isc_buffer_t *text) { 7167 int zonecount, xferrunning, xferdeferred, soaqueries; 7168 unsigned int n; 7169 const char *ob = "", *cb = "", *alt = ""; 7170 7171 if (ns_g_server->version_set) { 7172 ob = " ("; 7173 cb = ")"; 7174 if (ns_g_server->version == NULL) 7175 alt = "version.bind/txt/ch disabled"; 7176 else 7177 alt = ns_g_server->version; 7178 } 7179 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 7180 xferrunning = dns_zonemgr_getcount(server->zonemgr, 7181 DNS_ZONESTATE_XFERRUNNING); 7182 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 7183 DNS_ZONESTATE_XFERDEFERRED); 7184 soaqueries = dns_zonemgr_getcount(server->zonemgr, 7185 DNS_ZONESTATE_SOAQUERY); 7186 7187 n = snprintf((char *)isc_buffer_used(text), 7188 isc_buffer_availablelength(text), 7189 "version: %s%s%s%s\n" 7190#ifdef ISC_PLATFORM_USETHREADS 7191 "CPUs found: %u\n" 7192 "worker threads: %u\n" 7193 "UDP listeners per interface: %u\n" 7194#endif 7195 "number of zones: %u\n" 7196 "debug level: %d\n" 7197 "xfers running: %u\n" 7198 "xfers deferred: %u\n" 7199 "soa queries in progress: %u\n" 7200 "query logging is %s\n" 7201 "recursive clients: %d/%d/%d\n" 7202 "tcp clients: %d/%d\n" 7203 "server is up and running", 7204 ns_g_version, ob, alt, cb, 7205#ifdef ISC_PLATFORM_USETHREADS 7206 ns_g_cpus_detected, ns_g_cpus, ns_g_udpdisp, 7207#endif 7208 zonecount, ns_g_debuglevel, xferrunning, xferdeferred, 7209 soaqueries, server->log_queries ? "ON" : "OFF", 7210 server->recursionquota.used, server->recursionquota.soft, 7211 server->recursionquota.max, 7212 server->tcpquota.used, server->tcpquota.max); 7213 if (n >= isc_buffer_availablelength(text)) 7214 return (ISC_R_NOSPACE); 7215 isc_buffer_add(text, n); 7216 return (ISC_R_SUCCESS); 7217} 7218 7219static isc_result_t 7220delete_keynames(dns_tsig_keyring_t *ring, char *target, 7221 unsigned int *foundkeys) 7222{ 7223 char namestr[DNS_NAME_FORMATSIZE]; 7224 isc_result_t result; 7225 dns_rbtnodechain_t chain; 7226 dns_name_t foundname; 7227 dns_fixedname_t fixedorigin; 7228 dns_name_t *origin; 7229 dns_rbtnode_t *node; 7230 dns_tsigkey_t *tkey; 7231 7232 dns_name_init(&foundname, NULL); 7233 dns_fixedname_init(&fixedorigin); 7234 origin = dns_fixedname_name(&fixedorigin); 7235 7236 again: 7237 dns_rbtnodechain_init(&chain, ring->mctx); 7238 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, 7239 origin); 7240 if (result == ISC_R_NOTFOUND) { 7241 dns_rbtnodechain_invalidate(&chain); 7242 return (ISC_R_SUCCESS); 7243 } 7244 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 7245 dns_rbtnodechain_invalidate(&chain); 7246 return (result); 7247 } 7248 7249 for (;;) { 7250 node = NULL; 7251 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 7252 tkey = node->data; 7253 7254 if (tkey != NULL) { 7255 if (!tkey->generated) 7256 goto nextkey; 7257 7258 dns_name_format(&tkey->name, namestr, sizeof(namestr)); 7259 if (strcmp(namestr, target) == 0) { 7260 (*foundkeys)++; 7261 dns_rbtnodechain_invalidate(&chain); 7262 (void)dns_rbt_deletename(ring->keys, 7263 &tkey->name, 7264 ISC_FALSE); 7265 goto again; 7266 } 7267 } 7268 7269 nextkey: 7270 result = dns_rbtnodechain_next(&chain, &foundname, origin); 7271 if (result == ISC_R_NOMORE) 7272 break; 7273 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 7274 dns_rbtnodechain_invalidate(&chain); 7275 return (result); 7276 } 7277 } 7278 7279 return (ISC_R_SUCCESS); 7280} 7281 7282isc_result_t 7283ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) { 7284 isc_result_t result; 7285 unsigned int n; 7286 dns_view_t *view; 7287 unsigned int foundkeys = 0; 7288 char *target; 7289 char *viewname; 7290 7291 (void)next_token(&command, " \t"); /* skip command name */ 7292 target = next_token(&command, " \t"); 7293 if (target == NULL) 7294 return (ISC_R_UNEXPECTEDEND); 7295 viewname = next_token(&command, " \t"); 7296 7297 result = isc_task_beginexclusive(server->task); 7298 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7299 for (view = ISC_LIST_HEAD(server->viewlist); 7300 view != NULL; 7301 view = ISC_LIST_NEXT(view, link)) { 7302 if (viewname == NULL || strcmp(view->name, viewname) == 0) { 7303 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write); 7304 result = delete_keynames(view->dynamickeys, target, 7305 &foundkeys); 7306 RWUNLOCK(&view->dynamickeys->lock, 7307 isc_rwlocktype_write); 7308 if (result != ISC_R_SUCCESS) { 7309 isc_task_endexclusive(server->task); 7310 return (result); 7311 } 7312 } 7313 } 7314 isc_task_endexclusive(server->task); 7315 7316 n = snprintf((char *)isc_buffer_used(text), 7317 isc_buffer_availablelength(text), 7318 "%d tsig keys deleted.\n", foundkeys); 7319 if (n >= isc_buffer_availablelength(text)) 7320 return (ISC_R_NOSPACE); 7321 isc_buffer_add(text, n); 7322 7323 return (ISC_R_SUCCESS); 7324} 7325 7326static isc_result_t 7327list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text, 7328 unsigned int *foundkeys) 7329{ 7330 char namestr[DNS_NAME_FORMATSIZE]; 7331 char creatorstr[DNS_NAME_FORMATSIZE]; 7332 isc_result_t result; 7333 dns_rbtnodechain_t chain; 7334 dns_name_t foundname; 7335 dns_fixedname_t fixedorigin; 7336 dns_name_t *origin; 7337 dns_rbtnode_t *node; 7338 dns_tsigkey_t *tkey; 7339 unsigned int n; 7340 const char *viewname; 7341 7342 if (view != NULL) 7343 viewname = view->name; 7344 else 7345 viewname = "(global)"; 7346 7347 dns_name_init(&foundname, NULL); 7348 dns_fixedname_init(&fixedorigin); 7349 origin = dns_fixedname_name(&fixedorigin); 7350 dns_rbtnodechain_init(&chain, ring->mctx); 7351 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, 7352 origin); 7353 if (result == ISC_R_NOTFOUND) { 7354 dns_rbtnodechain_invalidate(&chain); 7355 return (ISC_R_SUCCESS); 7356 } 7357 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 7358 dns_rbtnodechain_invalidate(&chain); 7359 return (result); 7360 } 7361 7362 for (;;) { 7363 node = NULL; 7364 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 7365 tkey = node->data; 7366 7367 if (tkey != NULL) { 7368 (*foundkeys)++; 7369 dns_name_format(&tkey->name, namestr, sizeof(namestr)); 7370 if (tkey->generated) { 7371 dns_name_format(tkey->creator, creatorstr, 7372 sizeof(creatorstr)); 7373 n = snprintf((char *)isc_buffer_used(text), 7374 isc_buffer_availablelength(text), 7375 "view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n", 7376 viewname, namestr, creatorstr); 7377 } else { 7378 n = snprintf((char *)isc_buffer_used(text), 7379 isc_buffer_availablelength(text), 7380 "view \"%s\"; type \"static\"; key \"%s\";\n", 7381 viewname, namestr); 7382 } 7383 if (n >= isc_buffer_availablelength(text)) { 7384 dns_rbtnodechain_invalidate(&chain); 7385 return (ISC_R_NOSPACE); 7386 } 7387 isc_buffer_add(text, n); 7388 } 7389 result = dns_rbtnodechain_next(&chain, &foundname, origin); 7390 if (result == ISC_R_NOMORE) 7391 break; 7392 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 7393 dns_rbtnodechain_invalidate(&chain); 7394 return (result); 7395 } 7396 } 7397 7398 return (ISC_R_SUCCESS); 7399} 7400 7401isc_result_t 7402ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) { 7403 isc_result_t result; 7404 unsigned int n; 7405 dns_view_t *view; 7406 unsigned int foundkeys = 0; 7407 7408 result = isc_task_beginexclusive(server->task); 7409 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7410 for (view = ISC_LIST_HEAD(server->viewlist); 7411 view != NULL; 7412 view = ISC_LIST_NEXT(view, link)) { 7413 RWLOCK(&view->statickeys->lock, isc_rwlocktype_read); 7414 result = list_keynames(view, view->statickeys, text, 7415 &foundkeys); 7416 RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read); 7417 if (result != ISC_R_SUCCESS) { 7418 isc_task_endexclusive(server->task); 7419 return (result); 7420 } 7421 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); 7422 result = list_keynames(view, view->dynamickeys, text, 7423 &foundkeys); 7424 RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); 7425 if (result != ISC_R_SUCCESS) { 7426 isc_task_endexclusive(server->task); 7427 return (result); 7428 } 7429 } 7430 isc_task_endexclusive(server->task); 7431 7432 if (foundkeys == 0) { 7433 n = snprintf((char *)isc_buffer_used(text), 7434 isc_buffer_availablelength(text), 7435 "no tsig keys found.\n"); 7436 if (n >= isc_buffer_availablelength(text)) 7437 return (ISC_R_NOSPACE); 7438 isc_buffer_add(text, n); 7439 } 7440 7441 return (ISC_R_SUCCESS); 7442} 7443 7444/* 7445 * Act on a "sign" or "loadkeys" command from the command channel. 7446 */ 7447isc_result_t 7448ns_server_rekey(ns_server_t *server, char *args) { 7449 isc_result_t result; 7450 dns_zone_t *zone = NULL; 7451 dns_zonetype_t type; 7452 isc_uint16_t keyopts; 7453 isc_boolean_t fullsign = ISC_FALSE; 7454 7455 if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0) 7456 fullsign = ISC_TRUE; 7457 7458 result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); 7459 if (result != ISC_R_SUCCESS) 7460 return (result); 7461 if (zone == NULL) 7462 return (ISC_R_UNEXPECTEDEND); /* XXX: or do all zones? */ 7463 7464 type = dns_zone_gettype(zone); 7465 if (type != dns_zone_master) { 7466 dns_zone_detach(&zone); 7467 return (DNS_R_NOTMASTER); 7468 } 7469 7470 keyopts = dns_zone_getkeyopts(zone); 7471 7472 /* "rndc loadkeys" requires "auto-dnssec maintain". */ 7473 if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) 7474 result = ISC_R_NOPERM; 7475 else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) 7476 result = ISC_R_NOPERM; 7477 else 7478 dns_zone_rekey(zone, fullsign); 7479 7480 dns_zone_detach(&zone); 7481 return (result); 7482} 7483 7484/* 7485 * Act on a "sync" command from the command channel. 7486*/ 7487static isc_result_t 7488synczone(dns_zone_t *zone, void *uap) { 7489 isc_boolean_t cleanup = *(isc_boolean_t *)uap; 7490 isc_result_t result; 7491 dns_zone_t *raw = NULL; 7492 char *journal; 7493 7494 dns_zone_getraw(zone, &raw); 7495 if (raw != NULL) { 7496 synczone(raw, uap); 7497 dns_zone_detach(&raw); 7498 } 7499 7500 result = dns_zone_flush(zone); 7501 if (result != ISC_R_SUCCESS) 7502 cleanup = ISC_FALSE; 7503 if (cleanup) { 7504 journal = dns_zone_getjournal(zone); 7505 if (journal != NULL) 7506 (void)isc_file_remove(journal); 7507 } 7508 7509 return (result); 7510} 7511 7512isc_result_t 7513ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text) { 7514 isc_result_t result, tresult; 7515 dns_view_t *view; 7516 dns_zone_t *zone = NULL; 7517 char classstr[DNS_RDATACLASS_FORMATSIZE]; 7518 char zonename[DNS_NAME_FORMATSIZE]; 7519 const char *vname, *sep, *msg = NULL, *arg; 7520 isc_boolean_t cleanup = ISC_FALSE; 7521 7522 (void) next_token(&args, " \t"); 7523 7524 arg = next_token(&args, " \t"); 7525 if (arg != NULL && 7526 (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) { 7527 cleanup = ISC_TRUE; 7528 arg = next_token(&args, " \t"); 7529 } 7530 7531 result = zone_from_args(server, args, arg, &zone, NULL, ISC_FALSE); 7532 if (result != ISC_R_SUCCESS) 7533 return (result); 7534 7535 if (zone == NULL) { 7536 result = isc_task_beginexclusive(server->task); 7537 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7538 tresult = ISC_R_SUCCESS; 7539 for (view = ISC_LIST_HEAD(server->viewlist); 7540 view != NULL; 7541 view = ISC_LIST_NEXT(view, link)) { 7542 result = dns_zt_apply(view->zonetable, ISC_FALSE, 7543 synczone, &cleanup); 7544 if (result != ISC_R_SUCCESS && 7545 tresult == ISC_R_SUCCESS) 7546 tresult = result; 7547 } 7548 isc_task_endexclusive(server->task); 7549 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7550 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7551 "dumping all zones%s: %s", 7552 cleanup ? ", removing journal files" : "", 7553 isc_result_totext(result)); 7554 return (tresult); 7555 } 7556 7557 result = isc_task_beginexclusive(server->task); 7558 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7559 result = synczone(zone, &cleanup); 7560 isc_task_endexclusive(server->task); 7561 7562 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) 7563 isc_buffer_putmem(text, (const unsigned char *)msg, 7564 strlen(msg) + 1); 7565 7566 view = dns_zone_getview(zone); 7567 if (strcmp(view->name, "_default") == 0 || 7568 strcmp(view->name, "_bind") == 0) 7569 { 7570 vname = ""; 7571 sep = ""; 7572 } else { 7573 vname = view->name; 7574 sep = " "; 7575 } 7576 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 7577 sizeof(classstr)); 7578 dns_name_format(dns_zone_getorigin(zone), 7579 zonename, sizeof(zonename)); 7580 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7581 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7582 "sync: dumping zone '%s/%s'%s%s%s: %s", 7583 zonename, classstr, sep, vname, 7584 cleanup ? ", removing journal file" : "", 7585 isc_result_totext(result)); 7586 dns_zone_detach(&zone); 7587 return (result); 7588} 7589 7590/* 7591 * Act on a "freeze" or "thaw" command from the command channel. 7592 */ 7593isc_result_t 7594ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, 7595 isc_buffer_t *text) 7596{ 7597 isc_result_t result, tresult; 7598 dns_zone_t *zone = NULL, *raw = NULL; 7599 dns_zonetype_t type; 7600 char classstr[DNS_RDATACLASS_FORMATSIZE]; 7601 char zonename[DNS_NAME_FORMATSIZE]; 7602 dns_view_t *view; 7603 const char *vname, *sep; 7604 isc_boolean_t frozen; 7605 const char *msg = NULL; 7606 7607 result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); 7608 if (result != ISC_R_SUCCESS) 7609 return (result); 7610 if (zone == NULL) { 7611 result = isc_task_beginexclusive(server->task); 7612 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7613 tresult = ISC_R_SUCCESS; 7614 for (view = ISC_LIST_HEAD(server->viewlist); 7615 view != NULL; 7616 view = ISC_LIST_NEXT(view, link)) { 7617 result = dns_view_freezezones(view, freeze); 7618 if (result != ISC_R_SUCCESS && 7619 tresult == ISC_R_SUCCESS) 7620 tresult = result; 7621 } 7622 isc_task_endexclusive(server->task); 7623 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7624 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7625 "%s all zones: %s", 7626 freeze ? "freezing" : "thawing", 7627 isc_result_totext(tresult)); 7628 return (tresult); 7629 } 7630 dns_zone_getraw(zone, &raw); 7631 if (raw != NULL) { 7632 dns_zone_detach(&zone); 7633 dns_zone_attach(raw, &zone); 7634 dns_zone_detach(&raw); 7635 } 7636 type = dns_zone_gettype(zone); 7637 if (type != dns_zone_master) { 7638 dns_zone_detach(&zone); 7639 return (DNS_R_NOTMASTER); 7640 } 7641 7642 if (freeze && !dns_zone_isdynamic(zone, ISC_TRUE)) { 7643 dns_zone_detach(&zone); 7644 return (DNS_R_NOTDYNAMIC); 7645 } 7646 7647 result = isc_task_beginexclusive(server->task); 7648 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7649 frozen = dns_zone_getupdatedisabled(zone); 7650 if (freeze) { 7651 if (frozen) { 7652 msg = "WARNING: The zone was already frozen.\n" 7653 "Someone else may be editing it or " 7654 "it may still be re-loading."; 7655 result = DNS_R_FROZEN; 7656 } 7657 if (result == ISC_R_SUCCESS) { 7658 result = dns_zone_flush(zone); 7659 if (result != ISC_R_SUCCESS) 7660 msg = "Flushing the zone updates to " 7661 "disk failed."; 7662 } 7663 if (result == ISC_R_SUCCESS) 7664 dns_zone_setupdatedisabled(zone, freeze); 7665 } else { 7666 if (frozen) { 7667 result = dns_zone_loadandthaw(zone); 7668 switch (result) { 7669 case ISC_R_SUCCESS: 7670 case DNS_R_UPTODATE: 7671 msg = "The zone reload and thaw was " 7672 "successful."; 7673 result = ISC_R_SUCCESS; 7674 break; 7675 case DNS_R_CONTINUE: 7676 msg = "A zone reload and thaw was started.\n" 7677 "Check the logs to see the result."; 7678 result = ISC_R_SUCCESS; 7679 break; 7680 } 7681 } 7682 } 7683 isc_task_endexclusive(server->task); 7684 7685 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) 7686 isc_buffer_putmem(text, (const unsigned char *)msg, 7687 strlen(msg) + 1); 7688 7689 view = dns_zone_getview(zone); 7690 if (strcmp(view->name, "_default") == 0 || 7691 strcmp(view->name, "_bind") == 0) 7692 { 7693 vname = ""; 7694 sep = ""; 7695 } else { 7696 vname = view->name; 7697 sep = " "; 7698 } 7699 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 7700 sizeof(classstr)); 7701 dns_name_format(dns_zone_getorigin(zone), 7702 zonename, sizeof(zonename)); 7703 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7704 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7705 "%s zone '%s/%s'%s%s: %s", 7706 freeze ? "freezing" : "thawing", 7707 zonename, classstr, sep, vname, 7708 isc_result_totext(result)); 7709 dns_zone_detach(&zone); 7710 return (result); 7711} 7712 7713#ifdef HAVE_LIBSCF 7714/* 7715 * This function adds a message for rndc to echo if named 7716 * is managed by smf and is also running chroot. 7717 */ 7718isc_result_t 7719ns_smf_add_message(isc_buffer_t *text) { 7720 unsigned int n; 7721 7722 n = snprintf((char *)isc_buffer_used(text), 7723 isc_buffer_availablelength(text), 7724 "use svcadm(1M) to manage named"); 7725 if (n >= isc_buffer_availablelength(text)) 7726 return (ISC_R_NOSPACE); 7727 isc_buffer_add(text, n); 7728 return (ISC_R_SUCCESS); 7729} 7730#endif /* HAVE_LIBSCF */ 7731 7732/* 7733 * Act on an "addzone" command from the command channel. 7734 */ 7735isc_result_t 7736ns_server_add_zone(ns_server_t *server, char *args) { 7737 isc_result_t result; 7738 isc_buffer_t argbuf; 7739 size_t arglen; 7740 cfg_parser_t *parser = NULL; 7741 cfg_obj_t *config = NULL; 7742 const cfg_obj_t *vconfig = NULL; 7743 const cfg_obj_t *views = NULL; 7744 const cfg_obj_t *parms = NULL; 7745 const cfg_obj_t *obj = NULL; 7746 const cfg_listelt_t *element; 7747 const char *zonename; 7748 const char *classname = NULL; 7749 const char *argp; 7750 const char *viewname = NULL; 7751 dns_rdataclass_t rdclass; 7752 dns_view_t *view = 0; 7753 isc_buffer_t buf, *nbuf = NULL; 7754 dns_name_t dnsname; 7755 dns_zone_t *zone = NULL; 7756 FILE *fp = NULL; 7757 struct cfg_context *cfg = NULL; 7758 7759 /* Try to parse the argument string */ 7760 arglen = strlen(args); 7761 isc_buffer_init(&argbuf, args, arglen); 7762 isc_buffer_add(&argbuf, strlen(args)); 7763 CHECK(cfg_parser_create(server->mctx, ns_g_lctx, &parser)); 7764 CHECK(cfg_parse_buffer(parser, &argbuf, &cfg_type_addzoneconf, 7765 &config)); 7766 CHECK(cfg_map_get(config, "addzone", &parms)); 7767 7768 zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name")); 7769 isc_buffer_constinit(&buf, zonename, strlen(zonename)); 7770 isc_buffer_add(&buf, strlen(zonename)); 7771 dns_name_init(&dnsname, NULL); 7772 isc_buffer_allocate(server->mctx, &nbuf, 256); 7773 dns_name_setbuffer(&dnsname, nbuf); 7774 CHECK(dns_name_fromtext(&dnsname, &buf, dns_rootname, ISC_FALSE, NULL)); 7775 7776 /* Make sense of optional class argument */ 7777 obj = cfg_tuple_get(parms, "class"); 7778 CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass)); 7779 if (rdclass != dns_rdataclass_in && obj) 7780 classname = cfg_obj_asstring(obj); 7781 7782 /* Make sense of optional view argument */ 7783 obj = cfg_tuple_get(parms, "view"); 7784 if (obj && cfg_obj_isstring(obj)) 7785 viewname = cfg_obj_asstring(obj); 7786 if (viewname == NULL || *viewname == '\0') 7787 viewname = "_default"; 7788 CHECK(dns_viewlist_find(&server->viewlist, viewname, rdclass, &view)); 7789 7790 /* Are we accepting new zones? */ 7791 if (view->new_zone_file == NULL) { 7792 result = ISC_R_NOPERM; 7793 goto cleanup; 7794 } 7795 7796 cfg = (struct cfg_context *) view->new_zone_config; 7797 if (cfg == NULL) { 7798 result = ISC_R_FAILURE; 7799 goto cleanup; 7800 } 7801 7802 /* Zone shouldn't already exist */ 7803 result = dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone); 7804 if (result == ISC_R_SUCCESS) { 7805 result = ISC_R_EXISTS; 7806 goto cleanup; 7807 } else if (result == DNS_R_PARTIALMATCH) { 7808 /* Create our sub-zone anyway */ 7809 dns_zone_detach(&zone); 7810 zone = NULL; 7811 } 7812 else if (result != ISC_R_NOTFOUND) 7813 goto cleanup; 7814 7815 /* Find the view statement */ 7816 cfg_map_get(cfg->config, "view", &views); 7817 for (element = cfg_list_first(views); 7818 element != NULL; 7819 element = cfg_list_next(element)) 7820 { 7821 const char *vname; 7822 vconfig = cfg_listelt_value(element); 7823 vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 7824 if (vname && !strcasecmp(vname, viewname)) 7825 break; 7826 vconfig = NULL; 7827 } 7828 7829 /* Open save file for write configuration */ 7830 CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); 7831 7832 /* Mark view unfrozen so that zone can be added */ 7833 result = isc_task_beginexclusive(server->task); 7834 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7835 dns_view_thaw(view); 7836 result = configure_zone(cfg->config, parms, vconfig, 7837 server->mctx, view, cfg->actx, ISC_FALSE); 7838 dns_view_freeze(view); 7839 isc_task_endexclusive(server->task); 7840 if (result != ISC_R_SUCCESS) 7841 goto cleanup; 7842 7843 /* Is it there yet? */ 7844 CHECK(dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone)); 7845 7846 /* 7847 * Load the zone from the master file. If this fails, we'll 7848 * need to undo the configuration we've done already. 7849 */ 7850 result = dns_zone_loadnew(zone); 7851 if (result != ISC_R_SUCCESS) { 7852 dns_db_t *dbp = NULL; 7853 7854 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7855 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7856 "addzone failed; reverting."); 7857 7858 /* If the zone loaded partially, unload it */ 7859 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 7860 dns_db_detach(&dbp); 7861 dns_zone_unload(zone); 7862 } 7863 7864 /* Remove the zone from the zone table */ 7865 dns_zt_unmount(view->zonetable, zone); 7866 goto cleanup; 7867 } 7868 7869 /* Flag the zone as having been added at runtime */ 7870 dns_zone_setadded(zone, ISC_TRUE); 7871 7872 /* Emit just the zone name from args */ 7873 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 7874 CHECK(isc_stdio_write(zonename, strlen(zonename), 1, fp, NULL)); 7875 CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); 7876 7877 /* Classname, if not default */ 7878 if (classname != NULL && *classname != '\0') { 7879 CHECK(isc_stdio_write(classname, strlen(classname), 1, fp, 7880 NULL)); 7881 CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); 7882 } 7883 7884 /* Find beginning of option block from args */ 7885 for (argp = args; *argp; argp++, arglen--) { 7886 if (*argp == '{') { /* Assume matching '}' */ 7887 /* Add that to our file */ 7888 CHECK(isc_stdio_write(argp, arglen, 1, fp, NULL)); 7889 7890 /* Make sure we end with a LF */ 7891 if (argp[arglen-1] != '\n') { 7892 CHECK(isc_stdio_write("\n", 1, 1, fp, NULL)); 7893 } 7894 break; 7895 } 7896 } 7897 7898 CHECK(isc_stdio_close(fp)); 7899 fp = NULL; 7900 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 7901 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 7902 "zone %s added to view %s via addzone", 7903 zonename, viewname); 7904 7905 result = ISC_R_SUCCESS; 7906 7907 cleanup: 7908 if (fp != NULL) 7909 isc_stdio_close(fp); 7910 if (parser != NULL) { 7911 if (config != NULL) 7912 cfg_obj_destroy(parser, &config); 7913 cfg_parser_destroy(&parser); 7914 } 7915 if (zone != NULL) 7916 dns_zone_detach(&zone); 7917 if (view != NULL) 7918 dns_view_detach(&view); 7919 if (nbuf != NULL) 7920 isc_buffer_free(&nbuf); 7921 7922 return (result); 7923} 7924 7925/* 7926 * Act on a "delzone" command from the command channel. 7927 */ 7928isc_result_t 7929ns_server_del_zone(ns_server_t *server, char *args) { 7930 isc_result_t result; 7931 dns_zone_t *zone = NULL; 7932 dns_view_t *view = NULL; 7933 dns_db_t *dbp = NULL; 7934 const char *filename = NULL; 7935 char *tmpname = NULL; 7936 char buf[1024]; 7937 const char *zonename = NULL; 7938 size_t znamelen = 0; 7939 FILE *ifp = NULL, *ofp = NULL; 7940 7941 /* Parse parameters */ 7942 CHECK(zone_from_args(server, args, NULL, &zone, &zonename, ISC_TRUE)); 7943 7944 if (zone == NULL) { 7945 result = ISC_R_UNEXPECTEDEND; 7946 goto cleanup; 7947 } 7948 7949 /* 7950 * Was this zone originally added at runtime? 7951 * If not, we can't delete it now. 7952 */ 7953 if (!dns_zone_getadded(zone)) { 7954 result = ISC_R_NOPERM; 7955 goto cleanup; 7956 } 7957 7958 INSIST(zonename != NULL); 7959 znamelen = strlen(zonename); 7960 7961 /* Dig out configuration for this zone */ 7962 view = dns_zone_getview(zone); 7963 filename = view->new_zone_file; 7964 if (filename == NULL) { 7965 /* No adding zones in this view */ 7966 result = ISC_R_FAILURE; 7967 goto cleanup; 7968 } 7969 7970 /* Rewrite zone list */ 7971 result = isc_stdio_open(filename, "r", &ifp); 7972 if (ifp != NULL && result == ISC_R_SUCCESS) { 7973 char *found = NULL, *p = NULL; 7974 size_t n; 7975 7976 /* Create a temporary file */ 7977 CHECK(isc_string_printf(buf, 1023, "%s.%ld", filename, 7978 (long)getpid())); 7979 if (!(tmpname = isc_mem_strdup(server->mctx, buf))) { 7980 result = ISC_R_NOMEMORY; 7981 goto cleanup; 7982 } 7983 CHECK(isc_stdio_open(tmpname, "w", &ofp)); 7984 7985 /* Look for the entry for that zone */ 7986 while (fgets(buf, 1024, ifp)) { 7987 /* A 'zone' line */ 7988 if (strncasecmp(buf, "zone", 4)) { 7989 fputs(buf, ofp); 7990 continue; 7991 } 7992 p = buf+4; 7993 7994 /* Locate a name */ 7995 while (*p && 7996 ((*p == '"') || isspace((unsigned char)*p))) 7997 p++; 7998 7999 /* Is that the zone we're looking for */ 8000 if (strncasecmp(p, zonename, znamelen)) { 8001 fputs(buf, ofp); 8002 continue; 8003 } 8004 8005 /* And nothing else? */ 8006 p += znamelen; 8007 if (isspace((unsigned char)*p) || 8008 *p == '"' || *p == '{') { 8009 /* This must be the entry */ 8010 found = p; 8011 break; 8012 } 8013 8014 /* Spit it out, keep looking */ 8015 fputs(buf, ofp); 8016 } 8017 8018 /* Skip over an option block (matching # of braces) */ 8019 if (found) { 8020 int obrace = 0, cbrace = 0; 8021 for (;;) { 8022 while (*p) { 8023 if (*p == '{') obrace++; 8024 if (*p == '}') cbrace++; 8025 p++; 8026 } 8027 if (obrace && (obrace == cbrace)) 8028 break; 8029 if (!fgets(buf, 1024, ifp)) 8030 break; 8031 p = buf; 8032 } 8033 8034 /* Just spool the remainder of the file out */ 8035 result = isc_stdio_read(buf, 1, 1024, ifp, &n); 8036 while (n > 0U) { 8037 if (result == ISC_R_EOF) 8038 result = ISC_R_SUCCESS; 8039 CHECK(result); 8040 isc_stdio_write(buf, 1, n, ofp, NULL); 8041 result = isc_stdio_read(buf, 1, 1024, ifp, &n); 8042 } 8043 8044 /* Move temporary into place */ 8045 CHECK(isc_file_rename(tmpname, view->new_zone_file)); 8046 } else { 8047 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 8048 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 8049 "deleted zone %s was missing from " 8050 "new zone file", zonename); 8051 goto cleanup; 8052 } 8053 } 8054 8055 /* Stop answering for this zone */ 8056 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 8057 dns_db_detach(&dbp); 8058 dns_zone_unload(zone); 8059 } 8060 8061 CHECK(dns_zt_unmount(view->zonetable, zone)); 8062 8063 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 8064 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 8065 "zone %s removed via delzone", zonename); 8066 8067 result = ISC_R_SUCCESS; 8068 8069 cleanup: 8070 if (ifp != NULL) 8071 isc_stdio_close(ifp); 8072 if (ofp != NULL) { 8073 isc_stdio_close(ofp); 8074 isc_file_remove(tmpname); 8075 } 8076 if (tmpname != NULL) 8077 isc_mem_free(server->mctx, tmpname); 8078 if (zone != NULL) 8079 dns_zone_detach(&zone); 8080 8081 return (result); 8082} 8083 8084static void 8085newzone_cfgctx_destroy(void **cfgp) { 8086 struct cfg_context *cfg; 8087 8088 REQUIRE(cfgp != NULL && *cfgp != NULL); 8089 8090 cfg = *cfgp; 8091 8092 if (cfg->actx != NULL) 8093 cfg_aclconfctx_detach(&cfg->actx); 8094 8095 if (cfg->parser != NULL) { 8096 if (cfg->config != NULL) 8097 cfg_obj_destroy(cfg->parser, &cfg->config); 8098 cfg_parser_destroy(&cfg->parser); 8099 } 8100 if (cfg->nzparser != NULL) { 8101 if (cfg->nzconfig != NULL) 8102 cfg_obj_destroy(cfg->nzparser, &cfg->nzconfig); 8103 cfg_parser_destroy(&cfg->nzparser); 8104 } 8105 8106 isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); 8107 *cfgp = NULL; 8108} 8109 8110isc_result_t 8111ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text) { 8112 isc_result_t result = ISC_R_SUCCESS; 8113 dns_zone_t *zone = NULL; 8114 dns_name_t *origin; 8115 dns_db_t *db = NULL; 8116 dns_dbnode_t *node = NULL; 8117 dns_dbversion_t *version = NULL; 8118 dns_rdatatype_t privatetype; 8119 dns_rdataset_t privset; 8120 isc_boolean_t first = ISC_TRUE; 8121 isc_boolean_t list = ISC_FALSE, clear = ISC_FALSE; 8122 isc_boolean_t chain = ISC_FALSE; 8123 char keystr[DNS_SECALG_FORMATSIZE + 7]; 8124 unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; 8125 unsigned char salt[255]; 8126 const char *ptr; 8127 size_t n; 8128 8129 dns_rdataset_init(&privset); 8130 8131 /* Skip the command name. */ 8132 ptr = next_token(&args, " \t"); 8133 if (ptr == NULL) 8134 return (ISC_R_UNEXPECTEDEND); 8135 8136 /* Find out what we are to do. */ 8137 ptr = next_token(&args, " \t"); 8138 if (ptr == NULL) 8139 return (ISC_R_UNEXPECTEDEND); 8140 8141 if (strcasecmp(ptr, "-list") == 0) 8142 list = ISC_TRUE; 8143 else if ((strcasecmp(ptr, "-clear") == 0) || 8144 (strcasecmp(ptr, "-clean") == 0)) { 8145 clear = ISC_TRUE; 8146 ptr = next_token(&args, " \t"); 8147 if (ptr == NULL) 8148 return (ISC_R_UNEXPECTEDEND); 8149 memcpy(keystr, ptr, sizeof(keystr)); 8150 } else if(strcasecmp(ptr, "-nsec3param") == 0) { 8151 const char *hashstr, *flagstr, *iterstr; 8152 char nbuf[512]; 8153 8154 chain = ISC_TRUE; 8155 hashstr = next_token(&args, " \t"); 8156 if (hashstr == NULL) 8157 return (ISC_R_UNEXPECTEDEND); 8158 8159 if (strcasecmp(hashstr, "none") == 0) 8160 hash = 0; 8161 else { 8162 flagstr = next_token(&args, " \t"); 8163 iterstr = next_token(&args, " \t"); 8164 if (flagstr == NULL || iterstr == NULL) 8165 return (ISC_R_UNEXPECTEDEND); 8166 8167 n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", 8168 hashstr, flagstr, iterstr); 8169 if (n == sizeof(nbuf)) 8170 return (ISC_R_NOSPACE); 8171 n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); 8172 if (n != 3U) 8173 return (ISC_R_BADNUMBER); 8174 8175 if (hash > 0xffU || flags > 0xffU) 8176 return (ISC_R_RANGE); 8177 8178 ptr = next_token(&args, " \t"); 8179 if (ptr == NULL) 8180 return (ISC_R_UNEXPECTEDEND); 8181 if (strcmp(ptr, "-") != 0) { 8182 isc_buffer_t buf; 8183 8184 isc_buffer_init(&buf, salt, sizeof(salt)); 8185 CHECK(isc_hex_decodestring(ptr, &buf)); 8186 saltlen = isc_buffer_usedlength(&buf); 8187 } 8188 } 8189 } else 8190 CHECK(DNS_R_SYNTAX); 8191 8192 CHECK(zone_from_args(server, args, NULL, &zone, NULL, ISC_FALSE)); 8193 if (zone == NULL) 8194 CHECK(ISC_R_UNEXPECTEDEND); 8195 8196 if (clear) { 8197 CHECK(dns_zone_keydone(zone, keystr)); 8198 isc_buffer_putstr(text, "request queued"); 8199 isc_buffer_putuint8(text, 0); 8200 } else if (chain) { 8201 CHECK(dns_zone_setnsec3param(zone, (isc_uint8_t)hash, 8202 (isc_uint8_t)flags, iter, 8203 (isc_uint8_t)saltlen, salt, 8204 ISC_TRUE)); 8205 isc_buffer_putstr(text, "request queued"); 8206 isc_buffer_putuint8(text, 0); 8207 } else if (list) { 8208 privatetype = dns_zone_getprivatetype(zone); 8209 origin = dns_zone_getorigin(zone); 8210 CHECK(dns_zone_getdb(zone, &db)); 8211 CHECK(dns_db_findnode(db, origin, ISC_FALSE, &node)); 8212 dns_db_currentversion(db, &version); 8213 8214 result = dns_db_findrdataset(db, node, version, privatetype, 8215 dns_rdatatype_none, 0, 8216 &privset, NULL); 8217 if (result == ISC_R_NOTFOUND) { 8218 isc_buffer_putstr(text, "No signing records found"); 8219 isc_buffer_putuint8(text, 0); 8220 result = ISC_R_SUCCESS; 8221 goto cleanup; 8222 } 8223 8224 for (result = dns_rdataset_first(&privset); 8225 result == ISC_R_SUCCESS; 8226 result = dns_rdataset_next(&privset)) 8227 { 8228 dns_rdata_t priv = DNS_RDATA_INIT; 8229 char output[BUFSIZ]; 8230 isc_buffer_t buf; 8231 8232 dns_rdataset_current(&privset, &priv); 8233 8234 isc_buffer_init(&buf, output, sizeof(output)); 8235 CHECK(dns_private_totext(&priv, &buf)); 8236 8237 if (!first) 8238 isc_buffer_putstr(text, "\n"); 8239 first = ISC_FALSE; 8240 8241 n = snprintf((char *)isc_buffer_used(text), 8242 isc_buffer_availablelength(text), 8243 "%s", output); 8244 if (n >= isc_buffer_availablelength(text)) 8245 CHECK(ISC_R_NOSPACE); 8246 8247 isc_buffer_add(text, n); 8248 } 8249 8250 if (result == ISC_R_NOMORE) 8251 result = ISC_R_SUCCESS; 8252 } 8253 8254 cleanup: 8255 if (dns_rdataset_isassociated(&privset)) 8256 dns_rdataset_disassociate(&privset); 8257 if (node != NULL) 8258 dns_db_detachnode(db, &node); 8259 if (version != NULL) 8260 dns_db_closeversion(db, &version, ISC_FALSE); 8261 if (db != NULL) 8262 dns_db_detach(&db); 8263 if (zone != NULL) 8264 dns_zone_detach(&zone); 8265 8266 return (result); 8267} 8268