00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/file.h>
00025 #include <isc/magic.h>
00026 #include <isc/mem.h>
00027 #include <isc/string.h>
00028 #include <isc/task.h>
00029 #include <isc/util.h>
00030
00031 #include <dns/log.h>
00032 #include <dns/name.h>
00033 #include <dns/rbt.h>
00034 #include <dns/rdataclass.h>
00035 #include <dns/result.h>
00036 #include <dns/view.h>
00037 #include <dns/zone.h>
00038 #include <dns/zt.h>
00039
00040 struct dns_zt {
00041
00042 unsigned int magic;
00043 isc_mem_t *mctx;
00044 dns_rdataclass_t rdclass;
00045 isc_rwlock_t rwlock;
00046 dns_zt_allloaded_t loaddone;
00047 void * loaddone_arg;
00048
00049 isc_boolean_t flush;
00050 isc_uint32_t references;
00051 unsigned int loads_pending;
00052 dns_rbt_t *table;
00053 };
00054
00055 #define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l')
00056 #define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC)
00057
00058 static void
00059 auto_detach(void *, void *);
00060
00061 static isc_result_t
00062 load(dns_zone_t *zone, void *uap);
00063
00064 static isc_result_t
00065 asyncload(dns_zone_t *zone, void *callback);
00066
00067 static isc_result_t
00068 loadnew(dns_zone_t *zone, void *uap);
00069
00070 static isc_result_t
00071 freezezones(dns_zone_t *zone, void *uap);
00072
00073 static isc_result_t
00074 doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task);
00075
00076 isc_result_t
00077 dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) {
00078 dns_zt_t *zt;
00079 isc_result_t result;
00080
00081 REQUIRE(ztp != NULL && *ztp == NULL);
00082
00083 zt = isc_mem_get(mctx, sizeof(*zt));
00084 if (zt == NULL)
00085 return (ISC_R_NOMEMORY);
00086
00087 zt->table = NULL;
00088 result = dns_rbt_create(mctx, auto_detach, zt, &zt->table);
00089 if (result != ISC_R_SUCCESS)
00090 goto cleanup_zt;
00091
00092 result = isc_rwlock_init(&zt->rwlock, 0, 0);
00093 if (result != ISC_R_SUCCESS)
00094 goto cleanup_rbt;
00095
00096 zt->mctx = NULL;
00097 isc_mem_attach(mctx, &zt->mctx);
00098 zt->references = 1;
00099 zt->flush = ISC_FALSE;
00100 zt->rdclass = rdclass;
00101 zt->magic = ZTMAGIC;
00102 zt->loaddone = NULL;
00103 zt->loaddone_arg = NULL;
00104 zt->loads_pending = 0;
00105 *ztp = zt;
00106
00107 return (ISC_R_SUCCESS);
00108
00109 cleanup_rbt:
00110 dns_rbt_destroy(&zt->table);
00111
00112 cleanup_zt:
00113 isc_mem_put(mctx, zt, sizeof(*zt));
00114
00115 return (result);
00116 }
00117
00118 isc_result_t
00119 dns_zt_mount(dns_zt_t *zt, dns_zone_t *zone) {
00120 isc_result_t result;
00121 dns_zone_t *dummy = NULL;
00122 dns_name_t *name;
00123
00124 REQUIRE(VALID_ZT(zt));
00125
00126 name = dns_zone_getorigin(zone);
00127
00128 RWLOCK(&zt->rwlock, isc_rwlocktype_write);
00129
00130 result = dns_rbt_addname(zt->table, name, zone);
00131 if (result == ISC_R_SUCCESS)
00132 dns_zone_attach(zone, &dummy);
00133
00134 RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
00135
00136 return (result);
00137 }
00138
00139 isc_result_t
00140 dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
00141 isc_result_t result;
00142 dns_name_t *name;
00143
00144 REQUIRE(VALID_ZT(zt));
00145
00146 name = dns_zone_getorigin(zone);
00147
00148 RWLOCK(&zt->rwlock, isc_rwlocktype_write);
00149
00150 result = dns_rbt_deletename(zt->table, name, ISC_FALSE);
00151
00152 RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
00153
00154 return (result);
00155 }
00156
00157 isc_result_t
00158 dns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options,
00159 dns_name_t *foundname, dns_zone_t **zonep)
00160 {
00161 isc_result_t result;
00162 dns_zone_t *dummy = NULL;
00163 unsigned int rbtoptions = 0;
00164
00165 REQUIRE(VALID_ZT(zt));
00166
00167 if ((options & DNS_ZTFIND_NOEXACT) != 0)
00168 rbtoptions |= DNS_RBTFIND_NOEXACT;
00169
00170 RWLOCK(&zt->rwlock, isc_rwlocktype_read);
00171
00172 result = dns_rbt_findname(zt->table, name, rbtoptions, foundname,
00173 (void **) (void*)&dummy);
00174 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
00175 dns_zone_attach(dummy, zonep);
00176
00177 RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
00178
00179 return (result);
00180 }
00181
00182 void
00183 dns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp) {
00184
00185 REQUIRE(VALID_ZT(zt));
00186 REQUIRE(ztp != NULL && *ztp == NULL);
00187
00188 RWLOCK(&zt->rwlock, isc_rwlocktype_write);
00189
00190 INSIST(zt->references > 0);
00191 zt->references++;
00192 INSIST(zt->references != 0);
00193
00194 RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
00195
00196 *ztp = zt;
00197 }
00198
00199 static isc_result_t
00200 flush(dns_zone_t *zone, void *uap) {
00201 UNUSED(uap);
00202 return (dns_zone_flush(zone));
00203 }
00204
00205 static void
00206 zt_destroy(dns_zt_t *zt) {
00207 if (zt->flush)
00208 (void)dns_zt_apply(zt, ISC_FALSE, flush, NULL);
00209 dns_rbt_destroy(&zt->table);
00210 isc_rwlock_destroy(&zt->rwlock);
00211 zt->magic = 0;
00212 isc_mem_putanddetach(&zt->mctx, zt, sizeof(*zt));
00213 }
00214
00215 static void
00216 zt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) {
00217 isc_boolean_t destroy = ISC_FALSE;
00218 dns_zt_t *zt;
00219
00220 REQUIRE(ztp != NULL && VALID_ZT(*ztp));
00221
00222 zt = *ztp;
00223
00224 RWLOCK(&zt->rwlock, isc_rwlocktype_write);
00225
00226 INSIST(zt->references > 0);
00227 zt->references--;
00228 if (zt->references == 0)
00229 destroy = ISC_TRUE;
00230 if (need_flush)
00231 zt->flush = ISC_TRUE;
00232
00233 RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
00234
00235 if (destroy)
00236 zt_destroy(zt);
00237
00238 *ztp = NULL;
00239 }
00240
00241 void
00242 dns_zt_flushanddetach(dns_zt_t **ztp) {
00243 zt_flushanddetach(ztp, ISC_TRUE);
00244 }
00245
00246 void
00247 dns_zt_detach(dns_zt_t **ztp) {
00248 zt_flushanddetach(ztp, ISC_FALSE);
00249 }
00250
00251 isc_result_t
00252 dns_zt_load(dns_zt_t *zt, isc_boolean_t stop) {
00253 isc_result_t result;
00254
00255 REQUIRE(VALID_ZT(zt));
00256
00257 RWLOCK(&zt->rwlock, isc_rwlocktype_read);
00258 result = dns_zt_apply(zt, stop, load, NULL);
00259 RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
00260 return (result);
00261 }
00262
00263 static isc_result_t
00264 load(dns_zone_t *zone, void *uap) {
00265 isc_result_t result;
00266 UNUSED(uap);
00267
00268 result = dns_zone_load(zone);
00269 if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE)
00270 result = ISC_R_SUCCESS;
00271
00272 return (result);
00273 }
00274
00275 isc_result_t
00276 dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) {
00277 isc_result_t result;
00278 static dns_zt_zoneloaded_t dl = doneloading;
00279 int pending;
00280
00281 REQUIRE(VALID_ZT(zt));
00282
00283 RWLOCK(&zt->rwlock, isc_rwlocktype_write);
00284
00285 INSIST(zt->loads_pending == 0);
00286 result = dns_zt_apply2(zt, ISC_FALSE, NULL, asyncload, &dl);
00287
00288 pending = zt->loads_pending;
00289 if (pending != 0) {
00290 zt->loaddone = alldone;
00291 zt->loaddone_arg = arg;
00292 }
00293
00294 RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
00295
00296 if (pending == 0)
00297 alldone(arg);
00298
00299 return (result);
00300 }
00301
00302
00303
00304
00305
00306
00307 static isc_result_t
00308 asyncload(dns_zone_t *zone, void *callback) {
00309 isc_result_t result;
00310 dns_zt_zoneloaded_t *loaded = callback;
00311 dns_zt_t *zt;
00312
00313 REQUIRE(zone != NULL);
00314 zt = dns_zone_getview(zone)->zonetable;
00315 INSIST(VALID_ZT(zt));
00316
00317 result = dns_zone_asyncload(zone, *loaded, zt);
00318 if (result == ISC_R_SUCCESS) {
00319 INSIST(zt->references > 0);
00320 zt->references++;
00321 INSIST(zt->references != 0);
00322 zt->loads_pending++;
00323 }
00324 return (ISC_R_SUCCESS);
00325 }
00326
00327 isc_result_t
00328 dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop) {
00329 isc_result_t result;
00330
00331 REQUIRE(VALID_ZT(zt));
00332
00333 RWLOCK(&zt->rwlock, isc_rwlocktype_read);
00334 result = dns_zt_apply(zt, stop, loadnew, NULL);
00335 RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
00336 return (result);
00337 }
00338
00339 static isc_result_t
00340 loadnew(dns_zone_t *zone, void *uap) {
00341 isc_result_t result;
00342 UNUSED(uap);
00343
00344 result = dns_zone_loadnew(zone);
00345 if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE ||
00346 result == DNS_R_DYNAMIC)
00347 result = ISC_R_SUCCESS;
00348 return (result);
00349 }
00350
00351 isc_result_t
00352 dns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze) {
00353 isc_result_t result, tresult;
00354
00355 REQUIRE(VALID_ZT(zt));
00356
00357 RWLOCK(&zt->rwlock, isc_rwlocktype_read);
00358 result = dns_zt_apply2(zt, ISC_FALSE, &tresult, freezezones, &freeze);
00359 RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
00360 if (tresult == ISC_R_NOTFOUND)
00361 tresult = ISC_R_SUCCESS;
00362 return ((result == ISC_R_SUCCESS) ? tresult : result);
00363 }
00364
00365 static isc_result_t
00366 freezezones(dns_zone_t *zone, void *uap) {
00367 isc_boolean_t freeze = *(isc_boolean_t *)uap;
00368 isc_boolean_t frozen;
00369 isc_result_t result = ISC_R_SUCCESS;
00370 char classstr[DNS_RDATACLASS_FORMATSIZE];
00371 char zonename[DNS_NAME_FORMATSIZE];
00372 dns_zone_t *raw = NULL;
00373 dns_view_t *view;
00374 const char *vname;
00375 const char *sep;
00376 int level;
00377
00378 dns_zone_getraw(zone, &raw);
00379 if (raw != NULL)
00380 zone = raw;
00381 if (dns_zone_gettype(zone) != dns_zone_master) {
00382 if (raw != NULL)
00383 dns_zone_detach(&raw);
00384 return (ISC_R_SUCCESS);
00385 }
00386 if (!dns_zone_isdynamic(zone, ISC_TRUE)) {
00387 if (raw != NULL)
00388 dns_zone_detach(&raw);
00389 return (ISC_R_SUCCESS);
00390 }
00391
00392 frozen = dns_zone_getupdatedisabled(zone);
00393 if (freeze) {
00394 if (frozen)
00395 result = DNS_R_FROZEN;
00396 if (result == ISC_R_SUCCESS)
00397 result = dns_zone_flush(zone);
00398 if (result == ISC_R_SUCCESS)
00399 dns_zone_setupdatedisabled(zone, freeze);
00400 } else {
00401 if (frozen) {
00402 result = dns_zone_loadandthaw(zone);
00403 if (result == DNS_R_CONTINUE ||
00404 result == DNS_R_UPTODATE)
00405 result = ISC_R_SUCCESS;
00406 }
00407 }
00408 view = dns_zone_getview(zone);
00409 if (strcmp(view->name, "_bind") == 0 ||
00410 strcmp(view->name, "_default") == 0)
00411 {
00412 vname = "";
00413 sep = "";
00414 } else {
00415 vname = view->name;
00416 sep = " ";
00417 }
00418 dns_rdataclass_format(dns_zone_getclass(zone), classstr,
00419 sizeof(classstr));
00420 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
00421 level = (result != ISC_R_SUCCESS) ? ISC_LOG_ERROR : ISC_LOG_DEBUG(1);
00422 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
00423 level, "%s zone '%s/%s'%s%s: %s",
00424 freeze ? "freezing" : "thawing",
00425 zonename, classstr, sep, vname,
00426 isc_result_totext(result));
00427 if (raw != NULL)
00428 dns_zone_detach(&raw);
00429 return (result);
00430 }
00431
00432 isc_result_t
00433 dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop,
00434 isc_result_t (*action)(dns_zone_t *, void *), void *uap)
00435 {
00436 return (dns_zt_apply2(zt, stop, NULL, action, uap));
00437 }
00438
00439 isc_result_t
00440 dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub,
00441 isc_result_t (*action)(dns_zone_t *, void *), void *uap)
00442 {
00443 dns_rbtnode_t *node;
00444 dns_rbtnodechain_t chain;
00445 isc_result_t result, tresult = ISC_R_SUCCESS;
00446 dns_zone_t *zone;
00447
00448 REQUIRE(VALID_ZT(zt));
00449 REQUIRE(action != NULL);
00450
00451 dns_rbtnodechain_init(&chain, zt->mctx);
00452 result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
00453 if (result == ISC_R_NOTFOUND) {
00454
00455
00456
00457 tresult = result;
00458 result = ISC_R_NOMORE;
00459 }
00460 while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
00461 result = dns_rbtnodechain_current(&chain, NULL, NULL,
00462 &node);
00463 if (result == ISC_R_SUCCESS) {
00464 zone = node->data;
00465 if (zone != NULL)
00466 result = (action)(zone, uap);
00467 if (result != ISC_R_SUCCESS && stop) {
00468 tresult = result;
00469 goto cleanup;
00470 } else if (result != ISC_R_SUCCESS &&
00471 tresult == ISC_R_SUCCESS)
00472 tresult = result;
00473 }
00474 result = dns_rbtnodechain_next(&chain, NULL, NULL);
00475 }
00476 if (result == ISC_R_NOMORE)
00477 result = ISC_R_SUCCESS;
00478
00479 cleanup:
00480 dns_rbtnodechain_invalidate(&chain);
00481 if (sub != NULL)
00482 *sub = tresult;
00483
00484 return (result);
00485 }
00486
00487
00488
00489
00490
00491
00492 static isc_result_t
00493 doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
00494 isc_boolean_t destroy = ISC_FALSE;
00495 dns_zt_allloaded_t alldone = NULL;
00496 void *arg = NULL;
00497
00498 UNUSED(zone);
00499 UNUSED(task);
00500
00501 REQUIRE(VALID_ZT(zt));
00502
00503 RWLOCK(&zt->rwlock, isc_rwlocktype_write);
00504 INSIST(zt->loads_pending != 0);
00505 INSIST(zt->references != 0);
00506 zt->references--;
00507 if (zt->references == 0)
00508 destroy = ISC_TRUE;
00509 zt->loads_pending--;
00510 if (zt->loads_pending == 0) {
00511 alldone = zt->loaddone;
00512 arg = zt->loaddone_arg;
00513 zt->loaddone = NULL;
00514 zt->loaddone_arg = NULL;
00515 }
00516 RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
00517
00518 if (alldone != NULL)
00519 alldone(arg);
00520
00521 if (destroy)
00522 zt_destroy(zt);
00523
00524 return (ISC_R_SUCCESS);
00525 }
00526
00527
00528
00529
00530
00531 static void
00532 auto_detach(void *data, void *arg) {
00533 dns_zone_t *zone = data;
00534
00535 UNUSED(arg);
00536 dns_zone_detach(&zone);
00537 }