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