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