2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2002 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.12.6 2004/03/08 21:06:28 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
) {
239 result
= dns_zone_load(zone
);
240 if (result
== DNS_R_CONTINUE
|| result
== DNS_R_UPTODATE
)
241 result
= ISC_R_SUCCESS
;
246 dns_zt_loadnew(dns_zt_t
*zt
, isc_boolean_t stop
) {
249 REQUIRE(VALID_ZT(zt
));
251 RWLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
252 result
= dns_zt_apply(zt
, stop
, loadnew
, NULL
);
253 RWUNLOCK(&zt
->rwlock
, isc_rwlocktype_read
);
258 loadnew(dns_zone_t
*zone
, void *uap
) {
261 result
= dns_zone_loadnew(zone
);
262 if (result
== DNS_R_CONTINUE
|| result
== DNS_R_UPTODATE
||
263 result
== DNS_R_DYNAMIC
)
264 result
= ISC_R_SUCCESS
;
269 dns_zt_apply(dns_zt_t
*zt
, isc_boolean_t stop
,
270 isc_result_t (*action
)(dns_zone_t
*, void *), void *uap
)
273 dns_rbtnodechain_t chain
;
277 REQUIRE(VALID_ZT(zt
));
278 REQUIRE(action
!= NULL
);
280 dns_rbtnodechain_init(&chain
, zt
->mctx
);
281 result
= dns_rbtnodechain_first(&chain
, zt
->table
, NULL
, NULL
);
282 if (result
== ISC_R_NOTFOUND
) {
286 result
= ISC_R_NOMORE
;
288 while (result
== DNS_R_NEWORIGIN
|| result
== ISC_R_SUCCESS
) {
289 result
= dns_rbtnodechain_current(&chain
, NULL
, NULL
,
291 if (result
== ISC_R_SUCCESS
) {
294 result
= (action
)(zone
, uap
);
295 if (result
!= ISC_R_SUCCESS
&& stop
)
296 goto cleanup
; /* don't break */
298 result
= dns_rbtnodechain_next(&chain
, NULL
, NULL
);
300 if (result
== ISC_R_NOMORE
)
301 result
= ISC_R_SUCCESS
;
304 dns_rbtnodechain_invalidate(&chain
);
314 auto_detach(void *data
, void *arg
) {
315 dns_zone_t
*zone
= data
;
319 dns_zone_detach(&zone
);