OpenDNSSEC-signer  1.3.8
/build/buildd/opendnssec-1.3.8/signer/src/signer/zonedata.c
Go to the documentation of this file.
00001 /*
00002  * $Id: zonedata.c 6050 2012-01-10 11:25:28Z 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 "config.h"
00035 #include "adapter/adapter.h"
00036 #include "shared/allocator.h"
00037 #include "shared/log.h"
00038 #include "shared/util.h"
00039 #include "signer/backup.h"
00040 #include "signer/domain.h"
00041 #include "signer/nsec3params.h"
00042 #include "signer/zonedata.h"
00043 
00044 #include <ldns/ldns.h> /* ldns_dname_*(), ldns_rbtree_*() */
00045 
00046 static const char* zd_str = "data";
00047 
00048 static ldns_rbnode_t* domain2node(domain_type* domain);
00049 
00054 void
00055 log_rdf(ldns_rdf *rdf, const char* pre, int level)
00056 {
00057     char* str = NULL;
00058 
00059     if (ods_log_get_level() < level + 2) return;
00060 
00061     str = ldns_rdf2str(rdf);
00062 
00063     if (level == 1) {
00064         ods_log_error("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
00065     } else if (level == 2) {
00066         ods_log_warning("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
00067     } else if (level == 3) {
00068         ods_log_info("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
00069     } else if (level == 4) {
00070         ods_log_verbose("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
00071     } else if (level == 5) {
00072         ods_log_debug("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
00073     } else if (level == 6) {
00074         ods_log_deeebug("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
00075     } else {
00076         ods_log_deeebug("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
00077     }
00078 
00079     free((void*)str);
00080 
00081     return;
00082 }
00083 
00084 
00089 static ldns_rbnode_t*
00090 domain2node(domain_type* domain)
00091 {
00092     ldns_rbnode_t* node = (ldns_rbnode_t*) malloc(sizeof(ldns_rbnode_t));
00093     if (!node) {
00094         return NULL;
00095     }
00096     node->key = domain->dname;
00097     node->data = domain;
00098     return node;
00099 }
00100 
00101 
00106 static ldns_rbnode_t*
00107 denial2node(denial_type* denial)
00108 {
00109     ldns_rbnode_t* node = (ldns_rbnode_t*) malloc(sizeof(ldns_rbnode_t));
00110     if (!node) {
00111         return NULL;
00112     }
00113     node->key = denial->owner;
00114     node->data = denial;
00115     return node;
00116 }
00117 
00118 
00123 static int
00124 domain_compare(const void* a, const void* b)
00125 {
00126     ldns_rdf* x = (ldns_rdf*)a;
00127     ldns_rdf* y = (ldns_rdf*)b;
00128     return ldns_dname_compare(x, y);
00129 }
00130 
00131 
00136 void
00137 zonedata_init_denial(zonedata_type* zd)
00138 {
00139     if (zd) {
00140         zd->denial_chain = ldns_rbtree_create(domain_compare);
00141     }
00142     return;
00143 }
00144 
00145 
00150 static void
00151 zonedata_init_domains(zonedata_type* zd)
00152 {
00153     if (zd) {
00154         zd->domains = ldns_rbtree_create(domain_compare);
00155     }
00156     return;
00157 }
00158 
00159 
00164 zonedata_type*
00165 zonedata_create(allocator_type* allocator)
00166 {
00167     zonedata_type* zd = NULL;
00168 
00169     if (!allocator) {
00170         ods_log_error("[%s] cannot create zonedata: no allocator", zd_str);
00171         return NULL;
00172     }
00173     ods_log_assert(allocator);
00174 
00175     zd = (zonedata_type*) allocator_alloc(allocator, sizeof(zonedata_type));
00176     if (!zd) {
00177         ods_log_error("[%s] cannot create zonedata: allocator failed",
00178             zd_str);
00179         return NULL;
00180     }
00181     ods_log_assert(zd);
00182 
00183     zd->allocator = allocator;
00184     zonedata_init_domains(zd);
00185     zonedata_init_denial(zd);
00186     zd->initialized = 0;
00187     zd->inbound_serial = 0;
00188     zd->internal_serial = 0;
00189     zd->outbound_serial = 0;
00190     zd->default_ttl = 3600; /* TODO: configure --default-ttl option? */
00191     return zd;
00192 }
00193 
00194 
00199 ods_status
00200 zonedata_recover(zonedata_type* zd, FILE* fd)
00201 {
00202     const char* token = NULL;
00203     const char* owner = NULL;
00204     int dstatus = 0;
00205     ods_status status = ODS_STATUS_OK;
00206     domain_type* domain = NULL;
00207     ldns_rdf* rdf = NULL;
00208     ldns_rbnode_t* denial_node = LDNS_RBTREE_NULL;
00209 
00210     ods_log_assert(zd);
00211     ods_log_assert(fd);
00212 
00213     while (backup_read_str(fd, &token)) {
00214         /* domain part */
00215         if (ods_strcmp(token, ";;Domain:") == 0) {
00216             if (!backup_read_check_str(fd, "name") ||
00217                 !backup_read_str(fd, &owner) ||
00218                 !backup_read_check_str(fd, "status") ||
00219                 !backup_read_int(fd, &dstatus)) {
00220                 ods_log_error("[%s] domain in backup corrupted", zd_str);
00221                 goto recover_domain_error;
00222             }
00223             /* ok, look up domain */
00224             rdf = ldns_dname_new_frm_str(owner);
00225             if (rdf) {
00226                 domain = zonedata_lookup_domain(zd, rdf);
00227                 ldns_rdf_deep_free(rdf);
00228                 rdf = NULL;
00229             }
00230             if (!domain) {
00231                 ods_log_error("[%s] domain in backup, but not in zonedata",
00232                     zd_str);
00233                 goto recover_domain_error;
00234             }
00235             /* lookup success */
00236             status = domain_recover(domain, fd, dstatus);
00237             if (status != ODS_STATUS_OK) {
00238                 ods_log_error("[%s] unable to recover domain", zd_str);
00239                 goto recover_domain_error;
00240             }
00241             if (domain->denial) {
00242                 denial_node = denial2node(domain->denial);
00243                 /* insert */
00244                 if (!ldns_rbtree_insert(zd->denial_chain, denial_node)) {
00245                     ods_log_error("[%s] unable to recover denial", zd_str);
00246                     free((void*)denial_node);
00247                     goto recover_domain_error;
00248                 }
00249                 denial_node = NULL;
00250             }
00251 
00252             /* done, next domain */
00253             free((void*) owner);
00254             owner = NULL;
00255             domain = NULL;
00256         } else if (ods_strcmp(token, ";;") == 0) {
00257             /* done with all zone data */
00258             free((void*) token);
00259             token = NULL;
00260             return ODS_STATUS_OK;
00261         } else {
00262             /* domain corrupted */
00263             ods_log_error("[%s] domain in backup corrupted", zd_str);
00264             goto recover_domain_error;
00265         }
00266         free((void*) token);
00267         token = NULL;
00268     }
00269 
00270     if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC)) {
00271         goto recover_domain_error;
00272     }
00273 
00274     return ODS_STATUS_OK;
00275 
00276 recover_domain_error:
00277     free((void*) owner);
00278     owner = NULL;
00279 
00280     free((void*) token);
00281     token = NULL;
00282 
00283     return ODS_STATUS_ERR;
00284 }
00285 
00286 
00291 static domain_type*
00292 zonedata_domain_search(ldns_rbtree_t* tree, ldns_rdf* dname)
00293 {
00294     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00295 
00296     if (!tree || !dname) {
00297         return NULL;
00298     }
00299     node = ldns_rbtree_search(tree, dname);
00300     if (node && node != LDNS_RBTREE_NULL) {
00301         return (domain_type*) node->data;
00302     }
00303     return NULL;
00304 }
00305 
00306 
00311 domain_type*
00312 zonedata_lookup_domain(zonedata_type* zd, ldns_rdf* dname)
00313 {
00314     if (!zd) return NULL;
00315 
00316     return zonedata_domain_search(zd->domains, dname);
00317 }
00318 
00319 
00324 domain_type*
00325 zonedata_add_domain(zonedata_type* zd, domain_type* domain)
00326 {
00327     ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
00328 
00329     if (!domain) {
00330         ods_log_error("[%s] unable to add domain: no domain", zd_str);
00331         return NULL;
00332     }
00333     ods_log_assert(domain);
00334 
00335     if (!zd || !zd->domains) {
00336         log_rdf(domain->dname, "unable to add domain, no storage", 1);
00337         return NULL;
00338     }
00339     ods_log_assert(zd);
00340     ods_log_assert(zd->domains);
00341 
00342     new_node = domain2node(domain);
00343     if (ldns_rbtree_insert(zd->domains, new_node) == NULL) {
00344         log_rdf(domain->dname, "unable to add domain, already present", 1);
00345         free((void*)new_node);
00346         return NULL;
00347     }
00348     log_rdf(domain->dname, "+DD", 6);
00349     return domain;
00350 }
00351 
00352 
00357 static domain_type*
00358 zonedata_del_domain_fixup(ldns_rbtree_t* tree, domain_type* domain)
00359 {
00360     domain_type* del_domain = NULL;
00361     ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
00362 
00363     ods_log_assert(tree);
00364     ods_log_assert(domain);
00365     ods_log_assert(domain->dname);
00366 
00367     del_node = ldns_rbtree_search(tree, (const void*)domain->dname);
00368     if (del_node) {
00369         del_node = ldns_rbtree_delete(tree, (const void*)domain->dname);
00370         del_domain = (domain_type*) del_node->data;
00371         domain_cleanup(del_domain);
00372         free((void*)del_node);
00373         return NULL;
00374     } else {
00375         log_rdf(domain->dname, "unable to del domain, not found", 1);
00376     }
00377     return domain;
00378 }
00379 
00380 
00385 domain_type*
00386 zonedata_del_domain(zonedata_type* zd, domain_type* domain)
00387 {
00388     if (!domain) {
00389         ods_log_error("[%s] unable to delete domain: no domain", zd_str);
00390         return NULL;
00391     }
00392     ods_log_assert(domain);
00393     ods_log_assert(domain->dname);
00394 
00395     if (!zd || !zd->domains) {
00396         log_rdf(domain->dname, "unable to delete domain, no zonedata", 1);
00397         return domain;
00398     }
00399     ods_log_assert(zd);
00400     ods_log_assert(zd->domains);
00401 
00402     if (domain->denial && zonedata_del_denial(zd, domain->denial) != NULL) {
00403         log_rdf(domain->dname, "unable to delete domain, failed to delete "
00404             "denial of existence data point", 1);
00405         return domain;
00406     }
00407     domain->denial = NULL;
00408     log_rdf(domain->dname, "-DD", 6);
00409     return zonedata_del_domain_fixup(zd->domains, domain);
00410 }
00411 
00412 
00417 static denial_type*
00418 zonedata_denial_search(ldns_rbtree_t* tree, ldns_rdf* dname)
00419 {
00420     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00421 
00422     if (!tree || !dname) {
00423         return NULL;
00424     }
00425     node = ldns_rbtree_search(tree, dname);
00426     if (node && node != LDNS_RBTREE_NULL) {
00427         return (denial_type*) node->data;
00428     }
00429     return NULL;
00430 }
00431 
00432 
00437 denial_type*
00438 zonedata_lookup_denial(zonedata_type* zd, ldns_rdf* dname)
00439 {
00440     if (!zd) return NULL;
00441 
00442     return zonedata_denial_search(zd->denial_chain, dname);
00443 }
00444 
00445 
00450 static ldns_rdf*
00451 dname_hash(ldns_rdf* dname, ldns_rdf* apex, nsec3params_type* nsec3params)
00452 {
00453     ldns_rdf* hashed_ownername = NULL;
00454     ldns_rdf* hashed_label = NULL;
00455 
00456     ods_log_assert(dname);
00457     ods_log_assert(apex);
00458     ods_log_assert(nsec3params);
00459 
00464     hashed_label = ldns_nsec3_hash_name(dname, nsec3params->algorithm,
00465         nsec3params->iterations, nsec3params->salt_len,
00466         nsec3params->salt_data);
00467     if (!hashed_label) {
00468         log_rdf(dname, "unable to hash dname, hash failed", 1);
00469         return NULL;
00470     }
00471     hashed_ownername = ldns_dname_cat_clone((const ldns_rdf*) hashed_label,
00472         (const ldns_rdf*) apex);
00473     if (!hashed_ownername) {
00474         log_rdf(dname, "unable to hash dname, concat apex failed", 1);
00475         return NULL;
00476     }
00477     ldns_rdf_deep_free(hashed_label);
00478     return hashed_ownername;
00479 }
00480 
00481 
00486 ods_status
00487 zonedata_add_denial(zonedata_type* zd, domain_type* domain, ldns_rdf* apex,
00488     nsec3params_type* nsec3params)
00489 {
00490     ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
00491     ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
00492     ldns_rdf* owner = NULL;
00493     denial_type* denial = NULL;
00494     denial_type* prev_denial = NULL;
00495 
00496     if (!domain) {
00497         ods_log_error("[%s] unable to add denial of existence data point: "
00498             "no domain", zd_str);
00499         return ODS_STATUS_ASSERT_ERR;
00500     }
00501     ods_log_assert(domain);
00502 
00503     if (!zd || !zd->denial_chain) {
00504         log_rdf(domain->dname, "unable to add denial of existence data "
00505             "point for domain, no denial chain", 1);
00506         return ODS_STATUS_ASSERT_ERR;
00507     }
00508     ods_log_assert(zd);
00509     ods_log_assert(zd->denial_chain);
00510 
00511     if (!apex) {
00512         log_rdf(domain->dname, "unable to add denial of existence data "
00513             "point for domain, apex unknown", 1);
00514         return ODS_STATUS_ASSERT_ERR;
00515     }
00516     ods_log_assert(apex);
00517 
00518     /* nsec or nsec3 */
00519     if (nsec3params) {
00520         owner = dname_hash(domain->dname, apex, nsec3params);
00521         if (!owner) {
00522             log_rdf(domain->dname, "unable to add denial of existence data "
00523                 "point for domain, dname hash failed", 1);
00524             return ODS_STATUS_ERR;
00525         }
00526     } else {
00527         owner = ldns_rdf_clone(domain->dname);
00528     }
00529     /* lookup */
00530     if (zonedata_lookup_denial(zd, owner) != NULL) {
00531         log_rdf(domain->dname, "unable to add denial of existence for "
00532             "domain, data point exists", 1);
00533         return ODS_STATUS_CONFLICT_ERR;
00534     }
00535     /* create */
00536     denial = denial_create(owner);
00537     new_node = denial2node(denial);
00538     ldns_rdf_deep_free(owner);
00539     /* insert */
00540     if (!ldns_rbtree_insert(zd->denial_chain, new_node)) {
00541         log_rdf(domain->dname, "unable to add denial of existence for "
00542             "domain, insert failed", 1);
00543         free((void*)new_node);
00544         denial_cleanup(denial);
00545         return ODS_STATUS_ERR;
00546     }
00547     /* denial of existence data point added */
00548     denial->bitmap_changed = 1;
00549     denial->nxt_changed = 1;
00550     prev_node = ldns_rbtree_previous(new_node);
00551     if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
00552         prev_node = ldns_rbtree_last(zd->denial_chain);
00553     }
00554     ods_log_assert(prev_node);
00555     prev_denial = (denial_type*) prev_node->data;
00556     ods_log_assert(prev_denial);
00557     prev_denial->nxt_changed = 1;
00558     domain->denial = denial;
00559     domain->denial->domain = domain; /* back reference */
00560     return ODS_STATUS_OK;
00561 }
00562 
00563 
00568 static denial_type*
00569 zonedata_del_denial_fixup(ldns_rbtree_t* tree, denial_type* denial)
00570 {
00571     denial_type* del_denial = NULL;
00572     denial_type* prev_denial = NULL;
00573     ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
00574     ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
00575     ods_status status = ODS_STATUS_OK;
00576 
00577     ods_log_assert(tree);
00578     ods_log_assert(denial);
00579     ods_log_assert(denial->owner);
00580 
00581     del_node = ldns_rbtree_search(tree, (const void*)denial->owner);
00582     if (del_node) {
00587         prev_node = ldns_rbtree_previous(del_node);
00588         if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
00589             prev_node = ldns_rbtree_last(tree);
00590         }
00591         ods_log_assert(prev_node);
00592         ods_log_assert(prev_node->data);
00593         prev_denial = (denial_type*) prev_node->data;
00594         prev_denial->nxt_changed = 1;
00595 
00596         /* delete old NSEC RR(s) */
00597         if (denial->rrset) {
00598             status = rrset_wipe_out(denial->rrset);
00599             if (status != ODS_STATUS_OK) {
00600                 ods_log_alert("[%s] unable to del denial of existence data "
00601                     "point: failed to wipe out NSEC RRset", zd_str);
00602                 return denial;
00603             }
00604             status = rrset_commit(denial->rrset);
00605             if (status != ODS_STATUS_OK) {
00606                 ods_log_alert("[%s] unable to del denial of existence data "
00607                     "point: failed to commit NSEC RRset", zd_str);
00608                 return denial;
00609             }
00610         }
00611 
00612         del_node = ldns_rbtree_delete(tree, (const void*)denial->owner);
00613         del_denial = (denial_type*) del_node->data;
00614         denial_cleanup(del_denial);
00615         free((void*)del_node);
00616         return NULL;
00617     } else {
00618         log_rdf(denial->owner, "unable to del denial of existence data "
00619             "point, not found", 1);
00620     }
00621     return denial;
00622 }
00623 
00624 
00629 denial_type*
00630 zonedata_del_denial(zonedata_type* zd, denial_type* denial)
00631 {
00632     if (!denial) {
00633         ods_log_error("[%s] unable to delete denial of existence data "
00634             "point: no data point", zd_str);
00635         return NULL;
00636     }
00637     ods_log_assert(denial);
00638 
00639     if (!zd || !zd->denial_chain) {
00640         log_rdf(denial->owner, "unable to delete denial of existence data "
00641             "point, no zone data", 1);
00642         return denial;
00643     }
00644     ods_log_assert(zd);
00645     ods_log_assert(zd->denial_chain);
00646 
00647     return zonedata_del_denial_fixup(zd->denial_chain, denial);
00648 }
00649 
00650 
00655 ods_status
00656 zonedata_diff(zonedata_type* zd, keylist_type* kl)
00657 {
00658     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00659     domain_type* domain = NULL;
00660     ods_status status = ODS_STATUS_OK;
00661 
00662     if (!zd || !zd->domains) {
00663         return status;
00664     }
00665     if (zd->domains->root != LDNS_RBTREE_NULL) {
00666         node = ldns_rbtree_first(zd->domains);
00667     }
00668     while (node && node != LDNS_RBTREE_NULL) {
00669         domain = (domain_type*) node->data;
00670         status = domain_diff(domain, kl);
00671         if (status != ODS_STATUS_OK) {
00672             return status;
00673         }
00674         node = ldns_rbtree_next(node);
00675     }
00676     return status;
00677 }
00678 
00679 
00684 ods_status
00685 zonedata_commit(zonedata_type* zd)
00686 {
00687     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00688     ldns_rbnode_t* nxtnode = LDNS_RBTREE_NULL;
00689     ldns_rbnode_t* tmpnode = LDNS_RBTREE_NULL;
00690     domain_type* domain = NULL;
00691     domain_type* nxtdomain = NULL;
00692     ods_status status = ODS_STATUS_OK;
00693     size_t oldnum = 0;
00694 
00695     if (!zd || !zd->domains) {
00696         return ODS_STATUS_OK;
00697     }
00698     if (zd->domains->root != LDNS_RBTREE_NULL) {
00699         node = ldns_rbtree_last(zd->domains);
00700     }
00701     while (node && node != LDNS_RBTREE_NULL) {
00702         domain = (domain_type*) node->data;
00703         oldnum = domain_count_rrset(domain);
00704         status = domain_commit(domain);
00705         if (status != ODS_STATUS_OK) {
00706             return status;
00707         }
00708         tmpnode = node;
00709         node = ldns_rbtree_previous(node);
00710 
00711         /* delete memory if empty leaf domain */
00712         if (domain_count_rrset(domain) <= 0) {
00713             /* empty domain */
00714             nxtnode = ldns_rbtree_next(tmpnode);
00715             nxtdomain = NULL;
00716             if (nxtnode && nxtnode != LDNS_RBTREE_NULL) {
00717                 nxtdomain = (domain_type*) nxtnode->data;
00718             }
00719             if (!nxtdomain ||
00720                 !ldns_dname_is_subdomain(nxtdomain->dname, domain->dname)) {
00721                 /* leaf domain */
00722                 if (zonedata_del_domain(zd, domain) != NULL) {
00723                     ods_log_warning("[%s] unable to delete obsoleted "
00724                         "domain", zd_str);
00725                     return ODS_STATUS_ERR;
00726                 }
00727             }
00728         } /* if (domain_count_rrset(domain) <= 0) */
00729     }
00730     return status;
00731 }
00732 
00733 
00738 void
00739 zonedata_rollback(zonedata_type* zd)
00740 {
00741     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00742     domain_type* domain = NULL;
00743 
00744     if (!zd || !zd->domains) {
00745         return;
00746     }
00747     if (zd->domains->root != LDNS_RBTREE_NULL) {
00748         node = ldns_rbtree_first(zd->domains);
00749     }
00750     while (node && node != LDNS_RBTREE_NULL) {
00751         domain = (domain_type*) node->data;
00752         domain_rollback(domain);
00753         node = ldns_rbtree_next(node);
00754     }
00755     return;
00756 }
00757 
00758 
00763 static int
00764 domain_ent2glue(ldns_rbnode_t* node)
00765 {
00766     ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
00767     domain_type* nextdomain = NULL;
00768     domain_type* domain = NULL;
00769     ods_log_assert(node && node != LDNS_RBTREE_NULL);
00770     domain = (domain_type*) node->data;
00771     if (domain->dstatus == DOMAIN_STATUS_ENT) {
00772         ods_log_assert(domain_count_rrset(domain) == 0);
00773         nextnode = ldns_rbtree_next(node);
00774         while (nextnode && nextnode != LDNS_RBTREE_NULL) {
00775             nextdomain = (domain_type*) nextnode->data;
00776             if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
00777                 /* we are done, no non-glue found */
00778                 return 1;
00779             }
00780             if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
00781                 nextdomain->dstatus != DOMAIN_STATUS_ENT &&
00782                 nextdomain->dstatus != DOMAIN_STATUS_NONE) {
00783                 /* found non-glue */
00784                 return 0;
00785             }
00786             nextnode = ldns_rbtree_next(nextnode);
00787         }
00788     } else {
00789         /* no empty non-terminal */
00790         ods_log_assert(domain_count_rrset(domain) != 0);
00791         return 0;
00792     }
00793     /* no non-glue found */
00794     return 1;
00795 }
00796 
00797 
00802 static int
00803 domain_ent2unsigned(ldns_rbnode_t* node)
00804 {
00805     ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
00806     domain_type* nextdomain = NULL;
00807     domain_type* domain = NULL;
00808     ods_log_assert(node && node != LDNS_RBTREE_NULL);
00809     domain = (domain_type*) node->data;
00810     if (domain->dstatus == DOMAIN_STATUS_ENT) {
00811         ods_log_assert(domain_count_rrset(domain) == 0);
00812         nextnode = ldns_rbtree_next(node);
00813         while (nextnode && nextnode != LDNS_RBTREE_NULL) {
00814             nextdomain = (domain_type*) nextnode->data;
00815             if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
00816                 /* we are done, no unsigned delegation found */
00817                 return 1;
00818             }
00819             if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
00820                 nextdomain->dstatus != DOMAIN_STATUS_ENT &&
00821                 nextdomain->dstatus != DOMAIN_STATUS_NS &&
00822                 nextdomain->dstatus != DOMAIN_STATUS_NONE) {
00823                 /* found data that has to be signed */
00824                 return 0;
00825             }
00826             nextnode = ldns_rbtree_next(nextnode);
00827         }
00828     } else {
00829         /* no empty non-terminal */
00830         ods_log_assert(domain_count_rrset(domain) != 0);
00831         return 0;
00832     }
00833     /* no unsigned delegation found */
00834     return 1;
00835 }
00836 
00837 
00842 static ods_status
00843 domain_entize(zonedata_type* zd, domain_type* domain, ldns_rdf* apex)
00844 {
00845     ldns_rdf* parent_rdf = NULL;
00846     domain_type* parent_domain = NULL;
00847 
00848     ods_log_assert(apex);
00849     ods_log_assert(domain);
00850     ods_log_assert(domain->dname);
00851     ods_log_assert(zd);
00852     ods_log_assert(zd->domains);
00853 
00854     if (domain->parent) {
00855         /* domain already has parent */
00856         return ODS_STATUS_OK;
00857     }
00858 
00859     while (domain && ldns_dname_is_subdomain(domain->dname, apex) &&
00860            ldns_dname_compare(domain->dname, apex) != 0) {
00861 
00869         parent_rdf = ldns_dname_left_chop(domain->dname);
00870         if (!parent_rdf) {
00871             log_rdf(domain->dname, "unable to entize domain, left chop "
00872                 "failed", 1);
00873             return ODS_STATUS_ERR;
00874         }
00875         ods_log_assert(parent_rdf);
00876 
00877         parent_domain = zonedata_lookup_domain(zd, parent_rdf);
00878         if (!parent_domain) {
00879             parent_domain = domain_create(parent_rdf);
00880             ldns_rdf_deep_free(parent_rdf);
00881             if (!parent_domain) {
00882                 log_rdf(domain->dname, "unable to entize domain, create "
00883                     "parent failed", 1);
00884                 return ODS_STATUS_ERR;
00885             }
00886             ods_log_assert(parent_domain);
00887             if (zonedata_add_domain(zd, parent_domain) == NULL) {
00888                 log_rdf(domain->dname, "unable to entize domain, add parent "
00889                     "failed", 1);
00890                 domain_cleanup(parent_domain);
00891                 return ODS_STATUS_ERR;
00892             }
00893             parent_domain->dstatus = DOMAIN_STATUS_ENT;
00894             domain->parent = parent_domain;
00895             /* continue with the parent domain */
00896             domain = parent_domain;
00897         } else {
00898             ldns_rdf_deep_free(parent_rdf);
00899             domain->parent = parent_domain;
00900             /* we are done with this domain */
00901             domain = NULL;
00902         }
00903     }
00904     return ODS_STATUS_OK;
00905 }
00906 
00907 
00912 ods_status
00913 zonedata_entize(zonedata_type* zd, ldns_rdf* apex)
00914 {
00915     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00916     ods_status status = ODS_STATUS_OK;
00917     domain_type* domain = NULL;
00918 
00919     if (!zd || !zd->domains) {
00920         ods_log_error("[%s] unable to entize zone data: no zone data",
00921             zd_str);
00922         return ODS_STATUS_ASSERT_ERR;
00923     }
00924     ods_log_assert(zd);
00925     ods_log_assert(zd->domains);
00926 
00927     if (!apex) {
00928         ods_log_error("[%s] unable to entize zone data: no zone apex",
00929             zd_str);
00930         return ODS_STATUS_ASSERT_ERR;
00931     }
00932     ods_log_assert(apex);
00933 
00934     node = ldns_rbtree_first(zd->domains);
00935     while (node && node != LDNS_RBTREE_NULL) {
00936         domain = (domain_type*) node->data;
00937         status = domain_entize(zd, domain, apex);
00938         if (status != ODS_STATUS_OK) {
00939             ods_log_error("[%s] unable to entize zone data: entize domain "
00940                 "failed", zd_str);
00941             return status;
00942         }
00943         domain_dstatus(domain);
00944         node = ldns_rbtree_next(node);
00945     }
00946     return ODS_STATUS_OK;
00947 }
00948 
00949 
00954 ods_status
00955 zonedata_nsecify(zonedata_type* zd, ldns_rr_class klass, uint32_t ttl,
00956     uint32_t* num_added)
00957 {
00958     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00959     ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
00960     ods_status status = ODS_STATUS_OK;
00961     domain_type* domain = NULL;
00962     domain_type* apex = NULL;
00963     denial_type* denial = NULL;
00964     denial_type* nxt = NULL;
00965     size_t nsec_added = 0;
00966 
00967     if (!zd || !zd->domains) {
00968         return ODS_STATUS_OK;
00969     }
00970     ods_log_assert(zd);
00971     ods_log_assert(zd->domains);
00972 
00973     node = ldns_rbtree_first(zd->domains);
00974     while (node && node != LDNS_RBTREE_NULL) {
00975         domain = (domain_type*) node->data;
00976         if (domain->dstatus == DOMAIN_STATUS_APEX) {
00977             apex = domain;
00978         }
00979         /* don't do glue-only or empty domains */
00980         if (domain->dstatus == DOMAIN_STATUS_NONE ||
00981             domain->dstatus == DOMAIN_STATUS_ENT ||
00982             domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
00983             domain_count_rrset(domain) <= 0) {
00984             if (domain_count_rrset(domain)) {
00985                 log_rdf(domain->dname, "nsecify: don't do glue domain", 6);
00986             } else {
00987                 log_rdf(domain->dname, "nsecify: don't do empty domain", 6);
00988             }
00989             if (domain->denial) {
00990                 if (zonedata_del_denial(zd, domain->denial) != NULL) {
00991                     ods_log_warning("[%s] unable to nsecify: failed to "
00992                         "delete denial of existence data point", zd_str);
00993                     return ODS_STATUS_ERR;
00994                 }
00995                 domain->denial = NULL;
00996             }
00997             node = ldns_rbtree_next(node);
00998             continue;
00999         }
01000         if (!apex) {
01001             ods_log_alert("[%s] unable to nsecify: apex unknown", zd_str);
01002             return ODS_STATUS_ASSERT_ERR;
01003         }
01004 
01005         /* add the denial of existence */
01006         if (!domain->denial) {
01007             status = zonedata_add_denial(zd, domain, apex->dname, NULL);
01008             if (status != ODS_STATUS_OK) {
01009                 log_rdf(domain->dname, "unable to nsecify: failed to add "
01010                     "denial of existence for domain", 1);
01011                 return status;
01012             }
01013             nsec_added++;
01014         }
01015         node = ldns_rbtree_next(node);
01016     }
01017 
01019     node = ldns_rbtree_first(zd->denial_chain);
01020     while (node && node != LDNS_RBTREE_NULL) {
01021         denial = (denial_type*) node->data;
01022         nxt_node = ldns_rbtree_next(node);
01023         if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
01024              nxt_node = ldns_rbtree_first(zd->denial_chain);
01025         }
01026         nxt = (denial_type*) nxt_node->data;
01027 
01028         status = denial_nsecify(denial, nxt, ttl, klass);
01029         if (status != ODS_STATUS_OK) {
01030             ods_log_error("[%s] unable to nsecify: failed to add NSEC record",
01031                 zd_str);
01032             return status;
01033         }
01034         node = ldns_rbtree_next(node);
01035     }
01036     if (num_added) {
01037         *num_added = nsec_added;
01038     }
01039     return ODS_STATUS_OK;
01040 }
01041 
01042 
01047 ods_status
01048 zonedata_nsecify3(zonedata_type* zd, ldns_rr_class klass,
01049     uint32_t ttl, nsec3params_type* nsec3params, uint32_t* num_added)
01050 {
01051     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01052     ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
01053     ods_status status = ODS_STATUS_OK;
01054     domain_type* domain = NULL;
01055     domain_type* apex = NULL;
01056     denial_type* denial = NULL;
01057     denial_type* nxt = NULL;
01058     size_t nsec3_added = 0;
01059 
01060     if (!zd || !zd->domains) {
01061         return ODS_STATUS_OK;
01062     }
01063     ods_log_assert(zd);
01064     ods_log_assert(zd->domains);
01065 
01066     if (!nsec3params) {
01067         ods_log_error("[%s] unable to nsecify3: no nsec3 paramaters", zd_str);
01068         return ODS_STATUS_ASSERT_ERR;
01069     }
01070     ods_log_assert(nsec3params);
01071 
01072     node = ldns_rbtree_first(zd->domains);
01073     while (node && node != LDNS_RBTREE_NULL) {
01074         domain = (domain_type*) node->data;
01075         if (domain->dstatus == DOMAIN_STATUS_APEX) {
01076             apex = domain;
01077         }
01078 
01079         /* don't do glue-only domains */
01080         if (domain->dstatus == DOMAIN_STATUS_NONE ||
01081             domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
01082             domain_ent2glue(node)) {
01083             log_rdf(domain->dname, "nsecify3: don't do glue domain" , 6);
01084             if (domain->denial) {
01085                 if (zonedata_del_denial(zd, domain->denial) != NULL) {
01086                     ods_log_error("[%s] unable to nsecify3: failed to "
01087                         "delete denial of existence data point", zd_str);
01088                     return ODS_STATUS_ERR;
01089                 }
01090                 domain->denial = NULL;
01091             }
01092             node = ldns_rbtree_next(node);
01093             continue;
01094         }
01095         /* Opt-Out? */
01096         if (nsec3params->flags) {
01097             /* If Opt-Out is being used, owner names of unsigned delegations
01098                MAY be excluded. */
01099             if (domain->dstatus == DOMAIN_STATUS_NS ||
01100                 domain_ent2unsigned(node)) {
01101                 if (domain->dstatus == DOMAIN_STATUS_NS) {
01102                     log_rdf(domain->dname, "nsecify3: opt-out (unsigned "
01103                         "delegation)", 5);
01104                 } else {
01105                     log_rdf(domain->dname, "nsecify3: opt-out (empty "
01106                         "non-terminal (to unsigned delegation))", 5);
01107                 }
01108                 if (domain->denial) {
01109                     if (zonedata_del_denial(zd, domain->denial) != NULL) {
01110                         ods_log_error("[%s] unable to nsecify3: failed to "
01111                             "delete denial of existence data point", zd_str);
01112                         return ODS_STATUS_ERR;
01113                     }
01114                     domain->denial = NULL;
01115                 }
01116                 node = ldns_rbtree_next(node);
01117                 continue;
01118             }
01119         }
01120         if (!apex) {
01121             ods_log_alert("[%s] unable to nsecify3: apex unknown", zd_str);
01122             return ODS_STATUS_ASSERT_ERR;
01123         }
01124 
01125         /* add the denial of existence */
01126         if (!domain->denial) {
01127             status = zonedata_add_denial(zd, domain, apex->dname,
01128                 nsec3params);
01129             if (status != ODS_STATUS_OK) {
01130                 log_rdf(domain->dname, "unable to nsecify3: failed to add "
01131                     "denial of existence for domain", 1);
01132                 return status;
01133             }
01134             nsec3_added++;
01135         }
01136 
01137         /* The Next Hashed Owner Name field is left blank for the moment. */
01138 
01146         /* [TODO] */
01156         node = ldns_rbtree_next(node);
01157     }
01158 
01160     node = ldns_rbtree_first(zd->denial_chain);
01161     while (node && node != LDNS_RBTREE_NULL) {
01162         denial = (denial_type*) node->data;
01163         nxt_node = ldns_rbtree_next(node);
01164         if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
01165              nxt_node = ldns_rbtree_first(zd->denial_chain);
01166         }
01167         nxt = (denial_type*) nxt_node->data;
01168 
01169         status = denial_nsecify3(denial, nxt, ttl, klass, nsec3params);
01170         if (status != ODS_STATUS_OK) {
01171             ods_log_error("[%s] unable to nsecify3: failed to add NSEC3 "
01172                 "record", zd_str);
01173             return status;
01174         }
01175         node = ldns_rbtree_next(node);
01176     }
01177     if (num_added) {
01178         *num_added = nsec3_added;
01179     }
01180     return ODS_STATUS_OK;
01181 }
01182 
01183 
01188 ods_status
01189 zonedata_update_serial(zonedata_type* zd, signconf_type* sc)
01190 {
01191     uint32_t soa = 0;
01192     uint32_t prev = 0;
01193     uint32_t update = 0;
01194 
01195     ods_log_assert(zd);
01196     ods_log_assert(sc);
01197 
01198     prev = zd->outbound_serial;
01199     ods_log_debug("[%s] update serial: in=%u internal=%u out=%u now=%u",
01200         zd_str, zd->inbound_serial, zd->internal_serial, zd->outbound_serial,
01201         (uint32_t) time_now());
01202 
01203     if (!sc->soa_serial) {
01204         ods_log_error("[%s] no serial type given", zd_str);
01205         return ODS_STATUS_ERR;
01206     }
01207     if (ods_strcmp(sc->soa_serial, "unixtime") == 0) {
01208         soa = (uint32_t) time_now();
01209         if (!zd->initialized) {
01210             if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
01211                 ods_log_warning("[%s] unable to use unixtime %u as serial: "
01212                     "not greater than inbound serial %u", zd_str, soa,
01213                     zd->inbound_serial);
01214                 soa = zd->inbound_serial + 1;
01215             }
01216         } else if (!DNS_SERIAL_GT(soa, prev)) {
01217             soa = prev + 1;
01218         }
01219     } else if (strncmp(sc->soa_serial, "counter", 7) == 0) {
01220         soa = zd->inbound_serial;
01221         if (!zd->initialized) {
01222             soa = zd->inbound_serial + 1;
01223         } else if (!DNS_SERIAL_GT(soa, prev)) {
01224             soa = prev + 1;
01225         }
01226     } else if (strncmp(sc->soa_serial, "datecounter", 11) == 0) {
01227         soa = (uint32_t) time_datestamp(0, "%Y%m%d", NULL) * 100;
01228         if (!zd->initialized) {
01229             if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
01230                 ods_log_warning("[%s] unable to use datecounter %u as serial: "
01231                     "not greater than inbound serial %u", zd_str, soa,
01232                     zd->inbound_serial);
01233                 soa = zd->inbound_serial + 1;
01234             }
01235         } else if (!DNS_SERIAL_GT(soa, prev)) {
01236             soa = prev + 1;
01237         }
01238     } else if (strncmp(sc->soa_serial, "keep", 4) == 0) {
01239         soa = zd->inbound_serial;
01240         if (zd->initialized && !DNS_SERIAL_GT(soa, prev)) {
01241             ods_log_error("[%s] cannot keep SOA SERIAL from input zone "
01242                 " (%u): previous output SOA SERIAL is %u", zd_str, soa, prev);
01243             return ODS_STATUS_CONFLICT_ERR;
01244         }
01245     } else {
01246         ods_log_error("[%s] unknown serial type %s", zd_str, sc->soa_serial);
01247         return ODS_STATUS_ERR;
01248     }
01249 
01250     /* serial is stored in 32 bits */
01251     update = soa - prev;
01252     if (update > 0x7FFFFFFF) {
01253         update = 0x7FFFFFFF;
01254     }
01255 
01256     if (!zd->initialized) {
01257         zd->internal_serial = soa;
01258     } else {
01259         zd->internal_serial = prev + update; /* automatically does % 2^32 */
01260     }
01261     ods_log_debug("[%s] update serial: %u + %u = %u", zd_str, prev, update,
01262         zd->internal_serial);
01263     return ODS_STATUS_OK;
01264 }
01265 
01266 
01271 ods_status
01272 zonedata_queue(zonedata_type* zd, fifoq_type* q, worker_type* worker)
01273 {
01274     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01275     domain_type* domain = NULL;
01276     ods_status status = ODS_STATUS_OK;
01277 
01278     if (!zd || !zd->domains) {
01279         return ODS_STATUS_OK;
01280     }
01281     if (zd->domains->root != LDNS_RBTREE_NULL) {
01282         node = ldns_rbtree_first(zd->domains);
01283     }
01284     while (node && node != LDNS_RBTREE_NULL) {
01285         domain = (domain_type*) node->data;
01286         status = domain_queue(domain, q, worker);
01287         if (status != ODS_STATUS_OK) {
01288             return status;
01289         }
01290         node = ldns_rbtree_next(node);
01291     }
01292     return status;
01293 }
01294 
01295 
01300 static int
01301 zonedata_examine_domain_is_occluded(zonedata_type* zd, domain_type* domain,
01302     ldns_rdf* apex)
01303 {
01304     ldns_rdf* parent_rdf = NULL;
01305     ldns_rdf* next_rdf = NULL;
01306     domain_type* parent_domain = NULL;
01307     char* str_name = NULL;
01308     char* str_parent = NULL;
01309 
01310     ods_log_assert(apex);
01311     ods_log_assert(domain);
01312     ods_log_assert(domain->dname);
01313     ods_log_assert(zd);
01314     ods_log_assert(zd->domains);
01315 
01316     if (ldns_dname_compare(domain->dname, apex) == 0) {
01317         return 0;
01318     }
01319 
01320     if (domain_examine_valid_zonecut(domain) != 0) {
01321         log_rdf(domain->dname, "occluded (non-glue non-DS) data at NS", 2);
01322         return 1;
01323     }
01324 
01325     parent_rdf = ldns_dname_left_chop(domain->dname);
01326     while (parent_rdf && ldns_dname_is_subdomain(parent_rdf, apex) &&
01327            ldns_dname_compare(parent_rdf, apex) != 0) {
01328 
01329         parent_domain = zonedata_lookup_domain(zd, parent_rdf);
01330         next_rdf = ldns_dname_left_chop(parent_rdf);
01331         ldns_rdf_deep_free(parent_rdf);
01332 
01333         if (parent_domain) {
01334             /* check for DNAME or NS */
01335             if (domain_examine_data_exists(parent_domain, LDNS_RR_TYPE_DNAME,
01336                 0) && domain_examine_data_exists(domain, 0, 0)) {
01337                 /* data below DNAME */
01338                 str_name = ldns_rdf2str(domain->dname);
01339                 str_parent = ldns_rdf2str(parent_domain->dname);
01340                 ods_log_warning("[%s] occluded data at %s (below %s DNAME)",
01341                     zd_str, str_name, str_parent);
01342                 free((void*)str_name);
01343                 free((void*)str_parent);
01344                 return 1;
01345             } else if (domain_examine_data_exists(parent_domain,
01346                 LDNS_RR_TYPE_NS, 0) &&
01347                 domain_examine_data_exists(domain, 0, 1)) {
01348                 /* data (non-glue) below NS */
01349                 str_name = ldns_rdf2str(domain->dname);
01350                 str_parent = ldns_rdf2str(parent_domain->dname);
01351                 ods_log_warning("[%s] occluded (non-glue) data at %s (below "
01352                     "%s NS)", zd_str, str_name, str_parent);
01353                 free((void*)str_name);
01354                 free((void*)str_parent);
01355                 return 1;
01356 /* allow for now (root zone has it)
01357             } else if (domain_examine_data_exists(parent_domain,
01358                 LDNS_RR_TYPE_NS, 0) &&
01359                 domain_examine_data_exists(domain, 0, 0) &&
01360                 !domain_examine_ns_rdata(parent_domain, domain->dname)) {
01361                 str_name = ldns_rdf2str(domain->dname);
01362                 str_parent = ldns_rdf2str(parent_domain->dname);
01363                 ods_log_warning("[%s] occluded data at %s (below %s NS)",
01364                     zd_str, str_name, str_parent);
01365                 free((void*)str_name);
01366                 free((void*)str_parent);
01367                 return 1;
01368 */
01369             }
01370         }
01371         parent_rdf = next_rdf;
01372     }
01373     if (parent_rdf) {
01374         ldns_rdf_deep_free(parent_rdf);
01375     }
01376     return 0;
01377 }
01378 
01379 
01384 ods_status
01385 zonedata_examine(zonedata_type* zd, ldns_rdf* apex, adapter_mode mode)
01386 {
01387     int result = 0;
01388     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01389     domain_type* domain = NULL;
01390     ods_status status = ODS_STATUS_OK;
01391 
01392     if (!zd || !zd->domains) {
01393        /* no zone data, no error */
01394        return ODS_STATUS_OK;
01395     }
01396     ods_log_assert(zd);
01397     ods_log_assert(zd->domains);
01398 
01399     if (zd->domains->root != LDNS_RBTREE_NULL) {
01400         node = ldns_rbtree_first(zd->domains);
01401     }
01402     while (node && node != LDNS_RBTREE_NULL) {
01403         domain = (domain_type*) node->data;
01404         result =
01405         /* Thou shall not have other data next to CNAME */
01406         domain_examine_rrset_is_alone(domain, LDNS_RR_TYPE_CNAME) &&
01407         /* Thou shall have at most one CNAME per name */
01408         domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_CNAME) &&
01409         /* Thou shall have at most one DNAME per name */
01410         domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_DNAME);
01411         if (!result) {
01412             status = ODS_STATUS_ERR;
01413         }
01414 
01415         if (mode == ADAPTER_FILE) {
01416             result =
01417             /* Thou shall not have occluded data in your zone file */
01418             zonedata_examine_domain_is_occluded(zd, domain, apex);
01419             if (result) {
01420                 ; /* just warn if there is occluded data */
01421             }
01422         }
01423         node = ldns_rbtree_next(node);
01424     }
01425     return status;
01426 }
01427 
01428 
01433 void
01434 zonedata_wipe_denial(zonedata_type* zd)
01435 {
01436     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01437     denial_type* denial = NULL;
01438 
01439     if (zd && zd->denial_chain) {
01440         node = ldns_rbtree_first(zd->denial_chain);
01441         while (node && node != LDNS_RBTREE_NULL) {
01442             denial = (denial_type*) node->data;
01443             if (denial->rrset) {
01444                 /* [TODO] IXFR delete NSEC */
01445                 rrset_cleanup(denial->rrset);
01446                 denial->rrset = NULL;
01447             }
01448             node = ldns_rbtree_next(node);
01449         }
01450     }
01451     return;
01452 }
01453 
01454 
01459 static void
01460 domain_delfunc(ldns_rbnode_t* elem)
01461 {
01462     domain_type* domain = NULL;
01463 
01464     if (elem && elem != LDNS_RBTREE_NULL) {
01465         domain = (domain_type*) elem->data;
01466         domain_delfunc(elem->left);
01467         domain_delfunc(elem->right);
01468 
01469         domain_cleanup(domain);
01470         free((void*)elem);
01471     }
01472     return;
01473 }
01474 
01475 
01480 static void
01481 denial_delfunc(ldns_rbnode_t* elem)
01482 {
01483     denial_type* denial = NULL;
01484     domain_type* domain = NULL;
01485 
01486 
01487     if (elem && elem != LDNS_RBTREE_NULL) {
01488         denial = (denial_type*) elem->data;
01489         denial_delfunc(elem->left);
01490         denial_delfunc(elem->right);
01491 
01492         domain = denial->domain;
01493         if (domain) {
01494             domain->denial = NULL;
01495         }
01496         denial_cleanup(denial);
01497 
01498         free((void*)elem);
01499     }
01500     return;
01501 }
01502 
01503 
01508 static void
01509 zonedata_cleanup_domains(zonedata_type* zd)
01510 {
01511     if (zd && zd->domains) {
01512         domain_delfunc(zd->domains->root);
01513         ldns_rbtree_free(zd->domains);
01514         zd->domains = NULL;
01515     }
01516     return;
01517 }
01518 
01519 
01524 void
01525 zonedata_cleanup_chain(zonedata_type* zd)
01526 {
01527     if (zd && zd->denial_chain) {
01528         denial_delfunc(zd->denial_chain->root);
01529         ldns_rbtree_free(zd->denial_chain);
01530         zd->denial_chain = NULL;
01531     }
01532     return;
01533 }
01534 
01535 
01540 void
01541 zonedata_cleanup(zonedata_type* zd)
01542 {
01543     allocator_type* allocator;
01544 
01545     if (!zd) {
01546         return;
01547     }
01548     zonedata_cleanup_chain(zd);
01549     zonedata_cleanup_domains(zd);
01550     allocator = zd->allocator;
01551     allocator_deallocate(allocator, (void*) zd);
01552     return;
01553 }
01554 
01555 
01560 void
01561 zonedata_backup(FILE* fd, zonedata_type* zd)
01562 {
01563     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01564     domain_type* domain = NULL;
01565 
01566     if (!fd || !zd) {
01567         return;
01568     }
01569 
01570     node = ldns_rbtree_first(zd->domains);
01571     while (node && node != LDNS_RBTREE_NULL) {
01572         domain = (domain_type*) node->data;
01573         domain_backup(fd, domain);
01574         node = ldns_rbtree_next(node);
01575     }
01576     fprintf(fd, ";;\n");
01577     return;
01578 }
01579 
01580 
01585 ods_status
01586 zonedata_print(FILE* fd, zonedata_type* zd)
01587 {
01588     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01589     domain_type* domain = NULL;
01590 
01591     if (!fd) {
01592         ods_log_error("[%s] unable to print zone data: no file descriptor",
01593             zd_str);
01594         return ODS_STATUS_ASSERT_ERR;
01595     }
01596     ods_log_assert(fd);
01597 
01598     if (!zd || !zd->domains) {
01599         ods_log_error("[%s] unable to print zone data: no zone data",
01600             zd_str);
01601         return ODS_STATUS_ASSERT_ERR;
01602     }
01603     ods_log_assert(zd);
01604     ods_log_assert(zd->domains);
01605 
01606     node = ldns_rbtree_first(zd->domains);
01607     if (!node || node == LDNS_RBTREE_NULL) {
01608         fprintf(fd, "; empty zone\n");
01609         return ODS_STATUS_OK;
01610     }
01611     while (node && node != LDNS_RBTREE_NULL) {
01612         domain = (domain_type*) node->data;
01613         domain_print(fd, domain);
01614         node = ldns_rbtree_next(node);
01615     }
01616     return ODS_STATUS_OK;
01617 }