4 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: zt.c,v 1.47 2007/06/19 23:47:16 tbox Exp */
27 #include <isc/magic.h>
29 #include <isc/string.h>
35 #include <dns/rdataclass.h>
36 #include <dns/result.h>
45 dns_rdataclass_t rdclass
;
48 isc_uint32_t references
;
52 #define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l')
53 #define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC)
56 auto_detach(void *, void *);
59 load(dns_zone_t
*zone
, void *uap
);
62 loadnew(dns_zone_t
*zone
, void *uap
);
65 freezezones(dns_zone_t
*zone
, void *uap
);
68 dns_zt_create(isc_mem_t
*mctx
, dns_rdataclass_t rdclass
, dns_zt_t
**ztp
)
73 REQUIRE(ztp
!= NULL
&& *ztp
== NULL
);
75 zt
= isc_mem_get(mctx
, sizeof(*zt
));
77 return (ISC_R_NOMEMORY
);
80 result
= dns_rbt_create(mctx
, auto_detach
, zt
, &zt
->table
);
81 if (result
!= ISC_R_SUCCESS
)
84 result
= isc_rwlock_init(&zt
->rwlock
, 0, 0);
85 if (result
!= ISC_R_SUCCESS
)
90 zt
->rdclass
= rdclass
;
94 return (ISC_R_SUCCESS
);
97 dns_rbt_destroy(&zt
->table
);
100 isc_mem_put(mctx
, zt
, sizeof(*zt
));
106 dns_zt_mount(dns_zt_t
*zt
, dns_zone_t
*zone
) {
108 dns_zone_t
*dummy
= NULL
;
111 REQUIRE(VALID_ZT(zt
));
113 name
= dns_zone_getorigin(zone
);
115 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
117 result
= dns_rbt_addname(zt
->table
, name
, zone
);
118 if (result
== ISC_R_SUCCESS
)
119 dns_zone_attach(zone
, &dummy
);
121 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
127 dns_zt_unmount(dns_zt_t
*zt
, dns_zone_t
*zone
) {
131 REQUIRE(VALID_ZT(zt
));
133 name
= dns_zone_getorigin(zone
);
135 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
137 result
= dns_rbt_deletename(zt
->table
, name
, ISC_FALSE
);
139 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
145 dns_zt_find(dns_zt_t
*zt
, dns_name_t
*name
, unsigned int options
,
146 dns_name_t
*foundname
, dns_zone_t
**zonep
)
149 dns_zone_t
*dummy
= NULL
;
150 unsigned int rbtoptions
= 0;
152 REQUIRE(VALID_ZT(zt
));
154 if ((options
& DNS_ZTFIND_NOEXACT
) != 0)
155 rbtoptions
|= DNS_RBTFIND_NOEXACT
;
157 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
159 result
= dns_rbt_findname(zt
->table
, name
, rbtoptions
, foundname
,
160 (void **) (void*)&dummy
);
161 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
162 dns_zone_attach(dummy
, zonep
);
164 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
170 dns_zt_attach(dns_zt_t
*zt
, dns_zt_t
**ztp
) {
172 REQUIRE(VALID_ZT(zt
));
173 REQUIRE(ztp
!= NULL
&& *ztp
== NULL
);
175 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
177 INSIST(zt
->references
> 0);
179 INSIST(zt
->references
!= 0);
181 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
187 flush(dns_zone_t
*zone
, void *uap
) {
189 return (dns_zone_flush(zone
));
193 zt_flushanddetach(dns_zt_t
**ztp
, isc_boolean_t need_flush
) {
194 isc_boolean_t destroy
= ISC_FALSE
;
197 REQUIRE(ztp
!= NULL
&& VALID_ZT(*ztp
));
201 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
203 INSIST(zt
->references
> 0);
205 if (zt
->references
== 0)
208 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
212 (void)dns_zt_apply(zt
, ISC_FALSE
, flush
, NULL
);
213 dns_rbt_destroy(&zt
->table
);
214 isc_rwlock_destroy(&zt
->rwlock
);
216 isc_mem_put(zt
->mctx
, zt
, sizeof(*zt
));
223 dns_zt_flushanddetach(dns_zt_t
**ztp
) {
224 zt_flushanddetach(ztp
, ISC_TRUE
);
228 dns_zt_detach(dns_zt_t
**ztp
) {
229 zt_flushanddetach(ztp
, ISC_FALSE
);
233 dns_zt_load(dns_zt_t
*zt
, isc_boolean_t stop
) {
236 REQUIRE(VALID_ZT(zt
));
238 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
239 result
= dns_zt_apply(zt
, stop
, load
, NULL
);
240 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
245 load(dns_zone_t
*zone
, void *uap
) {
248 result
= dns_zone_load(zone
);
249 if (result
== DNS_R_CONTINUE
|| result
== DNS_R_UPTODATE
)
250 result
= ISC_R_SUCCESS
;
255 dns_zt_loadnew(dns_zt_t
*zt
, isc_boolean_t stop
) {
258 REQUIRE(VALID_ZT(zt
));
260 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
261 result
= dns_zt_apply(zt
, stop
, loadnew
, NULL
);
262 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
267 loadnew(dns_zone_t
*zone
, void *uap
) {
270 result
= dns_zone_loadnew(zone
);
271 if (result
== DNS_R_CONTINUE
|| result
== DNS_R_UPTODATE
||
272 result
== DNS_R_DYNAMIC
)
273 result
= ISC_R_SUCCESS
;
278 dns_zt_freezezones(dns_zt_t
*zt
, isc_boolean_t freeze
) {
279 isc_result_t result
, tresult
;
281 REQUIRE(VALID_ZT(zt
));
283 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
284 result
= dns_zt_apply2(zt
, ISC_FALSE
, &tresult
, freezezones
, &freeze
);
285 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
286 return ((result
== ISC_R_SUCCESS
) ? tresult
: result
);
290 freezezones(dns_zone_t
*zone
, void *uap
) {
291 isc_boolean_t freeze
= *(isc_boolean_t
*)uap
;
292 isc_boolean_t frozen
;
293 isc_result_t result
= ISC_R_SUCCESS
;
294 char classstr
[DNS_RDATACLASS_FORMATSIZE
];
295 char zonename
[DNS_NAME_FORMATSIZE
];
302 if (dns_zone_gettype(zone
) != dns_zone_master
)
303 return (ISC_R_SUCCESS
);
305 frozen
= dns_zone_getupdatedisabled(zone
);
308 result
= DNS_R_FROZEN
;
309 if (result
== ISC_R_SUCCESS
)
310 result
= dns_zone_flush(zone
);
311 if (result
== ISC_R_SUCCESS
) {
312 journal
= dns_zone_getjournal(zone
);
314 (void)isc_file_remove(journal
);
318 result
= dns_zone_load(zone
);
319 if (result
== DNS_R_CONTINUE
||
320 result
== DNS_R_UPTODATE
)
321 result
= ISC_R_SUCCESS
;
324 if (result
== ISC_R_SUCCESS
)
325 dns_zone_setupdatedisabled(zone
, freeze
);
326 view
= dns_zone_getview(zone
);
327 if (strcmp(view
->name
, "_bind") == 0 ||
328 strcmp(view
->name
, "_default") == 0)
336 dns_rdataclass_format(dns_zone_getclass(zone
), classstr
,
338 dns_name_format(dns_zone_getorigin(zone
), zonename
, sizeof(zonename
));
339 level
= (result
!= ISC_R_SUCCESS
) ? ISC_LOG_ERROR
: ISC_LOG_DEBUG(1);
340 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
, DNS_LOGMODULE_ZONE
,
341 level
, "%s zone '%s/%s'%s%s: %s",
342 freeze
? "freezing" : "thawing",
343 zonename
, classstr
, sep
, vname
,
344 isc_result_totext(result
));
349 dns_zt_apply(dns_zt_t
*zt
, isc_boolean_t stop
,
350 isc_result_t (*action
)(dns_zone_t
*, void *), void *uap
)
352 return (dns_zt_apply2(zt
, stop
, NULL
, action
, uap
));
356 dns_zt_apply2(dns_zt_t
*zt
, isc_boolean_t stop
, isc_result_t
*sub
,
357 isc_result_t (*action
)(dns_zone_t
*, void *), void *uap
)
360 dns_rbtnodechain_t chain
;
361 isc_result_t result
, tresult
= ISC_R_SUCCESS
;
364 REQUIRE(VALID_ZT(zt
));
365 REQUIRE(action
!= NULL
);
367 dns_rbtnodechain_init(&chain
, zt
->mctx
);
368 result
= dns_rbtnodechain_first(&chain
, zt
->table
, NULL
, NULL
);
369 if (result
== ISC_R_NOTFOUND
) {
373 result
= ISC_R_NOMORE
;
375 while (result
== DNS_R_NEWORIGIN
|| result
== ISC_R_SUCCESS
) {
376 result
= dns_rbtnodechain_current(&chain
, NULL
, NULL
,
378 if (result
== ISC_R_SUCCESS
) {
381 result
= (action
)(zone
, uap
);
382 if (result
!= ISC_R_SUCCESS
&& stop
) {
384 goto cleanup
; /* don't break */
385 } else if (result
!= ISC_R_SUCCESS
&&
386 tresult
== ISC_R_SUCCESS
)
389 result
= dns_rbtnodechain_next(&chain
, NULL
, NULL
);
391 if (result
== ISC_R_NOMORE
)
392 result
= ISC_R_SUCCESS
;
395 dns_rbtnodechain_invalidate(&chain
);
407 auto_detach(void *data
, void *arg
) {
408 dns_zone_t
*zone
= data
;
412 dns_zone_detach(&zone
);