Commit 6148338b authored by Dominik Taborsky's avatar Dominik Taborsky

zone contents: cleanup of changeset-related functions, comments

parent c449adcd
......@@ -178,8 +178,8 @@ static bool need_to_insert(zone_contents_t *counterpart, const knot_rrset_t *rr)
if (node->rrset_count == 0) {
// Remove empty node.
zone_tree_t *t = zone_contents_rrset_is_nsec3rel(rr) ? counterpart->nsec3_nodes :
counterpart->nodes;
zone_tree_t *t = knot_rrset_is_nsec3rel(rr) ?
counterpart->nsec3_nodes : counterpart->nodes;
zone_contents_delete_empty_node(counterpart, t, node);
}
......
......@@ -643,18 +643,61 @@ static int recreate_nsec3_tree(const zone_contents_t *z, zone_contents_t *out)
return KNOT_EOK;
}
bool zone_contents_rrset_is_nsec3rel(const knot_rrset_t *rr)
static zone_node_t *get_previous(const zone_contents_t *zone,
const knot_dname_t *name)
{
if (rr == NULL) {
return false;
if (zone == NULL || name == NULL) {
return NULL;
}
zone_node_t *found = NULL, *prev = NULL;
int exact_match = find_in_tree(zone->nodes, name, &found, &prev);
assert(exact_match >= 0);
//assert(prev != NULL);
return prev;
}
static zone_node_t *zone_contents_get_greatest_child(const zone_contents_t *zone, const knot_dname_t *parent)
{
if (knot_dname_size(parent) + 2 > KNOT_DNAME_MAXLEN) {
// Not enough space for children.
return NULL;
}
knot_dname_t dn[KNOT_DNAME_MAXLEN] = { 0x01, 0xff };
knot_dname_to_wire(dn + 2, parent, KNOT_DNAME_MAXLEN);
zone_node_t *child = get_node(zone, dn);
if (child) {
return child;
}
/* Is NSEC3 or non-empty RRSIG covering NSEC3. */
return ((rr->type == KNOT_RRTYPE_NSEC3) ||
(rr->type == KNOT_RRTYPE_RRSIG
&& knot_rrsig_type_covered(&rr->rrs, 0) == KNOT_RRTYPE_NSEC3));
child = get_previous(zone, dn);
if (!child) {
return NULL;
}
//assert(child);
const int parent_labels = knot_dname_labels(parent, NULL);
const int child_labels = knot_dname_labels(child->owner, NULL);
if (child_labels <= parent_labels) {
return NULL;
}
if (knot_dname_matched_labels(parent, child->owner) != parent_labels) {
return NULL;
}
return child;
}
static bool contents_has_children(const zone_contents_t *zone, const knot_dname_t *owner)
{
return zone_contents_get_greatest_child(zone, owner) != NULL;
}
// Public API
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr,
zone_node_t **n)
{
......@@ -662,15 +705,82 @@ int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr,
return KNOT_EINVAL;
}
return insert_rr(z, rr, n, zone_contents_rrset_is_nsec3rel(rr));
return insert_rr(z, rr, n, knot_rrset_is_nsec3rel(rr));
}
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset)
{
if (zone == NULL || rrset == NULL) {
return NULL;
}
const bool nsec3 = knot_rrset_is_nsec3rel(rrset);
zone_node_t *node = nsec3 ? get_nsec3_node(zone, rrset->owner) :
get_node(zone, rrset->owner);
if (node == NULL) {
node = node_new(rrset->owner, NULL);
int ret = nsec3 ? add_nsec3_node(zone, node) : add_node(zone, node, 1);
if (ret != KNOT_EOK) {
node_free(&node, NULL);
return NULL;
}
return node;
} else {
return node;
}
}
int zone_contents_delete_empty_node(zone_contents_t *contents, zone_tree_t *tree, zone_node_t *node)
{
if (!contents || !tree || !node) {
return KNOT_EINVAL;
}
if (node->rrset_count == 0 && !contents_has_children(contents, node->owner)) {
const knot_dname_t *parent_dname = knot_wire_next_label(node->owner, NULL);
zone_node_t *parent_node = NULL;
if (tree == contents->nsec3_nodes) {
// Only one level in NSEC3 tree
parent_node = (node == contents->apex) ? NULL : contents->apex;
} else {
parent_node = (zone_node_t *) zone_contents_find_node(contents, parent_dname);
}
if (parent_node && parent_node != contents->apex) {
// Recurse using the parent node, do not delete possibly empty parent.
int ret = zone_contents_delete_empty_node(contents, tree, parent_node);
if (ret != KNOT_EOK) {
return ret;
}
}
// Delete node
zone_node_t *removed_node = NULL;
zone_tree_remove(tree, node->owner, &removed_node);
UNUSED(removed_node);
node_free(&node, NULL);
}
return KNOT_EOK;
}
const zone_node_t *zone_contents_find_node(const zone_contents_t *zone,
const knot_dname_t *name)
const zone_node_t *zone_contents_find_node(const zone_contents_t *zone, const knot_dname_t *name)
{
return get_node(zone, name);
}
zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *contents, const knot_rrset_t *rrset)
{
if (contents == NULL || rrset == NULL) {
return NULL;
}
const bool nsec3 = knot_rrset_is_nsec3rel(rrset);
return nsec3 ? get_nsec3_node(contents, rrset->owner) :
get_node(contents, rrset->owner);
}
int zone_contents_find_dname(const zone_contents_t *zone,
const knot_dname_t *name,
const zone_node_t **node,
......@@ -723,22 +833,6 @@ int zone_contents_find_dname(const zone_contents_t *zone,
return exact_match ? ZONE_NAME_FOUND : ZONE_NAME_NOT_FOUND;
}
static zone_node_t *get_previous(const zone_contents_t *zone,
const knot_dname_t *name)
{
if (zone == NULL || name == NULL) {
return NULL;
}
zone_node_t *found = NULL, *prev = NULL;
int exact_match = find_in_tree(zone->nodes, name, &found, &prev);
assert(exact_match >= 0);
//assert(prev != NULL);
return prev;
}
const zone_node_t *zone_contents_find_previous(const zone_contents_t *zone,
const knot_dname_t *name)
{
......@@ -1100,102 +1194,3 @@ bool zone_contents_is_empty(const zone_contents_t *zone)
{
return !zone || !node_rrtype_exists(zone->apex, KNOT_RRTYPE_SOA);
}
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset)
{
if (zone == NULL || rrset == NULL) {
return NULL;
}
const bool nsec3 = zone_contents_rrset_is_nsec3rel(rrset);
zone_node_t *node = nsec3 ? get_nsec3_node(zone, rrset->owner) :
get_node(zone, rrset->owner);
if (node == NULL) {
node = node_new(rrset->owner, NULL);
int ret = nsec3 ? add_nsec3_node(zone, node) : add_node(zone, node, 1);
if (ret != KNOT_EOK) {
node_free(&node, NULL);
return NULL;
}
return node;
} else {
return node;
}
}
zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset)
{
if (zone == NULL || rrset == NULL) {
return NULL;
}
const bool nsec3 = zone_contents_rrset_is_nsec3rel(rrset);
return nsec3 ? get_nsec3_node(zone, rrset->owner) :
get_node(zone, rrset->owner);
}
zone_node_t *zone_contents_greatest_child(const zone_contents_t *zone, const knot_dname_t *parent)
{
if (knot_dname_size(parent) + 2 > KNOT_DNAME_MAXLEN) {
// Not enough space for children.
return NULL;
}
knot_dname_t dn[KNOT_DNAME_MAXLEN] = { 0x01, 0xff };
knot_dname_to_wire(dn + 2, parent, KNOT_DNAME_MAXLEN);
zone_node_t *child = get_node(zone, dn);
if (child) {
return child;
}
child = get_previous(zone, dn);
if (!child) {
return NULL;
}
//assert(child);
const int parent_labels = knot_dname_labels(parent, NULL);
const int child_labels = knot_dname_labels(child->owner, NULL);
if (child_labels <= parent_labels) {
return NULL;
}
if (knot_dname_matched_labels(parent, child->owner) != parent_labels) {
return NULL;
}
return child;
}
static bool contents_has_children(const zone_contents_t *zone, const knot_dname_t *owner)
{
return zone_contents_greatest_child(zone, owner) != NULL;
}
void zone_contents_delete_empty_node(zone_contents_t *zone, zone_tree_t *tree, zone_node_t *node)
{
assert(zone);
assert(tree);
assert(node);
if (node->rrset_count == 0 && !contents_has_children(zone, node->owner)) {
const knot_dname_t *parent_dname = knot_wire_next_label(node->owner, NULL);
zone_node_t *parent_node = NULL;
if (tree == zone->nsec3_nodes) {
// Only one level in NSEC3 tree
parent_node = (node == zone->apex) ? NULL : zone->apex;
} else {
parent_node = zone_contents_find_node(zone, parent_dname);
}
if (parent_node && parent_node != zone->apex) {
// Recurse using the parent node, do not delete possibly empty parent.
zone_contents_delete_empty_node(zone, tree, parent_node);
}
// Delete node
zone_node_t *removed_node = NULL;
zone_tree_remove(tree, node->owner, &removed_node);
UNUSED(removed_node);
node_free(&node, NULL);
}
}
......@@ -48,13 +48,46 @@ typedef struct zone_contents {
*/
typedef int (*zone_contents_apply_cb_t)(zone_node_t *node, void *data);
/*!
* \brief Allocate and create new zone contents.
*
* \param apex_name Name of the root node.
*
* \return New contents or NULL on error.
*/
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name);
/*!
* \brief Add an RR to contents.
*
* \param z Contents to add to.
* \param rr The RR to add.
* \param n Node to which the RR has been added to on success, unchanged otherwise.
*
* \return KNOT_E*
*/
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n);
bool zone_contents_rrset_is_nsec3rel(const knot_rrset_t *rr);
/*!
* \brief Get the node with this RR (the RR's owner).
*
* \param zone Contents to add to.
* \param rrset The RR to add.
*
* \return The searched node if it exists, a new added empty node or NULL on error.
*/
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n);
/*!
* \brief Delete a node that has no RRSets and no children.
*
* \param contents Contents to delete from.
* \param tree The tree to remove from.
* \param node The node to remove.
*
* \return KNOT_E*.
*/
int zone_contents_delete_empty_node(zone_contents_t *contents, zone_tree_t *tree, zone_node_t *node);
/*!
* \brief Tries to find a node with the specified name in the zone.
......@@ -67,8 +100,9 @@ int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t
*
* \return Corresponding node if found, NULL otherwise.
*/
const zone_node_t *zone_contents_find_node(const zone_contents_t *contents,
const knot_dname_t *name);
const zone_node_t *zone_contents_find_node(const zone_contents_t *contents, const knot_dname_t *name);
zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *contents, const knot_rrset_t *rrset);
/*!
* \brief Tries to find a node by owner in the zone contents.
......@@ -249,8 +283,18 @@ int zone_contents_nsec3_apply_inorder(zone_contents_t *zone,
*/
int zone_contents_shallow_copy(const zone_contents_t *from, zone_contents_t **to);
/*!
* \brief Deallocate directly owned data of zone contents.
*
* \param contents Zone contents to free.
*/
void zone_contents_free(zone_contents_t **contents);
/*!
* \brief Deallocate node RRSets inside the trees, then call zone_contents_free.
*
* \param contents Zone contents to free.
*/
void zone_contents_deep_free(zone_contents_t **contents);
/*!
......@@ -272,9 +316,4 @@ bool zone_contents_is_signed(const zone_contents_t *zone);
*/
bool zone_contents_is_empty(const zone_contents_t *zone);
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
void zone_contents_delete_empty_node(zone_contents_t *zone, zone_tree_t *tree, zone_node_t *node);
/*! @} */
......@@ -26,6 +26,7 @@
#include "libknot/internal/mempattern.h"
#include "libknot/rrset.h"
#include "libknot/rrtype/naptr.h"
#include "libknot/rrtype/rrsig.h"
_public_
knot_rrset_t *knot_rrset_new(const knot_dname_t *owner, uint16_t type,
......@@ -168,6 +169,19 @@ uint32_t knot_rrset_ttl(const knot_rrset_t *rrset)
return knot_rdata_ttl(knot_rdataset_at(&(rrset->rrs), 0));
}
_public_
bool knot_rrset_is_nsec3rel(const knot_rrset_t *rr)
{
if (rr == NULL) {
return false;
}
/* Is NSEC3 or non-empty RRSIG covering NSEC3. */
return ((rr->type == KNOT_RRTYPE_NSEC3) ||
(rr->type == KNOT_RRTYPE_RRSIG
&& knot_rrsig_type_covered(&rr->rrs, 0) == KNOT_RRTYPE_NSEC3));
}
_public_
int knot_rrset_rr_to_canonical(knot_rrset_t *rrset)
{
......
......@@ -175,6 +175,12 @@ bool knot_rrset_empty(const knot_rrset_t *rrset);
*/
uint32_t knot_rrset_ttl(const knot_rrset_t *rrset);
/*!
* \brief Return whether the RR type is NSEC3 related (NSEC3 or RRSIG).
*/
bool knot_rrset_is_nsec3rel(const knot_rrset_t *rr);
/*!
* \brief Convert one RR into canonical format.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment