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