1*00b67f09SDavid van Moolenbroek /* $NetBSD: zt.c,v 1.8 2015/07/08 17:28:59 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004-2007, 2011-2015 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 1999-2002 Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek *
7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek *
11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek */
19*00b67f09SDavid van Moolenbroek
20*00b67f09SDavid van Moolenbroek /* Id */
21*00b67f09SDavid van Moolenbroek
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek
26*00b67f09SDavid van Moolenbroek #include <isc/file.h>
27*00b67f09SDavid van Moolenbroek #include <isc/magic.h>
28*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
29*00b67f09SDavid van Moolenbroek #include <isc/string.h>
30*00b67f09SDavid van Moolenbroek #include <isc/task.h>
31*00b67f09SDavid van Moolenbroek #include <isc/util.h>
32*00b67f09SDavid van Moolenbroek
33*00b67f09SDavid van Moolenbroek #include <dns/log.h>
34*00b67f09SDavid van Moolenbroek #include <dns/name.h>
35*00b67f09SDavid van Moolenbroek #include <dns/rbt.h>
36*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
37*00b67f09SDavid van Moolenbroek #include <dns/result.h>
38*00b67f09SDavid van Moolenbroek #include <dns/view.h>
39*00b67f09SDavid van Moolenbroek #include <dns/zone.h>
40*00b67f09SDavid van Moolenbroek #include <dns/zt.h>
41*00b67f09SDavid van Moolenbroek
42*00b67f09SDavid van Moolenbroek struct dns_zt {
43*00b67f09SDavid van Moolenbroek /* Unlocked. */
44*00b67f09SDavid van Moolenbroek unsigned int magic;
45*00b67f09SDavid van Moolenbroek isc_mem_t *mctx;
46*00b67f09SDavid van Moolenbroek dns_rdataclass_t rdclass;
47*00b67f09SDavid van Moolenbroek isc_rwlock_t rwlock;
48*00b67f09SDavid van Moolenbroek dns_zt_allloaded_t loaddone;
49*00b67f09SDavid van Moolenbroek void * loaddone_arg;
50*00b67f09SDavid van Moolenbroek /* Locked by lock. */
51*00b67f09SDavid van Moolenbroek isc_boolean_t flush;
52*00b67f09SDavid van Moolenbroek isc_uint32_t references;
53*00b67f09SDavid van Moolenbroek unsigned int loads_pending;
54*00b67f09SDavid van Moolenbroek dns_rbt_t *table;
55*00b67f09SDavid van Moolenbroek };
56*00b67f09SDavid van Moolenbroek
57*00b67f09SDavid van Moolenbroek #define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l')
58*00b67f09SDavid van Moolenbroek #define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC)
59*00b67f09SDavid van Moolenbroek
60*00b67f09SDavid van Moolenbroek static void
61*00b67f09SDavid van Moolenbroek auto_detach(void *, void *);
62*00b67f09SDavid van Moolenbroek
63*00b67f09SDavid van Moolenbroek static isc_result_t
64*00b67f09SDavid van Moolenbroek load(dns_zone_t *zone, void *uap);
65*00b67f09SDavid van Moolenbroek
66*00b67f09SDavid van Moolenbroek static isc_result_t
67*00b67f09SDavid van Moolenbroek asyncload(dns_zone_t *zone, void *callback);
68*00b67f09SDavid van Moolenbroek
69*00b67f09SDavid van Moolenbroek static isc_result_t
70*00b67f09SDavid van Moolenbroek loadnew(dns_zone_t *zone, void *uap);
71*00b67f09SDavid van Moolenbroek
72*00b67f09SDavid van Moolenbroek static isc_result_t
73*00b67f09SDavid van Moolenbroek freezezones(dns_zone_t *zone, void *uap);
74*00b67f09SDavid van Moolenbroek
75*00b67f09SDavid van Moolenbroek static isc_result_t
76*00b67f09SDavid van Moolenbroek doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task);
77*00b67f09SDavid van Moolenbroek
78*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_create(isc_mem_t * mctx,dns_rdataclass_t rdclass,dns_zt_t ** ztp)79*00b67f09SDavid van Moolenbroek dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) {
80*00b67f09SDavid van Moolenbroek dns_zt_t *zt;
81*00b67f09SDavid van Moolenbroek isc_result_t result;
82*00b67f09SDavid van Moolenbroek
83*00b67f09SDavid van Moolenbroek REQUIRE(ztp != NULL && *ztp == NULL);
84*00b67f09SDavid van Moolenbroek
85*00b67f09SDavid van Moolenbroek zt = isc_mem_get(mctx, sizeof(*zt));
86*00b67f09SDavid van Moolenbroek if (zt == NULL)
87*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
88*00b67f09SDavid van Moolenbroek
89*00b67f09SDavid van Moolenbroek zt->table = NULL;
90*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, auto_detach, zt, &zt->table);
91*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
92*00b67f09SDavid van Moolenbroek goto cleanup_zt;
93*00b67f09SDavid van Moolenbroek
94*00b67f09SDavid van Moolenbroek result = isc_rwlock_init(&zt->rwlock, 0, 0);
95*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
96*00b67f09SDavid van Moolenbroek goto cleanup_rbt;
97*00b67f09SDavid van Moolenbroek
98*00b67f09SDavid van Moolenbroek zt->mctx = NULL;
99*00b67f09SDavid van Moolenbroek isc_mem_attach(mctx, &zt->mctx);
100*00b67f09SDavid van Moolenbroek zt->references = 1;
101*00b67f09SDavid van Moolenbroek zt->flush = ISC_FALSE;
102*00b67f09SDavid van Moolenbroek zt->rdclass = rdclass;
103*00b67f09SDavid van Moolenbroek zt->magic = ZTMAGIC;
104*00b67f09SDavid van Moolenbroek zt->loaddone = NULL;
105*00b67f09SDavid van Moolenbroek zt->loaddone_arg = NULL;
106*00b67f09SDavid van Moolenbroek zt->loads_pending = 0;
107*00b67f09SDavid van Moolenbroek *ztp = zt;
108*00b67f09SDavid van Moolenbroek
109*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
110*00b67f09SDavid van Moolenbroek
111*00b67f09SDavid van Moolenbroek cleanup_rbt:
112*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&zt->table);
113*00b67f09SDavid van Moolenbroek
114*00b67f09SDavid van Moolenbroek cleanup_zt:
115*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, zt, sizeof(*zt));
116*00b67f09SDavid van Moolenbroek
117*00b67f09SDavid van Moolenbroek return (result);
118*00b67f09SDavid van Moolenbroek }
119*00b67f09SDavid van Moolenbroek
120*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_mount(dns_zt_t * zt,dns_zone_t * zone)121*00b67f09SDavid van Moolenbroek dns_zt_mount(dns_zt_t *zt, dns_zone_t *zone) {
122*00b67f09SDavid van Moolenbroek isc_result_t result;
123*00b67f09SDavid van Moolenbroek dns_zone_t *dummy = NULL;
124*00b67f09SDavid van Moolenbroek dns_name_t *name;
125*00b67f09SDavid van Moolenbroek
126*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
127*00b67f09SDavid van Moolenbroek
128*00b67f09SDavid van Moolenbroek name = dns_zone_getorigin(zone);
129*00b67f09SDavid van Moolenbroek
130*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_write);
131*00b67f09SDavid van Moolenbroek
132*00b67f09SDavid van Moolenbroek result = dns_rbt_addname(zt->table, name, zone);
133*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
134*00b67f09SDavid van Moolenbroek dns_zone_attach(zone, &dummy);
135*00b67f09SDavid van Moolenbroek
136*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
137*00b67f09SDavid van Moolenbroek
138*00b67f09SDavid van Moolenbroek return (result);
139*00b67f09SDavid van Moolenbroek }
140*00b67f09SDavid van Moolenbroek
141*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_unmount(dns_zt_t * zt,dns_zone_t * zone)142*00b67f09SDavid van Moolenbroek dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
143*00b67f09SDavid van Moolenbroek isc_result_t result;
144*00b67f09SDavid van Moolenbroek dns_name_t *name;
145*00b67f09SDavid van Moolenbroek
146*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
147*00b67f09SDavid van Moolenbroek
148*00b67f09SDavid van Moolenbroek name = dns_zone_getorigin(zone);
149*00b67f09SDavid van Moolenbroek
150*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_write);
151*00b67f09SDavid van Moolenbroek
152*00b67f09SDavid van Moolenbroek result = dns_rbt_deletename(zt->table, name, ISC_FALSE);
153*00b67f09SDavid van Moolenbroek
154*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
155*00b67f09SDavid van Moolenbroek
156*00b67f09SDavid van Moolenbroek return (result);
157*00b67f09SDavid van Moolenbroek }
158*00b67f09SDavid van Moolenbroek
159*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_find(dns_zt_t * zt,dns_name_t * name,unsigned int options,dns_name_t * foundname,dns_zone_t ** zonep)160*00b67f09SDavid van Moolenbroek dns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options,
161*00b67f09SDavid van Moolenbroek dns_name_t *foundname, dns_zone_t **zonep)
162*00b67f09SDavid van Moolenbroek {
163*00b67f09SDavid van Moolenbroek isc_result_t result;
164*00b67f09SDavid van Moolenbroek dns_zone_t *dummy = NULL;
165*00b67f09SDavid van Moolenbroek unsigned int rbtoptions = 0;
166*00b67f09SDavid van Moolenbroek
167*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
168*00b67f09SDavid van Moolenbroek
169*00b67f09SDavid van Moolenbroek if ((options & DNS_ZTFIND_NOEXACT) != 0)
170*00b67f09SDavid van Moolenbroek rbtoptions |= DNS_RBTFIND_NOEXACT;
171*00b67f09SDavid van Moolenbroek
172*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_read);
173*00b67f09SDavid van Moolenbroek
174*00b67f09SDavid van Moolenbroek result = dns_rbt_findname(zt->table, name, rbtoptions, foundname,
175*00b67f09SDavid van Moolenbroek (void **) (void*)&dummy);
176*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
177*00b67f09SDavid van Moolenbroek dns_zone_attach(dummy, zonep);
178*00b67f09SDavid van Moolenbroek
179*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
180*00b67f09SDavid van Moolenbroek
181*00b67f09SDavid van Moolenbroek return (result);
182*00b67f09SDavid van Moolenbroek }
183*00b67f09SDavid van Moolenbroek
184*00b67f09SDavid van Moolenbroek void
dns_zt_attach(dns_zt_t * zt,dns_zt_t ** ztp)185*00b67f09SDavid van Moolenbroek dns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp) {
186*00b67f09SDavid van Moolenbroek
187*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
188*00b67f09SDavid van Moolenbroek REQUIRE(ztp != NULL && *ztp == NULL);
189*00b67f09SDavid van Moolenbroek
190*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_write);
191*00b67f09SDavid van Moolenbroek
192*00b67f09SDavid van Moolenbroek INSIST(zt->references > 0);
193*00b67f09SDavid van Moolenbroek zt->references++;
194*00b67f09SDavid van Moolenbroek INSIST(zt->references != 0);
195*00b67f09SDavid van Moolenbroek
196*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
197*00b67f09SDavid van Moolenbroek
198*00b67f09SDavid van Moolenbroek *ztp = zt;
199*00b67f09SDavid van Moolenbroek }
200*00b67f09SDavid van Moolenbroek
201*00b67f09SDavid van Moolenbroek static isc_result_t
flush(dns_zone_t * zone,void * uap)202*00b67f09SDavid van Moolenbroek flush(dns_zone_t *zone, void *uap) {
203*00b67f09SDavid van Moolenbroek UNUSED(uap);
204*00b67f09SDavid van Moolenbroek return (dns_zone_flush(zone));
205*00b67f09SDavid van Moolenbroek }
206*00b67f09SDavid van Moolenbroek
207*00b67f09SDavid van Moolenbroek static void
zt_destroy(dns_zt_t * zt)208*00b67f09SDavid van Moolenbroek zt_destroy(dns_zt_t *zt) {
209*00b67f09SDavid van Moolenbroek if (zt->flush)
210*00b67f09SDavid van Moolenbroek (void)dns_zt_apply(zt, ISC_FALSE, flush, NULL);
211*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&zt->table);
212*00b67f09SDavid van Moolenbroek isc_rwlock_destroy(&zt->rwlock);
213*00b67f09SDavid van Moolenbroek zt->magic = 0;
214*00b67f09SDavid van Moolenbroek isc_mem_putanddetach(&zt->mctx, zt, sizeof(*zt));
215*00b67f09SDavid van Moolenbroek }
216*00b67f09SDavid van Moolenbroek
217*00b67f09SDavid van Moolenbroek static void
zt_flushanddetach(dns_zt_t ** ztp,isc_boolean_t need_flush)218*00b67f09SDavid van Moolenbroek zt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) {
219*00b67f09SDavid van Moolenbroek isc_boolean_t destroy = ISC_FALSE;
220*00b67f09SDavid van Moolenbroek dns_zt_t *zt;
221*00b67f09SDavid van Moolenbroek
222*00b67f09SDavid van Moolenbroek REQUIRE(ztp != NULL && VALID_ZT(*ztp));
223*00b67f09SDavid van Moolenbroek
224*00b67f09SDavid van Moolenbroek zt = *ztp;
225*00b67f09SDavid van Moolenbroek
226*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_write);
227*00b67f09SDavid van Moolenbroek
228*00b67f09SDavid van Moolenbroek INSIST(zt->references > 0);
229*00b67f09SDavid van Moolenbroek zt->references--;
230*00b67f09SDavid van Moolenbroek if (zt->references == 0)
231*00b67f09SDavid van Moolenbroek destroy = ISC_TRUE;
232*00b67f09SDavid van Moolenbroek if (need_flush)
233*00b67f09SDavid van Moolenbroek zt->flush = ISC_TRUE;
234*00b67f09SDavid van Moolenbroek
235*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
236*00b67f09SDavid van Moolenbroek
237*00b67f09SDavid van Moolenbroek if (destroy)
238*00b67f09SDavid van Moolenbroek zt_destroy(zt);
239*00b67f09SDavid van Moolenbroek
240*00b67f09SDavid van Moolenbroek *ztp = NULL;
241*00b67f09SDavid van Moolenbroek }
242*00b67f09SDavid van Moolenbroek
243*00b67f09SDavid van Moolenbroek void
dns_zt_flushanddetach(dns_zt_t ** ztp)244*00b67f09SDavid van Moolenbroek dns_zt_flushanddetach(dns_zt_t **ztp) {
245*00b67f09SDavid van Moolenbroek zt_flushanddetach(ztp, ISC_TRUE);
246*00b67f09SDavid van Moolenbroek }
247*00b67f09SDavid van Moolenbroek
248*00b67f09SDavid van Moolenbroek void
dns_zt_detach(dns_zt_t ** ztp)249*00b67f09SDavid van Moolenbroek dns_zt_detach(dns_zt_t **ztp) {
250*00b67f09SDavid van Moolenbroek zt_flushanddetach(ztp, ISC_FALSE);
251*00b67f09SDavid van Moolenbroek }
252*00b67f09SDavid van Moolenbroek
253*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_load(dns_zt_t * zt,isc_boolean_t stop)254*00b67f09SDavid van Moolenbroek dns_zt_load(dns_zt_t *zt, isc_boolean_t stop) {
255*00b67f09SDavid van Moolenbroek isc_result_t result;
256*00b67f09SDavid van Moolenbroek
257*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
258*00b67f09SDavid van Moolenbroek
259*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_read);
260*00b67f09SDavid van Moolenbroek result = dns_zt_apply(zt, stop, load, NULL);
261*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
262*00b67f09SDavid van Moolenbroek return (result);
263*00b67f09SDavid van Moolenbroek }
264*00b67f09SDavid van Moolenbroek
265*00b67f09SDavid van Moolenbroek static isc_result_t
load(dns_zone_t * zone,void * uap)266*00b67f09SDavid van Moolenbroek load(dns_zone_t *zone, void *uap) {
267*00b67f09SDavid van Moolenbroek isc_result_t result;
268*00b67f09SDavid van Moolenbroek UNUSED(uap);
269*00b67f09SDavid van Moolenbroek
270*00b67f09SDavid van Moolenbroek result = dns_zone_load(zone);
271*00b67f09SDavid van Moolenbroek if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE)
272*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
273*00b67f09SDavid van Moolenbroek
274*00b67f09SDavid van Moolenbroek return (result);
275*00b67f09SDavid van Moolenbroek }
276*00b67f09SDavid van Moolenbroek
277*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_asyncload(dns_zt_t * zt,dns_zt_allloaded_t alldone,void * arg)278*00b67f09SDavid van Moolenbroek dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) {
279*00b67f09SDavid van Moolenbroek isc_result_t result;
280*00b67f09SDavid van Moolenbroek static dns_zt_zoneloaded_t dl = doneloading;
281*00b67f09SDavid van Moolenbroek int pending;
282*00b67f09SDavid van Moolenbroek
283*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
284*00b67f09SDavid van Moolenbroek
285*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_write);
286*00b67f09SDavid van Moolenbroek
287*00b67f09SDavid van Moolenbroek INSIST(zt->loads_pending == 0);
288*00b67f09SDavid van Moolenbroek result = dns_zt_apply2(zt, ISC_FALSE, NULL, asyncload, &dl);
289*00b67f09SDavid van Moolenbroek
290*00b67f09SDavid van Moolenbroek pending = zt->loads_pending;
291*00b67f09SDavid van Moolenbroek if (pending != 0) {
292*00b67f09SDavid van Moolenbroek zt->loaddone = alldone;
293*00b67f09SDavid van Moolenbroek zt->loaddone_arg = arg;
294*00b67f09SDavid van Moolenbroek }
295*00b67f09SDavid van Moolenbroek
296*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
297*00b67f09SDavid van Moolenbroek
298*00b67f09SDavid van Moolenbroek if (pending == 0)
299*00b67f09SDavid van Moolenbroek alldone(arg);
300*00b67f09SDavid van Moolenbroek
301*00b67f09SDavid van Moolenbroek return (result);
302*00b67f09SDavid van Moolenbroek }
303*00b67f09SDavid van Moolenbroek
304*00b67f09SDavid van Moolenbroek /*
305*00b67f09SDavid van Moolenbroek * Initiates asynchronous loading of zone 'zone'. 'callback' is a
306*00b67f09SDavid van Moolenbroek * pointer to a function which will be used to inform the caller when
307*00b67f09SDavid van Moolenbroek * the zone loading is complete.
308*00b67f09SDavid van Moolenbroek */
309*00b67f09SDavid van Moolenbroek static isc_result_t
asyncload(dns_zone_t * zone,void * callback)310*00b67f09SDavid van Moolenbroek asyncload(dns_zone_t *zone, void *callback) {
311*00b67f09SDavid van Moolenbroek isc_result_t result;
312*00b67f09SDavid van Moolenbroek dns_zt_zoneloaded_t *loaded = callback;
313*00b67f09SDavid van Moolenbroek dns_zt_t *zt;
314*00b67f09SDavid van Moolenbroek
315*00b67f09SDavid van Moolenbroek REQUIRE(zone != NULL);
316*00b67f09SDavid van Moolenbroek zt = dns_zone_getview(zone)->zonetable;
317*00b67f09SDavid van Moolenbroek INSIST(VALID_ZT(zt));
318*00b67f09SDavid van Moolenbroek
319*00b67f09SDavid van Moolenbroek INSIST(zt->references > 0);
320*00b67f09SDavid van Moolenbroek zt->references++;
321*00b67f09SDavid van Moolenbroek zt->loads_pending++;
322*00b67f09SDavid van Moolenbroek
323*00b67f09SDavid van Moolenbroek result = dns_zone_asyncload(zone, *loaded, zt);
324*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
325*00b67f09SDavid van Moolenbroek zt->references--;
326*00b67f09SDavid van Moolenbroek zt->loads_pending--;
327*00b67f09SDavid van Moolenbroek INSIST(zt->references > 0);
328*00b67f09SDavid van Moolenbroek }
329*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
330*00b67f09SDavid van Moolenbroek }
331*00b67f09SDavid van Moolenbroek
332*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_loadnew(dns_zt_t * zt,isc_boolean_t stop)333*00b67f09SDavid van Moolenbroek dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop) {
334*00b67f09SDavid van Moolenbroek isc_result_t result;
335*00b67f09SDavid van Moolenbroek
336*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
337*00b67f09SDavid van Moolenbroek
338*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_read);
339*00b67f09SDavid van Moolenbroek result = dns_zt_apply(zt, stop, loadnew, NULL);
340*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
341*00b67f09SDavid van Moolenbroek return (result);
342*00b67f09SDavid van Moolenbroek }
343*00b67f09SDavid van Moolenbroek
344*00b67f09SDavid van Moolenbroek static isc_result_t
loadnew(dns_zone_t * zone,void * uap)345*00b67f09SDavid van Moolenbroek loadnew(dns_zone_t *zone, void *uap) {
346*00b67f09SDavid van Moolenbroek isc_result_t result;
347*00b67f09SDavid van Moolenbroek UNUSED(uap);
348*00b67f09SDavid van Moolenbroek
349*00b67f09SDavid van Moolenbroek result = dns_zone_loadnew(zone);
350*00b67f09SDavid van Moolenbroek if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE ||
351*00b67f09SDavid van Moolenbroek result == DNS_R_DYNAMIC)
352*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
353*00b67f09SDavid van Moolenbroek return (result);
354*00b67f09SDavid van Moolenbroek }
355*00b67f09SDavid van Moolenbroek
356*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_freezezones(dns_zt_t * zt,isc_boolean_t freeze)357*00b67f09SDavid van Moolenbroek dns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze) {
358*00b67f09SDavid van Moolenbroek isc_result_t result, tresult;
359*00b67f09SDavid van Moolenbroek
360*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
361*00b67f09SDavid van Moolenbroek
362*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_read);
363*00b67f09SDavid van Moolenbroek result = dns_zt_apply2(zt, ISC_FALSE, &tresult, freezezones, &freeze);
364*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
365*00b67f09SDavid van Moolenbroek if (tresult == ISC_R_NOTFOUND)
366*00b67f09SDavid van Moolenbroek tresult = ISC_R_SUCCESS;
367*00b67f09SDavid van Moolenbroek return ((result == ISC_R_SUCCESS) ? tresult : result);
368*00b67f09SDavid van Moolenbroek }
369*00b67f09SDavid van Moolenbroek
370*00b67f09SDavid van Moolenbroek static isc_result_t
freezezones(dns_zone_t * zone,void * uap)371*00b67f09SDavid van Moolenbroek freezezones(dns_zone_t *zone, void *uap) {
372*00b67f09SDavid van Moolenbroek isc_boolean_t freeze = *(isc_boolean_t *)uap;
373*00b67f09SDavid van Moolenbroek isc_boolean_t frozen;
374*00b67f09SDavid van Moolenbroek isc_result_t result = ISC_R_SUCCESS;
375*00b67f09SDavid van Moolenbroek char classstr[DNS_RDATACLASS_FORMATSIZE];
376*00b67f09SDavid van Moolenbroek char zonename[DNS_NAME_FORMATSIZE];
377*00b67f09SDavid van Moolenbroek dns_zone_t *raw = NULL;
378*00b67f09SDavid van Moolenbroek dns_view_t *view;
379*00b67f09SDavid van Moolenbroek const char *vname;
380*00b67f09SDavid van Moolenbroek const char *sep;
381*00b67f09SDavid van Moolenbroek int level;
382*00b67f09SDavid van Moolenbroek
383*00b67f09SDavid van Moolenbroek dns_zone_getraw(zone, &raw);
384*00b67f09SDavid van Moolenbroek if (raw != NULL)
385*00b67f09SDavid van Moolenbroek zone = raw;
386*00b67f09SDavid van Moolenbroek if (dns_zone_gettype(zone) != dns_zone_master) {
387*00b67f09SDavid van Moolenbroek if (raw != NULL)
388*00b67f09SDavid van Moolenbroek dns_zone_detach(&raw);
389*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
390*00b67f09SDavid van Moolenbroek }
391*00b67f09SDavid van Moolenbroek if (!dns_zone_isdynamic(zone, ISC_TRUE)) {
392*00b67f09SDavid van Moolenbroek if (raw != NULL)
393*00b67f09SDavid van Moolenbroek dns_zone_detach(&raw);
394*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
395*00b67f09SDavid van Moolenbroek }
396*00b67f09SDavid van Moolenbroek
397*00b67f09SDavid van Moolenbroek frozen = dns_zone_getupdatedisabled(zone);
398*00b67f09SDavid van Moolenbroek if (freeze) {
399*00b67f09SDavid van Moolenbroek if (frozen)
400*00b67f09SDavid van Moolenbroek result = DNS_R_FROZEN;
401*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
402*00b67f09SDavid van Moolenbroek result = dns_zone_flush(zone);
403*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
404*00b67f09SDavid van Moolenbroek dns_zone_setupdatedisabled(zone, freeze);
405*00b67f09SDavid van Moolenbroek } else {
406*00b67f09SDavid van Moolenbroek if (frozen) {
407*00b67f09SDavid van Moolenbroek result = dns_zone_loadandthaw(zone);
408*00b67f09SDavid van Moolenbroek if (result == DNS_R_CONTINUE ||
409*00b67f09SDavid van Moolenbroek result == DNS_R_UPTODATE)
410*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
411*00b67f09SDavid van Moolenbroek }
412*00b67f09SDavid van Moolenbroek }
413*00b67f09SDavid van Moolenbroek view = dns_zone_getview(zone);
414*00b67f09SDavid van Moolenbroek if (strcmp(view->name, "_bind") == 0 ||
415*00b67f09SDavid van Moolenbroek strcmp(view->name, "_default") == 0)
416*00b67f09SDavid van Moolenbroek {
417*00b67f09SDavid van Moolenbroek vname = "";
418*00b67f09SDavid van Moolenbroek sep = "";
419*00b67f09SDavid van Moolenbroek } else {
420*00b67f09SDavid van Moolenbroek vname = view->name;
421*00b67f09SDavid van Moolenbroek sep = " ";
422*00b67f09SDavid van Moolenbroek }
423*00b67f09SDavid van Moolenbroek dns_rdataclass_format(dns_zone_getclass(zone), classstr,
424*00b67f09SDavid van Moolenbroek sizeof(classstr));
425*00b67f09SDavid van Moolenbroek dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
426*00b67f09SDavid van Moolenbroek level = (result != ISC_R_SUCCESS) ? ISC_LOG_ERROR : ISC_LOG_DEBUG(1);
427*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
428*00b67f09SDavid van Moolenbroek level, "%s zone '%s/%s'%s%s: %s",
429*00b67f09SDavid van Moolenbroek freeze ? "freezing" : "thawing",
430*00b67f09SDavid van Moolenbroek zonename, classstr, sep, vname,
431*00b67f09SDavid van Moolenbroek isc_result_totext(result));
432*00b67f09SDavid van Moolenbroek if (raw != NULL)
433*00b67f09SDavid van Moolenbroek dns_zone_detach(&raw);
434*00b67f09SDavid van Moolenbroek return (result);
435*00b67f09SDavid van Moolenbroek }
436*00b67f09SDavid van Moolenbroek
437*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_apply(dns_zt_t * zt,isc_boolean_t stop,isc_result_t (* action)(dns_zone_t *,void *),void * uap)438*00b67f09SDavid van Moolenbroek dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop,
439*00b67f09SDavid van Moolenbroek isc_result_t (*action)(dns_zone_t *, void *), void *uap)
440*00b67f09SDavid van Moolenbroek {
441*00b67f09SDavid van Moolenbroek return (dns_zt_apply2(zt, stop, NULL, action, uap));
442*00b67f09SDavid van Moolenbroek }
443*00b67f09SDavid van Moolenbroek
444*00b67f09SDavid van Moolenbroek isc_result_t
dns_zt_apply2(dns_zt_t * zt,isc_boolean_t stop,isc_result_t * sub,isc_result_t (* action)(dns_zone_t *,void *),void * uap)445*00b67f09SDavid van Moolenbroek dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub,
446*00b67f09SDavid van Moolenbroek isc_result_t (*action)(dns_zone_t *, void *), void *uap)
447*00b67f09SDavid van Moolenbroek {
448*00b67f09SDavid van Moolenbroek dns_rbtnode_t *node;
449*00b67f09SDavid van Moolenbroek dns_rbtnodechain_t chain;
450*00b67f09SDavid van Moolenbroek isc_result_t result, tresult = ISC_R_SUCCESS;
451*00b67f09SDavid van Moolenbroek dns_zone_t *zone;
452*00b67f09SDavid van Moolenbroek
453*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
454*00b67f09SDavid van Moolenbroek REQUIRE(action != NULL);
455*00b67f09SDavid van Moolenbroek
456*00b67f09SDavid van Moolenbroek dns_rbtnodechain_init(&chain, zt->mctx);
457*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
458*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOTFOUND) {
459*00b67f09SDavid van Moolenbroek /*
460*00b67f09SDavid van Moolenbroek * The tree is empty.
461*00b67f09SDavid van Moolenbroek */
462*00b67f09SDavid van Moolenbroek tresult = result;
463*00b67f09SDavid van Moolenbroek result = ISC_R_NOMORE;
464*00b67f09SDavid van Moolenbroek }
465*00b67f09SDavid van Moolenbroek while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
466*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_current(&chain, NULL, NULL,
467*00b67f09SDavid van Moolenbroek &node);
468*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
469*00b67f09SDavid van Moolenbroek zone = node->data;
470*00b67f09SDavid van Moolenbroek if (zone != NULL)
471*00b67f09SDavid van Moolenbroek result = (action)(zone, uap);
472*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS && stop) {
473*00b67f09SDavid van Moolenbroek tresult = result;
474*00b67f09SDavid van Moolenbroek goto cleanup; /* don't break */
475*00b67f09SDavid van Moolenbroek } else if (result != ISC_R_SUCCESS &&
476*00b67f09SDavid van Moolenbroek tresult == ISC_R_SUCCESS)
477*00b67f09SDavid van Moolenbroek tresult = result;
478*00b67f09SDavid van Moolenbroek }
479*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_next(&chain, NULL, NULL);
480*00b67f09SDavid van Moolenbroek }
481*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE)
482*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
483*00b67f09SDavid van Moolenbroek
484*00b67f09SDavid van Moolenbroek cleanup:
485*00b67f09SDavid van Moolenbroek dns_rbtnodechain_invalidate(&chain);
486*00b67f09SDavid van Moolenbroek if (sub != NULL)
487*00b67f09SDavid van Moolenbroek *sub = tresult;
488*00b67f09SDavid van Moolenbroek
489*00b67f09SDavid van Moolenbroek return (result);
490*00b67f09SDavid van Moolenbroek }
491*00b67f09SDavid van Moolenbroek
492*00b67f09SDavid van Moolenbroek /*
493*00b67f09SDavid van Moolenbroek * Decrement the loads_pending counter; when counter reaches
494*00b67f09SDavid van Moolenbroek * zero, call the loaddone callback that was initially set by
495*00b67f09SDavid van Moolenbroek * dns_zt_asyncload().
496*00b67f09SDavid van Moolenbroek */
497*00b67f09SDavid van Moolenbroek static isc_result_t
doneloading(dns_zt_t * zt,dns_zone_t * zone,isc_task_t * task)498*00b67f09SDavid van Moolenbroek doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
499*00b67f09SDavid van Moolenbroek isc_boolean_t destroy = ISC_FALSE;
500*00b67f09SDavid van Moolenbroek dns_zt_allloaded_t alldone = NULL;
501*00b67f09SDavid van Moolenbroek void *arg = NULL;
502*00b67f09SDavid van Moolenbroek
503*00b67f09SDavid van Moolenbroek UNUSED(zone);
504*00b67f09SDavid van Moolenbroek UNUSED(task);
505*00b67f09SDavid van Moolenbroek
506*00b67f09SDavid van Moolenbroek REQUIRE(VALID_ZT(zt));
507*00b67f09SDavid van Moolenbroek
508*00b67f09SDavid van Moolenbroek RWLOCK(&zt->rwlock, isc_rwlocktype_write);
509*00b67f09SDavid van Moolenbroek INSIST(zt->loads_pending != 0);
510*00b67f09SDavid van Moolenbroek INSIST(zt->references != 0);
511*00b67f09SDavid van Moolenbroek zt->references--;
512*00b67f09SDavid van Moolenbroek if (zt->references == 0)
513*00b67f09SDavid van Moolenbroek destroy = ISC_TRUE;
514*00b67f09SDavid van Moolenbroek zt->loads_pending--;
515*00b67f09SDavid van Moolenbroek if (zt->loads_pending == 0) {
516*00b67f09SDavid van Moolenbroek alldone = zt->loaddone;
517*00b67f09SDavid van Moolenbroek arg = zt->loaddone_arg;
518*00b67f09SDavid van Moolenbroek zt->loaddone = NULL;
519*00b67f09SDavid van Moolenbroek zt->loaddone_arg = NULL;
520*00b67f09SDavid van Moolenbroek }
521*00b67f09SDavid van Moolenbroek RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
522*00b67f09SDavid van Moolenbroek
523*00b67f09SDavid van Moolenbroek if (alldone != NULL)
524*00b67f09SDavid van Moolenbroek alldone(arg);
525*00b67f09SDavid van Moolenbroek
526*00b67f09SDavid van Moolenbroek if (destroy)
527*00b67f09SDavid van Moolenbroek zt_destroy(zt);
528*00b67f09SDavid van Moolenbroek
529*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
530*00b67f09SDavid van Moolenbroek }
531*00b67f09SDavid van Moolenbroek
532*00b67f09SDavid van Moolenbroek /***
533*00b67f09SDavid van Moolenbroek *** Private
534*00b67f09SDavid van Moolenbroek ***/
535*00b67f09SDavid van Moolenbroek
536*00b67f09SDavid van Moolenbroek static void
auto_detach(void * data,void * arg)537*00b67f09SDavid van Moolenbroek auto_detach(void *data, void *arg) {
538*00b67f09SDavid van Moolenbroek dns_zone_t *zone = data;
539*00b67f09SDavid van Moolenbroek
540*00b67f09SDavid van Moolenbroek UNUSED(arg);
541*00b67f09SDavid van Moolenbroek dns_zone_detach(&zone);
542*00b67f09SDavid van Moolenbroek }
543