1/* $NetBSD: view.c,v 1.5 2012/12/04 23:38:43 spz Exp $ */ 2 3/* 4 * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1999-2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20/* Id */ 21 22/*! \file */ 23 24#include <config.h> 25 26#include <isc/file.h> 27#include <isc/hash.h> 28#include <isc/print.h> 29#include <isc/sha2.h> 30#include <isc/stats.h> 31#include <isc/string.h> /* Required for HP/UX (and others?) */ 32#include <isc/task.h> 33#include <isc/util.h> 34 35#include <dns/acache.h> 36#include <dns/acl.h> 37#include <dns/adb.h> 38#include <dns/cache.h> 39#include <dns/db.h> 40#include <dns/dlz.h> 41#ifdef BIND9 42#include <dns/dns64.h> 43#endif 44#include <dns/dnssec.h> 45#include <dns/events.h> 46#include <dns/forward.h> 47#include <dns/keytable.h> 48#include <dns/keyvalues.h> 49#include <dns/master.h> 50#include <dns/masterdump.h> 51#include <dns/order.h> 52#include <dns/peer.h> 53#include <dns/rbt.h> 54#include <dns/rdataset.h> 55#include <dns/request.h> 56#include <dns/resolver.h> 57#include <dns/result.h> 58#include <dns/rpz.h> 59#include <dns/stats.h> 60#include <dns/tsig.h> 61#include <dns/zone.h> 62#include <dns/zt.h> 63 64#define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0) 65#define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0) 66#define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0) 67 68#define DNS_VIEW_DELONLYHASH 111 69 70static void resolver_shutdown(isc_task_t *task, isc_event_t *event); 71static void adb_shutdown(isc_task_t *task, isc_event_t *event); 72static void req_shutdown(isc_task_t *task, isc_event_t *event); 73 74isc_result_t 75dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, 76 const char *name, dns_view_t **viewp) 77{ 78 dns_view_t *view; 79 isc_result_t result; 80 81 /* 82 * Create a view. 83 */ 84 85 REQUIRE(name != NULL); 86 REQUIRE(viewp != NULL && *viewp == NULL); 87 88 view = isc_mem_get(mctx, sizeof(*view)); 89 if (view == NULL) 90 return (ISC_R_NOMEMORY); 91 view->name = isc_mem_strdup(mctx, name); 92 if (view->name == NULL) { 93 result = ISC_R_NOMEMORY; 94 goto cleanup_view; 95 } 96 result = isc_mutex_init(&view->lock); 97 if (result != ISC_R_SUCCESS) 98 goto cleanup_name; 99 100#ifdef BIND9 101 view->zonetable = NULL; 102 result = dns_zt_create(mctx, rdclass, &view->zonetable); 103 if (result != ISC_R_SUCCESS) { 104 UNEXPECTED_ERROR(__FILE__, __LINE__, 105 "dns_zt_create() failed: %s", 106 isc_result_totext(result)); 107 result = ISC_R_UNEXPECTED; 108 goto cleanup_mutex; 109 } 110#endif 111 view->secroots_priv = NULL; 112 view->fwdtable = NULL; 113 result = dns_fwdtable_create(mctx, &view->fwdtable); 114 if (result != ISC_R_SUCCESS) { 115 UNEXPECTED_ERROR(__FILE__, __LINE__, 116 "dns_fwdtable_create() failed: %s", 117 isc_result_totext(result)); 118 result = ISC_R_UNEXPECTED; 119 goto cleanup_zt; 120 } 121 122 view->acache = NULL; 123 view->cache = NULL; 124 view->cachedb = NULL; 125 view->dlzdatabase = NULL; 126 view->hints = NULL; 127 view->resolver = NULL; 128 view->adb = NULL; 129 view->requestmgr = NULL; 130 view->mctx = mctx; 131 view->rdclass = rdclass; 132 view->frozen = ISC_FALSE; 133 view->task = NULL; 134 result = isc_refcount_init(&view->references, 1); 135 if (result != ISC_R_SUCCESS) 136 goto cleanup_fwdtable; 137 view->weakrefs = 0; 138 view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN| 139 DNS_VIEWATTR_REQSHUTDOWN); 140 view->statickeys = NULL; 141 view->dynamickeys = NULL; 142 view->matchclients = NULL; 143 view->matchdestinations = NULL; 144 view->matchrecursiveonly = ISC_FALSE; 145 result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys); 146 if (result != ISC_R_SUCCESS) 147 goto cleanup_references; 148 view->peers = NULL; 149 view->order = NULL; 150 view->delonly = NULL; 151 view->rootdelonly = ISC_FALSE; 152 view->rootexclude = NULL; 153 view->resstats = NULL; 154 view->resquerystats = NULL; 155 view->cacheshared = ISC_FALSE; 156 ISC_LIST_INIT(view->dns64); 157 view->dns64cnt = 0; 158 159 /* 160 * Initialize configuration data with default values. 161 */ 162 view->recursion = ISC_TRUE; 163 view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ 164 view->additionalfromcache = ISC_TRUE; 165 view->additionalfromauth = ISC_TRUE; 166 view->enablednssec = ISC_TRUE; 167 view->enablevalidation = ISC_TRUE; 168 view->acceptexpired = ISC_FALSE; 169 view->minimalresponses = ISC_FALSE; 170 view->transfer_format = dns_one_answer; 171 view->cacheacl = NULL; 172 view->cacheonacl = NULL; 173 view->queryacl = NULL; 174 view->queryonacl = NULL; 175 view->recursionacl = NULL; 176 view->recursiononacl = NULL; 177 view->sortlist = NULL; 178 view->transferacl = NULL; 179 view->notifyacl = NULL; 180 view->updateacl = NULL; 181 view->upfwdacl = NULL; 182 view->denyansweracl = NULL; 183 view->answeracl_exclude = NULL; 184 view->denyanswernames = NULL; 185 view->answernames_exclude = NULL; 186 view->provideixfr = ISC_TRUE; 187 view->maxcachettl = 7 * 24 * 3600; 188 view->maxncachettl = 3 * 3600; 189 view->dstport = 53; 190 view->preferred_glue = 0; 191 view->flush = ISC_FALSE; 192 view->dlv = NULL; 193 view->maxudp = 0; 194 view->maxbits = 0; 195 view->v4_aaaa = dns_v4_aaaa_ok; 196 view->v4_aaaa_acl = NULL; 197 ISC_LIST_INIT(view->rpz_zones); 198 view->rpz_recursive_only = ISC_TRUE; 199 view->rpz_break_dnssec = ISC_FALSE; 200 dns_fixedname_init(&view->dlv_fixed); 201 view->managed_keys = NULL; 202 view->redirect = NULL; 203#ifdef BIND9 204 view->new_zone_file = NULL; 205 view->new_zone_config = NULL; 206 view->cfg_destroy = NULL; 207 208 result = dns_order_create(view->mctx, &view->order); 209 if (result != ISC_R_SUCCESS) 210 goto cleanup_dynkeys; 211#endif 212 213 result = dns_peerlist_new(view->mctx, &view->peers); 214 if (result != ISC_R_SUCCESS) 215 goto cleanup_order; 216 217 result = dns_aclenv_init(view->mctx, &view->aclenv); 218 if (result != ISC_R_SUCCESS) 219 goto cleanup_peerlist; 220 221 ISC_LINK_INIT(view, link); 222 ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL, 223 DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, 224 view, NULL, NULL, NULL); 225 ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL, 226 DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, 227 view, NULL, NULL, NULL); 228 ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL, 229 DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, 230 view, NULL, NULL, NULL); 231 view->magic = DNS_VIEW_MAGIC; 232 233 *viewp = view; 234 235 return (ISC_R_SUCCESS); 236 237 cleanup_peerlist: 238 dns_peerlist_detach(&view->peers); 239 240 cleanup_order: 241#ifdef BIND9 242 dns_order_detach(&view->order); 243 244 cleanup_dynkeys: 245#endif 246 dns_tsigkeyring_detach(&view->dynamickeys); 247 248 cleanup_references: 249 isc_refcount_destroy(&view->references); 250 251 cleanup_fwdtable: 252 dns_fwdtable_destroy(&view->fwdtable); 253 254 cleanup_zt: 255#ifdef BIND9 256 dns_zt_detach(&view->zonetable); 257 258 cleanup_mutex: 259#endif 260 DESTROYLOCK(&view->lock); 261 262 cleanup_name: 263 isc_mem_free(mctx, view->name); 264 265 cleanup_view: 266 isc_mem_put(mctx, view, sizeof(*view)); 267 268 return (result); 269} 270 271static inline void 272destroy(dns_view_t *view) { 273#ifdef BIND9 274 dns_dns64_t *dns64; 275#endif 276 277 REQUIRE(!ISC_LINK_LINKED(view, link)); 278 REQUIRE(isc_refcount_current(&view->references) == 0); 279 REQUIRE(view->weakrefs == 0); 280 REQUIRE(RESSHUTDOWN(view)); 281 REQUIRE(ADBSHUTDOWN(view)); 282 REQUIRE(REQSHUTDOWN(view)); 283 284#ifdef BIND9 285 if (view->order != NULL) 286 dns_order_detach(&view->order); 287#endif 288 if (view->peers != NULL) 289 dns_peerlist_detach(&view->peers); 290 291 if (view->dynamickeys != NULL) { 292 isc_result_t result; 293 char template[20]; 294 char keyfile[20]; 295 FILE *fp = NULL; 296 int n; 297 298 n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys", 299 view->name); 300 if (n > 0 && (size_t)n < sizeof(keyfile)) { 301 result = isc_file_mktemplate(keyfile, template, 302 sizeof(template)); 303 if (result == ISC_R_SUCCESS) 304 (void)isc_file_openuniqueprivate(template, &fp); 305 } 306 if (fp == NULL) 307 dns_tsigkeyring_detach(&view->dynamickeys); 308 else { 309 result = dns_tsigkeyring_dumpanddetach( 310 &view->dynamickeys, fp); 311 if (result == ISC_R_SUCCESS) { 312 if (fclose(fp) == 0) 313 result = isc_file_rename(template, 314 keyfile); 315 if (result != ISC_R_SUCCESS) 316 (void)remove(template); 317 } else { 318 (void)fclose(fp); 319 (void)remove(template); 320 } 321 } 322 } 323 if (view->statickeys != NULL) 324 dns_tsigkeyring_detach(&view->statickeys); 325 if (view->adb != NULL) 326 dns_adb_detach(&view->adb); 327 if (view->resolver != NULL) 328 dns_resolver_detach(&view->resolver); 329#ifdef BIND9 330 if (view->acache != NULL) { 331 if (view->cachedb != NULL) 332 dns_acache_putdb(view->acache, view->cachedb); 333 dns_acache_detach(&view->acache); 334 } 335 dns_rpz_view_destroy(view); 336#else 337 INSIST(view->acache == NULL); 338 INSIST(ISC_LIST_EMPTY(view->rpz_zones)); 339#endif 340 if (view->requestmgr != NULL) 341 dns_requestmgr_detach(&view->requestmgr); 342 if (view->task != NULL) 343 isc_task_detach(&view->task); 344 if (view->hints != NULL) 345 dns_db_detach(&view->hints); 346 if (view->dlzdatabase != NULL) 347 dns_dlzdestroy(&view->dlzdatabase); 348 if (view->cachedb != NULL) 349 dns_db_detach(&view->cachedb); 350 if (view->cache != NULL) 351 dns_cache_detach(&view->cache); 352 if (view->matchclients != NULL) 353 dns_acl_detach(&view->matchclients); 354 if (view->matchdestinations != NULL) 355 dns_acl_detach(&view->matchdestinations); 356 if (view->cacheacl != NULL) 357 dns_acl_detach(&view->cacheacl); 358 if (view->cacheonacl != NULL) 359 dns_acl_detach(&view->cacheonacl); 360 if (view->queryacl != NULL) 361 dns_acl_detach(&view->queryacl); 362 if (view->queryonacl != NULL) 363 dns_acl_detach(&view->queryonacl); 364 if (view->recursionacl != NULL) 365 dns_acl_detach(&view->recursionacl); 366 if (view->recursiononacl != NULL) 367 dns_acl_detach(&view->recursiononacl); 368 if (view->sortlist != NULL) 369 dns_acl_detach(&view->sortlist); 370 if (view->transferacl != NULL) 371 dns_acl_detach(&view->transferacl); 372 if (view->notifyacl != NULL) 373 dns_acl_detach(&view->notifyacl); 374 if (view->updateacl != NULL) 375 dns_acl_detach(&view->updateacl); 376 if (view->upfwdacl != NULL) 377 dns_acl_detach(&view->upfwdacl); 378 if (view->denyansweracl != NULL) 379 dns_acl_detach(&view->denyansweracl); 380 if (view->v4_aaaa_acl != NULL) 381 dns_acl_detach(&view->v4_aaaa_acl); 382 if (view->answeracl_exclude != NULL) 383 dns_rbt_destroy(&view->answeracl_exclude); 384 if (view->denyanswernames != NULL) 385 dns_rbt_destroy(&view->denyanswernames); 386 if (view->answernames_exclude != NULL) 387 dns_rbt_destroy(&view->answernames_exclude); 388 if (view->delonly != NULL) { 389 dns_name_t *name; 390 int i; 391 392 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 393 name = ISC_LIST_HEAD(view->delonly[i]); 394 while (name != NULL) { 395 ISC_LIST_UNLINK(view->delonly[i], name, link); 396 dns_name_free(name, view->mctx); 397 isc_mem_put(view->mctx, name, sizeof(*name)); 398 name = ISC_LIST_HEAD(view->delonly[i]); 399 } 400 } 401 isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) * 402 DNS_VIEW_DELONLYHASH); 403 view->delonly = NULL; 404 } 405 if (view->rootexclude != NULL) { 406 dns_name_t *name; 407 int i; 408 409 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 410 name = ISC_LIST_HEAD(view->rootexclude[i]); 411 while (name != NULL) { 412 ISC_LIST_UNLINK(view->rootexclude[i], 413 name, link); 414 dns_name_free(name, view->mctx); 415 isc_mem_put(view->mctx, name, sizeof(*name)); 416 name = ISC_LIST_HEAD(view->rootexclude[i]); 417 } 418 } 419 isc_mem_put(view->mctx, view->rootexclude, 420 sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH); 421 view->rootexclude = NULL; 422 } 423 if (view->resstats != NULL) 424 isc_stats_detach(&view->resstats); 425 if (view->resquerystats != NULL) 426 dns_stats_detach(&view->resquerystats); 427 if (view->secroots_priv != NULL) 428 dns_keytable_detach(&view->secroots_priv); 429#ifdef BIND9 430 for (dns64 = ISC_LIST_HEAD(view->dns64); 431 dns64 != NULL; 432 dns64 = ISC_LIST_HEAD(view->dns64)) { 433 dns_dns64_unlink(&view->dns64, dns64); 434 dns_dns64_destroy(&dns64); 435 } 436 if (view->managed_keys != NULL) 437 dns_zone_detach(&view->managed_keys); 438 if (view->redirect != NULL) 439 dns_zone_detach(&view->redirect); 440 dns_view_setnewzones(view, ISC_FALSE, NULL, NULL); 441#endif 442 dns_fwdtable_destroy(&view->fwdtable); 443 dns_aclenv_destroy(&view->aclenv); 444 DESTROYLOCK(&view->lock); 445 isc_refcount_destroy(&view->references); 446 isc_mem_free(view->mctx, view->name); 447 isc_mem_put(view->mctx, view, sizeof(*view)); 448} 449 450/* 451 * Return true iff 'view' may be freed. 452 * The caller must be holding the view lock. 453 */ 454static isc_boolean_t 455all_done(dns_view_t *view) { 456 457 if (isc_refcount_current(&view->references) == 0 && 458 view->weakrefs == 0 && 459 RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view)) 460 return (ISC_TRUE); 461 462 return (ISC_FALSE); 463} 464 465void 466dns_view_attach(dns_view_t *source, dns_view_t **targetp) { 467 468 REQUIRE(DNS_VIEW_VALID(source)); 469 REQUIRE(targetp != NULL && *targetp == NULL); 470 471 isc_refcount_increment(&source->references, NULL); 472 473 *targetp = source; 474} 475 476static void 477view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { 478 dns_view_t *view; 479 unsigned int refs; 480 isc_boolean_t done = ISC_FALSE; 481 482 REQUIRE(viewp != NULL); 483 view = *viewp; 484 REQUIRE(DNS_VIEW_VALID(view)); 485 486 if (flush) 487 view->flush = ISC_TRUE; 488 isc_refcount_decrement(&view->references, &refs); 489 if (refs == 0) { 490 LOCK(&view->lock); 491 if (!RESSHUTDOWN(view)) 492 dns_resolver_shutdown(view->resolver); 493 if (!ADBSHUTDOWN(view)) 494 dns_adb_shutdown(view->adb); 495 if (!REQSHUTDOWN(view)) 496 dns_requestmgr_shutdown(view->requestmgr); 497#ifdef BIND9 498 if (view->acache != NULL) 499 dns_acache_shutdown(view->acache); 500 if (view->flush) 501 dns_zt_flushanddetach(&view->zonetable); 502 else 503 dns_zt_detach(&view->zonetable); 504 if (view->managed_keys != NULL) { 505 if (view->flush) 506 dns_zone_flush(view->managed_keys); 507 dns_zone_detach(&view->managed_keys); 508 } 509 if (view->redirect != NULL) { 510 if (view->flush) 511 dns_zone_flush(view->redirect); 512 dns_zone_detach(&view->redirect); 513 } 514#endif 515 done = all_done(view); 516 UNLOCK(&view->lock); 517 } 518 519 *viewp = NULL; 520 521 if (done) 522 destroy(view); 523} 524 525void 526dns_view_flushanddetach(dns_view_t **viewp) { 527 view_flushanddetach(viewp, ISC_TRUE); 528} 529 530void 531dns_view_detach(dns_view_t **viewp) { 532 view_flushanddetach(viewp, ISC_FALSE); 533} 534 535#ifdef BIND9 536static isc_result_t 537dialup(dns_zone_t *zone, void *dummy) { 538 UNUSED(dummy); 539 dns_zone_dialup(zone); 540 return (ISC_R_SUCCESS); 541} 542 543void 544dns_view_dialup(dns_view_t *view) { 545 REQUIRE(DNS_VIEW_VALID(view)); 546 (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL); 547} 548#endif 549 550void 551dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) { 552 553 REQUIRE(DNS_VIEW_VALID(source)); 554 REQUIRE(targetp != NULL && *targetp == NULL); 555 556 LOCK(&source->lock); 557 source->weakrefs++; 558 UNLOCK(&source->lock); 559 560 *targetp = source; 561} 562 563void 564dns_view_weakdetach(dns_view_t **viewp) { 565 dns_view_t *view; 566 isc_boolean_t done = ISC_FALSE; 567 568 REQUIRE(viewp != NULL); 569 view = *viewp; 570 REQUIRE(DNS_VIEW_VALID(view)); 571 572 LOCK(&view->lock); 573 574 INSIST(view->weakrefs > 0); 575 view->weakrefs--; 576 done = all_done(view); 577 578 UNLOCK(&view->lock); 579 580 *viewp = NULL; 581 582 if (done) 583 destroy(view); 584} 585 586static void 587resolver_shutdown(isc_task_t *task, isc_event_t *event) { 588 dns_view_t *view = event->ev_arg; 589 isc_boolean_t done; 590 591 REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN); 592 REQUIRE(DNS_VIEW_VALID(view)); 593 REQUIRE(view->task == task); 594 595 UNUSED(task); 596 597 LOCK(&view->lock); 598 599 view->attributes |= DNS_VIEWATTR_RESSHUTDOWN; 600 done = all_done(view); 601 602 UNLOCK(&view->lock); 603 604 isc_event_free(&event); 605 606 if (done) 607 destroy(view); 608} 609 610static void 611adb_shutdown(isc_task_t *task, isc_event_t *event) { 612 dns_view_t *view = event->ev_arg; 613 isc_boolean_t done; 614 615 REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN); 616 REQUIRE(DNS_VIEW_VALID(view)); 617 REQUIRE(view->task == task); 618 619 UNUSED(task); 620 621 LOCK(&view->lock); 622 623 view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN; 624 done = all_done(view); 625 626 UNLOCK(&view->lock); 627 628 isc_event_free(&event); 629 630 if (done) 631 destroy(view); 632} 633 634static void 635req_shutdown(isc_task_t *task, isc_event_t *event) { 636 dns_view_t *view = event->ev_arg; 637 isc_boolean_t done; 638 639 REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN); 640 REQUIRE(DNS_VIEW_VALID(view)); 641 REQUIRE(view->task == task); 642 643 UNUSED(task); 644 645 LOCK(&view->lock); 646 647 view->attributes |= DNS_VIEWATTR_REQSHUTDOWN; 648 done = all_done(view); 649 650 UNLOCK(&view->lock); 651 652 isc_event_free(&event); 653 654 if (done) 655 destroy(view); 656} 657 658isc_result_t 659dns_view_createresolver(dns_view_t *view, 660 isc_taskmgr_t *taskmgr, unsigned int ntasks, 661 isc_socketmgr_t *socketmgr, 662 isc_timermgr_t *timermgr, 663 unsigned int options, 664 dns_dispatchmgr_t *dispatchmgr, 665 dns_dispatch_t *dispatchv4, 666 dns_dispatch_t *dispatchv6) 667{ 668 isc_result_t result; 669 isc_event_t *event; 670 isc_mem_t *mctx = NULL; 671 672 REQUIRE(DNS_VIEW_VALID(view)); 673 REQUIRE(!view->frozen); 674 REQUIRE(view->resolver == NULL); 675 676 result = isc_task_create(taskmgr, 0, &view->task); 677 if (result != ISC_R_SUCCESS) 678 return (result); 679 isc_task_setname(view->task, "view", view); 680 681 result = dns_resolver_create(view, taskmgr, ntasks, socketmgr, 682 timermgr, options, dispatchmgr, 683 dispatchv4, dispatchv6, 684 &view->resolver); 685 if (result != ISC_R_SUCCESS) { 686 isc_task_detach(&view->task); 687 return (result); 688 } 689 event = &view->resevent; 690 dns_resolver_whenshutdown(view->resolver, view->task, &event); 691 view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN; 692 693 result = isc_mem_create(0, 0, &mctx); 694 if (result != ISC_R_SUCCESS) { 695 dns_resolver_shutdown(view->resolver); 696 return (result); 697 } 698 699 result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb); 700 isc_mem_setname(mctx, "ADB", NULL); 701 isc_mem_detach(&mctx); 702 if (result != ISC_R_SUCCESS) { 703 dns_resolver_shutdown(view->resolver); 704 return (result); 705 } 706 event = &view->adbevent; 707 dns_adb_whenshutdown(view->adb, view->task, &event); 708 view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN; 709 710 result = dns_requestmgr_create(view->mctx, timermgr, socketmgr, 711 dns_resolver_taskmgr(view->resolver), 712 dns_resolver_dispatchmgr(view->resolver), 713 dns_resolver_dispatchv4(view->resolver), 714 dns_resolver_dispatchv6(view->resolver), 715 &view->requestmgr); 716 if (result != ISC_R_SUCCESS) { 717 dns_adb_shutdown(view->adb); 718 dns_resolver_shutdown(view->resolver); 719 return (result); 720 } 721 event = &view->reqevent; 722 dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event); 723 view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN; 724 725 return (ISC_R_SUCCESS); 726} 727 728void 729dns_view_setcache(dns_view_t *view, dns_cache_t *cache) { 730 dns_view_setcache2(view, cache, ISC_FALSE); 731} 732 733void 734dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) { 735 REQUIRE(DNS_VIEW_VALID(view)); 736 REQUIRE(!view->frozen); 737 738 view->cacheshared = shared; 739 if (view->cache != NULL) { 740#ifdef BIND9 741 if (view->acache != NULL) 742 dns_acache_putdb(view->acache, view->cachedb); 743#endif 744 dns_db_detach(&view->cachedb); 745 dns_cache_detach(&view->cache); 746 } 747 dns_cache_attach(cache, &view->cache); 748 dns_cache_attachdb(cache, &view->cachedb); 749 INSIST(DNS_DB_VALID(view->cachedb)); 750 751#ifdef BIND9 752 if (view->acache != NULL) 753 dns_acache_setdb(view->acache, view->cachedb); 754#endif 755} 756 757isc_boolean_t 758dns_view_iscacheshared(dns_view_t *view) { 759 REQUIRE(DNS_VIEW_VALID(view)); 760 761 return (view->cacheshared); 762} 763 764void 765dns_view_sethints(dns_view_t *view, dns_db_t *hints) { 766 REQUIRE(DNS_VIEW_VALID(view)); 767 REQUIRE(!view->frozen); 768 REQUIRE(view->hints == NULL); 769 REQUIRE(dns_db_iszone(hints)); 770 771 dns_db_attach(hints, &view->hints); 772} 773 774void 775dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { 776 REQUIRE(DNS_VIEW_VALID(view)); 777 REQUIRE(ring != NULL); 778 if (view->statickeys != NULL) 779 dns_tsigkeyring_detach(&view->statickeys); 780 dns_tsigkeyring_attach(ring, &view->statickeys); 781} 782 783void 784dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { 785 REQUIRE(DNS_VIEW_VALID(view)); 786 REQUIRE(ring != NULL); 787 if (view->dynamickeys != NULL) 788 dns_tsigkeyring_detach(&view->dynamickeys); 789 dns_tsigkeyring_attach(ring, &view->dynamickeys); 790} 791 792void 793dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) { 794 REQUIRE(DNS_VIEW_VALID(view)); 795 REQUIRE(ringp != NULL && *ringp == NULL); 796 if (view->dynamickeys != NULL) 797 dns_tsigkeyring_attach(view->dynamickeys, ringp); 798} 799 800void 801dns_view_restorekeyring(dns_view_t *view) { 802 FILE *fp; 803 char keyfile[20]; 804 int n; 805 806 REQUIRE(DNS_VIEW_VALID(view)); 807 808 if (view->dynamickeys != NULL) { 809 n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys", 810 view->name); 811 if (n > 0 && (size_t)n < sizeof(keyfile)) { 812 fp = fopen(keyfile, "r"); 813 if (fp != NULL) { 814 dns_keyring_restore(view->dynamickeys, fp); 815 (void)fclose(fp); 816 } 817 } 818 } 819} 820 821void 822dns_view_setdstport(dns_view_t *view, in_port_t dstport) { 823 REQUIRE(DNS_VIEW_VALID(view)); 824 view->dstport = dstport; 825} 826 827void 828dns_view_freeze(dns_view_t *view) { 829 REQUIRE(DNS_VIEW_VALID(view)); 830 REQUIRE(!view->frozen); 831 832 if (view->resolver != NULL) { 833 INSIST(view->cachedb != NULL); 834 dns_resolver_freeze(view->resolver); 835 } 836 view->frozen = ISC_TRUE; 837} 838 839#ifdef BIND9 840void 841dns_view_thaw(dns_view_t *view) { 842 REQUIRE(DNS_VIEW_VALID(view)); 843 REQUIRE(view->frozen); 844 845 view->frozen = ISC_FALSE; 846} 847 848isc_result_t 849dns_view_addzone(dns_view_t *view, dns_zone_t *zone) { 850 isc_result_t result; 851 852 REQUIRE(DNS_VIEW_VALID(view)); 853 REQUIRE(!view->frozen); 854 855 result = dns_zt_mount(view->zonetable, zone); 856 857 return (result); 858} 859#endif 860 861#ifdef BIND9 862isc_result_t 863dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) { 864 isc_result_t result; 865 866 REQUIRE(DNS_VIEW_VALID(view)); 867 868 result = dns_zt_find(view->zonetable, name, 0, NULL, zonep); 869 if (result == DNS_R_PARTIALMATCH) { 870 dns_zone_detach(zonep); 871 result = ISC_R_NOTFOUND; 872 } 873 874 return (result); 875} 876#endif 877 878isc_result_t 879dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 880 isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints, 881 dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, 882 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 883 return (dns_view_find2(view, name, type, now, options, use_hints, 884 ISC_FALSE, dbp, nodep, foundname, rdataset, 885 sigrdataset)); 886} 887 888isc_result_t 889dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 890 isc_stdtime_t now, unsigned int options, 891 isc_boolean_t use_hints, isc_boolean_t use_static_stub, 892 dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, 893 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 894{ 895 isc_result_t result; 896 dns_db_t *db, *zdb; 897 dns_dbnode_t *node, *znode; 898 isc_boolean_t is_cache, is_staticstub_zone; 899 dns_rdataset_t zrdataset, zsigrdataset; 900 dns_zone_t *zone; 901 902#ifndef BIND9 903 UNUSED(use_hints); 904 UNUSED(use_static_stub); 905#endif 906 907 /* 908 * Find an rdataset whose owner name is 'name', and whose type is 909 * 'type'. 910 */ 911 912 REQUIRE(DNS_VIEW_VALID(view)); 913 REQUIRE(view->frozen); 914 REQUIRE(type != dns_rdatatype_rrsig); 915 REQUIRE(rdataset != NULL); /* XXXBEW - remove this */ 916 REQUIRE(nodep == NULL || *nodep == NULL); 917 918 /* 919 * Initialize. 920 */ 921 dns_rdataset_init(&zrdataset); 922 dns_rdataset_init(&zsigrdataset); 923 zdb = NULL; 924 znode = NULL; 925 926 /* 927 * Find a database to answer the query. 928 */ 929 zone = NULL; 930 db = NULL; 931 node = NULL; 932 is_staticstub_zone = ISC_FALSE; 933#ifdef BIND9 934 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 935 if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub && 936 !use_static_stub) { 937 result = ISC_R_NOTFOUND; 938 } 939 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 940 result = dns_zone_getdb(zone, &db); 941 if (result != ISC_R_SUCCESS && view->cachedb != NULL) 942 dns_db_attach(view->cachedb, &db); 943 else if (result != ISC_R_SUCCESS) 944 goto cleanup; 945 if (dns_zone_gettype(zone) == dns_zone_staticstub && 946 dns_name_equal(name, dns_zone_getorigin(zone))) { 947 is_staticstub_zone = ISC_TRUE; 948 } 949 } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) 950 dns_db_attach(view->cachedb, &db); 951#else 952 result = ISC_R_NOTFOUND; 953 if (view->cachedb != NULL) 954 dns_db_attach(view->cachedb, &db); 955#endif /* BIND9 */ 956 else 957 goto cleanup; 958 959 is_cache = dns_db_iscache(db); 960 961 db_find: 962 /* 963 * Now look for an answer in the database. 964 */ 965 result = dns_db_find(db, name, NULL, type, options, 966 now, &node, foundname, rdataset, sigrdataset); 967 968 if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) { 969 if (dns_rdataset_isassociated(rdataset)) 970 dns_rdataset_disassociate(rdataset); 971 if (sigrdataset != NULL && 972 dns_rdataset_isassociated(sigrdataset)) 973 dns_rdataset_disassociate(sigrdataset); 974 if (node != NULL) 975 dns_db_detachnode(db, &node); 976 if (!is_cache) { 977 dns_db_detach(&db); 978 if (view->cachedb != NULL && !is_staticstub_zone) { 979 /* 980 * Either the answer is in the cache, or we 981 * don't know it. 982 * Note that if the result comes from a 983 * static-stub zone we stop the search here 984 * (see the function description in view.h). 985 */ 986 is_cache = ISC_TRUE; 987 dns_db_attach(view->cachedb, &db); 988 goto db_find; 989 } 990 } else { 991 /* 992 * We don't have the data in the cache. If we've got 993 * glue from the zone, use it. 994 */ 995 if (dns_rdataset_isassociated(&zrdataset)) { 996 dns_rdataset_clone(&zrdataset, rdataset); 997 if (sigrdataset != NULL && 998 dns_rdataset_isassociated(&zsigrdataset)) 999 dns_rdataset_clone(&zsigrdataset, 1000 sigrdataset); 1001 result = DNS_R_GLUE; 1002 if (db != NULL) 1003 dns_db_detach(&db); 1004 dns_db_attach(zdb, &db); 1005 dns_db_attachnode(db, znode, &node); 1006 goto cleanup; 1007 } 1008 } 1009 /* 1010 * We don't know the answer. 1011 */ 1012 result = ISC_R_NOTFOUND; 1013 } else if (result == DNS_R_GLUE) { 1014 if (view->cachedb != NULL && !is_staticstub_zone) { 1015 /* 1016 * We found an answer, but the cache may be better. 1017 * Remember what we've got and go look in the cache. 1018 */ 1019 is_cache = ISC_TRUE; 1020 dns_rdataset_clone(rdataset, &zrdataset); 1021 dns_rdataset_disassociate(rdataset); 1022 if (sigrdataset != NULL && 1023 dns_rdataset_isassociated(sigrdataset)) { 1024 dns_rdataset_clone(sigrdataset, &zsigrdataset); 1025 dns_rdataset_disassociate(sigrdataset); 1026 } 1027 dns_db_attach(db, &zdb); 1028 dns_db_attachnode(zdb, node, &znode); 1029 dns_db_detachnode(db, &node); 1030 dns_db_detach(&db); 1031 dns_db_attach(view->cachedb, &db); 1032 goto db_find; 1033 } 1034 /* 1035 * Otherwise, the glue is the best answer. 1036 */ 1037 result = ISC_R_SUCCESS; 1038 } 1039 1040#ifdef BIND9 1041 if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) { 1042 if (dns_rdataset_isassociated(rdataset)) 1043 dns_rdataset_disassociate(rdataset); 1044 if (sigrdataset != NULL && 1045 dns_rdataset_isassociated(sigrdataset)) 1046 dns_rdataset_disassociate(sigrdataset); 1047 if (db != NULL) { 1048 if (node != NULL) 1049 dns_db_detachnode(db, &node); 1050 dns_db_detach(&db); 1051 } 1052 result = dns_db_find(view->hints, name, NULL, type, options, 1053 now, &node, foundname, 1054 rdataset, sigrdataset); 1055 if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) { 1056 /* 1057 * We just used a hint. Let the resolver know it 1058 * should consider priming. 1059 */ 1060 dns_resolver_prime(view->resolver); 1061 dns_db_attach(view->hints, &db); 1062 result = DNS_R_HINT; 1063 } else if (result == DNS_R_NXRRSET) { 1064 dns_db_attach(view->hints, &db); 1065 result = DNS_R_HINTNXRRSET; 1066 } else if (result == DNS_R_NXDOMAIN) 1067 result = ISC_R_NOTFOUND; 1068 1069 /* 1070 * Cleanup if non-standard hints are used. 1071 */ 1072 if (db == NULL && node != NULL) 1073 dns_db_detachnode(view->hints, &node); 1074 } 1075#endif /* BIND9 */ 1076 1077 cleanup: 1078 if (dns_rdataset_isassociated(&zrdataset)) { 1079 dns_rdataset_disassociate(&zrdataset); 1080 if (dns_rdataset_isassociated(&zsigrdataset)) 1081 dns_rdataset_disassociate(&zsigrdataset); 1082 } 1083 1084 if (zdb != NULL) { 1085 if (znode != NULL) 1086 dns_db_detachnode(zdb, &znode); 1087 dns_db_detach(&zdb); 1088 } 1089 1090 if (db != NULL) { 1091 if (node != NULL) { 1092 if (nodep != NULL) 1093 *nodep = node; 1094 else 1095 dns_db_detachnode(db, &node); 1096 } 1097 if (dbp != NULL) 1098 *dbp = db; 1099 else 1100 dns_db_detach(&db); 1101 } else 1102 INSIST(node == NULL); 1103 1104#ifdef BIND9 1105 if (zone != NULL) 1106 dns_zone_detach(&zone); 1107#endif 1108 1109 return (result); 1110} 1111 1112isc_result_t 1113dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 1114 isc_stdtime_t now, unsigned int options, 1115 isc_boolean_t use_hints, 1116 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 1117{ 1118 isc_result_t result; 1119 dns_fixedname_t foundname; 1120 1121 dns_fixedname_init(&foundname); 1122 result = dns_view_find(view, name, type, now, options, use_hints, 1123 NULL, NULL, dns_fixedname_name(&foundname), 1124 rdataset, sigrdataset); 1125 if (result == DNS_R_NXDOMAIN) { 1126 /* 1127 * The rdataset and sigrdataset of the relevant NSEC record 1128 * may be returned, but the caller cannot use them because 1129 * foundname is not returned by this simplified API. We 1130 * disassociate them here to prevent any misuse by the caller. 1131 */ 1132 if (dns_rdataset_isassociated(rdataset)) 1133 dns_rdataset_disassociate(rdataset); 1134 if (sigrdataset != NULL && 1135 dns_rdataset_isassociated(sigrdataset)) 1136 dns_rdataset_disassociate(sigrdataset); 1137 } else if (result != ISC_R_SUCCESS && 1138 result != DNS_R_GLUE && 1139 result != DNS_R_HINT && 1140 result != DNS_R_NCACHENXDOMAIN && 1141 result != DNS_R_NCACHENXRRSET && 1142 result != DNS_R_NXRRSET && 1143 result != DNS_R_HINTNXRRSET && 1144 result != ISC_R_NOTFOUND) { 1145 if (dns_rdataset_isassociated(rdataset)) 1146 dns_rdataset_disassociate(rdataset); 1147 if (sigrdataset != NULL && 1148 dns_rdataset_isassociated(sigrdataset)) 1149 dns_rdataset_disassociate(sigrdataset); 1150 result = ISC_R_NOTFOUND; 1151 } 1152 1153 return (result); 1154} 1155 1156isc_result_t 1157dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname, 1158 isc_stdtime_t now, unsigned int options, 1159 isc_boolean_t use_hints, 1160 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 1161{ 1162 return(dns_view_findzonecut2(view, name, fname, now, options, 1163 use_hints, ISC_TRUE, 1164 rdataset, sigrdataset)); 1165} 1166 1167isc_result_t 1168dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, 1169 isc_stdtime_t now, unsigned int options, 1170 isc_boolean_t use_hints, isc_boolean_t use_cache, 1171 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 1172{ 1173 isc_result_t result; 1174 dns_db_t *db; 1175 isc_boolean_t is_cache, use_zone, try_hints; 1176 dns_zone_t *zone; 1177 dns_name_t *zfname; 1178 dns_rdataset_t zrdataset, zsigrdataset; 1179 dns_fixedname_t zfixedname; 1180 1181 REQUIRE(DNS_VIEW_VALID(view)); 1182 REQUIRE(view->frozen); 1183 1184 db = NULL; 1185 zone = NULL; 1186 use_zone = ISC_FALSE; 1187 try_hints = ISC_FALSE; 1188 zfname = NULL; 1189 1190 /* 1191 * Initialize. 1192 */ 1193 dns_fixedname_init(&zfixedname); 1194 dns_rdataset_init(&zrdataset); 1195 dns_rdataset_init(&zsigrdataset); 1196 1197 /* 1198 * Find the right database. 1199 */ 1200#ifdef BIND9 1201 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 1202 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) 1203 result = dns_zone_getdb(zone, &db); 1204#else 1205 result = ISC_R_NOTFOUND; 1206#endif 1207 if (result == ISC_R_NOTFOUND) { 1208 /* 1209 * We're not directly authoritative for this query name, nor 1210 * is it a subdomain of any zone for which we're 1211 * authoritative. 1212 */ 1213 if (use_cache && view->cachedb != NULL) { 1214 /* 1215 * We have a cache; try it. 1216 */ 1217 dns_db_attach(view->cachedb, &db); 1218 } else { 1219 /* 1220 * Maybe we have hints... 1221 */ 1222 try_hints = ISC_TRUE; 1223 goto finish; 1224 } 1225 } else if (result != ISC_R_SUCCESS) { 1226 /* 1227 * Something is broken. 1228 */ 1229 goto cleanup; 1230 } 1231 is_cache = dns_db_iscache(db); 1232 1233 db_find: 1234 /* 1235 * Look for the zonecut. 1236 */ 1237 if (!is_cache) { 1238 result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options, 1239 now, NULL, fname, rdataset, sigrdataset); 1240 if (result == DNS_R_DELEGATION) 1241 result = ISC_R_SUCCESS; 1242 else if (result != ISC_R_SUCCESS) 1243 goto cleanup; 1244 if (use_cache && view->cachedb != NULL && db != view->hints) { 1245 /* 1246 * We found an answer, but the cache may be better. 1247 */ 1248 zfname = dns_fixedname_name(&zfixedname); 1249 result = dns_name_copy(fname, zfname, NULL); 1250 if (result != ISC_R_SUCCESS) 1251 goto cleanup; 1252 dns_rdataset_clone(rdataset, &zrdataset); 1253 dns_rdataset_disassociate(rdataset); 1254 if (sigrdataset != NULL && 1255 dns_rdataset_isassociated(sigrdataset)) { 1256 dns_rdataset_clone(sigrdataset, &zsigrdataset); 1257 dns_rdataset_disassociate(sigrdataset); 1258 } 1259 dns_db_detach(&db); 1260 dns_db_attach(view->cachedb, &db); 1261 is_cache = ISC_TRUE; 1262 goto db_find; 1263 } 1264 } else { 1265 result = dns_db_findzonecut(db, name, options, now, NULL, 1266 fname, rdataset, sigrdataset); 1267 if (result == ISC_R_SUCCESS) { 1268 if (zfname != NULL && 1269 (!dns_name_issubdomain(fname, zfname) || 1270 (dns_zone_staticstub && 1271 dns_name_equal(fname, zfname)))) { 1272 /* 1273 * We found a zonecut in the cache, but our 1274 * zone delegation is better. 1275 */ 1276 use_zone = ISC_TRUE; 1277 } 1278 } else if (result == ISC_R_NOTFOUND) { 1279 if (zfname != NULL) { 1280 /* 1281 * We didn't find anything in the cache, but we 1282 * have a zone delegation, so use it. 1283 */ 1284 use_zone = ISC_TRUE; 1285 } else { 1286 /* 1287 * Maybe we have hints... 1288 */ 1289 try_hints = ISC_TRUE; 1290 } 1291 } else { 1292 /* 1293 * Something bad happened. 1294 */ 1295 goto cleanup; 1296 } 1297 } 1298 1299 finish: 1300 if (use_zone) { 1301 if (dns_rdataset_isassociated(rdataset)) { 1302 dns_rdataset_disassociate(rdataset); 1303 if (sigrdataset != NULL && 1304 dns_rdataset_isassociated(sigrdataset)) 1305 dns_rdataset_disassociate(sigrdataset); 1306 } 1307 result = dns_name_copy(zfname, fname, NULL); 1308 if (result != ISC_R_SUCCESS) 1309 goto cleanup; 1310 dns_rdataset_clone(&zrdataset, rdataset); 1311 if (sigrdataset != NULL && 1312 dns_rdataset_isassociated(&zrdataset)) 1313 dns_rdataset_clone(&zsigrdataset, sigrdataset); 1314 } else if (try_hints && use_hints && view->hints != NULL) { 1315 /* 1316 * We've found nothing so far, but we have hints. 1317 */ 1318 result = dns_db_find(view->hints, dns_rootname, NULL, 1319 dns_rdatatype_ns, 0, now, NULL, fname, 1320 rdataset, NULL); 1321 if (result != ISC_R_SUCCESS) { 1322 /* 1323 * We can't even find the hints for the root 1324 * nameservers! 1325 */ 1326 if (dns_rdataset_isassociated(rdataset)) 1327 dns_rdataset_disassociate(rdataset); 1328 result = ISC_R_NOTFOUND; 1329 } 1330 } 1331 1332 cleanup: 1333 if (dns_rdataset_isassociated(&zrdataset)) { 1334 dns_rdataset_disassociate(&zrdataset); 1335 if (dns_rdataset_isassociated(&zsigrdataset)) 1336 dns_rdataset_disassociate(&zsigrdataset); 1337 } 1338 if (db != NULL) 1339 dns_db_detach(&db); 1340#ifdef BIND9 1341 if (zone != NULL) 1342 dns_zone_detach(&zone); 1343#endif 1344 1345 return (result); 1346} 1347 1348isc_result_t 1349dns_viewlist_find(dns_viewlist_t *list, const char *name, 1350 dns_rdataclass_t rdclass, dns_view_t **viewp) 1351{ 1352 dns_view_t *view; 1353 1354 REQUIRE(list != NULL); 1355 1356 for (view = ISC_LIST_HEAD(*list); 1357 view != NULL; 1358 view = ISC_LIST_NEXT(view, link)) { 1359 if (strcmp(view->name, name) == 0 && view->rdclass == rdclass) 1360 break; 1361 } 1362 if (view == NULL) 1363 return (ISC_R_NOTFOUND); 1364 1365 dns_view_attach(view, viewp); 1366 1367 return (ISC_R_SUCCESS); 1368} 1369 1370#ifdef BIND9 1371isc_result_t 1372dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, 1373 isc_boolean_t allclasses, dns_rdataclass_t rdclass, 1374 dns_zone_t **zonep) 1375{ 1376 dns_view_t *view; 1377 isc_result_t result; 1378 dns_zone_t *zone1 = NULL, *zone2 = NULL; 1379 dns_zone_t **zp = NULL;; 1380 1381 REQUIRE(list != NULL); 1382 for (view = ISC_LIST_HEAD(*list); 1383 view != NULL; 1384 view = ISC_LIST_NEXT(view, link)) { 1385 if (allclasses == ISC_FALSE && view->rdclass != rdclass) 1386 continue; 1387 1388 /* 1389 * If the zone is defined in more than one view, 1390 * treat it as not found. 1391 */ 1392 zp = (zone1 == NULL) ? &zone1 : &zone2; 1393 result = dns_zt_find(view->zonetable, name, 0, NULL, zp); 1394 INSIST(result == ISC_R_SUCCESS || 1395 result == ISC_R_NOTFOUND || 1396 result == DNS_R_PARTIALMATCH); 1397 1398 /* Treat a partial match as no match */ 1399 if (result == DNS_R_PARTIALMATCH) { 1400 dns_zone_detach(zp); 1401 result = ISC_R_NOTFOUND; 1402 POST(result); 1403 } 1404 1405 if (zone2 != NULL) { 1406 dns_zone_detach(&zone1); 1407 dns_zone_detach(&zone2); 1408 return (ISC_R_NOTFOUND); 1409 } 1410 } 1411 1412 if (zone1 != NULL) { 1413 dns_zone_attach(zone1, zonep); 1414 dns_zone_detach(&zone1); 1415 return (ISC_R_SUCCESS); 1416 } 1417 1418 return (ISC_R_NOTFOUND); 1419} 1420 1421isc_result_t 1422dns_view_load(dns_view_t *view, isc_boolean_t stop) { 1423 1424 REQUIRE(DNS_VIEW_VALID(view)); 1425 REQUIRE(view->zonetable != NULL); 1426 1427 return (dns_zt_load(view->zonetable, stop)); 1428} 1429 1430isc_result_t 1431dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) { 1432 1433 REQUIRE(DNS_VIEW_VALID(view)); 1434 REQUIRE(view->zonetable != NULL); 1435 1436 return (dns_zt_loadnew(view->zonetable, stop)); 1437} 1438 1439isc_result_t 1440dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg) { 1441 REQUIRE(DNS_VIEW_VALID(view)); 1442 REQUIRE(view->zonetable != NULL); 1443 1444 return (dns_zt_asyncload(view->zonetable, callback, arg)); 1445} 1446 1447 1448#endif /* BIND9 */ 1449 1450isc_result_t 1451dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp) 1452{ 1453 isc_result_t result; 1454 REQUIRE(keyp != NULL && *keyp == NULL); 1455 1456 result = dns_tsigkey_find(keyp, keyname, NULL, 1457 view->statickeys); 1458 if (result == ISC_R_NOTFOUND) 1459 result = dns_tsigkey_find(keyp, keyname, NULL, 1460 view->dynamickeys); 1461 return (result); 1462} 1463 1464isc_result_t 1465dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr, 1466 dns_tsigkey_t **keyp) 1467{ 1468 isc_result_t result; 1469 dns_name_t *keyname = NULL; 1470 dns_peer_t *peer = NULL; 1471 1472 result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer); 1473 if (result != ISC_R_SUCCESS) 1474 return (result); 1475 1476 result = dns_peer_getkey(peer, &keyname); 1477 if (result != ISC_R_SUCCESS) 1478 return (result); 1479 1480 result = dns_view_gettsig(view, keyname, keyp); 1481 return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result); 1482} 1483 1484isc_result_t 1485dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) { 1486 REQUIRE(DNS_VIEW_VALID(view)); 1487 REQUIRE(source != NULL); 1488 1489 return (dns_tsig_verify(source, msg, view->statickeys, 1490 view->dynamickeys)); 1491} 1492 1493#ifdef BIND9 1494isc_result_t 1495dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { 1496 isc_result_t result; 1497 1498 REQUIRE(DNS_VIEW_VALID(view)); 1499 1500 (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name); 1501 result = dns_master_dumptostream(view->mctx, view->cachedb, NULL, 1502 &dns_master_style_cache, fp); 1503 if (result != ISC_R_SUCCESS) 1504 return (result); 1505 dns_adb_dump(view->adb, fp); 1506 dns_resolver_printbadcache(view->resolver, fp); 1507 return (ISC_R_SUCCESS); 1508} 1509#endif 1510 1511isc_result_t 1512dns_view_flushcache(dns_view_t *view) { 1513 return (dns_view_flushcache2(view, ISC_FALSE)); 1514} 1515 1516isc_result_t 1517dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) { 1518 isc_result_t result; 1519 1520 REQUIRE(DNS_VIEW_VALID(view)); 1521 1522 if (view->cachedb == NULL) 1523 return (ISC_R_SUCCESS); 1524 if (!fixuponly) { 1525 result = dns_cache_flush(view->cache); 1526 if (result != ISC_R_SUCCESS) 1527 return (result); 1528 } 1529#ifdef BIND9 1530 if (view->acache != NULL) 1531 dns_acache_putdb(view->acache, view->cachedb); 1532#endif 1533 dns_db_detach(&view->cachedb); 1534 dns_cache_attachdb(view->cache, &view->cachedb); 1535#ifdef BIND9 1536 if (view->acache != NULL) 1537 dns_acache_setdb(view->acache, view->cachedb); 1538 if (view->resolver != NULL) 1539 dns_resolver_flushbadcache(view->resolver, NULL); 1540#endif 1541 1542 dns_adb_flush(view->adb); 1543 return (ISC_R_SUCCESS); 1544} 1545 1546isc_result_t 1547dns_view_flushname(dns_view_t *view, dns_name_t *name) { 1548 return (dns_view_flushnode(view, name, ISC_FALSE)); 1549} 1550 1551isc_result_t 1552dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) { 1553 1554 REQUIRE(DNS_VIEW_VALID(view)); 1555 1556 if (!tree) { 1557 if (view->adb != NULL) 1558 dns_adb_flushname(view->adb, name); 1559 if (view->cache == NULL) 1560 return (ISC_R_SUCCESS); 1561 if (view->resolver != NULL) 1562 dns_resolver_flushbadcache(view->resolver, name); 1563 } 1564 return (dns_cache_flushnode(view->cache, name, tree)); 1565} 1566 1567isc_result_t 1568dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) { 1569 isc_result_t result; 1570 dns_name_t *new; 1571 isc_uint32_t hash; 1572 1573 REQUIRE(DNS_VIEW_VALID(view)); 1574 1575 if (view->delonly == NULL) { 1576 view->delonly = isc_mem_get(view->mctx, 1577 sizeof(dns_namelist_t) * 1578 DNS_VIEW_DELONLYHASH); 1579 if (view->delonly == NULL) 1580 return (ISC_R_NOMEMORY); 1581 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) 1582 ISC_LIST_INIT(view->delonly[hash]); 1583 } 1584 hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1585 new = ISC_LIST_HEAD(view->delonly[hash]); 1586 while (new != NULL && !dns_name_equal(new, name)) 1587 new = ISC_LIST_NEXT(new, link); 1588 if (new != NULL) 1589 return (ISC_R_SUCCESS); 1590 new = isc_mem_get(view->mctx, sizeof(*new)); 1591 if (new == NULL) 1592 return (ISC_R_NOMEMORY); 1593 dns_name_init(new, NULL); 1594 result = dns_name_dup(name, view->mctx, new); 1595 if (result == ISC_R_SUCCESS) 1596 ISC_LIST_APPEND(view->delonly[hash], new, link); 1597 else 1598 isc_mem_put(view->mctx, new, sizeof(*new)); 1599 return (result); 1600} 1601 1602isc_result_t 1603dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) { 1604 isc_result_t result; 1605 dns_name_t *new; 1606 isc_uint32_t hash; 1607 1608 REQUIRE(DNS_VIEW_VALID(view)); 1609 1610 if (view->rootexclude == NULL) { 1611 view->rootexclude = isc_mem_get(view->mctx, 1612 sizeof(dns_namelist_t) * 1613 DNS_VIEW_DELONLYHASH); 1614 if (view->rootexclude == NULL) 1615 return (ISC_R_NOMEMORY); 1616 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) 1617 ISC_LIST_INIT(view->rootexclude[hash]); 1618 } 1619 hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1620 new = ISC_LIST_HEAD(view->rootexclude[hash]); 1621 while (new != NULL && !dns_name_equal(new, name)) 1622 new = ISC_LIST_NEXT(new, link); 1623 if (new != NULL) 1624 return (ISC_R_SUCCESS); 1625 new = isc_mem_get(view->mctx, sizeof(*new)); 1626 if (new == NULL) 1627 return (ISC_R_NOMEMORY); 1628 dns_name_init(new, NULL); 1629 result = dns_name_dup(name, view->mctx, new); 1630 if (result == ISC_R_SUCCESS) 1631 ISC_LIST_APPEND(view->rootexclude[hash], new, link); 1632 else 1633 isc_mem_put(view->mctx, new, sizeof(*new)); 1634 return (result); 1635} 1636 1637isc_boolean_t 1638dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) { 1639 dns_name_t *new; 1640 isc_uint32_t hash; 1641 1642 REQUIRE(DNS_VIEW_VALID(view)); 1643 1644 if (!view->rootdelonly && view->delonly == NULL) 1645 return (ISC_FALSE); 1646 1647 hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1648 if (view->rootdelonly && dns_name_countlabels(name) <= 2) { 1649 if (view->rootexclude == NULL) 1650 return (ISC_TRUE); 1651 new = ISC_LIST_HEAD(view->rootexclude[hash]); 1652 while (new != NULL && !dns_name_equal(new, name)) 1653 new = ISC_LIST_NEXT(new, link); 1654 if (new == NULL) 1655 return (ISC_TRUE); 1656 } 1657 1658 if (view->delonly == NULL) 1659 return (ISC_FALSE); 1660 1661 new = ISC_LIST_HEAD(view->delonly[hash]); 1662 while (new != NULL && !dns_name_equal(new, name)) 1663 new = ISC_LIST_NEXT(new, link); 1664 if (new == NULL) 1665 return (ISC_FALSE); 1666 return (ISC_TRUE); 1667} 1668 1669void 1670dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) { 1671 REQUIRE(DNS_VIEW_VALID(view)); 1672 view->rootdelonly = value; 1673} 1674 1675isc_boolean_t 1676dns_view_getrootdelonly(dns_view_t *view) { 1677 REQUIRE(DNS_VIEW_VALID(view)); 1678 return (view->rootdelonly); 1679} 1680 1681#ifdef BIND9 1682isc_result_t 1683dns_view_freezezones(dns_view_t *view, isc_boolean_t value) { 1684 REQUIRE(DNS_VIEW_VALID(view)); 1685 return (dns_zt_freezezones(view->zonetable, value)); 1686} 1687#endif 1688 1689void 1690dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) { 1691 REQUIRE(DNS_VIEW_VALID(view)); 1692 REQUIRE(!view->frozen); 1693 REQUIRE(view->resstats == NULL); 1694 1695 isc_stats_attach(stats, &view->resstats); 1696} 1697 1698void 1699dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) { 1700 REQUIRE(DNS_VIEW_VALID(view)); 1701 REQUIRE(statsp != NULL && *statsp == NULL); 1702 1703 if (view->resstats != NULL) 1704 isc_stats_attach(view->resstats, statsp); 1705} 1706 1707void 1708dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) { 1709 REQUIRE(DNS_VIEW_VALID(view)); 1710 REQUIRE(!view->frozen); 1711 REQUIRE(view->resquerystats == NULL); 1712 1713 dns_stats_attach(stats, &view->resquerystats); 1714} 1715 1716void 1717dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) { 1718 REQUIRE(DNS_VIEW_VALID(view)); 1719 REQUIRE(statsp != NULL && *statsp == NULL); 1720 1721 if (view->resquerystats != NULL) 1722 dns_stats_attach(view->resquerystats, statsp); 1723} 1724 1725isc_result_t 1726dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) { 1727 REQUIRE(DNS_VIEW_VALID(view)); 1728 if (view->secroots_priv != NULL) 1729 dns_keytable_detach(&view->secroots_priv); 1730 return (dns_keytable_create(mctx, &view->secroots_priv)); 1731} 1732 1733isc_result_t 1734dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) { 1735 REQUIRE(DNS_VIEW_VALID(view)); 1736 REQUIRE(ktp != NULL && *ktp == NULL); 1737 if (view->secroots_priv == NULL) 1738 return (ISC_R_NOTFOUND); 1739 dns_keytable_attach(view->secroots_priv, ktp); 1740 return (ISC_R_SUCCESS); 1741} 1742 1743isc_result_t 1744dns_view_issecuredomain(dns_view_t *view, dns_name_t *name, 1745 isc_boolean_t *secure_domain) { 1746 REQUIRE(DNS_VIEW_VALID(view)); 1747 1748 if (view->secroots_priv == NULL) 1749 return (ISC_R_NOTFOUND); 1750 return (dns_keytable_issecuredomain(view->secroots_priv, name, 1751 secure_domain)); 1752} 1753 1754void 1755dns_view_untrust(dns_view_t *view, dns_name_t *keyname, 1756 dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) 1757{ 1758 isc_result_t result; 1759 unsigned char data[4096]; 1760 dns_rdata_t rdata = DNS_RDATA_INIT; 1761 isc_buffer_t buffer; 1762 dst_key_t *key = NULL; 1763 dns_keytable_t *sr = NULL; 1764 1765 /* 1766 * Clear the revoke bit, if set, so that the key will match what's 1767 * in secroots now. 1768 */ 1769 dnskey->flags &= ~DNS_KEYFLAG_REVOKE; 1770 1771 /* Convert dnskey to DST key. */ 1772 isc_buffer_init(&buffer, data, sizeof(data)); 1773 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass, 1774 dns_rdatatype_dnskey, dnskey, &buffer); 1775 result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key); 1776 if (result != ISC_R_SUCCESS) 1777 return; 1778 result = dns_view_getsecroots(view, &sr); 1779 if (result == ISC_R_SUCCESS) { 1780 dns_keytable_deletekeynode(sr, key); 1781 dns_keytable_detach(&sr); 1782 } 1783 dst_key_free(&key); 1784} 1785 1786#define NZF ".nzf" 1787 1788void 1789dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, 1790 void (*cfg_destroy)(void **)) 1791{ 1792 REQUIRE(DNS_VIEW_VALID(view)); 1793 REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow); 1794 1795#ifdef BIND9 1796 if (view->new_zone_file != NULL) { 1797 isc_mem_free(view->mctx, view->new_zone_file); 1798 view->new_zone_file = NULL; 1799 } 1800 1801 if (view->new_zone_config != NULL) { 1802 view->cfg_destroy(&view->new_zone_config); 1803 view->cfg_destroy = NULL; 1804 } 1805 1806 if (allow) { 1807 char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(NZF)]; 1808 isc_sha256_data((void *)view->name, strlen(view->name), buffer); 1809 /* Truncate the hash at 16 chars; full length is overkill */ 1810 isc_string_printf(buffer + 16, sizeof(NZF), "%s", NZF); 1811 view->new_zone_file = isc_mem_strdup(view->mctx, buffer); 1812 view->new_zone_config = cfgctx; 1813 view->cfg_destroy = cfg_destroy; 1814 } 1815#else 1816 UNUSED(allow); 1817 UNUSED(cfgctx); 1818 UNUSED(cfg_destroy); 1819#endif 1820} 1821