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