OpenDNSSEC-signer  1.3.8
/build/buildd/opendnssec-1.3.8/signer/src/signer/zone.c
Go to the documentation of this file.
00001 /*
00002  * $Id: zone.c 6244 2012-04-03 13:56:27Z 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;
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     /* check connection here? */
00542     ctx = hsm_create_context();
00543     if (ctx == NULL) {
00544         ods_log_error("[%s] unable to publish dnskeys for zone %s: error "
00545             "creating libhsm context", zone_str, zone->name);
00546         return ODS_STATUS_HSM_ERR;
00547     }
00548 
00549     key = zone->signconf->keys->first_key;
00550     for (count=0; count < zone->signconf->keys->count; count++) {
00551         if (key->publish) {
00552             do_publish = 0;
00553             if (!key->dnskey) {
00554                 do_publish = 1;
00555             }
00556 
00557             status = lhsm_get_key(ctx, zone->dname, key);
00558             if (status != ODS_STATUS_OK) {
00559                 ods_log_error("[%s] unable to publish dnskeys zone %s: "
00560                     "error creating DNSKEY for key %s", zone_str,
00561                     zone->name, key->locator?key->locator:"(null)");
00562                 break;
00563             }
00564             ods_log_assert(key->dnskey);
00565 
00566             if (recover) {
00567                 dnskey = ldns_rr_clone(key->dnskey);
00568                 status = zone_add_rr(zone, dnskey, 0);
00569             } else if (do_publish) {
00570                 ldns_rr_set_ttl(key->dnskey, ttl);
00571                 ldns_rr_set_class(key->dnskey, zone->klass);
00572                 ldns_rr2canonical(key->dnskey);
00573                 dnskey = ldns_rr_clone(key->dnskey);
00574                 status = zone_add_rr(zone, dnskey, 0);
00575             } else {
00576                 status = ODS_STATUS_OK;
00577             }
00578 
00579             if (status != ODS_STATUS_OK) {
00580                 ods_log_error("[%s] unable to publish dnskeys zone %s: "
00581                     "error adding DNSKEY[%u] for key %s", zone_str,
00582                     zone->name, ldns_calc_keytag(dnskey),
00583                     key->locator?key->locator:"(null)");
00584                 break;
00585             }
00586         }
00587         key = key->next;
00588     }
00589 
00590     if (status != ODS_STATUS_OK) {
00591         zonedata_rollback(zone->zonedata);
00592     }
00593 
00594     hsm_destroy_context(ctx);
00595     ctx = NULL;
00596     return status;
00597 }
00598 
00599 
00604 ods_status
00605 zone_prepare_nsec3(zone_type* zone, int recover)
00606 {
00607     ldns_rr* nsec3params_rr = NULL;
00608     ods_status status = ODS_STATUS_OK;
00609     int doe_rollover = 0;
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         doe_rollover = 1;
00637     }
00638     if (!zone->nsec3params) {
00639         ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed "
00640             "to create NSEC3 parameters", zone_str, zone->name);
00641         return ODS_STATUS_MALLOC_ERR;
00642     }
00643     ods_log_assert(zone->nsec3params);
00644 
00645     if (recover) {
00646         nsec3params_rr = ldns_rr_clone(zone->nsec3params->rr);
00647         status = zone_add_rr(zone, nsec3params_rr, 0);
00648     } else if (doe_rollover) {
00649         nsec3params_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
00650         if (!nsec3params_rr) {
00651             ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed "
00652                 "to create NSEC3PARAM RR", zone_str, zone->name);
00653             nsec3params_cleanup(zone->nsec3params);
00654             zone->nsec3params = NULL;
00655             return ODS_STATUS_MALLOC_ERR;
00656         }
00657         ods_log_assert(nsec3params_rr);
00658 
00659         ldns_rr_set_class(nsec3params_rr, zone->klass);
00660         ldns_rr_set_ttl(nsec3params_rr, zone->zonedata->default_ttl);
00661         ldns_rr_set_owner(nsec3params_rr, ldns_rdf_clone(zone->dname));
00662         ldns_nsec3_add_param_rdfs(nsec3params_rr,
00663             zone->nsec3params->algorithm, 0,
00664             zone->nsec3params->iterations,
00665             zone->nsec3params->salt_len,
00666             zone->nsec3params->salt_data);
00671         ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params_rr, 1)), 7, 0);
00672 
00673         ldns_rr2canonical(nsec3params_rr);
00674         zone->nsec3params->rr = ldns_rr_clone(nsec3params_rr);
00675         status = zone_add_rr(zone, nsec3params_rr, 0);
00676     }
00677 
00678     if (status != ODS_STATUS_OK) {
00679         ods_log_error("[%s] unable to add NSEC3PARAM RR to zone %s",
00680             zone_str, zone->name);
00681         nsec3params_cleanup(zone->nsec3params);
00682         zone->nsec3params = NULL;
00683         ldns_rr_free(nsec3params_rr);
00684     }
00685     /* previous nsec3params is already withdrawn during load signconf */
00686 
00687     return status;
00688 }
00689 
00690 
00695 ods_status
00696 zone_backup(zone_type* zone)
00697 {
00698     char* filename = NULL;
00699     FILE* fd = NULL;
00700 
00701     ods_log_assert(zone);
00702     ods_log_assert(zone->zonedata);
00703     ods_log_assert(zone->signconf);
00704 
00705     filename = ods_build_path(zone->name, ".backup", 0, 1);
00706     fd = ods_fopen(filename, NULL, "w");
00707     free((void*)filename);
00708 
00709     if (fd) {
00710         fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC);
00712         fprintf(fd, ";;Zone: name %s class %i ttl %u inbound %u internal "
00713             "%u outbound %u\n",
00714             zone->name?zone->name:"(null)",
00715             (int) zone->klass,
00716             (unsigned) zone->zonedata->default_ttl,
00717             (unsigned) zone->zonedata->inbound_serial,
00718             (unsigned) zone->zonedata->internal_serial,
00719             (unsigned) zone->zonedata->outbound_serial);
00721         if (zone->task) {
00722             task_backup(fd, (task_type*) zone->task);
00723         }
00725         signconf_backup(fd, zone->signconf);
00726         fprintf(fd, ";;\n");
00728         if (zone->nsec3params) {
00729             nsec3params_backup(fd,
00730                 zone->signconf->nsec3_algo,
00731                 zone->signconf->nsec3_optout,
00732                 zone->signconf->nsec3_iterations,
00733                 zone->signconf->nsec3_salt,
00734                 zone->nsec3params->rr);
00735         }
00737         keylist_backup(fd, zone->signconf->keys);
00739         zonedata_backup(fd, zone->zonedata);
00741         fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC);
00742         ods_fclose(fd);
00743     } else {
00744         return ODS_STATUS_FOPEN_ERR;
00745     }
00746     return ODS_STATUS_OK;
00747 }
00748 
00749 
00754 ods_status
00755 zone_recover(zone_type* zone)
00756 {
00757     char* filename = NULL;
00758     FILE* fd = NULL;
00759     const char* token = NULL;
00760     ods_status status = ODS_STATUS_OK;
00761     /* zone part */
00762     int klass = 0;
00763     uint32_t ttl = 0;
00764     uint32_t inbound = 0;
00765     uint32_t internal = 0;
00766     uint32_t outbound = 0;
00767     /* task part */
00768     task_type* task = NULL;
00769     time_t when = 0;
00770     time_t backoff = 0;
00771     int what = 0;
00772     int interrupt = 0;
00773     int halted = 0;
00774     int flush = 0;
00775     /* signconf part */
00776     time_t lastmod = 0;
00777     /* nsec3params part */
00778     const char* salt = NULL;
00779     ldns_rr* nsec3params_rr = NULL;
00780     nsec3params_type* nsec3params = NULL;
00781     /* keys part */
00782     key_type* key = NULL;
00783     /* zonedata part */
00784     int fetch = 0;
00785 
00786     ods_log_assert(zone);
00787     ods_log_assert(zone->signconf);
00788     ods_log_assert(zone->zonedata);
00789 
00790     filename = ods_build_path(zone->name, ".backup", 0, 1);
00791     fd = ods_fopen(filename, NULL, "r");
00792     free((void*)filename);
00793     if (fd) {
00794         /* start recovery */
00795         if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC) ||
00796             /* zone part */
00797             !backup_read_check_str(fd, ";;Zone:") ||
00798             !backup_read_check_str(fd, "name") ||
00799             !backup_read_check_str(fd, zone->name) ||
00800             !backup_read_check_str(fd, "class") ||
00801             !backup_read_int(fd, &klass) ||
00802             !backup_read_check_str(fd, "ttl") ||
00803             !backup_read_uint32_t(fd, &ttl) ||
00804             !backup_read_check_str(fd, "inbound") ||
00805             !backup_read_uint32_t(fd, &inbound) ||
00806             !backup_read_check_str(fd, "internal") ||
00807             !backup_read_uint32_t(fd, &internal) ||
00808             !backup_read_check_str(fd, "outbound") ||
00809             !backup_read_uint32_t(fd, &outbound) ||
00810             /* task part */
00811             !backup_read_check_str(fd, ";;Task:") ||
00812             !backup_read_check_str(fd, "when") ||
00813             !backup_read_time_t(fd, &when) ||
00814             !backup_read_check_str(fd, "what") ||
00815             !backup_read_int(fd, &what) ||
00816             !backup_read_check_str(fd, "interrupt") ||
00817             !backup_read_int(fd, &interrupt) ||
00818             !backup_read_check_str(fd, "halted") ||
00819             !backup_read_int(fd, &halted) ||
00820             !backup_read_check_str(fd, "backoff") ||
00821             !backup_read_time_t(fd, &backoff) ||
00822             !backup_read_check_str(fd, "flush") ||
00823             !backup_read_int(fd, &flush) ||
00824             /* signconf part */
00825             !backup_read_check_str(fd, ";;Signconf:") ||
00826             !backup_read_check_str(fd, "lastmod") ||
00827             !backup_read_time_t(fd, &lastmod) ||
00828             !backup_read_check_str(fd, "resign") ||
00829             !backup_read_duration(fd,
00830                 &zone->signconf->sig_resign_interval) ||
00831             !backup_read_check_str(fd, "refresh") ||
00832             !backup_read_duration(fd,
00833                 &zone->signconf->sig_refresh_interval) ||
00834             !backup_read_check_str(fd, "valid") ||
00835             !backup_read_duration(fd,
00836                 &zone->signconf->sig_validity_default) ||
00837             !backup_read_check_str(fd, "denial") ||
00838             !backup_read_duration(fd,
00839                 &zone->signconf->sig_validity_denial) ||
00840             !backup_read_check_str(fd, "jitter") ||
00841             !backup_read_duration(fd, &zone->signconf->sig_jitter) ||
00842             !backup_read_check_str(fd, "offset") ||
00843             !backup_read_duration(fd,
00844                 &zone->signconf->sig_inception_offset) ||
00845             !backup_read_check_str(fd, "nsec") ||
00846             !backup_read_rr_type(fd, &zone->signconf->nsec_type) ||
00847             !backup_read_check_str(fd, "dnskeyttl") ||
00848             !backup_read_duration(fd, &zone->signconf->dnskey_ttl) ||
00849             !backup_read_check_str(fd, "soattl") ||
00850             !backup_read_duration(fd, &zone->signconf->soa_ttl) ||
00851             !backup_read_check_str(fd, "soamin") ||
00852             !backup_read_duration(fd, &zone->signconf->soa_min) ||
00853             !backup_read_check_str(fd, "serial") ||
00854             !backup_read_str(fd, &zone->signconf->soa_serial) ||
00855             !backup_read_check_str(fd, "audit") ||
00856             !backup_read_int(fd, &zone->signconf->audit) ||
00857             !backup_read_check_str(fd, ";;")) {
00858             goto recover_error;
00859         }
00860         /* nsec3params part */
00861         if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
00862              if (!backup_read_check_str(fd, ";;Nsec3parameters:") ||
00863                  !backup_read_check_str(fd, "salt") ||
00864                  !backup_read_str(fd, &salt) ||
00865                  !backup_read_check_str(fd, "algorithm") ||
00866                  !backup_read_uint32_t(fd, &zone->signconf->nsec3_algo) ||
00867                  !backup_read_check_str(fd, "optout") ||
00868                  !backup_read_int(fd, &zone->signconf->nsec3_optout) ||
00869                  !backup_read_check_str(fd, "iterations") ||
00870                  !backup_read_uint32_t(fd,
00871                      &zone->signconf->nsec3_iterations) ||
00872                  ldns_rr_new_frm_fp(&nsec3params_rr, fd, NULL, NULL, NULL) ||
00873                  !backup_read_check_str(fd, ";;Nsec3done") ||
00874                  !backup_read_check_str(fd, ";;")) {
00875                  goto recover_error;
00876             }
00877         }
00878         /* keys part */
00879         zone->signconf->keys = keylist_create(zone->signconf->allocator);
00880         while (backup_read_str(fd, &token)) {
00881             if (ods_strcmp(token, ";;Key:") == 0) {
00882                 key = key_recover(fd, zone->signconf->allocator);
00883                 if (!key || keylist_push(zone->signconf->keys, key) !=
00884                     ODS_STATUS_OK) {
00885                     goto recover_error;
00886                 }
00887                 key = NULL;
00888             } else if (ods_strcmp(token, ";;") == 0) {
00889                 /* keylist done */
00890                 free((void*) token);
00891                 token = NULL;
00892                 break;
00893             } else {
00894                 /* keylist corrupted */
00895                 goto recover_error;
00896             }
00897             free((void*) token);
00898             token = NULL;
00899         }
00900         /* zonedata part */
00901         filename = ods_build_path(zone->name, ".inbound", 0, 1);
00902         status = adbackup_read(zone, filename);
00903         free((void*)filename);
00904         if (status != ODS_STATUS_OK) {
00905             goto recover_error;
00906         }
00907 
00908         zone->klass = (ldns_rr_class) klass;
00909         zone->zonedata->default_ttl = ttl;
00910         zone->zonedata->inbound_serial = inbound;
00911         zone->zonedata->internal_serial = internal;
00912         zone->zonedata->outbound_serial = outbound;
00913         zone->signconf->nsec3_salt = allocator_strdup(
00914             zone->signconf->allocator, salt);
00915         free((void*) salt);
00916         salt = NULL;
00917         task = task_create((task_id) what, when, zone->name, (void*) zone);
00918         if (!task) {
00919             goto recover_error;
00920         }
00921         if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
00922             nsec3params = nsec3params_create(zone->signconf->nsec3_algo,
00923                 zone->signconf->nsec3_optout,
00924                 zone->signconf->nsec3_iterations,
00925                 zone->signconf->nsec3_salt);
00926             if (!nsec3params) {
00927                 goto recover_error;
00928             }
00929             nsec3params->rr = nsec3params_rr;
00930             zone->nsec3params = nsec3params;
00931         }
00932         zone->task = (void*) task;
00933         zone->signconf->last_modified = lastmod;
00934 
00940         status = zone_publish_dnskeys(zone, 1);
00941         if (status != ODS_STATUS_OK) {
00942             zone->task = NULL;
00943             zone->nsec3params = NULL;
00944             goto recover_error;
00945         }
00946         status = zone_prepare_nsec3(zone, 1);
00947         if (status != ODS_STATUS_OK) {
00948             zone->task = NULL;
00949             zone->nsec3params = NULL;
00950             goto recover_error;
00951         }
00952         status = zonedata_commit(zone->zonedata);
00953         if (status != ODS_STATUS_OK) {
00954             zone->task = NULL;
00955             zone->nsec3params = NULL;
00956             goto recover_error;
00957         }
00958         status = zonedata_entize(zone->zonedata, zone->dname);
00959         if (status != ODS_STATUS_OK) {
00960             zone->task = NULL;
00961             zone->nsec3params = NULL;
00962             goto recover_error;
00963         }
00964         status = zonedata_recover(zone->zonedata, fd);
00965         if (status != ODS_STATUS_OK) {
00966             zone->task = NULL;
00967             zone->nsec3params = NULL;
00968             goto recover_error;
00969         }
00970         ods_fclose(fd);
00971 
00972         /* all ok */
00973         zone->zonedata->initialized = 1;
00974         zone->prepared = 1;
00975         if (zone->stats) {
00976             lock_basic_lock(&zone->stats->stats_lock);
00977             stats_clear(zone->stats);
00978             lock_basic_unlock(&zone->stats->stats_lock);
00979         }
00980         return ODS_STATUS_OK;
00981     } else {
00982         /* backwards compatible backup recovery (serial) */
00983         filename = ods_build_path(zone->name, ".state", 0, 1);
00984         fd = ods_fopen(filename, NULL, "r");
00985         free((void*)filename);
00986         if (fd) {
00987             if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1) ||
00988                 !backup_read_check_str(fd, ";name:") ||
00989                 !backup_read_check_str(fd, zone->name) ||
00990                 !backup_read_check_str(fd, ";class:") ||
00991                 !backup_read_int(fd, &klass) ||
00992                 !backup_read_check_str(fd, ";fetch:") ||
00993                 !backup_read_int(fd, &fetch) ||
00994                 !backup_read_check_str(fd, ";default_ttl:") ||
00995                 !backup_read_uint32_t(fd, &ttl) ||
00996                 !backup_read_check_str(fd, ";inbound_serial:") ||
00997                 !backup_read_uint32_t(fd, &inbound) ||
00998                 !backup_read_check_str(fd, ";internal_serial:") ||
00999                 !backup_read_uint32_t(fd, &internal) ||
01000                 !backup_read_check_str(fd, ";outbound_serial:") ||
01001                 !backup_read_uint32_t(fd, &outbound) ||
01002                 !backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1))
01003             {
01004                 goto recover_error;
01005             }
01006             zone->klass = (ldns_rr_class) klass;
01007             zone->zonedata->default_ttl = ttl;
01008             zone->zonedata->inbound_serial = inbound;
01009             zone->zonedata->internal_serial = internal;
01010             zone->zonedata->outbound_serial = outbound;
01011             /* all ok */
01012             zone->zonedata->initialized = 1;
01013             zone->prepared = 1;
01014             if (zone->stats) {
01015                 lock_basic_lock(&zone->stats->stats_lock);
01016                 stats_clear(zone->stats);
01017                 lock_basic_unlock(&zone->stats->stats_lock);
01018             }
01019             return ODS_STATUS_UNCHANGED;
01020         }
01021         ods_fclose(fd);
01022     }
01023 
01024     return ODS_STATUS_UNCHANGED;
01025 
01026 recover_error:
01027     ods_log_error("[%s] unable to recover zone %s: corrupted file",
01028         zone_str, zone->name);
01029     ods_fclose(fd);
01030 
01031     /* signconf cleanup */
01032     signconf_cleanup(zone->signconf);
01033     zone->signconf = signconf_create();
01034     ods_log_assert(zone->signconf);
01035 
01036     /* task cleanup */
01037     task_cleanup(task);
01038     task = NULL;
01039 
01040     /* nsec3params cleanup */
01041     free((void*)salt);
01042     salt = NULL;
01043 
01044     ldns_rr_free(nsec3params_rr);
01045     nsec3params_rr = NULL;
01046     if (nsec3params) {
01047         nsec3params->rr = NULL;
01048     }
01049     nsec3params_cleanup(nsec3params);
01050     nsec3params = NULL;
01051 
01052     /* zonedata cleanup */
01053     zonedata_cleanup(zone->zonedata);
01054     zone->zonedata = zonedata_create(zone->allocator);
01055     ods_log_assert(zone->zonedata);
01056     /* do keep serial information */
01057     zone->zonedata->inbound_serial = inbound;
01058     zone->zonedata->internal_serial = internal;
01059     zone->zonedata->outbound_serial = outbound;
01060     zone->zonedata->initialized = 1;
01061 
01062     if (zone->stats) {
01063        lock_basic_lock(&zone->stats->stats_lock);
01064        stats_clear(zone->stats);
01065        lock_basic_unlock(&zone->stats->stats_lock);
01066     }
01067     return ODS_STATUS_ERR;
01068 }
01069 
01070 
01075 void
01076 zone_merge(zone_type* z1, zone_type* z2)
01077 {
01078     const char* str;
01079     adapter_type* adtmp = NULL;
01080 
01081     if (!z1 || !z2) {
01082         return;
01083     }
01084 
01085     /* policy name */
01086     if (ods_strcmp(z2->policy_name, z1->policy_name) != 0) {
01087         if (z2->policy_name) {
01088             str = strdup(z2->policy_name);
01089             if (!str) {
01090                 ods_log_error("[%s] failed to merge policy %s name to zone "
01091                     "%s", zone_str, z2->policy_name, z1->name);
01092             } else {
01093                 free((void*)z1->policy_name);
01094                 z1->policy_name = str;
01095                 z1->just_updated = 1;
01096             }
01097         } else {
01098             free((void*)z1->policy_name);
01099             z1->policy_name = NULL;
01100             z1->just_updated = 1;
01101         }
01102     }
01103 
01104     /* signconf filename */
01105     if (ods_strcmp(z2->signconf_filename, z1->signconf_filename) != 0) {
01106         if (z2->signconf_filename) {
01107             str = strdup(z2->signconf_filename);
01108             if (!str) {
01109                 ods_log_error("[%s] failed to merge signconf filename %s to "
01110                     "zone %s", zone_str, z2->policy_name, z1->name);
01111             } else {
01112                 free((void*)z1->signconf_filename);
01113                 z1->signconf_filename = str;
01114                 z1->just_updated = 1;
01115             }
01116         } else {
01117             free((void*)z1->signconf_filename);
01118             z1->signconf_filename = NULL;
01119             z1->just_updated = 1;
01120         }
01121     }
01122 
01123     /* adapters */
01124     if (adapter_compare(z2->adinbound, z1->adinbound) != 0) {
01125         adtmp = z2->adinbound;
01126         z2->adinbound = z1->adinbound;
01127         z1->adinbound = adtmp;
01128         adtmp = NULL;
01129     }
01130     if (adapter_compare(z2->adoutbound, z1->adoutbound) != 0) {
01131         adtmp = z2->adoutbound;
01132         z2->adoutbound = z1->adoutbound;
01133         z1->adoutbound = adtmp;
01134         adtmp = NULL;
01135     }
01136     return;
01137 }
01138 
01139 
01144 ods_status
01145 zone_update_serial(zone_type* zone)
01146 {
01147     ods_status status = ODS_STATUS_OK;
01148     domain_type* domain = NULL;
01149     rrset_type* rrset = NULL;
01150     ldns_rdf* serial = NULL;
01151 
01152     if (!zone) {
01153         ods_log_error("[%s] unable to update serial: no zone",
01154             zone_str);
01155         return ODS_STATUS_ASSERT_ERR;
01156     }
01157     ods_log_assert(zone);
01158 
01159     if (!zone->signconf) {
01160         ods_log_error("[%s] unable to update serial: no signconf",
01161             zone_str);
01162         return ODS_STATUS_ASSERT_ERR;
01163     }
01164     ods_log_assert(zone->signconf);
01165 
01166     if (!zone->zonedata) {
01167         ods_log_error("[%s] unable to update serial: no zonedata",
01168             zone_str);
01169         return ODS_STATUS_ASSERT_ERR;
01170     }
01171     ods_log_assert(zone->zonedata);
01172 
01173     status = zonedata_update_serial(zone->zonedata, zone->signconf);
01174     if (status != ODS_STATUS_OK) {
01175         ods_log_error("[%s] unable to update serial: failed to increment",
01176             zone_str);
01177         return status;
01178     }
01179 
01180     /* lookup domain */
01181     domain = zonedata_lookup_domain(zone->zonedata, zone->dname);
01182     if (!domain) {
01183         ods_log_error("[%s] unable to update serial: apex not found",
01184             zone_str);
01185         return ODS_STATUS_ERR;
01186     }
01187     ods_log_assert(domain);
01188 
01189     /* lookup RRset */
01190     rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
01191     if (!rrset) {
01192         ods_log_error("[%s] unable to update serial: SOA RRset not found",
01193             zone_str);
01194         return ODS_STATUS_ERR;
01195     }
01196     ods_log_assert(rrset);
01197     ods_log_assert(rrset->rr_type == LDNS_RR_TYPE_SOA);
01198 
01199     if (rrset->rrs && rrset->rrs->rr) {
01200         serial = ldns_rr_set_rdf(rrset->rrs->rr,
01201             ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
01202             zone->zonedata->internal_serial), SE_SOA_RDATA_SERIAL);
01203         if (serial) {
01204             if (ldns_rdf2native_int32(serial) !=
01205                 zone->zonedata->internal_serial) {
01206                 rrset->needs_signing = 1;
01207             }
01208             ldns_rdf_deep_free(serial);
01209          } else {
01210             ods_log_error("[%s] unable to update serial: failed to replace "
01211                 "SOA SERIAL rdata", zone_str);
01212             return ODS_STATUS_ERR;
01213         }
01214     }
01215     return ODS_STATUS_OK;
01216 }
01217 
01218 
01223 ods_status
01224 zone_print(FILE* fd, zone_type* zone)
01225 {
01226     if (fd && zone && zone->zonedata) {
01227         return zonedata_print(fd, zone->zonedata);
01228     }
01229     return ODS_STATUS_ASSERT_ERR;
01230 }
01231 
01232 
01237 ods_status
01238 zone_examine(zone_type* zone)
01239 {
01240     if (zone && zone->zonedata && zone->adinbound) {
01241         return zonedata_examine(zone->zonedata, zone->dname,
01242             zone->adinbound->type);
01243     }
01244     return ODS_STATUS_ASSERT_ERR;
01245 }
01246 
01247 
01252 void
01253 zone_cleanup(zone_type* zone)
01254 {
01255     allocator_type* allocator;
01256     lock_basic_type zone_lock;
01257 
01258     if (!zone) {
01259         return;
01260     }
01261 
01262     allocator = zone->allocator;
01263     zone_lock = zone->zone_lock;
01264 
01265     ldns_rdf_deep_free(zone->dname);
01266     adapter_cleanup(zone->adinbound);
01267     adapter_cleanup(zone->adoutbound);
01268     zonedata_cleanup(zone->zonedata);
01269     signconf_cleanup(zone->signconf);
01270     nsec3params_cleanup(zone->nsec3params);
01271     stats_cleanup(zone->stats);
01272     allocator_deallocate(allocator, (void*) zone->notify_ns);
01273     allocator_deallocate(allocator, (void*) zone->policy_name);
01274     allocator_deallocate(allocator, (void*) zone->signconf_filename);
01275     allocator_deallocate(allocator, (void*) zone->name);
01276     allocator_deallocate(allocator, (void*) zone);
01277     allocator_cleanup(allocator);
01278     lock_basic_destroy(&zone_lock);
01279     return;
01280 }