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