diff options
Diffstat (limited to 'src/libknot/zone/zone-contents.c')
-rw-r--r-- | src/libknot/zone/zone-contents.c | 1976 |
1 files changed, 493 insertions, 1483 deletions
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c index 90aee0d..ff1a1d4 100644 --- a/src/libknot/zone/zone-contents.c +++ b/src/libknot/zone/zone-contents.c @@ -14,13 +14,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <config.h> #include <assert.h> #include "zone/zone-contents.h" #include "util/debug.h" +#include "libknot/rrset.h" #include "common/base32hex.h" -/*! \todo XXX TODO FIXME remove once testing is done. */ -#include "zcompile/zcompile.h" +#include "common/descriptor.h" +#include "common/hattrie/hat-trie.h" +#include "libknot/zone/zone-tree.h" #include "consts.h" /*----------------------------------------------------------------------------*/ @@ -36,6 +39,7 @@ typedef struct { knot_node_t *first_node; knot_zone_contents_t *zone; knot_node_t *previous_node; + hattrie_t *lookup_tree; int err; } knot_zone_adjust_arg_t; @@ -50,7 +54,7 @@ const uint8_t KNOT_ZONE_FLAGS_ANY = 4; /* 00000100 */ /*----------------------------------------------------------------------------*/ -static void knot_zone_tree_apply(knot_zone_tree_node_t *node, +static void tree_apply_cb(knot_node_t **node, void *data) { if (node == NULL || data == NULL) { @@ -58,7 +62,7 @@ static void knot_zone_tree_apply(knot_zone_tree_node_t *node, } knot_zone_tree_func_t *f = (knot_zone_tree_func_t *)data; - f->func(node->node, f->data); + f->func(*node, f->data); } /*----------------------------------------------------------------------------*/ @@ -87,13 +91,13 @@ static int knot_zone_contents_check_node( assert(contents->apex != NULL); if (!knot_dname_is_subdomain(node->owner, - knot_node_owner(contents->apex))) { + knot_node_owner(contents->apex))) { dbg_zone_exec( char *node_owner = knot_dname_to_str(knot_node_owner(node)); char *apex_owner = knot_dname_to_str(contents->apex->owner); dbg_zone("zone: Trying to insert foreign node to a " - "zone. Node owner: %s, zone apex: %s\n", - node_owner, apex_owner); + "zone. Node owner: %s, zone apex: %s\n", + node_owner, apex_owner); free(node_owner); free(apex_owner); ); @@ -112,166 +116,14 @@ dbg_zone_exec( * \param data Unused parameter. */ static void knot_zone_contents_destroy_node_rrsets_from_tree( - knot_zone_tree_node_t *tnode, void *data) + knot_node_t **tnode, void *data) { assert(tnode != NULL); - assert(tnode->node != NULL); + if (*tnode == NULL) return; /* non-existent node */ int free_rdata_dnames = (int)((intptr_t)data); - knot_node_free_rrsets(tnode->node, free_rdata_dnames); -} - -/*----------------------------------------------------------------------------*/ -/*! - * \brief Destroys node owner. - * - * This function is designed to be used in the tree-iterating functions. - * - * \param node Node to destroy the owner of. - * \param data Unused parameter. - */ -static void knot_zone_contents_destroy_node_owner_from_tree( - knot_zone_tree_node_t *tnode, void *data) -{ - assert(tnode != NULL); - assert(tnode->node != NULL); - - UNUSED(data); - /*!< \todo change completely! */ - knot_node_free(&tnode->node); -} - -/*----------------------------------------------------------------------------*/ - -static int knot_zone_contents_dnames_from_rdata_to_table( - knot_dname_table_t *table, knot_rdata_t *rdata, - knot_rrtype_descriptor_t *d) -{ - unsigned int count = knot_rdata_item_count(rdata); - int rc = 0; - if (d->fixed_items) { - assert(count <= d->length); - } - // for each RDATA item - for (unsigned int j = 0; j < count; ++j) { - if (d->wireformat[j] - == KNOT_RDATA_WF_COMPRESSED_DNAME - || d->wireformat[j] - == KNOT_RDATA_WF_UNCOMPRESSED_DNAME - || d->wireformat[j] - == KNOT_RDATA_WF_LITERAL_DNAME) { - rc = knot_dname_table_add_dname_check(table, - &knot_rdata_get_item(rdata, j)->dname); - if (rc < 0) { - dbg_zone("Error: %s\n", knot_strerror(rc)); - return rc; - } - } - } - - dbg_zone_detail("RDATA OK.\n"); - return KNOT_EOK; -} - -/*----------------------------------------------------------------------------*/ - -static int knot_zone_contents_dnames_from_rrset_to_table( - knot_dname_table_t *table, knot_rrset_t *rrset, int replace_owner, - knot_dname_t *owner) -{ - assert(table != NULL && rrset != NULL && owner != NULL); - -dbg_zone_exec_detail( - char *name = knot_dname_to_str(knot_rrset_owner(rrset)); - dbg_zone_detail("Putting dnames from RRSet to table: owner: (%p) %s," - " type: %s\n", knot_rrset_owner(rrset), - name, knot_rrtype_to_string( - knot_rrset_type(rrset))); - free(name); -); - - if (replace_owner) { - // discard the old owner and replace it with the new - knot_rrset_set_owner(rrset, owner); - } - dbg_zone_detail("RRSet owner: %p\n", rrset->owner); - - knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type( - knot_rrset_type(rrset)); - if (desc == NULL) { - // not recognized RR type, ignore - dbg_zone("RRSet type not recognized.\n"); - return KNOT_EOK; - } - // for each RDATA in RRSet - knot_rdata_t *rdata = knot_rrset_get_rdata(rrset); - while (rdata != NULL) { - int rc = knot_zone_contents_dnames_from_rdata_to_table(table, - rdata, desc); - if (rc != KNOT_EOK) { - return rc; - } - - rdata = knot_rrset_rdata_get_next(rrset, rdata); - } - - dbg_zone("RRSet OK.\n"); - return KNOT_EOK; -} - -/*----------------------------------------------------------------------------*/ - -static int knot_zone_contents_dnames_from_node_to_table( - knot_dname_table_t *table, knot_node_t *node) -{ - /* - * Assuming that all the RRSets have the same owner as the node. - */ - - // insert owner - char *name = knot_dname_to_str(node->owner); - dbg_zone_detail("Node owner before inserting to dname table: %p.\n", - node->owner); - dbg_zone_detail("Node owner before inserting to dname table: %s.\n", - name); - free(name); - //knot_dname_t *old_owner = node->owner; - int rc = knot_dname_table_add_dname_check(table, &node->owner); - if (rc < 0) { - dbg_zone("Failed to add dname to dname table.\n"); - return rc; - } - int replace_owner = (rc > 0); - -dbg_zone_exec_detail( - name = knot_dname_to_str(node->owner); - dbg_zone_detail("Node owner after inserting to dname table: %p (%s).\n", - node->owner, name); - free(name); -); - - knot_rrset_t **rrsets = knot_node_get_rrsets(node); - // for each RRSet - for (int i = 0; i < knot_node_rrset_count(node); ++i) { - dbg_zone_detail("Inserting RRSets from node to table.\n"); - rc = knot_zone_contents_dnames_from_rrset_to_table(table, - rrsets[i], replace_owner, node->owner); - - if (rc == KNOT_EOK && knot_rrset_rrsigs(rrsets[i]) != NULL) { - rc = knot_zone_contents_dnames_from_rrset_to_table( - table, knot_rrset_get_rrsigs(rrsets[i]), - replace_owner, node->owner); - } - - if (rc != KNOT_EOK) { - return rc; - } - } - - free(rrsets); - - dbg_zone("Node OK\n"); - return KNOT_EOK; + knot_node_free_rrsets(*tnode, free_rdata_dnames); + knot_node_free(tnode); } /*----------------------------------------------------------------------------*/ @@ -286,7 +138,7 @@ static const knot_node_t *knot_zone_contents_find_wildcard_child( CHECK_ALLOC(tmp, NULL); knot_dname_t *wildcard = knot_dname_cat(tmp, knot_node_owner( - closest_encloser)); + closest_encloser)); if (wildcard == NULL) { free(tmp); return NULL; @@ -298,14 +150,14 @@ dbg_zone_exec_detail( char *name = knot_dname_to_str(knot_node_owner(closest_encloser)); char *name2 = knot_dname_to_str(wildcard); dbg_zone_detail("Searching for wildcard child of %s (%s)\n", name, - name2); + name2); free(name); free(name2); ); const knot_node_t *found = NULL, *ce = NULL, *prev = NULL; int ret = knot_zone_contents_find_dname(zone, wildcard, &found, &ce, - &prev); + &prev); knot_dname_free(&wildcard); @@ -316,6 +168,29 @@ dbg_zone_exec_detail( } } +void knot_zone_contents_insert_dname_into_table(knot_dname_t **in_dname, + hattrie_t *lookup_tree) +{ + if (lookup_tree == NULL) { + /* = Do not check duplicates. */ + return; + } + assert(in_dname && *in_dname); + /* First thing - make sure dname is not duplicated. */ + knot_dname_t *found_dname = hattrie_get_dname(lookup_tree, *in_dname); + if (found_dname != NULL && found_dname != *in_dname) { + /* Duplicate. */ + knot_dname_release(*in_dname); + knot_dname_retain(found_dname); + *in_dname = found_dname; + } else if (found_dname == NULL) { + /* Into the tree it goes. */ + hattrie_insert_dname(lookup_tree, *in_dname); + } else { + assert(found_dname == *in_dname); + } +} + /*----------------------------------------------------------------------------*/ /*! * \brief Adjusts one RDATA item by replacing domain name by one present in the @@ -333,49 +208,48 @@ dbg_zone_exec_detail( * \param zone Zone to which the RDATA belongs. * \param pos Position of the RDATA item in the RDATA. */ -static void knot_zone_contents_adjust_rdata_item(knot_rdata_t *rdata, - knot_zone_contents_t *zone, - knot_node_t *node, int pos) -{ - const knot_rdata_item_t *dname_item = knot_rdata_item(rdata, pos); - - assert(dname_item); - - if (dname_item != NULL) { - knot_dname_t *dname = dname_item->dname; - - /* - * The case when dname.node is already set is handled here. - * No use to check it later. - */ - if (knot_dname_node(dname) != NULL - || !knot_dname_is_subdomain(dname, knot_node_owner( - knot_zone_contents_apex(zone)))) { - // The name's node is either already set - // or the name does not belong to the zone - dbg_zone_detail("Name's (%p) node either set or the name" - "does not belong to the zone (%p).\n", - dname, knot_dname_node(dname)); - return; - } +static void knot_zone_contents_adjust_rdata_dname(knot_zone_contents_t *zone, + hattrie_t *lookup_tree, + knot_node_t *node, + knot_dname_t **in_dname) +{ +// const knot_node_t *old_dname_node = (*in_dname)->node; + knot_zone_contents_insert_dname_into_table(in_dname, lookup_tree); +// assert((*in_dname)->node == old_dname_node || old_dname_node == NULL); - const knot_node_t *n = NULL; - const knot_node_t *closest_encloser = NULL; - const knot_node_t *prev = NULL; + knot_dname_t *dname = *in_dname; + /* + * The case when dname.node is already set is handled here. + * No use to check it later. + */ + if (knot_dname_node(dname) != NULL + || !knot_dname_is_subdomain(dname, knot_node_owner( + knot_zone_contents_apex(zone)))) { + // The name's node is either already set + // or the name does not belong to the zone + dbg_zone_detail("Name's node either set or the name " + "does not belong to the zone (%p).\n", + knot_dname_node(dname)); + return; + } - int ret = knot_zone_contents_find_dname(zone, dname, &n, - &closest_encloser, &prev); + const knot_node_t *n = NULL; + const knot_node_t *closest_encloser = NULL; + const knot_node_t *prev = NULL; - if (ret == KNOT_EINVAL || ret == KNOT_EBADZONE) { - // TODO: do some cleanup if needed - dbg_zone_detail("Failed to find the name in zone: %s\n", - knot_strerror(ret)); - return; - } + int ret = knot_zone_contents_find_dname(zone, dname, &n, + &closest_encloser, &prev); - assert(ret != KNOT_ZONE_NAME_FOUND || n == closest_encloser); + if (ret == KNOT_EINVAL || ret == KNOT_EBADZONE) { + // TODO: do some cleanup if needed + dbg_zone_detail("Failed to find the name in zone: %s\n", + knot_strerror(ret)); + return; + } - if (ret != KNOT_ZONE_NAME_FOUND && (closest_encloser != NULL)) { + assert(ret != KNOT_ZONE_NAME_FOUND || n == closest_encloser); + + if (ret != KNOT_ZONE_NAME_FOUND && (closest_encloser != NULL)) { /*! * \note There is no need to set closer encloser to the * name. We may find the possible wildcard child @@ -388,57 +262,22 @@ static void knot_zone_contents_adjust_rdata_item(knot_rdata_t *rdata, dbg_zone_verb("Trying to find wildcard child.\n"); n = knot_zone_contents_find_wildcard_child(zone, - closest_encloser); + closest_encloser); if (n != NULL) { knot_dname_set_node(dname, (knot_node_t *)n); dbg_zone_exec_detail( char *name = knot_dname_to_str( - knot_node_owner(n)); + knot_node_owner(n)); char *name2 = knot_dname_to_str(dname); dbg_zone_detail("Set wildcard node %s " - "to RDATA dname %s.\n", - name, name2); + "to RDATA dname %s.\n", + name, name2); free(name); free(name2); ); } - } - } -} - -/*----------------------------------------------------------------------------*/ - -static int knot_zone_contents_adjust_rdata(knot_rdata_t *rdata, - knot_rrtype_descriptor_t *desc, - knot_zone_contents_t *zone, - knot_node_t *node) -{ - for (int i = 0; i < rdata->count; ++i) { - if (desc->wireformat[i] - == KNOT_RDATA_WF_COMPRESSED_DNAME - || desc->wireformat[i] - == KNOT_RDATA_WF_UNCOMPRESSED_DNAME - || desc->wireformat[i] - == KNOT_RDATA_WF_LITERAL_DNAME) { - dbg_zone_detail("Adjusting domain name at position %d" - " of the RDATA\n", i); - knot_zone_contents_adjust_rdata_item(rdata, zone, node, - i); - } - } - - /* - * DS digest length check (#2050). - */ - int ret; - if (desc->type == KNOT_RRTYPE_DS - && (ret = knot_rdata_ds_check(rdata)) != KNOT_EOK) { - dbg_zone("DS RDATA check failed: %s\n", knot_strerror(ret)); - return KNOT_EMALF; } - - return KNOT_EOK; } /*----------------------------------------------------------------------------*/ @@ -453,51 +292,18 @@ static int knot_zone_contents_adjust_rdata(knot_rdata_t *rdata, * \param rrset RRSet to adjust RDATA in. * \param zone Zone to which the RRSet belongs. */ -static int knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset, - knot_zone_contents_t *zone, - knot_node_t *node) +static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset, + hattrie_t *lookup_tree, + knot_zone_contents_t *zone, + knot_node_t *node) { - uint16_t type = knot_rrset_type(rrset); - - knot_rrtype_descriptor_t *desc = - knot_rrtype_descriptor_by_type(type); - assert(desc); - - knot_rdata_t *rdata_first = knot_rrset_get_rdata(rrset); - knot_rdata_t *rdata = rdata_first; - - if (rdata == NULL) { - return KNOT_EOK; - } - - int i = 1; - int ret; - while (rdata->next != rdata_first) { -dbg_zone_exec_detail( - char *name = knot_dname_to_str(knot_rrset_owner(rrset)); - dbg_zone_detail("Adjusting domain name at %d. RDATA of RRSet " - "with owner %s and type %s.\n", i, name, - knot_rrtype_to_string(type)); - free(name); -); - ret = knot_zone_contents_adjust_rdata(rdata, desc, - zone, node); - if (ret != KNOT_EOK) { - return ret; - } - - rdata = rdata->next; - ++i; + knot_dname_t **dn = NULL; + while((dn = knot_rrset_get_next_dname(rrset, dn))) { + knot_zone_contents_adjust_rdata_dname(zone, + lookup_tree, + node, + dn); } - -dbg_zone_exec_detail( - char *name = knot_dname_to_str(knot_rrset_owner(rrset)); - dbg_zone_detail("Adjusting domain name at %d. RDATA of RRSet " - "with owner %s and type %s.\n", i, name, - knot_rrtype_to_string(type)); - free(name); -); - return knot_zone_contents_adjust_rdata(rdata, desc, zone, node); } /*----------------------------------------------------------------------------*/ @@ -512,36 +318,46 @@ dbg_zone_exec_detail( * \param zone Zone to which the node belongs. */ static int knot_zone_contents_adjust_rrsets(knot_node_t *node, - knot_zone_contents_t *zone) + hattrie_t *lookup_tree, + knot_zone_contents_t *zone) { - knot_rrset_t **rrsets = knot_node_get_rrsets(node); + knot_rrset_t **rrsets = knot_node_get_rrsets_no_copy(node); short count = knot_node_rrset_count(node); assert(count == 0 || rrsets != NULL); - int ret = KNOT_EOK; for (int r = 0; r < count; ++r) { assert(rrsets[r] != NULL); - dbg_zone("Adjusting next RRSet.\n"); - ret = knot_zone_contents_adjust_rdata_in_rrset(rrsets[r], zone, - node); + /* Make sure that RRSet owner is the same as node's. */ + if (node->owner != rrsets[r]->owner) { + knot_rrset_set_owner(rrsets[r], node->owner); + } + + dbg_zone("Adjusting next RRSet.\n"); + knot_rrset_dump(rrsets[r]); + knot_zone_contents_adjust_rdata_in_rrset(rrsets[r], + lookup_tree, zone, + node); knot_rrset_t *rrsigs = rrsets[r]->rrsigs; - if (ret == KNOT_EOK && rrsigs != NULL) { + if (rrsigs != NULL) { dbg_zone("Adjusting next RRSIGs.\n"); - ret = knot_zone_contents_adjust_rdata_in_rrset(rrsigs, - zone, - node); + knot_rrset_dump(rrsigs); + knot_zone_contents_adjust_rdata_in_rrset(rrsigs, + lookup_tree, zone, + node); } - if (ret != KNOT_EOK) { - break; + if (rrsets[r]->type == KNOT_RRTYPE_DS) { + int ret = knot_rrset_ds_check(rrsets[r]); + if (ret != KNOT_EOK) { + dbg_zone("DS RDATA check failed: %s\n", knot_strerror(ret)); + return KNOT_EMALF; + } } } - free(rrsets); - - return ret; + return KNOT_EOK; } /*----------------------------------------------------------------------------*/ /*! @@ -561,15 +377,20 @@ static int knot_zone_contents_adjust_rrsets(knot_node_t *node, * old changeset processing). */ static int knot_zone_contents_adjust_node(knot_node_t *node, + hattrie_t *lookup_tree, knot_zone_contents_t *zone) { // adjust domain names in RDATA - /*! \note Enabled again after a LONG time. Should test thoroughly. */ - int ret = knot_zone_contents_adjust_rrsets(node, zone); + int ret = knot_zone_contents_adjust_rrsets(node, lookup_tree, + zone); if (ret != KNOT_EOK) { return ret; } +// const knot_node_t *old_dname_node = node->owner->node; + knot_zone_contents_insert_dname_into_table(&node->owner, lookup_tree); +// assert(node->owner->node == old_dname_node || old_dname_node == NULL); + // assure that owner has proper node if (knot_dname_node(knot_node_owner(node)) == NULL) { knot_dname_set_node(knot_node_get_owner(node), node); @@ -582,25 +403,30 @@ static int knot_zone_contents_adjust_node(knot_node_t *node, } // NSEC3 node (only if NSEC3 tree is not empty) - const knot_node_t *prev; - const knot_node_t *nsec3; - int match = knot_zone_contents_find_nsec3_for_name(zone, - knot_node_owner(node), - &nsec3, &prev); - UNUSED(prev); - - if (match != KNOT_ZONE_NAME_FOUND) { - nsec3 = NULL; + /*! \todo We need only exact matches, what if node has no nsec3 node? */ + /* This is faster, as it doesn't need ordered access. */ + knot_node_t *nsec3 = NULL; + knot_dname_t *nsec3_name = NULL; + ret = knot_zone_contents_nsec3_name(zone, knot_node_owner(node), + &nsec3_name); + if (ret == KNOT_EOK) { + assert(nsec3_name); + knot_zone_tree_get(zone->nsec3_nodes, nsec3_name, &nsec3); + knot_node_set_nsec3_node(node, nsec3); + } else if (ret == KNOT_ENSEC3PAR) { + knot_node_set_nsec3_node(node, NULL); + } else { + /* Something could be in DNAME. */ + knot_dname_free(&nsec3_name); + return ret; } - - knot_node_set_nsec3_node(node, (knot_node_t *)nsec3); + knot_dname_free(&nsec3_name); dbg_zone_detail("Set flags to the node: \n"); dbg_zone_detail("Delegation point: %s\n", - knot_node_is_deleg_point(node) ? "yes" : "no"); + knot_node_is_deleg_point(node) ? "yes" : "no"); dbg_zone_detail("Non-authoritative: %s\n", - knot_node_is_non_auth(node) ? "yes" : "no"); - + knot_node_is_non_auth(node) ? "yes" : "no"); return KNOT_EOK; } @@ -615,18 +441,17 @@ static int knot_zone_contents_adjust_node(knot_node_t *node, * \param data Zone the node belongs to. */ static void knot_zone_contents_adjust_node_in_tree( - knot_zone_tree_node_t *tnode, void *data) + knot_node_t **tnode, void *data) { assert(data != NULL); assert(tnode != NULL); - assert(tnode->node != NULL); knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data; - knot_node_t *node = tnode->node; + knot_node_t *node = *tnode; if (args->err != KNOT_EOK) { dbg_xfrin_detail("Error during adjusting: %s, skipping node.\n", - knot_strerror(args->err)); + knot_strerror(args->err)); return; } @@ -639,43 +464,22 @@ dbg_zone_exec_verb( knot_zone_contents_t *zone = args->zone; /* - * 1) Store domain names to dname table. - * TODO: make optional! - */ - assert(zone->dname_table != NULL); - - int ret = knot_zone_contents_dnames_from_node_to_table( - zone->dname_table, node); - if (ret != KNOT_EOK) { - dbg_xfrin("Failed to add dnames from adjusted node to " - "table: %s\n", knot_strerror(ret)); - args->err = ret; - return; - } - - /* - * 2) Do other adjusting (flags, closest enclosers, wildcard children, + * Do other adjusting (flags, closest enclosers, wildcard children, * etc.). */ - ret = knot_zone_contents_adjust_node(node, zone); - if (ret != KNOT_EOK) { - dbg_xfrin("Failed to adjust node: %s\n", knot_strerror(ret)); - args->err = ret; - return; - } + args->err = knot_zone_contents_adjust_node(node, args->lookup_tree, zone); } /*----------------------------------------------------------------------------*/ static void knot_zone_contents_adjust_node_in_tree_ptr( - knot_zone_tree_node_t *tnode, void *data) + knot_node_t **tnode, void *data) { assert(data != NULL); assert(tnode != NULL); - assert(tnode->node != NULL); knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data; - knot_node_t *node = tnode->node; + knot_node_t *node = *tnode; dbg_zone_exec_detail( if (knot_node_parent(node)) { @@ -736,18 +540,17 @@ static void knot_zone_contents_adjust_node_in_tree_ptr( * \param data Zone the node belongs to. */ static void knot_zone_contents_adjust_nsec3_node_in_tree( - knot_zone_tree_node_t *tnode, void *data) + knot_node_t **tnode, void *data) { assert(data != NULL); assert(tnode != NULL); - assert(tnode->node != NULL); + knot_node_t *node = *tnode; knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data; - knot_node_t *node = tnode->node; if (args->err != KNOT_EOK) { dbg_xfrin_detail("Error during adjusting: %s, skipping node.\n", - knot_strerror(args->err)); + knot_strerror(args->err)); return; } @@ -757,32 +560,24 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree( } /* - * Store domain names to dname table. + * We assume, that NSEC3 nodes have none DNAMEs in their RDATA and + * that node owners are all unique. \todo Harmful? */ + knot_zone_contents_t *zone = args->zone; assert(zone != NULL); - - int ret = knot_zone_contents_dnames_from_node_to_table( - zone->dname_table, node); - if (ret != KNOT_EOK) { - dbg_xfrin("Failed to add dnames from adjusted node to " - "table: %s\n", knot_strerror(ret)); - args->err = ret; - return; - } } /*----------------------------------------------------------------------------*/ static void knot_zone_contents_adjust_nsec3_node_in_tree_ptr( - knot_zone_tree_node_t *tnode, void *data) + knot_node_t **tnode, void *data) { assert(data != NULL); assert(tnode != NULL); - assert(tnode->node != NULL); knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data; - knot_node_t *node = tnode->node; + knot_node_t *node = *tnode; // set previous node knot_node_set_previous(node, args->previous_node); @@ -796,23 +591,8 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree_ptr( } /*----------------------------------------------------------------------------*/ -/*! - * \brief Creates a NSEC3 hashed name for the given domain name. - * - * \note The zone's NSEC3PARAM record must be parsed prior to calling this - * function (see knot_zone_load_nsec3param()). - * - * \param zone Zone from which to take the NSEC3 parameters. - * \param name Domain name to hash. - * \param nsec3_name Hashed name. - * - * \retval KNOT_EOK - * \retval KNOT_ENSEC3PAR - * \retval KNOT_ECRYPTO - * \retval KNOT_ERROR if an error occured while creating a new domain name - * from the hash or concatenating it with the zone name. - */ -static int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone, + +int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone, const knot_dname_t *name, knot_dname_t **nsec3_name) { @@ -842,8 +622,8 @@ dbg_zone_exec_verb( ); int res = knot_nsec3_sha1(nsec3_params, knot_dname_name(name), - knot_dname_size(name), &hashed_name, - &hash_size); + knot_dname_size(name), &hashed_name, + &hash_size); if (res != 0) { char *n = knot_dname_to_str(name); @@ -856,29 +636,31 @@ dbg_zone_exec_verb( dbg_zone_hex((char *)hashed_name, hash_size); dbg_zone("\n"); - char *name_b32 = NULL; - int32_t b32_ret = base32hex_encode_alloc(hashed_name, hash_size, - (uint8_t **)(&name_b32)); + uint8_t *name_b32 = NULL; + size_t size = base32hex_encode_alloc(hashed_name, hash_size, + &name_b32); - if (b32_ret <= 0) { + if (size == 0) { char *n = knot_dname_to_str(name); dbg_zone("Error while encoding hashed name %s to base32.\n", n); free(n); - if (name_b32 != NULL) { - free(name_b32); - } + free(name_b32); return KNOT_ECRYPTO; } - size_t size = b32_ret; - assert(name_b32 != NULL); free(hashed_name); - dbg_zone_verb("Base32-encoded hash: %s\n", name_b32); +dbg_zone_exec_verb( + /* name_b32 is not 0-terminated. */ + char b32_string[hash_size + 1]; + memset(b32_string, 0, hash_size + 1); + memcpy(b32_string, name_b32, hash_size); + dbg_zone_verb("Base32-encoded hash: %s\n", b32_string); +); /* Will be returned to caller, make sure it is released after use. */ - *nsec3_name = knot_dname_new_from_str(name_b32, size, NULL); + *nsec3_name = knot_dname_new_from_str((char *)name_b32, size, NULL); free(name_b32); @@ -886,13 +668,14 @@ dbg_zone_exec_verb( dbg_zone("Error while creating domain name for hashed name.\n"); return KNOT_ERROR; } + knot_dname_to_lower(*nsec3_name); assert(zone->apex->owner != NULL); knot_dname_t *ret = knot_dname_cat(*nsec3_name, zone->apex->owner); if (ret == NULL) { dbg_zone("Error while creating NSEC3 domain name for " - "hashed name.\n"); + "hashed name.\n"); knot_dname_release(*nsec3_name); return KNOT_ERROR; } @@ -932,7 +715,7 @@ static int knot_zone_contents_find_in_tree(knot_zone_tree_t *tree, knot_node_t *found = NULL, *prev = NULL; int exact_match = knot_zone_tree_get_less_or_equal(tree, name, &found, - &prev); + &prev); assert(exact_match >= 0); *node = found; @@ -943,201 +726,29 @@ static int knot_zone_contents_find_in_tree(knot_zone_tree_t *tree, /*----------------------------------------------------------------------------*/ -static void knot_zone_contents_node_to_hash(knot_zone_tree_node_t *tnode, - void *data) -{ - assert(tnode != NULL && tnode->node != NULL - && tnode->node->owner != NULL && data != NULL); - - knot_node_t *node = tnode->node; - - knot_zone_contents_t *zone = (knot_zone_contents_t *)data; - /* - * By the original approach, only authoritative nodes and delegation - * points should be added to the hash table, but currently, all nodes - * are being added when the zone is created (don't know why actually:), - * so we will do no distinction here neither. - */ - -#ifdef USE_HASH_TABLE - // add the node also to the hash table if authoritative, or deleg. point - if (zone->table != NULL - && ck_insert_item(zone->table, - (const char *)node->owner->name, - node->owner->size, (void *)node) != 0) { - dbg_zone("Error inserting node into hash table!\n"); - } -#endif -} - -/*----------------------------------------------------------------------------*/ -/* CNAME chain checking */ -/*----------------------------------------------------------------------------*/ - -typedef struct cname_chain { - const knot_node_t *node; - struct cname_chain *next; -} cname_chain_t; - -/*----------------------------------------------------------------------------*/ - -static int cname_chain_add(cname_chain_t **last, const knot_node_t *node) -{ - assert(last != NULL); - - cname_chain_t *new_cname = - (cname_chain_t *)malloc(sizeof(cname_chain_t)); - CHECK_ALLOC_LOG(new_cname, KNOT_ENOMEM); - - new_cname->node = node; - new_cname->next = NULL; - - if (*last != NULL) { - (*last)->next = new_cname; - } else { - *last = new_cname; - } - - return KNOT_EOK; -} - -/*----------------------------------------------------------------------------*/ - -static int cname_chain_contains(cname_chain_t *chain, const knot_node_t *node) -{ - cname_chain_t *act = chain; - while (act != NULL) { - if (act->node == node) { - return 1; - } - act = act->next; - } - - return 0; -} - -/*----------------------------------------------------------------------------*/ - -static void cname_chain_free(cname_chain_t *chain) -{ - cname_chain_t *act = chain; - - while (act != NULL) { - chain = chain->next; - free(act); - act = chain; - } -} - -/*----------------------------------------------------------------------------*/ - -typedef struct loop_check_data { - knot_zone_contents_t *zone; - int err; -} loop_check_data_t; - -/*----------------------------------------------------------------------------*/ - -static void knot_zone_contents_check_loops_in_tree(knot_zone_tree_node_t *tnode, - void *data) +static int knot_zc_nsec3_parameters_match(const knot_rrset_t *rrset, + const knot_nsec3_params_t *params, + size_t rdata_pos) { - assert(tnode != NULL); - assert(tnode->node != NULL); - assert(data != NULL); - - loop_check_data_t *args = (loop_check_data_t *)data; - const knot_node_t *node = tnode->node; - - assert(args->zone != NULL); - - if (args->err != KNOT_EOK) { - dbg_xfrin_detail("Error during CNAME loop checking, skipping " - "node.\n"); - return; - } - - // if there is CNAME in the node - const knot_rrset_t *cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME); - cname_chain_t *chain = NULL; - cname_chain_t **act_cname = &chain; - int ret = 0; - - while (cname != NULL && !cname_chain_contains(chain, node)) { - ret = cname_chain_add(act_cname, node); - if (ret != KNOT_EOK) { - cname_chain_free(chain); - args->err = ret; - return; - } - act_cname = &(*act_cname)->next; - - // follow the CNAME chain, including wildcards and - // remember the nodes passed through - const knot_dname_t *next_name = knot_rdata_cname_name( - knot_rrset_rdata(cname)); - assert(next_name != NULL); - const knot_node_t *next_node = knot_dname_node(next_name); - if (next_node == NULL) { - // try to find the name in the zone - const knot_node_t *ce = NULL; - ret = knot_zone_contents_find_dname_hash( - args->zone, next_name, - &next_node, &ce); - - if (ret != KNOT_ZONE_NAME_FOUND - && ce != NULL) { - // try to find wildcard child - assert(knot_dname_is_subdomain(next_name, - knot_node_owner(ce))); - next_node = knot_node_wildcard_child(ce); - } - - assert(next_node == NULL || knot_dname_compare( - knot_node_owner(next_node), next_name) == 0 - || knot_dname_is_wildcard(knot_node_owner(next_node))); - } - - if (next_node == NULL) { - // no CNAME node to follow - cname = NULL; - } else { - node = next_node; - cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME); - } - } - - if (cname != NULL) { - // this means the node is in the chain already - args->err = KNOT_ECNAME; - } - - cname_chain_free(chain); -} - -/*----------------------------------------------------------------------------*/ + assert(rrset != NULL && params != NULL); -static int knot_zc_nsec3_parameters_match(const knot_rdata_t *rdata, - const knot_nsec3_params_t *params) -{ - assert(rdata != NULL && params != NULL); - dbg_zone_detail("RDATA algo: %u, iterations: %u, salt length: %u, salt:" - " %.*s\n", - knot_rdata_nsec3_algorithm(rdata), - knot_rdata_nsec3_iterations(rdata), - knot_rdata_nsec3_salt_length(rdata), - knot_rdata_nsec3_salt_length(rdata), - knot_rdata_nsec3_salt(rdata)); + " %.*s\n", + knot_rrset_rdata_nsec3_algorithm(rrset, rdata_pos), + knot_rrset_rdata_nsec3_iterations(rrset, rdata_pos), + knot_rrset_rdata_nsec3_salt_length(rrset, rdata_pos), + knot_rrset_rdata_nsec3_salt_length(rrset, rdata_pos), + knot_rrset_rdata_nsec3_salt(rrset, rdata_pos)); dbg_zone_detail("NSEC3PARAM algo: %u, iterations: %u, salt length: %u, " - "salt: %.*s\n", params->algorithm, params->iterations, - params->salt_length, params->salt_length, params->salt); - - return (knot_rdata_nsec3_algorithm(rdata) == params->algorithm - && knot_rdata_nsec3_iterations(rdata) == params->iterations - && knot_rdata_nsec3_salt_length(rdata) == params->salt_length - && strncmp((const char *)knot_rdata_nsec3_salt(rdata), - (const char *)params->salt, params->salt_length) - == 0); + "salt: %.*s\n", params->algorithm, params->iterations, + params->salt_length, params->salt_length, params->salt); + + return (knot_rrset_rdata_nsec3_algorithm(rrset, rdata_pos) == params->algorithm + && knot_rrset_rdata_nsec3_iterations(rrset, rdata_pos) == params->iterations + && knot_rrset_rdata_nsec3_salt_length(rrset, rdata_pos) == params->salt_length + && strncmp((const char *)knot_rrset_rdata_nsec3_salt(rrset, rdata_pos), + (const char *)params->salt, params->salt_length) + == 0); } /*----------------------------------------------------------------------------*/ @@ -1145,13 +756,10 @@ static int knot_zc_nsec3_parameters_match(const knot_rdata_t *rdata, /*----------------------------------------------------------------------------*/ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex, - uint node_count, - int use_domain_table, struct knot_zone *zone) { - dbg_zone("Creating contents for %u nodes.\n", node_count); knot_zone_contents_t *contents = (knot_zone_contents_t *) - calloc(1, sizeof(knot_zone_contents_t)); + calloc(1, sizeof(knot_zone_contents_t)); if (contents == NULL) { ERR_ALLOC_FAILED; return NULL; @@ -1163,32 +771,19 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex, contents->node_count = 1; dbg_zone_verb("Creating tree for normal nodes.\n"); - contents->nodes = malloc(sizeof(knot_zone_tree_t)); + contents->nodes = knot_zone_tree_create(); if (contents->nodes == NULL) { ERR_ALLOC_FAILED; goto cleanup; } dbg_zone_verb("Creating tree for NSEC3 nodes.\n"); - contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t)); + contents->nsec3_nodes = knot_zone_tree_create(); if (contents->nsec3_nodes == NULL) { ERR_ALLOC_FAILED; goto cleanup; } - if (use_domain_table) { - dbg_zone_verb("Creating domain name table.\n"); - contents->dname_table = knot_dname_table_new(); - if (contents->dname_table == NULL) { - ERR_ALLOC_FAILED; - goto cleanup; - } - } else { - contents->dname_table = NULL; - } - - //contents->node_count = node_count; - /* Initialize NSEC3 params */ dbg_zone_verb("Initializing NSEC3 parameters.\n"); contents->nsec3_params.algorithm = 0; @@ -1197,57 +792,16 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex, contents->nsec3_params.salt_length = 0; contents->nsec3_params.salt = NULL; - dbg_zone_verb("Initializing zone trees.\n"); - if (knot_zone_tree_init(contents->nodes) != KNOT_EOK - || knot_zone_tree_init(contents->nsec3_nodes) != KNOT_EOK) { - goto cleanup; - } - dbg_zone_verb("Inserting apex into the zone tree.\n"); if (knot_zone_tree_insert(contents->nodes, apex) != KNOT_EOK) { dbg_zone("Failed to insert apex to the zone tree.\n"); goto cleanup; } -#ifdef USE_HASH_TABLE - if (node_count > 0) { - dbg_zone_verb("Creating hash table.\n"); - contents->table = ck_create_table(node_count); - if (contents->table == NULL) { - goto cleanup; - } - - // insert the apex into the hash table - dbg_zone_verb("Inserting apex into the hash table.\n"); - if (ck_insert_item(contents->table, - (const char *)knot_dname_name( - knot_node_owner(apex)), - knot_dname_size(knot_node_owner(apex)), - (void *)apex) != 0) { - ck_destroy_table(&contents->table, NULL, 0); - goto cleanup; - } - } else { - contents->table = NULL; - } -#endif - - // insert names from the apex to the domain table - if (use_domain_table) { - dbg_zone_verb("Inserting names from apex to table.\n"); - int rc = knot_zone_contents_dnames_from_node_to_table( - contents->dname_table, apex); - if (rc != KNOT_EOK) { - ck_destroy_table(&contents->table, NULL, 0); - goto cleanup; - } - } - return contents; cleanup: dbg_zone_verb("Cleaning up.\n"); - free(contents->dname_table); free(contents->nodes); free(contents->nsec3_nodes); free(contents); @@ -1259,7 +813,7 @@ cleanup: int knot_zone_contents_gen_is_old(const knot_zone_contents_t *contents) { return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK) - == KNOT_ZONE_FLAGS_GEN_OLD); + == KNOT_ZONE_FLAGS_GEN_OLD); } /*----------------------------------------------------------------------------*/ @@ -1267,7 +821,7 @@ int knot_zone_contents_gen_is_old(const knot_zone_contents_t *contents) int knot_zone_contents_gen_is_new(const knot_zone_contents_t *contents) { return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK) - == KNOT_ZONE_FLAGS_GEN_NEW); + == KNOT_ZONE_FLAGS_GEN_NEW); } /*----------------------------------------------------------------------------*/ @@ -1275,7 +829,7 @@ int knot_zone_contents_gen_is_new(const knot_zone_contents_t *contents) int knot_zone_contents_gen_is_finished(const knot_zone_contents_t *contents) { return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK) - == KNOT_ZONE_FLAGS_GEN_FIN); + == KNOT_ZONE_FLAGS_GEN_FIN); } /*----------------------------------------------------------------------------*/ @@ -1307,7 +861,7 @@ void knot_zone_contents_set_gen_new_finished(knot_zone_contents_t *contents) int knot_zone_contents_any_disabled(const knot_zone_contents_t *contents) { return ((contents->flags & KNOT_ZONE_FLAGS_ANY_MASK) - == KNOT_ZONE_FLAGS_ANY); + == KNOT_ZONE_FLAGS_ANY); } /*----------------------------------------------------------------------------*/ @@ -1334,14 +888,14 @@ uint16_t knot_zone_contents_class(const knot_zone_contents_t *contents) } return knot_rrset_class(knot_node_rrset(contents->apex, - KNOT_RRTYPE_SOA)); + KNOT_RRTYPE_SOA)); } /*----------------------------------------------------------------------------*/ int knot_zone_contents_add_node(knot_zone_contents_t *zone, knot_node_t *node, int create_parents, - uint8_t flags, int use_domain_table) + uint8_t flags) { if (zone == NULL || node == NULL) { return KNOT_EINVAL; @@ -1359,37 +913,12 @@ dbg_zone_exec_detail( return ret; } - if (use_domain_table) { - ret = knot_zone_contents_dnames_from_node_to_table( - zone->dname_table, node); - if (ret != KNOT_EOK) { - dbg_zone("Failed to add dnames into table.\n"); - return ret; - } - } - ret = knot_zone_tree_insert(zone->nodes, node); if (ret != KNOT_EOK) { dbg_zone("Failed to insert node into zone tree.\n"); return ret; } -#ifdef USE_HASH_TABLE - // add the node also to the hash table if authoritative, or deleg. point - if (zone->table != NULL - && ck_insert_item(zone->table, - (const char *)node->owner->name, - node->owner->size, (void *)node) != 0) { - dbg_zone("Error inserting node into hash table!\n"); - knot_zone_tree_node_t *removed; - (void)knot_zone_tree_remove(zone->nodes, knot_node_owner(node), - &removed); - assert(removed->node == node); - return KNOT_EHASH; - } -#endif - assert(knot_zone_contents_find_node(zone, node->owner)); - knot_node_set_zone(node, zone->zone); ++zone->node_count; @@ -1404,11 +933,11 @@ dbg_zone_exec_detail( knot_dname_left_chop(knot_node_owner(node)); if(chopped == NULL) { /* Root domain and root domain only. */ - assert(node->owner && node->owner->labels && + assert(node->owner && node->owner->labels && node->owner->labels[0] == 0); return KNOT_EOK; } - + if (knot_dname_compare(knot_node_owner(zone->apex), chopped) == 0) { dbg_zone_detail("Zone apex is the parent.\n"); knot_node_set_parent(node, zone->apex); @@ -1425,7 +954,7 @@ dbg_zone_exec_detail( chopped != NULL) { /* Adding new dname to zone + add to table. */ dbg_zone_detail("Creating new node.\n"); - + assert(chopped); next_node = knot_node_new(chopped, NULL, flags); if (next_node == NULL) { @@ -1433,17 +962,13 @@ dbg_zone_exec_detail( knot_dname_free(&chopped); return KNOT_ENOMEM; } - - if (use_domain_table) { - ret = - knot_zone_contents_dnames_from_node_to_table( - zone->dname_table, next_node); - if (ret != KNOT_EOK) { - knot_node_free(&next_node); - knot_dname_release(chopped); - return ret; - } - } + //TODO possible leak +// ret = knot_zone_contents_solve_node_dnames(zone, +// next_node); +// if (ret != KNOT_EOK) { +// knot_node_free(&next_node); +// knot_dname_release(chopped); +// } if (next_node->owner != chopped) { /* Node owner was in RDATA */ @@ -1459,39 +984,16 @@ dbg_zone_exec_detail( dbg_zone_detail("Inserting new node to zone tree.\n"); ret = knot_zone_tree_insert(zone->nodes, - next_node); + next_node); if (ret != KNOT_EOK) { dbg_zone("Failed to insert new node " - "to zone tree.\n"); + "to zone tree.\n"); /*! \todo Delete the node?? */ /* Directly discard. */ knot_dname_release(chopped); return ret; } -#ifdef USE_HASH_TABLE -dbg_zone_exec_detail( - char *name = knot_dname_to_str( - knot_node_owner(next_node)); - dbg_zone_detail("Adding new node with owner %s to " - "hash table.\n", name); - free(name); -); - - if (zone->table != NULL - && ck_insert_item(zone->table, - (const char *)knot_dname_name( - knot_node_owner(next_node)), - knot_dname_size(knot_node_owner(next_node)), - (void *)next_node) != 0) { - dbg_zone("Error inserting node into " - "hash table!\n"); - /*! \todo Delete the node?? */ - /* Directly discard. */ - knot_dname_release(chopped); - return KNOT_EHASH; - } -#endif // set parent knot_node_set_parent(node, next_node); @@ -1536,8 +1038,7 @@ dbg_zone_exec_detail( int knot_zone_contents_add_rrset(knot_zone_contents_t *zone, knot_rrset_t *rrset, knot_node_t **node, - knot_rrset_dupl_handling_t dupl, - int use_domain_table) + knot_rrset_dupl_handling_t dupl) { if (zone == NULL || rrset == NULL || zone->apex == NULL || zone->apex->owner == NULL || node == NULL) { @@ -1546,22 +1047,22 @@ int knot_zone_contents_add_rrset(knot_zone_contents_t *zone, dbg_zone_exec_detail( char *name = knot_dname_to_str(knot_rrset_owner(rrset)); - dbg_zone_detail("Adding RRSet to zone contents: %s, type %s\n", - name, knot_rrtype_to_string(knot_rrset_type(rrset))); + dbg_zone_detail("Adding RRSet to zone contents: %s, type %d\n", + name, knot_rrset_type(rrset)); free(name); ); // check if the RRSet belongs to the zone if (knot_dname_compare(knot_rrset_owner(rrset), - zone->apex->owner) != 0 + zone->apex->owner) != 0 && !knot_dname_is_subdomain(knot_rrset_owner(rrset), - zone->apex->owner)) { + zone->apex->owner)) { return KNOT_EBADZONE; } if ((*node) == NULL && (*node = knot_zone_contents_get_node(zone, - knot_rrset_owner(rrset))) == NULL) { + knot_rrset_owner(rrset))) == NULL) { return KNOT_ENONODE; } @@ -1572,9 +1073,9 @@ dbg_zone_exec_detail( /*! \todo REMOVE RRSET */ if (dupl == KNOT_RRSET_DUPL_MERGE) { - rc = knot_node_add_rrset_no_dupl(*node, rrset); + rc = knot_node_add_rrset(*node, rrset); } else { - rc = knot_node_add_rrset(*node, rrset, 0); + rc = knot_node_add_rrset_no_merge(*node, rrset); } if (rc < 0) { @@ -1584,40 +1085,17 @@ dbg_zone_exec_detail( int ret = rc; - if (use_domain_table) { - dbg_zone_detail("Saving RRSet to table.\n"); - rc = knot_zone_contents_dnames_from_rrset_to_table( - zone->dname_table, rrset, 0, (*node)->owner); - if (rc != KNOT_EOK) { - dbg_zone("Error saving domain names from " - "RRSIGs to the domain name table.\n " - "The zone may be in an inconsistent state.\n"); - // WARNING: the zone is not in consistent state now - - // there may be domain names in it that are not inserted - // into the domain table - return rc; - } - } - - // replace RRSet's owner with the node's owner (that is already in the - // table) - /*! \todo Do even if domain table is not used?? */ - if (ret == KNOT_EOK && rrset->owner != (*node)->owner) { - knot_rrset_set_owner(rrset, (*node)->owner); - } - - dbg_zone_detail("RRSet OK.\n"); + dbg_zone_detail("RRSet OK (%d).\n", ret); return ret; } /*----------------------------------------------------------------------------*/ int knot_zone_contents_add_rrsigs(knot_zone_contents_t *zone, - knot_rrset_t *rrsigs, - knot_rrset_t **rrset, - knot_node_t **node, - knot_rrset_dupl_handling_t dupl, - int use_domain_table) + knot_rrset_t *rrsigs, + knot_rrset_t **rrset, + knot_node_t **node, + knot_rrset_dupl_handling_t dupl) { dbg_zone_verb("Adding RRSIGs to zone contents.\n"); @@ -1625,11 +1103,11 @@ int knot_zone_contents_add_rrsigs(knot_zone_contents_t *zone, || zone->apex == NULL || zone->apex->owner == NULL) { dbg_zone_exec( dbg_zone("Parameters: zone=%p, rrsigs=%p, rrset=%p, " - "node=%p\n", zone, rrsigs, rrset, node); + "node=%p\n", zone, rrsigs, rrset, node); if (zone != NULL) { dbg_zone("zone->apex=%p\n", zone->apex); if (zone->apex != NULL) { - dbg_zone("zone->apex->owner=%p\n", + dbg_zone("zone->apex->owner=%p\n", zone->apex->owner); } } @@ -1640,16 +1118,16 @@ dbg_zone_exec( // check if the RRSet belongs to the zone if (*rrset != NULL && knot_dname_compare(knot_rrset_owner(*rrset), - zone->apex->owner) != 0 + zone->apex->owner) != 0 && !knot_dname_is_subdomain(knot_rrset_owner(*rrset), - zone->apex->owner)) { + zone->apex->owner)) { return KNOT_EBADZONE; } // check if the RRSIGs belong to the RRSet if (*rrset != NULL && (knot_dname_compare(knot_rrset_owner(rrsigs), - knot_rrset_owner(*rrset)) != 0)) { + knot_rrset_owner(*rrset)) != 0)) { dbg_zone("RRSIGs do not belong to the given RRSet.\n"); return KNOT_EINVAL; } @@ -1659,15 +1137,14 @@ dbg_zone_exec( // even no node given // find proper node knot_node_t *(*get_node)(const knot_zone_contents_t *, - const knot_dname_t *) - = (knot_rdata_rrsig_type_covered( - knot_rrset_rdata(rrsigs)) == KNOT_RRTYPE_NSEC3) + const knot_dname_t *) + = (knot_rrset_rdata_rrsig_type_covered(rrsigs) == KNOT_RRTYPE_NSEC3) ? knot_zone_contents_get_nsec3_node : knot_zone_contents_get_node; if (*node == NULL && (*node = get_node( - zone, knot_rrset_owner(rrsigs))) == NULL) { + zone, knot_rrset_owner(rrsigs))) == NULL) { dbg_zone("Failed to find node for RRSIGs.\n"); return KNOT_ENONODE; } @@ -1676,13 +1153,10 @@ dbg_zone_exec( // find the RRSet in the node // take only the first RDATA from the RRSIGs - dbg_zone_detail("Finding RRSet for type %s\n", - knot_rrtype_to_string( - knot_rdata_rrsig_type_covered( - knot_rrset_rdata(rrsigs)))); + dbg_zone_detail("Finding RRSet for type %d\n", + knot_rrset_rdata_rrsig_type_covered(rrsigs)); *rrset = knot_node_get_rrset( - *node, knot_rdata_rrsig_type_covered( - knot_rrset_rdata(rrsigs))); + *node, knot_rrset_rdata_rrsig_type_covered(rrsigs)); if (*rrset == NULL) { dbg_zone("Failed to find RRSet for RRSIGs.\n"); return KNOT_ENORRSET; @@ -1704,28 +1178,6 @@ dbg_zone_exec( ret = 1; } - // add all domain names from the RRSet to domain name table - if (use_domain_table) { - dbg_zone_detail("Saving RRSIG RRSet to table.\n"); - rc = knot_zone_contents_dnames_from_rrset_to_table( - zone->dname_table, (*rrset)->rrsigs, 0, (*rrset)->owner); - if (rc != KNOT_EOK) { - dbg_zone("Error saving domain names from " - "RRSIGs to the domain name table.\n " - "The zone may be in an inconsistent state.\n"); - // WARNING: the zone is not in consistent state now - - // there may be domain names in it that are not inserted - // into the domain table - return rc; - } - } - - // replace RRSet's owner with the node's owner (that is already in the - // table) - if ((*rrset)->owner != (*rrset)->rrsigs->owner) { - knot_rrset_set_owner((*rrset)->rrsigs, (*rrset)->owner); - } - dbg_zone_detail("RRSIGs OK\n"); return ret; } @@ -1734,7 +1186,7 @@ dbg_zone_exec( int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone, knot_node_t *node, int create_parents, - uint8_t flags, int use_domain_table) + uint8_t flags) { UNUSED(create_parents); UNUSED(flags); @@ -1750,25 +1202,13 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone, } // how to know if this is successfull?? -// TREE_INSERT(zone->nsec3_nodes, knot_node, avl, node); ret = knot_zone_tree_insert(zone->nsec3_nodes, node); if (ret != KNOT_EOK) { dbg_zone("Failed to insert node into NSEC3 tree: %s.\n", - knot_strerror(ret)); + knot_strerror(ret)); return ret; } - if (use_domain_table) { - ret = knot_zone_contents_dnames_from_node_to_table( - zone->dname_table, node); - if (ret != KNOT_EOK) { - /*! \todo Remove the node from the tree. */ - dbg_zone("Failed to add dnames into table: %s.\n", - knot_strerror(ret)); - return ret; - } - } - // no parents to be created, the only parent is the zone apex // set the apex as the parent of the node knot_node_set_parent(node, zone->apex); @@ -1786,8 +1226,7 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone, int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone, knot_rrset_t *rrset, knot_node_t **node, - knot_rrset_dupl_handling_t dupl, - int use_domain_table) + knot_rrset_dupl_handling_t dupl) { if (zone == NULL || rrset == NULL || zone->apex == NULL || zone->apex->owner == NULL || node == NULL) { @@ -1796,28 +1235,26 @@ int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone, // check if the RRSet belongs to the zone if (knot_dname_compare(knot_rrset_owner(rrset), - zone->apex->owner) != 0 + zone->apex->owner) != 0 && !knot_dname_is_subdomain(knot_rrset_owner(rrset), - zone->apex->owner)) { + zone->apex->owner)) { return KNOT_EBADZONE; } if ((*node) == NULL && (*node = knot_zone_contents_get_nsec3_node( - zone, knot_rrset_owner(rrset))) == NULL) { + zone, knot_rrset_owner(rrset))) == NULL) { return KNOT_ENONODE; } assert(*node != NULL); - - // add all domain names from the RRSet to domain name table int rc; /*! \todo REMOVE RRSET */ if (dupl == KNOT_RRSET_DUPL_MERGE) { - rc = knot_node_add_rrset_no_dupl(*node, rrset); + rc = knot_node_add_rrset(*node, rrset); } else { - rc = knot_node_add_rrset(*node, rrset, 0); + rc = knot_node_add_rrset_no_merge(*node, rrset); } if (rc < 0) { @@ -1826,37 +1263,14 @@ int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone, int ret = rc; - if (use_domain_table) { - dbg_zone_detail("Saving NSEC3 RRSet to table.\n"); - rc = knot_zone_contents_dnames_from_rrset_to_table( - zone->dname_table, rrset, 0, (*node)->owner); - if (rc != KNOT_EOK) { - dbg_zone("Error saving domain names from " - "RRSIGs to the domain name table.\n " - "The zone may be in an inconsistent state.\n"); - // WARNING: the zone is not in consistent state now - - // there may be domain names in it that are not inserted - // into the domain table - return rc; - } - } - - // replace RRSet's owner with the node's owner (that is already in the - // table) - /*! \todo Do even if domain table is not used? */ - if (rrset->owner != (*node)->owner) { - knot_rrset_set_owner(rrset, (*node)->owner); - } - dbg_zone_detail("NSEC3 OK\n"); return ret; } /*----------------------------------------------------------------------------*/ -int knot_zone_contents_remove_node(knot_zone_contents_t *contents, - const knot_node_t *node, knot_zone_tree_node_t **removed_tree, - ck_hash_table_item_t **removed_hash) +int knot_zone_contents_remove_node(knot_zone_contents_t *contents, + const knot_node_t *node, knot_node_t **removed_tree) { if (contents == NULL || node == NULL) { return KNOT_EINVAL; @@ -1870,15 +1284,6 @@ dbg_zone_exec_verb( free(name); ); - // 1) remove the node from hash table - *removed_hash = NULL; - *removed_hash = ck_remove_item(contents->table, - (const char *)knot_dname_name(owner), - knot_dname_size(owner)); - if (*removed_hash == NULL) { - return KNOT_ENONODE; - } - // 2) remove the node from the zone tree *removed_tree = NULL; int ret = knot_zone_tree_remove(contents->nodes, owner, removed_tree); @@ -1891,8 +1296,8 @@ dbg_zone_exec_verb( /*----------------------------------------------------------------------------*/ -int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents, - const knot_node_t *node, knot_zone_tree_node_t **removed) +int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents, + const knot_node_t *node, knot_node_t **removed) { if (contents == NULL || node == NULL) { return KNOT_EINVAL; @@ -1912,56 +1317,6 @@ int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents, /*----------------------------------------------------------------------------*/ -int knot_zone_contents_create_and_fill_hash_table( - knot_zone_contents_t *zone) -{ - if (zone == NULL || zone->apex == NULL || zone->apex->owner == NULL) { - return KNOT_EINVAL; - } - /* - * 1) Create hash table. - */ -#ifdef USE_HASH_TABLE - if (zone->node_count > 0) { - zone->table = ck_create_table(zone->node_count); - if (zone->table == NULL) { - return KNOT_ENOMEM; - } - - // insert the apex into the hash table - if (ck_insert_item(zone->table, - (const char *)zone->apex->owner->name, - zone->apex->owner->size, - (void *)zone->apex) != 0) { - return KNOT_EHASH; - } - } else { - zone->table = NULL; - return KNOT_EOK; // OK? - } - - /* - * 2) Fill in the hash table. - * - * In this point, the nodes in the zone must be adjusted, so that only - * relevant nodes (authoritative and delegation points are inserted. - * - * TODO: how to know if this was successful?? - */ - /*! \todo Replace by zone tree. */ - int ret = knot_zone_tree_forward_apply_inorder(zone->nodes, - knot_zone_contents_node_to_hash, zone); - if (ret != KNOT_EOK) { - dbg_zone("Failed to insert nodes to hash table.\n"); - return ret; - } - -#endif - return KNOT_EOK; -} - -/*----------------------------------------------------------------------------*/ - knot_node_t *knot_zone_contents_get_node(const knot_zone_contents_t *zone, const knot_dname_t *name) { @@ -1993,7 +1348,7 @@ knot_node_t *knot_zone_contents_get_nsec3_node( if (ret != KNOT_EOK) { dbg_zone("Failed to find NSEC3 name in the zone tree." - "\n"); + "\n"); return NULL; } @@ -2026,7 +1381,7 @@ dbg_zone_exec_verb( char *name_str = knot_dname_to_str(name); char *zone_str = knot_dname_to_str(zone->apex->owner); dbg_zone_verb("Searching for name %s in zone %s...\n", - name_str, zone_str); + name_str, zone_str); free(name_str); free(zone_str); ); @@ -2046,19 +1401,19 @@ dbg_zone_exec_verb( knot_node_t *found = NULL, *prev = NULL; int exact_match = knot_zone_contents_find_in_tree(zone->nodes, name, - &found, &prev); + &found, &prev); assert(exact_match >= 0); *node = found; *previous = prev; dbg_zone_exec_detail( char *name_str = (*node) ? knot_dname_to_str((*node)->owner) - : "(nil)"; + : "(nil)"; char *name_str2 = (*previous != NULL) - ? knot_dname_to_str((*previous)->owner) - : "(nil)"; + ? knot_dname_to_str((*previous)->owner) + : "(nil)"; dbg_zone_detail("Search function returned %d, node %s (%p) and prev: %s (%p)\n", - exact_match, name_str, *node, name_str2, *previous); + exact_match, name_str, *node, name_str2, *previous); if (*node) { free(name_str); @@ -2118,7 +1473,7 @@ knot_node_t *knot_zone_contents_get_previous( knot_node_t *found = NULL, *prev = NULL; int exact_match = knot_zone_contents_find_in_tree(zone->nodes, name, - &found, &prev); + &found, &prev); assert(exact_match >= 0); assert(prev != NULL); @@ -2145,7 +1500,7 @@ knot_node_t *knot_zone_contents_get_previous_nsec3( knot_node_t *found = NULL, *prev = NULL; int exact_match = knot_zone_contents_find_in_tree(zone->nsec3_nodes, - name, &found, &prev); + name, &found, &prev); assert(exact_match >= 0); assert(prev != NULL); @@ -2162,99 +1517,6 @@ const knot_node_t *knot_zone_contents_find_previous_nsec3( /*----------------------------------------------------------------------------*/ -static void knot_zone_contents_left_chop(char *name, size_t *size) -{ - short label_size = (unsigned char)name[0]; - - memmove(name, name + label_size + 1, *size -label_size - 1); - *size = *size - label_size - 1; -} - -/*----------------------------------------------------------------------------*/ -#ifdef USE_HASH_TABLE -int knot_zone_contents_find_dname_hash(const knot_zone_contents_t *zone, - const knot_dname_t *name, - const knot_node_t **node, - const knot_node_t **closest_encloser) -{ - if (zone == NULL || name == NULL || node == NULL - || closest_encloser == NULL) { - return KNOT_EINVAL; - } - -dbg_zone_exec_verb( - char *name_str = knot_dname_to_str(name); - char *zone_str = knot_dname_to_str(zone->apex->owner); - dbg_zone_verb("Searching for name %s in zone %s...\n", - name_str, zone_str); - free(name_str); - free(zone_str); -); - - if (knot_dname_compare(name, zone->apex->owner) == 0) { - *node = zone->apex; - *closest_encloser = *node; - return KNOT_ZONE_NAME_FOUND; - } - - if (!knot_dname_is_subdomain(name, zone->apex->owner)) { - *node = NULL; - *closest_encloser = NULL; - return KNOT_EBADZONE; - } - - // temporary name used for hashing - char name_tmp[KNOT_MAX_DNAME_LENGTH]; - size_t name_size = name->size; - if (knot_dname_to_lower_copy(name, name_tmp, KNOT_MAX_DNAME_LENGTH) - != KNOT_EOK) { - return KNOT_ERROR; - } - - assert(zone->table != NULL); - const ck_hash_table_item_t *item = ck_find_item(zone->table, - name_tmp, name_size); - - if (item != NULL) { - *node = (const knot_node_t *)item->value; - *closest_encloser = *node; - - dbg_zone_detail("Found node in hash table: %p (owner %p, " - "labels: %d)\n", *node, (*node)->owner, - knot_dname_label_count((*node)->owner)); - assert(*node != NULL); - assert(*closest_encloser != NULL); - return KNOT_ZONE_NAME_FOUND; - } - - *node = NULL; - - // chop leftmost labels until some node is found - // copy the name for chopping - - dbg_zone_detail("Finding closest encloser..\nStarting with: %.*s\n", - (int)name_size, name_tmp); - - while (item == NULL) { - knot_zone_contents_left_chop(name_tmp, &name_size); -dbg_zone_exec_detail( - dbg_zone_detail("Chopped leftmost label: %.*s\n", - (int)name_size, name_tmp); -); - // not satisfied in root zone!! - assert(name_size > 0); - - item = ck_find_item(zone->table, name_tmp, name_size); - } - - assert(item != NULL); - *closest_encloser = (const knot_node_t *)item->value; - - return KNOT_ZONE_NAME_NOT_FOUND; -} -#endif -/*----------------------------------------------------------------------------*/ - const knot_node_t *knot_zone_contents_find_nsec3_node( const knot_zone_contents_t *zone, const knot_dname_t *name) { @@ -2281,7 +1543,7 @@ int knot_zone_contents_find_nsec3_for_name(const knot_zone_contents_t *zone, } // check if the NSEC3 tree is not empty - if (zone->nsec3_nodes->th_root == NULL) { + if (knot_zone_tree_weight(zone->nsec3_nodes) == 0) { dbg_zone("NSEC3 tree is empty.\n"); knot_dname_release(nsec3_name); return KNOT_ENSEC3CHAIN; @@ -2341,39 +1603,40 @@ dbg_zone_exec_detail( } dbg_zone_verb("find_nsec3_for_name() returning %d\n", exact_match); - - /* The previous may be from wrong NSEC3 chain. Search for previous - * from the right chain. Check iterations, hash algorithm and salt + + /* The previous may be from wrong NSEC3 chain. Search for previous + * from the right chain. Check iterations, hash algorithm and salt * values and compare them to the ones from NSEC3PARAM. */ - const knot_rrset_t *nsec3_rrset = knot_node_rrset(*nsec3_previous, - KNOT_RRTYPE_NSEC3); - const knot_rdata_t *nsec3_rdata = (nsec3_rrset != NULL) - ? knot_rrset_rdata(nsec3_rrset) - : NULL; + const knot_rrset_t *nsec3_rrset = knot_node_rrset(*nsec3_previous, + KNOT_RRTYPE_NSEC3); + assert(nsec3_rrset); const knot_node_t *original_prev = *nsec3_previous; - - while (nsec3_rdata != NULL - && !knot_zc_nsec3_parameters_match(nsec3_rdata, - &zone->nsec3_params)) { - /* Try other RDATA if there are some. In case of name collision - * the node would contain records from both NSEC3 chains. - */ - if ((nsec3_rdata = knot_rrset_rdata_next( - nsec3_rrset, nsec3_rdata)) != NULL) { - continue; + + int match = 0; + + while (nsec3_rrset && !match) { + for (uint16_t i = 0; + i < knot_rrset_rdata_rr_count(nsec3_rrset) && !match; + i++) { + if (knot_zc_nsec3_parameters_match(nsec3_rrset, + &zone->nsec3_params, + i)) { + /* Matching NSEC3PARAM match at position nr.: i. */ + match = 1; + } } - - /* If there is none, try previous node. */ - + + if (match) { + break; + } + + /* This RRSET was not a match, try the one from previous node. */ *nsec3_previous = knot_node_previous(*nsec3_previous); - nsec3_rrset = knot_node_rrset(*nsec3_previous, - KNOT_RRTYPE_NSEC3); - nsec3_rdata = (nsec3_rrset != NULL) - ? knot_rrset_rdata(nsec3_rrset) - : NULL; -dbg_zone_exec_detail( - char *name = (*nsec3_previous) + nsec3_rrset = knot_node_rrset(*nsec3_previous, + KNOT_RRTYPE_NSEC3); + dbg_zone_exec_detail( + char *name = (*nsec3_previous) ? knot_dname_to_str( knot_node_owner(*nsec3_previous)) : "none"; @@ -2383,7 +1646,7 @@ dbg_zone_exec_detail( free(name); } ); - if (*nsec3_previous == original_prev || nsec3_rdata == NULL) { + if (*nsec3_previous == original_prev || nsec3_rrset == NULL) { // cycle *nsec3_previous = NULL; break; @@ -2420,43 +1683,63 @@ knot_node_t *knot_zone_contents_get_apex(const knot_zone_contents_t *zone) /*----------------------------------------------------------------------------*/ -int knot_zone_contents_adjust(knot_zone_contents_t *zone) +int knot_zone_contents_adjust(knot_zone_contents_t *zone, + knot_node_t **first_nsec3_node, + knot_node_t **last_nsec3_node, int dupl_check) { if (zone == NULL) { return KNOT_EINVAL; } + /* Heal zone indexes. */ + hattrie_build_index(zone->nodes); + hattrie_build_index(zone->nsec3_nodes); + // load NSEC3PARAM (needed on adjusting function) knot_zone_contents_load_nsec3param(zone); + hattrie_t *lookup_tree = NULL; + if (dupl_check) { + lookup_tree = hattrie_create(); + if (lookup_tree == NULL) { + dbg_zone("Failed to create out of zone lookup structure.\n"); + return KNOT_ERROR; + } + } + knot_zone_adjust_arg_t adjust_arg; adjust_arg.zone = zone; adjust_arg.first_node = NULL; adjust_arg.previous_node = NULL; + adjust_arg.lookup_tree = lookup_tree; adjust_arg.err = KNOT_EOK; /* * First of all we must set node.prev pointers, as these are used in * the search functions. - * - * We must also set flags, as these are required to set the prev - * pointers well. */ dbg_zone("Setting 'prev' pointers to NSEC3 nodes.\n"); - int ret = knot_zone_tree_forward_apply_inorder(zone->nsec3_nodes, - knot_zone_contents_adjust_nsec3_node_in_tree_ptr, &adjust_arg); + int ret = knot_zone_tree_apply_inorder(zone->nsec3_nodes, + knot_zone_contents_adjust_nsec3_node_in_tree_ptr, &adjust_arg); assert(ret == KNOT_EOK); if (adjust_arg.err != KNOT_EOK) { dbg_zone("Failed to set 'prev' pointers to NSEC3 nodes: %s\n", - knot_strerror(adjust_arg.err)); + knot_strerror(adjust_arg.err)); + hattrie_free(lookup_tree); return adjust_arg.err; } // set the last node as previous of the first node if (adjust_arg.first_node) { knot_node_set_previous(adjust_arg.first_node, - adjust_arg.previous_node); + adjust_arg.previous_node); + } + if (first_nsec3_node) { + *first_nsec3_node = adjust_arg.first_node; + } + if (last_nsec3_node) { + *last_nsec3_node = adjust_arg.previous_node; } dbg_zone("Done.\n"); @@ -2464,13 +1747,14 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone) adjust_arg.previous_node = NULL; dbg_zone("Setting 'prev' pointers to normal nodes.\n"); - ret = knot_zone_tree_forward_apply_inorder(zone->nodes, - knot_zone_contents_adjust_node_in_tree_ptr, &adjust_arg); + ret = knot_zone_tree_apply_inorder(zone->nodes, + knot_zone_contents_adjust_node_in_tree_ptr, &adjust_arg); assert(ret == KNOT_EOK); if (adjust_arg.err != KNOT_EOK) { dbg_zone("Failed to set 'prev' pointers to normal nodes: %s\n", - knot_strerror(adjust_arg.err)); + knot_strerror(adjust_arg.err)); + hattrie_free(lookup_tree); return adjust_arg.err; } @@ -2486,60 +1770,35 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone) */ dbg_zone("Adjusting NSEC3 nodes.\n"); - ret = knot_zone_tree_forward_apply_inorder(zone->nsec3_nodes, - knot_zone_contents_adjust_nsec3_node_in_tree, &adjust_arg); + ret = knot_zone_tree_apply_inorder(zone->nsec3_nodes, + knot_zone_contents_adjust_nsec3_node_in_tree, &adjust_arg); assert(ret == KNOT_EOK); if (adjust_arg.err != KNOT_EOK) { dbg_zone("Failed to adjust NSEC3 nodes: %s\n", - knot_strerror(adjust_arg.err)); + knot_strerror(adjust_arg.err)); + hattrie_free(lookup_tree); return adjust_arg.err; } dbg_zone("Adjusting normal nodes.\n"); - ret = knot_zone_tree_forward_apply_inorder(zone->nodes, - knot_zone_contents_adjust_node_in_tree, - &adjust_arg); + ret = knot_zone_tree_apply_inorder(zone->nodes, + knot_zone_contents_adjust_node_in_tree, + &adjust_arg); assert(ret == KNOT_EOK); if (adjust_arg.err != KNOT_EOK) { dbg_zone("Failed to adjust normal nodes: %s\n", - knot_strerror(adjust_arg.err)); + knot_strerror(adjust_arg.err)); + hattrie_free(lookup_tree); return adjust_arg.err; } dbg_zone("Done.\n"); - return ret; -} - -/*----------------------------------------------------------------------------*/ - -int knot_zone_contents_check_loops(knot_zone_contents_t *zone) -{ - if (zone == NULL) { - return KNOT_EINVAL; - } - - dbg_zone("Checking CNAME and wildcard loops.\n"); - - loop_check_data_t data; - data.err = KNOT_EOK; - data.zone = zone; - - assert(zone->nodes != NULL); - knot_zone_tree_forward_apply_inorder(zone->nodes, - knot_zone_contents_check_loops_in_tree, - (void *)&data); - - if (data.err != KNOT_EOK) { - dbg_zone("Found CNAME loop in data. Aborting transfer.\n"); - return data.err; - } + hattrie_free(lookup_tree); - dbg_zone("Done\n"); - - return KNOT_EOK; + return ret; } /*----------------------------------------------------------------------------*/ @@ -2551,11 +1810,15 @@ int knot_zone_contents_load_nsec3param(knot_zone_contents_t *zone) } const knot_rrset_t *rrset = knot_node_rrset(zone->apex, - KNOT_RRTYPE_NSEC3PARAM); + KNOT_RRTYPE_NSEC3PARAM); if (rrset != NULL) { int r = knot_nsec3_params_from_wire(&zone->nsec3_params, rrset); - assert(r == KNOT_EOK); + if (r != KNOT_EOK) { + dbg_zone("Failed to load NSEC3PARAM (%s).\n", + knot_strerror(r)); + return r; + } } else { memset(&zone->nsec3_params, 0, sizeof(knot_nsec3_params_t)); } @@ -2572,7 +1835,7 @@ int knot_zone_contents_nsec3_enabled(const knot_zone_contents_t *zone) } return (zone->nsec3_params.algorithm != 0 - && zone->nsec3_nodes->th_root != NULL); + && knot_zone_tree_weight(zone->nsec3_nodes) != 0); } /*----------------------------------------------------------------------------*/ @@ -2593,24 +1856,6 @@ const knot_nsec3_params_t *knot_zone_contents_nsec3params( /*----------------------------------------------------------------------------*/ -int knot_zone_contents_tree_apply_postorder(knot_zone_contents_t *zone, - void (*function)(knot_node_t *node, void *data), - void *data) -{ - if (zone == NULL) { - return KNOT_EINVAL; - } - - knot_zone_tree_func_t f; - f.func = function; - f.data = data; - - return knot_zone_tree_forward_apply_postorder(zone->nodes, - knot_zone_tree_apply, &f); -} - -/*----------------------------------------------------------------------------*/ - int knot_zone_contents_tree_apply_inorder(knot_zone_contents_t *zone, void (*function)(knot_node_t *node, void *data), void *data) @@ -2623,8 +1868,8 @@ int knot_zone_contents_tree_apply_inorder(knot_zone_contents_t *zone, f.func = function; f.data = data; - return knot_zone_tree_forward_apply_inorder(zone->nodes, - knot_zone_tree_apply, &f); + return knot_zone_tree_apply_inorder(zone->nodes, + tree_apply_cb, &f); } /*----------------------------------------------------------------------------*/ @@ -2641,26 +1886,8 @@ int knot_zone_contents_tree_apply_inorder_reverse( f.func = function; f.data = data; - return knot_zone_tree_reverse_apply_inorder(zone->nodes, - knot_zone_tree_apply, &f); -} - -/*----------------------------------------------------------------------------*/ - -int knot_zone_contents_nsec3_apply_postorder(knot_zone_contents_t *zone, - void (*function)(knot_node_t *node, void *data), - void *data) -{ - if (zone == NULL) { - return KNOT_EINVAL; - } - - knot_zone_tree_func_t f; - f.func = function; - f.data = data; - - return knot_zone_tree_forward_apply_postorder( - zone->nsec3_nodes, knot_zone_tree_apply, &f); + return knot_zone_tree_apply_recursive(zone->nodes, + tree_apply_cb, &f); } /*----------------------------------------------------------------------------*/ @@ -2677,8 +1904,8 @@ int knot_zone_contents_nsec3_apply_inorder(knot_zone_contents_t *zone, f.func = function; f.data = data; - return knot_zone_tree_forward_apply_inorder( - zone->nsec3_nodes, knot_zone_tree_apply, &f); + return knot_zone_tree_apply_inorder( + zone->nsec3_nodes, tree_apply_cb, &f); } /*----------------------------------------------------------------------------*/ @@ -2695,8 +1922,8 @@ int knot_zone_contents_nsec3_apply_inorder_reverse( f.func = function; f.data = data; - return knot_zone_tree_reverse_apply_inorder( - zone->nsec3_nodes, knot_zone_tree_apply, &f); + return knot_zone_tree_apply_recursive( + zone->nsec3_nodes, tree_apply_cb, &f); } /*----------------------------------------------------------------------------*/ @@ -2717,31 +1944,6 @@ knot_zone_tree_t *knot_zone_contents_get_nsec3_nodes( /*----------------------------------------------------------------------------*/ -ck_hash_table_t *knot_zone_contents_get_hash_table( - knot_zone_contents_t *contents) -{ - return contents->table; -} - -/*----------------------------------------------------------------------------*/ - -int knot_zone_contents_dname_table_apply(knot_zone_contents_t *contents, - void (*function)(knot_dname_t *, - void *), - void *data) -{ - if (contents == NULL || function == NULL) { - return KNOT_EINVAL; - } - - knot_dname_table_tree_inorder_apply(contents->dname_table, - function, data); - - return KNOT_EOK; -} - -/*----------------------------------------------------------------------------*/ - int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from, knot_zone_contents_t **to) { @@ -2757,7 +1959,7 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from, int ret = KNOT_EOK; knot_zone_contents_t *contents = (knot_zone_contents_t *)calloc( - 1, sizeof(knot_zone_contents_t)); + 1, sizeof(knot_zone_contents_t)); if (contents == NULL) { ERR_ALLOC_FAILED; return KNOT_ENOMEM; @@ -2765,35 +1967,6 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from, contents->apex = from->apex; - contents->nodes = malloc(sizeof(knot_zone_tree_t)); - if (contents->nodes == NULL) { - ERR_ALLOC_FAILED; - ret = KNOT_ENOMEM; - goto cleanup; - } - - contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t)); - if (contents->nsec3_nodes == NULL) { - ERR_ALLOC_FAILED; - ret = KNOT_ENOMEM; - goto cleanup; - } - - if (from->dname_table != NULL) { - contents->dname_table = knot_dname_table_new(); - if (contents->dname_table == NULL) { - ERR_ALLOC_FAILED; - ret = KNOT_ENOMEM; - goto cleanup; - } - if ((ret = knot_dname_table_shallow_copy(from->dname_table, - contents->dname_table)) != KNOT_EOK) { - goto cleanup; - } - } else { - contents->dname_table = NULL; - } - contents->node_count = from->node_count; contents->flags = from->flags; @@ -2804,25 +1977,12 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from, sizeof(knot_nsec3_params_t)); if ((ret = knot_zone_tree_shallow_copy(from->nodes, - contents->nodes)) != KNOT_EOK + &contents->nodes)) != KNOT_EOK || (ret = knot_zone_tree_shallow_copy(from->nsec3_nodes, - contents->nsec3_nodes)) != KNOT_EOK) { + &contents->nsec3_nodes)) != KNOT_EOK) { goto cleanup; } -#ifdef USE_HASH_TABLE - if (from->table != NULL) { -// ret = ck_copy_table(from->table, &contents->table); - ret = ck_shallow_copy(from->table, &contents->table); - if (ret != 0) { - dbg_zone_verb("knot_zone_contents_shallow_copy: " - "hash table copied\n"); - ret = KNOT_ERROR; - goto cleanup; - } - } -#endif - dbg_zone("knot_zone_contents_shallow_copy: finished OK\n"); *to = contents; @@ -2831,7 +1991,6 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from, cleanup: knot_zone_tree_free(&contents->nodes); knot_zone_tree_free(&contents->nsec3_nodes); - free(contents->dname_table); free(contents); return ret; } @@ -2853,7 +2012,7 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from, int ret = KNOT_EOK; knot_zone_contents_t *contents = (knot_zone_contents_t *)calloc( - 1, sizeof(knot_zone_contents_t)); + 1, sizeof(knot_zone_contents_t)); if (contents == NULL) { ERR_ALLOC_FAILED; return KNOT_ENOMEM; @@ -2861,35 +2020,6 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from, //contents->apex = from->apex; - contents->nodes = malloc(sizeof(knot_zone_tree_t)); - if (contents->nodes == NULL) { - ERR_ALLOC_FAILED; - ret = KNOT_ENOMEM; - goto cleanup; - } - - contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t)); - if (contents->nsec3_nodes == NULL) { - ERR_ALLOC_FAILED; - ret = KNOT_ENOMEM; - goto cleanup; - } - - if (from->dname_table != NULL) { - contents->dname_table = knot_dname_table_new(); - if (contents->dname_table == NULL) { - ERR_ALLOC_FAILED; - ret = KNOT_ENOMEM; - goto cleanup; - } - if ((ret = knot_dname_table_shallow_copy(from->dname_table, - contents->dname_table)) != KNOT_EOK) { - goto cleanup; - } - } else { - contents->dname_table = NULL; - } - contents->node_count = from->node_count; contents->flags = from->flags; // set the 'new' flag @@ -2898,23 +2028,12 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from, contents->zone = from->zone; if ((ret = knot_zone_tree_deep_copy(from->nodes, - contents->nodes)) != KNOT_EOK + &contents->nodes)) != KNOT_EOK || (ret = knot_zone_tree_deep_copy(from->nsec3_nodes, - contents->nsec3_nodes)) != KNOT_EOK) { + &contents->nsec3_nodes)) != KNOT_EOK) { goto cleanup; } -#ifdef USE_HASH_TABLE - if (from->table != NULL) { - ret = ck_deep_copy(from->table, &contents->table); - if (ret != 0) { - dbg_zone_verb("knot_zone_contents_shallow_copy: " - "hash table copied\n"); - ret = KNOT_ERROR; - goto cleanup; - } - } -#endif contents->apex = knot_node_get_new_node(from->apex); dbg_zone("knot_zone_contents_shallow_copy: finished OK\n"); @@ -2925,7 +2044,6 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from, cleanup: knot_zone_tree_free(&contents->nodes); knot_zone_tree_free(&contents->nsec3_nodes); - free(contents->dname_table); free(contents); return ret; } @@ -2942,14 +2060,7 @@ void knot_zone_contents_free(knot_zone_contents_t **contents) knot_zone_tree_free(&(*contents)->nodes); knot_zone_tree_free(&(*contents)->nsec3_nodes); -#ifdef USE_HASH_TABLE - if ((*contents)->table != NULL) { - ck_destroy_table(&(*contents)->table, NULL, 0); - } -#endif knot_nsec3_params_free(&(*contents)->nsec3_params); - - knot_dname_table_free(&(*contents)->dname_table); free(*contents); *contents = NULL; @@ -2957,43 +2068,28 @@ void knot_zone_contents_free(knot_zone_contents_t **contents) /*----------------------------------------------------------------------------*/ -void knot_zone_contents_deep_free(knot_zone_contents_t **contents, - int destroy_dname_table) +void knot_zone_contents_deep_free(knot_zone_contents_t **contents) { if (contents == NULL || *contents == NULL) { return; } if ((*contents) != NULL) { - -#ifdef USE_HASH_TABLE - if ((*contents)->table != NULL) { - ck_destroy_table(&(*contents)->table, NULL, 0); - } -#endif /* has to go through zone twice, rdata may contain references to node owners earlier in the zone which may be already freed */ /* NSEC3 tree is deleted first as it may contain references to the normal tree. */ - knot_zone_tree_reverse_apply_postorder( + knot_zone_tree_apply_recursive( (*contents)->nsec3_nodes, knot_zone_contents_destroy_node_rrsets_from_tree, (void*)1); - knot_zone_tree_reverse_apply_postorder( - (*contents)->nsec3_nodes, - knot_zone_contents_destroy_node_owner_from_tree, 0); - - knot_zone_tree_reverse_apply_postorder( + knot_zone_tree_apply_recursive( (*contents)->nodes, knot_zone_contents_destroy_node_rrsets_from_tree, (void*)1); - knot_zone_tree_reverse_apply_postorder( - (*contents)->nodes, - knot_zone_contents_destroy_node_owner_from_tree, 0); - // free the zone tree, but only the structure // (nodes are already destroyed) dbg_zone("Destroying zone tree.\n"); @@ -3002,16 +2098,6 @@ void knot_zone_contents_deep_free(knot_zone_contents_t **contents, knot_zone_tree_free(&(*contents)->nsec3_nodes); knot_nsec3_params_free(&(*contents)->nsec3_params); - - if (destroy_dname_table) { - /* - * Hack, used in zcompile - destroys the table using - * dname_free() instead of dname_retain(). - */ - knot_dname_table_destroy(&(*contents)->dname_table); - } else { - knot_dname_table_deep_free(&(*contents)->dname_table); - } } free((*contents)); @@ -3040,7 +2126,7 @@ static void knot_zc_integrity_check_previous(const knot_node_t *node, // first, check if the previous and next pointers are set properly if (check_data->previous != NULL) { char *name_prev = knot_dname_to_str( - knot_node_owner(check_data->previous)); + knot_node_owner(check_data->previous)); if (knot_node_previous(node) != check_data->previous) { char *name2 = knot_dname_to_str(knot_node_owner( @@ -3066,8 +2152,8 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node, if (node == knot_zone_contents_apex(check_data->contents)) { if (!knot_node_is_auth(node)) { fprintf(stderr, "Wrong flags: node %s, flags: %u. " - "Should be non-authoritative.\n", name, - node->flags); + "Should be non-authoritative.\n", name, + node->flags); ++check_data->errors; } return; @@ -3076,12 +2162,12 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node, // check the flags if (check_data->deleg_point != NULL && knot_dname_is_subdomain(knot_node_owner(node), - knot_node_owner(check_data->deleg_point))) { + knot_node_owner(check_data->deleg_point))) { // this is a non-authoritative node if (!knot_node_is_non_auth(node)) { fprintf(stderr, "Wrong flags: node %s, flags: %u. " - "Should be non-authoritative.\n", name, - node->flags); + "Should be non-authoritative.\n", name, + node->flags); ++check_data->errors; } } else { @@ -3089,8 +2175,8 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node, // this is a delegation point if (!knot_node_is_deleg_point(node)) { fprintf(stderr, "Wrong flags: node %s, flags: " - "%u. Should be deleg. point.\n", name, - node->flags); + "%u. Should be deleg. point.\n", name, + node->flags); ++check_data->errors; } check_data->deleg_point = node; @@ -3098,8 +2184,8 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node, // this is an authoritative node if (!knot_node_is_auth(node)) { fprintf(stderr, "Wrong flags: node %s, flags: " - "%u. Should be authoritative.\n", name, - node->flags); + "%u. Should be authoritative.\n", name, + node->flags); ++check_data->errors; } check_data->deleg_point = NULL; @@ -3139,11 +2225,11 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node, const knot_node_t *parent = knot_node_parent(node); if (parent != check_data->parent) { char *name2 = (parent != NULL) - ? knot_dname_to_str( - knot_node_owner(parent)) - : "none"; + ? knot_dname_to_str( + knot_node_owner(parent)) + : "none"; fprintf(stderr, "Wrong parent: node %s, parent %s. " - " Should be %s\n", name, name2, pname); + " Should be %s\n", name, name2, pname); if (parent != NULL) { free(name2); } @@ -3157,14 +2243,14 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node, && knot_node_wildcard_child(check_data->parent) != node) { char *wc = (knot_node_wildcard_child( - check_data->parent) == NULL) + check_data->parent) == NULL) ? strdup("none") : knot_dname_to_str(knot_node_owner( - knot_node_wildcard_child( - check_data->parent))); + knot_node_wildcard_child( + check_data->parent))); fprintf(stderr, "Wrong wildcard child: node %s," - " wildcard child: %s. Should be %s\n", - pname, wc, name); + " wildcard child: %s. Should be %s\n", + pname, wc, name); if (knot_node_wildcard_child( check_data->parent) != NULL) { } @@ -3181,24 +2267,6 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node, /*----------------------------------------------------------------------------*/ -static void knot_zc_integrity_check_rrset_count(const knot_node_t *node, - check_data_t *check_data, - const char *name) -{ - // count RRSets - int real_count = knot_node_count_rrsets(node); - int count = knot_node_rrset_count(node); - - if (count != real_count) { - fprintf(stderr, "Wrong RRSet count: node %s, count %d. " - "Should be %d\n", name, count, real_count); - - ++check_data->errors; - } -} - -/*----------------------------------------------------------------------------*/ - typedef struct find_dname_data { const knot_dname_t *to_find; const knot_dname_t *found; @@ -3206,132 +2274,25 @@ typedef struct find_dname_data { /*----------------------------------------------------------------------------*/ -void find_in_dname_table(knot_dname_t *dname, void *data) -{ - assert(dname != NULL); - assert(data != NULL); - - find_dname_data_t *fdata = (find_dname_data_t *)data; - - if (fdata->found != NULL) { - return; - } - - if (knot_dname_compare(dname, fdata->to_find) == 0) { - fdata->found = dname; - } -} - -/*----------------------------------------------------------------------------*/ - -static int knot_zc_integrity_check_find_dname(const knot_zone_contents_t *zone, - const knot_dname_t *to_find, - const char *node_name) -{ - int ret = 0; - if (!zone || !to_find || !node_name) { - return KNOT_EINVAL; - } - - knot_dname_t *found = knot_dname_table_find_dname(zone->dname_table, - (knot_dname_t *)to_find); - - char *to_find_name = knot_dname_to_str(to_find); - - if (!found || found != to_find) { - fprintf(stderr, "Dname not stored in dname table: " - "node %s, name %s, found some dname: %s\n", node_name, - to_find_name, (found != NULL) ? "yes" : "no"); - fprintf(stderr, "Dname to find: %p, found dname: %p\n", - found, to_find); - ret = 1; - } - - free(to_find_name); - - knot_dname_release(found); - - return ret; -} - -/*----------------------------------------------------------------------------*/ - static void knot_zc_integrity_check_owner(const knot_node_t *node, check_data_t *check_data, const char *name) { // check node stored in owner const knot_node_t *owner_node = - knot_dname_node(knot_node_owner(node)); + knot_dname_node(knot_node_owner(node)); if (owner_node != node) { char *name2 = (owner_node != NULL) - ? knot_dname_to_str(knot_node_owner(owner_node)) - : "none"; + ? knot_dname_to_str(knot_node_owner(owner_node)) + : "none"; fprintf(stderr, "Wrong owner's node: node %s, owner's node %s" - "\n", name, name2); + "\n", name, name2); if (owner_node != NULL) { free(name2); } ++check_data->errors; } - - // check if the owner is stored in dname table - check_data->errors += knot_zc_integrity_check_find_dname( - check_data->contents, knot_node_owner(node), name); -} - -/*----------------------------------------------------------------------------*/ - -static void knot_zc_integrity_check_dnames_in_rrset(const knot_rrset_t *rrset, - check_data_t *check_data, - const char *name) -{ - // check owner of the RRSet - check_data->errors += knot_zc_integrity_check_find_dname( - check_data->contents, - knot_rrset_owner(rrset), name); - - knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type( - knot_rrset_type(rrset)); - - assert(desc != NULL); - - const knot_rdata_t *rdata = knot_rrset_rdata(rrset); - while (rdata != NULL) { - for (int i = 0; i < knot_rdata_item_count(rdata); ++i) { - if (desc->wireformat[i] - == KNOT_RDATA_WF_COMPRESSED_DNAME - || desc->wireformat[i] - == KNOT_RDATA_WF_UNCOMPRESSED_DNAME - || desc->wireformat[i] - == KNOT_RDATA_WF_LITERAL_DNAME) { - knot_rdata_item_t *item = knot_rdata_get_item( - rdata, i); - check_data->errors += - knot_zc_integrity_check_find_dname( - check_data->contents, item->dname, name); - } - } - rdata = knot_rrset_rdata_next(rrset, rdata); - } -} - -/*----------------------------------------------------------------------------*/ - -static void knot_zc_integrity_check_dnames(const knot_node_t *node, - check_data_t *check_data, - const char *name) -{ - // check all dnames in all RRSets - both owners and in RDATA - const knot_rrset_t **rrsets = knot_node_rrsets(node); - if (rrsets != NULL) { - for (int i = 0; i < knot_node_rrset_count(node); ++i) { - knot_zc_integrity_check_dnames_in_rrset(rrsets[i], - check_data, name); - } - } - free(rrsets); } /*----------------------------------------------------------------------------*/ @@ -3356,15 +2317,9 @@ static void knot_zc_integrity_check_node(knot_node_t *node, void *data) // & wildcard child knot_zc_integrity_check_parent(node, check_data, name); - // check RRSet count - knot_zc_integrity_check_rrset_count(node, check_data, name); - // check owner knot_zc_integrity_check_owner(node, check_data, name); - // check dnames - knot_zc_integrity_check_dnames(node, check_data, name); - /*! \todo Check NSEC3 node. */ free(name); @@ -3390,74 +2345,70 @@ static void knot_zc_integrity_check_nsec3(knot_node_t *node, void *data) // check if the node is child of the zone apex if (node->parent != check_data->parent) { fprintf(stderr, "NSEC3 node's parent is not apex. Node: %s.\n", - name); + name); ++check_data->errors; } - // check RRSet count - knot_zc_integrity_check_rrset_count(node, check_data, name); - // check owner knot_zc_integrity_check_owner(node, check_data, name); - // check dnames - knot_zc_integrity_check_dnames(node, check_data, name); - free(name); } /*----------------------------------------------------------------------------*/ -void reset_child_count(knot_zone_tree_node_t *tree_node, void *data) +void reset_child_count(knot_node_t **tnode, void *data) { - assert(tree_node != NULL); + assert(tnode != NULL); assert(data != NULL); + knot_node_t *node = *tnode; knot_node_t **apex_copy = (knot_node_t **)data; if (*apex_copy == NULL) { - *apex_copy = tree_node->node; + *apex_copy = node; } - if (tree_node->node != NULL) { - tree_node->node->children = 0; + if (tnode != NULL) { + node->children = 0; } } /*----------------------------------------------------------------------------*/ -void count_children(knot_zone_tree_node_t *tree_node, void *data) +void count_children(knot_node_t **tnode, void *data) { UNUSED(data); - if (tree_node->node != NULL && tree_node->node->parent != NULL) { - assert(tree_node->node->parent->new_node != NULL); + knot_node_t *node = *tnode; + if (node != NULL && node->parent != NULL) { + assert(node->parent->new_node != NULL); // fix parent pointer - tree_node->node->parent = tree_node->node->parent->new_node; - ++tree_node->node->parent->children; + node->parent = node->parent->new_node; + ++node->parent->children; } } /*----------------------------------------------------------------------------*/ -void check_child_count(knot_zone_tree_node_t *tree_node, void *data) +void check_child_count(knot_node_t **tnode, void *data) { - assert(tree_node != NULL); + assert(tnode != NULL); assert(data != NULL); check_data_t *check_data = (check_data_t *)data; - knot_node_t *node = tree_node->node; + knot_node_t *node = *tnode; // find corresponding node in the given contents const knot_node_t *found = NULL; found = knot_zone_contents_find_node(check_data->contents, - knot_node_owner(node)); + knot_node_owner(node)); assert(found != NULL); if (knot_node_children(node) != knot_node_children(found)) { char *name = knot_dname_to_str(knot_node_owner(node)); fprintf(stderr, "Wrong children count: node (%p) %s, count %u. " - "Should be %u (%p)\n", found, name, - knot_node_children(found), - knot_node_children(node), node); + "Should be %u (%p)\n", found, name, + knot_node_children(found), + knot_node_children(node), node); free(name); ++check_data->errors; @@ -3466,26 +2417,25 @@ void check_child_count(knot_zone_tree_node_t *tree_node, void *data) /*----------------------------------------------------------------------------*/ -static void reset_new_nodes(knot_zone_tree_node_t *tree_node, void *data) +static void reset_new_nodes(knot_node_t **tnode, void *data) { - assert(tree_node != NULL); + assert(tnode != NULL); UNUSED(data); - knot_node_t *node = tree_node->node; + knot_node_t *node = *tnode; knot_node_set_new_node(node, NULL); } /*----------------------------------------------------------------------------*/ -static void count_nsec3_nodes(knot_zone_tree_node_t *tree_node, void *data) +static void count_nsec3_nodes(knot_node_t **tnode, void *data) { - assert(tree_node != NULL); - assert(tree_node->node != NULL); + assert(tnode != NULL); assert(data != NULL); knot_node_t *apex = (knot_node_t *)data; assert(apex != NULL); - + apex->children += 1; } @@ -3496,44 +2446,40 @@ int knot_zc_integrity_check_child_count(check_data_t *data) int errors = 0; // do shallow copy of the node tree - knot_zone_tree_t *nodes_copy = (knot_zone_tree_t *) - malloc(sizeof(knot_zone_tree_t)); + knot_zone_tree_t *nodes_copy = NULL; + + int ret = knot_zone_tree_deep_copy(data->contents->nodes, &nodes_copy); + assert(ret == KNOT_EOK); if (nodes_copy == NULL) { return 1; } - knot_zone_tree_init(nodes_copy); - - int ret = knot_zone_tree_deep_copy(data->contents->nodes, nodes_copy); - assert(ret == KNOT_EOK); - - // set children count of all nodes to 0 // in the same walkthrough find the apex knot_node_t *apex_copy = NULL; - knot_zone_tree_forward_apply_inorder(nodes_copy, reset_child_count, - (void *)&apex_copy); + knot_zone_tree_apply_inorder(nodes_copy, reset_child_count, + (void *)&apex_copy); assert(apex_copy != NULL); // now count children of all nodes, presuming the parent pointers are ok - knot_zone_tree_forward_apply_inorder(nodes_copy, count_children, NULL); + knot_zone_tree_apply_inorder(nodes_copy, count_children, NULL); // add count of NSEC3 nodes to the apex' children count fprintf(stderr, "Children count of new apex before NSEC3: %d\n", - data->contents->apex->new_node->children); - knot_zone_tree_forward_apply_inorder(data->contents->nsec3_nodes, - count_nsec3_nodes, - (void *)apex_copy); + data->contents->apex->new_node->children); + knot_zone_tree_apply_inorder(data->contents->nsec3_nodes, + count_nsec3_nodes, + (void *)apex_copy); // now compare the children counts // iterate over the old zone and search for nodes in the copy - knot_zone_tree_forward_apply_inorder(nodes_copy, check_child_count, - (void *)data); + knot_zone_tree_apply_inorder(nodes_copy, check_child_count, + (void *)data); // cleanup old zone tree - reset pointers to new node to NULL - knot_zone_tree_forward_apply_inorder(data->contents->nodes, - reset_new_nodes, NULL); + knot_zone_tree_apply_inorder(data->contents->nodes, + reset_new_nodes, NULL); // destroy the shallow copy knot_zone_tree_deep_free(&nodes_copy); @@ -3570,8 +2516,8 @@ int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents) data.contents = contents; int ret = knot_zone_contents_tree_apply_inorder( - (knot_zone_contents_t *)contents, - knot_zc_integrity_check_node, (void *)&data); + (knot_zone_contents_t *)contents, + knot_zc_integrity_check_node, (void *)&data); assert(ret == KNOT_EOK); // if OK, we can continue with checking children count @@ -3585,10 +2531,74 @@ int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents) data.children = 0; data.parent = contents->apex; ret = knot_zone_contents_nsec3_apply_inorder( - (knot_zone_contents_t *)contents, - knot_zc_integrity_check_nsec3, (void *)&data); + (knot_zone_contents_t *)contents, + knot_zc_integrity_check_nsec3, (void *)&data); assert(ret == KNOT_EOK); return data.errors; } +struct dname_lookup_data { + const knot_dname_t *dname; + const knot_dname_t *found_dname; + int stopped; +}; + +static void find_dname_in_rdata(knot_node_t **tnode, void *data) +{ + struct dname_lookup_data *in_data = (struct dname_lookup_data *)data; + if (in_data->stopped) { + return; + } + + /* For all RRSets in node. */ + const knot_rrset_t **rrsets = knot_node_rrsets_no_copy(*tnode); + if (rrsets == NULL) { + return; + } + + for (uint16_t i = 0; i < (*tnode)->rrset_count; i++) { + knot_dname_t **dname = NULL; + while ((dname = knot_rrset_get_next_dname(rrsets[i], dname))) { + if (*dname == in_data->dname) { + in_data->found_dname = *dname; + in_data->stopped = 1; + return; + } else if (knot_dname_compare(*dname, + in_data->dname) == 0) { + in_data->found_dname = *dname; + in_data->stopped = 1; + return; + } + } + } + + assert(in_data->stopped == 0); +} + +const knot_dname_t *knot_zone_contents_find_dname_in_rdata( + const knot_zone_contents_t *zone, + const knot_dname_t *dname) +{ + struct dname_lookup_data data; + data.stopped = 0; + data.dname = dname; + data.found_dname = NULL; + knot_zone_tree_apply_inorder(zone->nodes, + find_dname_in_rdata, &data); + if (data.stopped) { + /* Dname found. */ + return data.found_dname; + } else { + assert(data.found_dname == NULL); + return NULL; + } +} + +unsigned knot_zone_serial(const knot_zone_contents_t *zone) +{ + if (!zone) return 0; + const knot_rrset_t *soa = NULL; + soa = knot_node_rrset(knot_zone_contents_apex(zone), KNOT_RRTYPE_SOA); + return knot_rrset_rdata_soa_serial(soa); +} |