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