1/* $NetBSD: view.c,v 1.15 2024/02/21 22:52:08 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16/*! \file */ 17 18#include <inttypes.h> 19#include <limits.h> 20#include <stdbool.h> 21 22#ifdef HAVE_LMDB 23#include <lmdb.h> 24#endif /* ifdef HAVE_LMDB */ 25 26#include <isc/atomic.h> 27#include <isc/dir.h> 28#include <isc/file.h> 29#include <isc/hash.h> 30#include <isc/lex.h> 31#include <isc/print.h> 32#include <isc/result.h> 33#include <isc/stats.h> 34#include <isc/string.h> /* Required for HP/UX (and others?) */ 35#include <isc/task.h> 36#include <isc/util.h> 37 38#include <dns/acl.h> 39#include <dns/adb.h> 40#include <dns/badcache.h> 41#include <dns/cache.h> 42#include <dns/db.h> 43#include <dns/dispatch.h> 44#include <dns/dlz.h> 45#include <dns/dns64.h> 46#include <dns/dnssec.h> 47#include <dns/events.h> 48#include <dns/forward.h> 49#include <dns/keytable.h> 50#include <dns/keyvalues.h> 51#include <dns/master.h> 52#include <dns/masterdump.h> 53#include <dns/nta.h> 54#include <dns/order.h> 55#include <dns/peer.h> 56#include <dns/rbt.h> 57#include <dns/rdataset.h> 58#include <dns/request.h> 59#include <dns/resolver.h> 60#include <dns/rpz.h> 61#include <dns/rrl.h> 62#include <dns/stats.h> 63#include <dns/time.h> 64#include <dns/transport.h> 65#include <dns/tsig.h> 66#include <dns/zone.h> 67#include <dns/zt.h> 68 69#define CHECK(op) \ 70 do { \ 71 result = (op); \ 72 if (result != ISC_R_SUCCESS) \ 73 goto cleanup; \ 74 } while (0) 75 76#define RESSHUTDOWN(v) \ 77 ((atomic_load(&(v)->attributes) & DNS_VIEWATTR_RESSHUTDOWN) != 0) 78#define ADBSHUTDOWN(v) \ 79 ((atomic_load(&(v)->attributes) & DNS_VIEWATTR_ADBSHUTDOWN) != 0) 80#define REQSHUTDOWN(v) \ 81 ((atomic_load(&(v)->attributes) & DNS_VIEWATTR_REQSHUTDOWN) != 0) 82 83#define DNS_VIEW_DELONLYHASH 111 84#define DNS_VIEW_FAILCACHESIZE 1021 85 86static void 87resolver_shutdown(isc_task_t *task, isc_event_t *event); 88static void 89adb_shutdown(isc_task_t *task, isc_event_t *event); 90static void 91req_shutdown(isc_task_t *task, isc_event_t *event); 92 93isc_result_t 94dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name, 95 dns_view_t **viewp) { 96 dns_view_t *view; 97 isc_result_t result; 98 char buffer[1024]; 99 100 /* 101 * Create a view. 102 */ 103 104 REQUIRE(name != NULL); 105 REQUIRE(viewp != NULL && *viewp == NULL); 106 107 view = isc_mem_get(mctx, sizeof(*view)); 108 109 view->nta_file = NULL; 110 view->mctx = NULL; 111 isc_mem_attach(mctx, &view->mctx); 112 view->name = isc_mem_strdup(mctx, name); 113 114 result = isc_file_sanitize(NULL, view->name, "nta", buffer, 115 sizeof(buffer)); 116 if (result != ISC_R_SUCCESS) { 117 goto cleanup_name; 118 } 119 view->nta_file = isc_mem_strdup(mctx, buffer); 120 121 isc_mutex_init(&view->lock); 122 123 isc_rwlock_init(&view->sfd_lock, 0, 0); 124 125 view->zonetable = NULL; 126 result = dns_zt_create(mctx, rdclass, &view->zonetable); 127 if (result != ISC_R_SUCCESS) { 128 UNEXPECTED_ERROR("dns_zt_create() failed: %s", 129 isc_result_totext(result)); 130 result = ISC_R_UNEXPECTED; 131 goto cleanup_mutex; 132 } 133 134 view->secroots_priv = NULL; 135 view->ntatable_priv = NULL; 136 view->fwdtable = NULL; 137 result = dns_fwdtable_create(mctx, &view->fwdtable); 138 if (result != ISC_R_SUCCESS) { 139 UNEXPECTED_ERROR("dns_fwdtable_create() failed: %s", 140 isc_result_totext(result)); 141 result = ISC_R_UNEXPECTED; 142 goto cleanup_zt; 143 } 144 145 view->cache = NULL; 146 view->cachedb = NULL; 147 ISC_LIST_INIT(view->dlz_searched); 148 ISC_LIST_INIT(view->dlz_unsearched); 149 view->hints = NULL; 150 view->resolver = NULL; 151 view->adb = NULL; 152 view->requestmgr = NULL; 153 view->rdclass = rdclass; 154 view->frozen = false; 155 view->task = NULL; 156 isc_refcount_init(&view->references, 1); 157 isc_refcount_init(&view->weakrefs, 1); 158 atomic_init(&view->attributes, 159 (DNS_VIEWATTR_RESSHUTDOWN | DNS_VIEWATTR_ADBSHUTDOWN | 160 DNS_VIEWATTR_REQSHUTDOWN)); 161 view->transports = NULL; 162 view->statickeys = NULL; 163 view->dynamickeys = NULL; 164 view->matchclients = NULL; 165 view->matchdestinations = NULL; 166 view->matchrecursiveonly = false; 167 result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys); 168 if (result != ISC_R_SUCCESS) { 169 goto cleanup_weakrefs; 170 } 171 view->peers = NULL; 172 view->order = NULL; 173 view->delonly = NULL; 174 view->rootdelonly = false; 175 view->rootexclude = NULL; 176 view->adbstats = NULL; 177 view->resstats = NULL; 178 view->resquerystats = NULL; 179 view->cacheshared = false; 180 ISC_LIST_INIT(view->dns64); 181 view->dns64cnt = 0; 182 183 /* 184 * Initialize configuration data with default values. 185 */ 186 view->recursion = true; 187 view->qminimization = false; 188 view->qmin_strict = false; 189 view->auth_nxdomain = false; /* Was true in BIND 8 */ 190 view->enablevalidation = true; 191 view->acceptexpired = false; 192 view->use_glue_cache = false; 193 view->minimal_any = false; 194 view->minimalresponses = dns_minimal_no; 195 view->transfer_format = dns_one_answer; 196 view->cacheacl = NULL; 197 view->cacheonacl = NULL; 198 view->checknames = false; 199 view->queryacl = NULL; 200 view->queryonacl = NULL; 201 view->recursionacl = NULL; 202 view->recursiononacl = NULL; 203 view->sortlist = NULL; 204 view->transferacl = NULL; 205 view->notifyacl = NULL; 206 view->updateacl = NULL; 207 view->upfwdacl = NULL; 208 view->denyansweracl = NULL; 209 view->nocasecompress = NULL; 210 view->msgcompression = true; 211 view->answeracl_exclude = NULL; 212 view->denyanswernames = NULL; 213 view->answernames_exclude = NULL; 214 view->rrl = NULL; 215 view->sfd = NULL; 216 view->provideixfr = true; 217 view->maxcachettl = 7 * 24 * 3600; 218 view->maxncachettl = 3 * 3600; 219 view->mincachettl = 0; 220 view->minncachettl = 0; 221 view->nta_lifetime = 0; 222 view->nta_recheck = 0; 223 view->prefetch_eligible = 0; 224 view->prefetch_trigger = 0; 225 view->dstport = 53; 226 view->preferred_glue = 0; 227 view->flush = false; 228 view->maxudp = 0; 229 view->staleanswerttl = 1; 230 view->staleanswersok = dns_stale_answer_conf; 231 view->staleanswersenable = false; 232 view->nocookieudp = 0; 233 view->padding = 0; 234 view->pad_acl = NULL; 235 view->maxbits = 0; 236 view->rpzs = NULL; 237 view->catzs = NULL; 238 view->managed_keys = NULL; 239 view->redirect = NULL; 240 view->redirectzone = NULL; 241 dns_fixedname_init(&view->redirectfixed); 242 view->requestnsid = false; 243 view->sendcookie = true; 244 view->requireservercookie = false; 245 view->synthfromdnssec = true; 246 view->trust_anchor_telemetry = true; 247 view->root_key_sentinel = true; 248 view->new_zone_dir = NULL; 249 view->new_zone_file = NULL; 250 view->new_zone_db = NULL; 251 view->new_zone_dbenv = NULL; 252 view->new_zone_mapsize = 0ULL; 253 view->new_zone_config = NULL; 254 view->cfg_destroy = NULL; 255 view->fail_ttl = 0; 256 view->failcache = NULL; 257 result = dns_badcache_init(view->mctx, DNS_VIEW_FAILCACHESIZE, 258 &view->failcache); 259 if (result != ISC_R_SUCCESS) { 260 goto cleanup_dynkeys; 261 } 262 view->v6bias = 0; 263 view->dtenv = NULL; 264 view->dttypes = 0; 265 266 view->plugins = NULL; 267 view->plugins_free = NULL; 268 view->hooktable = NULL; 269 view->hooktable_free = NULL; 270 271 isc_mutex_init(&view->new_zone_lock); 272 273 result = dns_order_create(view->mctx, &view->order); 274 if (result != ISC_R_SUCCESS) { 275 goto cleanup_new_zone_lock; 276 } 277 278 result = dns_peerlist_new(view->mctx, &view->peers); 279 if (result != ISC_R_SUCCESS) { 280 goto cleanup_order; 281 } 282 283 result = dns_aclenv_create(view->mctx, &view->aclenv); 284 if (result != ISC_R_SUCCESS) { 285 goto cleanup_peerlist; 286 } 287 288 ISC_LINK_INIT(view, link); 289 ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL, 290 DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, view, NULL, 291 NULL, NULL); 292 ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL, 293 DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, view, NULL, 294 NULL, NULL); 295 ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL, 296 DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, view, NULL, 297 NULL, NULL); 298 view->viewlist = NULL; 299 view->magic = DNS_VIEW_MAGIC; 300 301 *viewp = view; 302 303 return (ISC_R_SUCCESS); 304 305cleanup_peerlist: 306 if (view->peers != NULL) { 307 dns_peerlist_detach(&view->peers); 308 } 309 310cleanup_order: 311 if (view->order != NULL) { 312 dns_order_detach(&view->order); 313 } 314 315cleanup_new_zone_lock: 316 isc_mutex_destroy(&view->new_zone_lock); 317 318 dns_badcache_destroy(&view->failcache); 319 320cleanup_dynkeys: 321 if (view->dynamickeys != NULL) { 322 dns_tsigkeyring_detach(&view->dynamickeys); 323 } 324 325cleanup_weakrefs: 326 isc_refcount_decrementz(&view->weakrefs); 327 isc_refcount_destroy(&view->weakrefs); 328 329 isc_refcount_decrementz(&view->references); 330 isc_refcount_destroy(&view->references); 331 332 if (view->fwdtable != NULL) { 333 dns_fwdtable_destroy(&view->fwdtable); 334 } 335 336cleanup_zt: 337 if (view->zonetable != NULL) { 338 dns_zt_detach(&view->zonetable); 339 } 340 341cleanup_mutex: 342 isc_rwlock_destroy(&view->sfd_lock); 343 isc_mutex_destroy(&view->lock); 344 345 if (view->nta_file != NULL) { 346 isc_mem_free(mctx, view->nta_file); 347 } 348 349cleanup_name: 350 isc_mem_free(mctx, view->name); 351 isc_mem_putanddetach(&view->mctx, view, sizeof(*view)); 352 353 return (result); 354} 355 356static void 357destroy(dns_view_t *view) { 358 dns_dns64_t *dns64; 359 dns_dlzdb_t *dlzdb; 360 361 REQUIRE(!ISC_LINK_LINKED(view, link)); 362 REQUIRE(RESSHUTDOWN(view)); 363 REQUIRE(ADBSHUTDOWN(view)); 364 REQUIRE(REQSHUTDOWN(view)); 365 366 isc_refcount_destroy(&view->references); 367 isc_refcount_destroy(&view->weakrefs); 368 369 if (view->order != NULL) { 370 dns_order_detach(&view->order); 371 } 372 if (view->peers != NULL) { 373 dns_peerlist_detach(&view->peers); 374 } 375 376 if (view->dynamickeys != NULL) { 377 isc_result_t result; 378 char template[PATH_MAX]; 379 char keyfile[PATH_MAX]; 380 FILE *fp = NULL; 381 382 result = isc_file_mktemplate(NULL, template, sizeof(template)); 383 if (result == ISC_R_SUCCESS) { 384 (void)isc_file_openuniqueprivate(template, &fp); 385 } 386 if (fp == NULL) { 387 dns_tsigkeyring_detach(&view->dynamickeys); 388 } else { 389 result = dns_tsigkeyring_dumpanddetach( 390 &view->dynamickeys, fp); 391 if (result == ISC_R_SUCCESS) { 392 if (fclose(fp) == 0) { 393 result = isc_file_sanitize( 394 NULL, view->name, "tsigkeys", 395 keyfile, sizeof(keyfile)); 396 if (result == ISC_R_SUCCESS) { 397 result = isc_file_rename( 398 template, keyfile); 399 } 400 } 401 if (result != ISC_R_SUCCESS) { 402 (void)remove(template); 403 } 404 } else { 405 (void)fclose(fp); 406 (void)remove(template); 407 } 408 } 409 } 410 if (view->transports != NULL) { 411 dns_transport_list_detach(&view->transports); 412 } 413 if (view->statickeys != NULL) { 414 dns_tsigkeyring_detach(&view->statickeys); 415 } 416 if (view->adb != NULL) { 417 dns_adb_detach(&view->adb); 418 } 419 if (view->resolver != NULL) { 420 dns_resolver_detach(&view->resolver); 421 } 422 dns_rrl_view_destroy(view); 423 if (view->rpzs != NULL) { 424 dns_rpz_shutdown_rpzs(view->rpzs); 425 dns_rpz_detach_rpzs(&view->rpzs); 426 } 427 if (view->catzs != NULL) { 428 dns_catz_shutdown_catzs(view->catzs); 429 dns_catz_detach_catzs(&view->catzs); 430 } 431 for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL; 432 dlzdb = ISC_LIST_HEAD(view->dlz_searched)) 433 { 434 ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link); 435 dns_dlzdestroy(&dlzdb); 436 } 437 for (dlzdb = ISC_LIST_HEAD(view->dlz_unsearched); dlzdb != NULL; 438 dlzdb = ISC_LIST_HEAD(view->dlz_unsearched)) 439 { 440 ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link); 441 dns_dlzdestroy(&dlzdb); 442 } 443 if (view->requestmgr != NULL) { 444 dns_requestmgr_detach(&view->requestmgr); 445 } 446 if (view->task != NULL) { 447 isc_task_detach(&view->task); 448 } 449 if (view->hints != NULL) { 450 dns_db_detach(&view->hints); 451 } 452 if (view->cachedb != NULL) { 453 dns_db_detach(&view->cachedb); 454 } 455 if (view->cache != NULL) { 456 dns_cache_detach(&view->cache); 457 } 458 if (view->nocasecompress != NULL) { 459 dns_acl_detach(&view->nocasecompress); 460 } 461 if (view->matchclients != NULL) { 462 dns_acl_detach(&view->matchclients); 463 } 464 if (view->matchdestinations != NULL) { 465 dns_acl_detach(&view->matchdestinations); 466 } 467 if (view->cacheacl != NULL) { 468 dns_acl_detach(&view->cacheacl); 469 } 470 if (view->cacheonacl != NULL) { 471 dns_acl_detach(&view->cacheonacl); 472 } 473 if (view->queryacl != NULL) { 474 dns_acl_detach(&view->queryacl); 475 } 476 if (view->queryonacl != NULL) { 477 dns_acl_detach(&view->queryonacl); 478 } 479 if (view->recursionacl != NULL) { 480 dns_acl_detach(&view->recursionacl); 481 } 482 if (view->recursiononacl != NULL) { 483 dns_acl_detach(&view->recursiononacl); 484 } 485 if (view->sortlist != NULL) { 486 dns_acl_detach(&view->sortlist); 487 } 488 if (view->transferacl != NULL) { 489 dns_acl_detach(&view->transferacl); 490 } 491 if (view->notifyacl != NULL) { 492 dns_acl_detach(&view->notifyacl); 493 } 494 if (view->updateacl != NULL) { 495 dns_acl_detach(&view->updateacl); 496 } 497 if (view->upfwdacl != NULL) { 498 dns_acl_detach(&view->upfwdacl); 499 } 500 if (view->denyansweracl != NULL) { 501 dns_acl_detach(&view->denyansweracl); 502 } 503 if (view->pad_acl != NULL) { 504 dns_acl_detach(&view->pad_acl); 505 } 506 if (view->answeracl_exclude != NULL) { 507 dns_rbt_destroy(&view->answeracl_exclude); 508 } 509 if (view->denyanswernames != NULL) { 510 dns_rbt_destroy(&view->denyanswernames); 511 } 512 if (view->answernames_exclude != NULL) { 513 dns_rbt_destroy(&view->answernames_exclude); 514 } 515 if (view->sfd != NULL) { 516 dns_rbt_destroy(&view->sfd); 517 } 518 if (view->delonly != NULL) { 519 dns_name_t *name; 520 int i; 521 522 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 523 name = ISC_LIST_HEAD(view->delonly[i]); 524 while (name != NULL) { 525 ISC_LIST_UNLINK(view->delonly[i], name, link); 526 dns_name_free(name, view->mctx); 527 isc_mem_put(view->mctx, name, sizeof(*name)); 528 name = ISC_LIST_HEAD(view->delonly[i]); 529 } 530 } 531 isc_mem_put(view->mctx, view->delonly, 532 sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH); 533 view->delonly = NULL; 534 } 535 if (view->rootexclude != NULL) { 536 dns_name_t *name; 537 int i; 538 539 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 540 name = ISC_LIST_HEAD(view->rootexclude[i]); 541 while (name != NULL) { 542 ISC_LIST_UNLINK(view->rootexclude[i], name, 543 link); 544 dns_name_free(name, view->mctx); 545 isc_mem_put(view->mctx, name, sizeof(*name)); 546 name = ISC_LIST_HEAD(view->rootexclude[i]); 547 } 548 } 549 isc_mem_put(view->mctx, view->rootexclude, 550 sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH); 551 view->rootexclude = NULL; 552 } 553 if (view->adbstats != NULL) { 554 isc_stats_detach(&view->adbstats); 555 } 556 if (view->resstats != NULL) { 557 isc_stats_detach(&view->resstats); 558 } 559 if (view->resquerystats != NULL) { 560 dns_stats_detach(&view->resquerystats); 561 } 562 if (view->secroots_priv != NULL) { 563 dns_keytable_detach(&view->secroots_priv); 564 } 565 if (view->ntatable_priv != NULL) { 566 dns_ntatable_detach(&view->ntatable_priv); 567 } 568 for (dns64 = ISC_LIST_HEAD(view->dns64); dns64 != NULL; 569 dns64 = ISC_LIST_HEAD(view->dns64)) 570 { 571 dns_dns64_unlink(&view->dns64, dns64); 572 dns_dns64_destroy(&dns64); 573 } 574 if (view->managed_keys != NULL) { 575 dns_zone_detach(&view->managed_keys); 576 } 577 if (view->redirect != NULL) { 578 dns_zone_detach(&view->redirect); 579 } 580#ifdef HAVE_DNSTAP 581 if (view->dtenv != NULL) { 582 dns_dt_detach(&view->dtenv); 583 } 584#endif /* HAVE_DNSTAP */ 585 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 586 if (view->new_zone_file != NULL) { 587 isc_mem_free(view->mctx, view->new_zone_file); 588 view->new_zone_file = NULL; 589 } 590 if (view->new_zone_dir != NULL) { 591 isc_mem_free(view->mctx, view->new_zone_dir); 592 view->new_zone_dir = NULL; 593 } 594#ifdef HAVE_LMDB 595 if (view->new_zone_dbenv != NULL) { 596 mdb_env_close((MDB_env *)view->new_zone_dbenv); 597 view->new_zone_dbenv = NULL; 598 } 599 if (view->new_zone_db != NULL) { 600 isc_mem_free(view->mctx, view->new_zone_db); 601 view->new_zone_db = NULL; 602 } 603#endif /* HAVE_LMDB */ 604 dns_fwdtable_destroy(&view->fwdtable); 605 dns_aclenv_detach(&view->aclenv); 606 if (view->failcache != NULL) { 607 dns_badcache_destroy(&view->failcache); 608 } 609 isc_mutex_destroy(&view->new_zone_lock); 610 isc_rwlock_destroy(&view->sfd_lock); 611 isc_mutex_destroy(&view->lock); 612 isc_refcount_destroy(&view->references); 613 isc_refcount_destroy(&view->weakrefs); 614 isc_mem_free(view->mctx, view->nta_file); 615 isc_mem_free(view->mctx, view->name); 616 if (view->hooktable != NULL && view->hooktable_free != NULL) { 617 view->hooktable_free(view->mctx, &view->hooktable); 618 } 619 if (view->plugins != NULL && view->plugins_free != NULL) { 620 view->plugins_free(view->mctx, &view->plugins); 621 } 622 isc_mem_putanddetach(&view->mctx, view, sizeof(*view)); 623} 624 625void 626dns_view_attach(dns_view_t *source, dns_view_t **targetp) { 627 REQUIRE(DNS_VIEW_VALID(source)); 628 REQUIRE(targetp != NULL && *targetp == NULL); 629 630 isc_refcount_increment(&source->references); 631 632 *targetp = source; 633} 634 635static void 636view_flushanddetach(dns_view_t **viewp, bool flush) { 637 REQUIRE(viewp != NULL && DNS_VIEW_VALID(*viewp)); 638 dns_view_t *view = *viewp; 639 *viewp = NULL; 640 641 if (flush) { 642 view->flush = flush; 643 } 644 645 if (isc_refcount_decrement(&view->references) == 1) { 646 dns_zone_t *mkzone = NULL, *rdzone = NULL; 647 dns_zt_t *zt = NULL; 648 649 isc_refcount_destroy(&view->references); 650 651 if (!RESSHUTDOWN(view)) { 652 dns_resolver_shutdown(view->resolver); 653 } 654 if (!ADBSHUTDOWN(view)) { 655 dns_adb_shutdown(view->adb); 656 } 657 if (!REQSHUTDOWN(view)) { 658 dns_requestmgr_shutdown(view->requestmgr); 659 } 660 661 LOCK(&view->lock); 662 663 if (view->zonetable != NULL) { 664 zt = view->zonetable; 665 view->zonetable = NULL; 666 if (view->flush) { 667 dns_zt_flush(zt); 668 } 669 } 670 671 if (view->managed_keys != NULL) { 672 mkzone = view->managed_keys; 673 view->managed_keys = NULL; 674 if (view->flush) { 675 dns_zone_flush(mkzone); 676 } 677 } 678 if (view->redirect != NULL) { 679 rdzone = view->redirect; 680 view->redirect = NULL; 681 if (view->flush) { 682 dns_zone_flush(rdzone); 683 } 684 } 685 if (view->catzs != NULL) { 686 dns_catz_shutdown_catzs(view->catzs); 687 dns_catz_detach_catzs(&view->catzs); 688 } 689 if (view->ntatable_priv != NULL) { 690 dns_ntatable_shutdown(view->ntatable_priv); 691 } 692 UNLOCK(&view->lock); 693 694 /* Need to detach zt and zones outside view lock */ 695 if (zt != NULL) { 696 dns_zt_detach(&zt); 697 } 698 699 if (mkzone != NULL) { 700 dns_zone_detach(&mkzone); 701 } 702 703 if (rdzone != NULL) { 704 dns_zone_detach(&rdzone); 705 } 706 707 dns_view_weakdetach(&view); 708 } 709} 710 711void 712dns_view_flushanddetach(dns_view_t **viewp) { 713 view_flushanddetach(viewp, true); 714} 715 716void 717dns_view_detach(dns_view_t **viewp) { 718 view_flushanddetach(viewp, false); 719} 720 721static isc_result_t 722dialup(dns_zone_t *zone, void *dummy) { 723 UNUSED(dummy); 724 dns_zone_dialup(zone); 725 return (ISC_R_SUCCESS); 726} 727 728void 729dns_view_dialup(dns_view_t *view) { 730 REQUIRE(DNS_VIEW_VALID(view)); 731 REQUIRE(view->zonetable != NULL); 732 733 (void)dns_zt_apply(view->zonetable, isc_rwlocktype_read, false, NULL, 734 dialup, NULL); 735} 736 737void 738dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) { 739 REQUIRE(DNS_VIEW_VALID(source)); 740 REQUIRE(targetp != NULL && *targetp == NULL); 741 742 isc_refcount_increment(&source->weakrefs); 743 744 *targetp = source; 745} 746 747void 748dns_view_weakdetach(dns_view_t **viewp) { 749 dns_view_t *view; 750 751 REQUIRE(viewp != NULL); 752 view = *viewp; 753 *viewp = NULL; 754 REQUIRE(DNS_VIEW_VALID(view)); 755 756 if (isc_refcount_decrement(&view->weakrefs) == 1) { 757 destroy(view); 758 } 759} 760 761static void 762resolver_shutdown(isc_task_t *task, isc_event_t *event) { 763 dns_view_t *view = event->ev_arg; 764 765 REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN); 766 REQUIRE(DNS_VIEW_VALID(view)); 767 REQUIRE(view->task == task); 768 769 UNUSED(task); 770 771 isc_event_free(&event); 772 773 atomic_fetch_or(&view->attributes, DNS_VIEWATTR_RESSHUTDOWN); 774 dns_view_weakdetach(&view); 775} 776 777static void 778adb_shutdown(isc_task_t *task, isc_event_t *event) { 779 dns_view_t *view = event->ev_arg; 780 781 REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN); 782 REQUIRE(DNS_VIEW_VALID(view)); 783 REQUIRE(view->task == task); 784 785 UNUSED(task); 786 787 isc_event_free(&event); 788 789 atomic_fetch_or(&view->attributes, DNS_VIEWATTR_ADBSHUTDOWN); 790 791 dns_view_weakdetach(&view); 792} 793 794static void 795req_shutdown(isc_task_t *task, isc_event_t *event) { 796 dns_view_t *view = event->ev_arg; 797 798 REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN); 799 REQUIRE(DNS_VIEW_VALID(view)); 800 REQUIRE(view->task == task); 801 802 UNUSED(task); 803 804 isc_event_free(&event); 805 806 atomic_fetch_or(&view->attributes, DNS_VIEWATTR_REQSHUTDOWN); 807 808 dns_view_weakdetach(&view); 809} 810 811isc_result_t 812dns_view_createzonetable(dns_view_t *view) { 813 REQUIRE(DNS_VIEW_VALID(view)); 814 REQUIRE(!view->frozen); 815 REQUIRE(view->zonetable == NULL); 816 817 return (dns_zt_create(view->mctx, view->rdclass, &view->zonetable)); 818} 819 820isc_result_t 821dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr, 822 unsigned int ntasks, unsigned int ndisp, isc_nm_t *nm, 823 isc_timermgr_t *timermgr, unsigned int options, 824 dns_dispatchmgr_t *dispatchmgr, 825 dns_dispatch_t *dispatchv4, 826 dns_dispatch_t *dispatchv6) { 827 isc_result_t result; 828 isc_event_t *event; 829 isc_mem_t *mctx = NULL; 830 831 REQUIRE(DNS_VIEW_VALID(view)); 832 REQUIRE(!view->frozen); 833 REQUIRE(view->resolver == NULL); 834 835 result = isc_task_create(taskmgr, 0, &view->task); 836 if (result != ISC_R_SUCCESS) { 837 return (result); 838 } 839 isc_task_setname(view->task, "view", view); 840 841 result = dns_resolver_create(view, taskmgr, ntasks, ndisp, nm, timermgr, 842 options, dispatchmgr, dispatchv4, 843 dispatchv6, &view->resolver); 844 if (result != ISC_R_SUCCESS) { 845 isc_task_detach(&view->task); 846 return (result); 847 } 848 event = &view->resevent; 849 dns_resolver_whenshutdown(view->resolver, view->task, &event); 850 atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_RESSHUTDOWN); 851 isc_refcount_increment(&view->weakrefs); 852 853 isc_mem_create(&mctx); 854 isc_mem_setname(mctx, "ADB"); 855 856 result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb); 857 isc_mem_detach(&mctx); 858 if (result != ISC_R_SUCCESS) { 859 dns_resolver_shutdown(view->resolver); 860 return (result); 861 } 862 event = &view->adbevent; 863 dns_adb_whenshutdown(view->adb, view->task, &event); 864 atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_ADBSHUTDOWN); 865 isc_refcount_increment(&view->weakrefs); 866 867 result = dns_requestmgr_create( 868 view->mctx, dns_resolver_taskmgr(view->resolver), 869 dns_resolver_dispatchmgr(view->resolver), dispatchv4, 870 dispatchv6, &view->requestmgr); 871 if (result != ISC_R_SUCCESS) { 872 dns_adb_shutdown(view->adb); 873 dns_resolver_shutdown(view->resolver); 874 return (result); 875 } 876 event = &view->reqevent; 877 dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event); 878 atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_REQSHUTDOWN); 879 isc_refcount_increment(&view->weakrefs); 880 881 return (ISC_R_SUCCESS); 882} 883 884void 885dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) { 886 REQUIRE(DNS_VIEW_VALID(view)); 887 REQUIRE(!view->frozen); 888 889 view->cacheshared = shared; 890 if (view->cache != NULL) { 891 dns_db_detach(&view->cachedb); 892 dns_cache_detach(&view->cache); 893 } 894 dns_cache_attach(cache, &view->cache); 895 dns_cache_attachdb(cache, &view->cachedb); 896 INSIST(DNS_DB_VALID(view->cachedb)); 897} 898 899bool 900dns_view_iscacheshared(dns_view_t *view) { 901 REQUIRE(DNS_VIEW_VALID(view)); 902 903 return (view->cacheshared); 904} 905 906void 907dns_view_sethints(dns_view_t *view, dns_db_t *hints) { 908 REQUIRE(DNS_VIEW_VALID(view)); 909 REQUIRE(!view->frozen); 910 REQUIRE(view->hints == NULL); 911 REQUIRE(dns_db_iszone(hints)); 912 913 dns_db_attach(hints, &view->hints); 914} 915 916void 917dns_view_settransports(dns_view_t *view, dns_transport_list_t *list) { 918 REQUIRE(DNS_VIEW_VALID(view)); 919 REQUIRE(list != NULL); 920 if (view->transports != NULL) { 921 dns_transport_list_detach(&view->transports); 922 } 923 dns_transport_list_attach(list, &view->transports); 924} 925 926void 927dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { 928 REQUIRE(DNS_VIEW_VALID(view)); 929 REQUIRE(ring != NULL); 930 if (view->statickeys != NULL) { 931 dns_tsigkeyring_detach(&view->statickeys); 932 } 933 dns_tsigkeyring_attach(ring, &view->statickeys); 934} 935 936void 937dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { 938 REQUIRE(DNS_VIEW_VALID(view)); 939 REQUIRE(ring != NULL); 940 if (view->dynamickeys != NULL) { 941 dns_tsigkeyring_detach(&view->dynamickeys); 942 } 943 dns_tsigkeyring_attach(ring, &view->dynamickeys); 944} 945 946void 947dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) { 948 REQUIRE(DNS_VIEW_VALID(view)); 949 REQUIRE(ringp != NULL && *ringp == NULL); 950 if (view->dynamickeys != NULL) { 951 dns_tsigkeyring_attach(view->dynamickeys, ringp); 952 } 953} 954 955void 956dns_view_restorekeyring(dns_view_t *view) { 957 FILE *fp; 958 char keyfile[PATH_MAX]; 959 isc_result_t result; 960 961 REQUIRE(DNS_VIEW_VALID(view)); 962 963 if (view->dynamickeys != NULL) { 964 result = isc_file_sanitize(NULL, view->name, "tsigkeys", 965 keyfile, sizeof(keyfile)); 966 if (result == ISC_R_SUCCESS) { 967 fp = fopen(keyfile, "r"); 968 if (fp != NULL) { 969 dns_keyring_restore(view->dynamickeys, fp); 970 (void)fclose(fp); 971 } 972 } 973 } 974} 975 976void 977dns_view_setdstport(dns_view_t *view, in_port_t dstport) { 978 REQUIRE(DNS_VIEW_VALID(view)); 979 view->dstport = dstport; 980} 981 982void 983dns_view_freeze(dns_view_t *view) { 984 REQUIRE(DNS_VIEW_VALID(view)); 985 REQUIRE(!view->frozen); 986 987 if (view->resolver != NULL) { 988 INSIST(view->cachedb != NULL); 989 dns_resolver_freeze(view->resolver); 990 } 991 view->frozen = true; 992} 993 994void 995dns_view_thaw(dns_view_t *view) { 996 REQUIRE(DNS_VIEW_VALID(view)); 997 REQUIRE(view->frozen); 998 999 view->frozen = false; 1000} 1001 1002isc_result_t 1003dns_view_addzone(dns_view_t *view, dns_zone_t *zone) { 1004 isc_result_t result; 1005 1006 REQUIRE(DNS_VIEW_VALID(view)); 1007 REQUIRE(!view->frozen); 1008 REQUIRE(view->zonetable != NULL); 1009 1010 result = dns_zt_mount(view->zonetable, zone); 1011 1012 return (result); 1013} 1014 1015isc_result_t 1016dns_view_findzone(dns_view_t *view, const dns_name_t *name, 1017 dns_zone_t **zonep) { 1018 isc_result_t result; 1019 1020 REQUIRE(DNS_VIEW_VALID(view)); 1021 1022 LOCK(&view->lock); 1023 if (view->zonetable != NULL) { 1024 result = dns_zt_find(view->zonetable, name, 0, NULL, zonep); 1025 if (result == DNS_R_PARTIALMATCH) { 1026 dns_zone_detach(zonep); 1027 result = ISC_R_NOTFOUND; 1028 } 1029 } else { 1030 result = ISC_R_NOTFOUND; 1031 } 1032 UNLOCK(&view->lock); 1033 1034 return (result); 1035} 1036 1037isc_result_t 1038dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type, 1039 isc_stdtime_t now, unsigned int options, bool use_hints, 1040 bool use_static_stub, dns_db_t **dbp, dns_dbnode_t **nodep, 1041 dns_name_t *foundname, dns_rdataset_t *rdataset, 1042 dns_rdataset_t *sigrdataset) { 1043 isc_result_t result; 1044 dns_db_t *db, *zdb; 1045 dns_dbnode_t *node, *znode; 1046 bool is_cache, is_staticstub_zone; 1047 dns_rdataset_t zrdataset, zsigrdataset; 1048 dns_zone_t *zone; 1049 1050 /* 1051 * Find an rdataset whose owner name is 'name', and whose type is 1052 * 'type'. 1053 */ 1054 1055 REQUIRE(DNS_VIEW_VALID(view)); 1056 REQUIRE(view->frozen); 1057 REQUIRE(type != dns_rdatatype_rrsig); 1058 REQUIRE(rdataset != NULL); /* XXXBEW - remove this */ 1059 REQUIRE(nodep == NULL || *nodep == NULL); 1060 1061 /* 1062 * Initialize. 1063 */ 1064 dns_rdataset_init(&zrdataset); 1065 dns_rdataset_init(&zsigrdataset); 1066 zdb = NULL; 1067 znode = NULL; 1068 1069 /* 1070 * Find a database to answer the query. 1071 */ 1072 db = NULL; 1073 node = NULL; 1074 is_staticstub_zone = false; 1075 zone = NULL; 1076 LOCK(&view->lock); 1077 if (view->zonetable != NULL) { 1078 result = dns_zt_find(view->zonetable, name, DNS_ZTFIND_MIRROR, 1079 NULL, &zone); 1080 } else { 1081 result = ISC_R_NOTFOUND; 1082 } 1083 UNLOCK(&view->lock); 1084 if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub && 1085 !use_static_stub) 1086 { 1087 result = ISC_R_NOTFOUND; 1088 } 1089 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 1090 result = dns_zone_getdb(zone, &db); 1091 if (result != ISC_R_SUCCESS && view->cachedb != NULL) { 1092 dns_db_attach(view->cachedb, &db); 1093 } else if (result != ISC_R_SUCCESS) { 1094 goto cleanup; 1095 } 1096 if (dns_zone_gettype(zone) == dns_zone_staticstub && 1097 dns_name_equal(name, dns_zone_getorigin(zone))) 1098 { 1099 is_staticstub_zone = true; 1100 } 1101 } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) { 1102 dns_db_attach(view->cachedb, &db); 1103 } else { 1104 goto cleanup; 1105 } 1106 1107 is_cache = dns_db_iscache(db); 1108 1109db_find: 1110 /* 1111 * Now look for an answer in the database. 1112 */ 1113 result = dns_db_find(db, name, NULL, type, options, now, &node, 1114 foundname, rdataset, sigrdataset); 1115 1116 if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) { 1117 if (dns_rdataset_isassociated(rdataset)) { 1118 dns_rdataset_disassociate(rdataset); 1119 } 1120 if (sigrdataset != NULL && 1121 dns_rdataset_isassociated(sigrdataset)) 1122 { 1123 dns_rdataset_disassociate(sigrdataset); 1124 } 1125 if (node != NULL) { 1126 dns_db_detachnode(db, &node); 1127 } 1128 if (!is_cache) { 1129 dns_db_detach(&db); 1130 if (view->cachedb != NULL && !is_staticstub_zone) { 1131 /* 1132 * Either the answer is in the cache, or we 1133 * don't know it. 1134 * Note that if the result comes from a 1135 * static-stub zone we stop the search here 1136 * (see the function description in view.h). 1137 */ 1138 is_cache = true; 1139 dns_db_attach(view->cachedb, &db); 1140 goto db_find; 1141 } 1142 } else { 1143 /* 1144 * We don't have the data in the cache. If we've got 1145 * glue from the zone, use it. 1146 */ 1147 if (dns_rdataset_isassociated(&zrdataset)) { 1148 dns_rdataset_clone(&zrdataset, rdataset); 1149 if (sigrdataset != NULL && 1150 dns_rdataset_isassociated(&zsigrdataset)) 1151 { 1152 dns_rdataset_clone(&zsigrdataset, 1153 sigrdataset); 1154 } 1155 result = DNS_R_GLUE; 1156 if (db != NULL) { 1157 dns_db_detach(&db); 1158 } 1159 dns_db_attach(zdb, &db); 1160 dns_db_attachnode(db, znode, &node); 1161 goto cleanup; 1162 } 1163 } 1164 /* 1165 * We don't know the answer. 1166 */ 1167 result = ISC_R_NOTFOUND; 1168 } else if (result == DNS_R_GLUE) { 1169 if (view->cachedb != NULL && !is_staticstub_zone) { 1170 /* 1171 * We found an answer, but the cache may be better. 1172 * Remember what we've got and go look in the cache. 1173 */ 1174 is_cache = true; 1175 dns_rdataset_clone(rdataset, &zrdataset); 1176 dns_rdataset_disassociate(rdataset); 1177 if (sigrdataset != NULL && 1178 dns_rdataset_isassociated(sigrdataset)) 1179 { 1180 dns_rdataset_clone(sigrdataset, &zsigrdataset); 1181 dns_rdataset_disassociate(sigrdataset); 1182 } 1183 dns_db_attach(db, &zdb); 1184 dns_db_attachnode(zdb, node, &znode); 1185 dns_db_detachnode(db, &node); 1186 dns_db_detach(&db); 1187 dns_db_attach(view->cachedb, &db); 1188 goto db_find; 1189 } 1190 /* 1191 * Otherwise, the glue is the best answer. 1192 */ 1193 result = ISC_R_SUCCESS; 1194 } 1195 1196 if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) { 1197 if (dns_rdataset_isassociated(rdataset)) { 1198 dns_rdataset_disassociate(rdataset); 1199 } 1200 if (sigrdataset != NULL && 1201 dns_rdataset_isassociated(sigrdataset)) 1202 { 1203 dns_rdataset_disassociate(sigrdataset); 1204 } 1205 if (db != NULL) { 1206 if (node != NULL) { 1207 dns_db_detachnode(db, &node); 1208 } 1209 dns_db_detach(&db); 1210 } 1211 result = dns_db_find(view->hints, name, NULL, type, options, 1212 now, &node, foundname, rdataset, 1213 sigrdataset); 1214 if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) { 1215 /* 1216 * We just used a hint. Let the resolver know it 1217 * should consider priming. 1218 */ 1219 dns_resolver_prime(view->resolver); 1220 dns_db_attach(view->hints, &db); 1221 result = DNS_R_HINT; 1222 } else if (result == DNS_R_NXRRSET) { 1223 dns_db_attach(view->hints, &db); 1224 result = DNS_R_HINTNXRRSET; 1225 } else if (result == DNS_R_NXDOMAIN) { 1226 result = ISC_R_NOTFOUND; 1227 } 1228 1229 /* 1230 * Cleanup if non-standard hints are used. 1231 */ 1232 if (db == NULL && node != NULL) { 1233 dns_db_detachnode(view->hints, &node); 1234 } 1235 } 1236 1237cleanup: 1238 if (dns_rdataset_isassociated(&zrdataset)) { 1239 dns_rdataset_disassociate(&zrdataset); 1240 if (dns_rdataset_isassociated(&zsigrdataset)) { 1241 dns_rdataset_disassociate(&zsigrdataset); 1242 } 1243 } 1244 1245 if (zdb != NULL) { 1246 if (znode != NULL) { 1247 dns_db_detachnode(zdb, &znode); 1248 } 1249 dns_db_detach(&zdb); 1250 } 1251 1252 if (db != NULL) { 1253 if (node != NULL) { 1254 if (nodep != NULL) { 1255 *nodep = node; 1256 } else { 1257 dns_db_detachnode(db, &node); 1258 } 1259 } 1260 if (dbp != NULL) { 1261 *dbp = db; 1262 } else { 1263 dns_db_detach(&db); 1264 } 1265 } else { 1266 INSIST(node == NULL); 1267 } 1268 1269 if (zone != NULL) { 1270 dns_zone_detach(&zone); 1271 } 1272 1273 return (result); 1274} 1275 1276isc_result_t 1277dns_view_simplefind(dns_view_t *view, const dns_name_t *name, 1278 dns_rdatatype_t type, isc_stdtime_t now, 1279 unsigned int options, bool use_hints, 1280 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 1281 isc_result_t result; 1282 dns_fixedname_t foundname; 1283 1284 dns_fixedname_init(&foundname); 1285 result = dns_view_find(view, name, type, now, options, use_hints, false, 1286 NULL, NULL, dns_fixedname_name(&foundname), 1287 rdataset, sigrdataset); 1288 if (result == DNS_R_NXDOMAIN) { 1289 /* 1290 * The rdataset and sigrdataset of the relevant NSEC record 1291 * may be returned, but the caller cannot use them because 1292 * foundname is not returned by this simplified API. We 1293 * disassociate them here to prevent any misuse by the caller. 1294 */ 1295 if (dns_rdataset_isassociated(rdataset)) { 1296 dns_rdataset_disassociate(rdataset); 1297 } 1298 if (sigrdataset != NULL && 1299 dns_rdataset_isassociated(sigrdataset)) 1300 { 1301 dns_rdataset_disassociate(sigrdataset); 1302 } 1303 } else if (result != ISC_R_SUCCESS && result != DNS_R_GLUE && 1304 result != DNS_R_HINT && result != DNS_R_NCACHENXDOMAIN && 1305 result != DNS_R_NCACHENXRRSET && result != DNS_R_NXRRSET && 1306 result != DNS_R_HINTNXRRSET && result != ISC_R_NOTFOUND) 1307 { 1308 if (dns_rdataset_isassociated(rdataset)) { 1309 dns_rdataset_disassociate(rdataset); 1310 } 1311 if (sigrdataset != NULL && 1312 dns_rdataset_isassociated(sigrdataset)) 1313 { 1314 dns_rdataset_disassociate(sigrdataset); 1315 } 1316 result = ISC_R_NOTFOUND; 1317 } 1318 1319 return (result); 1320} 1321 1322isc_result_t 1323dns_view_findzonecut(dns_view_t *view, const dns_name_t *name, 1324 dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now, 1325 unsigned int options, bool use_hints, bool use_cache, 1326 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 1327 isc_result_t result; 1328 dns_db_t *db; 1329 bool is_cache, use_zone, try_hints; 1330 dns_zone_t *zone; 1331 dns_name_t *zfname; 1332 dns_rdataset_t zrdataset, zsigrdataset; 1333 dns_fixedname_t zfixedname; 1334 unsigned int ztoptions = DNS_ZTFIND_MIRROR; 1335 1336 REQUIRE(DNS_VIEW_VALID(view)); 1337 REQUIRE(view->frozen); 1338 1339 db = NULL; 1340 use_zone = false; 1341 try_hints = false; 1342 zfname = NULL; 1343 1344 /* 1345 * Initialize. 1346 */ 1347 dns_fixedname_init(&zfixedname); 1348 dns_rdataset_init(&zrdataset); 1349 dns_rdataset_init(&zsigrdataset); 1350 1351 /* 1352 * Find the right database. 1353 */ 1354 zone = NULL; 1355 LOCK(&view->lock); 1356 if (view->zonetable != NULL) { 1357 if ((options & DNS_DBFIND_NOEXACT) != 0) { 1358 ztoptions |= DNS_ZTFIND_NOEXACT; 1359 } 1360 result = dns_zt_find(view->zonetable, name, ztoptions, NULL, 1361 &zone); 1362 } else { 1363 result = ISC_R_NOTFOUND; 1364 } 1365 UNLOCK(&view->lock); 1366 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 1367 result = dns_zone_getdb(zone, &db); 1368 } 1369 if (result == ISC_R_NOTFOUND) { 1370 /* 1371 * We're not directly authoritative for this query name, nor 1372 * is it a subdomain of any zone for which we're 1373 * authoritative. 1374 */ 1375 if (use_cache && view->cachedb != NULL) { 1376 /* 1377 * We have a cache; try it. 1378 */ 1379 dns_db_attach(view->cachedb, &db); 1380 } else if (use_hints && view->hints != NULL) { 1381 /* 1382 * Maybe we have hints... 1383 */ 1384 try_hints = true; 1385 goto finish; 1386 } else { 1387 result = DNS_R_NXDOMAIN; 1388 goto cleanup; 1389 } 1390 } else if (result != ISC_R_SUCCESS) { 1391 /* 1392 * Something is broken. 1393 */ 1394 goto cleanup; 1395 } 1396 is_cache = dns_db_iscache(db); 1397 1398db_find: 1399 /* 1400 * Look for the zonecut. 1401 */ 1402 if (!is_cache) { 1403 result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options, 1404 now, NULL, fname, rdataset, sigrdataset); 1405 if (result == DNS_R_DELEGATION) { 1406 result = ISC_R_SUCCESS; 1407 } else if (result != ISC_R_SUCCESS) { 1408 goto cleanup; 1409 } 1410 1411 if (use_cache && view->cachedb != NULL && db != view->hints) { 1412 /* 1413 * We found an answer, but the cache may be better. 1414 */ 1415 zfname = dns_fixedname_name(&zfixedname); 1416 dns_name_copy(fname, zfname); 1417 dns_rdataset_clone(rdataset, &zrdataset); 1418 dns_rdataset_disassociate(rdataset); 1419 if (sigrdataset != NULL && 1420 dns_rdataset_isassociated(sigrdataset)) 1421 { 1422 dns_rdataset_clone(sigrdataset, &zsigrdataset); 1423 dns_rdataset_disassociate(sigrdataset); 1424 } 1425 dns_db_detach(&db); 1426 dns_db_attach(view->cachedb, &db); 1427 is_cache = true; 1428 goto db_find; 1429 } 1430 } else { 1431 result = dns_db_findzonecut(db, name, options, now, NULL, fname, 1432 dcname, rdataset, sigrdataset); 1433 if (result == ISC_R_SUCCESS) { 1434 if (zfname != NULL && 1435 (!dns_name_issubdomain(fname, zfname) || 1436 (dns_zone_gettype(zone) == dns_zone_staticstub && 1437 dns_name_equal(fname, zfname)))) 1438 { 1439 /* 1440 * We found a zonecut in the cache, but our 1441 * zone delegation is better. 1442 */ 1443 use_zone = true; 1444 } 1445 } else if (result == ISC_R_NOTFOUND) { 1446 if (zfname != NULL) { 1447 /* 1448 * We didn't find anything in the cache, but we 1449 * have a zone delegation, so use it. 1450 */ 1451 use_zone = true; 1452 result = ISC_R_SUCCESS; 1453 } else if (use_hints && view->hints != NULL) { 1454 /* 1455 * Maybe we have hints... 1456 */ 1457 try_hints = true; 1458 result = ISC_R_SUCCESS; 1459 } else { 1460 result = DNS_R_NXDOMAIN; 1461 } 1462 } else { 1463 /* 1464 * Something bad happened. 1465 */ 1466 goto cleanup; 1467 } 1468 } 1469 1470finish: 1471 if (use_zone) { 1472 if (dns_rdataset_isassociated(rdataset)) { 1473 dns_rdataset_disassociate(rdataset); 1474 if (sigrdataset != NULL && 1475 dns_rdataset_isassociated(sigrdataset)) 1476 { 1477 dns_rdataset_disassociate(sigrdataset); 1478 } 1479 } 1480 dns_name_copy(zfname, fname); 1481 if (dcname != NULL) { 1482 dns_name_copy(zfname, dcname); 1483 } 1484 dns_rdataset_clone(&zrdataset, rdataset); 1485 if (sigrdataset != NULL && 1486 dns_rdataset_isassociated(&zrdataset)) 1487 { 1488 dns_rdataset_clone(&zsigrdataset, sigrdataset); 1489 } 1490 } else if (try_hints) { 1491 /* 1492 * We've found nothing so far, but we have hints. 1493 */ 1494 result = dns_db_find(view->hints, dns_rootname, NULL, 1495 dns_rdatatype_ns, 0, now, NULL, fname, 1496 rdataset, NULL); 1497 if (result != ISC_R_SUCCESS) { 1498 /* 1499 * We can't even find the hints for the root 1500 * nameservers! 1501 */ 1502 if (dns_rdataset_isassociated(rdataset)) { 1503 dns_rdataset_disassociate(rdataset); 1504 } 1505 result = ISC_R_NOTFOUND; 1506 } else if (dcname != NULL) { 1507 dns_name_copy(fname, dcname); 1508 } 1509 } 1510 1511cleanup: 1512 if (dns_rdataset_isassociated(&zrdataset)) { 1513 dns_rdataset_disassociate(&zrdataset); 1514 if (dns_rdataset_isassociated(&zsigrdataset)) { 1515 dns_rdataset_disassociate(&zsigrdataset); 1516 } 1517 } 1518 if (db != NULL) { 1519 dns_db_detach(&db); 1520 } 1521 if (zone != NULL) { 1522 dns_zone_detach(&zone); 1523 } 1524 1525 return (result); 1526} 1527 1528isc_result_t 1529dns_viewlist_find(dns_viewlist_t *list, const char *name, 1530 dns_rdataclass_t rdclass, dns_view_t **viewp) { 1531 dns_view_t *view; 1532 1533 REQUIRE(list != NULL); 1534 1535 for (view = ISC_LIST_HEAD(*list); view != NULL; 1536 view = ISC_LIST_NEXT(view, link)) 1537 { 1538 if (strcmp(view->name, name) == 0 && view->rdclass == rdclass) { 1539 break; 1540 } 1541 } 1542 if (view == NULL) { 1543 return (ISC_R_NOTFOUND); 1544 } 1545 1546 dns_view_attach(view, viewp); 1547 1548 return (ISC_R_SUCCESS); 1549} 1550 1551isc_result_t 1552dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name, 1553 bool allclasses, dns_rdataclass_t rdclass, 1554 dns_zone_t **zonep) { 1555 dns_view_t *view; 1556 isc_result_t result; 1557 dns_zone_t *zone1 = NULL, *zone2 = NULL; 1558 dns_zone_t **zp = NULL; 1559 1560 REQUIRE(list != NULL); 1561 REQUIRE(zonep != NULL && *zonep == NULL); 1562 1563 for (view = ISC_LIST_HEAD(*list); view != NULL; 1564 view = ISC_LIST_NEXT(view, link)) 1565 { 1566 if (!allclasses && view->rdclass != rdclass) { 1567 continue; 1568 } 1569 1570 /* 1571 * If the zone is defined in more than one view, 1572 * treat it as not found. 1573 */ 1574 zp = (zone1 == NULL) ? &zone1 : &zone2; 1575 LOCK(&view->lock); 1576 if (view->zonetable != NULL) { 1577 result = dns_zt_find(view->zonetable, name, 0, NULL, 1578 zp); 1579 } else { 1580 result = ISC_R_NOTFOUND; 1581 } 1582 UNLOCK(&view->lock); 1583 INSIST(result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND || 1584 result == DNS_R_PARTIALMATCH); 1585 1586 /* Treat a partial match as no match */ 1587 if (result == DNS_R_PARTIALMATCH) { 1588 dns_zone_detach(zp); 1589 result = ISC_R_NOTFOUND; 1590 POST(result); 1591 } 1592 1593 if (zone2 != NULL) { 1594 dns_zone_detach(&zone1); 1595 dns_zone_detach(&zone2); 1596 return (ISC_R_MULTIPLE); 1597 } 1598 } 1599 1600 if (zone1 != NULL) { 1601 dns_zone_attach(zone1, zonep); 1602 dns_zone_detach(&zone1); 1603 return (ISC_R_SUCCESS); 1604 } 1605 1606 return (ISC_R_NOTFOUND); 1607} 1608 1609isc_result_t 1610dns_view_load(dns_view_t *view, bool stop, bool newonly) { 1611 REQUIRE(DNS_VIEW_VALID(view)); 1612 REQUIRE(view->zonetable != NULL); 1613 1614 return (dns_zt_load(view->zonetable, stop, newonly)); 1615} 1616 1617isc_result_t 1618dns_view_asyncload(dns_view_t *view, bool newonly, dns_zt_allloaded_t callback, 1619 void *arg) { 1620 REQUIRE(DNS_VIEW_VALID(view)); 1621 REQUIRE(view->zonetable != NULL); 1622 1623 return (dns_zt_asyncload(view->zonetable, newonly, callback, arg)); 1624} 1625 1626isc_result_t 1627dns_view_gettsig(dns_view_t *view, const dns_name_t *keyname, 1628 dns_tsigkey_t **keyp) { 1629 isc_result_t result; 1630 REQUIRE(keyp != NULL && *keyp == NULL); 1631 1632 result = dns_tsigkey_find(keyp, keyname, NULL, view->statickeys); 1633 if (result == ISC_R_NOTFOUND) { 1634 result = dns_tsigkey_find(keyp, keyname, NULL, 1635 view->dynamickeys); 1636 } 1637 return (result); 1638} 1639 1640isc_result_t 1641dns_view_gettransport(dns_view_t *view, const dns_transport_type_t type, 1642 const dns_name_t *name, dns_transport_t **transportp) { 1643 REQUIRE(DNS_VIEW_VALID(view)); 1644 REQUIRE(transportp != NULL && *transportp == NULL); 1645 1646 dns_transport_t *transport = dns_transport_find(type, name, 1647 view->transports); 1648 if (transport == NULL) { 1649 return (ISC_R_NOTFOUND); 1650 } 1651 1652 *transportp = transport; 1653 return (ISC_R_SUCCESS); 1654} 1655 1656isc_result_t 1657dns_view_getpeertsig(dns_view_t *view, const isc_netaddr_t *peeraddr, 1658 dns_tsigkey_t **keyp) { 1659 isc_result_t result; 1660 dns_name_t *keyname = NULL; 1661 dns_peer_t *peer = NULL; 1662 1663 result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer); 1664 if (result != ISC_R_SUCCESS) { 1665 return (result); 1666 } 1667 1668 result = dns_peer_getkey(peer, &keyname); 1669 if (result != ISC_R_SUCCESS) { 1670 return (result); 1671 } 1672 1673 result = dns_view_gettsig(view, keyname, keyp); 1674 return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result); 1675} 1676 1677isc_result_t 1678dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) { 1679 REQUIRE(DNS_VIEW_VALID(view)); 1680 REQUIRE(source != NULL); 1681 1682 return (dns_tsig_verify(source, msg, view->statickeys, 1683 view->dynamickeys)); 1684} 1685 1686isc_result_t 1687dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { 1688 isc_result_t result; 1689 1690 REQUIRE(DNS_VIEW_VALID(view)); 1691 1692 (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name); 1693 result = dns_master_dumptostream(view->mctx, view->cachedb, NULL, 1694 &dns_master_style_cache, 1695 dns_masterformat_text, NULL, fp); 1696 if (result != ISC_R_SUCCESS) { 1697 return (result); 1698 } 1699 dns_adb_dump(view->adb, fp); 1700 dns_resolver_printbadcache(view->resolver, fp); 1701 dns_badcache_print(view->failcache, "SERVFAIL cache", fp); 1702 return (ISC_R_SUCCESS); 1703} 1704 1705isc_result_t 1706dns_view_flushcache(dns_view_t *view, bool fixuponly) { 1707 isc_result_t result; 1708 1709 REQUIRE(DNS_VIEW_VALID(view)); 1710 1711 if (view->cachedb == NULL) { 1712 return (ISC_R_SUCCESS); 1713 } 1714 if (!fixuponly) { 1715 result = dns_cache_flush(view->cache); 1716 if (result != ISC_R_SUCCESS) { 1717 return (result); 1718 } 1719 } 1720 dns_db_detach(&view->cachedb); 1721 dns_cache_attachdb(view->cache, &view->cachedb); 1722 if (view->resolver != NULL) { 1723 dns_resolver_flushbadcache(view->resolver, NULL); 1724 } 1725 if (view->failcache != NULL) { 1726 dns_badcache_flush(view->failcache); 1727 } 1728 1729 dns_adb_flush(view->adb); 1730 return (ISC_R_SUCCESS); 1731} 1732 1733isc_result_t 1734dns_view_flushname(dns_view_t *view, const dns_name_t *name) { 1735 return (dns_view_flushnode(view, name, false)); 1736} 1737 1738isc_result_t 1739dns_view_flushnode(dns_view_t *view, const dns_name_t *name, bool tree) { 1740 isc_result_t result = ISC_R_SUCCESS; 1741 1742 REQUIRE(DNS_VIEW_VALID(view)); 1743 1744 if (tree) { 1745 if (view->adb != NULL) { 1746 dns_adb_flushnames(view->adb, name); 1747 } 1748 if (view->resolver != NULL) { 1749 dns_resolver_flushbadnames(view->resolver, name); 1750 } 1751 if (view->failcache != NULL) { 1752 dns_badcache_flushtree(view->failcache, name); 1753 } 1754 } else { 1755 if (view->adb != NULL) { 1756 dns_adb_flushname(view->adb, name); 1757 } 1758 if (view->resolver != NULL) { 1759 dns_resolver_flushbadcache(view->resolver, name); 1760 } 1761 if (view->failcache != NULL) { 1762 dns_badcache_flushname(view->failcache, name); 1763 } 1764 } 1765 1766 if (view->cache != NULL) { 1767 result = dns_cache_flushnode(view->cache, name, tree); 1768 } 1769 1770 return (result); 1771} 1772 1773void 1774dns_view_adddelegationonly(dns_view_t *view, const dns_name_t *name) { 1775 dns_name_t *item; 1776 unsigned int hash; 1777 1778 REQUIRE(DNS_VIEW_VALID(view)); 1779 1780 if (view->delonly == NULL) { 1781 view->delonly = isc_mem_get(view->mctx, 1782 sizeof(dns_namelist_t) * 1783 DNS_VIEW_DELONLYHASH); 1784 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) { 1785 ISC_LIST_INIT(view->delonly[hash]); 1786 } 1787 } 1788 hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH; 1789 item = ISC_LIST_HEAD(view->delonly[hash]); 1790 while (item != NULL && !dns_name_equal(item, name)) { 1791 item = ISC_LIST_NEXT(item, link); 1792 } 1793 if (item != NULL) { 1794 return; 1795 } 1796 item = isc_mem_get(view->mctx, sizeof(*item)); 1797 dns_name_init(item, NULL); 1798 dns_name_dup(name, view->mctx, item); 1799 ISC_LIST_APPEND(view->delonly[hash], item, link); 1800} 1801 1802void 1803dns_view_excludedelegationonly(dns_view_t *view, const dns_name_t *name) { 1804 dns_name_t *item; 1805 unsigned int hash; 1806 1807 REQUIRE(DNS_VIEW_VALID(view)); 1808 1809 if (view->rootexclude == NULL) { 1810 view->rootexclude = isc_mem_get(view->mctx, 1811 sizeof(dns_namelist_t) * 1812 DNS_VIEW_DELONLYHASH); 1813 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) { 1814 ISC_LIST_INIT(view->rootexclude[hash]); 1815 } 1816 } 1817 hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH; 1818 item = ISC_LIST_HEAD(view->rootexclude[hash]); 1819 while (item != NULL && !dns_name_equal(item, name)) { 1820 item = ISC_LIST_NEXT(item, link); 1821 } 1822 if (item != NULL) { 1823 return; 1824 } 1825 item = isc_mem_get(view->mctx, sizeof(*item)); 1826 dns_name_init(item, NULL); 1827 dns_name_dup(name, view->mctx, item); 1828 ISC_LIST_APPEND(view->rootexclude[hash], item, link); 1829} 1830 1831bool 1832dns_view_isdelegationonly(dns_view_t *view, const dns_name_t *name) { 1833 dns_name_t *item; 1834 unsigned int hash; 1835 1836 REQUIRE(DNS_VIEW_VALID(view)); 1837 1838 if (!view->rootdelonly && view->delonly == NULL) { 1839 return (false); 1840 } 1841 1842 hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH; 1843 if (view->rootdelonly && dns_name_countlabels(name) <= 2) { 1844 if (view->rootexclude == NULL) { 1845 return (true); 1846 } 1847 item = ISC_LIST_HEAD(view->rootexclude[hash]); 1848 while (item != NULL && !dns_name_equal(item, name)) { 1849 item = ISC_LIST_NEXT(item, link); 1850 } 1851 if (item == NULL) { 1852 return (true); 1853 } 1854 } 1855 1856 if (view->delonly == NULL) { 1857 return (false); 1858 } 1859 1860 item = ISC_LIST_HEAD(view->delonly[hash]); 1861 while (item != NULL && !dns_name_equal(item, name)) { 1862 item = ISC_LIST_NEXT(item, link); 1863 } 1864 if (item == NULL) { 1865 return (false); 1866 } 1867 return (true); 1868} 1869 1870void 1871dns_view_setrootdelonly(dns_view_t *view, bool value) { 1872 REQUIRE(DNS_VIEW_VALID(view)); 1873 view->rootdelonly = value; 1874} 1875 1876bool 1877dns_view_getrootdelonly(dns_view_t *view) { 1878 REQUIRE(DNS_VIEW_VALID(view)); 1879 return (view->rootdelonly); 1880} 1881 1882isc_result_t 1883dns_view_freezezones(dns_view_t *view, bool value) { 1884 REQUIRE(DNS_VIEW_VALID(view)); 1885 REQUIRE(view->zonetable != NULL); 1886 1887 return (dns_zt_freezezones(view->zonetable, view, value)); 1888} 1889 1890void 1891dns_view_setadbstats(dns_view_t *view, isc_stats_t *stats) { 1892 REQUIRE(DNS_VIEW_VALID(view)); 1893 REQUIRE(!view->frozen); 1894 REQUIRE(view->adbstats == NULL); 1895 1896 isc_stats_attach(stats, &view->adbstats); 1897} 1898 1899void 1900dns_view_getadbstats(dns_view_t *view, isc_stats_t **statsp) { 1901 REQUIRE(DNS_VIEW_VALID(view)); 1902 REQUIRE(statsp != NULL && *statsp == NULL); 1903 1904 if (view->adbstats != NULL) { 1905 isc_stats_attach(view->adbstats, statsp); 1906 } 1907} 1908 1909void 1910dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) { 1911 REQUIRE(DNS_VIEW_VALID(view)); 1912 REQUIRE(!view->frozen); 1913 REQUIRE(view->resstats == NULL); 1914 1915 isc_stats_attach(stats, &view->resstats); 1916} 1917 1918void 1919dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) { 1920 REQUIRE(DNS_VIEW_VALID(view)); 1921 REQUIRE(statsp != NULL && *statsp == NULL); 1922 1923 if (view->resstats != NULL) { 1924 isc_stats_attach(view->resstats, statsp); 1925 } 1926} 1927 1928void 1929dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) { 1930 REQUIRE(DNS_VIEW_VALID(view)); 1931 REQUIRE(!view->frozen); 1932 REQUIRE(view->resquerystats == NULL); 1933 1934 dns_stats_attach(stats, &view->resquerystats); 1935} 1936 1937void 1938dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) { 1939 REQUIRE(DNS_VIEW_VALID(view)); 1940 REQUIRE(statsp != NULL && *statsp == NULL); 1941 1942 if (view->resquerystats != NULL) { 1943 dns_stats_attach(view->resquerystats, statsp); 1944 } 1945} 1946 1947isc_result_t 1948dns_view_initntatable(dns_view_t *view, isc_taskmgr_t *taskmgr, 1949 isc_timermgr_t *timermgr) { 1950 REQUIRE(DNS_VIEW_VALID(view)); 1951 if (view->ntatable_priv != NULL) { 1952 dns_ntatable_detach(&view->ntatable_priv); 1953 } 1954 return (dns_ntatable_create(view, taskmgr, timermgr, 1955 &view->ntatable_priv)); 1956} 1957 1958isc_result_t 1959dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) { 1960 REQUIRE(DNS_VIEW_VALID(view)); 1961 REQUIRE(ntp != NULL && *ntp == NULL); 1962 if (view->ntatable_priv == NULL) { 1963 return (ISC_R_NOTFOUND); 1964 } 1965 dns_ntatable_attach(view->ntatable_priv, ntp); 1966 return (ISC_R_SUCCESS); 1967} 1968 1969isc_result_t 1970dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) { 1971 REQUIRE(DNS_VIEW_VALID(view)); 1972 if (view->secroots_priv != NULL) { 1973 dns_keytable_detach(&view->secroots_priv); 1974 } 1975 return (dns_keytable_create(mctx, &view->secroots_priv)); 1976} 1977 1978isc_result_t 1979dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) { 1980 REQUIRE(DNS_VIEW_VALID(view)); 1981 REQUIRE(ktp != NULL && *ktp == NULL); 1982 if (view->secroots_priv == NULL) { 1983 return (ISC_R_NOTFOUND); 1984 } 1985 dns_keytable_attach(view->secroots_priv, ktp); 1986 return (ISC_R_SUCCESS); 1987} 1988 1989bool 1990dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, const dns_name_t *name, 1991 const dns_name_t *anchor) { 1992 REQUIRE(DNS_VIEW_VALID(view)); 1993 1994 if (view->ntatable_priv == NULL) { 1995 return (false); 1996 } 1997 1998 return (dns_ntatable_covered(view->ntatable_priv, now, name, anchor)); 1999} 2000 2001isc_result_t 2002dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name, 2003 isc_stdtime_t now, bool checknta, bool *ntap, 2004 bool *secure_domain) { 2005 isc_result_t result; 2006 bool secure = false; 2007 dns_fixedname_t fn; 2008 dns_name_t *anchor; 2009 2010 REQUIRE(DNS_VIEW_VALID(view)); 2011 2012 if (view->secroots_priv == NULL) { 2013 return (ISC_R_NOTFOUND); 2014 } 2015 2016 anchor = dns_fixedname_initname(&fn); 2017 2018 result = dns_keytable_issecuredomain(view->secroots_priv, name, anchor, 2019 &secure); 2020 if (result != ISC_R_SUCCESS) { 2021 return (result); 2022 } 2023 2024 if (ntap != NULL) { 2025 *ntap = false; 2026 } 2027 if (checknta && secure && view->ntatable_priv != NULL && 2028 dns_ntatable_covered(view->ntatable_priv, now, name, anchor)) 2029 { 2030 if (ntap != NULL) { 2031 *ntap = true; 2032 } 2033 secure = false; 2034 } 2035 2036 *secure_domain = secure; 2037 return (ISC_R_SUCCESS); 2038} 2039 2040void 2041dns_view_untrust(dns_view_t *view, const dns_name_t *keyname, 2042 const dns_rdata_dnskey_t *dnskey) { 2043 isc_result_t result; 2044 dns_keytable_t *sr = NULL; 2045 dns_rdata_dnskey_t tmpkey; 2046 2047 REQUIRE(DNS_VIEW_VALID(view)); 2048 REQUIRE(keyname != NULL); 2049 REQUIRE(dnskey != NULL); 2050 2051 result = dns_view_getsecroots(view, &sr); 2052 if (result != ISC_R_SUCCESS) { 2053 return; 2054 } 2055 2056 /* 2057 * Clear the revoke bit, if set, so that the key will match what's 2058 * in secroots now. 2059 */ 2060 tmpkey = *dnskey; 2061 tmpkey.flags &= ~DNS_KEYFLAG_REVOKE; 2062 2063 result = dns_keytable_deletekey(sr, keyname, &tmpkey); 2064 if (result == ISC_R_SUCCESS) { 2065 /* 2066 * If key was found in secroots, then it was a 2067 * configured trust anchor, and we want to fail 2068 * secure. If there are no other configured keys, 2069 * then leave a null key so that we can't validate 2070 * anymore. 2071 */ 2072 dns_keytable_marksecure(sr, keyname); 2073 } 2074 2075 dns_keytable_detach(&sr); 2076} 2077 2078bool 2079dns_view_istrusted(dns_view_t *view, const dns_name_t *keyname, 2080 const dns_rdata_dnskey_t *dnskey) { 2081 isc_result_t result; 2082 dns_keytable_t *sr = NULL; 2083 dns_keynode_t *knode = NULL; 2084 bool answer = false; 2085 dns_rdataset_t dsset; 2086 2087 REQUIRE(DNS_VIEW_VALID(view)); 2088 REQUIRE(keyname != NULL); 2089 REQUIRE(dnskey != NULL); 2090 2091 result = dns_view_getsecroots(view, &sr); 2092 if (result != ISC_R_SUCCESS) { 2093 return (false); 2094 } 2095 2096 dns_rdataset_init(&dsset); 2097 result = dns_keytable_find(sr, keyname, &knode); 2098 if (result == ISC_R_SUCCESS) { 2099 if (dns_keynode_dsset(knode, &dsset)) { 2100 dns_rdata_t rdata = DNS_RDATA_INIT; 2101 unsigned char data[4096], digest[DNS_DS_BUFFERSIZE]; 2102 dns_rdata_dnskey_t tmpkey = *dnskey; 2103 dns_rdata_ds_t ds; 2104 isc_buffer_t b; 2105 dns_rdataclass_t rdclass = tmpkey.common.rdclass; 2106 2107 /* 2108 * Clear the revoke bit, if set, so that the key 2109 * will match what's in secroots now. 2110 */ 2111 tmpkey.flags &= ~DNS_KEYFLAG_REVOKE; 2112 2113 isc_buffer_init(&b, data, sizeof(data)); 2114 result = dns_rdata_fromstruct(&rdata, rdclass, 2115 dns_rdatatype_dnskey, 2116 &tmpkey, &b); 2117 if (result != ISC_R_SUCCESS) { 2118 goto finish; 2119 } 2120 2121 result = dns_ds_fromkeyrdata(keyname, &rdata, 2122 DNS_DSDIGEST_SHA256, 2123 digest, &ds); 2124 if (result != ISC_R_SUCCESS) { 2125 goto finish; 2126 } 2127 2128 dns_rdata_reset(&rdata); 2129 isc_buffer_init(&b, data, sizeof(data)); 2130 result = dns_rdata_fromstruct( 2131 &rdata, rdclass, dns_rdatatype_ds, &ds, &b); 2132 if (result != ISC_R_SUCCESS) { 2133 goto finish; 2134 } 2135 2136 result = dns_rdataset_first(&dsset); 2137 while (result == ISC_R_SUCCESS) { 2138 dns_rdata_t this = DNS_RDATA_INIT; 2139 dns_rdataset_current(&dsset, &this); 2140 if (dns_rdata_compare(&rdata, &this) == 0) { 2141 answer = true; 2142 break; 2143 } 2144 result = dns_rdataset_next(&dsset); 2145 } 2146 } 2147 } 2148 2149finish: 2150 if (dns_rdataset_isassociated(&dsset)) { 2151 dns_rdataset_disassociate(&dsset); 2152 } 2153 if (knode != NULL) { 2154 dns_keytable_detachkeynode(sr, &knode); 2155 } 2156 dns_keytable_detach(&sr); 2157 return (answer); 2158} 2159 2160/* 2161 * Create path to a directory and a filename constructed from viewname. 2162 * This is a front-end to isc_file_sanitize(), allowing backward 2163 * compatibility to older versions when a file couldn't be expected 2164 * to be in the specified directory but might be in the current working 2165 * directory instead. 2166 * 2167 * It first tests for the existence of a file <viewname>.<suffix> in 2168 * 'directory'. If the file does not exist, it checks again in the 2169 * current working directory. If it does not exist there either, 2170 * return the path inside the directory. 2171 * 2172 * Returns ISC_R_SUCCESS if a path to an existing file is found or 2173 * a new path is created; returns ISC_R_NOSPACE if the path won't 2174 * fit in 'buflen'. 2175 */ 2176 2177static isc_result_t 2178nz_legacy(const char *directory, const char *viewname, const char *suffix, 2179 char *buffer, size_t buflen) { 2180 isc_result_t result; 2181 char newbuf[PATH_MAX]; 2182 2183 result = isc_file_sanitize(directory, viewname, suffix, buffer, buflen); 2184 if (result != ISC_R_SUCCESS) { 2185 return (result); 2186 } else if (directory == NULL || isc_file_exists(buffer)) { 2187 return (ISC_R_SUCCESS); 2188 } else { 2189 /* Save buffer */ 2190 strlcpy(newbuf, buffer, sizeof(newbuf)); 2191 } 2192 2193 /* 2194 * It isn't in the specified directory; check CWD. 2195 */ 2196 result = isc_file_sanitize(NULL, viewname, suffix, buffer, buflen); 2197 if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) { 2198 return (result); 2199 } 2200 2201 /* 2202 * File does not exist in either 'directory' or CWD, 2203 * so use the path in 'directory'. 2204 */ 2205 strlcpy(buffer, newbuf, buflen); 2206 return (ISC_R_SUCCESS); 2207} 2208 2209isc_result_t 2210dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx, 2211 void (*cfg_destroy)(void **), uint64_t mapsize) { 2212 isc_result_t result = ISC_R_SUCCESS; 2213 char buffer[1024]; 2214#ifdef HAVE_LMDB 2215 MDB_env *env = NULL; 2216 int status; 2217#endif /* ifdef HAVE_LMDB */ 2218 2219#ifndef HAVE_LMDB 2220 UNUSED(mapsize); 2221#endif /* ifndef HAVE_LMDB */ 2222 2223 REQUIRE(DNS_VIEW_VALID(view)); 2224 REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow); 2225 2226 if (view->new_zone_file != NULL) { 2227 isc_mem_free(view->mctx, view->new_zone_file); 2228 view->new_zone_file = NULL; 2229 } 2230 2231#ifdef HAVE_LMDB 2232 if (view->new_zone_dbenv != NULL) { 2233 mdb_env_close((MDB_env *)view->new_zone_dbenv); 2234 view->new_zone_dbenv = NULL; 2235 } 2236 2237 if (view->new_zone_db != NULL) { 2238 isc_mem_free(view->mctx, view->new_zone_db); 2239 view->new_zone_db = NULL; 2240 } 2241#endif /* HAVE_LMDB */ 2242 2243 if (view->new_zone_config != NULL) { 2244 view->cfg_destroy(&view->new_zone_config); 2245 view->cfg_destroy = NULL; 2246 } 2247 2248 if (!allow) { 2249 return (ISC_R_SUCCESS); 2250 } 2251 2252 CHECK(nz_legacy(view->new_zone_dir, view->name, "nzf", buffer, 2253 sizeof(buffer))); 2254 2255 view->new_zone_file = isc_mem_strdup(view->mctx, buffer); 2256 2257#ifdef HAVE_LMDB 2258 CHECK(nz_legacy(view->new_zone_dir, view->name, "nzd", buffer, 2259 sizeof(buffer))); 2260 2261 view->new_zone_db = isc_mem_strdup(view->mctx, buffer); 2262 2263 status = mdb_env_create(&env); 2264 if (status != MDB_SUCCESS) { 2265 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2266 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 2267 "mdb_env_create failed: %s", 2268 mdb_strerror(status)); 2269 CHECK(ISC_R_FAILURE); 2270 } 2271 2272 if (mapsize != 0ULL) { 2273 status = mdb_env_set_mapsize(env, mapsize); 2274 if (status != MDB_SUCCESS) { 2275 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2276 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 2277 "mdb_env_set_mapsize failed: %s", 2278 mdb_strerror(status)); 2279 CHECK(ISC_R_FAILURE); 2280 } 2281 view->new_zone_mapsize = mapsize; 2282 } 2283 2284 status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); 2285 if (status != MDB_SUCCESS) { 2286 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 2287 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 2288 "mdb_env_open of '%s' failed: %s", 2289 view->new_zone_db, mdb_strerror(status)); 2290 CHECK(ISC_R_FAILURE); 2291 } 2292 2293 view->new_zone_dbenv = env; 2294 env = NULL; 2295#endif /* HAVE_LMDB */ 2296 2297 view->new_zone_config = cfgctx; 2298 view->cfg_destroy = cfg_destroy; 2299 2300cleanup: 2301 if (result != ISC_R_SUCCESS) { 2302 if (view->new_zone_file != NULL) { 2303 isc_mem_free(view->mctx, view->new_zone_file); 2304 view->new_zone_file = NULL; 2305 } 2306 2307#ifdef HAVE_LMDB 2308 if (view->new_zone_db != NULL) { 2309 isc_mem_free(view->mctx, view->new_zone_db); 2310 view->new_zone_db = NULL; 2311 } 2312 if (env != NULL) { 2313 mdb_env_close(env); 2314 } 2315#endif /* HAVE_LMDB */ 2316 view->new_zone_config = NULL; 2317 view->cfg_destroy = NULL; 2318 } 2319 2320 return (result); 2321} 2322 2323void 2324dns_view_setnewzonedir(dns_view_t *view, const char *dir) { 2325 REQUIRE(DNS_VIEW_VALID(view)); 2326 2327 if (view->new_zone_dir != NULL) { 2328 isc_mem_free(view->mctx, view->new_zone_dir); 2329 view->new_zone_dir = NULL; 2330 } 2331 2332 if (dir == NULL) { 2333 return; 2334 } 2335 2336 view->new_zone_dir = isc_mem_strdup(view->mctx, dir); 2337} 2338 2339const char * 2340dns_view_getnewzonedir(dns_view_t *view) { 2341 REQUIRE(DNS_VIEW_VALID(view)); 2342 2343 return (view->new_zone_dir); 2344} 2345 2346isc_result_t 2347dns_view_searchdlz(dns_view_t *view, const dns_name_t *name, 2348 unsigned int minlabels, dns_clientinfomethods_t *methods, 2349 dns_clientinfo_t *clientinfo, dns_db_t **dbp) { 2350 dns_fixedname_t fname; 2351 dns_name_t *zonename; 2352 unsigned int namelabels; 2353 unsigned int i; 2354 isc_result_t result; 2355 dns_dlzfindzone_t findzone; 2356 dns_dlzdb_t *dlzdb; 2357 dns_db_t *db, *best = NULL; 2358 2359 /* 2360 * Performs checks to make sure data is as we expect it to be. 2361 */ 2362 REQUIRE(DNS_VIEW_VALID(view)); 2363 REQUIRE(name != NULL); 2364 REQUIRE(dbp != NULL && *dbp == NULL); 2365 2366 /* setup a "fixed" dns name */ 2367 zonename = dns_fixedname_initname(&fname); 2368 2369 /* count the number of labels in the name */ 2370 namelabels = dns_name_countlabels(name); 2371 2372 for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL; 2373 dlzdb = ISC_LIST_NEXT(dlzdb, link)) 2374 { 2375 REQUIRE(DNS_DLZ_VALID(dlzdb)); 2376 2377 /* 2378 * loop through starting with the longest domain name and 2379 * trying shorter names portions of the name until we find a 2380 * match, have an error, or are below the 'minlabels' 2381 * threshold. minlabels is 0, if neither the standard 2382 * database nor any previous DLZ database had a zone name 2383 * match. Otherwise minlabels is the number of labels 2384 * in that name. We need to beat that for a "better" 2385 * match for this DLZ database to be authoritative. 2386 */ 2387 for (i = namelabels; i > minlabels && i > 1; i--) { 2388 if (i == namelabels) { 2389 dns_name_copy(name, zonename); 2390 } else { 2391 dns_name_split(name, i, NULL, zonename); 2392 } 2393 2394 /* ask SDLZ driver if the zone is supported */ 2395 db = NULL; 2396 findzone = dlzdb->implementation->methods->findzone; 2397 result = (*findzone)(dlzdb->implementation->driverarg, 2398 dlzdb->dbdata, dlzdb->mctx, 2399 view->rdclass, zonename, methods, 2400 clientinfo, &db); 2401 2402 if (result != ISC_R_NOTFOUND) { 2403 if (best != NULL) { 2404 dns_db_detach(&best); 2405 } 2406 if (result == ISC_R_SUCCESS) { 2407 INSIST(db != NULL); 2408 dns_db_attach(db, &best); 2409 dns_db_detach(&db); 2410 minlabels = i; 2411 } else { 2412 if (db != NULL) { 2413 dns_db_detach(&db); 2414 } 2415 break; 2416 } 2417 } else if (db != NULL) { 2418 dns_db_detach(&db); 2419 } 2420 } 2421 } 2422 2423 if (best != NULL) { 2424 dns_db_attach(best, dbp); 2425 dns_db_detach(&best); 2426 return (ISC_R_SUCCESS); 2427 } 2428 2429 return (ISC_R_NOTFOUND); 2430} 2431 2432uint32_t 2433dns_view_getfailttl(dns_view_t *view) { 2434 REQUIRE(DNS_VIEW_VALID(view)); 2435 return (view->fail_ttl); 2436} 2437 2438void 2439dns_view_setfailttl(dns_view_t *view, uint32_t fail_ttl) { 2440 REQUIRE(DNS_VIEW_VALID(view)); 2441 view->fail_ttl = fail_ttl; 2442} 2443 2444isc_result_t 2445dns_view_saventa(dns_view_t *view) { 2446 isc_result_t result; 2447 bool removefile = false; 2448 dns_ntatable_t *ntatable = NULL; 2449 FILE *fp = NULL; 2450 2451 REQUIRE(DNS_VIEW_VALID(view)); 2452 2453 if (view->nta_lifetime == 0) { 2454 return (ISC_R_SUCCESS); 2455 } 2456 2457 /* Open NTA save file for overwrite. */ 2458 CHECK(isc_stdio_open(view->nta_file, "w", &fp)); 2459 2460 result = dns_view_getntatable(view, &ntatable); 2461 if (result == ISC_R_NOTFOUND) { 2462 removefile = true; 2463 result = ISC_R_SUCCESS; 2464 goto cleanup; 2465 } else { 2466 CHECK(result); 2467 } 2468 2469 result = dns_ntatable_save(ntatable, fp); 2470 if (result == ISC_R_NOTFOUND) { 2471 removefile = true; 2472 result = ISC_R_SUCCESS; 2473 } else if (result == ISC_R_SUCCESS) { 2474 result = isc_stdio_close(fp); 2475 fp = NULL; 2476 } 2477 2478cleanup: 2479 if (ntatable != NULL) { 2480 dns_ntatable_detach(&ntatable); 2481 } 2482 2483 if (fp != NULL) { 2484 (void)isc_stdio_close(fp); 2485 } 2486 2487 /* Don't leave half-baked NTA save files lying around. */ 2488 if (result != ISC_R_SUCCESS || removefile) { 2489 (void)isc_file_remove(view->nta_file); 2490 } 2491 2492 return (result); 2493} 2494 2495#define TSTR(t) ((t).value.as_textregion.base) 2496#define TLEN(t) ((t).value.as_textregion.length) 2497 2498isc_result_t 2499dns_view_loadnta(dns_view_t *view) { 2500 isc_result_t result; 2501 dns_ntatable_t *ntatable = NULL; 2502 isc_lex_t *lex = NULL; 2503 isc_token_t token; 2504 isc_stdtime_t now; 2505 2506 REQUIRE(DNS_VIEW_VALID(view)); 2507 2508 if (view->nta_lifetime == 0) { 2509 return (ISC_R_SUCCESS); 2510 } 2511 2512 CHECK(isc_lex_create(view->mctx, 1025, &lex)); 2513 CHECK(isc_lex_openfile(lex, view->nta_file)); 2514 CHECK(dns_view_getntatable(view, &ntatable)); 2515 isc_stdtime_get(&now); 2516 2517 for (;;) { 2518 int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF); 2519 char *name, *type, *timestamp; 2520 size_t len; 2521 dns_fixedname_t fn; 2522 const dns_name_t *ntaname; 2523 isc_buffer_t b; 2524 isc_stdtime_t t; 2525 bool forced; 2526 2527 CHECK(isc_lex_gettoken(lex, options, &token)); 2528 if (token.type == isc_tokentype_eof) { 2529 break; 2530 } else if (token.type != isc_tokentype_string) { 2531 CHECK(ISC_R_UNEXPECTEDTOKEN); 2532 } 2533 name = TSTR(token); 2534 len = TLEN(token); 2535 2536 if (strcmp(name, ".") == 0) { 2537 ntaname = dns_rootname; 2538 } else { 2539 dns_name_t *fname; 2540 fname = dns_fixedname_initname(&fn); 2541 2542 isc_buffer_init(&b, name, (unsigned int)len); 2543 isc_buffer_add(&b, (unsigned int)len); 2544 CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0, 2545 NULL)); 2546 ntaname = fname; 2547 } 2548 2549 CHECK(isc_lex_gettoken(lex, options, &token)); 2550 if (token.type != isc_tokentype_string) { 2551 CHECK(ISC_R_UNEXPECTEDTOKEN); 2552 } 2553 type = TSTR(token); 2554 2555 if (strcmp(type, "regular") == 0) { 2556 forced = false; 2557 } else if (strcmp(type, "forced") == 0) { 2558 forced = true; 2559 } else { 2560 CHECK(ISC_R_UNEXPECTEDTOKEN); 2561 } 2562 2563 CHECK(isc_lex_gettoken(lex, options, &token)); 2564 if (token.type != isc_tokentype_string) { 2565 CHECK(ISC_R_UNEXPECTEDTOKEN); 2566 } 2567 timestamp = TSTR(token); 2568 CHECK(dns_time32_fromtext(timestamp, &t)); 2569 2570 CHECK(isc_lex_gettoken(lex, options, &token)); 2571 if (token.type != isc_tokentype_eol && 2572 token.type != isc_tokentype_eof) 2573 { 2574 CHECK(ISC_R_UNEXPECTEDTOKEN); 2575 } 2576 2577 if (now <= t) { 2578 if (t > (now + 604800)) { 2579 t = now + 604800; 2580 } 2581 2582 (void)dns_ntatable_add(ntatable, ntaname, forced, 0, t); 2583 } else { 2584 char nb[DNS_NAME_FORMATSIZE]; 2585 dns_name_format(ntaname, nb, sizeof(nb)); 2586 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2587 DNS_LOGMODULE_NTA, ISC_LOG_INFO, 2588 "ignoring expired NTA at %s", nb); 2589 } 2590 } 2591 2592cleanup: 2593 if (ntatable != NULL) { 2594 dns_ntatable_detach(&ntatable); 2595 } 2596 2597 if (lex != NULL) { 2598 isc_lex_close(lex); 2599 isc_lex_destroy(&lex); 2600 } 2601 2602 return (result); 2603} 2604 2605void 2606dns_view_setviewcommit(dns_view_t *view) { 2607 dns_zone_t *redirect = NULL, *managed_keys = NULL; 2608 2609 REQUIRE(DNS_VIEW_VALID(view)); 2610 2611 LOCK(&view->lock); 2612 2613 if (view->redirect != NULL) { 2614 dns_zone_attach(view->redirect, &redirect); 2615 } 2616 if (view->managed_keys != NULL) { 2617 dns_zone_attach(view->managed_keys, &managed_keys); 2618 } 2619 2620 UNLOCK(&view->lock); 2621 2622 if (view->zonetable != NULL) { 2623 dns_zt_setviewcommit(view->zonetable); 2624 } 2625 if (redirect != NULL) { 2626 dns_zone_setviewcommit(redirect); 2627 dns_zone_detach(&redirect); 2628 } 2629 if (managed_keys != NULL) { 2630 dns_zone_setviewcommit(managed_keys); 2631 dns_zone_detach(&managed_keys); 2632 } 2633} 2634 2635void 2636dns_view_setviewrevert(dns_view_t *view) { 2637 dns_zone_t *redirect = NULL, *managed_keys = NULL; 2638 dns_zt_t *zonetable; 2639 2640 REQUIRE(DNS_VIEW_VALID(view)); 2641 2642 /* 2643 * dns_zt_setviewrevert() attempts to lock this view, so we must 2644 * release the lock. 2645 */ 2646 LOCK(&view->lock); 2647 if (view->redirect != NULL) { 2648 dns_zone_attach(view->redirect, &redirect); 2649 } 2650 if (view->managed_keys != NULL) { 2651 dns_zone_attach(view->managed_keys, &managed_keys); 2652 } 2653 zonetable = view->zonetable; 2654 UNLOCK(&view->lock); 2655 2656 if (redirect != NULL) { 2657 dns_zone_setviewrevert(redirect); 2658 dns_zone_detach(&redirect); 2659 } 2660 if (managed_keys != NULL) { 2661 dns_zone_setviewrevert(managed_keys); 2662 dns_zone_detach(&managed_keys); 2663 } 2664 if (zonetable != NULL) { 2665 dns_zt_setviewrevert(zonetable); 2666 } 2667} 2668 2669bool 2670dns_view_staleanswerenabled(dns_view_t *view) { 2671 uint32_t stale_ttl = 0; 2672 bool result = false; 2673 2674 REQUIRE(DNS_VIEW_VALID(view)); 2675 2676 if (dns_db_getservestalettl(view->cachedb, &stale_ttl) != ISC_R_SUCCESS) 2677 { 2678 return (false); 2679 } 2680 if (stale_ttl > 0) { 2681 if (view->staleanswersok == dns_stale_answer_yes) { 2682 result = true; 2683 } else if (view->staleanswersok == dns_stale_answer_conf) { 2684 result = view->staleanswersenable; 2685 } 2686 } 2687 2688 return (result); 2689} 2690 2691static void 2692free_sfd(void *data, void *arg) { 2693 isc_mem_put(arg, data, sizeof(unsigned int)); 2694} 2695 2696void 2697dns_view_sfd_add(dns_view_t *view, const dns_name_t *name) { 2698 isc_result_t result; 2699 dns_rbtnode_t *node = NULL; 2700 2701 REQUIRE(DNS_VIEW_VALID(view)); 2702 2703 RWLOCK(&view->sfd_lock, isc_rwlocktype_write); 2704 if (view->sfd == NULL) { 2705 result = dns_rbt_create(view->mctx, free_sfd, view->mctx, 2706 &view->sfd); 2707 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2708 } 2709 2710 result = dns_rbt_addnode(view->sfd, name, &node); 2711 RUNTIME_CHECK(result == ISC_R_SUCCESS || result == ISC_R_EXISTS); 2712 if (node->data != NULL) { 2713 unsigned int *count = node->data; 2714 (*count)++; 2715 } else { 2716 unsigned int *count = isc_mem_get(view->mctx, 2717 sizeof(unsigned int)); 2718 *count = 1; 2719 node->data = count; 2720 } 2721 RWUNLOCK(&view->sfd_lock, isc_rwlocktype_write); 2722} 2723 2724void 2725dns_view_sfd_del(dns_view_t *view, const dns_name_t *name) { 2726 isc_result_t result; 2727 void *data = NULL; 2728 2729 REQUIRE(DNS_VIEW_VALID(view)); 2730 2731 RWLOCK(&view->sfd_lock, isc_rwlocktype_write); 2732 INSIST(view->sfd != NULL); 2733 result = dns_rbt_findname(view->sfd, name, 0, NULL, &data); 2734 if (result == ISC_R_SUCCESS) { 2735 unsigned int *count = data; 2736 INSIST(count != NULL); 2737 if (--(*count) == 0U) { 2738 result = dns_rbt_deletename(view->sfd, name, false); 2739 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2740 } 2741 } 2742 RWUNLOCK(&view->sfd_lock, isc_rwlocktype_write); 2743} 2744 2745void 2746dns_view_sfd_find(dns_view_t *view, const dns_name_t *name, 2747 dns_name_t *foundname) { 2748 REQUIRE(DNS_VIEW_VALID(view)); 2749 2750 if (view->sfd != NULL) { 2751 isc_result_t result; 2752 void *data = NULL; 2753 2754 RWLOCK(&view->sfd_lock, isc_rwlocktype_read); 2755 result = dns_rbt_findname(view->sfd, name, 0, foundname, &data); 2756 RWUNLOCK(&view->sfd_lock, isc_rwlocktype_read); 2757 if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) { 2758 dns_name_copy(dns_rootname, foundname); 2759 } 2760 } else { 2761 dns_name_copy(dns_rootname, foundname); 2762 } 2763} 2764