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