view.c revision 186462
1135446Strhodes/* 2186462Sdougb * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2003 Internet Software Consortium. 4135446Strhodes * 5174187Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18186462Sdougb/* $Id: view.c,v 1.126.18.16 2008/06/17 23:46:03 tbox Exp $ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24135446Strhodes#include <isc/hash.h> 25135446Strhodes#include <isc/task.h> 26135446Strhodes#include <isc/string.h> /* Required for HP/UX (and others?) */ 27135446Strhodes#include <isc/util.h> 28135446Strhodes 29170222Sdougb#include <dns/acache.h> 30135446Strhodes#include <dns/acl.h> 31135446Strhodes#include <dns/adb.h> 32135446Strhodes#include <dns/cache.h> 33135446Strhodes#include <dns/db.h> 34170222Sdougb#include <dns/dlz.h> 35135446Strhodes#include <dns/events.h> 36135446Strhodes#include <dns/forward.h> 37135446Strhodes#include <dns/keytable.h> 38135446Strhodes#include <dns/master.h> 39135446Strhodes#include <dns/masterdump.h> 40135446Strhodes#include <dns/order.h> 41135446Strhodes#include <dns/peer.h> 42135446Strhodes#include <dns/rdataset.h> 43135446Strhodes#include <dns/request.h> 44135446Strhodes#include <dns/resolver.h> 45135446Strhodes#include <dns/result.h> 46135446Strhodes#include <dns/tsig.h> 47135446Strhodes#include <dns/zone.h> 48135446Strhodes#include <dns/zt.h> 49135446Strhodes 50135446Strhodes#define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0) 51135446Strhodes#define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0) 52135446Strhodes#define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0) 53135446Strhodes 54135446Strhodes#define DNS_VIEW_DELONLYHASH 111 55135446Strhodes 56135446Strhodesstatic void resolver_shutdown(isc_task_t *task, isc_event_t *event); 57135446Strhodesstatic void adb_shutdown(isc_task_t *task, isc_event_t *event); 58135446Strhodesstatic void req_shutdown(isc_task_t *task, isc_event_t *event); 59135446Strhodes 60135446Strhodesisc_result_t 61135446Strhodesdns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, 62135446Strhodes const char *name, dns_view_t **viewp) 63135446Strhodes{ 64135446Strhodes dns_view_t *view; 65135446Strhodes isc_result_t result; 66135446Strhodes 67135446Strhodes /* 68135446Strhodes * Create a view. 69135446Strhodes */ 70135446Strhodes 71135446Strhodes REQUIRE(name != NULL); 72135446Strhodes REQUIRE(viewp != NULL && *viewp == NULL); 73135446Strhodes 74135446Strhodes view = isc_mem_get(mctx, sizeof(*view)); 75135446Strhodes if (view == NULL) 76135446Strhodes return (ISC_R_NOMEMORY); 77135446Strhodes view->name = isc_mem_strdup(mctx, name); 78135446Strhodes if (view->name == NULL) { 79135446Strhodes result = ISC_R_NOMEMORY; 80135446Strhodes goto cleanup_view; 81135446Strhodes } 82135446Strhodes result = isc_mutex_init(&view->lock); 83170222Sdougb if (result != ISC_R_SUCCESS) 84135446Strhodes goto cleanup_name; 85170222Sdougb 86135446Strhodes view->zonetable = NULL; 87135446Strhodes result = dns_zt_create(mctx, rdclass, &view->zonetable); 88135446Strhodes if (result != ISC_R_SUCCESS) { 89135446Strhodes UNEXPECTED_ERROR(__FILE__, __LINE__, 90135446Strhodes "dns_zt_create() failed: %s", 91135446Strhodes isc_result_totext(result)); 92135446Strhodes result = ISC_R_UNEXPECTED; 93135446Strhodes goto cleanup_mutex; 94135446Strhodes } 95135446Strhodes view->secroots = NULL; 96135446Strhodes result = dns_keytable_create(mctx, &view->secroots); 97135446Strhodes if (result != ISC_R_SUCCESS) { 98135446Strhodes UNEXPECTED_ERROR(__FILE__, __LINE__, 99135446Strhodes "dns_keytable_create() failed: %s", 100135446Strhodes isc_result_totext(result)); 101135446Strhodes result = ISC_R_UNEXPECTED; 102135446Strhodes goto cleanup_zt; 103135446Strhodes } 104135446Strhodes view->trustedkeys = NULL; 105135446Strhodes result = dns_keytable_create(mctx, &view->trustedkeys); 106135446Strhodes if (result != ISC_R_SUCCESS) { 107135446Strhodes UNEXPECTED_ERROR(__FILE__, __LINE__, 108135446Strhodes "dns_keytable_create() failed: %s", 109135446Strhodes isc_result_totext(result)); 110135446Strhodes result = ISC_R_UNEXPECTED; 111135446Strhodes goto cleanup_secroots; 112135446Strhodes } 113135446Strhodes view->fwdtable = NULL; 114135446Strhodes result = dns_fwdtable_create(mctx, &view->fwdtable); 115135446Strhodes if (result != ISC_R_SUCCESS) { 116135446Strhodes UNEXPECTED_ERROR(__FILE__, __LINE__, 117135446Strhodes "dns_fwdtable_create() failed: %s", 118135446Strhodes isc_result_totext(result)); 119135446Strhodes result = ISC_R_UNEXPECTED; 120135446Strhodes goto cleanup_trustedkeys; 121135446Strhodes } 122135446Strhodes 123170222Sdougb view->acache = NULL; 124135446Strhodes view->cache = NULL; 125135446Strhodes view->cachedb = NULL; 126170222Sdougb view->dlzdatabase = NULL; 127135446Strhodes view->hints = NULL; 128135446Strhodes view->resolver = NULL; 129135446Strhodes view->adb = NULL; 130135446Strhodes view->requestmgr = NULL; 131135446Strhodes view->mctx = mctx; 132135446Strhodes view->rdclass = rdclass; 133135446Strhodes view->frozen = ISC_FALSE; 134135446Strhodes view->task = NULL; 135170222Sdougb result = isc_refcount_init(&view->references, 1); 136170222Sdougb if (result != ISC_R_SUCCESS) 137170222Sdougb goto cleanup_fwdtable; 138135446Strhodes view->weakrefs = 0; 139135446Strhodes view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN| 140135446Strhodes DNS_VIEWATTR_REQSHUTDOWN); 141135446Strhodes view->statickeys = NULL; 142135446Strhodes view->dynamickeys = NULL; 143135446Strhodes view->matchclients = NULL; 144135446Strhodes view->matchdestinations = NULL; 145135446Strhodes view->matchrecursiveonly = ISC_FALSE; 146135446Strhodes result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys); 147135446Strhodes if (result != ISC_R_SUCCESS) 148170222Sdougb goto cleanup_references; 149135446Strhodes view->peers = NULL; 150135446Strhodes view->order = NULL; 151135446Strhodes view->delonly = NULL; 152135446Strhodes view->rootdelonly = ISC_FALSE; 153135446Strhodes view->rootexclude = NULL; 154135446Strhodes 155135446Strhodes /* 156135446Strhodes * Initialize configuration data with default values. 157135446Strhodes */ 158135446Strhodes view->recursion = ISC_TRUE; 159135446Strhodes view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ 160135446Strhodes view->additionalfromcache = ISC_TRUE; 161135446Strhodes view->additionalfromauth = ISC_TRUE; 162135446Strhodes view->enablednssec = ISC_TRUE; 163170222Sdougb view->enablevalidation = ISC_TRUE; 164170222Sdougb view->acceptexpired = ISC_FALSE; 165135446Strhodes view->minimalresponses = ISC_FALSE; 166135446Strhodes view->transfer_format = dns_one_answer; 167135446Strhodes view->queryacl = NULL; 168135446Strhodes view->recursionacl = NULL; 169135446Strhodes view->sortlist = NULL; 170135446Strhodes view->requestixfr = ISC_TRUE; 171135446Strhodes view->provideixfr = ISC_TRUE; 172135446Strhodes view->maxcachettl = 7 * 24 * 3600; 173135446Strhodes view->maxncachettl = 3 * 3600; 174135446Strhodes view->dstport = 53; 175135446Strhodes view->preferred_glue = 0; 176135446Strhodes view->flush = ISC_FALSE; 177135446Strhodes view->dlv = NULL; 178170222Sdougb view->maxudp = 0; 179135446Strhodes dns_fixedname_init(&view->dlv_fixed); 180135446Strhodes 181135446Strhodes result = dns_order_create(view->mctx, &view->order); 182135446Strhodes if (result != ISC_R_SUCCESS) 183135446Strhodes goto cleanup_dynkeys; 184135446Strhodes 185135446Strhodes result = dns_peerlist_new(view->mctx, &view->peers); 186135446Strhodes if (result != ISC_R_SUCCESS) 187135446Strhodes goto cleanup_order; 188135446Strhodes 189135446Strhodes result = dns_aclenv_init(view->mctx, &view->aclenv); 190135446Strhodes if (result != ISC_R_SUCCESS) 191135446Strhodes goto cleanup_peerlist; 192135446Strhodes 193135446Strhodes ISC_LINK_INIT(view, link); 194135446Strhodes ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL, 195135446Strhodes DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, 196135446Strhodes view, NULL, NULL, NULL); 197135446Strhodes ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL, 198135446Strhodes DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, 199135446Strhodes view, NULL, NULL, NULL); 200135446Strhodes ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL, 201135446Strhodes DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, 202135446Strhodes view, NULL, NULL, NULL); 203135446Strhodes view->magic = DNS_VIEW_MAGIC; 204135446Strhodes 205135446Strhodes *viewp = view; 206135446Strhodes 207135446Strhodes return (ISC_R_SUCCESS); 208135446Strhodes 209135446Strhodes cleanup_peerlist: 210135446Strhodes dns_peerlist_detach(&view->peers); 211135446Strhodes 212135446Strhodes cleanup_order: 213135446Strhodes dns_order_detach(&view->order); 214135446Strhodes 215135446Strhodes cleanup_dynkeys: 216135446Strhodes dns_tsigkeyring_destroy(&view->dynamickeys); 217135446Strhodes 218170222Sdougb cleanup_references: 219170222Sdougb isc_refcount_destroy(&view->references); 220170222Sdougb 221135446Strhodes cleanup_fwdtable: 222135446Strhodes dns_fwdtable_destroy(&view->fwdtable); 223135446Strhodes 224135446Strhodes cleanup_trustedkeys: 225135446Strhodes dns_keytable_detach(&view->trustedkeys); 226135446Strhodes 227135446Strhodes cleanup_secroots: 228135446Strhodes dns_keytable_detach(&view->secroots); 229135446Strhodes 230135446Strhodes cleanup_zt: 231135446Strhodes dns_zt_detach(&view->zonetable); 232135446Strhodes 233135446Strhodes cleanup_mutex: 234135446Strhodes DESTROYLOCK(&view->lock); 235135446Strhodes 236135446Strhodes cleanup_name: 237135446Strhodes isc_mem_free(mctx, view->name); 238135446Strhodes 239135446Strhodes cleanup_view: 240135446Strhodes isc_mem_put(mctx, view, sizeof(*view)); 241135446Strhodes 242135446Strhodes return (result); 243135446Strhodes} 244135446Strhodes 245135446Strhodesstatic inline void 246135446Strhodesdestroy(dns_view_t *view) { 247135446Strhodes REQUIRE(!ISC_LINK_LINKED(view, link)); 248135446Strhodes REQUIRE(isc_refcount_current(&view->references) == 0); 249135446Strhodes REQUIRE(view->weakrefs == 0); 250135446Strhodes REQUIRE(RESSHUTDOWN(view)); 251135446Strhodes REQUIRE(ADBSHUTDOWN(view)); 252135446Strhodes REQUIRE(REQSHUTDOWN(view)); 253135446Strhodes 254135446Strhodes if (view->order != NULL) 255135446Strhodes dns_order_detach(&view->order); 256135446Strhodes if (view->peers != NULL) 257135446Strhodes dns_peerlist_detach(&view->peers); 258135446Strhodes if (view->dynamickeys != NULL) 259135446Strhodes dns_tsigkeyring_destroy(&view->dynamickeys); 260135446Strhodes if (view->statickeys != NULL) 261135446Strhodes dns_tsigkeyring_destroy(&view->statickeys); 262135446Strhodes if (view->adb != NULL) 263135446Strhodes dns_adb_detach(&view->adb); 264135446Strhodes if (view->resolver != NULL) 265135446Strhodes dns_resolver_detach(&view->resolver); 266170222Sdougb if (view->acache != NULL) { 267170222Sdougb if (view->cachedb != NULL) 268170222Sdougb dns_acache_putdb(view->acache, view->cachedb); 269170222Sdougb dns_acache_detach(&view->acache); 270170222Sdougb } 271135446Strhodes if (view->requestmgr != NULL) 272135446Strhodes dns_requestmgr_detach(&view->requestmgr); 273135446Strhodes if (view->task != NULL) 274135446Strhodes isc_task_detach(&view->task); 275135446Strhodes if (view->hints != NULL) 276135446Strhodes dns_db_detach(&view->hints); 277170222Sdougb if (view->dlzdatabase != NULL) 278170222Sdougb dns_dlzdestroy(&view->dlzdatabase); 279135446Strhodes if (view->cachedb != NULL) 280135446Strhodes dns_db_detach(&view->cachedb); 281135446Strhodes if (view->cache != NULL) 282135446Strhodes dns_cache_detach(&view->cache); 283135446Strhodes if (view->matchclients != NULL) 284135446Strhodes dns_acl_detach(&view->matchclients); 285135446Strhodes if (view->matchdestinations != NULL) 286135446Strhodes dns_acl_detach(&view->matchdestinations); 287135446Strhodes if (view->queryacl != NULL) 288135446Strhodes dns_acl_detach(&view->queryacl); 289135446Strhodes if (view->recursionacl != NULL) 290135446Strhodes dns_acl_detach(&view->recursionacl); 291135446Strhodes if (view->sortlist != NULL) 292135446Strhodes dns_acl_detach(&view->sortlist); 293135446Strhodes if (view->delonly != NULL) { 294135446Strhodes dns_name_t *name; 295135446Strhodes int i; 296135446Strhodes 297135446Strhodes for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 298135446Strhodes name = ISC_LIST_HEAD(view->delonly[i]); 299135446Strhodes while (name != NULL) { 300135446Strhodes ISC_LIST_UNLINK(view->delonly[i], name, link); 301135446Strhodes dns_name_free(name, view->mctx); 302135446Strhodes isc_mem_put(view->mctx, name, sizeof(*name)); 303135446Strhodes name = ISC_LIST_HEAD(view->delonly[i]); 304135446Strhodes } 305135446Strhodes } 306135446Strhodes isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) * 307135446Strhodes DNS_VIEW_DELONLYHASH); 308135446Strhodes view->delonly = NULL; 309135446Strhodes } 310135446Strhodes if (view->rootexclude != NULL) { 311135446Strhodes dns_name_t *name; 312135446Strhodes int i; 313135446Strhodes 314135446Strhodes for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 315135446Strhodes name = ISC_LIST_HEAD(view->rootexclude[i]); 316135446Strhodes while (name != NULL) { 317135446Strhodes ISC_LIST_UNLINK(view->rootexclude[i], 318186462Sdougb name, link); 319135446Strhodes dns_name_free(name, view->mctx); 320135446Strhodes isc_mem_put(view->mctx, name, sizeof(*name)); 321135446Strhodes name = ISC_LIST_HEAD(view->rootexclude[i]); 322135446Strhodes } 323135446Strhodes } 324135446Strhodes isc_mem_put(view->mctx, view->rootexclude, 325135446Strhodes sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH); 326135446Strhodes view->rootexclude = NULL; 327135446Strhodes } 328135446Strhodes dns_keytable_detach(&view->trustedkeys); 329135446Strhodes dns_keytable_detach(&view->secroots); 330135446Strhodes dns_fwdtable_destroy(&view->fwdtable); 331135446Strhodes dns_aclenv_destroy(&view->aclenv); 332135446Strhodes DESTROYLOCK(&view->lock); 333135446Strhodes isc_refcount_destroy(&view->references); 334135446Strhodes isc_mem_free(view->mctx, view->name); 335135446Strhodes isc_mem_put(view->mctx, view, sizeof(*view)); 336135446Strhodes} 337135446Strhodes 338135446Strhodes/* 339135446Strhodes * Return true iff 'view' may be freed. 340135446Strhodes * The caller must be holding the view lock. 341135446Strhodes */ 342135446Strhodesstatic isc_boolean_t 343135446Strhodesall_done(dns_view_t *view) { 344135446Strhodes 345135446Strhodes if (isc_refcount_current(&view->references) == 0 && 346135446Strhodes view->weakrefs == 0 && 347135446Strhodes RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view)) 348135446Strhodes return (ISC_TRUE); 349135446Strhodes 350135446Strhodes return (ISC_FALSE); 351135446Strhodes} 352135446Strhodes 353135446Strhodesvoid 354135446Strhodesdns_view_attach(dns_view_t *source, dns_view_t **targetp) { 355135446Strhodes 356135446Strhodes REQUIRE(DNS_VIEW_VALID(source)); 357135446Strhodes REQUIRE(targetp != NULL && *targetp == NULL); 358135446Strhodes 359135446Strhodes isc_refcount_increment(&source->references, NULL); 360135446Strhodes 361135446Strhodes *targetp = source; 362135446Strhodes} 363135446Strhodes 364135446Strhodesstatic void 365135446Strhodesview_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { 366135446Strhodes dns_view_t *view; 367135446Strhodes unsigned int refs; 368135446Strhodes isc_boolean_t done = ISC_FALSE; 369135446Strhodes 370135446Strhodes REQUIRE(viewp != NULL); 371135446Strhodes view = *viewp; 372135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 373135446Strhodes 374135446Strhodes if (flush) 375135446Strhodes view->flush = ISC_TRUE; 376135446Strhodes isc_refcount_decrement(&view->references, &refs); 377135446Strhodes if (refs == 0) { 378135446Strhodes LOCK(&view->lock); 379135446Strhodes if (!RESSHUTDOWN(view)) 380135446Strhodes dns_resolver_shutdown(view->resolver); 381135446Strhodes if (!ADBSHUTDOWN(view)) 382135446Strhodes dns_adb_shutdown(view->adb); 383135446Strhodes if (!REQSHUTDOWN(view)) 384135446Strhodes dns_requestmgr_shutdown(view->requestmgr); 385170222Sdougb if (view->acache != NULL) 386170222Sdougb dns_acache_shutdown(view->acache); 387135446Strhodes if (view->flush) 388135446Strhodes dns_zt_flushanddetach(&view->zonetable); 389135446Strhodes else 390135446Strhodes dns_zt_detach(&view->zonetable); 391135446Strhodes done = all_done(view); 392135446Strhodes UNLOCK(&view->lock); 393135446Strhodes } 394135446Strhodes 395135446Strhodes *viewp = NULL; 396135446Strhodes 397135446Strhodes if (done) 398135446Strhodes destroy(view); 399135446Strhodes} 400135446Strhodes 401135446Strhodesvoid 402135446Strhodesdns_view_flushanddetach(dns_view_t **viewp) { 403135446Strhodes view_flushanddetach(viewp, ISC_TRUE); 404135446Strhodes} 405135446Strhodes 406135446Strhodesvoid 407135446Strhodesdns_view_detach(dns_view_t **viewp) { 408135446Strhodes view_flushanddetach(viewp, ISC_FALSE); 409135446Strhodes} 410135446Strhodes 411135446Strhodesstatic isc_result_t 412135446Strhodesdialup(dns_zone_t *zone, void *dummy) { 413135446Strhodes UNUSED(dummy); 414135446Strhodes dns_zone_dialup(zone); 415135446Strhodes return (ISC_R_SUCCESS); 416135446Strhodes} 417135446Strhodes 418135446Strhodesvoid 419135446Strhodesdns_view_dialup(dns_view_t *view) { 420135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 421135446Strhodes (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL); 422135446Strhodes} 423135446Strhodes 424135446Strhodesvoid 425135446Strhodesdns_view_weakattach(dns_view_t *source, dns_view_t **targetp) { 426135446Strhodes 427135446Strhodes REQUIRE(DNS_VIEW_VALID(source)); 428135446Strhodes REQUIRE(targetp != NULL && *targetp == NULL); 429135446Strhodes 430135446Strhodes LOCK(&source->lock); 431135446Strhodes source->weakrefs++; 432135446Strhodes UNLOCK(&source->lock); 433135446Strhodes 434135446Strhodes *targetp = source; 435135446Strhodes} 436135446Strhodes 437135446Strhodesvoid 438135446Strhodesdns_view_weakdetach(dns_view_t **viewp) { 439135446Strhodes dns_view_t *view; 440135446Strhodes isc_boolean_t done = ISC_FALSE; 441135446Strhodes 442135446Strhodes REQUIRE(viewp != NULL); 443135446Strhodes view = *viewp; 444135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 445135446Strhodes 446135446Strhodes LOCK(&view->lock); 447135446Strhodes 448135446Strhodes INSIST(view->weakrefs > 0); 449135446Strhodes view->weakrefs--; 450135446Strhodes done = all_done(view); 451135446Strhodes 452135446Strhodes UNLOCK(&view->lock); 453135446Strhodes 454135446Strhodes *viewp = NULL; 455135446Strhodes 456135446Strhodes if (done) 457135446Strhodes destroy(view); 458135446Strhodes} 459135446Strhodes 460135446Strhodesstatic void 461135446Strhodesresolver_shutdown(isc_task_t *task, isc_event_t *event) { 462135446Strhodes dns_view_t *view = event->ev_arg; 463135446Strhodes isc_boolean_t done; 464135446Strhodes 465135446Strhodes REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN); 466135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 467135446Strhodes REQUIRE(view->task == task); 468135446Strhodes 469135446Strhodes UNUSED(task); 470135446Strhodes 471135446Strhodes LOCK(&view->lock); 472135446Strhodes 473135446Strhodes view->attributes |= DNS_VIEWATTR_RESSHUTDOWN; 474135446Strhodes done = all_done(view); 475135446Strhodes 476135446Strhodes UNLOCK(&view->lock); 477135446Strhodes 478135446Strhodes isc_event_free(&event); 479135446Strhodes 480135446Strhodes if (done) 481135446Strhodes destroy(view); 482135446Strhodes} 483135446Strhodes 484135446Strhodesstatic void 485135446Strhodesadb_shutdown(isc_task_t *task, isc_event_t *event) { 486135446Strhodes dns_view_t *view = event->ev_arg; 487135446Strhodes isc_boolean_t done; 488135446Strhodes 489135446Strhodes REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN); 490135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 491135446Strhodes REQUIRE(view->task == task); 492135446Strhodes 493135446Strhodes UNUSED(task); 494135446Strhodes 495135446Strhodes LOCK(&view->lock); 496135446Strhodes 497135446Strhodes view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN; 498135446Strhodes done = all_done(view); 499135446Strhodes 500135446Strhodes UNLOCK(&view->lock); 501135446Strhodes 502135446Strhodes isc_event_free(&event); 503135446Strhodes 504135446Strhodes if (done) 505135446Strhodes destroy(view); 506135446Strhodes} 507135446Strhodes 508135446Strhodesstatic void 509135446Strhodesreq_shutdown(isc_task_t *task, isc_event_t *event) { 510135446Strhodes dns_view_t *view = event->ev_arg; 511135446Strhodes isc_boolean_t done; 512135446Strhodes 513135446Strhodes REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN); 514135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 515135446Strhodes REQUIRE(view->task == task); 516135446Strhodes 517135446Strhodes UNUSED(task); 518135446Strhodes 519135446Strhodes LOCK(&view->lock); 520135446Strhodes 521135446Strhodes view->attributes |= DNS_VIEWATTR_REQSHUTDOWN; 522135446Strhodes done = all_done(view); 523135446Strhodes 524135446Strhodes UNLOCK(&view->lock); 525135446Strhodes 526135446Strhodes isc_event_free(&event); 527135446Strhodes 528135446Strhodes if (done) 529135446Strhodes destroy(view); 530135446Strhodes} 531135446Strhodes 532135446Strhodesisc_result_t 533135446Strhodesdns_view_createresolver(dns_view_t *view, 534135446Strhodes isc_taskmgr_t *taskmgr, unsigned int ntasks, 535135446Strhodes isc_socketmgr_t *socketmgr, 536135446Strhodes isc_timermgr_t *timermgr, 537135446Strhodes unsigned int options, 538135446Strhodes dns_dispatchmgr_t *dispatchmgr, 539135446Strhodes dns_dispatch_t *dispatchv4, 540135446Strhodes dns_dispatch_t *dispatchv6) 541135446Strhodes{ 542135446Strhodes isc_result_t result; 543135446Strhodes isc_event_t *event; 544135446Strhodes isc_mem_t *mctx = NULL; 545135446Strhodes 546135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 547135446Strhodes REQUIRE(!view->frozen); 548135446Strhodes REQUIRE(view->resolver == NULL); 549135446Strhodes 550135446Strhodes result = isc_task_create(taskmgr, 0, &view->task); 551135446Strhodes if (result != ISC_R_SUCCESS) 552135446Strhodes return (result); 553135446Strhodes isc_task_setname(view->task, "view", view); 554135446Strhodes 555135446Strhodes result = dns_resolver_create(view, taskmgr, ntasks, socketmgr, 556135446Strhodes timermgr, options, dispatchmgr, 557135446Strhodes dispatchv4, dispatchv6, 558135446Strhodes &view->resolver); 559135446Strhodes if (result != ISC_R_SUCCESS) { 560135446Strhodes isc_task_detach(&view->task); 561135446Strhodes return (result); 562135446Strhodes } 563135446Strhodes event = &view->resevent; 564135446Strhodes dns_resolver_whenshutdown(view->resolver, view->task, &event); 565135446Strhodes view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN; 566135446Strhodes 567135446Strhodes result = isc_mem_create(0, 0, &mctx); 568135446Strhodes if (result != ISC_R_SUCCESS) { 569135446Strhodes dns_resolver_shutdown(view->resolver); 570135446Strhodes return (result); 571135446Strhodes } 572135446Strhodes 573135446Strhodes result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb); 574135446Strhodes isc_mem_detach(&mctx); 575135446Strhodes if (result != ISC_R_SUCCESS) { 576135446Strhodes dns_resolver_shutdown(view->resolver); 577135446Strhodes return (result); 578135446Strhodes } 579135446Strhodes event = &view->adbevent; 580135446Strhodes dns_adb_whenshutdown(view->adb, view->task, &event); 581135446Strhodes view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN; 582135446Strhodes 583135446Strhodes result = dns_requestmgr_create(view->mctx, timermgr, socketmgr, 584135446Strhodes dns_resolver_taskmgr(view->resolver), 585135446Strhodes dns_resolver_dispatchmgr(view->resolver), 586135446Strhodes dns_resolver_dispatchv4(view->resolver), 587135446Strhodes dns_resolver_dispatchv6(view->resolver), 588135446Strhodes &view->requestmgr); 589135446Strhodes if (result != ISC_R_SUCCESS) { 590135446Strhodes dns_adb_shutdown(view->adb); 591135446Strhodes dns_resolver_shutdown(view->resolver); 592135446Strhodes return (result); 593135446Strhodes } 594135446Strhodes event = &view->reqevent; 595135446Strhodes dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event); 596135446Strhodes view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN; 597135446Strhodes 598135446Strhodes return (ISC_R_SUCCESS); 599135446Strhodes} 600135446Strhodes 601135446Strhodesvoid 602135446Strhodesdns_view_setcache(dns_view_t *view, dns_cache_t *cache) { 603135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 604135446Strhodes REQUIRE(!view->frozen); 605135446Strhodes 606135446Strhodes if (view->cache != NULL) { 607170222Sdougb if (view->acache != NULL) 608170222Sdougb dns_acache_putdb(view->acache, view->cachedb); 609135446Strhodes dns_db_detach(&view->cachedb); 610135446Strhodes dns_cache_detach(&view->cache); 611135446Strhodes } 612135446Strhodes dns_cache_attach(cache, &view->cache); 613135446Strhodes dns_cache_attachdb(cache, &view->cachedb); 614135446Strhodes INSIST(DNS_DB_VALID(view->cachedb)); 615170222Sdougb 616170222Sdougb if (view->acache != NULL) 617170222Sdougb dns_acache_setdb(view->acache, view->cachedb); 618135446Strhodes} 619135446Strhodes 620135446Strhodesvoid 621135446Strhodesdns_view_sethints(dns_view_t *view, dns_db_t *hints) { 622135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 623135446Strhodes REQUIRE(!view->frozen); 624135446Strhodes REQUIRE(view->hints == NULL); 625135446Strhodes REQUIRE(dns_db_iszone(hints)); 626135446Strhodes 627135446Strhodes dns_db_attach(hints, &view->hints); 628135446Strhodes} 629135446Strhodes 630135446Strhodesvoid 631135446Strhodesdns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { 632135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 633135446Strhodes REQUIRE(ring != NULL); 634135446Strhodes if (view->statickeys != NULL) 635135446Strhodes dns_tsigkeyring_destroy(&view->statickeys); 636135446Strhodes view->statickeys = ring; 637135446Strhodes} 638135446Strhodes 639135446Strhodesvoid 640135446Strhodesdns_view_setdstport(dns_view_t *view, in_port_t dstport) { 641135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 642135446Strhodes view->dstport = dstport; 643135446Strhodes} 644135446Strhodes 645135446Strhodesisc_result_t 646135446Strhodesdns_view_addzone(dns_view_t *view, dns_zone_t *zone) { 647135446Strhodes isc_result_t result; 648135446Strhodes 649135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 650135446Strhodes REQUIRE(!view->frozen); 651135446Strhodes 652135446Strhodes result = dns_zt_mount(view->zonetable, zone); 653135446Strhodes 654135446Strhodes return (result); 655135446Strhodes} 656135446Strhodes 657135446Strhodesvoid 658135446Strhodesdns_view_freeze(dns_view_t *view) { 659135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 660135446Strhodes REQUIRE(!view->frozen); 661135446Strhodes 662135446Strhodes if (view->resolver != NULL) { 663135446Strhodes INSIST(view->cachedb != NULL); 664135446Strhodes dns_resolver_freeze(view->resolver); 665135446Strhodes } 666135446Strhodes view->frozen = ISC_TRUE; 667135446Strhodes} 668135446Strhodes 669135446Strhodesisc_result_t 670135446Strhodesdns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) { 671135446Strhodes isc_result_t result; 672135446Strhodes 673135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 674135446Strhodes 675135446Strhodes result = dns_zt_find(view->zonetable, name, 0, NULL, zonep); 676135446Strhodes if (result == DNS_R_PARTIALMATCH) { 677135446Strhodes dns_zone_detach(zonep); 678135446Strhodes result = ISC_R_NOTFOUND; 679135446Strhodes } 680135446Strhodes 681135446Strhodes return (result); 682135446Strhodes} 683135446Strhodes 684135446Strhodesisc_result_t 685135446Strhodesdns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 686135446Strhodes isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints, 687135446Strhodes dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, 688135446Strhodes dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 689135446Strhodes{ 690135446Strhodes isc_result_t result; 691135446Strhodes dns_db_t *db, *zdb; 692135446Strhodes dns_dbnode_t *node, *znode; 693135446Strhodes isc_boolean_t is_cache; 694135446Strhodes dns_rdataset_t zrdataset, zsigrdataset; 695135446Strhodes dns_zone_t *zone; 696135446Strhodes 697135446Strhodes /* 698135446Strhodes * Find an rdataset whose owner name is 'name', and whose type is 699135446Strhodes * 'type'. 700135446Strhodes */ 701135446Strhodes 702135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 703135446Strhodes REQUIRE(view->frozen); 704135446Strhodes REQUIRE(type != dns_rdatatype_rrsig); 705135446Strhodes REQUIRE(rdataset != NULL); /* XXXBEW - remove this */ 706174187Sdougb REQUIRE(nodep == NULL || *nodep == NULL); 707135446Strhodes 708135446Strhodes /* 709135446Strhodes * Initialize. 710135446Strhodes */ 711135446Strhodes dns_rdataset_init(&zrdataset); 712135446Strhodes dns_rdataset_init(&zsigrdataset); 713135446Strhodes zdb = NULL; 714135446Strhodes znode = NULL; 715135446Strhodes 716135446Strhodes /* 717135446Strhodes * Find a database to answer the query. 718135446Strhodes */ 719135446Strhodes zone = NULL; 720135446Strhodes db = NULL; 721135446Strhodes node = NULL; 722135446Strhodes result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 723135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 724135446Strhodes result = dns_zone_getdb(zone, &db); 725135446Strhodes if (result != ISC_R_SUCCESS && view->cachedb != NULL) 726135446Strhodes dns_db_attach(view->cachedb, &db); 727135446Strhodes else if (result != ISC_R_SUCCESS) 728135446Strhodes goto cleanup; 729135446Strhodes } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) 730135446Strhodes dns_db_attach(view->cachedb, &db); 731135446Strhodes else 732135446Strhodes goto cleanup; 733135446Strhodes 734135446Strhodes is_cache = dns_db_iscache(db); 735135446Strhodes 736135446Strhodes db_find: 737135446Strhodes /* 738135446Strhodes * Now look for an answer in the database. 739135446Strhodes */ 740135446Strhodes result = dns_db_find(db, name, NULL, type, options, 741135446Strhodes now, &node, foundname, rdataset, sigrdataset); 742135446Strhodes 743135446Strhodes if (result == DNS_R_DELEGATION || 744135446Strhodes result == ISC_R_NOTFOUND) { 745135446Strhodes if (dns_rdataset_isassociated(rdataset)) 746135446Strhodes dns_rdataset_disassociate(rdataset); 747135446Strhodes if (sigrdataset != NULL && 748135446Strhodes dns_rdataset_isassociated(sigrdataset)) 749135446Strhodes dns_rdataset_disassociate(sigrdataset); 750135446Strhodes if (node != NULL) 751135446Strhodes dns_db_detachnode(db, &node); 752135446Strhodes if (!is_cache) { 753135446Strhodes dns_db_detach(&db); 754135446Strhodes if (view->cachedb != NULL) { 755135446Strhodes /* 756135446Strhodes * Either the answer is in the cache, or we 757135446Strhodes * don't know it. 758135446Strhodes */ 759135446Strhodes is_cache = ISC_TRUE; 760135446Strhodes dns_db_attach(view->cachedb, &db); 761135446Strhodes goto db_find; 762135446Strhodes } 763135446Strhodes } else { 764135446Strhodes /* 765135446Strhodes * We don't have the data in the cache. If we've got 766135446Strhodes * glue from the zone, use it. 767135446Strhodes */ 768135446Strhodes if (dns_rdataset_isassociated(&zrdataset)) { 769135446Strhodes dns_rdataset_clone(&zrdataset, rdataset); 770135446Strhodes if (sigrdataset != NULL && 771135446Strhodes dns_rdataset_isassociated(&zsigrdataset)) 772135446Strhodes dns_rdataset_clone(&zsigrdataset, 773135446Strhodes sigrdataset); 774135446Strhodes result = DNS_R_GLUE; 775135446Strhodes if (db != NULL) 776135446Strhodes dns_db_detach(&db); 777135446Strhodes dns_db_attach(zdb, &db); 778135446Strhodes dns_db_attachnode(db, znode, &node); 779135446Strhodes goto cleanup; 780135446Strhodes } 781135446Strhodes } 782135446Strhodes /* 783135446Strhodes * We don't know the answer. 784135446Strhodes */ 785135446Strhodes result = ISC_R_NOTFOUND; 786135446Strhodes } else if (result == DNS_R_GLUE) { 787135446Strhodes if (view->cachedb != NULL) { 788135446Strhodes /* 789135446Strhodes * We found an answer, but the cache may be better. 790135446Strhodes * Remember what we've got and go look in the cache. 791135446Strhodes */ 792135446Strhodes is_cache = ISC_TRUE; 793135446Strhodes dns_rdataset_clone(rdataset, &zrdataset); 794135446Strhodes dns_rdataset_disassociate(rdataset); 795135446Strhodes if (sigrdataset != NULL && 796135446Strhodes dns_rdataset_isassociated(sigrdataset)) { 797135446Strhodes dns_rdataset_clone(sigrdataset, &zsigrdataset); 798135446Strhodes dns_rdataset_disassociate(sigrdataset); 799135446Strhodes } 800135446Strhodes dns_db_attach(db, &zdb); 801135446Strhodes dns_db_attachnode(zdb, node, &znode); 802135446Strhodes dns_db_detachnode(db, &node); 803135446Strhodes dns_db_detach(&db); 804135446Strhodes dns_db_attach(view->cachedb, &db); 805135446Strhodes goto db_find; 806135446Strhodes } 807135446Strhodes /* 808135446Strhodes * Otherwise, the glue is the best answer. 809135446Strhodes */ 810135446Strhodes result = ISC_R_SUCCESS; 811135446Strhodes } 812135446Strhodes 813135446Strhodes if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) { 814135446Strhodes if (dns_rdataset_isassociated(rdataset)) 815135446Strhodes dns_rdataset_disassociate(rdataset); 816135446Strhodes if (sigrdataset != NULL && 817135446Strhodes dns_rdataset_isassociated(sigrdataset)) 818135446Strhodes dns_rdataset_disassociate(sigrdataset); 819135446Strhodes if (db != NULL) { 820135446Strhodes if (node != NULL) 821135446Strhodes dns_db_detachnode(db, &node); 822135446Strhodes dns_db_detach(&db); 823135446Strhodes } 824135446Strhodes result = dns_db_find(view->hints, name, NULL, type, options, 825135446Strhodes now, &node, foundname, 826135446Strhodes rdataset, sigrdataset); 827135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) { 828135446Strhodes /* 829135446Strhodes * We just used a hint. Let the resolver know it 830135446Strhodes * should consider priming. 831135446Strhodes */ 832135446Strhodes dns_resolver_prime(view->resolver); 833135446Strhodes dns_db_attach(view->hints, &db); 834135446Strhodes result = DNS_R_HINT; 835135446Strhodes } else if (result == DNS_R_NXRRSET) { 836135446Strhodes dns_db_attach(view->hints, &db); 837135446Strhodes result = DNS_R_HINTNXRRSET; 838135446Strhodes } else if (result == DNS_R_NXDOMAIN) 839135446Strhodes result = ISC_R_NOTFOUND; 840135446Strhodes 841135446Strhodes /* 842135446Strhodes * Cleanup if non-standard hints are used. 843135446Strhodes */ 844135446Strhodes if (db == NULL && node != NULL) 845135446Strhodes dns_db_detachnode(view->hints, &node); 846135446Strhodes } 847135446Strhodes 848135446Strhodes cleanup: 849135446Strhodes if (dns_rdataset_isassociated(&zrdataset)) { 850135446Strhodes dns_rdataset_disassociate(&zrdataset); 851135446Strhodes if (dns_rdataset_isassociated(&zsigrdataset)) 852135446Strhodes dns_rdataset_disassociate(&zsigrdataset); 853135446Strhodes } 854135446Strhodes 855135446Strhodes if (zdb != NULL) { 856135446Strhodes if (znode != NULL) 857135446Strhodes dns_db_detachnode(zdb, &znode); 858135446Strhodes dns_db_detach(&zdb); 859135446Strhodes } 860135446Strhodes 861135446Strhodes if (db != NULL) { 862135446Strhodes if (node != NULL) { 863135446Strhodes if (nodep != NULL) 864135446Strhodes *nodep = node; 865135446Strhodes else 866135446Strhodes dns_db_detachnode(db, &node); 867135446Strhodes } 868135446Strhodes if (dbp != NULL) 869135446Strhodes *dbp = db; 870135446Strhodes else 871135446Strhodes dns_db_detach(&db); 872135446Strhodes } else 873135446Strhodes INSIST(node == NULL); 874135446Strhodes 875135446Strhodes if (zone != NULL) 876135446Strhodes dns_zone_detach(&zone); 877135446Strhodes 878135446Strhodes return (result); 879135446Strhodes} 880135446Strhodes 881135446Strhodesisc_result_t 882135446Strhodesdns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 883135446Strhodes isc_stdtime_t now, unsigned int options, 884135446Strhodes isc_boolean_t use_hints, 885135446Strhodes dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 886135446Strhodes{ 887135446Strhodes isc_result_t result; 888135446Strhodes dns_fixedname_t foundname; 889135446Strhodes 890135446Strhodes dns_fixedname_init(&foundname); 891135446Strhodes result = dns_view_find(view, name, type, now, options, use_hints, 892135446Strhodes NULL, NULL, dns_fixedname_name(&foundname), 893135446Strhodes rdataset, sigrdataset); 894135446Strhodes if (result == DNS_R_NXDOMAIN) { 895135446Strhodes /* 896135446Strhodes * The rdataset and sigrdataset of the relevant NSEC record 897135446Strhodes * may be returned, but the caller cannot use them because 898135446Strhodes * foundname is not returned by this simplified API. We 899135446Strhodes * disassociate them here to prevent any misuse by the caller. 900135446Strhodes */ 901135446Strhodes if (dns_rdataset_isassociated(rdataset)) 902135446Strhodes dns_rdataset_disassociate(rdataset); 903135446Strhodes if (sigrdataset != NULL && 904135446Strhodes dns_rdataset_isassociated(sigrdataset)) 905135446Strhodes dns_rdataset_disassociate(sigrdataset); 906135446Strhodes } else if (result != ISC_R_SUCCESS && 907135446Strhodes result != DNS_R_GLUE && 908135446Strhodes result != DNS_R_HINT && 909135446Strhodes result != DNS_R_NCACHENXDOMAIN && 910135446Strhodes result != DNS_R_NCACHENXRRSET && 911135446Strhodes result != DNS_R_NXRRSET && 912135446Strhodes result != DNS_R_HINTNXRRSET && 913135446Strhodes result != ISC_R_NOTFOUND) { 914135446Strhodes if (dns_rdataset_isassociated(rdataset)) 915135446Strhodes dns_rdataset_disassociate(rdataset); 916135446Strhodes if (sigrdataset != NULL && 917135446Strhodes dns_rdataset_isassociated(sigrdataset)) 918135446Strhodes dns_rdataset_disassociate(sigrdataset); 919135446Strhodes result = ISC_R_NOTFOUND; 920135446Strhodes } 921135446Strhodes 922135446Strhodes return (result); 923135446Strhodes} 924135446Strhodes 925135446Strhodesisc_result_t 926135446Strhodesdns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname, 927135446Strhodes isc_stdtime_t now, unsigned int options, 928186462Sdougb isc_boolean_t use_hints, 929135446Strhodes dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 930135446Strhodes{ 931135446Strhodes return(dns_view_findzonecut2(view, name, fname, now, options, 932135446Strhodes use_hints, ISC_TRUE, 933135446Strhodes rdataset, sigrdataset)); 934135446Strhodes} 935135446Strhodes 936135446Strhodesisc_result_t 937135446Strhodesdns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, 938135446Strhodes isc_stdtime_t now, unsigned int options, 939135446Strhodes isc_boolean_t use_hints, isc_boolean_t use_cache, 940135446Strhodes dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 941135446Strhodes{ 942135446Strhodes isc_result_t result; 943135446Strhodes dns_db_t *db; 944135446Strhodes isc_boolean_t is_cache, use_zone, try_hints; 945135446Strhodes dns_zone_t *zone; 946135446Strhodes dns_name_t *zfname; 947135446Strhodes dns_rdataset_t zrdataset, zsigrdataset; 948135446Strhodes dns_fixedname_t zfixedname; 949135446Strhodes 950135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 951135446Strhodes REQUIRE(view->frozen); 952135446Strhodes 953135446Strhodes db = NULL; 954135446Strhodes zone = NULL; 955135446Strhodes use_zone = ISC_FALSE; 956135446Strhodes try_hints = ISC_FALSE; 957135446Strhodes zfname = NULL; 958135446Strhodes 959135446Strhodes /* 960135446Strhodes * Initialize. 961135446Strhodes */ 962135446Strhodes dns_fixedname_init(&zfixedname); 963135446Strhodes dns_rdataset_init(&zrdataset); 964135446Strhodes dns_rdataset_init(&zsigrdataset); 965135446Strhodes 966135446Strhodes /* 967135446Strhodes * Find the right database. 968135446Strhodes */ 969135446Strhodes result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 970135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) 971135446Strhodes result = dns_zone_getdb(zone, &db); 972135446Strhodes if (result == ISC_R_NOTFOUND) { 973135446Strhodes /* 974135446Strhodes * We're not directly authoritative for this query name, nor 975135446Strhodes * is it a subdomain of any zone for which we're 976135446Strhodes * authoritative. 977135446Strhodes */ 978135446Strhodes if (use_cache && view->cachedb != NULL) { 979135446Strhodes /* 980135446Strhodes * We have a cache; try it. 981135446Strhodes */ 982135446Strhodes dns_db_attach(view->cachedb, &db); 983135446Strhodes } else { 984135446Strhodes /* 985135446Strhodes * Maybe we have hints... 986135446Strhodes */ 987135446Strhodes try_hints = ISC_TRUE; 988135446Strhodes goto finish; 989135446Strhodes } 990135446Strhodes } else if (result != ISC_R_SUCCESS) { 991135446Strhodes /* 992135446Strhodes * Something is broken. 993135446Strhodes */ 994135446Strhodes goto cleanup; 995135446Strhodes } 996135446Strhodes is_cache = dns_db_iscache(db); 997135446Strhodes 998135446Strhodes db_find: 999135446Strhodes /* 1000135446Strhodes * Look for the zonecut. 1001135446Strhodes */ 1002135446Strhodes if (!is_cache) { 1003135446Strhodes result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options, 1004135446Strhodes now, NULL, fname, rdataset, sigrdataset); 1005135446Strhodes if (result == DNS_R_DELEGATION) 1006135446Strhodes result = ISC_R_SUCCESS; 1007135446Strhodes else if (result != ISC_R_SUCCESS) 1008135446Strhodes goto cleanup; 1009135446Strhodes if (use_cache && view->cachedb != NULL && db != view->hints) { 1010135446Strhodes /* 1011135446Strhodes * We found an answer, but the cache may be better. 1012135446Strhodes */ 1013135446Strhodes zfname = dns_fixedname_name(&zfixedname); 1014135446Strhodes result = dns_name_copy(fname, zfname, NULL); 1015135446Strhodes if (result != ISC_R_SUCCESS) 1016135446Strhodes goto cleanup; 1017135446Strhodes dns_rdataset_clone(rdataset, &zrdataset); 1018135446Strhodes dns_rdataset_disassociate(rdataset); 1019135446Strhodes if (sigrdataset != NULL && 1020135446Strhodes dns_rdataset_isassociated(sigrdataset)) { 1021135446Strhodes dns_rdataset_clone(sigrdataset, &zsigrdataset); 1022135446Strhodes dns_rdataset_disassociate(sigrdataset); 1023135446Strhodes } 1024135446Strhodes dns_db_detach(&db); 1025135446Strhodes dns_db_attach(view->cachedb, &db); 1026135446Strhodes is_cache = ISC_TRUE; 1027135446Strhodes goto db_find; 1028135446Strhodes } 1029135446Strhodes } else { 1030135446Strhodes result = dns_db_findzonecut(db, name, options, now, NULL, 1031135446Strhodes fname, rdataset, sigrdataset); 1032135446Strhodes if (result == ISC_R_SUCCESS) { 1033135446Strhodes if (zfname != NULL && 1034135446Strhodes !dns_name_issubdomain(fname, zfname)) { 1035135446Strhodes /* 1036135446Strhodes * We found a zonecut in the cache, but our 1037135446Strhodes * zone delegation is better. 1038135446Strhodes */ 1039135446Strhodes use_zone = ISC_TRUE; 1040135446Strhodes } 1041135446Strhodes } else if (result == ISC_R_NOTFOUND) { 1042135446Strhodes if (zfname != NULL) { 1043135446Strhodes /* 1044135446Strhodes * We didn't find anything in the cache, but we 1045135446Strhodes * have a zone delegation, so use it. 1046135446Strhodes */ 1047135446Strhodes use_zone = ISC_TRUE; 1048135446Strhodes } else { 1049135446Strhodes /* 1050135446Strhodes * Maybe we have hints... 1051135446Strhodes */ 1052135446Strhodes try_hints = ISC_TRUE; 1053135446Strhodes } 1054135446Strhodes } else { 1055135446Strhodes /* 1056135446Strhodes * Something bad happened. 1057135446Strhodes */ 1058135446Strhodes goto cleanup; 1059135446Strhodes } 1060135446Strhodes } 1061135446Strhodes 1062135446Strhodes finish: 1063135446Strhodes if (use_zone) { 1064135446Strhodes if (dns_rdataset_isassociated(rdataset)) { 1065135446Strhodes dns_rdataset_disassociate(rdataset); 1066135446Strhodes if (sigrdataset != NULL && 1067135446Strhodes dns_rdataset_isassociated(sigrdataset)) 1068135446Strhodes dns_rdataset_disassociate(sigrdataset); 1069135446Strhodes } 1070135446Strhodes result = dns_name_copy(zfname, fname, NULL); 1071135446Strhodes if (result != ISC_R_SUCCESS) 1072135446Strhodes goto cleanup; 1073135446Strhodes dns_rdataset_clone(&zrdataset, rdataset); 1074135446Strhodes if (sigrdataset != NULL && 1075135446Strhodes dns_rdataset_isassociated(&zrdataset)) 1076135446Strhodes dns_rdataset_clone(&zsigrdataset, sigrdataset); 1077135446Strhodes } else if (try_hints && use_hints && view->hints != NULL) { 1078135446Strhodes /* 1079135446Strhodes * We've found nothing so far, but we have hints. 1080135446Strhodes */ 1081135446Strhodes result = dns_db_find(view->hints, dns_rootname, NULL, 1082135446Strhodes dns_rdatatype_ns, 0, now, NULL, fname, 1083135446Strhodes rdataset, NULL); 1084135446Strhodes if (result != ISC_R_SUCCESS) { 1085135446Strhodes /* 1086135446Strhodes * We can't even find the hints for the root 1087135446Strhodes * nameservers! 1088135446Strhodes */ 1089135446Strhodes if (dns_rdataset_isassociated(rdataset)) 1090135446Strhodes dns_rdataset_disassociate(rdataset); 1091135446Strhodes result = ISC_R_NOTFOUND; 1092135446Strhodes } 1093135446Strhodes } 1094135446Strhodes 1095135446Strhodes cleanup: 1096135446Strhodes if (dns_rdataset_isassociated(&zrdataset)) { 1097135446Strhodes dns_rdataset_disassociate(&zrdataset); 1098135446Strhodes if (dns_rdataset_isassociated(&zsigrdataset)) 1099135446Strhodes dns_rdataset_disassociate(&zsigrdataset); 1100135446Strhodes } 1101135446Strhodes if (db != NULL) 1102135446Strhodes dns_db_detach(&db); 1103135446Strhodes if (zone != NULL) 1104135446Strhodes dns_zone_detach(&zone); 1105135446Strhodes 1106135446Strhodes return (result); 1107135446Strhodes} 1108135446Strhodes 1109135446Strhodesisc_result_t 1110135446Strhodesdns_viewlist_find(dns_viewlist_t *list, const char *name, 1111135446Strhodes dns_rdataclass_t rdclass, dns_view_t **viewp) 1112135446Strhodes{ 1113135446Strhodes dns_view_t *view; 1114135446Strhodes 1115135446Strhodes REQUIRE(list != NULL); 1116135446Strhodes 1117135446Strhodes for (view = ISC_LIST_HEAD(*list); 1118135446Strhodes view != NULL; 1119135446Strhodes view = ISC_LIST_NEXT(view, link)) { 1120135446Strhodes if (strcmp(view->name, name) == 0 && view->rdclass == rdclass) 1121135446Strhodes break; 1122135446Strhodes } 1123135446Strhodes if (view == NULL) 1124135446Strhodes return (ISC_R_NOTFOUND); 1125135446Strhodes 1126135446Strhodes dns_view_attach(view, viewp); 1127135446Strhodes 1128135446Strhodes return (ISC_R_SUCCESS); 1129135446Strhodes} 1130135446Strhodes 1131135446Strhodesisc_result_t 1132135446Strhodesdns_view_load(dns_view_t *view, isc_boolean_t stop) { 1133135446Strhodes 1134135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1135135446Strhodes 1136135446Strhodes return (dns_zt_load(view->zonetable, stop)); 1137135446Strhodes} 1138135446Strhodes 1139135446Strhodesisc_result_t 1140135446Strhodesdns_view_loadnew(dns_view_t *view, isc_boolean_t stop) { 1141135446Strhodes 1142135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1143135446Strhodes 1144135446Strhodes return (dns_zt_loadnew(view->zonetable, stop)); 1145135446Strhodes} 1146135446Strhodes 1147135446Strhodesisc_result_t 1148135446Strhodesdns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp) 1149135446Strhodes{ 1150135446Strhodes isc_result_t result; 1151135446Strhodes REQUIRE(keyp != NULL && *keyp == NULL); 1152135446Strhodes 1153135446Strhodes result = dns_tsigkey_find(keyp, keyname, NULL, 1154135446Strhodes view->statickeys); 1155135446Strhodes if (result == ISC_R_NOTFOUND) 1156135446Strhodes result = dns_tsigkey_find(keyp, keyname, NULL, 1157135446Strhodes view->dynamickeys); 1158135446Strhodes return (result); 1159135446Strhodes} 1160135446Strhodes 1161135446Strhodesisc_result_t 1162135446Strhodesdns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr, 1163135446Strhodes dns_tsigkey_t **keyp) 1164135446Strhodes{ 1165135446Strhodes isc_result_t result; 1166135446Strhodes dns_name_t *keyname = NULL; 1167135446Strhodes dns_peer_t *peer = NULL; 1168135446Strhodes 1169135446Strhodes result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer); 1170135446Strhodes if (result != ISC_R_SUCCESS) 1171135446Strhodes return (result); 1172135446Strhodes 1173135446Strhodes result = dns_peer_getkey(peer, &keyname); 1174135446Strhodes if (result != ISC_R_SUCCESS) 1175135446Strhodes return (result); 1176135446Strhodes 1177135446Strhodes return (dns_view_gettsig(view, keyname, keyp)); 1178135446Strhodes} 1179135446Strhodes 1180135446Strhodesisc_result_t 1181135446Strhodesdns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) { 1182135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1183135446Strhodes REQUIRE(source != NULL); 1184135446Strhodes 1185135446Strhodes return (dns_tsig_verify(source, msg, view->statickeys, 1186135446Strhodes view->dynamickeys)); 1187135446Strhodes} 1188135446Strhodes 1189135446Strhodesisc_result_t 1190135446Strhodesdns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { 1191135446Strhodes isc_result_t result; 1192135446Strhodes 1193135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1194135446Strhodes 1195135446Strhodes (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name); 1196135446Strhodes result = dns_master_dumptostream(view->mctx, view->cachedb, NULL, 1197135446Strhodes &dns_master_style_cache, fp); 1198135446Strhodes if (result != ISC_R_SUCCESS) 1199135446Strhodes return (result); 1200135446Strhodes dns_adb_dump(view->adb, fp); 1201135446Strhodes return (ISC_R_SUCCESS); 1202135446Strhodes} 1203135446Strhodes 1204135446Strhodesisc_result_t 1205135446Strhodesdns_view_flushcache(dns_view_t *view) { 1206135446Strhodes isc_result_t result; 1207135446Strhodes 1208135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1209135446Strhodes 1210135446Strhodes if (view->cachedb == NULL) 1211135446Strhodes return (ISC_R_SUCCESS); 1212135446Strhodes result = dns_cache_flush(view->cache); 1213135446Strhodes if (result != ISC_R_SUCCESS) 1214135446Strhodes return (result); 1215170222Sdougb if (view->acache != NULL) 1216170222Sdougb dns_acache_putdb(view->acache, view->cachedb); 1217135446Strhodes dns_db_detach(&view->cachedb); 1218135446Strhodes dns_cache_attachdb(view->cache, &view->cachedb); 1219170222Sdougb if (view->acache != NULL) 1220170222Sdougb dns_acache_setdb(view->acache, view->cachedb); 1221135446Strhodes 1222135446Strhodes dns_adb_flush(view->adb); 1223135446Strhodes return (ISC_R_SUCCESS); 1224135446Strhodes} 1225135446Strhodes 1226135446Strhodesisc_result_t 1227135446Strhodesdns_view_flushname(dns_view_t *view, dns_name_t *name) { 1228135446Strhodes 1229135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1230135446Strhodes 1231135446Strhodes if (view->adb != NULL) 1232135446Strhodes dns_adb_flushname(view->adb, name); 1233135446Strhodes if (view->cache == NULL) 1234135446Strhodes return (ISC_R_SUCCESS); 1235135446Strhodes return (dns_cache_flushname(view->cache, name)); 1236135446Strhodes} 1237135446Strhodes 1238135446Strhodesisc_result_t 1239135446Strhodesdns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) { 1240135446Strhodes isc_result_t result; 1241135446Strhodes dns_name_t *new; 1242135446Strhodes isc_uint32_t hash; 1243135446Strhodes 1244135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1245135446Strhodes 1246135446Strhodes if (view->delonly == NULL) { 1247135446Strhodes view->delonly = isc_mem_get(view->mctx, 1248135446Strhodes sizeof(dns_namelist_t) * 1249135446Strhodes DNS_VIEW_DELONLYHASH); 1250135446Strhodes if (view->delonly == NULL) 1251135446Strhodes return (ISC_R_NOMEMORY); 1252135446Strhodes for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) 1253135446Strhodes ISC_LIST_INIT(view->delonly[hash]); 1254135446Strhodes } 1255135446Strhodes hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1256135446Strhodes new = ISC_LIST_HEAD(view->delonly[hash]); 1257135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1258135446Strhodes new = ISC_LIST_NEXT(new, link); 1259135446Strhodes if (new != NULL) 1260135446Strhodes return (ISC_R_SUCCESS); 1261135446Strhodes new = isc_mem_get(view->mctx, sizeof(*new)); 1262135446Strhodes if (new == NULL) 1263135446Strhodes return (ISC_R_NOMEMORY); 1264135446Strhodes dns_name_init(new, NULL); 1265135446Strhodes result = dns_name_dup(name, view->mctx, new); 1266135446Strhodes if (result == ISC_R_SUCCESS) 1267135446Strhodes ISC_LIST_APPEND(view->delonly[hash], new, link); 1268135446Strhodes else 1269135446Strhodes isc_mem_put(view->mctx, new, sizeof(*new)); 1270135446Strhodes return (result); 1271135446Strhodes} 1272135446Strhodes 1273135446Strhodesisc_result_t 1274135446Strhodesdns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) { 1275135446Strhodes isc_result_t result; 1276135446Strhodes dns_name_t *new; 1277135446Strhodes isc_uint32_t hash; 1278135446Strhodes 1279135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1280135446Strhodes 1281135446Strhodes if (view->rootexclude == NULL) { 1282135446Strhodes view->rootexclude = isc_mem_get(view->mctx, 1283135446Strhodes sizeof(dns_namelist_t) * 1284135446Strhodes DNS_VIEW_DELONLYHASH); 1285135446Strhodes if (view->rootexclude == NULL) 1286135446Strhodes return (ISC_R_NOMEMORY); 1287135446Strhodes for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) 1288135446Strhodes ISC_LIST_INIT(view->rootexclude[hash]); 1289135446Strhodes } 1290135446Strhodes hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1291135446Strhodes new = ISC_LIST_HEAD(view->rootexclude[hash]); 1292135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1293135446Strhodes new = ISC_LIST_NEXT(new, link); 1294135446Strhodes if (new != NULL) 1295135446Strhodes return (ISC_R_SUCCESS); 1296135446Strhodes new = isc_mem_get(view->mctx, sizeof(*new)); 1297135446Strhodes if (new == NULL) 1298135446Strhodes return (ISC_R_NOMEMORY); 1299135446Strhodes dns_name_init(new, NULL); 1300135446Strhodes result = dns_name_dup(name, view->mctx, new); 1301135446Strhodes if (result == ISC_R_SUCCESS) 1302135446Strhodes ISC_LIST_APPEND(view->rootexclude[hash], new, link); 1303135446Strhodes else 1304135446Strhodes isc_mem_put(view->mctx, new, sizeof(*new)); 1305135446Strhodes return (result); 1306135446Strhodes} 1307135446Strhodes 1308135446Strhodesisc_boolean_t 1309135446Strhodesdns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) { 1310135446Strhodes dns_name_t *new; 1311135446Strhodes isc_uint32_t hash; 1312135446Strhodes 1313135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1314135446Strhodes 1315135446Strhodes if (!view->rootdelonly && view->delonly == NULL) 1316135446Strhodes return (ISC_FALSE); 1317135446Strhodes 1318135446Strhodes hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1319135446Strhodes if (view->rootdelonly && dns_name_countlabels(name) <= 2) { 1320135446Strhodes if (view->rootexclude == NULL) 1321135446Strhodes return (ISC_TRUE); 1322135446Strhodes new = ISC_LIST_HEAD(view->rootexclude[hash]); 1323135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1324135446Strhodes new = ISC_LIST_NEXT(new, link); 1325135446Strhodes if (new == NULL) 1326135446Strhodes return (ISC_TRUE); 1327135446Strhodes } 1328135446Strhodes 1329135446Strhodes if (view->delonly == NULL) 1330135446Strhodes return (ISC_FALSE); 1331135446Strhodes 1332135446Strhodes new = ISC_LIST_HEAD(view->delonly[hash]); 1333135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1334135446Strhodes new = ISC_LIST_NEXT(new, link); 1335135446Strhodes if (new == NULL) 1336135446Strhodes return (ISC_FALSE); 1337135446Strhodes return (ISC_TRUE); 1338135446Strhodes} 1339135446Strhodes 1340186462Sdougbvoid 1341135446Strhodesdns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) { 1342135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1343135446Strhodes view->rootdelonly = value; 1344135446Strhodes} 1345135446Strhodes 1346135446Strhodesisc_boolean_t 1347135446Strhodesdns_view_getrootdelonly(dns_view_t *view) { 1348135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1349135446Strhodes return (view->rootdelonly); 1350135446Strhodes} 1351170222Sdougb 1352170222Sdougbisc_result_t 1353170222Sdougbdns_view_freezezones(dns_view_t *view, isc_boolean_t value) { 1354170222Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1355170222Sdougb return (dns_zt_freezezones(view->zonetable, value)); 1356170222Sdougb} 1357