OpenDNSSEC-signer 1.2.1

/build/buildd-opendnssec_1.2.1.dfsg-1-ia64-j6OroR/opendnssec-1.2.1.dfsg/signer/src/signer/domain.c

Go to the documentation of this file.
00001 /*
00002  * $Id: domain.c 4523 2011-03-03 12:48:18Z 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 "signer/backup.h"
00036 #include "signer/domain.h"
00037 #include "signer/hsm.h"
00038 #include "signer/rrset.h"
00039 #include "util/duration.h"
00040 #include "util/log.h"
00041 #include "util/se_malloc.h"
00042 #include "util/util.h"
00043 
00044 #include <ldns/ldns.h> /* ldns_*() */
00045 
00046 
00051 static int
00052 rrset_compare(const void* a, const void* b)
00053 {
00054     ldns_rr_type* x = (ldns_rr_type*)a;
00055     ldns_rr_type* y = (ldns_rr_type*)b;
00056     return (*x)-(*y);
00057 }
00058 
00059 
00064 domain_type*
00065 domain_create(ldns_rdf* dname)
00066 {
00067     domain_type* domain = (domain_type*) se_malloc(sizeof(domain_type));
00068     se_log_assert(dname);
00069 
00070     domain->name = ldns_rdf_clone(dname);
00071     domain->parent = NULL;
00072     domain->denial = NULL;
00073     domain->rrsets = ldns_rbtree_create(rrset_compare);
00074     domain->domain_status = DOMAIN_STATUS_NONE;
00075     domain->internal_serial = 0;
00076     domain->initialized = 0;
00077     domain->outbound_serial = 0;
00078     domain->subdomain_count = 0;
00079     domain->subdomain_auth = 0;
00080     return domain;
00081 }
00082 
00083 
00088 domain_type*
00089 domain_recover_from_backup(FILE* fd, int* curnxt, int* curbm)
00090 {
00091     domain_type* domain = NULL;
00092     const char* name = NULL;
00093     uint32_t internal_serial = 0;
00094     uint32_t outbound_serial = 0;
00095     int domain_status = DOMAIN_STATUS_NONE;
00096     size_t subdomain_count = 0;
00097     size_t subdomain_auth = 0;
00098     int nsec_bitmap_changed = 0;
00099     int nsec_nxt_changed = 0;
00100 
00101     se_log_assert(fd);
00102 
00103     if (!backup_read_str(fd, &name) ||
00104         !backup_read_uint32_t(fd, &internal_serial) ||
00105         !backup_read_uint32_t(fd, &outbound_serial) ||
00106         !backup_read_int(fd, &domain_status) ||
00107         !backup_read_size_t(fd, &subdomain_count) ||
00108         !backup_read_size_t(fd, &subdomain_auth) ||
00109         !backup_read_int(fd, &nsec_bitmap_changed) ||
00110         !backup_read_int(fd, &nsec_nxt_changed)) {
00111         se_log_error("domain part in backup file is corrupted");
00112         if (name) {
00113             se_free((void*)name);
00114         }
00115         return NULL;
00116     }
00117 
00118     domain = (domain_type*) se_malloc(sizeof(domain_type));
00119     se_log_assert(name);
00120     domain->name = ldns_dname_new_frm_str(name);
00121     if (!domain->name) {
00122         se_log_error("failed to create domain from name");
00123         se_free((void*)name);
00124         se_free((void*)domain);
00125         return NULL;
00126     }
00127     domain->parent = NULL;
00128     domain->denial = NULL;
00129     domain->rrsets = ldns_rbtree_create(rrset_compare);
00130     domain->domain_status = domain_status;
00131     domain->internal_serial = internal_serial;
00132     domain->initialized = 0;
00133     domain->outbound_serial = outbound_serial;
00134     domain->subdomain_count = subdomain_count;
00135     domain->subdomain_auth = subdomain_auth;
00136     se_log_deeebug("recovered domain %s internal_serial=%u, "
00137         "outbound_serial=%u, domain_status=%i, nsec_status=(%i, %i)",
00138         name, domain->internal_serial, domain->outbound_serial,
00139         domain->domain_status, nsec_bitmap_changed,
00140         nsec_nxt_changed);
00141 
00142     se_free((void*)name);
00143     if (curnxt) {
00144         *curnxt = nsec_nxt_changed;
00145     }
00146     if (curbm) {
00147         *curbm = nsec_bitmap_changed;
00148     }
00149     return domain;
00150 }
00151 
00156 static ldns_rbnode_t*
00157 rrset2node(rrset_type* rrset)
00158 {
00159     ldns_rbnode_t* node = (ldns_rbnode_t*) se_malloc(sizeof(ldns_rbnode_t));
00160     node->key = &(rrset->rr_type);
00161     node->data = rrset;
00162     return node;
00163 }
00164 
00165 
00170 rrset_type*
00171 domain_lookup_rrset(domain_type* domain, ldns_rr_type type)
00172 {
00173     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00174 
00175     se_log_assert(domain);
00176     se_log_assert(domain->rrsets);
00177 
00178     node = ldns_rbtree_search(domain->rrsets, &(type));
00179     if (node && node != LDNS_RBTREE_NULL) {
00180         return (rrset_type*) node->data;
00181     }
00182     return NULL;
00183 }
00184 
00185 
00190 rrset_type*
00191 domain_add_rrset(domain_type* domain, rrset_type* rrset, int recover)
00192 {
00193     ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
00194     char* str = NULL;
00195 
00196     se_log_assert(rrset);
00197     se_log_assert(domain);
00198     se_log_assert(domain->rrsets);
00199 
00200     new_node = rrset2node(rrset);
00201     if (ldns_rbtree_insert(domain->rrsets, new_node) == NULL) {
00202         str = ldns_rdf2str(domain->name);
00203         se_log_error("unable to add RRset %i to domain %s: already present",
00204             rrset->rr_type, str?str:"(null)");
00205         se_free((void*)str);
00206         se_free((void*)new_node);
00207         return NULL;
00208     }
00209     if (!recover && domain->denial) {
00210         domain->denial->bitmap_changed = 1;
00211     }
00212     return rrset;
00213 }
00214 
00215 
00220 rrset_type*
00221 domain_del_rrset(domain_type* domain, rrset_type* rrset, int recover)
00222 {
00223     rrset_type* del_rrset = NULL;
00224     ldns_rbnode_t* del_node = NULL;
00225     char* str = NULL;
00226 
00227     se_log_assert(rrset);
00228     se_log_assert(domain);
00229     se_log_assert(domain->rrsets);
00230 
00231     del_node = ldns_rbtree_delete(domain->rrsets,
00232         (const void*)&rrset->rr_type);
00233     if (del_node) {
00234         del_rrset = (rrset_type*) del_node->data;
00235         rrset_cleanup(del_rrset);
00236         se_free((void*)del_node);
00237         if (!recover && domain->denial) {
00238             domain->denial->bitmap_changed = 1;
00239         }
00240         return NULL;
00241     } else {
00242         str = ldns_rdf2str(domain->name);
00243         se_log_error("unable to delete RRset %i from domain %s: "
00244             "not in tree", rrset->rr_type, str?str:"(null)");
00245         se_free((void*)str);
00246         return rrset;
00247     }
00248     return rrset;
00249 }
00250 
00251 
00256 int domain_count_rrset(domain_type* domain)
00257 {
00258     se_log_assert(domain);
00259     if (!domain->rrsets) {
00260         return 0;
00261     }
00262     return domain->rrsets->count;
00263 }
00264 
00265 
00270 int
00271 domain_examine_data_exists(domain_type* domain, ldns_rr_type rrtype,
00272     int skip_glue)
00273 {
00274     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00275     rrset_type* rrset = NULL;
00276 
00277     se_log_assert(domain);
00278 
00279     if (domain->rrsets->root != LDNS_RBTREE_NULL) {
00280         node = ldns_rbtree_first(domain->rrsets);
00281     }
00282     while (node && node != LDNS_RBTREE_NULL) {
00283         rrset = (rrset_type*) node->data;
00284         if (rrset_count_RR(rrset) > 0) {
00285             if (rrtype) {
00286                 /* looking for a specific RRset */
00287                 if (rrset->rr_type == rrtype) {
00288                     return 0;
00289                 }
00290             } else if (!skip_glue ||
00291                 (rrset->rr_type != LDNS_RR_TYPE_A &&
00292                  rrset->rr_type != LDNS_RR_TYPE_AAAA)) {
00293                 /* not glue or not skipping glue */
00294                 return 0;
00295             }
00296         }
00297         node = ldns_rbtree_next(node);
00298     }
00299     return 1;
00300 }
00301 
00302 
00307 int
00308 domain_examine_ns_rdata(domain_type* domain, ldns_rdf* nsdname)
00309 {
00310     rrset_type* rrset = NULL;
00311 
00312     se_log_assert(domain);
00313     if (!nsdname) {
00314        return 1;
00315     }
00316 
00317     rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_NS);
00318     if (rrset && rrset_count_RR(rrset) > 0) {
00319         /* NS RRset exists after update */
00320         if (rrset_examine_ns_rdata(rrset, nsdname) == 0) {
00321             return 0;
00322         }
00323     }
00324     return 1;
00325 }
00326 
00327 
00332 int
00333 domain_examine_rrset_is_alone(domain_type* domain, ldns_rr_type rrtype)
00334 {
00335     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00336     rrset_type* rrset = NULL;
00337     ldns_dnssec_rrs* rrs = NULL;
00338     char* str_name = NULL;
00339     char* str_type = NULL;
00340 
00341     se_log_assert(domain);
00342     se_log_assert(rrtype);
00343 
00344     rrset = domain_lookup_rrset(domain, rrtype);
00345     if (rrset && rrset_count_RR(rrset) > 0) {
00346         if (domain_count_rrset(domain) < 2) {
00347             /* one or zero, that's ok */
00348             return 0;
00349         }
00350         /* make sure all other RRsets become empty */
00351         if (domain->rrsets->root != LDNS_RBTREE_NULL) {
00352             node = ldns_rbtree_first(domain->rrsets);
00353         }
00354         while (node && node != LDNS_RBTREE_NULL) {
00355             rrset = (rrset_type*) node->data;
00356             if (rrset->rr_type != rrtype && rrset_count_RR(rrset) > 0) {
00357                 /* found other data next to rrtype */
00358                 str_name = ldns_rdf2str(domain->name);
00359                 str_type = ldns_rr_type2str(rrtype);
00360                 se_log_error("other data next to %s %s", str_name, str_type);
00361                 rrs = rrset->rrs;
00362                 while (rrs) {
00363                     if (rrs->rr) {
00364                         log_rr(rrs->rr, "next-to-CNAME: ", 2);
00365                     }
00366                     rrs = rrs->next;
00367                 }
00368                 rrs = rrset->add;
00369                 while (rrs) {
00370                     if (rrs->rr) {
00371                         log_rr(rrs->rr, "next-to-CNAME: ", 2);
00372                     }
00373                     rrs = rrs->next;
00374                 }
00375                 se_free((void*)str_name);
00376                 se_free((void*)str_type);
00377                 return 1;
00378             }
00379             node = ldns_rbtree_next(node);
00380         }
00381     }
00382     return 0;
00383 }
00384 
00385 
00390 int
00391 domain_examine_valid_zonecut(domain_type* domain)
00392 {
00393     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00394     rrset_type* rrset = NULL;
00395 
00396     se_log_assert(domain);
00397 
00398     rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_NS);
00399     if (rrset && rrset_count_RR(rrset) > 0) {
00400         /* make sure all other RRsets become empty (except DS, glue) */
00401         if (domain->rrsets->root != LDNS_RBTREE_NULL) {
00402             node = ldns_rbtree_first(domain->rrsets);
00403         }
00404         while (node && node != LDNS_RBTREE_NULL) {
00405             rrset = (rrset_type*) node->data;
00406             if (rrset->rr_type != LDNS_RR_TYPE_DS &&
00407                 rrset->rr_type != LDNS_RR_TYPE_NS &&
00408                 rrset->rr_type != LDNS_RR_TYPE_A &&
00409                 rrset->rr_type != LDNS_RR_TYPE_AAAA &&
00410                 rrset_count_RR(rrset) > 0) {
00411                 /* found occluded data next to delegation */
00412                 se_log_error("occluded glue data at zonecut, RRtype=%u",
00413                     rrset->rr_type);
00414                 return 1;
00415             } else if (rrset->rr_type == LDNS_RR_TYPE_A ||
00416                 rrset->rr_type == LDNS_RR_TYPE_AAAA) {
00417                 /* check if glue is allowed at the delegation */
00418                 if (rrset_count_RR(rrset) > 0 &&
00419                     domain_examine_ns_rdata(domain, domain->name) != 0) {
00420                     se_log_error("occluded glue data at zonecut, #RR=%u",
00421                         rrset_count_RR(rrset));
00422                     return 1;
00423                 }
00424             }
00425 
00426             node = ldns_rbtree_next(node);
00427         }
00428     }
00429     return 0;
00430 }
00431 
00432 
00437 int
00438 domain_examine_rrset_is_singleton(domain_type* domain, ldns_rr_type rrtype)
00439 {
00440     rrset_type* rrset = NULL;
00441     char* str_name = NULL;
00442     char* str_type = NULL;
00443 
00444     se_log_assert(domain);
00445     se_log_assert(rrtype);
00446 
00447     rrset = domain_lookup_rrset(domain, rrtype);
00448     if (rrset && rrset_count_RR(rrset) > 1) {
00449         /* multiple RRs in the RRset for singleton RRtype*/
00450         str_name = ldns_rdf2str(domain->name);
00451         str_type = ldns_rr_type2str(rrtype);
00452         se_log_error("multiple records for singleton type at %s %s",
00453             str_name, str_type);
00454         se_free((void*)str_name);
00455         se_free((void*)str_type);
00456         return 1;
00457     }
00458     return 0;
00459 }
00460 
00461 
00466 int
00467 domain_update(domain_type* domain, uint32_t serial)
00468 {
00469     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00470     rrset_type* rrset = NULL;
00471 
00472     se_log_assert(serial);
00473     se_log_assert(domain);
00474     se_log_assert(domain->rrsets);
00475 
00476     if (!domain->initialized || DNS_SERIAL_GT(serial, domain->internal_serial)) {
00477         if (domain->rrsets->root != LDNS_RBTREE_NULL) {
00478             node = ldns_rbtree_first(domain->rrsets);
00479         }
00480         while (node && node != LDNS_RBTREE_NULL) {
00481             rrset = (rrset_type*) node->data;
00482             if (rrset->rr_type == LDNS_RR_TYPE_SOA && rrset->rrs &&
00483                 rrset->rrs->rr) {
00484                 rrset->drop_signatures = 1;
00485             }
00486 
00487             if (rrset_update(rrset, serial) != 0) {
00488                 se_log_error("failed to update domain to serial %u: failed "
00489                     "to update RRset", serial);
00490                 return 1;
00491             }
00492             node = ldns_rbtree_next(node);
00493             /* delete memory of RRsets if no RRs exist */
00494             if (rrset_count_rr(rrset) <= 0) {
00495                 rrset = domain_del_rrset(domain, rrset, 0);
00496                 if (rrset) {
00497                     se_log_error("failed to delete obsoleted RRset");
00498                 }
00499             }
00500         }
00501         domain->internal_serial = serial;
00502         domain->initialized = 1;
00503     } else {
00504         se_log_error("cannot update domain: serial %u should be larger than "
00505             "domain internal serial %u", serial, domain->internal_serial);
00506         return 2;
00507     }
00508     return 0;
00509 }
00510 
00511 
00516 void
00517 domain_cancel_update(domain_type* domain)
00518 {
00519     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00520     rrset_type* rrset = NULL;
00521 
00522     se_log_assert(domain);
00523     se_log_assert(domain->rrsets);
00524 
00525     if (domain->rrsets->root != LDNS_RBTREE_NULL) {
00526         node = ldns_rbtree_first(domain->rrsets);
00527     }
00528     while (node && node != LDNS_RBTREE_NULL) {
00529         rrset = (rrset_type*) node->data;
00530         rrset_cancel_update(rrset);
00531         node = ldns_rbtree_next(node);
00532     }
00533     return;
00534 }
00535 
00536 
00541 void
00542 domain_update_status(domain_type* domain)
00543 {
00544     domain_type* parent = NULL;
00545 
00546     se_log_assert(domain);
00547     if (domain->domain_status == DOMAIN_STATUS_APEX) {
00548         return;
00549     }
00550 
00551     if (domain_count_rrset(domain) <= 0) {
00552         /* Empty Non-Terminal */
00553         return; /* we don't care */
00554     }
00555 
00556     if (domain_lookup_rrset(domain, LDNS_RR_TYPE_NS)) {
00557         if (domain_lookup_rrset(domain, LDNS_RR_TYPE_DS)) {
00558             domain->domain_status = DOMAIN_STATUS_DS;
00559         } else {
00560             domain->domain_status = DOMAIN_STATUS_NS;
00561         }
00562     } else { /* else, it is just an authoritative domain */
00563         domain->domain_status = DOMAIN_STATUS_AUTH;
00564     }
00565 
00566     parent = domain->parent;
00567     while (parent && parent->domain_status != DOMAIN_STATUS_APEX) {
00568         if (domain_lookup_rrset(parent, LDNS_RR_TYPE_DNAME) ||
00569             domain_lookup_rrset(parent, LDNS_RR_TYPE_NS)) {
00570             domain->domain_status = DOMAIN_STATUS_OCCLUDED;
00571             return;
00572         }
00573         parent = parent->parent;
00574     }
00575     return;
00576 }
00577 
00578 
00583 int
00584 domain_sign(hsm_ctx_t* ctx, domain_type* domain, ldns_rdf* owner,
00585     signconf_type* sc, time_t signtime, uint32_t serial, stats_type* stats)
00586 {
00587     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00588     ldns_rdf* soa_serial = NULL;
00589     rrset_type* rrset = NULL;
00590     int error = 0;
00591 
00592     se_log_assert(domain);
00593     se_log_assert(domain->rrsets);
00594     se_log_assert(owner);
00595     se_log_assert(sc);
00596     se_log_assert(signtime);
00597     se_log_assert(stats);
00598 
00599     if (domain->domain_status == DOMAIN_STATUS_NONE ||
00600         domain->domain_status == DOMAIN_STATUS_OCCLUDED) {
00601         return 0;
00602     }
00603 
00604     if (domain->denial && domain->denial->rrset) {
00605         error = rrset_sign(ctx, domain->denial->rrset, owner, sc, signtime, stats);
00606         if (error) {
00607             return error;
00608         }
00609     }
00610 
00611     if (domain->rrsets->root != LDNS_RBTREE_NULL) {
00612         node = ldns_rbtree_first(domain->rrsets);
00613     }
00614     while (node && node != LDNS_RBTREE_NULL) {
00615         rrset = (rrset_type*) node->data;
00616 
00617         /* skip delegation RRsets */
00618         if (domain->domain_status != DOMAIN_STATUS_APEX &&
00619             rrset->rr_type == LDNS_RR_TYPE_NS) {
00620             node = ldns_rbtree_next(node);
00621             continue;
00622         }
00623         /* skip glue at the delegation */
00624         if ((domain->domain_status == DOMAIN_STATUS_DS ||
00625              domain->domain_status == DOMAIN_STATUS_NS) &&
00626             (rrset->rr_type == LDNS_RR_TYPE_A ||
00627              rrset->rr_type == LDNS_RR_TYPE_AAAA)) {
00628             node = ldns_rbtree_next(node);
00629             continue;
00630         }
00631 
00632         if (rrset->rr_type == LDNS_RR_TYPE_SOA && rrset->rrs &&
00633             rrset->rrs->rr) {
00634             soa_serial = ldns_rr_set_rdf(rrset->rrs->rr,
00635                 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, serial),
00636                 SE_SOA_RDATA_SERIAL);
00637             if (soa_serial) {
00638                 if (ldns_rdf2native_int32(soa_serial) != serial) {
00639                     rrset->drop_signatures = 1;
00640                 }
00641                 ldns_rdf_deep_free(soa_serial);
00642              } else {
00643                 se_log_error("unable to sign domain: failed to replace "
00644                     "SOA SERIAL rdata");
00645                 return 1;
00646             }
00647         }
00648 
00649         error = rrset_sign(ctx, rrset, owner, sc, signtime, stats);
00650         if (error) {
00651             se_log_error("failed to sign RRset[%i]", (int) rrset->rr_type);
00652             return error;
00653         }
00654         node = ldns_rbtree_next(node);
00655     }
00656 
00657     return 0;
00658 }
00659 
00660 
00665 int
00666 domain_add_rr(domain_type* domain, ldns_rr* rr)
00667 {
00668     rrset_type* rrset = NULL;
00669 
00670     se_log_assert(rr);
00671     se_log_assert(domain);
00672     se_log_assert(domain->name);
00673     se_log_assert(domain->rrsets);
00674     se_log_assert((ldns_dname_compare(domain->name, ldns_rr_owner(rr)) == 0));
00675 
00676     rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
00677     if (rrset) {
00678         return rrset_add_rr(rrset, rr);
00679     }
00680     /* no RRset with this RRtype yet */
00681     rrset = rrset_create(ldns_rr_get_type(rr));
00682     rrset = domain_add_rrset(domain, rrset, 0);
00683     if (!rrset) {
00684         se_log_error("unable to add RR to domain: failed to add RRset");
00685         return 1;
00686     }
00687     return rrset_add_rr(rrset, rr);
00688 }
00689 
00690 
00695 int
00696 domain_recover_rr_from_backup(domain_type* domain, ldns_rr* rr)
00697 {
00698     rrset_type* rrset = NULL;
00699 
00700     se_log_assert(rr);
00701     se_log_assert(domain);
00702     se_log_assert(domain->name);
00703     se_log_assert(domain->rrsets);
00704     se_log_assert((ldns_dname_compare(domain->name, ldns_rr_owner(rr)) == 0));
00705 
00706     rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
00707     if (rrset) {
00708         return rrset_recover_rr_from_backup(rrset, rr);
00709     }
00710     /* no RRset with this RRtype yet */
00711     rrset = rrset_create(ldns_rr_get_type(rr));
00712     rrset = domain_add_rrset(domain, rrset, 1);
00713     if (!rrset) {
00714         se_log_error("unable to recover RR to domain: failed to add RRset");
00715         return 1;
00716     }
00717     return rrset_recover_rr_from_backup(rrset, rr);
00718 }
00719 
00720 
00725 int
00726 domain_recover_rrsig_from_backup(domain_type* domain, ldns_rr* rrsig,
00727     ldns_rr_type type_covered, const char* locator, uint32_t flags)
00728 {
00729     rrset_type* rrset = NULL;
00730 
00731     se_log_assert(rrsig);
00732     se_log_assert(domain);
00733     se_log_assert(domain->name);
00734     se_log_assert(domain->rrsets);
00735     se_log_assert((ldns_dname_compare(domain->name,
00736         ldns_rr_owner(rrsig)) == 0));
00737 
00738     if (type_covered == LDNS_RR_TYPE_NSEC ||
00739         type_covered == LDNS_RR_TYPE_NSEC3) {
00740         if (domain->denial && domain->denial->rrset) {
00741             return rrset_recover_rrsig_from_backup(domain->denial->rrset,
00742                 rrsig, locator, flags);
00743         } else if (type_covered == LDNS_RR_TYPE_NSEC) {
00744             se_log_error("unable to recover RRSIG to domain: no NSEC RRset");
00745         } else {
00746             se_log_error("unable to recover RRSIG to domain: no NSEC3 RRset");
00747         }
00748     } else {
00749         rrset = domain_lookup_rrset(domain, type_covered);
00750         if (rrset) {
00751             return rrset_recover_rrsig_from_backup(rrset, rrsig,
00752                 locator, flags);
00753         } else {
00754             se_log_error("unable to recover RRSIG to domain: no such RRset");
00755         }
00756     }
00757     return 1;
00758 }
00759 
00760 
00765 int
00766 domain_del_rr(domain_type* domain, ldns_rr* rr)
00767 {
00768     rrset_type* rrset = NULL;
00769 
00770     se_log_assert(rr);
00771     se_log_assert(domain);
00772     se_log_assert(domain->name);
00773     se_log_assert(domain->rrsets);
00774     se_log_assert((ldns_dname_compare(domain->name, ldns_rr_owner(rr)) == 0));
00775 
00776     rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
00777     if (rrset) {
00778         return rrset_del_rr(rrset, rr);
00779     }
00780     /* no RRset with this RRtype yet */
00781     se_log_warning("unable to delete RR from domain: no such RRset "
00782         "[rrtype %i]", ldns_rr_get_type(rr));
00783     return 0; /* well, it is not present in the zone anymore, is it? */
00784 }
00785 
00786 
00791 int
00792 domain_del_rrs(domain_type* domain)
00793 {
00794     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00795     rrset_type* rrset = NULL;
00796 
00797     se_log_assert(domain);
00798     se_log_assert(domain->rrsets);
00799 
00800     if (domain->rrsets->root != LDNS_RBTREE_NULL) {
00801         node = ldns_rbtree_first(domain->rrsets);
00802     }
00803     while (node && node != LDNS_RBTREE_NULL) {
00804         rrset = (rrset_type*) node->data;
00805         if (rrset_del_rrs(rrset) != 0) {
00806             return 1;
00807         }
00808         node = ldns_rbtree_next(node);
00809     }
00810     return 0;
00811 }
00812 
00813 
00818 static void
00819 domain_cleanup_rrsets(ldns_rbtree_t* rrset_tree)
00820 {
00821     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00822     rrset_type* rrset = NULL;
00823 
00824     if (rrset_tree && rrset_tree->root != LDNS_RBTREE_NULL) {
00825         node = ldns_rbtree_first(rrset_tree);
00826     }
00827     while (node && node != LDNS_RBTREE_NULL) {
00828         rrset = (rrset_type*) node->data;
00829         rrset_cleanup(rrset);
00830         node = ldns_rbtree_next(node);
00831     }
00832     if (rrset_tree && rrset_tree->root != LDNS_RBTREE_NULL) {
00833         se_rbnode_free(rrset_tree->root);
00834     }
00835     if (rrset_tree) {
00836         ldns_rbtree_free(rrset_tree);
00837     }
00838     return;
00839 }
00840 
00841 
00846 void
00847 domain_cleanup(domain_type* domain)
00848 {
00849     if (domain) {
00850         if (domain->name) {
00851             ldns_rdf_deep_free(domain->name);
00852             domain->name = NULL;
00853         }
00854         if (domain->rrsets) {
00855             domain_cleanup_rrsets(domain->rrsets);
00856             domain->rrsets = NULL;
00857         }
00858         /* don't destroy corresponding parent and nsec3 domain */
00859         se_free((void*) domain);
00860     } else {
00861         se_log_warning("cleanup empty domain");
00862     }
00863     return;
00864 }
00865 
00866 
00871 void
00872 domain_print(FILE* fd, domain_type* domain)
00873 {
00874     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00875     domain_type* parent = NULL;
00876     int print_glue = 0;
00877     rrset_type* rrset = NULL;
00878     rrset_type* soa_rrset = NULL;
00879     rrset_type* cname_rrset = NULL;
00880 
00881     if (domain->rrsets && domain->rrsets->root != LDNS_RBTREE_NULL) {
00882         node = ldns_rbtree_first(domain->rrsets);
00883     }
00884 
00885     /* no other data may accompany a CNAME */
00886     cname_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_CNAME);
00887     if (cname_rrset) {
00888         rrset_print(fd, cname_rrset, 0);
00889     } else {
00890         /* if SOA, print soa first */
00891         soa_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
00892         if (soa_rrset) {
00893             rrset_print(fd, soa_rrset, 0);
00894         }
00895 
00896         /* print other RRsets */
00897         while (node && node != LDNS_RBTREE_NULL) {
00898             rrset = (rrset_type*) node->data;
00899             if (rrset->rr_type != LDNS_RR_TYPE_SOA) {
00900                 if (domain->domain_status == DOMAIN_STATUS_NONE ||
00901                     domain->domain_status == DOMAIN_STATUS_OCCLUDED) {
00902 
00903                     parent = domain->parent;
00904                     print_glue = 0;
00905                     while (parent && parent->domain_status != DOMAIN_STATUS_APEX) {
00906                         if (domain_lookup_rrset(parent, LDNS_RR_TYPE_NS)) {
00907                             print_glue = 1;
00908                             break;
00909                         }
00910                         parent = parent->parent;
00911                     }
00912 
00913                     /* only output glue */
00914                     if (print_glue && (rrset->rr_type == LDNS_RR_TYPE_A ||
00915                         rrset->rr_type == LDNS_RR_TYPE_AAAA)) {
00916                         rrset_print(fd, rrset, 0);
00917                     }
00918                 } else {
00919                     rrset_print(fd, rrset, 0);
00920                 }
00921             }
00922 
00923             node = ldns_rbtree_next(node);
00924         }
00925     }
00926 
00927     /* print NSEC(3) */
00928     if (domain->denial && domain->denial->rrset) {
00929         rrset_print(fd, domain->denial->rrset, 0);
00930     }
00931     return;
00932 }
00933 
00934 
00939 void
00940 domain_print_nsec(FILE* fd, domain_type* domain)
00941 {
00942     char* str = NULL;
00943     int nsec_bitmap_changed = 0;
00944     int nsec_nxt_changed = 0;
00945     ldns_rr* rr = NULL;
00946 
00947     if (domain->denial) {
00948         nsec_bitmap_changed = domain->denial->bitmap_changed;
00949         nsec_nxt_changed = domain->denial->nxt_changed;
00950     }
00951 
00952     str = ldns_rdf2str(domain->name);
00953     fprintf(fd, ";DNAME %s %u %u %i %i %i %i %i\n", str,
00954         domain->internal_serial, domain->outbound_serial,
00955         (int) domain->domain_status,
00956         (int) domain->subdomain_count, (int) domain->subdomain_auth,
00957         nsec_bitmap_changed, nsec_nxt_changed);
00958     se_free((void*) str);
00959 
00960     if (domain->denial && domain->denial->rrset &&
00961         domain->denial->rrset->rrs && domain->denial->rrset->rrs->rr) {
00962 
00963         rr = domain->denial->rrset->rrs->rr;
00964         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3) {
00965             str = ldns_rdf2str(domain->denial->owner);
00966             fprintf(fd, ";DNAME3 %s %u %u %i %i %i %i %i\n", str,
00967                 domain->internal_serial, domain->outbound_serial,
00968                 DOMAIN_STATUS_HASH, 0, 0, nsec_bitmap_changed,
00969                 nsec_nxt_changed);
00970             se_free((void*) str);
00971 
00972             fprintf(fd, ";NSEC3\n");
00973 
00974 
00975         } else {
00976             fprintf(fd, ";NSEC\n");
00977         }
00978         ldns_rr_print(fd, rr);
00979     }
00980     return;
00981 }
00982 
00983 
00988 void
00989 domain_print_rrsig(FILE* fd, domain_type* domain)
00990 {
00991     ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00992     rrset_type* rrset = NULL;
00993 
00994     if (domain->rrsets && domain->rrsets->root != LDNS_RBTREE_NULL) {
00995         node = ldns_rbtree_first(domain->rrsets);
00996     }
00997 
00998     while (node && node != LDNS_RBTREE_NULL) {
00999         rrset = (rrset_type*) node->data;
01000         rrset_print_rrsig(fd, rrset);
01001         node = ldns_rbtree_next(node);
01002     }
01003 
01004     /* print nsec */
01005     if (domain->denial && domain->denial->rrset) {
01006         rrset_print_rrsig(fd, domain->denial->rrset);
01007     }
01008     return;
01009 }