1135446Strhodes/* 2234010Sdougb * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2002 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * 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 18234010Sdougb/* $Id$ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24170222Sdougb#include <isc/file.h> 25135446Strhodes#include <isc/magic.h> 26135446Strhodes#include <isc/mem.h> 27170222Sdougb#include <isc/string.h> 28254897Serwin#include <isc/task.h> 29135446Strhodes#include <isc/util.h> 30135446Strhodes 31170222Sdougb#include <dns/log.h> 32170222Sdougb#include <dns/name.h> 33135446Strhodes#include <dns/rbt.h> 34170222Sdougb#include <dns/rdataclass.h> 35135446Strhodes#include <dns/result.h> 36170222Sdougb#include <dns/view.h> 37135446Strhodes#include <dns/zone.h> 38135446Strhodes#include <dns/zt.h> 39135446Strhodes 40135446Strhodesstruct dns_zt { 41135446Strhodes /* Unlocked. */ 42135446Strhodes unsigned int magic; 43135446Strhodes isc_mem_t *mctx; 44135446Strhodes dns_rdataclass_t rdclass; 45135446Strhodes isc_rwlock_t rwlock; 46254897Serwin dns_zt_allloaded_t loaddone; 47254897Serwin void * loaddone_arg; 48135446Strhodes /* Locked by lock. */ 49254897Serwin isc_boolean_t flush; 50135446Strhodes isc_uint32_t references; 51254897Serwin unsigned int loads_pending; 52135446Strhodes dns_rbt_t *table; 53135446Strhodes}; 54135446Strhodes 55135446Strhodes#define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l') 56135446Strhodes#define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC) 57135446Strhodes 58135446Strhodesstatic void 59135446Strhodesauto_detach(void *, void *); 60135446Strhodes 61135446Strhodesstatic isc_result_t 62135446Strhodesload(dns_zone_t *zone, void *uap); 63135446Strhodes 64135446Strhodesstatic isc_result_t 65254897Serwinasyncload(dns_zone_t *zone, void *callback); 66254897Serwin 67254897Serwinstatic isc_result_t 68135446Strhodesloadnew(dns_zone_t *zone, void *uap); 69135446Strhodes 70170222Sdougbstatic isc_result_t 71170222Sdougbfreezezones(dns_zone_t *zone, void *uap); 72170222Sdougb 73254897Serwinstatic isc_result_t 74254897Serwindoneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task); 75254897Serwin 76135446Strhodesisc_result_t 77193149Sdougbdns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) 78193149Sdougb{ 79135446Strhodes dns_zt_t *zt; 80135446Strhodes isc_result_t result; 81135446Strhodes 82135446Strhodes REQUIRE(ztp != NULL && *ztp == NULL); 83135446Strhodes 84135446Strhodes zt = isc_mem_get(mctx, sizeof(*zt)); 85135446Strhodes if (zt == NULL) 86135446Strhodes return (ISC_R_NOMEMORY); 87135446Strhodes 88135446Strhodes zt->table = NULL; 89135446Strhodes result = dns_rbt_create(mctx, auto_detach, zt, &zt->table); 90135446Strhodes if (result != ISC_R_SUCCESS) 91135446Strhodes goto cleanup_zt; 92135446Strhodes 93135446Strhodes result = isc_rwlock_init(&zt->rwlock, 0, 0); 94170222Sdougb if (result != ISC_R_SUCCESS) 95135446Strhodes goto cleanup_rbt; 96135446Strhodes 97254897Serwin zt->mctx = NULL; 98254897Serwin isc_mem_attach(mctx, &zt->mctx); 99135446Strhodes zt->references = 1; 100254897Serwin zt->flush = ISC_FALSE; 101135446Strhodes zt->rdclass = rdclass; 102135446Strhodes zt->magic = ZTMAGIC; 103254897Serwin zt->loaddone = NULL; 104254897Serwin zt->loaddone_arg = NULL; 105254897Serwin zt->loads_pending = 0; 106135446Strhodes *ztp = zt; 107135446Strhodes 108135446Strhodes return (ISC_R_SUCCESS); 109135446Strhodes 110135446Strhodes cleanup_rbt: 111135446Strhodes dns_rbt_destroy(&zt->table); 112135446Strhodes 113135446Strhodes cleanup_zt: 114135446Strhodes isc_mem_put(mctx, zt, sizeof(*zt)); 115135446Strhodes 116135446Strhodes return (result); 117135446Strhodes} 118135446Strhodes 119135446Strhodesisc_result_t 120135446Strhodesdns_zt_mount(dns_zt_t *zt, dns_zone_t *zone) { 121135446Strhodes isc_result_t result; 122135446Strhodes dns_zone_t *dummy = NULL; 123135446Strhodes dns_name_t *name; 124135446Strhodes 125135446Strhodes REQUIRE(VALID_ZT(zt)); 126135446Strhodes 127135446Strhodes name = dns_zone_getorigin(zone); 128135446Strhodes 129135446Strhodes RWLOCK(&zt->rwlock, isc_rwlocktype_write); 130135446Strhodes 131135446Strhodes result = dns_rbt_addname(zt->table, name, zone); 132135446Strhodes if (result == ISC_R_SUCCESS) 133135446Strhodes dns_zone_attach(zone, &dummy); 134135446Strhodes 135135446Strhodes RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); 136135446Strhodes 137135446Strhodes return (result); 138135446Strhodes} 139135446Strhodes 140135446Strhodesisc_result_t 141135446Strhodesdns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) { 142135446Strhodes isc_result_t result; 143135446Strhodes dns_name_t *name; 144135446Strhodes 145135446Strhodes REQUIRE(VALID_ZT(zt)); 146135446Strhodes 147135446Strhodes name = dns_zone_getorigin(zone); 148135446Strhodes 149135446Strhodes RWLOCK(&zt->rwlock, isc_rwlocktype_write); 150135446Strhodes 151135446Strhodes result = dns_rbt_deletename(zt->table, name, ISC_FALSE); 152135446Strhodes 153135446Strhodes RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); 154135446Strhodes 155135446Strhodes return (result); 156135446Strhodes} 157135446Strhodes 158135446Strhodesisc_result_t 159135446Strhodesdns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options, 160135446Strhodes dns_name_t *foundname, dns_zone_t **zonep) 161135446Strhodes{ 162135446Strhodes isc_result_t result; 163135446Strhodes dns_zone_t *dummy = NULL; 164135446Strhodes unsigned int rbtoptions = 0; 165135446Strhodes 166135446Strhodes REQUIRE(VALID_ZT(zt)); 167135446Strhodes 168135446Strhodes if ((options & DNS_ZTFIND_NOEXACT) != 0) 169135446Strhodes rbtoptions |= DNS_RBTFIND_NOEXACT; 170135446Strhodes 171135446Strhodes RWLOCK(&zt->rwlock, isc_rwlocktype_read); 172135446Strhodes 173135446Strhodes result = dns_rbt_findname(zt->table, name, rbtoptions, foundname, 174135446Strhodes (void **) (void*)&dummy); 175135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) 176135446Strhodes dns_zone_attach(dummy, zonep); 177135446Strhodes 178135446Strhodes RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); 179135446Strhodes 180135446Strhodes return (result); 181135446Strhodes} 182135446Strhodes 183135446Strhodesvoid 184135446Strhodesdns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp) { 185135446Strhodes 186135446Strhodes REQUIRE(VALID_ZT(zt)); 187135446Strhodes REQUIRE(ztp != NULL && *ztp == NULL); 188135446Strhodes 189135446Strhodes RWLOCK(&zt->rwlock, isc_rwlocktype_write); 190135446Strhodes 191135446Strhodes INSIST(zt->references > 0); 192135446Strhodes zt->references++; 193135446Strhodes INSIST(zt->references != 0); 194135446Strhodes 195135446Strhodes RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); 196135446Strhodes 197135446Strhodes *ztp = zt; 198135446Strhodes} 199135446Strhodes 200135446Strhodesstatic isc_result_t 201135446Strhodesflush(dns_zone_t *zone, void *uap) { 202135446Strhodes UNUSED(uap); 203135446Strhodes return (dns_zone_flush(zone)); 204135446Strhodes} 205135446Strhodes 206135446Strhodesstatic void 207254897Serwinzt_destroy(dns_zt_t *zt) { 208254897Serwin if (zt->flush) 209254897Serwin (void)dns_zt_apply(zt, ISC_FALSE, flush, NULL); 210254897Serwin dns_rbt_destroy(&zt->table); 211254897Serwin isc_rwlock_destroy(&zt->rwlock); 212254897Serwin zt->magic = 0; 213254897Serwin isc_mem_putanddetach(&zt->mctx, zt, sizeof(*zt)); 214254897Serwin} 215254897Serwin 216254897Serwinstatic void 217135446Strhodeszt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) { 218135446Strhodes isc_boolean_t destroy = ISC_FALSE; 219135446Strhodes dns_zt_t *zt; 220135446Strhodes 221135446Strhodes REQUIRE(ztp != NULL && VALID_ZT(*ztp)); 222135446Strhodes 223135446Strhodes zt = *ztp; 224135446Strhodes 225135446Strhodes RWLOCK(&zt->rwlock, isc_rwlocktype_write); 226135446Strhodes 227135446Strhodes INSIST(zt->references > 0); 228135446Strhodes zt->references--; 229135446Strhodes if (zt->references == 0) 230135446Strhodes destroy = ISC_TRUE; 231254897Serwin if (need_flush) 232254897Serwin zt->flush = ISC_TRUE; 233135446Strhodes 234135446Strhodes RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); 235135446Strhodes 236254897Serwin if (destroy) 237254897Serwin zt_destroy(zt); 238135446Strhodes 239135446Strhodes *ztp = NULL; 240135446Strhodes} 241135446Strhodes 242135446Strhodesvoid 243135446Strhodesdns_zt_flushanddetach(dns_zt_t **ztp) { 244135446Strhodes zt_flushanddetach(ztp, ISC_TRUE); 245135446Strhodes} 246135446Strhodes 247135446Strhodesvoid 248135446Strhodesdns_zt_detach(dns_zt_t **ztp) { 249135446Strhodes zt_flushanddetach(ztp, ISC_FALSE); 250135446Strhodes} 251135446Strhodes 252135446Strhodesisc_result_t 253135446Strhodesdns_zt_load(dns_zt_t *zt, isc_boolean_t stop) { 254135446Strhodes isc_result_t result; 255135446Strhodes 256135446Strhodes REQUIRE(VALID_ZT(zt)); 257135446Strhodes 258135446Strhodes RWLOCK(&zt->rwlock, isc_rwlocktype_read); 259135446Strhodes result = dns_zt_apply(zt, stop, load, NULL); 260135446Strhodes RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); 261135446Strhodes return (result); 262135446Strhodes} 263135446Strhodes 264135446Strhodesstatic isc_result_t 265135446Strhodesload(dns_zone_t *zone, void *uap) { 266135446Strhodes isc_result_t result; 267135446Strhodes UNUSED(uap); 268254897Serwin 269135446Strhodes result = dns_zone_load(zone); 270135446Strhodes if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE) 271135446Strhodes result = ISC_R_SUCCESS; 272254897Serwin 273135446Strhodes return (result); 274135446Strhodes} 275135446Strhodes 276135446Strhodesisc_result_t 277254897Serwindns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) { 278254897Serwin isc_result_t result; 279254897Serwin static dns_zt_zoneloaded_t dl = doneloading; 280254897Serwin int pending; 281254897Serwin 282254897Serwin REQUIRE(VALID_ZT(zt)); 283254897Serwin 284254897Serwin RWLOCK(&zt->rwlock, isc_rwlocktype_write); 285254897Serwin 286254897Serwin INSIST(zt->loads_pending == 0); 287254897Serwin result = dns_zt_apply2(zt, ISC_FALSE, NULL, asyncload, &dl); 288254897Serwin 289254897Serwin pending = zt->loads_pending; 290254897Serwin if (pending != 0) { 291254897Serwin zt->loaddone = alldone; 292254897Serwin zt->loaddone_arg = arg; 293254897Serwin } 294254897Serwin 295254897Serwin RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); 296254897Serwin 297254897Serwin if (pending == 0) 298254897Serwin alldone(arg); 299254897Serwin 300254897Serwin return (result); 301254897Serwin} 302254897Serwin 303254897Serwin/* 304254897Serwin * Initiates asynchronous loading of zone 'zone'. 'callback' is a 305254897Serwin * pointer to a function which will be used to inform the caller when 306254897Serwin * the zone loading is complete. 307254897Serwin */ 308254897Serwinstatic isc_result_t 309254897Serwinasyncload(dns_zone_t *zone, void *callback) { 310254897Serwin isc_result_t result; 311254897Serwin dns_zt_zoneloaded_t *loaded = callback; 312254897Serwin dns_zt_t *zt; 313254897Serwin 314254897Serwin REQUIRE(zone != NULL); 315254897Serwin zt = dns_zone_getview(zone)->zonetable; 316254897Serwin INSIST(VALID_ZT(zt)); 317254897Serwin 318254897Serwin result = dns_zone_asyncload(zone, *loaded, zt); 319254897Serwin if (result == ISC_R_SUCCESS) { 320254897Serwin INSIST(zt->references > 0); 321254897Serwin zt->references++; 322254897Serwin INSIST(zt->references != 0); 323254897Serwin zt->loads_pending++; 324254897Serwin } 325254897Serwin return (ISC_R_SUCCESS); 326254897Serwin} 327254897Serwin 328254897Serwinisc_result_t 329135446Strhodesdns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop) { 330135446Strhodes isc_result_t result; 331135446Strhodes 332135446Strhodes REQUIRE(VALID_ZT(zt)); 333135446Strhodes 334135446Strhodes RWLOCK(&zt->rwlock, isc_rwlocktype_read); 335135446Strhodes result = dns_zt_apply(zt, stop, loadnew, NULL); 336135446Strhodes RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); 337135446Strhodes return (result); 338135446Strhodes} 339135446Strhodes 340135446Strhodesstatic isc_result_t 341135446Strhodesloadnew(dns_zone_t *zone, void *uap) { 342135446Strhodes isc_result_t result; 343135446Strhodes UNUSED(uap); 344254897Serwin 345135446Strhodes result = dns_zone_loadnew(zone); 346135446Strhodes if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE || 347135446Strhodes result == DNS_R_DYNAMIC) 348135446Strhodes result = ISC_R_SUCCESS; 349135446Strhodes return (result); 350135446Strhodes} 351135446Strhodes 352135446Strhodesisc_result_t 353170222Sdougbdns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze) { 354170222Sdougb isc_result_t result, tresult; 355170222Sdougb 356170222Sdougb REQUIRE(VALID_ZT(zt)); 357170222Sdougb 358170222Sdougb RWLOCK(&zt->rwlock, isc_rwlocktype_read); 359170222Sdougb result = dns_zt_apply2(zt, ISC_FALSE, &tresult, freezezones, &freeze); 360170222Sdougb RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); 361254897Serwin if (tresult == ISC_R_NOTFOUND) 362254897Serwin tresult = ISC_R_SUCCESS; 363170222Sdougb return ((result == ISC_R_SUCCESS) ? tresult : result); 364170222Sdougb} 365170222Sdougb 366170222Sdougbstatic isc_result_t 367170222Sdougbfreezezones(dns_zone_t *zone, void *uap) { 368170222Sdougb isc_boolean_t freeze = *(isc_boolean_t *)uap; 369170222Sdougb isc_boolean_t frozen; 370170222Sdougb isc_result_t result = ISC_R_SUCCESS; 371170222Sdougb char classstr[DNS_RDATACLASS_FORMATSIZE]; 372170222Sdougb char zonename[DNS_NAME_FORMATSIZE]; 373254897Serwin dns_zone_t *raw = NULL; 374170222Sdougb dns_view_t *view; 375170222Sdougb const char *vname; 376170222Sdougb const char *sep; 377170222Sdougb int level; 378170222Sdougb 379254897Serwin dns_zone_getraw(zone, &raw); 380254897Serwin if (raw != NULL) 381254897Serwin zone = raw; 382254897Serwin if (dns_zone_gettype(zone) != dns_zone_master) { 383254897Serwin if (raw != NULL) 384254897Serwin dns_zone_detach(&raw); 385170222Sdougb return (ISC_R_SUCCESS); 386254897Serwin } 387254897Serwin if (!dns_zone_isdynamic(zone, ISC_TRUE)) { 388254897Serwin if (raw != NULL) 389254897Serwin dns_zone_detach(&raw); 390254897Serwin return (ISC_R_SUCCESS); 391254897Serwin } 392170222Sdougb 393170222Sdougb frozen = dns_zone_getupdatedisabled(zone); 394170222Sdougb if (freeze) { 395170222Sdougb if (frozen) 396170222Sdougb result = DNS_R_FROZEN; 397170222Sdougb if (result == ISC_R_SUCCESS) 398170222Sdougb result = dns_zone_flush(zone); 399170222Sdougb } else { 400170222Sdougb if (frozen) { 401170222Sdougb result = dns_zone_load(zone); 402170222Sdougb if (result == DNS_R_CONTINUE || 403170222Sdougb result == DNS_R_UPTODATE) 404170222Sdougb result = ISC_R_SUCCESS; 405170222Sdougb } 406170222Sdougb } 407170222Sdougb if (result == ISC_R_SUCCESS) 408170222Sdougb dns_zone_setupdatedisabled(zone, freeze); 409170222Sdougb view = dns_zone_getview(zone); 410170222Sdougb if (strcmp(view->name, "_bind") == 0 || 411170222Sdougb strcmp(view->name, "_default") == 0) 412170222Sdougb { 413170222Sdougb vname = ""; 414170222Sdougb sep = ""; 415170222Sdougb } else { 416170222Sdougb vname = view->name; 417170222Sdougb sep = " "; 418170222Sdougb } 419170222Sdougb dns_rdataclass_format(dns_zone_getclass(zone), classstr, 420170222Sdougb sizeof(classstr)); 421170222Sdougb dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 422170222Sdougb level = (result != ISC_R_SUCCESS) ? ISC_LOG_ERROR : ISC_LOG_DEBUG(1); 423170222Sdougb isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, 424170222Sdougb level, "%s zone '%s/%s'%s%s: %s", 425170222Sdougb freeze ? "freezing" : "thawing", 426170222Sdougb zonename, classstr, sep, vname, 427170222Sdougb isc_result_totext(result)); 428254897Serwin if (raw != NULL) 429254897Serwin dns_zone_detach(&raw); 430170222Sdougb return (result); 431170222Sdougb} 432170222Sdougb 433170222Sdougbisc_result_t 434135446Strhodesdns_zt_apply(dns_zt_t *zt, isc_boolean_t stop, 435135446Strhodes isc_result_t (*action)(dns_zone_t *, void *), void *uap) 436135446Strhodes{ 437170222Sdougb return (dns_zt_apply2(zt, stop, NULL, action, uap)); 438170222Sdougb} 439170222Sdougb 440170222Sdougbisc_result_t 441170222Sdougbdns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub, 442170222Sdougb isc_result_t (*action)(dns_zone_t *, void *), void *uap) 443170222Sdougb{ 444135446Strhodes dns_rbtnode_t *node; 445135446Strhodes dns_rbtnodechain_t chain; 446170222Sdougb isc_result_t result, tresult = ISC_R_SUCCESS; 447135446Strhodes dns_zone_t *zone; 448135446Strhodes 449135446Strhodes REQUIRE(VALID_ZT(zt)); 450135446Strhodes REQUIRE(action != NULL); 451135446Strhodes 452135446Strhodes dns_rbtnodechain_init(&chain, zt->mctx); 453135446Strhodes result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL); 454135446Strhodes if (result == ISC_R_NOTFOUND) { 455135446Strhodes /* 456135446Strhodes * The tree is empty. 457135446Strhodes */ 458254897Serwin tresult = result; 459135446Strhodes result = ISC_R_NOMORE; 460135446Strhodes } 461135446Strhodes while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) { 462135446Strhodes result = dns_rbtnodechain_current(&chain, NULL, NULL, 463135446Strhodes &node); 464135446Strhodes if (result == ISC_R_SUCCESS) { 465135446Strhodes zone = node->data; 466135446Strhodes if (zone != NULL) 467135446Strhodes result = (action)(zone, uap); 468170222Sdougb if (result != ISC_R_SUCCESS && stop) { 469170222Sdougb tresult = result; 470135446Strhodes goto cleanup; /* don't break */ 471170222Sdougb } else if (result != ISC_R_SUCCESS && 472170222Sdougb tresult == ISC_R_SUCCESS) 473170222Sdougb tresult = result; 474135446Strhodes } 475135446Strhodes result = dns_rbtnodechain_next(&chain, NULL, NULL); 476135446Strhodes } 477135446Strhodes if (result == ISC_R_NOMORE) 478135446Strhodes result = ISC_R_SUCCESS; 479135446Strhodes 480135446Strhodes cleanup: 481135446Strhodes dns_rbtnodechain_invalidate(&chain); 482170222Sdougb if (sub != NULL) 483170222Sdougb *sub = tresult; 484135446Strhodes 485135446Strhodes return (result); 486135446Strhodes} 487135446Strhodes 488254897Serwin/* 489254897Serwin * Decrement the loads_pending counter; when counter reaches 490254897Serwin * zero, call the loaddone callback that was initially set by 491254897Serwin * dns_zt_asyncload(). 492254897Serwin */ 493254897Serwinstatic isc_result_t 494254897Serwindoneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) { 495254897Serwin isc_boolean_t destroy = ISC_FALSE; 496254897Serwin dns_zt_allloaded_t alldone = NULL; 497254897Serwin void *arg = NULL; 498254897Serwin 499254897Serwin UNUSED(zone); 500254897Serwin UNUSED(task); 501254897Serwin 502254897Serwin REQUIRE(VALID_ZT(zt)); 503254897Serwin 504254897Serwin RWLOCK(&zt->rwlock, isc_rwlocktype_write); 505254897Serwin INSIST(zt->loads_pending != 0); 506254897Serwin INSIST(zt->references != 0); 507254897Serwin zt->references--; 508254897Serwin if (zt->references == 0) 509254897Serwin destroy = ISC_TRUE; 510254897Serwin zt->loads_pending--; 511254897Serwin if (zt->loads_pending == 0) { 512254897Serwin alldone = zt->loaddone; 513254897Serwin arg = zt->loaddone_arg; 514254897Serwin zt->loaddone = NULL; 515254897Serwin zt->loaddone_arg = NULL; 516254897Serwin } 517254897Serwin RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); 518254897Serwin 519254897Serwin if (alldone != NULL) 520254897Serwin alldone(arg); 521254897Serwin 522254897Serwin if (destroy) 523254897Serwin zt_destroy(zt); 524254897Serwin 525254897Serwin return (ISC_R_SUCCESS); 526254897Serwin} 527254897Serwin 528135446Strhodes/*** 529135446Strhodes *** Private 530135446Strhodes ***/ 531135446Strhodes 532135446Strhodesstatic void 533135446Strhodesauto_detach(void *data, void *arg) { 534135446Strhodes dns_zone_t *zone = data; 535135446Strhodes 536135446Strhodes UNUSED(arg); 537135446Strhodes 538135446Strhodes dns_zone_detach(&zone); 539135446Strhodes} 540