2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: zt.c,v 1.47 2007/06/19 23:47:16 tbox Exp $ */
25 #include <isc/magic.h>
27 #include <isc/string.h>
33 #include <dns/rdataclass.h>
34 #include <dns/result.h>
43 dns_rdataclass_t rdclass
;
46 isc_uint32_t references
;
50 #define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l')
51 #define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC)
54 auto_detach(void *, void *);
57 load(dns_zone_t
*zone
, void *uap
);
60 loadnew(dns_zone_t
*zone
, void *uap
);
63 freezezones(dns_zone_t
*zone
, void *uap
);
66 dns_zt_create(isc_mem_t
*mctx
, dns_rdataclass_t rdclass
, dns_zt_t
**ztp
)
71 REQUIRE(ztp
!= NULL
&& *ztp
== NULL
);
73 zt
= isc_mem_get(mctx
, sizeof(*zt
));
75 return (ISC_R_NOMEMORY
);
78 result
= dns_rbt_create(mctx
, auto_detach
, zt
, &zt
->table
);
79 if (result
!= ISC_R_SUCCESS
)
82 result
= isc_rwlock_init(&zt
->rwlock
, 0, 0);
83 if (result
!= ISC_R_SUCCESS
)
88 zt
->rdclass
= rdclass
;
92 return (ISC_R_SUCCESS
);
95 dns_rbt_destroy(&zt
->table
);
98 isc_mem_put(mctx
, zt
, sizeof(*zt
));
104 dns_zt_mount(dns_zt_t
*zt
, dns_zone_t
*zone
) {
106 dns_zone_t
*dummy
= NULL
;
109 REQUIRE(VALID_ZT(zt
));
111 name
= dns_zone_getorigin(zone
);
113 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
115 result
= dns_rbt_addname(zt
->table
, name
, zone
);
116 if (result
== ISC_R_SUCCESS
)
117 dns_zone_attach(zone
, &dummy
);
119 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
125 dns_zt_unmount(dns_zt_t
*zt
, dns_zone_t
*zone
) {
129 REQUIRE(VALID_ZT(zt
));
131 name
= dns_zone_getorigin(zone
);
133 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
135 result
= dns_rbt_deletename(zt
->table
, name
, ISC_FALSE
);
137 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
143 dns_zt_find(dns_zt_t
*zt
, dns_name_t
*name
, unsigned int options
,
144 dns_name_t
*foundname
, dns_zone_t
**zonep
)
147 dns_zone_t
*dummy
= NULL
;
148 unsigned int rbtoptions
= 0;
150 REQUIRE(VALID_ZT(zt
));
152 if ((options
& DNS_ZTFIND_NOEXACT
) != 0)
153 rbtoptions
|= DNS_RBTFIND_NOEXACT
;
155 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
157 result
= dns_rbt_findname(zt
->table
, name
, rbtoptions
, foundname
,
158 (void **) (void*)&dummy
);
159 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
160 dns_zone_attach(dummy
, zonep
);
162 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
168 dns_zt_attach(dns_zt_t
*zt
, dns_zt_t
**ztp
) {
170 REQUIRE(VALID_ZT(zt
));
171 REQUIRE(ztp
!= NULL
&& *ztp
== NULL
);
173 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
175 INSIST(zt
->references
> 0);
177 INSIST(zt
->references
!= 0);
179 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
185 flush(dns_zone_t
*zone
, void *uap
) {
187 return (dns_zone_flush(zone
));
191 zt_flushanddetach(dns_zt_t
**ztp
, isc_boolean_t need_flush
) {
192 isc_boolean_t destroy
= ISC_FALSE
;
195 REQUIRE(ztp
!= NULL
&& VALID_ZT(*ztp
));
199 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
201 INSIST(zt
->references
> 0);
203 if (zt
->references
== 0)
206 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
210 (void)dns_zt_apply(zt
, ISC_FALSE
, flush
, NULL
);
211 dns_rbt_destroy(&zt
->table
);
212 isc_rwlock_destroy(&zt
->rwlock
);
214 isc_mem_put(zt
->mctx
, zt
, sizeof(*zt
));
221 dns_zt_flushanddetach(dns_zt_t
**ztp
) {
222 zt_flushanddetach(ztp
, ISC_TRUE
);
226 dns_zt_detach(dns_zt_t
**ztp
) {
227 zt_flushanddetach(ztp
, ISC_FALSE
);
231 dns_zt_load(dns_zt_t
*zt
, isc_boolean_t stop
) {
234 REQUIRE(VALID_ZT(zt
));
236 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
237 result
= dns_zt_apply(zt
, stop
, load
, NULL
);
238 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
243 load(dns_zone_t
*zone
, void *uap
) {
246 result
= dns_zone_load(zone
);
247 if (result
== DNS_R_CONTINUE
|| result
== DNS_R_UPTODATE
)
248 result
= ISC_R_SUCCESS
;
253 dns_zt_loadnew(dns_zt_t
*zt
, isc_boolean_t stop
) {
256 REQUIRE(VALID_ZT(zt
));
258 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
259 result
= dns_zt_apply(zt
, stop
, loadnew
, NULL
);
260 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
265 loadnew(dns_zone_t
*zone
, void *uap
) {
268 result
= dns_zone_loadnew(zone
);
269 if (result
== DNS_R_CONTINUE
|| result
== DNS_R_UPTODATE
||
270 result
== DNS_R_DYNAMIC
)
271 result
= ISC_R_SUCCESS
;
276 dns_zt_freezezones(dns_zt_t
*zt
, isc_boolean_t freeze
) {
277 isc_result_t result
, tresult
;
279 REQUIRE(VALID_ZT(zt
));
281 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
282 result
= dns_zt_apply2(zt
, ISC_FALSE
, &tresult
, freezezones
, &freeze
);
283 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
284 return ((result
== ISC_R_SUCCESS
) ? tresult
: result
);
288 freezezones(dns_zone_t
*zone
, void *uap
) {
289 isc_boolean_t freeze
= *(isc_boolean_t
*)uap
;
290 isc_boolean_t frozen
;
291 isc_result_t result
= ISC_R_SUCCESS
;
292 char classstr
[DNS_RDATACLASS_FORMATSIZE
];
293 char zonename
[DNS_NAME_FORMATSIZE
];
300 if (dns_zone_gettype(zone
) != dns_zone_master
)
301 return (ISC_R_SUCCESS
);
303 frozen
= dns_zone_getupdatedisabled(zone
);
306 result
= DNS_R_FROZEN
;
307 if (result
== ISC_R_SUCCESS
)
308 result
= dns_zone_flush(zone
);
309 if (result
== ISC_R_SUCCESS
) {
310 journal
= dns_zone_getjournal(zone
);
312 (void)isc_file_remove(journal
);
316 result
= dns_zone_load(zone
);
317 if (result
== DNS_R_CONTINUE
||
318 result
== DNS_R_UPTODATE
)
319 result
= ISC_R_SUCCESS
;
322 if (result
== ISC_R_SUCCESS
)
323 dns_zone_setupdatedisabled(zone
, freeze
);
324 view
= dns_zone_getview(zone
);
325 if (strcmp(view
->name
, "_bind") == 0 ||
326 strcmp(view
->name
, "_default") == 0)
334 dns_rdataclass_format(dns_zone_getclass(zone
), classstr
,
336 dns_name_format(dns_zone_getorigin(zone
), zonename
, sizeof(zonename
));
337 level
= (result
!= ISC_R_SUCCESS
) ? ISC_LOG_ERROR
: ISC_LOG_DEBUG(1);
338 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
, DNS_LOGMODULE_ZONE
,
339 level
, "%s zone '%s/%s'%s%s: %s",
340 freeze
? "freezing" : "thawing",
341 zonename
, classstr
, sep
, vname
,
342 isc_result_totext(result
));
347 dns_zt_apply(dns_zt_t
*zt
, isc_boolean_t stop
,
348 isc_result_t (*action
)(dns_zone_t
*, void *), void *uap
)
350 return (dns_zt_apply2(zt
, stop
, NULL
, action
, uap
));
354 dns_zt_apply2(dns_zt_t
*zt
, isc_boolean_t stop
, isc_result_t
*sub
,
355 isc_result_t (*action
)(dns_zone_t
*, void *), void *uap
)
358 dns_rbtnodechain_t chain
;
359 isc_result_t result
, tresult
= ISC_R_SUCCESS
;
362 REQUIRE(VALID_ZT(zt
));
363 REQUIRE(action
!= NULL
);
365 dns_rbtnodechain_init(&chain
, zt
->mctx
);
366 result
= dns_rbtnodechain_first(&chain
, zt
->table
, NULL
, NULL
);
367 if (result
== ISC_R_NOTFOUND
) {
371 result
= ISC_R_NOMORE
;
373 while (result
== DNS_R_NEWORIGIN
|| result
== ISC_R_SUCCESS
) {
374 result
= dns_rbtnodechain_current(&chain
, NULL
, NULL
,
376 if (result
== ISC_R_SUCCESS
) {
379 result
= (action
)(zone
, uap
);
380 if (result
!= ISC_R_SUCCESS
&& stop
) {
382 goto cleanup
; /* don't break */
383 } else if (result
!= ISC_R_SUCCESS
&&
384 tresult
== ISC_R_SUCCESS
)
387 result
= dns_rbtnodechain_next(&chain
, NULL
, NULL
);
389 if (result
== ISC_R_NOMORE
)
390 result
= ISC_R_SUCCESS
;
393 dns_rbtnodechain_invalidate(&chain
);
405 auto_detach(void *data
, void *arg
) {
406 dns_zone_t
*zone
= data
;
410 dns_zone_detach(&zone
);