diff --git a/src/libknot/dnssec/zone-nsec.c b/src/libknot/dnssec/zone-nsec.c index 577f6f638fa60c2c0b26b92ccd96231a3476e968..e33975c810f26d03e07b22ab7d8c7b1af8f00b22 100644 --- a/src/libknot/dnssec/zone-nsec.c +++ b/src/libknot/dnssec/zone-nsec.c @@ -786,6 +786,88 @@ static int create_nsec3_chain(const knot_zone_contents_t *zone, uint32_t ttl, return result; } +/* - deleting NSEC3 chain -------------------------------------------------- */ + +typedef struct { + knot_changeset_t *changeset; + int result; +} nsec3_chain_delete_data_t; + +static int copy_node_and_delete(const knot_rrset_t *rrset, + knot_changeset_t *changeset) +{ + knot_rrset_t *copy = NULL; + int result = knot_rrset_deep_copy_no_sig(rrset, ©); + if (result != KNOT_EOK) { + return result; + } + + result = knot_changeset_add_rrset(changeset, copy, KNOT_CHANGESET_REMOVE); + if (result != KNOT_EOK) { + knot_rrset_deep_free(©, 1); + } + + return result; +} + +static void delete_nsec3_chain_node_cb(knot_node_t **node_ptr, void *data) +{ + assert(node_ptr && *node_ptr); + assert(data); + + knot_node_t *node = *node_ptr; + nsec3_chain_delete_data_t *params = (nsec3_chain_delete_data_t *)data; + + if (params->result != KNOT_EOK) { + return; + } + + int result = KNOT_EOK; + + for (int i = 0; i < node->rrset_count; i++) { + const knot_rrset_t *rrset = node->rrset_tree[i]; + result = copy_node_and_delete(rrset, params->changeset); + if (result != KNOT_EOK) { + break; + } + + result = copy_node_and_delete(rrset->rrsigs, params->changeset); + if (result != KNOT_EOK) { + break; + } + } + + params->result = result; +} + +static int delete_nsec3_chain(const knot_zone_contents_t *zone, + knot_changeset_t *changeset) +{ + assert(zone); + assert(changeset); + + if (knot_zone_tree_is_empty(zone->nsec3_nodes)) { + return KNOT_EOK; + } + + dbg_dnssec_detail("deleting NSEC3 chain\n"); + + nsec3_chain_delete_data_t cb_data = { + .changeset = changeset, + .result = KNOT_EOK + }; + + knot_zone_tree_apply(zone->nsec3_nodes, delete_nsec3_chain_node_cb, + &cb_data); + + return cb_data.result; +} + +/* - helper functions ------------------------------------------------------ */ + +/*! + * \brief Check if NSEC3 is enabled for given zone. + */ bool is_nsec3_enabled(const knot_zone_contents_t *zone) { if (!zone) { @@ -795,8 +877,6 @@ bool is_nsec3_enabled(const knot_zone_contents_t *zone) return zone->nsec3_params.algorithm != 0; } -/* - helper functions ------------------------------------------------------ */ - /*! * \brief Get minimum TTL from zone SOA. * \note Value should be used for NSEC records. @@ -873,13 +953,18 @@ int knot_zone_create_nsec_chain(const knot_zone_contents_t *zone, } int result; + bool nsec3_enabled = is_nsec3_enabled(zone); - if (is_nsec3_enabled(zone)) { + if (nsec3_enabled) { result = create_nsec3_chain(zone, nsec_ttl, changeset); } else { result = create_nsec_chain(zone, nsec_ttl, changeset); } + if (result == KNOT_EOK && !nsec3_enabled) { + result = delete_nsec3_chain(zone, changeset); + } + if (result != KNOT_EOK) { return result; } diff --git a/src/libknot/zone/zone-tree.c b/src/libknot/zone/zone-tree.c index 0a73c69440dc469f43310f91494f8b884c083a4d..c33731bc39b38a4775525d101443acdeeaaafd1f 100644 --- a/src/libknot/zone/zone-tree.c +++ b/src/libknot/zone/zone-tree.c @@ -56,6 +56,11 @@ size_t knot_zone_tree_weight(knot_zone_tree_t* tree) return hattrie_weight(tree); } +int knot_zone_tree_is_empty(knot_zone_tree_t *tree) +{ + return knot_zone_tree_weight(tree) == 0; +} + /*----------------------------------------------------------------------------*/ int knot_zone_tree_insert(knot_zone_tree_t *tree, knot_node_t *node) diff --git a/src/libknot/zone/zone-tree.h b/src/libknot/zone/zone-tree.h index d9172ce4c6e9c4c8aae705294300daad0eeae4c0..8e15d88b9c663deed20e188a7846a131fdeac288 100644 --- a/src/libknot/zone/zone-tree.h +++ b/src/libknot/zone/zone-tree.h @@ -51,6 +51,15 @@ knot_zone_tree_t* knot_zone_tree_create(); */ size_t knot_zone_tree_weight(knot_zone_tree_t* tree); +/*! + * \brief Checks if the zone tree is empty. + * + * \param tree Zone tree to check. + * + * \return Nonzero if the zone tree is empty. + */ +int knot_zone_tree_is_empty(knot_zone_tree_t *tree); + /*! * \brief Inserts the given node into the zone tree. *