2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.33.2.3 2004/04/15 01:38:09 marka Exp $ */
22 #include <isc/magic.h>
27 #include <dns/result.h>
35 dns_rdataclass_t rdclass
;
38 isc_uint32_t references
;
42 #define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l')
43 #define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC)
46 auto_detach(void *, void *);
49 load(dns_zone_t
*zone
, void *uap
);
52 loadnew(dns_zone_t
*zone
, void *uap
);
55 dns_zt_create(isc_mem_t
*mctx
, dns_rdataclass_t rdclass
, dns_zt_t
**ztp
) {
59 REQUIRE(ztp
!= NULL
&& *ztp
== NULL
);
61 zt
= isc_mem_get(mctx
, sizeof *zt
);
63 return (ISC_R_NOMEMORY
);
66 result
= dns_rbt_create(mctx
, auto_detach
, zt
, &zt
->table
);
67 if (result
!= ISC_R_SUCCESS
)
70 result
= isc_rwlock_init(&zt
->rwlock
, 0, 0);
71 if (result
!= ISC_R_SUCCESS
) {
72 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
73 "isc_rwlock_init() failed: %s",
74 isc_result_totext(result
));
75 result
= ISC_R_UNEXPECTED
;
81 zt
->rdclass
= rdclass
;
85 return (ISC_R_SUCCESS
);
88 dns_rbt_destroy(&zt
->table
);
91 isc_mem_put(mctx
, zt
, sizeof *zt
);
97 dns_zt_mount(dns_zt_t
*zt
, dns_zone_t
*zone
) {
99 dns_zone_t
*dummy
= NULL
;
102 REQUIRE(VALID_ZT(zt
));
104 name
= dns_zone_getorigin(zone
);
106 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
108 result
= dns_rbt_addname(zt
->table
, name
, zone
);
109 if (result
== ISC_R_SUCCESS
)
110 dns_zone_attach(zone
, &dummy
);
112 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
118 dns_zt_unmount(dns_zt_t
*zt
, dns_zone_t
*zone
) {
122 REQUIRE(VALID_ZT(zt
));
124 name
= dns_zone_getorigin(zone
);
126 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
128 result
= dns_rbt_deletename(zt
->table
, name
, ISC_FALSE
);
130 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
136 dns_zt_find(dns_zt_t
*zt
, dns_name_t
*name
, unsigned int options
,
137 dns_name_t
*foundname
, dns_zone_t
**zonep
)
140 dns_zone_t
*dummy
= NULL
;
141 unsigned int rbtoptions
= 0;
143 REQUIRE(VALID_ZT(zt
));
145 if ((options
& DNS_ZTFIND_NOEXACT
) != 0)
146 rbtoptions
|= DNS_RBTFIND_NOEXACT
;
148 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
150 result
= dns_rbt_findname(zt
->table
, name
, rbtoptions
, foundname
,
151 (void **) (void*)&dummy
);
152 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
153 dns_zone_attach(dummy
, zonep
);
155 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
161 dns_zt_attach(dns_zt_t
*zt
, dns_zt_t
**ztp
) {
163 REQUIRE(VALID_ZT(zt
));
164 REQUIRE(ztp
!= NULL
&& *ztp
== NULL
);
166 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
168 INSIST(zt
->references
> 0);
170 INSIST(zt
->references
!= 0);
172 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
178 flush(dns_zone_t
*zone
, void *uap
) {
180 return (dns_zone_flush(zone
));
184 zt_flushanddetach(dns_zt_t
**ztp
, isc_boolean_t need_flush
) {
185 isc_boolean_t destroy
= ISC_FALSE
;
188 REQUIRE(ztp
!= NULL
&& VALID_ZT(*ztp
));
192 RWLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
194 INSIST(zt
->references
> 0);
196 if (zt
->references
== 0)
199 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_write
);
203 (void)dns_zt_apply(zt
, ISC_FALSE
, flush
, NULL
);
204 dns_rbt_destroy(&zt
->table
);
205 isc_rwlock_destroy(&zt
->rwlock
);
207 isc_mem_put(zt
->mctx
, zt
, sizeof *zt
);
214 dns_zt_flushanddetach(dns_zt_t
**ztp
) {
215 zt_flushanddetach(ztp
, ISC_TRUE
);
219 dns_zt_detach(dns_zt_t
**ztp
) {
220 zt_flushanddetach(ztp
, ISC_FALSE
);
224 dns_zt_load(dns_zt_t
*zt
, isc_boolean_t stop
) {
227 REQUIRE(VALID_ZT(zt
));
229 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
230 result
= dns_zt_apply(zt
, stop
, load
, NULL
);
231 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
236 load(dns_zone_t
*zone
, void *uap
) {
238 return (dns_zone_load(zone
));
242 dns_zt_loadnew(dns_zt_t
*zt
, isc_boolean_t stop
) {
245 REQUIRE(VALID_ZT(zt
));
247 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
248 result
= dns_zt_apply(zt
, stop
, loadnew
, NULL
);
249 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
254 loadnew(dns_zone_t
*zone
, void *uap
) {
257 result
= dns_zone_loadnew(zone
);
258 if (result
== DNS_R_CONTINUE
|| result
== DNS_R_UPTODATE
||
259 result
== DNS_R_DYNAMIC
)
260 result
= ISC_R_SUCCESS
;
265 dns_zt_apply(dns_zt_t
*zt
, isc_boolean_t stop
,
266 isc_result_t (*action
)(dns_zone_t
*, void *), void *uap
)
269 dns_rbtnodechain_t chain
;
273 REQUIRE(VALID_ZT(zt
));
274 REQUIRE(action
!= NULL
);
276 dns_rbtnodechain_init(&chain
, zt
->mctx
);
277 result
= dns_rbtnodechain_first(&chain
, zt
->table
, NULL
, NULL
);
278 if (result
== ISC_R_NOTFOUND
) {
282 result
= ISC_R_NOMORE
;
284 while (result
== DNS_R_NEWORIGIN
|| result
== ISC_R_SUCCESS
) {
285 result
= dns_rbtnodechain_current(&chain
, NULL
, NULL
,
287 if (result
== ISC_R_SUCCESS
) {
290 result
= (action
)(zone
, uap
);
291 if (result
!= ISC_R_SUCCESS
&& stop
)
292 goto cleanup
; /* don't break */
294 result
= dns_rbtnodechain_next(&chain
, NULL
, NULL
);
296 if (result
== ISC_R_NOMORE
)
297 result
= ISC_R_SUCCESS
;
300 dns_rbtnodechain_invalidate(&chain
);
310 auto_detach(void *data
, void *arg
) {
311 dns_zone_t
*zone
= data
;
315 dns_zone_detach(&zone
);