view.c revision 224092
1135446Strhodes/* 2224092Sdougb * Copyright (C) 2004-2011 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 18224092Sdougb/* $Id: view.c,v 1.178 2011-01-13 09:53:04 marka Exp $ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24224092Sdougb#include <isc/file.h> 25135446Strhodes#include <isc/hash.h> 26224092Sdougb#include <isc/print.h> 27224092Sdougb#include <isc/sha2.h> 28193149Sdougb#include <isc/stats.h> 29193149Sdougb#include <isc/string.h> /* Required for HP/UX (and others?) */ 30135446Strhodes#include <isc/task.h> 31135446Strhodes#include <isc/util.h> 32135446Strhodes 33170222Sdougb#include <dns/acache.h> 34135446Strhodes#include <dns/acl.h> 35135446Strhodes#include <dns/adb.h> 36135446Strhodes#include <dns/cache.h> 37135446Strhodes#include <dns/db.h> 38170222Sdougb#include <dns/dlz.h> 39224092Sdougb#ifdef BIND9 40224092Sdougb#include <dns/dns64.h> 41224092Sdougb#endif 42224092Sdougb#include <dns/dnssec.h> 43135446Strhodes#include <dns/events.h> 44135446Strhodes#include <dns/forward.h> 45135446Strhodes#include <dns/keytable.h> 46224092Sdougb#include <dns/keyvalues.h> 47135446Strhodes#include <dns/master.h> 48135446Strhodes#include <dns/masterdump.h> 49135446Strhodes#include <dns/order.h> 50135446Strhodes#include <dns/peer.h> 51224092Sdougb#include <dns/rbt.h> 52135446Strhodes#include <dns/rdataset.h> 53135446Strhodes#include <dns/request.h> 54135446Strhodes#include <dns/resolver.h> 55135446Strhodes#include <dns/result.h> 56224092Sdougb#include <dns/rpz.h> 57193149Sdougb#include <dns/stats.h> 58135446Strhodes#include <dns/tsig.h> 59135446Strhodes#include <dns/zone.h> 60135446Strhodes#include <dns/zt.h> 61135446Strhodes 62135446Strhodes#define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0) 63135446Strhodes#define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0) 64135446Strhodes#define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0) 65135446Strhodes 66135446Strhodes#define DNS_VIEW_DELONLYHASH 111 67135446Strhodes 68135446Strhodesstatic void resolver_shutdown(isc_task_t *task, isc_event_t *event); 69135446Strhodesstatic void adb_shutdown(isc_task_t *task, isc_event_t *event); 70135446Strhodesstatic void req_shutdown(isc_task_t *task, isc_event_t *event); 71135446Strhodes 72135446Strhodesisc_result_t 73135446Strhodesdns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, 74135446Strhodes const char *name, dns_view_t **viewp) 75135446Strhodes{ 76135446Strhodes dns_view_t *view; 77135446Strhodes isc_result_t result; 78135446Strhodes 79135446Strhodes /* 80135446Strhodes * Create a view. 81135446Strhodes */ 82135446Strhodes 83135446Strhodes REQUIRE(name != NULL); 84135446Strhodes REQUIRE(viewp != NULL && *viewp == NULL); 85135446Strhodes 86135446Strhodes view = isc_mem_get(mctx, sizeof(*view)); 87135446Strhodes if (view == NULL) 88135446Strhodes return (ISC_R_NOMEMORY); 89135446Strhodes view->name = isc_mem_strdup(mctx, name); 90135446Strhodes if (view->name == NULL) { 91135446Strhodes result = ISC_R_NOMEMORY; 92135446Strhodes goto cleanup_view; 93135446Strhodes } 94135446Strhodes result = isc_mutex_init(&view->lock); 95170222Sdougb if (result != ISC_R_SUCCESS) 96135446Strhodes goto cleanup_name; 97170222Sdougb 98224092Sdougb#ifdef BIND9 99135446Strhodes view->zonetable = NULL; 100135446Strhodes result = dns_zt_create(mctx, rdclass, &view->zonetable); 101135446Strhodes if (result != ISC_R_SUCCESS) { 102135446Strhodes UNEXPECTED_ERROR(__FILE__, __LINE__, 103135446Strhodes "dns_zt_create() failed: %s", 104135446Strhodes isc_result_totext(result)); 105135446Strhodes result = ISC_R_UNEXPECTED; 106135446Strhodes goto cleanup_mutex; 107135446Strhodes } 108224092Sdougb#endif 109224092Sdougb view->secroots_priv = NULL; 110135446Strhodes view->fwdtable = NULL; 111135446Strhodes result = dns_fwdtable_create(mctx, &view->fwdtable); 112135446Strhodes if (result != ISC_R_SUCCESS) { 113135446Strhodes UNEXPECTED_ERROR(__FILE__, __LINE__, 114135446Strhodes "dns_fwdtable_create() failed: %s", 115135446Strhodes isc_result_totext(result)); 116135446Strhodes result = ISC_R_UNEXPECTED; 117224092Sdougb goto cleanup_zt; 118135446Strhodes } 119135446Strhodes 120170222Sdougb view->acache = NULL; 121135446Strhodes view->cache = NULL; 122135446Strhodes view->cachedb = NULL; 123170222Sdougb view->dlzdatabase = NULL; 124135446Strhodes view->hints = NULL; 125135446Strhodes view->resolver = NULL; 126135446Strhodes view->adb = NULL; 127135446Strhodes view->requestmgr = NULL; 128135446Strhodes view->mctx = mctx; 129135446Strhodes view->rdclass = rdclass; 130135446Strhodes view->frozen = ISC_FALSE; 131135446Strhodes view->task = NULL; 132170222Sdougb result = isc_refcount_init(&view->references, 1); 133170222Sdougb if (result != ISC_R_SUCCESS) 134170222Sdougb goto cleanup_fwdtable; 135135446Strhodes view->weakrefs = 0; 136135446Strhodes view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN| 137135446Strhodes DNS_VIEWATTR_REQSHUTDOWN); 138135446Strhodes view->statickeys = NULL; 139135446Strhodes view->dynamickeys = NULL; 140135446Strhodes view->matchclients = NULL; 141135446Strhodes view->matchdestinations = NULL; 142135446Strhodes view->matchrecursiveonly = ISC_FALSE; 143135446Strhodes result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys); 144135446Strhodes if (result != ISC_R_SUCCESS) 145170222Sdougb goto cleanup_references; 146135446Strhodes view->peers = NULL; 147135446Strhodes view->order = NULL; 148135446Strhodes view->delonly = NULL; 149135446Strhodes view->rootdelonly = ISC_FALSE; 150135446Strhodes view->rootexclude = NULL; 151193149Sdougb view->resstats = NULL; 152193149Sdougb view->resquerystats = NULL; 153224092Sdougb view->cacheshared = ISC_FALSE; 154224092Sdougb ISC_LIST_INIT(view->dns64); 155224092Sdougb view->dns64cnt = 0; 156135446Strhodes 157135446Strhodes /* 158135446Strhodes * Initialize configuration data with default values. 159135446Strhodes */ 160135446Strhodes view->recursion = ISC_TRUE; 161135446Strhodes view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ 162135446Strhodes view->additionalfromcache = ISC_TRUE; 163135446Strhodes view->additionalfromauth = ISC_TRUE; 164135446Strhodes view->enablednssec = ISC_TRUE; 165170222Sdougb view->enablevalidation = ISC_TRUE; 166170222Sdougb view->acceptexpired = ISC_FALSE; 167135446Strhodes view->minimalresponses = ISC_FALSE; 168135446Strhodes view->transfer_format = dns_one_answer; 169216175Sdougb view->cacheacl = NULL; 170216175Sdougb view->cacheonacl = NULL; 171135446Strhodes view->queryacl = NULL; 172193149Sdougb view->queryonacl = NULL; 173135446Strhodes view->recursionacl = NULL; 174193149Sdougb view->recursiononacl = NULL; 175135446Strhodes view->sortlist = NULL; 176193149Sdougb view->transferacl = NULL; 177193149Sdougb view->notifyacl = NULL; 178193149Sdougb view->updateacl = NULL; 179193149Sdougb view->upfwdacl = NULL; 180224092Sdougb view->denyansweracl = NULL; 181224092Sdougb view->answeracl_exclude = NULL; 182224092Sdougb view->denyanswernames = NULL; 183224092Sdougb view->answernames_exclude = NULL; 184135446Strhodes view->requestixfr = ISC_TRUE; 185135446Strhodes view->provideixfr = ISC_TRUE; 186135446Strhodes view->maxcachettl = 7 * 24 * 3600; 187135446Strhodes view->maxncachettl = 3 * 3600; 188135446Strhodes view->dstport = 53; 189135446Strhodes view->preferred_glue = 0; 190135446Strhodes view->flush = ISC_FALSE; 191135446Strhodes view->dlv = NULL; 192170222Sdougb view->maxudp = 0; 193224092Sdougb view->v4_aaaa = dns_v4_aaaa_ok; 194224092Sdougb view->v4_aaaa_acl = NULL; 195224092Sdougb ISC_LIST_INIT(view->rpz_zones); 196135446Strhodes dns_fixedname_init(&view->dlv_fixed); 197224092Sdougb view->managed_keys = NULL; 198224092Sdougb#ifdef BIND9 199224092Sdougb view->new_zone_file = NULL; 200224092Sdougb view->new_zone_config = NULL; 201224092Sdougb view->cfg_destroy = NULL; 202135446Strhodes 203135446Strhodes result = dns_order_create(view->mctx, &view->order); 204135446Strhodes if (result != ISC_R_SUCCESS) 205135446Strhodes goto cleanup_dynkeys; 206224092Sdougb#endif 207135446Strhodes 208135446Strhodes result = dns_peerlist_new(view->mctx, &view->peers); 209135446Strhodes if (result != ISC_R_SUCCESS) 210135446Strhodes goto cleanup_order; 211135446Strhodes 212135446Strhodes result = dns_aclenv_init(view->mctx, &view->aclenv); 213135446Strhodes if (result != ISC_R_SUCCESS) 214135446Strhodes goto cleanup_peerlist; 215135446Strhodes 216135446Strhodes ISC_LINK_INIT(view, link); 217135446Strhodes ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL, 218135446Strhodes DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, 219135446Strhodes view, NULL, NULL, NULL); 220135446Strhodes ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL, 221135446Strhodes DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, 222135446Strhodes view, NULL, NULL, NULL); 223135446Strhodes ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL, 224135446Strhodes DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, 225135446Strhodes view, NULL, NULL, NULL); 226135446Strhodes view->magic = DNS_VIEW_MAGIC; 227135446Strhodes 228135446Strhodes *viewp = view; 229135446Strhodes 230135446Strhodes return (ISC_R_SUCCESS); 231135446Strhodes 232135446Strhodes cleanup_peerlist: 233135446Strhodes dns_peerlist_detach(&view->peers); 234135446Strhodes 235135446Strhodes cleanup_order: 236224092Sdougb#ifdef BIND9 237135446Strhodes dns_order_detach(&view->order); 238135446Strhodes 239135446Strhodes cleanup_dynkeys: 240224092Sdougb#endif 241224092Sdougb dns_tsigkeyring_detach(&view->dynamickeys); 242135446Strhodes 243170222Sdougb cleanup_references: 244170222Sdougb isc_refcount_destroy(&view->references); 245170222Sdougb 246135446Strhodes cleanup_fwdtable: 247135446Strhodes dns_fwdtable_destroy(&view->fwdtable); 248135446Strhodes 249135446Strhodes cleanup_zt: 250224092Sdougb#ifdef BIND9 251135446Strhodes dns_zt_detach(&view->zonetable); 252135446Strhodes 253135446Strhodes cleanup_mutex: 254224092Sdougb#endif 255135446Strhodes DESTROYLOCK(&view->lock); 256135446Strhodes 257135446Strhodes cleanup_name: 258135446Strhodes isc_mem_free(mctx, view->name); 259135446Strhodes 260135446Strhodes cleanup_view: 261135446Strhodes isc_mem_put(mctx, view, sizeof(*view)); 262135446Strhodes 263135446Strhodes return (result); 264135446Strhodes} 265135446Strhodes 266135446Strhodesstatic inline void 267135446Strhodesdestroy(dns_view_t *view) { 268224092Sdougb#ifdef BIND9 269224092Sdougb dns_dns64_t *dns64; 270224092Sdougb#endif 271224092Sdougb 272135446Strhodes REQUIRE(!ISC_LINK_LINKED(view, link)); 273135446Strhodes REQUIRE(isc_refcount_current(&view->references) == 0); 274135446Strhodes REQUIRE(view->weakrefs == 0); 275135446Strhodes REQUIRE(RESSHUTDOWN(view)); 276135446Strhodes REQUIRE(ADBSHUTDOWN(view)); 277135446Strhodes REQUIRE(REQSHUTDOWN(view)); 278135446Strhodes 279224092Sdougb#ifdef BIND9 280135446Strhodes if (view->order != NULL) 281135446Strhodes dns_order_detach(&view->order); 282224092Sdougb#endif 283135446Strhodes if (view->peers != NULL) 284135446Strhodes dns_peerlist_detach(&view->peers); 285224092Sdougb 286224092Sdougb if (view->dynamickeys != NULL) { 287224092Sdougb isc_result_t result; 288224092Sdougb char template[20]; 289224092Sdougb char keyfile[20]; 290224092Sdougb FILE *fp = NULL; 291224092Sdougb int n; 292224092Sdougb 293224092Sdougb n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys", 294224092Sdougb view->name); 295224092Sdougb if (n > 0 && (size_t)n < sizeof(keyfile)) { 296224092Sdougb result = isc_file_mktemplate(keyfile, template, 297224092Sdougb sizeof(template)); 298224092Sdougb if (result == ISC_R_SUCCESS) 299224092Sdougb (void)isc_file_openuniqueprivate(template, &fp); 300224092Sdougb } 301224092Sdougb if (fp == NULL) 302224092Sdougb dns_tsigkeyring_detach(&view->dynamickeys); 303224092Sdougb else { 304224092Sdougb result = dns_tsigkeyring_dumpanddetach( 305224092Sdougb &view->dynamickeys, fp); 306224092Sdougb if (result == ISC_R_SUCCESS) { 307224092Sdougb if (fclose(fp) == 0) 308224092Sdougb result = isc_file_rename(template, 309224092Sdougb keyfile); 310224092Sdougb if (result != ISC_R_SUCCESS) 311224092Sdougb (void)remove(template); 312224092Sdougb } else { 313224092Sdougb (void)fclose(fp); 314224092Sdougb (void)remove(template); 315224092Sdougb } 316224092Sdougb } 317224092Sdougb } 318135446Strhodes if (view->statickeys != NULL) 319224092Sdougb dns_tsigkeyring_detach(&view->statickeys); 320135446Strhodes if (view->adb != NULL) 321135446Strhodes dns_adb_detach(&view->adb); 322135446Strhodes if (view->resolver != NULL) 323135446Strhodes dns_resolver_detach(&view->resolver); 324224092Sdougb#ifdef BIND9 325170222Sdougb if (view->acache != NULL) { 326170222Sdougb if (view->cachedb != NULL) 327170222Sdougb dns_acache_putdb(view->acache, view->cachedb); 328170222Sdougb dns_acache_detach(&view->acache); 329170222Sdougb } 330224092Sdougb dns_rpz_view_destroy(view); 331224092Sdougb#else 332224092Sdougb INSIST(view->acache == NULL); 333224092Sdougb INSIST(ISC_LIST_EMPTY(view->rpz_zones)); 334224092Sdougb#endif 335135446Strhodes if (view->requestmgr != NULL) 336135446Strhodes dns_requestmgr_detach(&view->requestmgr); 337135446Strhodes if (view->task != NULL) 338135446Strhodes isc_task_detach(&view->task); 339135446Strhodes if (view->hints != NULL) 340135446Strhodes dns_db_detach(&view->hints); 341170222Sdougb if (view->dlzdatabase != NULL) 342170222Sdougb dns_dlzdestroy(&view->dlzdatabase); 343135446Strhodes if (view->cachedb != NULL) 344135446Strhodes dns_db_detach(&view->cachedb); 345135446Strhodes if (view->cache != NULL) 346135446Strhodes dns_cache_detach(&view->cache); 347135446Strhodes if (view->matchclients != NULL) 348135446Strhodes dns_acl_detach(&view->matchclients); 349135446Strhodes if (view->matchdestinations != NULL) 350135446Strhodes dns_acl_detach(&view->matchdestinations); 351216175Sdougb if (view->cacheacl != NULL) 352216175Sdougb dns_acl_detach(&view->cacheacl); 353216175Sdougb if (view->cacheonacl != NULL) 354216175Sdougb dns_acl_detach(&view->cacheonacl); 355135446Strhodes if (view->queryacl != NULL) 356135446Strhodes dns_acl_detach(&view->queryacl); 357193149Sdougb if (view->queryonacl != NULL) 358193149Sdougb dns_acl_detach(&view->queryonacl); 359135446Strhodes if (view->recursionacl != NULL) 360135446Strhodes dns_acl_detach(&view->recursionacl); 361193149Sdougb if (view->recursiononacl != NULL) 362193149Sdougb dns_acl_detach(&view->recursiononacl); 363135446Strhodes if (view->sortlist != NULL) 364135446Strhodes dns_acl_detach(&view->sortlist); 365193149Sdougb if (view->transferacl != NULL) 366193149Sdougb dns_acl_detach(&view->transferacl); 367193149Sdougb if (view->notifyacl != NULL) 368193149Sdougb dns_acl_detach(&view->notifyacl); 369193149Sdougb if (view->updateacl != NULL) 370193149Sdougb dns_acl_detach(&view->updateacl); 371193149Sdougb if (view->upfwdacl != NULL) 372193149Sdougb dns_acl_detach(&view->upfwdacl); 373224092Sdougb if (view->denyansweracl != NULL) 374224092Sdougb dns_acl_detach(&view->denyansweracl); 375224092Sdougb if (view->v4_aaaa_acl != NULL) 376224092Sdougb dns_acl_detach(&view->v4_aaaa_acl); 377224092Sdougb if (view->answeracl_exclude != NULL) 378224092Sdougb dns_rbt_destroy(&view->answeracl_exclude); 379224092Sdougb if (view->denyanswernames != NULL) 380224092Sdougb dns_rbt_destroy(&view->denyanswernames); 381224092Sdougb if (view->answernames_exclude != NULL) 382224092Sdougb dns_rbt_destroy(&view->answernames_exclude); 383135446Strhodes if (view->delonly != NULL) { 384135446Strhodes dns_name_t *name; 385135446Strhodes int i; 386135446Strhodes 387135446Strhodes for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 388135446Strhodes name = ISC_LIST_HEAD(view->delonly[i]); 389135446Strhodes while (name != NULL) { 390135446Strhodes ISC_LIST_UNLINK(view->delonly[i], name, link); 391135446Strhodes dns_name_free(name, view->mctx); 392135446Strhodes isc_mem_put(view->mctx, name, sizeof(*name)); 393135446Strhodes name = ISC_LIST_HEAD(view->delonly[i]); 394135446Strhodes } 395135446Strhodes } 396135446Strhodes isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) * 397135446Strhodes DNS_VIEW_DELONLYHASH); 398135446Strhodes view->delonly = NULL; 399135446Strhodes } 400135446Strhodes if (view->rootexclude != NULL) { 401135446Strhodes dns_name_t *name; 402135446Strhodes int i; 403135446Strhodes 404135446Strhodes for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { 405135446Strhodes name = ISC_LIST_HEAD(view->rootexclude[i]); 406135446Strhodes while (name != NULL) { 407135446Strhodes ISC_LIST_UNLINK(view->rootexclude[i], 408186462Sdougb name, link); 409135446Strhodes dns_name_free(name, view->mctx); 410135446Strhodes isc_mem_put(view->mctx, name, sizeof(*name)); 411135446Strhodes name = ISC_LIST_HEAD(view->rootexclude[i]); 412135446Strhodes } 413135446Strhodes } 414135446Strhodes isc_mem_put(view->mctx, view->rootexclude, 415135446Strhodes sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH); 416135446Strhodes view->rootexclude = NULL; 417135446Strhodes } 418193149Sdougb if (view->resstats != NULL) 419193149Sdougb isc_stats_detach(&view->resstats); 420193149Sdougb if (view->resquerystats != NULL) 421193149Sdougb dns_stats_detach(&view->resquerystats); 422224092Sdougb if (view->secroots_priv != NULL) 423224092Sdougb dns_keytable_detach(&view->secroots_priv); 424224092Sdougb#ifdef BIND9 425224092Sdougb for (dns64 = ISC_LIST_HEAD(view->dns64); 426224092Sdougb dns64 != NULL; 427224092Sdougb dns64 = ISC_LIST_HEAD(view->dns64)) { 428224092Sdougb dns_dns64_unlink(&view->dns64, dns64); 429224092Sdougb dns_dns64_destroy(&dns64); 430224092Sdougb } 431224092Sdougb if (view->managed_keys != NULL) 432224092Sdougb dns_zone_detach(&view->managed_keys); 433224092Sdougb dns_view_setnewzones(view, ISC_FALSE, NULL, NULL); 434224092Sdougb#endif 435135446Strhodes dns_fwdtable_destroy(&view->fwdtable); 436135446Strhodes dns_aclenv_destroy(&view->aclenv); 437135446Strhodes DESTROYLOCK(&view->lock); 438135446Strhodes isc_refcount_destroy(&view->references); 439135446Strhodes isc_mem_free(view->mctx, view->name); 440135446Strhodes isc_mem_put(view->mctx, view, sizeof(*view)); 441135446Strhodes} 442135446Strhodes 443135446Strhodes/* 444135446Strhodes * Return true iff 'view' may be freed. 445135446Strhodes * The caller must be holding the view lock. 446135446Strhodes */ 447135446Strhodesstatic isc_boolean_t 448135446Strhodesall_done(dns_view_t *view) { 449135446Strhodes 450135446Strhodes if (isc_refcount_current(&view->references) == 0 && 451135446Strhodes view->weakrefs == 0 && 452135446Strhodes RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view)) 453135446Strhodes return (ISC_TRUE); 454135446Strhodes 455135446Strhodes return (ISC_FALSE); 456135446Strhodes} 457135446Strhodes 458135446Strhodesvoid 459135446Strhodesdns_view_attach(dns_view_t *source, dns_view_t **targetp) { 460135446Strhodes 461135446Strhodes REQUIRE(DNS_VIEW_VALID(source)); 462135446Strhodes REQUIRE(targetp != NULL && *targetp == NULL); 463135446Strhodes 464135446Strhodes isc_refcount_increment(&source->references, NULL); 465135446Strhodes 466135446Strhodes *targetp = source; 467135446Strhodes} 468135446Strhodes 469135446Strhodesstatic void 470135446Strhodesview_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { 471135446Strhodes dns_view_t *view; 472135446Strhodes unsigned int refs; 473135446Strhodes isc_boolean_t done = ISC_FALSE; 474135446Strhodes 475135446Strhodes REQUIRE(viewp != NULL); 476135446Strhodes view = *viewp; 477135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 478135446Strhodes 479135446Strhodes if (flush) 480135446Strhodes view->flush = ISC_TRUE; 481135446Strhodes isc_refcount_decrement(&view->references, &refs); 482135446Strhodes if (refs == 0) { 483135446Strhodes LOCK(&view->lock); 484135446Strhodes if (!RESSHUTDOWN(view)) 485135446Strhodes dns_resolver_shutdown(view->resolver); 486135446Strhodes if (!ADBSHUTDOWN(view)) 487135446Strhodes dns_adb_shutdown(view->adb); 488135446Strhodes if (!REQSHUTDOWN(view)) 489135446Strhodes dns_requestmgr_shutdown(view->requestmgr); 490224092Sdougb#ifdef BIND9 491170222Sdougb if (view->acache != NULL) 492170222Sdougb dns_acache_shutdown(view->acache); 493135446Strhodes if (view->flush) 494135446Strhodes dns_zt_flushanddetach(&view->zonetable); 495135446Strhodes else 496135446Strhodes dns_zt_detach(&view->zonetable); 497224092Sdougb if (view->managed_keys != NULL) { 498224092Sdougb if (view->flush) 499224092Sdougb dns_zone_flush(view->managed_keys); 500224092Sdougb dns_zone_detach(&view->managed_keys); 501224092Sdougb } 502224092Sdougb#endif 503135446Strhodes done = all_done(view); 504135446Strhodes UNLOCK(&view->lock); 505135446Strhodes } 506135446Strhodes 507135446Strhodes *viewp = NULL; 508135446Strhodes 509135446Strhodes if (done) 510135446Strhodes destroy(view); 511135446Strhodes} 512135446Strhodes 513135446Strhodesvoid 514135446Strhodesdns_view_flushanddetach(dns_view_t **viewp) { 515135446Strhodes view_flushanddetach(viewp, ISC_TRUE); 516135446Strhodes} 517135446Strhodes 518135446Strhodesvoid 519135446Strhodesdns_view_detach(dns_view_t **viewp) { 520135446Strhodes view_flushanddetach(viewp, ISC_FALSE); 521135446Strhodes} 522135446Strhodes 523224092Sdougb#ifdef BIND9 524135446Strhodesstatic isc_result_t 525135446Strhodesdialup(dns_zone_t *zone, void *dummy) { 526135446Strhodes UNUSED(dummy); 527135446Strhodes dns_zone_dialup(zone); 528135446Strhodes return (ISC_R_SUCCESS); 529135446Strhodes} 530135446Strhodes 531135446Strhodesvoid 532135446Strhodesdns_view_dialup(dns_view_t *view) { 533135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 534135446Strhodes (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL); 535135446Strhodes} 536224092Sdougb#endif 537135446Strhodes 538135446Strhodesvoid 539135446Strhodesdns_view_weakattach(dns_view_t *source, dns_view_t **targetp) { 540135446Strhodes 541135446Strhodes REQUIRE(DNS_VIEW_VALID(source)); 542135446Strhodes REQUIRE(targetp != NULL && *targetp == NULL); 543135446Strhodes 544135446Strhodes LOCK(&source->lock); 545135446Strhodes source->weakrefs++; 546135446Strhodes UNLOCK(&source->lock); 547135446Strhodes 548135446Strhodes *targetp = source; 549135446Strhodes} 550135446Strhodes 551135446Strhodesvoid 552135446Strhodesdns_view_weakdetach(dns_view_t **viewp) { 553135446Strhodes dns_view_t *view; 554135446Strhodes isc_boolean_t done = ISC_FALSE; 555135446Strhodes 556135446Strhodes REQUIRE(viewp != NULL); 557135446Strhodes view = *viewp; 558135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 559135446Strhodes 560135446Strhodes LOCK(&view->lock); 561135446Strhodes 562135446Strhodes INSIST(view->weakrefs > 0); 563135446Strhodes view->weakrefs--; 564135446Strhodes done = all_done(view); 565135446Strhodes 566135446Strhodes UNLOCK(&view->lock); 567135446Strhodes 568135446Strhodes *viewp = NULL; 569135446Strhodes 570135446Strhodes if (done) 571135446Strhodes destroy(view); 572135446Strhodes} 573135446Strhodes 574135446Strhodesstatic void 575135446Strhodesresolver_shutdown(isc_task_t *task, isc_event_t *event) { 576135446Strhodes dns_view_t *view = event->ev_arg; 577135446Strhodes isc_boolean_t done; 578135446Strhodes 579135446Strhodes REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN); 580135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 581135446Strhodes REQUIRE(view->task == task); 582135446Strhodes 583135446Strhodes UNUSED(task); 584135446Strhodes 585135446Strhodes LOCK(&view->lock); 586135446Strhodes 587135446Strhodes view->attributes |= DNS_VIEWATTR_RESSHUTDOWN; 588135446Strhodes done = all_done(view); 589135446Strhodes 590135446Strhodes UNLOCK(&view->lock); 591135446Strhodes 592135446Strhodes isc_event_free(&event); 593135446Strhodes 594135446Strhodes if (done) 595135446Strhodes destroy(view); 596135446Strhodes} 597135446Strhodes 598135446Strhodesstatic void 599135446Strhodesadb_shutdown(isc_task_t *task, isc_event_t *event) { 600135446Strhodes dns_view_t *view = event->ev_arg; 601135446Strhodes isc_boolean_t done; 602135446Strhodes 603135446Strhodes REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN); 604135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 605135446Strhodes REQUIRE(view->task == task); 606135446Strhodes 607135446Strhodes UNUSED(task); 608135446Strhodes 609135446Strhodes LOCK(&view->lock); 610135446Strhodes 611135446Strhodes view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN; 612135446Strhodes done = all_done(view); 613135446Strhodes 614135446Strhodes UNLOCK(&view->lock); 615135446Strhodes 616135446Strhodes isc_event_free(&event); 617135446Strhodes 618135446Strhodes if (done) 619135446Strhodes destroy(view); 620135446Strhodes} 621135446Strhodes 622135446Strhodesstatic void 623135446Strhodesreq_shutdown(isc_task_t *task, isc_event_t *event) { 624135446Strhodes dns_view_t *view = event->ev_arg; 625135446Strhodes isc_boolean_t done; 626135446Strhodes 627135446Strhodes REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN); 628135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 629135446Strhodes REQUIRE(view->task == task); 630135446Strhodes 631135446Strhodes UNUSED(task); 632135446Strhodes 633135446Strhodes LOCK(&view->lock); 634135446Strhodes 635135446Strhodes view->attributes |= DNS_VIEWATTR_REQSHUTDOWN; 636135446Strhodes done = all_done(view); 637135446Strhodes 638135446Strhodes UNLOCK(&view->lock); 639135446Strhodes 640135446Strhodes isc_event_free(&event); 641135446Strhodes 642135446Strhodes if (done) 643135446Strhodes destroy(view); 644135446Strhodes} 645135446Strhodes 646135446Strhodesisc_result_t 647135446Strhodesdns_view_createresolver(dns_view_t *view, 648135446Strhodes isc_taskmgr_t *taskmgr, unsigned int ntasks, 649135446Strhodes isc_socketmgr_t *socketmgr, 650135446Strhodes isc_timermgr_t *timermgr, 651135446Strhodes unsigned int options, 652135446Strhodes dns_dispatchmgr_t *dispatchmgr, 653135446Strhodes dns_dispatch_t *dispatchv4, 654135446Strhodes dns_dispatch_t *dispatchv6) 655135446Strhodes{ 656135446Strhodes isc_result_t result; 657135446Strhodes isc_event_t *event; 658135446Strhodes isc_mem_t *mctx = NULL; 659135446Strhodes 660135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 661135446Strhodes REQUIRE(!view->frozen); 662135446Strhodes REQUIRE(view->resolver == NULL); 663135446Strhodes 664135446Strhodes result = isc_task_create(taskmgr, 0, &view->task); 665135446Strhodes if (result != ISC_R_SUCCESS) 666135446Strhodes return (result); 667135446Strhodes isc_task_setname(view->task, "view", view); 668135446Strhodes 669135446Strhodes result = dns_resolver_create(view, taskmgr, ntasks, socketmgr, 670135446Strhodes timermgr, options, dispatchmgr, 671135446Strhodes dispatchv4, dispatchv6, 672135446Strhodes &view->resolver); 673135446Strhodes if (result != ISC_R_SUCCESS) { 674135446Strhodes isc_task_detach(&view->task); 675135446Strhodes return (result); 676135446Strhodes } 677135446Strhodes event = &view->resevent; 678135446Strhodes dns_resolver_whenshutdown(view->resolver, view->task, &event); 679135446Strhodes view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN; 680135446Strhodes 681135446Strhodes result = isc_mem_create(0, 0, &mctx); 682135446Strhodes if (result != ISC_R_SUCCESS) { 683135446Strhodes dns_resolver_shutdown(view->resolver); 684135446Strhodes return (result); 685135446Strhodes } 686135446Strhodes 687135446Strhodes result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb); 688193149Sdougb isc_mem_setname(mctx, "ADB", NULL); 689135446Strhodes isc_mem_detach(&mctx); 690135446Strhodes if (result != ISC_R_SUCCESS) { 691135446Strhodes dns_resolver_shutdown(view->resolver); 692135446Strhodes return (result); 693135446Strhodes } 694135446Strhodes event = &view->adbevent; 695135446Strhodes dns_adb_whenshutdown(view->adb, view->task, &event); 696135446Strhodes view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN; 697135446Strhodes 698135446Strhodes result = dns_requestmgr_create(view->mctx, timermgr, socketmgr, 699135446Strhodes dns_resolver_taskmgr(view->resolver), 700135446Strhodes dns_resolver_dispatchmgr(view->resolver), 701135446Strhodes dns_resolver_dispatchv4(view->resolver), 702135446Strhodes dns_resolver_dispatchv6(view->resolver), 703135446Strhodes &view->requestmgr); 704135446Strhodes if (result != ISC_R_SUCCESS) { 705135446Strhodes dns_adb_shutdown(view->adb); 706135446Strhodes dns_resolver_shutdown(view->resolver); 707135446Strhodes return (result); 708135446Strhodes } 709135446Strhodes event = &view->reqevent; 710135446Strhodes dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event); 711135446Strhodes view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN; 712135446Strhodes 713135446Strhodes return (ISC_R_SUCCESS); 714135446Strhodes} 715135446Strhodes 716135446Strhodesvoid 717135446Strhodesdns_view_setcache(dns_view_t *view, dns_cache_t *cache) { 718224092Sdougb dns_view_setcache2(view, cache, ISC_FALSE); 719224092Sdougb} 720224092Sdougb 721224092Sdougbvoid 722224092Sdougbdns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) { 723135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 724135446Strhodes REQUIRE(!view->frozen); 725135446Strhodes 726224092Sdougb view->cacheshared = shared; 727135446Strhodes if (view->cache != NULL) { 728224092Sdougb#ifdef BIND9 729170222Sdougb if (view->acache != NULL) 730170222Sdougb dns_acache_putdb(view->acache, view->cachedb); 731224092Sdougb#endif 732135446Strhodes dns_db_detach(&view->cachedb); 733135446Strhodes dns_cache_detach(&view->cache); 734135446Strhodes } 735135446Strhodes dns_cache_attach(cache, &view->cache); 736135446Strhodes dns_cache_attachdb(cache, &view->cachedb); 737135446Strhodes INSIST(DNS_DB_VALID(view->cachedb)); 738170222Sdougb 739224092Sdougb#ifdef BIND9 740170222Sdougb if (view->acache != NULL) 741170222Sdougb dns_acache_setdb(view->acache, view->cachedb); 742224092Sdougb#endif 743135446Strhodes} 744135446Strhodes 745224092Sdougbisc_boolean_t 746224092Sdougbdns_view_iscacheshared(dns_view_t *view) { 747224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 748224092Sdougb 749224092Sdougb return (view->cacheshared); 750224092Sdougb} 751224092Sdougb 752135446Strhodesvoid 753135446Strhodesdns_view_sethints(dns_view_t *view, dns_db_t *hints) { 754135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 755135446Strhodes REQUIRE(!view->frozen); 756135446Strhodes REQUIRE(view->hints == NULL); 757135446Strhodes REQUIRE(dns_db_iszone(hints)); 758135446Strhodes 759135446Strhodes dns_db_attach(hints, &view->hints); 760135446Strhodes} 761135446Strhodes 762135446Strhodesvoid 763135446Strhodesdns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { 764135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 765135446Strhodes REQUIRE(ring != NULL); 766135446Strhodes if (view->statickeys != NULL) 767224092Sdougb dns_tsigkeyring_detach(&view->statickeys); 768224092Sdougb dns_tsigkeyring_attach(ring, &view->statickeys); 769135446Strhodes} 770135446Strhodes 771135446Strhodesvoid 772224092Sdougbdns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) { 773135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 774224092Sdougb REQUIRE(ring != NULL); 775224092Sdougb if (view->dynamickeys != NULL) 776224092Sdougb dns_tsigkeyring_detach(&view->dynamickeys); 777224092Sdougb dns_tsigkeyring_attach(ring, &view->dynamickeys); 778135446Strhodes} 779135446Strhodes 780224092Sdougbvoid 781224092Sdougbdns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) { 782224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 783224092Sdougb REQUIRE(ringp != NULL && *ringp == NULL); 784224092Sdougb if (view->dynamickeys != NULL) 785224092Sdougb dns_tsigkeyring_attach(view->dynamickeys, ringp); 786224092Sdougb} 787135446Strhodes 788224092Sdougbvoid 789224092Sdougbdns_view_restorekeyring(dns_view_t *view) { 790224092Sdougb FILE *fp; 791224092Sdougb char keyfile[20]; 792224092Sdougb int n; 793224092Sdougb 794135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 795135446Strhodes 796224092Sdougb if (view->dynamickeys != NULL) { 797224092Sdougb n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys", 798224092Sdougb view->name); 799224092Sdougb if (n > 0 && (size_t)n < sizeof(keyfile)) { 800224092Sdougb fp = fopen(keyfile, "r"); 801224092Sdougb if (fp != NULL) { 802224092Sdougb dns_keyring_restore(view->dynamickeys, fp); 803224092Sdougb (void)fclose(fp); 804224092Sdougb } 805224092Sdougb } 806224092Sdougb } 807224092Sdougb} 808135446Strhodes 809224092Sdougbvoid 810224092Sdougbdns_view_setdstport(dns_view_t *view, in_port_t dstport) { 811224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 812224092Sdougb view->dstport = dstport; 813135446Strhodes} 814135446Strhodes 815135446Strhodesvoid 816135446Strhodesdns_view_freeze(dns_view_t *view) { 817135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 818135446Strhodes REQUIRE(!view->frozen); 819135446Strhodes 820135446Strhodes if (view->resolver != NULL) { 821135446Strhodes INSIST(view->cachedb != NULL); 822135446Strhodes dns_resolver_freeze(view->resolver); 823135446Strhodes } 824135446Strhodes view->frozen = ISC_TRUE; 825135446Strhodes} 826135446Strhodes 827224092Sdougb#ifdef BIND9 828224092Sdougbvoid 829224092Sdougbdns_view_thaw(dns_view_t *view) { 830224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 831224092Sdougb REQUIRE(view->frozen); 832224092Sdougb 833224092Sdougb view->frozen = ISC_FALSE; 834224092Sdougb} 835224092Sdougb 836135446Strhodesisc_result_t 837224092Sdougbdns_view_addzone(dns_view_t *view, dns_zone_t *zone) { 838224092Sdougb isc_result_t result; 839224092Sdougb 840224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 841224092Sdougb REQUIRE(!view->frozen); 842224092Sdougb 843224092Sdougb result = dns_zt_mount(view->zonetable, zone); 844224092Sdougb 845224092Sdougb return (result); 846224092Sdougb} 847224092Sdougb#endif 848224092Sdougb 849224092Sdougb#ifdef BIND9 850224092Sdougbisc_result_t 851135446Strhodesdns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) { 852135446Strhodes isc_result_t result; 853135446Strhodes 854135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 855135446Strhodes 856135446Strhodes result = dns_zt_find(view->zonetable, name, 0, NULL, zonep); 857135446Strhodes if (result == DNS_R_PARTIALMATCH) { 858135446Strhodes dns_zone_detach(zonep); 859135446Strhodes result = ISC_R_NOTFOUND; 860135446Strhodes } 861135446Strhodes 862135446Strhodes return (result); 863135446Strhodes} 864224092Sdougb#endif 865135446Strhodes 866135446Strhodesisc_result_t 867135446Strhodesdns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 868135446Strhodes isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints, 869135446Strhodes dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, 870224092Sdougb dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 871224092Sdougb return (dns_view_find2(view, name, type, now, options, use_hints, 872224092Sdougb ISC_FALSE, dbp, nodep, foundname, rdataset, 873224092Sdougb sigrdataset)); 874224092Sdougb} 875224092Sdougb 876224092Sdougbisc_result_t 877224092Sdougbdns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 878224092Sdougb isc_stdtime_t now, unsigned int options, 879224092Sdougb isc_boolean_t use_hints, isc_boolean_t use_static_stub, 880224092Sdougb dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname, 881224092Sdougb dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 882135446Strhodes{ 883135446Strhodes isc_result_t result; 884135446Strhodes dns_db_t *db, *zdb; 885135446Strhodes dns_dbnode_t *node, *znode; 886224092Sdougb isc_boolean_t is_cache, is_staticstub_zone; 887135446Strhodes dns_rdataset_t zrdataset, zsigrdataset; 888135446Strhodes dns_zone_t *zone; 889135446Strhodes 890224092Sdougb#ifndef BIND9 891224092Sdougb UNUSED(use_hints); 892224092Sdougb UNUSED(use_static_stub); 893224092Sdougb#endif 894224092Sdougb 895135446Strhodes /* 896135446Strhodes * Find an rdataset whose owner name is 'name', and whose type is 897135446Strhodes * 'type'. 898135446Strhodes */ 899135446Strhodes 900135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 901135446Strhodes REQUIRE(view->frozen); 902135446Strhodes REQUIRE(type != dns_rdatatype_rrsig); 903135446Strhodes REQUIRE(rdataset != NULL); /* XXXBEW - remove this */ 904174187Sdougb REQUIRE(nodep == NULL || *nodep == NULL); 905135446Strhodes 906135446Strhodes /* 907135446Strhodes * Initialize. 908135446Strhodes */ 909135446Strhodes dns_rdataset_init(&zrdataset); 910135446Strhodes dns_rdataset_init(&zsigrdataset); 911135446Strhodes zdb = NULL; 912135446Strhodes znode = NULL; 913135446Strhodes 914135446Strhodes /* 915135446Strhodes * Find a database to answer the query. 916135446Strhodes */ 917135446Strhodes zone = NULL; 918135446Strhodes db = NULL; 919135446Strhodes node = NULL; 920224092Sdougb is_staticstub_zone = ISC_FALSE; 921224092Sdougb#ifdef BIND9 922135446Strhodes result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 923224092Sdougb if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub && 924224092Sdougb !use_static_stub) { 925224092Sdougb result = ISC_R_NOTFOUND; 926224092Sdougb } 927135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 928135446Strhodes result = dns_zone_getdb(zone, &db); 929135446Strhodes if (result != ISC_R_SUCCESS && view->cachedb != NULL) 930135446Strhodes dns_db_attach(view->cachedb, &db); 931135446Strhodes else if (result != ISC_R_SUCCESS) 932135446Strhodes goto cleanup; 933224092Sdougb if (dns_zone_gettype(zone) == dns_zone_staticstub && 934224092Sdougb dns_name_equal(name, dns_zone_getorigin(zone))) { 935224092Sdougb is_staticstub_zone = ISC_TRUE; 936224092Sdougb } 937135446Strhodes } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) 938135446Strhodes dns_db_attach(view->cachedb, &db); 939224092Sdougb#else 940224092Sdougb result = ISC_R_NOTFOUND; 941224092Sdougb if (view->cachedb != NULL) 942224092Sdougb dns_db_attach(view->cachedb, &db); 943224092Sdougb#endif /* BIND9 */ 944135446Strhodes else 945135446Strhodes goto cleanup; 946135446Strhodes 947135446Strhodes is_cache = dns_db_iscache(db); 948135446Strhodes 949135446Strhodes db_find: 950135446Strhodes /* 951135446Strhodes * Now look for an answer in the database. 952135446Strhodes */ 953135446Strhodes result = dns_db_find(db, name, NULL, type, options, 954135446Strhodes now, &node, foundname, rdataset, sigrdataset); 955135446Strhodes 956224092Sdougb if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) { 957135446Strhodes if (dns_rdataset_isassociated(rdataset)) 958135446Strhodes dns_rdataset_disassociate(rdataset); 959135446Strhodes if (sigrdataset != NULL && 960135446Strhodes dns_rdataset_isassociated(sigrdataset)) 961135446Strhodes dns_rdataset_disassociate(sigrdataset); 962135446Strhodes if (node != NULL) 963135446Strhodes dns_db_detachnode(db, &node); 964135446Strhodes if (!is_cache) { 965135446Strhodes dns_db_detach(&db); 966224092Sdougb if (view->cachedb != NULL && !is_staticstub_zone) { 967135446Strhodes /* 968135446Strhodes * Either the answer is in the cache, or we 969135446Strhodes * don't know it. 970224092Sdougb * Note that if the result comes from a 971224092Sdougb * static-stub zone we stop the search here 972224092Sdougb * (see the function description in view.h). 973135446Strhodes */ 974135446Strhodes is_cache = ISC_TRUE; 975135446Strhodes dns_db_attach(view->cachedb, &db); 976135446Strhodes goto db_find; 977135446Strhodes } 978135446Strhodes } else { 979135446Strhodes /* 980135446Strhodes * We don't have the data in the cache. If we've got 981135446Strhodes * glue from the zone, use it. 982135446Strhodes */ 983135446Strhodes if (dns_rdataset_isassociated(&zrdataset)) { 984135446Strhodes dns_rdataset_clone(&zrdataset, rdataset); 985135446Strhodes if (sigrdataset != NULL && 986135446Strhodes dns_rdataset_isassociated(&zsigrdataset)) 987135446Strhodes dns_rdataset_clone(&zsigrdataset, 988135446Strhodes sigrdataset); 989135446Strhodes result = DNS_R_GLUE; 990135446Strhodes if (db != NULL) 991135446Strhodes dns_db_detach(&db); 992135446Strhodes dns_db_attach(zdb, &db); 993135446Strhodes dns_db_attachnode(db, znode, &node); 994135446Strhodes goto cleanup; 995135446Strhodes } 996135446Strhodes } 997135446Strhodes /* 998135446Strhodes * We don't know the answer. 999135446Strhodes */ 1000135446Strhodes result = ISC_R_NOTFOUND; 1001135446Strhodes } else if (result == DNS_R_GLUE) { 1002224092Sdougb if (view->cachedb != NULL && !is_staticstub_zone) { 1003135446Strhodes /* 1004135446Strhodes * We found an answer, but the cache may be better. 1005135446Strhodes * Remember what we've got and go look in the cache. 1006135446Strhodes */ 1007135446Strhodes is_cache = ISC_TRUE; 1008135446Strhodes dns_rdataset_clone(rdataset, &zrdataset); 1009135446Strhodes dns_rdataset_disassociate(rdataset); 1010135446Strhodes if (sigrdataset != NULL && 1011135446Strhodes dns_rdataset_isassociated(sigrdataset)) { 1012135446Strhodes dns_rdataset_clone(sigrdataset, &zsigrdataset); 1013135446Strhodes dns_rdataset_disassociate(sigrdataset); 1014135446Strhodes } 1015135446Strhodes dns_db_attach(db, &zdb); 1016135446Strhodes dns_db_attachnode(zdb, node, &znode); 1017135446Strhodes dns_db_detachnode(db, &node); 1018135446Strhodes dns_db_detach(&db); 1019135446Strhodes dns_db_attach(view->cachedb, &db); 1020135446Strhodes goto db_find; 1021135446Strhodes } 1022135446Strhodes /* 1023135446Strhodes * Otherwise, the glue is the best answer. 1024135446Strhodes */ 1025135446Strhodes result = ISC_R_SUCCESS; 1026135446Strhodes } 1027135446Strhodes 1028224092Sdougb#ifdef BIND9 1029135446Strhodes if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) { 1030135446Strhodes if (dns_rdataset_isassociated(rdataset)) 1031135446Strhodes dns_rdataset_disassociate(rdataset); 1032135446Strhodes if (sigrdataset != NULL && 1033135446Strhodes dns_rdataset_isassociated(sigrdataset)) 1034135446Strhodes dns_rdataset_disassociate(sigrdataset); 1035135446Strhodes if (db != NULL) { 1036135446Strhodes if (node != NULL) 1037135446Strhodes dns_db_detachnode(db, &node); 1038135446Strhodes dns_db_detach(&db); 1039135446Strhodes } 1040135446Strhodes result = dns_db_find(view->hints, name, NULL, type, options, 1041135446Strhodes now, &node, foundname, 1042135446Strhodes rdataset, sigrdataset); 1043135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) { 1044135446Strhodes /* 1045135446Strhodes * We just used a hint. Let the resolver know it 1046135446Strhodes * should consider priming. 1047135446Strhodes */ 1048135446Strhodes dns_resolver_prime(view->resolver); 1049135446Strhodes dns_db_attach(view->hints, &db); 1050135446Strhodes result = DNS_R_HINT; 1051135446Strhodes } else if (result == DNS_R_NXRRSET) { 1052135446Strhodes dns_db_attach(view->hints, &db); 1053135446Strhodes result = DNS_R_HINTNXRRSET; 1054135446Strhodes } else if (result == DNS_R_NXDOMAIN) 1055135446Strhodes result = ISC_R_NOTFOUND; 1056135446Strhodes 1057135446Strhodes /* 1058135446Strhodes * Cleanup if non-standard hints are used. 1059135446Strhodes */ 1060135446Strhodes if (db == NULL && node != NULL) 1061135446Strhodes dns_db_detachnode(view->hints, &node); 1062135446Strhodes } 1063224092Sdougb#endif /* BIND9 */ 1064135446Strhodes 1065135446Strhodes cleanup: 1066135446Strhodes if (dns_rdataset_isassociated(&zrdataset)) { 1067135446Strhodes dns_rdataset_disassociate(&zrdataset); 1068135446Strhodes if (dns_rdataset_isassociated(&zsigrdataset)) 1069135446Strhodes dns_rdataset_disassociate(&zsigrdataset); 1070135446Strhodes } 1071135446Strhodes 1072135446Strhodes if (zdb != NULL) { 1073135446Strhodes if (znode != NULL) 1074135446Strhodes dns_db_detachnode(zdb, &znode); 1075135446Strhodes dns_db_detach(&zdb); 1076135446Strhodes } 1077135446Strhodes 1078135446Strhodes if (db != NULL) { 1079135446Strhodes if (node != NULL) { 1080135446Strhodes if (nodep != NULL) 1081135446Strhodes *nodep = node; 1082135446Strhodes else 1083135446Strhodes dns_db_detachnode(db, &node); 1084135446Strhodes } 1085135446Strhodes if (dbp != NULL) 1086135446Strhodes *dbp = db; 1087135446Strhodes else 1088135446Strhodes dns_db_detach(&db); 1089135446Strhodes } else 1090135446Strhodes INSIST(node == NULL); 1091135446Strhodes 1092224092Sdougb#ifdef BIND9 1093135446Strhodes if (zone != NULL) 1094135446Strhodes dns_zone_detach(&zone); 1095224092Sdougb#endif 1096135446Strhodes 1097135446Strhodes return (result); 1098135446Strhodes} 1099135446Strhodes 1100135446Strhodesisc_result_t 1101135446Strhodesdns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 1102135446Strhodes isc_stdtime_t now, unsigned int options, 1103135446Strhodes isc_boolean_t use_hints, 1104135446Strhodes dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 1105135446Strhodes{ 1106135446Strhodes isc_result_t result; 1107135446Strhodes dns_fixedname_t foundname; 1108135446Strhodes 1109135446Strhodes dns_fixedname_init(&foundname); 1110135446Strhodes result = dns_view_find(view, name, type, now, options, use_hints, 1111135446Strhodes NULL, NULL, dns_fixedname_name(&foundname), 1112135446Strhodes rdataset, sigrdataset); 1113135446Strhodes if (result == DNS_R_NXDOMAIN) { 1114135446Strhodes /* 1115135446Strhodes * The rdataset and sigrdataset of the relevant NSEC record 1116135446Strhodes * may be returned, but the caller cannot use them because 1117135446Strhodes * foundname is not returned by this simplified API. We 1118135446Strhodes * disassociate them here to prevent any misuse by the caller. 1119135446Strhodes */ 1120135446Strhodes if (dns_rdataset_isassociated(rdataset)) 1121135446Strhodes dns_rdataset_disassociate(rdataset); 1122135446Strhodes if (sigrdataset != NULL && 1123135446Strhodes dns_rdataset_isassociated(sigrdataset)) 1124135446Strhodes dns_rdataset_disassociate(sigrdataset); 1125135446Strhodes } else if (result != ISC_R_SUCCESS && 1126135446Strhodes result != DNS_R_GLUE && 1127135446Strhodes result != DNS_R_HINT && 1128135446Strhodes result != DNS_R_NCACHENXDOMAIN && 1129135446Strhodes result != DNS_R_NCACHENXRRSET && 1130135446Strhodes result != DNS_R_NXRRSET && 1131135446Strhodes result != DNS_R_HINTNXRRSET && 1132135446Strhodes result != ISC_R_NOTFOUND) { 1133135446Strhodes if (dns_rdataset_isassociated(rdataset)) 1134135446Strhodes dns_rdataset_disassociate(rdataset); 1135135446Strhodes if (sigrdataset != NULL && 1136135446Strhodes dns_rdataset_isassociated(sigrdataset)) 1137135446Strhodes dns_rdataset_disassociate(sigrdataset); 1138135446Strhodes result = ISC_R_NOTFOUND; 1139135446Strhodes } 1140135446Strhodes 1141135446Strhodes return (result); 1142135446Strhodes} 1143135446Strhodes 1144135446Strhodesisc_result_t 1145135446Strhodesdns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname, 1146135446Strhodes isc_stdtime_t now, unsigned int options, 1147186462Sdougb isc_boolean_t use_hints, 1148135446Strhodes dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 1149135446Strhodes{ 1150135446Strhodes return(dns_view_findzonecut2(view, name, fname, now, options, 1151135446Strhodes use_hints, ISC_TRUE, 1152135446Strhodes rdataset, sigrdataset)); 1153135446Strhodes} 1154135446Strhodes 1155135446Strhodesisc_result_t 1156135446Strhodesdns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, 1157135446Strhodes isc_stdtime_t now, unsigned int options, 1158224092Sdougb isc_boolean_t use_hints, isc_boolean_t use_cache, 1159135446Strhodes dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 1160135446Strhodes{ 1161135446Strhodes isc_result_t result; 1162135446Strhodes dns_db_t *db; 1163224092Sdougb isc_boolean_t is_cache, use_zone, try_hints, is_staticstub_zone; 1164135446Strhodes dns_zone_t *zone; 1165135446Strhodes dns_name_t *zfname; 1166135446Strhodes dns_rdataset_t zrdataset, zsigrdataset; 1167135446Strhodes dns_fixedname_t zfixedname; 1168135446Strhodes 1169135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1170135446Strhodes REQUIRE(view->frozen); 1171135446Strhodes 1172135446Strhodes db = NULL; 1173135446Strhodes zone = NULL; 1174135446Strhodes use_zone = ISC_FALSE; 1175224092Sdougb is_staticstub_zone = ISC_FALSE; 1176135446Strhodes try_hints = ISC_FALSE; 1177135446Strhodes zfname = NULL; 1178135446Strhodes 1179135446Strhodes /* 1180135446Strhodes * Initialize. 1181135446Strhodes */ 1182135446Strhodes dns_fixedname_init(&zfixedname); 1183135446Strhodes dns_rdataset_init(&zrdataset); 1184135446Strhodes dns_rdataset_init(&zsigrdataset); 1185135446Strhodes 1186135446Strhodes /* 1187135446Strhodes * Find the right database. 1188135446Strhodes */ 1189224092Sdougb#ifdef BIND9 1190135446Strhodes result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 1191224092Sdougb if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 1192135446Strhodes result = dns_zone_getdb(zone, &db); 1193224092Sdougb if (dns_zone_gettype(zone) == dns_zone_staticstub) 1194224092Sdougb is_staticstub_zone = ISC_TRUE; 1195224092Sdougb } 1196224092Sdougb#else 1197224092Sdougb result = ISC_R_NOTFOUND; 1198224092Sdougb#endif 1199135446Strhodes if (result == ISC_R_NOTFOUND) { 1200135446Strhodes /* 1201135446Strhodes * We're not directly authoritative for this query name, nor 1202135446Strhodes * is it a subdomain of any zone for which we're 1203135446Strhodes * authoritative. 1204135446Strhodes */ 1205135446Strhodes if (use_cache && view->cachedb != NULL) { 1206135446Strhodes /* 1207135446Strhodes * We have a cache; try it. 1208135446Strhodes */ 1209135446Strhodes dns_db_attach(view->cachedb, &db); 1210135446Strhodes } else { 1211135446Strhodes /* 1212135446Strhodes * Maybe we have hints... 1213135446Strhodes */ 1214135446Strhodes try_hints = ISC_TRUE; 1215135446Strhodes goto finish; 1216135446Strhodes } 1217135446Strhodes } else if (result != ISC_R_SUCCESS) { 1218135446Strhodes /* 1219135446Strhodes * Something is broken. 1220135446Strhodes */ 1221135446Strhodes goto cleanup; 1222135446Strhodes } 1223135446Strhodes is_cache = dns_db_iscache(db); 1224135446Strhodes 1225135446Strhodes db_find: 1226135446Strhodes /* 1227135446Strhodes * Look for the zonecut. 1228135446Strhodes */ 1229135446Strhodes if (!is_cache) { 1230135446Strhodes result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options, 1231135446Strhodes now, NULL, fname, rdataset, sigrdataset); 1232135446Strhodes if (result == DNS_R_DELEGATION) 1233135446Strhodes result = ISC_R_SUCCESS; 1234135446Strhodes else if (result != ISC_R_SUCCESS) 1235135446Strhodes goto cleanup; 1236135446Strhodes if (use_cache && view->cachedb != NULL && db != view->hints) { 1237135446Strhodes /* 1238135446Strhodes * We found an answer, but the cache may be better. 1239135446Strhodes */ 1240135446Strhodes zfname = dns_fixedname_name(&zfixedname); 1241135446Strhodes result = dns_name_copy(fname, zfname, NULL); 1242135446Strhodes if (result != ISC_R_SUCCESS) 1243135446Strhodes goto cleanup; 1244135446Strhodes dns_rdataset_clone(rdataset, &zrdataset); 1245135446Strhodes dns_rdataset_disassociate(rdataset); 1246135446Strhodes if (sigrdataset != NULL && 1247135446Strhodes dns_rdataset_isassociated(sigrdataset)) { 1248135446Strhodes dns_rdataset_clone(sigrdataset, &zsigrdataset); 1249135446Strhodes dns_rdataset_disassociate(sigrdataset); 1250135446Strhodes } 1251135446Strhodes dns_db_detach(&db); 1252135446Strhodes dns_db_attach(view->cachedb, &db); 1253135446Strhodes is_cache = ISC_TRUE; 1254135446Strhodes goto db_find; 1255135446Strhodes } 1256135446Strhodes } else { 1257135446Strhodes result = dns_db_findzonecut(db, name, options, now, NULL, 1258135446Strhodes fname, rdataset, sigrdataset); 1259135446Strhodes if (result == ISC_R_SUCCESS) { 1260135446Strhodes if (zfname != NULL && 1261224092Sdougb (!dns_name_issubdomain(fname, zfname) || 1262224092Sdougb (dns_zone_staticstub && 1263224092Sdougb dns_name_equal(fname, zfname)))) { 1264135446Strhodes /* 1265135446Strhodes * We found a zonecut in the cache, but our 1266135446Strhodes * zone delegation is better. 1267135446Strhodes */ 1268135446Strhodes use_zone = ISC_TRUE; 1269135446Strhodes } 1270135446Strhodes } else if (result == ISC_R_NOTFOUND) { 1271135446Strhodes if (zfname != NULL) { 1272135446Strhodes /* 1273135446Strhodes * We didn't find anything in the cache, but we 1274135446Strhodes * have a zone delegation, so use it. 1275135446Strhodes */ 1276135446Strhodes use_zone = ISC_TRUE; 1277135446Strhodes } else { 1278135446Strhodes /* 1279135446Strhodes * Maybe we have hints... 1280135446Strhodes */ 1281135446Strhodes try_hints = ISC_TRUE; 1282135446Strhodes } 1283135446Strhodes } else { 1284135446Strhodes /* 1285135446Strhodes * Something bad happened. 1286135446Strhodes */ 1287135446Strhodes goto cleanup; 1288135446Strhodes } 1289135446Strhodes } 1290135446Strhodes 1291135446Strhodes finish: 1292135446Strhodes if (use_zone) { 1293135446Strhodes if (dns_rdataset_isassociated(rdataset)) { 1294135446Strhodes dns_rdataset_disassociate(rdataset); 1295135446Strhodes if (sigrdataset != NULL && 1296135446Strhodes dns_rdataset_isassociated(sigrdataset)) 1297135446Strhodes dns_rdataset_disassociate(sigrdataset); 1298135446Strhodes } 1299135446Strhodes result = dns_name_copy(zfname, fname, NULL); 1300135446Strhodes if (result != ISC_R_SUCCESS) 1301135446Strhodes goto cleanup; 1302135446Strhodes dns_rdataset_clone(&zrdataset, rdataset); 1303135446Strhodes if (sigrdataset != NULL && 1304135446Strhodes dns_rdataset_isassociated(&zrdataset)) 1305135446Strhodes dns_rdataset_clone(&zsigrdataset, sigrdataset); 1306135446Strhodes } else if (try_hints && use_hints && view->hints != NULL) { 1307135446Strhodes /* 1308135446Strhodes * We've found nothing so far, but we have hints. 1309135446Strhodes */ 1310135446Strhodes result = dns_db_find(view->hints, dns_rootname, NULL, 1311135446Strhodes dns_rdatatype_ns, 0, now, NULL, fname, 1312135446Strhodes rdataset, NULL); 1313135446Strhodes if (result != ISC_R_SUCCESS) { 1314135446Strhodes /* 1315135446Strhodes * We can't even find the hints for the root 1316135446Strhodes * nameservers! 1317135446Strhodes */ 1318135446Strhodes if (dns_rdataset_isassociated(rdataset)) 1319135446Strhodes dns_rdataset_disassociate(rdataset); 1320135446Strhodes result = ISC_R_NOTFOUND; 1321135446Strhodes } 1322135446Strhodes } 1323135446Strhodes 1324135446Strhodes cleanup: 1325135446Strhodes if (dns_rdataset_isassociated(&zrdataset)) { 1326135446Strhodes dns_rdataset_disassociate(&zrdataset); 1327135446Strhodes if (dns_rdataset_isassociated(&zsigrdataset)) 1328135446Strhodes dns_rdataset_disassociate(&zsigrdataset); 1329135446Strhodes } 1330135446Strhodes if (db != NULL) 1331135446Strhodes dns_db_detach(&db); 1332224092Sdougb#ifdef BIND9 1333135446Strhodes if (zone != NULL) 1334135446Strhodes dns_zone_detach(&zone); 1335224092Sdougb#endif 1336135446Strhodes 1337135446Strhodes return (result); 1338135446Strhodes} 1339135446Strhodes 1340135446Strhodesisc_result_t 1341135446Strhodesdns_viewlist_find(dns_viewlist_t *list, const char *name, 1342135446Strhodes dns_rdataclass_t rdclass, dns_view_t **viewp) 1343135446Strhodes{ 1344135446Strhodes dns_view_t *view; 1345135446Strhodes 1346135446Strhodes REQUIRE(list != NULL); 1347135446Strhodes 1348135446Strhodes for (view = ISC_LIST_HEAD(*list); 1349135446Strhodes view != NULL; 1350135446Strhodes view = ISC_LIST_NEXT(view, link)) { 1351135446Strhodes if (strcmp(view->name, name) == 0 && view->rdclass == rdclass) 1352135446Strhodes break; 1353135446Strhodes } 1354135446Strhodes if (view == NULL) 1355135446Strhodes return (ISC_R_NOTFOUND); 1356135446Strhodes 1357135446Strhodes dns_view_attach(view, viewp); 1358135446Strhodes 1359135446Strhodes return (ISC_R_SUCCESS); 1360135446Strhodes} 1361135446Strhodes 1362224092Sdougb#ifdef BIND9 1363135446Strhodesisc_result_t 1364193149Sdougbdns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, 1365193149Sdougb isc_boolean_t allclasses, dns_rdataclass_t rdclass, 1366193149Sdougb dns_zone_t **zonep) 1367193149Sdougb{ 1368193149Sdougb dns_view_t *view; 1369193149Sdougb isc_result_t result; 1370193149Sdougb dns_zone_t *zone1 = NULL, *zone2 = NULL; 1371193149Sdougb dns_zone_t **zp = NULL;; 1372193149Sdougb 1373193149Sdougb REQUIRE(list != NULL); 1374193149Sdougb for (view = ISC_LIST_HEAD(*list); 1375193149Sdougb view != NULL; 1376193149Sdougb view = ISC_LIST_NEXT(view, link)) { 1377193149Sdougb if (allclasses == ISC_FALSE && view->rdclass != rdclass) 1378193149Sdougb continue; 1379193149Sdougb 1380193149Sdougb /* 1381193149Sdougb * If the zone is defined in more than one view, 1382193149Sdougb * treat it as not found. 1383193149Sdougb */ 1384193149Sdougb zp = (zone1 == NULL) ? &zone1 : &zone2; 1385193149Sdougb result = dns_zt_find(view->zonetable, name, 0, NULL, zp); 1386193149Sdougb INSIST(result == ISC_R_SUCCESS || 1387193149Sdougb result == ISC_R_NOTFOUND || 1388193149Sdougb result == DNS_R_PARTIALMATCH); 1389193149Sdougb 1390193149Sdougb /* Treat a partial match as no match */ 1391193149Sdougb if (result == DNS_R_PARTIALMATCH) { 1392193149Sdougb dns_zone_detach(zp); 1393193149Sdougb result = ISC_R_NOTFOUND; 1394193149Sdougb } 1395193149Sdougb 1396193149Sdougb if (zone2 != NULL) { 1397193149Sdougb dns_zone_detach(&zone1); 1398193149Sdougb dns_zone_detach(&zone2); 1399193149Sdougb return (ISC_R_NOTFOUND); 1400193149Sdougb } 1401193149Sdougb } 1402193149Sdougb 1403193149Sdougb if (zone1 != NULL) { 1404193149Sdougb dns_zone_attach(zone1, zonep); 1405193149Sdougb dns_zone_detach(&zone1); 1406193149Sdougb return (ISC_R_SUCCESS); 1407193149Sdougb } 1408193149Sdougb 1409193149Sdougb return (ISC_R_NOTFOUND); 1410193149Sdougb} 1411193149Sdougb 1412193149Sdougbisc_result_t 1413135446Strhodesdns_view_load(dns_view_t *view, isc_boolean_t stop) { 1414135446Strhodes 1415135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1416135446Strhodes 1417135446Strhodes return (dns_zt_load(view->zonetable, stop)); 1418135446Strhodes} 1419135446Strhodes 1420135446Strhodesisc_result_t 1421135446Strhodesdns_view_loadnew(dns_view_t *view, isc_boolean_t stop) { 1422135446Strhodes 1423135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1424135446Strhodes 1425135446Strhodes return (dns_zt_loadnew(view->zonetable, stop)); 1426135446Strhodes} 1427224092Sdougb#endif /* BIND9 */ 1428135446Strhodes 1429135446Strhodesisc_result_t 1430135446Strhodesdns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp) 1431135446Strhodes{ 1432135446Strhodes isc_result_t result; 1433135446Strhodes REQUIRE(keyp != NULL && *keyp == NULL); 1434135446Strhodes 1435135446Strhodes result = dns_tsigkey_find(keyp, keyname, NULL, 1436135446Strhodes view->statickeys); 1437135446Strhodes if (result == ISC_R_NOTFOUND) 1438135446Strhodes result = dns_tsigkey_find(keyp, keyname, NULL, 1439135446Strhodes view->dynamickeys); 1440135446Strhodes return (result); 1441135446Strhodes} 1442135446Strhodes 1443135446Strhodesisc_result_t 1444135446Strhodesdns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr, 1445135446Strhodes dns_tsigkey_t **keyp) 1446135446Strhodes{ 1447135446Strhodes isc_result_t result; 1448135446Strhodes dns_name_t *keyname = NULL; 1449135446Strhodes dns_peer_t *peer = NULL; 1450135446Strhodes 1451135446Strhodes result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer); 1452135446Strhodes if (result != ISC_R_SUCCESS) 1453135446Strhodes return (result); 1454135446Strhodes 1455135446Strhodes result = dns_peer_getkey(peer, &keyname); 1456135446Strhodes if (result != ISC_R_SUCCESS) 1457135446Strhodes return (result); 1458135446Strhodes 1459204619Sdougb result = dns_view_gettsig(view, keyname, keyp); 1460204619Sdougb return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result); 1461135446Strhodes} 1462135446Strhodes 1463135446Strhodesisc_result_t 1464135446Strhodesdns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) { 1465135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1466135446Strhodes REQUIRE(source != NULL); 1467135446Strhodes 1468135446Strhodes return (dns_tsig_verify(source, msg, view->statickeys, 1469135446Strhodes view->dynamickeys)); 1470135446Strhodes} 1471135446Strhodes 1472224092Sdougb#ifdef BIND9 1473135446Strhodesisc_result_t 1474135446Strhodesdns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { 1475135446Strhodes isc_result_t result; 1476135446Strhodes 1477135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1478135446Strhodes 1479135446Strhodes (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name); 1480135446Strhodes result = dns_master_dumptostream(view->mctx, view->cachedb, NULL, 1481205292Sdougb &dns_master_style_cache, fp); 1482135446Strhodes if (result != ISC_R_SUCCESS) 1483135446Strhodes return (result); 1484135446Strhodes dns_adb_dump(view->adb, fp); 1485205292Sdougb dns_resolver_printbadcache(view->resolver, fp); 1486135446Strhodes return (ISC_R_SUCCESS); 1487135446Strhodes} 1488224092Sdougb#endif 1489135446Strhodes 1490135446Strhodesisc_result_t 1491135446Strhodesdns_view_flushcache(dns_view_t *view) { 1492224092Sdougb return (dns_view_flushcache2(view, ISC_FALSE)); 1493224092Sdougb} 1494224092Sdougb 1495224092Sdougbisc_result_t 1496224092Sdougbdns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) { 1497135446Strhodes isc_result_t result; 1498135446Strhodes 1499135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1500135446Strhodes 1501135446Strhodes if (view->cachedb == NULL) 1502135446Strhodes return (ISC_R_SUCCESS); 1503224092Sdougb if (!fixuponly) { 1504224092Sdougb result = dns_cache_flush(view->cache); 1505224092Sdougb if (result != ISC_R_SUCCESS) 1506224092Sdougb return (result); 1507224092Sdougb } 1508224092Sdougb#ifdef BIND9 1509170222Sdougb if (view->acache != NULL) 1510170222Sdougb dns_acache_putdb(view->acache, view->cachedb); 1511224092Sdougb#endif 1512135446Strhodes dns_db_detach(&view->cachedb); 1513135446Strhodes dns_cache_attachdb(view->cache, &view->cachedb); 1514224092Sdougb#ifdef BIND9 1515170222Sdougb if (view->acache != NULL) 1516170222Sdougb dns_acache_setdb(view->acache, view->cachedb); 1517205292Sdougb if (view->resolver != NULL) 1518205292Sdougb dns_resolver_flushbadcache(view->resolver, NULL); 1519224092Sdougb#endif 1520135446Strhodes 1521135446Strhodes dns_adb_flush(view->adb); 1522135446Strhodes return (ISC_R_SUCCESS); 1523135446Strhodes} 1524135446Strhodes 1525135446Strhodesisc_result_t 1526135446Strhodesdns_view_flushname(dns_view_t *view, dns_name_t *name) { 1527135446Strhodes 1528135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1529135446Strhodes 1530135446Strhodes if (view->adb != NULL) 1531135446Strhodes dns_adb_flushname(view->adb, name); 1532135446Strhodes if (view->cache == NULL) 1533135446Strhodes return (ISC_R_SUCCESS); 1534205292Sdougb if (view->resolver != NULL) 1535205292Sdougb dns_resolver_flushbadcache(view->resolver, name); 1536135446Strhodes return (dns_cache_flushname(view->cache, name)); 1537135446Strhodes} 1538135446Strhodes 1539135446Strhodesisc_result_t 1540135446Strhodesdns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) { 1541135446Strhodes isc_result_t result; 1542135446Strhodes dns_name_t *new; 1543135446Strhodes isc_uint32_t hash; 1544135446Strhodes 1545135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1546135446Strhodes 1547135446Strhodes if (view->delonly == NULL) { 1548135446Strhodes view->delonly = isc_mem_get(view->mctx, 1549135446Strhodes sizeof(dns_namelist_t) * 1550135446Strhodes DNS_VIEW_DELONLYHASH); 1551135446Strhodes if (view->delonly == NULL) 1552135446Strhodes return (ISC_R_NOMEMORY); 1553135446Strhodes for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) 1554135446Strhodes ISC_LIST_INIT(view->delonly[hash]); 1555135446Strhodes } 1556135446Strhodes hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1557135446Strhodes new = ISC_LIST_HEAD(view->delonly[hash]); 1558135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1559135446Strhodes new = ISC_LIST_NEXT(new, link); 1560135446Strhodes if (new != NULL) 1561135446Strhodes return (ISC_R_SUCCESS); 1562135446Strhodes new = isc_mem_get(view->mctx, sizeof(*new)); 1563135446Strhodes if (new == NULL) 1564135446Strhodes return (ISC_R_NOMEMORY); 1565135446Strhodes dns_name_init(new, NULL); 1566135446Strhodes result = dns_name_dup(name, view->mctx, new); 1567135446Strhodes if (result == ISC_R_SUCCESS) 1568135446Strhodes ISC_LIST_APPEND(view->delonly[hash], new, link); 1569135446Strhodes else 1570135446Strhodes isc_mem_put(view->mctx, new, sizeof(*new)); 1571135446Strhodes return (result); 1572135446Strhodes} 1573135446Strhodes 1574135446Strhodesisc_result_t 1575135446Strhodesdns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) { 1576135446Strhodes isc_result_t result; 1577135446Strhodes dns_name_t *new; 1578135446Strhodes isc_uint32_t hash; 1579135446Strhodes 1580135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1581135446Strhodes 1582135446Strhodes if (view->rootexclude == NULL) { 1583135446Strhodes view->rootexclude = isc_mem_get(view->mctx, 1584135446Strhodes sizeof(dns_namelist_t) * 1585135446Strhodes DNS_VIEW_DELONLYHASH); 1586135446Strhodes if (view->rootexclude == NULL) 1587135446Strhodes return (ISC_R_NOMEMORY); 1588135446Strhodes for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) 1589135446Strhodes ISC_LIST_INIT(view->rootexclude[hash]); 1590135446Strhodes } 1591135446Strhodes hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1592135446Strhodes new = ISC_LIST_HEAD(view->rootexclude[hash]); 1593135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1594135446Strhodes new = ISC_LIST_NEXT(new, link); 1595135446Strhodes if (new != NULL) 1596135446Strhodes return (ISC_R_SUCCESS); 1597135446Strhodes new = isc_mem_get(view->mctx, sizeof(*new)); 1598135446Strhodes if (new == NULL) 1599135446Strhodes return (ISC_R_NOMEMORY); 1600135446Strhodes dns_name_init(new, NULL); 1601135446Strhodes result = dns_name_dup(name, view->mctx, new); 1602135446Strhodes if (result == ISC_R_SUCCESS) 1603135446Strhodes ISC_LIST_APPEND(view->rootexclude[hash], new, link); 1604135446Strhodes else 1605135446Strhodes isc_mem_put(view->mctx, new, sizeof(*new)); 1606135446Strhodes return (result); 1607135446Strhodes} 1608135446Strhodes 1609135446Strhodesisc_boolean_t 1610135446Strhodesdns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) { 1611135446Strhodes dns_name_t *new; 1612135446Strhodes isc_uint32_t hash; 1613135446Strhodes 1614135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1615135446Strhodes 1616135446Strhodes if (!view->rootdelonly && view->delonly == NULL) 1617135446Strhodes return (ISC_FALSE); 1618135446Strhodes 1619135446Strhodes hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; 1620135446Strhodes if (view->rootdelonly && dns_name_countlabels(name) <= 2) { 1621135446Strhodes if (view->rootexclude == NULL) 1622135446Strhodes return (ISC_TRUE); 1623135446Strhodes new = ISC_LIST_HEAD(view->rootexclude[hash]); 1624135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1625135446Strhodes new = ISC_LIST_NEXT(new, link); 1626135446Strhodes if (new == NULL) 1627135446Strhodes return (ISC_TRUE); 1628135446Strhodes } 1629135446Strhodes 1630135446Strhodes if (view->delonly == NULL) 1631135446Strhodes return (ISC_FALSE); 1632135446Strhodes 1633135446Strhodes new = ISC_LIST_HEAD(view->delonly[hash]); 1634135446Strhodes while (new != NULL && !dns_name_equal(new, name)) 1635135446Strhodes new = ISC_LIST_NEXT(new, link); 1636135446Strhodes if (new == NULL) 1637135446Strhodes return (ISC_FALSE); 1638135446Strhodes return (ISC_TRUE); 1639135446Strhodes} 1640135446Strhodes 1641186462Sdougbvoid 1642135446Strhodesdns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) { 1643135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1644135446Strhodes view->rootdelonly = value; 1645135446Strhodes} 1646135446Strhodes 1647135446Strhodesisc_boolean_t 1648135446Strhodesdns_view_getrootdelonly(dns_view_t *view) { 1649135446Strhodes REQUIRE(DNS_VIEW_VALID(view)); 1650135446Strhodes return (view->rootdelonly); 1651135446Strhodes} 1652170222Sdougb 1653224092Sdougb#ifdef BIND9 1654170222Sdougbisc_result_t 1655170222Sdougbdns_view_freezezones(dns_view_t *view, isc_boolean_t value) { 1656170222Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1657170222Sdougb return (dns_zt_freezezones(view->zonetable, value)); 1658170222Sdougb} 1659224092Sdougb#endif 1660193149Sdougb 1661193149Sdougbvoid 1662193149Sdougbdns_view_setresstats(dns_view_t *view, isc_stats_t *stats) { 1663193149Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1664193149Sdougb REQUIRE(!view->frozen); 1665193149Sdougb REQUIRE(view->resstats == NULL); 1666193149Sdougb 1667193149Sdougb isc_stats_attach(stats, &view->resstats); 1668193149Sdougb} 1669193149Sdougb 1670193149Sdougbvoid 1671193149Sdougbdns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) { 1672193149Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1673193149Sdougb REQUIRE(statsp != NULL && *statsp == NULL); 1674193149Sdougb 1675193149Sdougb if (view->resstats != NULL) 1676193149Sdougb isc_stats_attach(view->resstats, statsp); 1677193149Sdougb} 1678193149Sdougb 1679193149Sdougbvoid 1680193149Sdougbdns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) { 1681193149Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1682193149Sdougb REQUIRE(!view->frozen); 1683193149Sdougb REQUIRE(view->resquerystats == NULL); 1684193149Sdougb 1685193149Sdougb dns_stats_attach(stats, &view->resquerystats); 1686193149Sdougb} 1687193149Sdougb 1688193149Sdougbvoid 1689193149Sdougbdns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) { 1690193149Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1691193149Sdougb REQUIRE(statsp != NULL && *statsp == NULL); 1692193149Sdougb 1693193149Sdougb if (view->resquerystats != NULL) 1694193149Sdougb dns_stats_attach(view->resquerystats, statsp); 1695193149Sdougb} 1696224092Sdougb 1697224092Sdougbisc_result_t 1698224092Sdougbdns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) { 1699224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1700224092Sdougb if (view->secroots_priv != NULL) 1701224092Sdougb dns_keytable_detach(&view->secroots_priv); 1702224092Sdougb return (dns_keytable_create(mctx, &view->secroots_priv)); 1703224092Sdougb} 1704224092Sdougb 1705224092Sdougbisc_result_t 1706224092Sdougbdns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) { 1707224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1708224092Sdougb REQUIRE(ktp != NULL && *ktp == NULL); 1709224092Sdougb if (view->secroots_priv == NULL) 1710224092Sdougb return (ISC_R_NOTFOUND); 1711224092Sdougb dns_keytable_attach(view->secroots_priv, ktp); 1712224092Sdougb return (ISC_R_SUCCESS); 1713224092Sdougb} 1714224092Sdougb 1715224092Sdougbisc_result_t 1716224092Sdougbdns_view_issecuredomain(dns_view_t *view, dns_name_t *name, 1717224092Sdougb isc_boolean_t *secure_domain) { 1718224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1719224092Sdougb return (dns_keytable_issecuredomain(view->secroots_priv, name, 1720224092Sdougb secure_domain)); 1721224092Sdougb} 1722224092Sdougb 1723224092Sdougbvoid 1724224092Sdougbdns_view_untrust(dns_view_t *view, dns_name_t *keyname, 1725224092Sdougb dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) 1726224092Sdougb{ 1727224092Sdougb isc_result_t result; 1728224092Sdougb unsigned char data[4096]; 1729224092Sdougb dns_rdata_t rdata = DNS_RDATA_INIT; 1730224092Sdougb isc_buffer_t buffer; 1731224092Sdougb dst_key_t *key = NULL; 1732224092Sdougb dns_keytable_t *sr = NULL; 1733224092Sdougb 1734224092Sdougb /* 1735224092Sdougb * Clear the revoke bit, if set, so that the key will match what's 1736224092Sdougb * in secroots now. 1737224092Sdougb */ 1738224092Sdougb dnskey->flags &= ~DNS_KEYFLAG_REVOKE; 1739224092Sdougb 1740224092Sdougb /* Convert dnskey to DST key. */ 1741224092Sdougb isc_buffer_init(&buffer, data, sizeof(data)); 1742224092Sdougb dns_rdata_fromstruct(&rdata, dnskey->common.rdclass, 1743224092Sdougb dns_rdatatype_dnskey, dnskey, &buffer); 1744224092Sdougb result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key); 1745224092Sdougb if (result != ISC_R_SUCCESS) 1746224092Sdougb return; 1747224092Sdougb result = dns_view_getsecroots(view, &sr); 1748224092Sdougb if (result == ISC_R_SUCCESS) { 1749224092Sdougb dns_keytable_deletekeynode(sr, key); 1750224092Sdougb dns_keytable_detach(&sr); 1751224092Sdougb } 1752224092Sdougb dst_key_free(&key); 1753224092Sdougb} 1754224092Sdougb 1755224092Sdougb#define NZF ".nzf" 1756224092Sdougb 1757224092Sdougbvoid 1758224092Sdougbdns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, 1759224092Sdougb void (*cfg_destroy)(void **)) 1760224092Sdougb{ 1761224092Sdougb REQUIRE(DNS_VIEW_VALID(view)); 1762224092Sdougb REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow); 1763224092Sdougb 1764224092Sdougb#ifdef BIND9 1765224092Sdougb if (view->new_zone_file != NULL) { 1766224092Sdougb isc_mem_free(view->mctx, view->new_zone_file); 1767224092Sdougb view->new_zone_file = NULL; 1768224092Sdougb } 1769224092Sdougb 1770224092Sdougb if (view->new_zone_config != NULL) { 1771224092Sdougb view->cfg_destroy(&view->new_zone_config); 1772224092Sdougb view->cfg_destroy = NULL; 1773224092Sdougb } 1774224092Sdougb 1775224092Sdougb if (allow) { 1776224092Sdougb char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(NZF)]; 1777224092Sdougb isc_sha256_data((void *)view->name, strlen(view->name), buffer); 1778224092Sdougb /* Truncate the hash at 16 chars; full length is overkill */ 1779224092Sdougb isc_string_printf(buffer + 16, sizeof(NZF), "%s", NZF); 1780224092Sdougb view->new_zone_file = isc_mem_strdup(view->mctx, buffer); 1781224092Sdougb view->new_zone_config = cfgctx; 1782224092Sdougb view->cfg_destroy = cfg_destroy; 1783224092Sdougb } 1784224092Sdougb#else 1785224092Sdougb UNUSED(allow); 1786224092Sdougb UNUSED(cfgctx); 1787224092Sdougb UNUSED(cfg_destroy); 1788224092Sdougb#endif 1789224092Sdougb} 1790