OpenDNSSEC-signer 1.3.0
/build/buildd/opendnssec-1.3.0/signer/src/signer/zonedata.c
Go to the documentation of this file.
00001 /*
00002  * $Id: zonedata.c 5320 2011-07-12 10:42:26Z jakob $
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 /*
00292 int
00293 zonedata_recover_rr_from_backup(zonedata_type* zd, ldns_rr* rr)
00294 {
00295     domain_type* domain = NULL;
00296 
00297     ods_log_assert(zd);
00298     ods_log_assert(zd->domains);
00299     ods_log_assert(rr);
00300 
00301     domain = zonedata_lookup_domain(zd, ldns_rr_owner(rr));
00302     if (domain) {
00303         return domain_recover_rr_from_backup(domain, rr);
00304     }
00305 
00306     ods_log_error("[%s] unable to recover RR to zonedata: domain does not exist",
00307         zd_str);
00308     return 1;
00309 }
00310 */
00311 
00316 /*
00317 int
00318 zonedata_recover_rrsig_from_backup(zonedata_type* zd, ldns_rr* rrsig,
00319     const char* locator, uint32_t flags)
00320 {
00321     domain_type* domain = NULL;
00322     ldns_rr_type type_covered;
00323 
00324     ods_log_assert(zd);
00325     ods_log_assert(zd->domains);
00326     ods_log_assert(rrsig);
00327 
00328     type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig));
00329     domain = zonedata_lookup_domain(zd, ldns_rr_owner(rrsig));
00330     if (domain) {
00331         return domain_recover_rrsig_from_backup(domain, rrsig, type_covered,
00332             locator, flags);
00333     }
00334     ods_log_error("[%s] unable to recover RRSIG to zonedata: domain does not "
00335         "exist", zd_str);
00336     return 1;
00337 }
00338 */
00339 
00340 
00345 static domain_type*
00346 zonedata_domain_search(ldns_rbtree_t* tree, ldns_rdf* dname)
00347 {
00348     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00349 
00350     if (!tree || !dname) {
00351         return NULL;
00352     }
00353     node = ldns_rbtree_search(tree, dname);
00354     if (node && node != LDNS_RBTREE_NULL) {
00355         return (domain_type*) node->data;
00356     }
00357     return NULL;
00358 }
00359 
00360 
00365 domain_type*
00366 zonedata_lookup_domain(zonedata_type* zd, ldns_rdf* dname)
00367 {
00368     if (!zd) return NULL;
00369 
00370     return zonedata_domain_search(zd->domains, dname);
00371 }
00372 
00373 
00378 domain_type*
00379 zonedata_add_domain(zonedata_type* zd, domain_type* domain)
00380 {
00381     ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
00382 
00383     if (!domain) {
00384         ods_log_error("[%s] unable to add domain: no domain", zd_str);
00385         return NULL;
00386     }
00387     ods_log_assert(domain);
00388 
00389     if (!zd || !zd->domains) {
00390         log_rdf(domain->dname, "unable to add domain, no storage", 1);
00391         return NULL;
00392     }
00393     ods_log_assert(zd);
00394     ods_log_assert(zd->domains);
00395 
00396     new_node = domain2node(domain);
00397     if (ldns_rbtree_insert(zd->domains, new_node) == NULL) {
00398         log_rdf(domain->dname, "unable to add domain, already present", 1);
00399         free((void*)new_node);
00400         return NULL;
00401     }
00402     log_rdf(domain->dname, "+DD", 6);
00403     return domain;
00404 }
00405 
00406 
00411 static domain_type*
00412 zonedata_del_domain_fixup(ldns_rbtree_t* tree, domain_type* domain)
00413 {
00414     domain_type* del_domain = NULL;
00415     ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
00416 
00417     ods_log_assert(tree);
00418     ods_log_assert(domain);
00419     ods_log_assert(domain->dname);
00420 
00421     del_node = ldns_rbtree_search(tree, (const void*)domain->dname);
00422     if (del_node) {
00423         del_node = ldns_rbtree_delete(tree, (const void*)domain->dname);
00424         del_domain = (domain_type*) del_node->data;
00425         domain_cleanup(del_domain);
00426         free((void*)del_node);
00427         return NULL;
00428     } else {
00429         log_rdf(domain->dname, "unable to del domain, not found", 1);
00430     }
00431     return domain;
00432 }
00433 
00434 
00439 domain_type*
00440 zonedata_del_domain(zonedata_type* zd, domain_type* domain)
00441 {
00442     if (!domain) {
00443         ods_log_error("[%s] unable to delete domain: no domain", zd_str);
00444         return NULL;
00445     }
00446     ods_log_assert(domain);
00447     ods_log_assert(domain->dname);
00448 
00449     if (!zd || !zd->domains) {
00450         log_rdf(domain->dname, "unable to delete domain, no zonedata", 1);
00451         return domain;
00452     }
00453     ods_log_assert(zd);
00454     ods_log_assert(zd->domains);
00455 
00456     if (domain->denial && zonedata_del_denial(zd, domain->denial) != NULL) {
00457         log_rdf(domain->dname, "unable to delete domain, failed to delete "
00458             "denial of existence data point", 1);
00459         return domain;
00460     }
00461     log_rdf(domain->dname, "-DD", 6);
00462     return zonedata_del_domain_fixup(zd->domains, domain);
00463 }
00464 
00465 
00470 static denial_type*
00471 zonedata_denial_search(ldns_rbtree_t* tree, ldns_rdf* dname)
00472 {
00473     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00474 
00475     if (!tree || !dname) {
00476         return NULL;
00477     }
00478     node = ldns_rbtree_search(tree, dname);
00479     if (node && node != LDNS_RBTREE_NULL) {
00480         return (denial_type*) node->data;
00481     }
00482     return NULL;
00483 }
00484 
00485 
00490 denial_type*
00491 zonedata_lookup_denial(zonedata_type* zd, ldns_rdf* dname)
00492 {
00493     if (!zd) return NULL;
00494 
00495     return zonedata_denial_search(zd->denial_chain, dname);
00496 }
00497 
00498 
00503 static ldns_rdf*
00504 dname_hash(ldns_rdf* dname, ldns_rdf* apex, nsec3params_type* nsec3params)
00505 {
00506     ldns_rdf* hashed_ownername = NULL;
00507     ldns_rdf* hashed_label = NULL;
00508 
00509     ods_log_assert(dname);
00510     ods_log_assert(apex);
00511     ods_log_assert(nsec3params);
00512 
00517     hashed_label = ldns_nsec3_hash_name(dname, nsec3params->algorithm,
00518         nsec3params->iterations, nsec3params->salt_len,
00519         nsec3params->salt_data);
00520     if (!hashed_label) {
00521         log_rdf(dname, "unable to hash dname, hash failed", 1);
00522         return NULL;
00523     }
00524     hashed_ownername = ldns_dname_cat_clone((const ldns_rdf*) hashed_label,
00525         (const ldns_rdf*) apex);
00526     if (!hashed_ownername) {
00527         log_rdf(dname, "unable to hash dname, concat apex failed", 1);
00528         return NULL;
00529     }
00530     ldns_rdf_deep_free(hashed_label);
00531     return hashed_ownername;
00532 }
00533 
00534 
00539 ods_status
00540 zonedata_add_denial(zonedata_type* zd, domain_type* domain, ldns_rdf* apex,
00541     nsec3params_type* nsec3params)
00542 {
00543     ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
00544     ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
00545     ldns_rdf* owner = NULL;
00546     denial_type* denial = NULL;
00547     denial_type* prev_denial = NULL;
00548 
00549     if (!domain) {
00550         ods_log_error("[%s] unable to add denial of existence data point: "
00551             "no domain", zd_str);
00552         return ODS_STATUS_ASSERT_ERR;
00553     }
00554     ods_log_assert(domain);
00555 
00556     if (!zd || !zd->denial_chain) {
00557         log_rdf(domain->dname, "unable to add denial of existence data "
00558             "point for domain, no denial chain", 1);
00559         return ODS_STATUS_ASSERT_ERR;
00560     }
00561     ods_log_assert(zd);
00562     ods_log_assert(zd->denial_chain);
00563 
00564     if (!apex) {
00565         log_rdf(domain->dname, "unable to add denial of existence data "
00566             "point for domain, apex unknown", 1);
00567         return ODS_STATUS_ASSERT_ERR;
00568     }
00569     ods_log_assert(apex);
00570 
00571     /* nsec or nsec3 */
00572     if (nsec3params) {
00573         owner = dname_hash(domain->dname, apex, nsec3params);
00574         if (!owner) {
00575             log_rdf(domain->dname, "unable to add denial of existence data "
00576                 "point for domain, dname hash failed", 1);
00577             return ODS_STATUS_ERR;
00578         }
00579     } else {
00580         owner = ldns_rdf_clone(domain->dname);
00581     }
00582     /* lookup */
00583     if (zonedata_lookup_denial(zd, owner) != NULL) {
00584         log_rdf(domain->dname, "unable to add denial of existence for "
00585             "domain, data point exists", 1);
00586         return ODS_STATUS_CONFLICT_ERR;
00587     }
00588     /* create */
00589     denial = denial_create(owner);
00590     new_node = denial2node(denial);
00591     ldns_rdf_deep_free(owner);
00592     /* insert */
00593     if (!ldns_rbtree_insert(zd->denial_chain, new_node)) {
00594         log_rdf(domain->dname, "unable to add denial of existence for "
00595             "domain, insert failed", 1);
00596         free((void*)new_node);
00597         denial_cleanup(denial);
00598         return ODS_STATUS_ERR;
00599     }
00600     /* denial of existence data point added */
00601     denial->bitmap_changed = 1;
00602     denial->nxt_changed = 1;
00603     prev_node = ldns_rbtree_previous(new_node);
00604     if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
00605         prev_node = ldns_rbtree_last(zd->denial_chain);
00606     }
00607     ods_log_assert(prev_node);
00608     prev_denial = (denial_type*) prev_node->data;
00609     ods_log_assert(prev_denial);
00610     prev_denial->nxt_changed = 1;
00611     domain->denial = denial;
00612     domain->denial->domain = domain; /* back reference */
00613     return ODS_STATUS_OK;
00614 }
00615 
00616 
00621 static denial_type*
00622 zonedata_del_denial_fixup(ldns_rbtree_t* tree, denial_type* denial)
00623 {
00624     denial_type* del_denial = NULL;
00625     denial_type* prev_denial = NULL;
00626     ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
00627     ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
00628     ods_status status = ODS_STATUS_OK;
00629 
00630     ods_log_assert(tree);
00631     ods_log_assert(denial);
00632     ods_log_assert(denial->owner);
00633 
00634     del_node = ldns_rbtree_search(tree, (const void*)denial->owner);
00635     if (del_node) {
00640         prev_node = ldns_rbtree_previous(del_node);
00641         if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
00642             prev_node = ldns_rbtree_last(tree);
00643         }
00644         ods_log_assert(prev_node);
00645         ods_log_assert(prev_node->data);
00646         prev_denial = (denial_type*) prev_node->data;
00647         prev_denial->nxt_changed = 1;
00648 
00649         /* delete old NSEC RR(s) */
00650         if (denial->rrset) {
00651             status = rrset_wipe_out(denial->rrset);
00652             if (status != ODS_STATUS_OK) {
00653                 ods_log_alert("[%s] unable to del denial of existence data "
00654                     "point: failed to wipe out NSEC RRset", zd_str);
00655                 return denial;
00656             }
00657             status = rrset_commit(denial->rrset);
00658             if (status != ODS_STATUS_OK) {
00659                 ods_log_alert("[%s] unable to del denial of existence data "
00660                     "point: failed to commit NSEC RRset", zd_str);
00661                 return denial;
00662             }
00663         }
00664 
00665         del_node = ldns_rbtree_delete(tree, (const void*)denial->owner);
00666         del_denial = (denial_type*) del_node->data;
00667         denial_cleanup(del_denial);
00668         free((void*)del_node);
00669         return NULL;
00670     } else {
00671         log_rdf(denial->owner, "unable to del denial of existence data "
00672             "point, not found", 1);
00673     }
00674     return denial;
00675 }
00676 
00677 
00682 denial_type*
00683 zonedata_del_denial(zonedata_type* zd, denial_type* denial)
00684 {
00685     if (!denial) {
00686         ods_log_error("[%s] unable to delete denial of existence data "
00687             "point: no data point", zd_str);
00688         return NULL;
00689     }
00690     ods_log_assert(denial);
00691 
00692     if (!zd || !zd->denial_chain) {
00693         log_rdf(denial->owner, "unable to delete denial of existence data "
00694             "point, no zone data", 1);
00695         return denial;
00696     }
00697     ods_log_assert(zd);
00698     ods_log_assert(zd->denial_chain);
00699 
00700     return zonedata_del_denial_fixup(zd->denial_chain, denial);
00701 }
00702 
00703 
00708 ods_status
00709 zonedata_diff(zonedata_type* zd, keylist_type* kl)
00710 {
00711     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00712     domain_type* domain = NULL;
00713     ods_status status = ODS_STATUS_OK;
00714 
00715     if (!zd || !zd->domains) {
00716         return status;
00717     }
00718     if (zd->domains->root != LDNS_RBTREE_NULL) {
00719         node = ldns_rbtree_first(zd->domains);
00720     }
00721     while (node && node != LDNS_RBTREE_NULL) {
00722         domain = (domain_type*) node->data;
00723         status = domain_diff(domain, kl);
00724         if (status != ODS_STATUS_OK) {
00725             return status;
00726         }
00727         node = ldns_rbtree_next(node);
00728     }
00729     return status;
00730 }
00731 
00732 
00737 ods_status
00738 zonedata_commit(zonedata_type* zd)
00739 {
00740     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00741     ldns_rbnode_t* nxtnode = LDNS_RBTREE_NULL;
00742     ldns_rbnode_t* tmpnode = LDNS_RBTREE_NULL;
00743     domain_type* domain = NULL;
00744     domain_type* nxtdomain = NULL;
00745     ods_status status = ODS_STATUS_OK;
00746     size_t oldnum = 0;
00747 
00748     if (!zd || !zd->domains) {
00749         return ODS_STATUS_OK;
00750     }
00751     if (zd->domains->root != LDNS_RBTREE_NULL) {
00752         node = ldns_rbtree_last(zd->domains);
00753     }
00754     while (node && node != LDNS_RBTREE_NULL) {
00755         domain = (domain_type*) node->data;
00756         oldnum = domain_count_rrset(domain);
00757         status = domain_commit(domain);
00758         if (status != ODS_STATUS_OK) {
00759             return status;
00760         }
00761         tmpnode = node;
00762         node = ldns_rbtree_previous(node);
00763 
00764         /* delete memory if empty leaf domain */
00765         if (domain_count_rrset(domain) <= 0) {
00766             /* empty domain */
00767             nxtnode = ldns_rbtree_next(tmpnode);
00768             nxtdomain = NULL;
00769             if (nxtnode && nxtnode != LDNS_RBTREE_NULL) {
00770                 nxtdomain = (domain_type*) nxtnode->data;
00771             }
00772             if (!nxtdomain ||
00773                 !ldns_dname_is_subdomain(nxtdomain->dname, domain->dname)) {
00774                 /* leaf domain */
00775                 if (zonedata_del_domain(zd, domain) != NULL) {
00776                     ods_log_warning("[%s] unable to delete obsoleted "
00777                         "domain", zd_str);
00778                     return ODS_STATUS_ERR;
00779                 }
00780             }
00781         } /* if (domain_count_rrset(domain) <= 0) */
00782     }
00783     return status;
00784 }
00785 
00786 
00791 void
00792 zonedata_rollback(zonedata_type* zd)
00793 {
00794     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00795     domain_type* domain = NULL;
00796 
00797     if (!zd || !zd->domains) {
00798         return;
00799     }
00800     if (zd->domains->root != LDNS_RBTREE_NULL) {
00801         node = ldns_rbtree_first(zd->domains);
00802     }
00803     while (node && node != LDNS_RBTREE_NULL) {
00804         domain = (domain_type*) node->data;
00805         domain_rollback(domain);
00806         node = ldns_rbtree_next(node);
00807     }
00808     return;
00809 }
00810 
00811 
00816 static int
00817 domain_ent2glue(ldns_rbnode_t* node)
00818 {
00819     ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
00820     domain_type* nextdomain = NULL;
00821     domain_type* domain = NULL;
00822     ods_log_assert(node && node != LDNS_RBTREE_NULL);
00823     domain = (domain_type*) node->data;
00824     if (domain->dstatus == DOMAIN_STATUS_ENT) {
00825         ods_log_assert(domain_count_rrset(domain) == 0);
00826         nextnode = ldns_rbtree_next(node);
00827         while (nextnode && nextnode != LDNS_RBTREE_NULL) {
00828             nextdomain = (domain_type*) nextnode->data;
00829             if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
00830                 /* we are done, no non-glue found */
00831                 return 1;
00832             }
00833             if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
00834                 nextdomain->dstatus != DOMAIN_STATUS_ENT &&
00835                 nextdomain->dstatus != DOMAIN_STATUS_NONE) {
00836                 /* found non-glue */
00837                 return 0;
00838             }
00839             nextnode = ldns_rbtree_next(nextnode);
00840         }
00841     } else {
00842         /* no empty non-terminal */
00843         ods_log_assert(domain_count_rrset(domain) != 0);
00844         return 0;
00845     }
00846     /* no non-glue found */
00847     return 1;
00848 }
00849 
00850 
00855 static int
00856 domain_ent2unsigned(ldns_rbnode_t* node)
00857 {
00858     ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
00859     domain_type* nextdomain = NULL;
00860     domain_type* domain = NULL;
00861     ods_log_assert(node && node != LDNS_RBTREE_NULL);
00862     domain = (domain_type*) node->data;
00863     if (domain->dstatus == DOMAIN_STATUS_ENT) {
00864         ods_log_assert(domain_count_rrset(domain) == 0);
00865         nextnode = ldns_rbtree_next(node);
00866         while (nextnode && nextnode != LDNS_RBTREE_NULL) {
00867             nextdomain = (domain_type*) nextnode->data;
00868             if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
00869                 /* we are done, no unsigned delegation found */
00870                 return 1;
00871             }
00872             if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
00873                 nextdomain->dstatus != DOMAIN_STATUS_ENT &&
00874                 nextdomain->dstatus != DOMAIN_STATUS_NS &&
00875                 nextdomain->dstatus != DOMAIN_STATUS_NONE) {
00876                 /* found data that has to be signed */
00877                 return 0;
00878             }
00879             nextnode = ldns_rbtree_next(nextnode);
00880         }
00881     } else {
00882         /* no empty non-terminal */
00883         ods_log_assert(domain_count_rrset(domain) != 0);
00884         return 0;
00885     }
00886     /* no unsigned delegation found */
00887     return 1;
00888 }
00889 
00890 
00895 static ods_status
00896 domain_entize(zonedata_type* zd, domain_type* domain, ldns_rdf* apex)
00897 {
00898     ldns_rdf* parent_rdf = NULL;
00899     domain_type* parent_domain = NULL;
00900 
00901     ods_log_assert(apex);
00902     ods_log_assert(domain);
00903     ods_log_assert(domain->dname);
00904     ods_log_assert(zd);
00905     ods_log_assert(zd->domains);
00906 
00907     if (domain->parent) {
00908         /* domain already has parent */
00909         return ODS_STATUS_OK;
00910     }
00911 
00912     while (domain && ldns_dname_is_subdomain(domain->dname, apex) &&
00913            ldns_dname_compare(domain->dname, apex) != 0) {
00914 
00922         parent_rdf = ldns_dname_left_chop(domain->dname);
00923         if (!parent_rdf) {
00924             log_rdf(domain->dname, "unable to entize domain, left chop "
00925                 "failed", 1);
00926             return ODS_STATUS_ERR;
00927         }
00928         ods_log_assert(parent_rdf);
00929 
00930         parent_domain = zonedata_lookup_domain(zd, parent_rdf);
00931         if (!parent_domain) {
00932             parent_domain = domain_create(parent_rdf);
00933             ldns_rdf_deep_free(parent_rdf);
00934             if (!parent_domain) {
00935                 log_rdf(domain->dname, "unable to entize domain, create "
00936                     "parent failed", 1);
00937                 return ODS_STATUS_ERR;
00938             }
00939             ods_log_assert(parent_domain);
00940             if (zonedata_add_domain(zd, parent_domain) == NULL) {
00941                 log_rdf(domain->dname, "unable to entize domain, add parent "
00942                     "failed", 1);
00943                 domain_cleanup(parent_domain);
00944                 return ODS_STATUS_ERR;
00945             }
00946             parent_domain->dstatus = DOMAIN_STATUS_ENT;
00947             domain->parent = parent_domain;
00948             /* continue with the parent domain */
00949             domain = parent_domain;
00950         } else {
00951             ldns_rdf_deep_free(parent_rdf);
00952             domain->parent = parent_domain;
00953             /* we are done with this domain */
00954             domain = NULL;
00955         }
00956     }
00957     return ODS_STATUS_OK;
00958 }
00959 
00960 
00965 ods_status
00966 zonedata_entize(zonedata_type* zd, ldns_rdf* apex)
00967 {
00968     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00969     ods_status status = ODS_STATUS_OK;
00970     domain_type* domain = NULL;
00971 
00972     if (!zd || !zd->domains) {
00973         ods_log_error("[%s] unable to entize zone data: no zone data",
00974             zd_str);
00975         return ODS_STATUS_ASSERT_ERR;
00976     }
00977     ods_log_assert(zd);
00978     ods_log_assert(zd->domains);
00979 
00980     if (!apex) {
00981         ods_log_error("[%s] unable to entize zone data: no zone apex",
00982             zd_str);
00983         return ODS_STATUS_ASSERT_ERR;
00984     }
00985     ods_log_assert(apex);
00986 
00987     node = ldns_rbtree_first(zd->domains);
00988     while (node && node != LDNS_RBTREE_NULL) {
00989         domain = (domain_type*) node->data;
00990         status = domain_entize(zd, domain, apex);
00991         if (status != ODS_STATUS_OK) {
00992             ods_log_error("[%s] unable to entize zone data: entize domain "
00993                 "failed", zd_str);
00994             return status;
00995         }
00996         domain_dstatus(domain);
00997         node = ldns_rbtree_next(node);
00998     }
00999     return ODS_STATUS_OK;
01000 }
01001 
01002 
01007 ods_status
01008 zonedata_nsecify(zonedata_type* zd, ldns_rr_class klass, uint32_t ttl,
01009     uint32_t* num_added)
01010 {
01011     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01012     ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
01013     ods_status status = ODS_STATUS_OK;
01014     domain_type* domain = NULL;
01015     domain_type* apex = NULL;
01016     denial_type* denial = NULL;
01017     denial_type* nxt = NULL;
01018     size_t nsec_added = 0;
01019 
01020     if (!zd || !zd->domains) {
01021         return ODS_STATUS_OK;
01022     }
01023     ods_log_assert(zd);
01024     ods_log_assert(zd->domains);
01025 
01026     node = ldns_rbtree_first(zd->domains);
01027     while (node && node != LDNS_RBTREE_NULL) {
01028         domain = (domain_type*) node->data;
01029         if (domain->dstatus == DOMAIN_STATUS_APEX) {
01030             apex = domain;
01031         }
01032         /* don't do glue-only or empty domains */
01033         if (domain->dstatus == DOMAIN_STATUS_NONE ||
01034             domain->dstatus == DOMAIN_STATUS_ENT ||
01035             domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
01036             domain_count_rrset(domain) <= 0) {
01037             if (domain_count_rrset(domain)) {
01038                 log_rdf(domain->dname, "nsecify: don't do glue domain", 6);
01039             } else {
01040                 log_rdf(domain->dname, "nsecify: don't do empty domain", 6);
01041             }
01042             if (domain->denial) {
01043                 if (zonedata_del_denial(zd, domain->denial) != NULL) {
01044                     ods_log_warning("[%s] unable to nsecify: failed to "
01045                         "delete denial of existence data point", zd_str);
01046                     return ODS_STATUS_ERR;
01047                 }
01048             }
01049             node = ldns_rbtree_next(node);
01050             continue;
01051         }
01052         if (!apex) {
01053             ods_log_alert("[%s] unable to nsecify: apex unknown", zd_str);
01054             return ODS_STATUS_ASSERT_ERR;
01055         }
01056 
01057         /* add the denial of existence */
01058         if (!domain->denial) {
01059             status = zonedata_add_denial(zd, domain, apex->dname, NULL);
01060             if (status != ODS_STATUS_OK) {
01061                 log_rdf(domain->dname, "unable to nsecify: failed to add "
01062                     "denial of existence for domain", 1);
01063                 return status;
01064             }
01065             nsec_added++;
01066         }
01067         node = ldns_rbtree_next(node);
01068     }
01069 
01071     node = ldns_rbtree_first(zd->denial_chain);
01072     while (node && node != LDNS_RBTREE_NULL) {
01073         denial = (denial_type*) node->data;
01074         nxt_node = ldns_rbtree_next(node);
01075         if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
01076              nxt_node = ldns_rbtree_first(zd->denial_chain);
01077         }
01078         nxt = (denial_type*) nxt_node->data;
01079 
01080         status = denial_nsecify(denial, nxt, ttl, klass);
01081         if (status != ODS_STATUS_OK) {
01082             ods_log_error("[%s] unable to nsecify: failed to add NSEC record",
01083                 zd_str);
01084             return status;
01085         }
01086         node = ldns_rbtree_next(node);
01087     }
01088     if (num_added) {
01089         *num_added = nsec_added;
01090     }
01091     return ODS_STATUS_OK;
01092 }
01093 
01094 
01099 ods_status
01100 zonedata_nsecify3(zonedata_type* zd, ldns_rr_class klass,
01101     uint32_t ttl, nsec3params_type* nsec3params, uint32_t* num_added)
01102 {
01103     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01104     ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
01105     ods_status status = ODS_STATUS_OK;
01106     domain_type* domain = NULL;
01107     domain_type* apex = NULL;
01108     denial_type* denial = NULL;
01109     denial_type* nxt = NULL;
01110     size_t nsec3_added = 0;
01111 
01112     if (!zd || !zd->domains) {
01113         return ODS_STATUS_OK;
01114     }
01115     ods_log_assert(zd);
01116     ods_log_assert(zd->domains);
01117 
01118     if (!nsec3params) {
01119         ods_log_error("[%s] unable to nsecify3: no nsec3 paramaters", zd_str);
01120         return ODS_STATUS_ASSERT_ERR;
01121     }
01122     ods_log_assert(nsec3params);
01123 
01124     node = ldns_rbtree_first(zd->domains);
01125     while (node && node != LDNS_RBTREE_NULL) {
01126         domain = (domain_type*) node->data;
01127         if (domain->dstatus == DOMAIN_STATUS_APEX) {
01128             apex = domain;
01129         }
01130 
01131         /* don't do glue-only domains */
01132         if (domain->dstatus == DOMAIN_STATUS_NONE ||
01133             domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
01134             domain_ent2glue(node)) {
01135             log_rdf(domain->dname, "nsecify3: don't do glue domain" , 6);
01136             if (domain->denial) {
01137                 if (zonedata_del_denial(zd, domain->denial) != NULL) {
01138                     ods_log_error("[%s] unable to nsecify3: failed to "
01139                         "delete denial of existence data point", zd_str);
01140                     return ODS_STATUS_ERR;
01141                 }
01142             }
01143             node = ldns_rbtree_next(node);
01144             continue;
01145         }
01146         /* Opt-Out? */
01147         if (nsec3params->flags) {
01148             /* If Opt-Out is being used, owner names of unsigned delegations
01149                MAY be excluded. */
01150             if (domain->dstatus == DOMAIN_STATUS_NS ||
01151                 domain_ent2unsigned(node)) {
01152                 if (domain->dstatus == DOMAIN_STATUS_NS) {
01153                     log_rdf(domain->dname, "nsecify3: opt-out (unsigned "
01154                         "delegation)", 5);
01155                 } else {
01156                     log_rdf(domain->dname, "nsecify3: opt-out (empty "
01157                         "non-terminal (to unsigned delegation))", 5);
01158                 }
01159                 if (domain->denial) {
01160                     if (zonedata_del_denial(zd, domain->denial) != NULL) {
01161                         ods_log_error("[%s] unable to nsecify3: failed to "
01162                             "delete denial of existence data point", zd_str);
01163                         return ODS_STATUS_ERR;
01164                     }
01165                 }
01166                 node = ldns_rbtree_next(node);
01167                 continue;
01168             }
01169         }
01170         if (!apex) {
01171             ods_log_alert("[%s] unable to nsecify3: apex unknown", zd_str);
01172             return ODS_STATUS_ASSERT_ERR;
01173         }
01174 
01175         /* add the denial of existence */
01176         if (!domain->denial) {
01177             status = zonedata_add_denial(zd, domain, apex->dname,
01178                 nsec3params);
01179             if (status != ODS_STATUS_OK) {
01180                 log_rdf(domain->dname, "unable to nsecify3: failed to add "
01181                     "denial of existence for domain", 1);
01182                 return status;
01183             }
01184             nsec3_added++;
01185         }
01186 
01187         /* The Next Hashed Owner Name field is left blank for the moment. */
01188 
01196         /* [TODO] */
01206         node = ldns_rbtree_next(node);
01207     }
01208 
01210     node = ldns_rbtree_first(zd->denial_chain);
01211     while (node && node != LDNS_RBTREE_NULL) {
01212         denial = (denial_type*) node->data;
01213         nxt_node = ldns_rbtree_next(node);
01214         if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
01215              nxt_node = ldns_rbtree_first(zd->denial_chain);
01216         }
01217         nxt = (denial_type*) nxt_node->data;
01218 
01219         status = denial_nsecify3(denial, nxt, ttl, klass, nsec3params);
01220         if (status != ODS_STATUS_OK) {
01221             ods_log_error("[%s] unable to nsecify3: failed to add NSEC3 "
01222                 "record", zd_str);
01223             return status;
01224         }
01225         node = ldns_rbtree_next(node);
01226     }
01227     if (num_added) {
01228         *num_added = nsec3_added;
01229     }
01230     return ODS_STATUS_OK;
01231 }
01232 
01233 
01238 ods_status
01239 zonedata_update_serial(zonedata_type* zd, signconf_type* sc)
01240 {
01241     uint32_t soa = 0;
01242     uint32_t prev = 0;
01243     uint32_t update = 0;
01244 
01245     ods_log_assert(zd);
01246     ods_log_assert(sc);
01247 
01248     prev = zd->outbound_serial;
01249     if (!zd->initialized) {
01250         prev = zd->inbound_serial;
01251     }
01252     ods_log_debug("[%s] update serial: in=%u internal=%u out=%u now=%u",
01253         zd_str, zd->inbound_serial, zd->internal_serial, zd->outbound_serial,
01254         (uint32_t) time_now());
01255 
01256     if (!sc->soa_serial) {
01257         ods_log_error("[%s] no serial type given", zd_str);
01258         return ODS_STATUS_ERR;
01259     }
01260 
01261     if (ods_strcmp(sc->soa_serial, "unixtime") == 0) {
01262         soa = (uint32_t) time_now();
01263         if (!DNS_SERIAL_GT(soa, prev)) {
01264             soa = prev + 1;
01265         }
01266     } else if (strncmp(sc->soa_serial, "counter", 7) == 0) {
01267         soa = zd->inbound_serial;
01268         if (zd->initialized && !DNS_SERIAL_GT(soa, prev)) {
01269             soa = prev + 1;
01270         }
01271     } else if (strncmp(sc->soa_serial, "datecounter", 11) == 0) {
01272         soa = (uint32_t) time_datestamp(0, "%Y%m%d", NULL) * 100;
01273         if (!DNS_SERIAL_GT(soa, prev)) {
01274             soa = prev + 1;
01275         }
01276     } else if (strncmp(sc->soa_serial, "keep", 4) == 0) {
01277         soa = zd->inbound_serial;
01278         if (zd->initialized && !DNS_SERIAL_GT(soa, prev)) {
01279             ods_log_error("[%s] cannot keep SOA SERIAL from input zone "
01280                 " (%u): output SOA SERIAL is %u", zd_str, soa, prev);
01281             return ODS_STATUS_CONFLICT_ERR;
01282         }
01283     } else {
01284         ods_log_error("[%s] unknown serial type %s", zd_str, sc->soa_serial);
01285         return ODS_STATUS_ERR;
01286     }
01287 
01288     /* serial is stored in 32 bits */
01289     update = soa - prev;
01290     if (update > 0x7FFFFFFF) {
01291         update = 0x7FFFFFFF;
01292     }
01293 
01294     if (!zd->initialized) {
01295         zd->internal_serial = soa;
01296     } else {
01297         zd->internal_serial += update; /* automatically does % 2^32 */
01298     }
01299     ods_log_debug("[%s] update serial: %u + %u = %u", zd_str, prev, update,
01300         zd->internal_serial);
01301     return ODS_STATUS_OK;
01302 }
01303 
01304 
01309 ods_status
01310 zonedata_queue(zonedata_type* zd, fifoq_type* q, worker_type* worker)
01311 {
01312     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01313     domain_type* domain = NULL;
01314     ods_status status = ODS_STATUS_OK;
01315 
01316     if (!zd || !zd->domains) {
01317         return ODS_STATUS_OK;
01318     }
01319     if (zd->domains->root != LDNS_RBTREE_NULL) {
01320         node = ldns_rbtree_first(zd->domains);
01321     }
01322     while (node && node != LDNS_RBTREE_NULL) {
01323         domain = (domain_type*) node->data;
01324         status = domain_queue(domain, q, worker);
01325         if (status != ODS_STATUS_OK) {
01326             return status;
01327         }
01328         node = ldns_rbtree_next(node);
01329     }
01330     return status;
01331 }
01332 
01333 
01338 static int
01339 zonedata_examine_domain_is_occluded(zonedata_type* zd, domain_type* domain,
01340     ldns_rdf* apex)
01341 {
01342     ldns_rdf* parent_rdf = NULL;
01343     ldns_rdf* next_rdf = NULL;
01344     domain_type* parent_domain = NULL;
01345     char* str_name = NULL;
01346     char* str_parent = NULL;
01347 
01348     ods_log_assert(apex);
01349     ods_log_assert(domain);
01350     ods_log_assert(domain->dname);
01351     ods_log_assert(zd);
01352     ods_log_assert(zd->domains);
01353 
01354     if (ldns_dname_compare(domain->dname, apex) == 0) {
01355         return 0;
01356     }
01357 
01358     if (domain_examine_valid_zonecut(domain) != 0) {
01359         log_rdf(domain->dname, "occluded (non-glue non-DS) data at NS", 2);
01360         return 1;
01361     }
01362 
01363     parent_rdf = ldns_dname_left_chop(domain->dname);
01364     while (parent_rdf && ldns_dname_is_subdomain(parent_rdf, apex) &&
01365            ldns_dname_compare(parent_rdf, apex) != 0) {
01366 
01367         parent_domain = zonedata_lookup_domain(zd, parent_rdf);
01368         next_rdf = ldns_dname_left_chop(parent_rdf);
01369         ldns_rdf_deep_free(parent_rdf);
01370 
01371         if (parent_domain) {
01372             /* check for DNAME or NS */
01373             if (domain_examine_data_exists(parent_domain, LDNS_RR_TYPE_DNAME,
01374                 0) && domain_examine_data_exists(domain, 0, 0)) {
01375                 /* data below DNAME */
01376                 str_name = ldns_rdf2str(domain->dname);
01377                 str_parent = ldns_rdf2str(parent_domain->dname);
01378                 ods_log_warning("[%s] occluded data at %s (below %s DNAME)",
01379                     zd_str, str_name, str_parent);
01380                 free((void*)str_name);
01381                 free((void*)str_parent);
01382                 return 1;
01383             } else if (domain_examine_data_exists(parent_domain,
01384                 LDNS_RR_TYPE_NS, 0) &&
01385                 domain_examine_data_exists(domain, 0, 1)) {
01386                 /* data (non-glue) below NS */
01387                 str_name = ldns_rdf2str(domain->dname);
01388                 str_parent = ldns_rdf2str(parent_domain->dname);
01389                 ods_log_warning("[%s] occluded (non-glue) data at %s (below "
01390                     "%s NS)", zd_str, str_name, str_parent);
01391                 free((void*)str_name);
01392                 free((void*)str_parent);
01393                 return 1;
01394 /* allow for now (root zone has it)
01395             } else if (domain_examine_data_exists(parent_domain,
01396                 LDNS_RR_TYPE_NS, 0) &&
01397                 domain_examine_data_exists(domain, 0, 0) &&
01398                 !domain_examine_ns_rdata(parent_domain, domain->dname)) {
01399                 str_name = ldns_rdf2str(domain->dname);
01400                 str_parent = ldns_rdf2str(parent_domain->dname);
01401                 ods_log_warning("[%s] occluded data at %s (below %s NS)",
01402                     zd_str, str_name, str_parent);
01403                 free((void*)str_name);
01404                 free((void*)str_parent);
01405                 return 1;
01406 */
01407             }
01408         }
01409         parent_rdf = next_rdf;
01410     }
01411     if (parent_rdf) {
01412         ldns_rdf_deep_free(parent_rdf);
01413     }
01414     return 0;
01415 }
01416 
01417 
01422 ods_status
01423 zonedata_examine(zonedata_type* zd, ldns_rdf* apex, adapter_mode mode)
01424 {
01425     int result = 0;
01426     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01427     domain_type* domain = NULL;
01428     ods_status status = ODS_STATUS_OK;
01429 
01430     if (!zd || !zd->domains) {
01431        /* no zone data, no error */
01432        return ODS_STATUS_OK;
01433     }
01434     ods_log_assert(zd);
01435     ods_log_assert(zd->domains);
01436 
01437     if (zd->domains->root != LDNS_RBTREE_NULL) {
01438         node = ldns_rbtree_first(zd->domains);
01439     }
01440     while (node && node != LDNS_RBTREE_NULL) {
01441         domain = (domain_type*) node->data;
01442         result =
01443         /* Thou shall not have other data next to CNAME */
01444         domain_examine_rrset_is_alone(domain, LDNS_RR_TYPE_CNAME) &&
01445         /* Thou shall have at most one CNAME per name */
01446         domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_CNAME) &&
01447         /* Thou shall have at most one DNAME per name */
01448         domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_DNAME);
01449         if (!result) {
01450             status = ODS_STATUS_ERR;
01451         }
01452 
01453         if (mode == ADAPTER_FILE) {
01454             result =
01455             /* Thou shall not have occluded data in your zone file */
01456             zonedata_examine_domain_is_occluded(zd, domain, apex);
01457             if (result) {
01458                 ; /* just warn if there is occluded data */
01459             }
01460         }
01461         node = ldns_rbtree_next(node);
01462     }
01463     return status;
01464 }
01465 
01466 
01471 void
01472 zonedata_wipe_denial(zonedata_type* zd)
01473 {
01474     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01475     denial_type* denial = NULL;
01476 
01477     if (zd && zd->denial_chain) {
01478         node = ldns_rbtree_first(zd->denial_chain);
01479         while (node && node != LDNS_RBTREE_NULL) {
01480             denial = (denial_type*) node->data;
01481             if (denial->rrset) {
01482                 /* [TODO] IXFR delete NSEC */
01483                 rrset_cleanup(denial->rrset);
01484                 denial->rrset = NULL;
01485             }
01486             node = ldns_rbtree_next(node);
01487         }
01488     }
01489     return;
01490 }
01491 
01492 
01497 static void
01498 domain_delfunc(ldns_rbnode_t* elem)
01499 {
01500     domain_type* domain = NULL;
01501 
01502     if (elem && elem != LDNS_RBTREE_NULL) {
01503         domain = (domain_type*) elem->data;
01504         domain_delfunc(elem->left);
01505         domain_delfunc(elem->right);
01506 
01507         domain_cleanup(domain);
01508         free((void*)elem);
01509     }
01510     return;
01511 }
01512 
01513 
01518 static void
01519 denial_delfunc(ldns_rbnode_t* elem)
01520 {
01521     denial_type* denial = NULL;
01522     domain_type* domain = NULL;
01523 
01524 
01525     if (elem && elem != LDNS_RBTREE_NULL) {
01526         denial = (denial_type*) elem->data;
01527         denial_delfunc(elem->left);
01528         denial_delfunc(elem->right);
01529 
01530         domain = denial->domain;
01531         if (domain) {
01532             domain->denial = NULL;
01533         }
01534         denial_cleanup(denial);
01535 
01536         free((void*)elem);
01537     }
01538     return;
01539 }
01540 
01541 
01546 static void
01547 zonedata_cleanup_domains(zonedata_type* zd)
01548 {
01549     if (zd && zd->domains) {
01550         domain_delfunc(zd->domains->root);
01551         ldns_rbtree_free(zd->domains);
01552         zd->domains = NULL;
01553     }
01554     return;
01555 }
01556 
01557 
01562 void
01563 zonedata_cleanup_chain(zonedata_type* zd)
01564 {
01565     if (zd && zd->denial_chain) {
01566         denial_delfunc(zd->denial_chain->root);
01567         ldns_rbtree_free(zd->denial_chain);
01568         zd->denial_chain = NULL;
01569     }
01570     return;
01571 }
01572 
01573 
01578 void
01579 zonedata_cleanup(zonedata_type* zd)
01580 {
01581     allocator_type* allocator;
01582 
01583     if (!zd) {
01584         return;
01585     }
01586     zonedata_cleanup_chain(zd);
01587     zonedata_cleanup_domains(zd);
01588     allocator = zd->allocator;
01589     allocator_deallocate(allocator, (void*) zd);
01590     return;
01591 }
01592 
01593 
01598 void
01599 zonedata_backup(FILE* fd, zonedata_type* zd)
01600 {
01601     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01602     domain_type* domain = NULL;
01603 
01604     if (!fd || !zd) {
01605         return;
01606     }
01607 
01608     node = ldns_rbtree_first(zd->domains);
01609     while (node && node != LDNS_RBTREE_NULL) {
01610         domain = (domain_type*) node->data;
01611         domain_backup(fd, domain);
01612         node = ldns_rbtree_next(node);
01613     }
01614     fprintf(fd, ";;\n");
01615     return;
01616 }
01617 
01618 
01623 ods_status
01624 zonedata_print(FILE* fd, zonedata_type* zd)
01625 {
01626     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
01627     domain_type* domain = NULL;
01628 
01629     if (!fd) {
01630         ods_log_error("[%s] unable to print zone data: no file descriptor",
01631             zd_str);
01632         return ODS_STATUS_ASSERT_ERR;
01633     }
01634     ods_log_assert(fd);
01635 
01636     if (!zd || !zd->domains) {
01637         ods_log_error("[%s] unable to print zone data: no zone data",
01638             zd_str);
01639         return ODS_STATUS_ASSERT_ERR;
01640     }
01641     ods_log_assert(zd);
01642     ods_log_assert(zd->domains);
01643 
01644     node = ldns_rbtree_first(zd->domains);
01645     if (!node || node == LDNS_RBTREE_NULL) {
01646         fprintf(fd, "; empty zone\n");
01647         return ODS_STATUS_OK;
01648     }
01649     while (node && node != LDNS_RBTREE_NULL) {
01650         domain = (domain_type*) node->data;
01651         domain_print(fd, domain);
01652         node = ldns_rbtree_next(node);
01653     }
01654     return ODS_STATUS_OK;
01655 }