OpenDNSSEC-signer
1.3.4
|
00001 /* 00002 * $Id: zone.c 5802 2011-10-19 14:07:31Z matthijs $ 00003 * 00004 * Copyright (c) 2009 NLNet Labs. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00034 #include "adapter/adapi.h" 00035 #include "adapter/adapter.h" 00036 #include "scheduler/schedule.h" 00037 #include "scheduler/task.h" 00038 #include "shared/allocator.h" 00039 #include "shared/file.h" 00040 #include "shared/hsm.h" 00041 #include "shared/locks.h" 00042 #include "shared/log.h" 00043 #include "shared/status.h" 00044 #include "shared/util.h" 00045 #include "signer/backup.h" 00046 #include "signer/nsec3params.h" 00047 #include "signer/signconf.h" 00048 #include "signer/zone.h" 00049 #include "signer/zonedata.h" 00050 00051 #include <ldns/ldns.h> 00052 00053 static const char* zone_str = "zone"; 00054 00055 00060 zone_type* 00061 zone_create(char* name, ldns_rr_class klass) 00062 { 00063 allocator_type* allocator = NULL; 00064 zone_type* zone = NULL; 00065 00066 if (!name || !klass) { 00067 ods_log_error("[%s] unable to create zone: no name or class", 00068 zone_str); 00069 return NULL; 00070 } 00071 00072 allocator = allocator_create(malloc, free); 00073 if (!allocator) { 00074 ods_log_error("[%s] unable to create zone %s: create allocator " 00075 "failed", zone_str, name); 00076 return NULL; 00077 } 00078 ods_log_assert(allocator); 00079 00080 zone = (zone_type*) allocator_alloc(allocator, sizeof(zone_type)); 00081 if (!zone) { 00082 ods_log_error("[%s] unable to create zone %s: allocator failed", 00083 zone_str, name); 00084 allocator_cleanup(allocator); 00085 return NULL; 00086 } 00087 ods_log_assert(zone); 00088 00089 zone->allocator = allocator; 00090 /* [start] PS 9218653: Drop trailing dot in domain name */ 00091 if (strlen(name) > 1 && name[strlen(name)-1] == '.') { 00092 name[strlen(name)-1] = '\0'; 00093 } 00094 /* [end] PS 9218653 */ 00095 zone->name = allocator_strdup(allocator, name); 00096 zone->klass = klass; 00097 00098 zone->dname = ldns_dname_new_frm_str(name); 00099 ldns_dname2canonical(zone->dname); 00100 zone->notify_ns = NULL; 00101 zone->policy_name = NULL; 00102 zone->signconf_filename = NULL; 00103 00104 zone->adinbound = NULL; 00105 zone->adoutbound = NULL; 00106 zone->nsec3params = NULL; 00107 00108 zone->just_added = 0; 00109 zone->just_updated = 0; 00110 zone->tobe_removed = 0; 00111 zone->processed = 0; 00112 zone->prepared = 0; 00113 zone->fetch = 0; 00114 00115 zone->zonedata = zonedata_create(zone->allocator); 00116 if (!zone->zonedata) { 00117 ods_log_error("[%s] unable to create zone %s: create zonedata " 00118 "failed", zone_str, name); 00119 zone_cleanup(zone); 00120 return NULL; 00121 } 00122 00123 zone->signconf = signconf_create(); 00124 if (!zone->signconf) { 00125 ods_log_error("[%s] unable to create zone %s: create signconf " 00126 "failed", zone_str, name); 00127 zone_cleanup(zone); 00128 return NULL; 00129 } 00130 00131 zone->stats = stats_create(); 00132 zone->task = NULL; 00133 lock_basic_init(&zone->zone_lock); 00134 return zone; 00135 } 00136 00137 00142 ods_status 00143 zone_add_rr(zone_type* zone, ldns_rr* rr, int do_stats) 00144 { 00145 domain_type* domain = NULL; 00146 rrset_type* rrset = NULL; 00147 ldns_rdf* soa_min = NULL; 00148 ldns_rr_type type = LDNS_RR_TYPE_FIRST; 00149 uint32_t tmp = 0; 00150 00151 if (!rr) { 00152 ods_log_error("[%s] unable to add RR: no RR", zone_str); 00153 return ODS_STATUS_ASSERT_ERR; 00154 } 00155 ods_log_assert(rr); 00156 00157 if (!zone || !zone->zonedata) { 00158 ods_log_error("[%s] unable to add RR: no storage", zone_str); 00159 return ODS_STATUS_ASSERT_ERR; 00160 } 00161 ods_log_assert(zone); 00162 ods_log_assert(zone->zonedata); 00163 00164 if (!zone->signconf) { 00165 ods_log_error("[%s] unable to add RR: no signconf", zone_str); 00166 return ODS_STATUS_ASSERT_ERR; 00167 } 00168 ods_log_assert(zone->signconf); 00169 00170 /* in-zone? */ 00171 if (ldns_dname_compare(zone->dname, ldns_rr_owner(rr)) != 0 && 00172 !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->dname)) { 00173 ods_log_warning("[%s] zone %s contains out-of-zone data, skipping", 00174 zone_str, zone->name?zone->name:"(null)"); 00175 /* ok, just filter */ 00176 ldns_rr_free(rr); 00177 return ODS_STATUS_OK; 00178 } 00179 00180 /* type specific configuration */ 00181 type = ldns_rr_get_type(rr); 00182 if (type == LDNS_RR_TYPE_DNSKEY && zone->signconf->dnskey_ttl) { 00183 tmp = (uint32_t) duration2time(zone->signconf->dnskey_ttl); 00184 ods_log_verbose("[%s] zone %s set DNSKEY TTL to %u", 00185 zone_str, zone->name?zone->name:"(null)", tmp); 00186 ldns_rr_set_ttl(rr, tmp); 00187 } 00188 if (type == LDNS_RR_TYPE_SOA) { 00189 if (zone->signconf->soa_ttl) { 00190 tmp = (uint32_t) duration2time(zone->signconf->soa_ttl); 00191 ods_log_verbose("[%s] zone %s set SOA TTL to %u", 00192 zone_str, zone->name?zone->name:"(null)", tmp); 00193 ldns_rr_set_ttl(rr, tmp); 00194 } 00195 if (zone->signconf->soa_min) { 00196 tmp = (uint32_t) duration2time(zone->signconf->soa_min); 00197 ods_log_verbose("[%s] zone %s set SOA MINIMUM to %u", 00198 zone_str, zone->name?zone->name:"(null)", tmp); 00199 soa_min = ldns_rr_set_rdf(rr, 00200 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, tmp), 00201 SE_SOA_RDATA_MINIMUM); 00202 if (soa_min) { 00203 ldns_rdf_deep_free(soa_min); 00204 } else { 00205 ods_log_error("[%s] zone %s failed to replace SOA MINIMUM " 00206 "rdata", zone_str, zone->name?zone->name:"(null)"); 00207 return ODS_STATUS_ASSERT_ERR; 00208 } 00209 } 00210 } 00211 00212 /* lookup domain */ 00213 domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr)); 00214 if (!domain) { 00215 /* add domain */ 00216 domain = domain_create(ldns_rr_owner(rr)); 00217 if (!domain) { 00218 ods_log_error("[%s] unable to add RR: create domain failed", 00219 zone_str); 00220 return ODS_STATUS_ERR; 00221 } 00222 if (zonedata_add_domain(zone->zonedata, domain) == NULL) { 00223 ods_log_error("[%s] unable to add RR: add domain failed", 00224 zone_str); 00225 return ODS_STATUS_ERR; 00226 } 00227 if (ldns_dname_compare(domain->dname, zone->dname) == 0) { 00228 domain->dstatus = DOMAIN_STATUS_APEX; 00229 } 00230 } 00231 ods_log_assert(domain); 00232 00233 /* lookup RRset */ 00234 rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr)); 00235 if (!rrset) { 00236 /* add RRset */ 00237 rrset = rrset_create(ldns_rr_get_type(rr)); 00238 if (!rrset) { 00239 ods_log_error("[%s] unable to add RR: create RRset failed", 00240 zone_str); 00241 return ODS_STATUS_ERR; 00242 } 00243 if (domain_add_rrset(domain, rrset) == NULL) { 00244 ods_log_error("[%s] unable to add RR: add RRset failed", 00245 zone_str); 00246 return ODS_STATUS_ERR; 00247 } 00248 } 00249 ods_log_assert(rrset); 00250 00251 /* add RR */ 00252 if (rrset_add_rr(rrset, rr) == NULL) { 00253 ods_log_error("[%s] unable to add RR: pend RR failed", zone_str); 00254 return ODS_STATUS_ERR; 00255 } 00256 00257 /* update stats */ 00258 if (zone->stats && do_stats) { 00259 zone->stats->sort_count += 1; 00260 } 00261 return ODS_STATUS_OK; 00262 } 00263 00264 00269 ods_status 00270 zone_del_rr(zone_type* zone, ldns_rr* rr, int do_stats) 00271 { 00272 domain_type* domain = NULL; 00273 rrset_type* rrset = NULL; 00274 00275 if (!rr) { 00276 ods_log_error("[%s] unable to del RR: no RR", zone_str); 00277 return ODS_STATUS_ASSERT_ERR; 00278 } 00279 ods_log_assert(rr); 00280 00281 if (!zone || !zone->zonedata) { 00282 ods_log_error("[%s] unable to del RR: no storage", zone_str); 00283 return ODS_STATUS_ASSERT_ERR; 00284 } 00285 ods_log_assert(zone); 00286 ods_log_assert(zone->zonedata); 00287 00288 /* lookup domain */ 00289 domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr)); 00290 if (!domain) { 00291 /* no domain, no del */ 00292 ods_log_warning("[%s] unable to del RR: no such domain", zone_str); 00293 return ODS_STATUS_UNCHANGED; 00294 } 00295 ods_log_assert(domain); 00296 00297 /* lookup RRset */ 00298 rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr)); 00299 if (!rrset) { 00300 /* no RRset, no del */ 00301 ods_log_warning("[%s] unable to del RR: no such RRset", zone_str); 00302 return ODS_STATUS_UNCHANGED; 00303 } 00304 ods_log_assert(rrset); 00305 00306 /* del RR */ 00307 if (rrset_del_rr(rrset, rr, (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY)) 00308 == NULL) { 00309 ods_log_error("[%s] unable to del RR: pend RR failed", zone_str); 00310 return ODS_STATUS_ERR; 00311 } 00312 00313 /* update stats */ 00314 if (do_stats && zone->stats) { 00315 zone->stats->sort_count -= 1; 00316 } 00317 return ODS_STATUS_OK; 00318 } 00319 00320 00325 static ods_status 00326 dnskey_withdraw(zone_type* zone, ldns_rr_list* del) 00327 { 00328 ldns_rr* clone = NULL; 00329 ods_status status = ODS_STATUS_OK; 00330 size_t i = 0; 00331 00332 for (i=0; i < ldns_rr_list_rr_count(del); i++) { 00333 clone = ldns_rr_clone(ldns_rr_list_rr(del, i)); 00334 status = zone_del_rr(zone, clone, 0); 00335 if (status != ODS_STATUS_OK) { 00336 return status; 00337 } 00338 } 00339 return status; 00340 } 00341 00342 00347 static ods_status 00348 nsec3param_withdraw(zone_type* zone, ldns_rr* rr) 00349 { 00350 ldns_rr* clone = NULL; 00351 ods_status status = ODS_STATUS_OK; 00352 00353 if (!rr) { /* no nsec3param, nothing to withdraw */ 00354 return status; 00355 } 00356 clone = ldns_rr_clone(rr); 00357 status = zone_del_rr(zone, clone, 0); 00358 if (status != ODS_STATUS_OK) { 00359 return status; 00360 } 00361 return status; 00362 } 00363 00364 00369 ods_status 00370 zone_load_signconf(zone_type* zone, task_id* tbs) 00371 { 00372 ods_status status = ODS_STATUS_OK; 00373 signconf_type* signconf = NULL; 00374 ldns_rr_list* del = NULL; 00375 char* datestamp = NULL; 00376 uint32_t ustamp = 0; 00377 task_id denial_what; 00378 task_id keys_what; 00379 task_id what; 00380 00381 if (!zone) { 00382 ods_log_error("[%s] unable to load signconf: no zone", zone_str); 00383 return ODS_STATUS_ASSERT_ERR; 00384 } 00385 ods_log_assert(zone); 00386 if (!zone->signconf_filename) { 00387 ods_log_warning("[%s] zone %s has no signconf filename, treat as " 00388 "insecure?", zone_str, zone->name); 00389 return ODS_STATUS_INSECURE; 00390 } 00391 ods_log_assert(zone->signconf_filename); 00392 00393 status = signconf_update(&signconf, zone->signconf_filename, 00394 zone->signconf->last_modified); 00395 if (status == ODS_STATUS_OK) { 00396 if (!signconf) { 00397 /* this is unexpected */ 00398 ods_log_error("[%s] unable to load signconf: zone %s signconf " 00399 "%s: storage empty", zone_str, zone->name, 00400 zone->signconf_filename); 00401 return ODS_STATUS_ASSERT_ERR; 00402 } 00403 ustamp = time_datestamp(signconf->last_modified, "%Y-%m-%d %T", 00404 &datestamp); 00405 ods_log_debug("[%s] zone %s signconf file %s is modified since %s", 00406 zone_str, zone->name, zone->signconf_filename, 00407 datestamp?datestamp:"Unknown"); 00408 free((void*)datestamp); 00409 00410 /* do stuff */ 00411 del = ldns_rr_list_new(); 00412 if (!del) { 00413 ods_log_error("[%s] unable to load signconf: zone %s " 00414 "signconf %s: ldns_rr_list_new() failed", 00415 zone_str, zone->name, zone->signconf_filename); 00416 return ODS_STATUS_MALLOC_ERR; 00417 } 00418 denial_what = signconf_compare_denial(zone->signconf, signconf); 00419 keys_what = signconf_compare_keys(zone->signconf, signconf, del); 00420 00421 /* Key Rollover? */ 00422 if (keys_what == TASK_READ) { 00423 status = dnskey_withdraw(zone, del); 00424 } 00425 ldns_rr_list_free(del); 00426 if (status != ODS_STATUS_OK) { 00427 ods_log_error("[%s] unable to load signconf: zone %s " 00428 "signconf %s: failed to delete DNSKEY from RRset", 00429 zone_str, zone->name, zone->signconf_filename); 00430 zonedata_rollback(zone->zonedata); 00431 return status; 00432 } 00433 00434 /* Denial of Existence Rollover? */ 00435 if (denial_what == TASK_NSECIFY) { 00436 status = ODS_STATUS_OK; 00437 if (denial_what == TASK_NSECIFY && zone->nsec3params) { 00438 status = nsec3param_withdraw(zone, zone->nsec3params->rr); 00439 } 00440 if (status != ODS_STATUS_OK) { 00441 ods_log_error("[%s] unable to load signconf: zone %s " 00442 "signconf %s: failed to delete NSEC3PARAM RRset", 00443 zone_str, zone->name, zone->signconf_filename); 00444 zonedata_rollback(zone->zonedata); 00445 return status; 00446 } 00447 /* or NSEC -> NSEC3, or NSEC3 -> NSEC, or NSEC3PARAM changed */ 00448 nsec3params_cleanup(zone->nsec3params); 00449 zone->nsec3params = NULL; 00450 /* all NSEC(3)s become invalid */ 00451 zonedata_wipe_denial(zone->zonedata); 00452 zonedata_cleanup_chain(zone->zonedata); 00453 zonedata_init_denial(zone->zonedata); 00454 } 00455 00456 /* all ok, switch to new signconf */ 00457 if (keys_what != TASK_NONE) { 00458 what = keys_what; 00459 } else { 00460 what = denial_what; 00461 } 00462 if (what == TASK_NONE) { /* no major changes, continue signing */ 00463 what = TASK_SIGN; 00464 } 00465 *tbs = what; 00466 ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str, 00467 zone->name, task_what2str(*tbs)); 00468 signconf_cleanup(zone->signconf); 00469 ods_log_debug("[%s] zone %s switch to new signconf", zone_str, 00470 zone->name); 00471 zone->signconf = signconf; 00472 signconf_log(zone->signconf, zone->name); 00473 zone->zonedata->default_ttl = 00474 (uint32_t) duration2time(zone->signconf->soa_min); 00475 } else if (status == ODS_STATUS_UNCHANGED) { 00476 *tbs = TASK_READ; 00477 ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str, 00478 zone->name, task_what2str(*tbs)); 00479 ustamp = time_datestamp(zone->signconf->last_modified, 00480 "%Y-%m-%d %T", &datestamp); 00481 ods_log_verbose("[%s] zone %s signconf file %s is unchanged since " 00482 "%s", zone_str, zone->name, zone->signconf_filename, 00483 datestamp?datestamp:"Unknown"); 00484 free((void*)datestamp); 00485 } else { 00486 ods_log_error("[%s] unable to load signconf: zone %s signconf %s: " 00487 "%s", zone_str, zone->name, zone->signconf_filename, 00488 ods_status2str(status)); 00489 } 00490 return status; 00491 } 00492 00493 00498 ods_status 00499 zone_publish_dnskeys(zone_type* zone, int recover) 00500 { 00501 hsm_ctx_t* ctx = NULL; 00502 key_type* key = NULL; 00503 uint32_t ttl = 0; 00504 size_t count = 0; 00505 ods_status status = ODS_STATUS_OK; 00506 ldns_rr* dnskey = NULL; 00507 int do_publish = 0; 00508 00509 if (!zone) { 00510 ods_log_error("[%s] unable to publish dnskeys: no zone", zone_str); 00511 return ODS_STATUS_ASSERT_ERR; 00512 } 00513 ods_log_assert(zone); 00514 00515 if (!zone->signconf) { 00516 ods_log_error("[%s] unable to publish dnskeys zone %s: no signconf", 00517 zone_str, zone->name); 00518 return ODS_STATUS_ASSERT_ERR; 00519 } 00520 ods_log_assert(zone->signconf); 00521 00522 if (!zone->signconf->keys) { 00523 ods_log_error("[%s] unable to publish dnskeys zone %s: no keys", 00524 zone_str, zone->name); 00525 return ODS_STATUS_ASSERT_ERR; 00526 } 00527 ods_log_assert(zone->signconf->keys); 00528 00529 if (!zone->zonedata) { 00530 ods_log_error("[%s] unable to publish dnskeys zone %s: no zonedata", 00531 zone_str, zone->name); 00532 return ODS_STATUS_ASSERT_ERR; 00533 } 00534 ods_log_assert(zone->zonedata); 00535 00536 ttl = zone->zonedata->default_ttl; 00537 if (zone->signconf->dnskey_ttl) { 00538 ttl = (uint32_t) duration2time(zone->signconf->dnskey_ttl); 00539 } 00540 00541 ctx = hsm_create_context(); 00542 if (ctx == NULL) { 00543 ods_log_error("[%s] unable to publish dnskeys for zone %s: error " 00544 "creating libhsm context", zone_str, zone->name); 00545 return ODS_STATUS_HSM_ERR; 00546 } 00547 00548 key = zone->signconf->keys->first_key; 00549 for (count=0; count < zone->signconf->keys->count; count++) { 00550 if (key->publish) { 00551 do_publish = 0; 00552 if (!key->dnskey) { 00553 do_publish = 1; 00554 } 00555 00556 status = lhsm_get_key(ctx, zone->dname, key); 00557 if (status != ODS_STATUS_OK) { 00558 ods_log_error("[%s] unable to publish dnskeys zone %s: " 00559 "error creating DNSKEY for key %s", zone_str, 00560 zone->name, key->locator?key->locator:"(null)"); 00561 break; 00562 } 00563 ods_log_assert(key->dnskey); 00564 00565 if (recover) { 00566 dnskey = ldns_rr_clone(key->dnskey); 00567 status = zone_add_rr(zone, dnskey, 0); 00568 } else if (do_publish) { 00569 ldns_rr_set_ttl(key->dnskey, ttl); 00570 ldns_rr_set_class(key->dnskey, zone->klass); 00571 ldns_rr2canonical(key->dnskey); 00572 dnskey = ldns_rr_clone(key->dnskey); 00573 status = zone_add_rr(zone, dnskey, 0); 00574 } else { 00575 status = ODS_STATUS_OK; 00576 } 00577 00578 if (status != ODS_STATUS_OK) { 00579 ods_log_error("[%s] unable to publish dnskeys zone %s: " 00580 "error adding DNSKEY[%u] for key %s", zone_str, 00581 zone->name, ldns_calc_keytag(dnskey), 00582 key->locator?key->locator:"(null)"); 00583 break; 00584 } 00585 } 00586 key = key->next; 00587 } 00588 00589 if (status != ODS_STATUS_OK) { 00590 zonedata_rollback(zone->zonedata); 00591 } 00592 00593 hsm_destroy_context(ctx); 00594 ctx = NULL; 00595 return status; 00596 } 00597 00598 00603 ods_status 00604 zone_prepare_nsec3(zone_type* zone, int recover) 00605 { 00606 ldns_rr* nsec3params_rr = NULL; 00607 domain_type* apex = NULL; 00608 rrset_type* rrset = NULL; 00609 ods_status status = ODS_STATUS_OK; 00610 00611 if (!zone) { 00612 ods_log_error("[%s] unable to prepare NSEC3: no zone", zone_str); 00613 return ODS_STATUS_ASSERT_ERR; 00614 } 00615 ods_log_assert(zone); 00616 00617 if (!zone->signconf) { 00618 ods_log_error("[%s] unable to prepare NSEC3: no signconf", zone_str); 00619 return ODS_STATUS_ASSERT_ERR; 00620 } 00621 ods_log_assert(zone->signconf); 00622 00623 if (zone->signconf->nsec_type != LDNS_RR_TYPE_NSEC3) { 00624 /* no preparations needed */ 00625 return ODS_STATUS_OK; 00626 } 00627 00628 if (!zone->nsec3params) { 00629 ods_log_debug("[%s] prepare NSEC3 for zone %s", zone_str, zone->name); 00630 00631 zone->nsec3params = nsec3params_create( 00632 (uint8_t) zone->signconf->nsec3_algo, 00633 (uint8_t) zone->signconf->nsec3_optout, 00634 (uint16_t) zone->signconf->nsec3_iterations, 00635 zone->signconf->nsec3_salt); 00636 } 00637 if (!zone->nsec3params) { 00638 ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed " 00639 "to create NSEC3 parameters", zone_str, zone->name); 00640 return ODS_STATUS_MALLOC_ERR; 00641 } 00642 ods_log_assert(zone->nsec3params); 00643 00644 if (recover) { 00645 nsec3params_rr = ldns_rr_clone(zone->nsec3params->rr); 00646 status = zone_add_rr(zone, nsec3params_rr, 0); 00647 } else { 00648 nsec3params_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS); 00649 if (!nsec3params_rr) { 00650 ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed " 00651 "to create NSEC3PARAM RR", zone_str, zone->name); 00652 nsec3params_cleanup(zone->nsec3params); 00653 return ODS_STATUS_MALLOC_ERR; 00654 } 00655 ods_log_assert(nsec3params_rr); 00656 00657 ldns_rr_set_class(nsec3params_rr, zone->klass); 00658 ldns_rr_set_ttl(nsec3params_rr, zone->zonedata->default_ttl); 00659 ldns_rr_set_owner(nsec3params_rr, ldns_rdf_clone(zone->dname)); 00660 ldns_nsec3_add_param_rdfs(nsec3params_rr, 00661 zone->nsec3params->algorithm, 0, 00662 zone->nsec3params->iterations, 00663 zone->nsec3params->salt_len, 00664 zone->nsec3params->salt_data); 00669 ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params_rr, 1)), 7, 0); 00670 00671 ldns_rr2canonical(nsec3params_rr); 00672 zone->nsec3params->rr = ldns_rr_clone(nsec3params_rr); 00673 status = zone_add_rr(zone, nsec3params_rr, 0); 00674 } 00675 00676 if (status != ODS_STATUS_OK) { 00677 ods_log_error("[%s] unable to add NSEC3PARAM RR to zone %s", 00678 zone_str, zone->name); 00679 nsec3params_cleanup(zone->nsec3params); 00680 zone->nsec3params = NULL; 00681 ldns_rr_free(nsec3params_rr); 00682 } else if (!recover) { 00683 /* add ok, wipe out previous nsec3params */ 00684 apex = zonedata_lookup_domain(zone->zonedata, zone->dname); 00685 if (!apex) { 00686 ods_log_crit("[%s] unable to delete previous NSEC3PARAM RR " 00687 "from zone %s: apex undefined", zone_str, zone->name); 00688 nsec3params_cleanup(zone->nsec3params); 00689 zone->nsec3params = NULL; 00690 zonedata_rollback(zone->zonedata); 00691 return ODS_STATUS_ASSERT_ERR; 00692 } 00693 ods_log_assert(apex); 00694 00695 rrset = domain_lookup_rrset(apex, LDNS_RR_TYPE_NSEC3PARAMS); 00696 if (rrset) { 00697 status = rrset_wipe_out(rrset); 00698 if (status != ODS_STATUS_OK) { 00699 ods_log_error("[%s] unable to wipe out previous " 00700 "NSEC3PARAM RR from zone %s", zone_str, zone->name); 00701 nsec3params_cleanup(zone->nsec3params); 00702 zone->nsec3params = NULL; 00703 rrset_rollback(rrset); 00704 return status; 00705 } 00706 } 00707 } 00708 return status; 00709 } 00710 00711 00716 ods_status 00717 zone_backup(zone_type* zone) 00718 { 00719 char* filename = NULL; 00720 FILE* fd = NULL; 00721 00722 ods_log_assert(zone); 00723 ods_log_assert(zone->zonedata); 00724 ods_log_assert(zone->signconf); 00725 00726 filename = ods_build_path(zone->name, ".backup", 0); 00727 fd = ods_fopen(filename, NULL, "w"); 00728 free((void*)filename); 00729 00730 if (fd) { 00731 fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC); 00733 fprintf(fd, ";;Zone: name %s class %i ttl %u inbound %u internal " 00734 "%u outbound %u\n", 00735 zone->name?zone->name:"(null)", 00736 (int) zone->klass, 00737 (unsigned) zone->zonedata->default_ttl, 00738 (unsigned) zone->zonedata->inbound_serial, 00739 (unsigned) zone->zonedata->internal_serial, 00740 (unsigned) zone->zonedata->outbound_serial); 00742 if (zone->task) { 00743 task_backup(fd, (task_type*) zone->task); 00744 } 00746 signconf_backup(fd, zone->signconf); 00747 fprintf(fd, ";;\n"); 00749 if (zone->nsec3params) { 00750 nsec3params_backup(fd, 00751 zone->signconf->nsec3_algo, 00752 zone->signconf->nsec3_optout, 00753 zone->signconf->nsec3_iterations, 00754 zone->signconf->nsec3_salt, 00755 zone->nsec3params->rr); 00756 } 00758 keylist_backup(fd, zone->signconf->keys); 00760 zonedata_backup(fd, zone->zonedata); 00762 fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC); 00763 ods_fclose(fd); 00764 } else { 00765 return ODS_STATUS_FOPEN_ERR; 00766 } 00767 return ODS_STATUS_OK; 00768 } 00769 00770 00775 ods_status 00776 zone_recover(zone_type* zone) 00777 { 00778 char* filename = NULL; 00779 FILE* fd = NULL; 00780 const char* token = NULL; 00781 ods_status status = ODS_STATUS_OK; 00782 /* zone part */ 00783 int klass = 0; 00784 uint32_t ttl = 0; 00785 uint32_t inbound = 0; 00786 uint32_t internal = 0; 00787 uint32_t outbound = 0; 00788 /* task part */ 00789 task_type* task = NULL; 00790 time_t when = 0; 00791 time_t backoff = 0; 00792 int what = 0; 00793 int interrupt = 0; 00794 int halted = 0; 00795 int flush = 0; 00796 /* signconf part */ 00797 time_t lastmod = 0; 00798 /* nsec3params part */ 00799 const char* salt = NULL; 00800 ldns_rr* nsec3params_rr = NULL; 00801 nsec3params_type* nsec3params = NULL; 00802 /* keys part */ 00803 key_type* key = NULL; 00804 /* zonedata part */ 00805 int fetch = 0; 00806 00807 ods_log_assert(zone); 00808 ods_log_assert(zone->signconf); 00809 ods_log_assert(zone->zonedata); 00810 00811 filename = ods_build_path(zone->name, ".backup", 0); 00812 fd = ods_fopen(filename, NULL, "r"); 00813 free((void*)filename); 00814 if (fd) { 00815 /* start recovery */ 00816 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC) || 00817 /* zone part */ 00818 !backup_read_check_str(fd, ";;Zone:") || 00819 !backup_read_check_str(fd, "name") || 00820 !backup_read_check_str(fd, zone->name) || 00821 !backup_read_check_str(fd, "class") || 00822 !backup_read_int(fd, &klass) || 00823 !backup_read_check_str(fd, "ttl") || 00824 !backup_read_uint32_t(fd, &ttl) || 00825 !backup_read_check_str(fd, "inbound") || 00826 !backup_read_uint32_t(fd, &inbound) || 00827 !backup_read_check_str(fd, "internal") || 00828 !backup_read_uint32_t(fd, &internal) || 00829 !backup_read_check_str(fd, "outbound") || 00830 !backup_read_uint32_t(fd, &outbound) || 00831 /* task part */ 00832 !backup_read_check_str(fd, ";;Task:") || 00833 !backup_read_check_str(fd, "when") || 00834 !backup_read_time_t(fd, &when) || 00835 !backup_read_check_str(fd, "what") || 00836 !backup_read_int(fd, &what) || 00837 !backup_read_check_str(fd, "interrupt") || 00838 !backup_read_int(fd, &interrupt) || 00839 !backup_read_check_str(fd, "halted") || 00840 !backup_read_int(fd, &halted) || 00841 !backup_read_check_str(fd, "backoff") || 00842 !backup_read_time_t(fd, &backoff) || 00843 !backup_read_check_str(fd, "flush") || 00844 !backup_read_int(fd, &flush) || 00845 /* signconf part */ 00846 !backup_read_check_str(fd, ";;Signconf:") || 00847 !backup_read_check_str(fd, "lastmod") || 00848 !backup_read_time_t(fd, &lastmod) || 00849 !backup_read_check_str(fd, "resign") || 00850 !backup_read_duration(fd, 00851 &zone->signconf->sig_resign_interval) || 00852 !backup_read_check_str(fd, "refresh") || 00853 !backup_read_duration(fd, 00854 &zone->signconf->sig_refresh_interval) || 00855 !backup_read_check_str(fd, "valid") || 00856 !backup_read_duration(fd, 00857 &zone->signconf->sig_validity_default) || 00858 !backup_read_check_str(fd, "denial") || 00859 !backup_read_duration(fd, 00860 &zone->signconf->sig_validity_denial) || 00861 !backup_read_check_str(fd, "jitter") || 00862 !backup_read_duration(fd, &zone->signconf->sig_jitter) || 00863 !backup_read_check_str(fd, "offset") || 00864 !backup_read_duration(fd, 00865 &zone->signconf->sig_inception_offset) || 00866 !backup_read_check_str(fd, "nsec") || 00867 !backup_read_rr_type(fd, &zone->signconf->nsec_type) || 00868 !backup_read_check_str(fd, "dnskeyttl") || 00869 !backup_read_duration(fd, &zone->signconf->dnskey_ttl) || 00870 !backup_read_check_str(fd, "soattl") || 00871 !backup_read_duration(fd, &zone->signconf->soa_ttl) || 00872 !backup_read_check_str(fd, "soamin") || 00873 !backup_read_duration(fd, &zone->signconf->soa_min) || 00874 !backup_read_check_str(fd, "serial") || 00875 !backup_read_str(fd, &zone->signconf->soa_serial) || 00876 !backup_read_check_str(fd, "audit") || 00877 !backup_read_int(fd, &zone->signconf->audit) || 00878 !backup_read_check_str(fd, ";;")) { 00879 goto recover_error; 00880 } 00881 /* nsec3params part */ 00882 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00883 if (!backup_read_check_str(fd, ";;Nsec3parameters:") || 00884 !backup_read_check_str(fd, "salt") || 00885 !backup_read_str(fd, &salt) || 00886 !backup_read_check_str(fd, "algorithm") || 00887 !backup_read_uint32_t(fd, &zone->signconf->nsec3_algo) || 00888 !backup_read_check_str(fd, "optout") || 00889 !backup_read_int(fd, &zone->signconf->nsec3_optout) || 00890 !backup_read_check_str(fd, "iterations") || 00891 !backup_read_uint32_t(fd, 00892 &zone->signconf->nsec3_iterations) || 00893 ldns_rr_new_frm_fp(&nsec3params_rr, fd, NULL, NULL, NULL) || 00894 !backup_read_check_str(fd, ";;Nsec3done") || 00895 !backup_read_check_str(fd, ";;")) { 00896 goto recover_error; 00897 } 00898 } 00899 /* keys part */ 00900 zone->signconf->keys = keylist_create(zone->signconf->allocator); 00901 while (backup_read_str(fd, &token)) { 00902 if (ods_strcmp(token, ";;Key:") == 0) { 00903 key = key_recover(fd, zone->signconf->allocator); 00904 if (!key || keylist_push(zone->signconf->keys, key) != 00905 ODS_STATUS_OK) { 00906 goto recover_error; 00907 } 00908 key = NULL; 00909 } else if (ods_strcmp(token, ";;") == 0) { 00910 /* keylist done */ 00911 free((void*) token); 00912 token = NULL; 00913 break; 00914 } else { 00915 /* keylist corrupted */ 00916 goto recover_error; 00917 } 00918 free((void*) token); 00919 token = NULL; 00920 } 00921 /* zonedata part */ 00922 filename = ods_build_path(zone->name, ".inbound", 0); 00923 status = adbackup_read(zone, filename); 00924 free((void*)filename); 00925 if (status != ODS_STATUS_OK) { 00926 goto recover_error; 00927 } 00928 00929 zone->klass = (ldns_rr_class) klass; 00930 zone->zonedata->default_ttl = ttl; 00931 zone->zonedata->inbound_serial = inbound; 00932 zone->zonedata->internal_serial = internal; 00933 zone->zonedata->outbound_serial = outbound; 00934 zone->signconf->nsec3_salt = allocator_strdup( 00935 zone->signconf->allocator, salt); 00936 free((void*) salt); 00937 salt = NULL; 00938 task = task_create((task_id) what, when, zone->name, (void*) zone); 00939 if (!task) { 00940 goto recover_error; 00941 } 00942 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00943 nsec3params = nsec3params_create(zone->signconf->nsec3_algo, 00944 zone->signconf->nsec3_optout, 00945 zone->signconf->nsec3_iterations, 00946 zone->signconf->nsec3_salt); 00947 if (!nsec3params) { 00948 goto recover_error; 00949 } 00950 nsec3params->rr = nsec3params_rr; 00951 zone->nsec3params = nsec3params; 00952 } 00953 zone->task = (void*) task; 00954 zone->signconf->last_modified = lastmod; 00955 00956 status = zone_publish_dnskeys(zone, 1); 00957 if (status != ODS_STATUS_OK) { 00958 zone->task = NULL; 00959 zone->nsec3params = NULL; 00960 goto recover_error; 00961 } 00962 status = zone_prepare_nsec3(zone, 1); 00963 if (status != ODS_STATUS_OK) { 00964 zone->task = NULL; 00965 zone->nsec3params = NULL; 00966 goto recover_error; 00967 } 00968 status = zonedata_commit(zone->zonedata); 00969 if (status != ODS_STATUS_OK) { 00970 zone->task = NULL; 00971 zone->nsec3params = NULL; 00972 goto recover_error; 00973 } 00974 status = zonedata_entize(zone->zonedata, zone->dname); 00975 if (status != ODS_STATUS_OK) { 00976 zone->task = NULL; 00977 zone->nsec3params = NULL; 00978 goto recover_error; 00979 } 00980 status = zonedata_recover(zone->zonedata, fd); 00981 if (status != ODS_STATUS_OK) { 00982 zone->task = NULL; 00983 zone->nsec3params = NULL; 00984 goto recover_error; 00985 } 00986 ods_fclose(fd); 00987 00988 /* all ok */ 00989 zone->zonedata->initialized = 1; 00990 zone->prepared = 1; 00991 if (zone->stats) { 00992 lock_basic_lock(&zone->stats->stats_lock); 00993 stats_clear(zone->stats); 00994 lock_basic_unlock(&zone->stats->stats_lock); 00995 } 00996 return ODS_STATUS_OK; 00997 } else { 00998 /* backwards compatible backup recovery (serial) */ 00999 filename = ods_build_path(zone->name, ".state", 0); 01000 fd = ods_fopen(filename, NULL, "r"); 01001 free((void*)filename); 01002 if (fd) { 01003 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1) || 01004 !backup_read_check_str(fd, ";name:") || 01005 !backup_read_check_str(fd, zone->name) || 01006 !backup_read_check_str(fd, ";class:") || 01007 !backup_read_int(fd, &klass) || 01008 !backup_read_check_str(fd, ";fetch:") || 01009 !backup_read_int(fd, &fetch) || 01010 !backup_read_check_str(fd, ";default_ttl:") || 01011 !backup_read_uint32_t(fd, &ttl) || 01012 !backup_read_check_str(fd, ";inbound_serial:") || 01013 !backup_read_uint32_t(fd, &inbound) || 01014 !backup_read_check_str(fd, ";internal_serial:") || 01015 !backup_read_uint32_t(fd, &internal) || 01016 !backup_read_check_str(fd, ";outbound_serial:") || 01017 !backup_read_uint32_t(fd, &outbound) || 01018 !backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1)) 01019 { 01020 goto recover_error; 01021 } 01022 zone->klass = (ldns_rr_class) klass; 01023 zone->zonedata->default_ttl = ttl; 01024 zone->zonedata->inbound_serial = inbound; 01025 zone->zonedata->internal_serial = internal; 01026 zone->zonedata->outbound_serial = outbound; 01027 /* all ok */ 01028 zone->zonedata->initialized = 1; 01029 zone->prepared = 1; 01030 if (zone->stats) { 01031 lock_basic_lock(&zone->stats->stats_lock); 01032 stats_clear(zone->stats); 01033 lock_basic_unlock(&zone->stats->stats_lock); 01034 } 01035 return ODS_STATUS_UNCHANGED; 01036 } 01037 ods_fclose(fd); 01038 } 01039 01040 return ODS_STATUS_UNCHANGED; 01041 01042 recover_error: 01043 ods_log_error("[%s] unable to recover zone %s: corrupted file", 01044 zone_str, zone->name); 01045 ods_fclose(fd); 01046 01047 /* signconf cleanup */ 01048 signconf_cleanup(zone->signconf); 01049 zone->signconf = signconf_create(); 01050 ods_log_assert(zone->signconf); 01051 01052 /* task cleanup */ 01053 task_cleanup(task); 01054 task = NULL; 01055 01056 /* nsec3params cleanup */ 01057 free((void*)salt); 01058 salt = NULL; 01059 01060 ldns_rr_free(nsec3params_rr); 01061 nsec3params_rr = NULL; 01062 if (nsec3params) { 01063 nsec3params->rr = NULL; 01064 } 01065 nsec3params_cleanup(nsec3params); 01066 nsec3params = NULL; 01067 01068 /* zonedata cleanup */ 01069 zonedata_cleanup(zone->zonedata); 01070 zone->zonedata = zonedata_create(zone->allocator); 01071 ods_log_assert(zone->zonedata); 01072 01073 if (zone->stats) { 01074 lock_basic_lock(&zone->stats->stats_lock); 01075 stats_clear(zone->stats); 01076 lock_basic_unlock(&zone->stats->stats_lock); 01077 } 01078 return ODS_STATUS_ERR; 01079 } 01080 01081 01086 void 01087 zone_merge(zone_type* z1, zone_type* z2) 01088 { 01089 const char* str; 01090 adapter_type* adtmp = NULL; 01091 01092 if (!z1 || !z2) { 01093 return; 01094 } 01095 01096 /* policy name */ 01097 if (ods_strcmp(z2->policy_name, z1->policy_name) != 0) { 01098 if (z2->policy_name) { 01099 str = strdup(z2->policy_name); 01100 if (!str) { 01101 ods_log_error("[%s] failed to merge policy %s name to zone " 01102 "%s", zone_str, z2->policy_name, z1->name); 01103 } else { 01104 free((void*)z1->policy_name); 01105 z1->policy_name = str; 01106 z1->just_updated = 1; 01107 } 01108 } else { 01109 free((void*)z1->policy_name); 01110 z1->policy_name = NULL; 01111 z1->just_updated = 1; 01112 } 01113 } 01114 01115 /* signconf filename */ 01116 if (ods_strcmp(z2->signconf_filename, z1->signconf_filename) != 0) { 01117 if (z2->signconf_filename) { 01118 str = strdup(z2->signconf_filename); 01119 if (!str) { 01120 ods_log_error("[%s] failed to merge signconf filename %s to " 01121 "zone %s", zone_str, z2->policy_name, z1->name); 01122 } else { 01123 free((void*)z1->signconf_filename); 01124 z1->signconf_filename = str; 01125 z1->just_updated = 1; 01126 } 01127 } else { 01128 free((void*)z1->signconf_filename); 01129 z1->signconf_filename = NULL; 01130 z1->just_updated = 1; 01131 } 01132 } 01133 01134 /* adapters */ 01135 if (adapter_compare(z2->adinbound, z1->adinbound) != 0) { 01136 adtmp = z2->adinbound; 01137 z2->adinbound = z1->adinbound; 01138 z1->adinbound = adtmp; 01139 adtmp = NULL; 01140 } 01141 if (adapter_compare(z2->adoutbound, z1->adoutbound) != 0) { 01142 adtmp = z2->adoutbound; 01143 z2->adoutbound = z1->adoutbound; 01144 z1->adoutbound = adtmp; 01145 adtmp = NULL; 01146 } 01147 return; 01148 } 01149 01150 01155 ods_status 01156 zone_update_serial(zone_type* zone) 01157 { 01158 ods_status status = ODS_STATUS_OK; 01159 domain_type* domain = NULL; 01160 rrset_type* rrset = NULL; 01161 ldns_rdf* serial = NULL; 01162 01163 if (!zone) { 01164 ods_log_error("[%s] unable to update serial: no zone", 01165 zone_str); 01166 return ODS_STATUS_ASSERT_ERR; 01167 } 01168 ods_log_assert(zone); 01169 01170 if (!zone->signconf) { 01171 ods_log_error("[%s] unable to update serial: no signconf", 01172 zone_str); 01173 return ODS_STATUS_ASSERT_ERR; 01174 } 01175 ods_log_assert(zone->signconf); 01176 01177 if (!zone->zonedata) { 01178 ods_log_error("[%s] unable to update serial: no zonedata", 01179 zone_str); 01180 return ODS_STATUS_ASSERT_ERR; 01181 } 01182 ods_log_assert(zone->zonedata); 01183 01184 status = zonedata_update_serial(zone->zonedata, zone->signconf); 01185 if (status != ODS_STATUS_OK) { 01186 ods_log_error("[%s] unable to update serial: failed to increment", 01187 zone_str); 01188 return status; 01189 } 01190 01191 /* lookup domain */ 01192 domain = zonedata_lookup_domain(zone->zonedata, zone->dname); 01193 if (!domain) { 01194 ods_log_error("[%s] unable to update serial: apex not found", 01195 zone_str); 01196 return ODS_STATUS_ERR; 01197 } 01198 ods_log_assert(domain); 01199 01200 /* lookup RRset */ 01201 rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA); 01202 if (!rrset) { 01203 ods_log_error("[%s] unable to update serial: SOA RRset not found", 01204 zone_str); 01205 return ODS_STATUS_ERR; 01206 } 01207 ods_log_assert(rrset); 01208 ods_log_assert(rrset->rr_type == LDNS_RR_TYPE_SOA); 01209 01210 if (rrset->rrs && rrset->rrs->rr) { 01211 serial = ldns_rr_set_rdf(rrset->rrs->rr, 01212 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 01213 zone->zonedata->internal_serial), SE_SOA_RDATA_SERIAL); 01214 if (serial) { 01215 if (ldns_rdf2native_int32(serial) != 01216 zone->zonedata->internal_serial) { 01217 rrset->needs_signing = 1; 01218 } 01219 ldns_rdf_deep_free(serial); 01220 } else { 01221 ods_log_error("[%s] unable to update serial: failed to replace " 01222 "SOA SERIAL rdata", zone_str); 01223 return ODS_STATUS_ERR; 01224 } 01225 } 01226 return ODS_STATUS_OK; 01227 } 01228 01229 01234 ods_status 01235 zone_print(FILE* fd, zone_type* zone) 01236 { 01237 if (fd && zone && zone->zonedata) { 01238 return zonedata_print(fd, zone->zonedata); 01239 } 01240 return ODS_STATUS_ASSERT_ERR; 01241 } 01242 01243 01248 ods_status 01249 zone_examine(zone_type* zone) 01250 { 01251 if (zone && zone->zonedata && zone->adinbound) { 01252 return zonedata_examine(zone->zonedata, zone->dname, 01253 zone->adinbound->type); 01254 } 01255 return ODS_STATUS_ASSERT_ERR; 01256 } 01257 01258 01263 void 01264 zone_cleanup(zone_type* zone) 01265 { 01266 allocator_type* allocator; 01267 lock_basic_type zone_lock; 01268 01269 if (!zone) { 01270 return; 01271 } 01272 01273 allocator = zone->allocator; 01274 zone_lock = zone->zone_lock; 01275 01276 ldns_rdf_deep_free(zone->dname); 01277 adapter_cleanup(zone->adinbound); 01278 adapter_cleanup(zone->adoutbound); 01279 zonedata_cleanup(zone->zonedata); 01280 signconf_cleanup(zone->signconf); 01281 nsec3params_cleanup(zone->nsec3params); 01282 stats_cleanup(zone->stats); 01283 allocator_deallocate(allocator, (void*) zone->notify_ns); 01284 allocator_deallocate(allocator, (void*) zone->policy_name); 01285 allocator_deallocate(allocator, (void*) zone->signconf_filename); 01286 allocator_deallocate(allocator, (void*) zone->name); 01287 allocator_deallocate(allocator, (void*) zone); 01288 allocator_cleanup(allocator); 01289 lock_basic_destroy(&zone_lock); 01290 return; 01291 }