diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c index 89420c2353a686db7e229ea7d38d6fc1187ef6e5..989ef30e833473868a8967afa030b791b132efd5 100644 --- a/src/knot/nameserver/internet.c +++ b/src/knot/nameserver/internet.c @@ -468,10 +468,17 @@ static int name_not_found(knot_pkt_t *pkt, struct query_data *qdata) dbg_ns("%s(%p, %p)\n", __func__, pkt, qdata); /* Name is covered by wildcard. */ - const knot_node_t *wildcard_node = knot_node_wildcard_child(qdata->encloser); - if (wildcard_node) { + if (knot_node_has_wildcard_child(qdata->encloser)) { dbg_ns("%s: name %p covered by wildcard\n", __func__, qdata->name); + + /* Find wildcard child in the zone. */ + const knot_node_t *wildcard_node = + knot_zone_contents_find_wildcard_child( + qdata->zone->contents, qdata->encloser); + qdata->node = wildcard_node; + assert(qdata->node != NULL); + /* keep encloser */ qdata->previous = NULL; @@ -480,7 +487,7 @@ static int name_not_found(knot_pkt_t *pkt, struct query_data *qdata) /* Put to wildcard node list. */ if (wildcard_visit(qdata, wildcard_node, qdata->name) != KNOT_EOK) { - next_state = ERROR; + next_state = ERROR; } return next_state; diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c index 170055c7bbaec71ef2bb238f993f7e47aed7fe84..5ff46af34d7b8f85ac7271219d8479564f5a4ac9 100644 --- a/src/knot/updates/xfr-in.c +++ b/src/knot/updates/xfr-in.c @@ -987,8 +987,9 @@ static int xfrin_mark_empty(knot_node_t **node_p, void *data) } knot_node_set_empty(node); if (node->parent) { - if (node->parent->wildcard_child == node) { - node->parent->wildcard_child = NULL; + if (knot_node_has_wildcard_child(node->parent) + && knot_dname_is_wildcard(node->owner)) { + knot_node_clear_wildcard_child(node->parent); } node->parent->children--; // Recurse using the parent node diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c index a27c351aba63b67d1fdc11f8e876525ab4340f19..76291fb011831ab47d931753b169f16481d9c95e 100644 --- a/src/knot/zone/node.c +++ b/src/knot/zone/node.c @@ -377,37 +377,27 @@ knot_dname_t *knot_node_get_owner(const knot_node_t *node) /*----------------------------------------------------------------------------*/ -knot_node_t *knot_node_get_wildcard_child(const knot_node_t *node) +void knot_node_set_wildcard_child(knot_node_t *node) { if (node == NULL) { - return NULL; + return; } - return node->wildcard_child; + knot_node_flags_set(node, KNOT_NODE_FLAGS_WILDCARD_CHILD); } /*----------------------------------------------------------------------------*/ -void knot_node_set_wildcard_child(knot_node_t *node, - knot_node_t *wildcard_child) +int knot_node_has_wildcard_child(const knot_node_t *node) { - if (node == NULL) { - return; - } - - node->wildcard_child = wildcard_child; -// assert(wildcard_child->parent == node); + return knot_node_flags_get(node, KNOT_NODE_FLAGS_WILDCARD_CHILD); } /*----------------------------------------------------------------------------*/ -const knot_node_t *knot_node_wildcard_child(const knot_node_t *node) +void knot_node_clear_wildcard_child(knot_node_t *node) { - if (node == NULL) { - return NULL; - } - - return knot_node_get_wildcard_child(node); + knot_node_flags_clear(node, KNOT_NODE_FLAGS_WILDCARD_CHILD); } /*----------------------------------------------------------------------------*/ @@ -641,4 +631,3 @@ bool knot_node_rrtype_exists(const knot_node_t *node, uint16_t type) { return knot_node_rrs(node, type) != NULL; } - diff --git a/src/knot/zone/node.h b/src/knot/zone/node.h index 22f8c859b3666201bee38ca767e61c285e342447..a18fefe8008bf5aed946aa68068a0d835aaf10a7 100644 --- a/src/knot/zone/node.h +++ b/src/knot/zone/node.h @@ -48,9 +48,6 @@ struct knot_node { /*! \brief Type-ordered array of RRSets belonging to this node. */ struct rr_data *rrs; - /*! \brief Wildcard node being the direct descendant of this node. */ - struct knot_node *wildcard_child; - /*! * \brief Previous node in canonical order. * @@ -75,10 +72,7 @@ struct knot_node { /*! * \brief Various flags. * - * 0x01 - node is a delegation point - * 0x02 - node is non-authoritative (under a delegation point) - * 0x04 - NSEC(3) was removed from the node. - * 0x10 - node is empty and will be deleted after update + * \ref knot_node_flags_t */ uint8_t flags; }; @@ -106,6 +100,8 @@ typedef enum { /*! \brief Node is empty and will be deleted after update. * \todo Remove after dname refactoring, update description in node. */ KNOT_NODE_FLAGS_EMPTY = 1 << 4, + /*! \brief Node has a wildcard child. */ + KNOT_NODE_FLAGS_WILDCARD_CHILD = 1 << 5 } knot_node_flags_t; /*----------------------------------------------------------------------------*/ @@ -260,29 +256,37 @@ void knot_node_set_nsec3_node(knot_node_t *node, knot_node_t *nsec3_node); const knot_dname_t *knot_node_owner(const knot_node_t *node); /*! - * \todo Document me. + * \brief Returns the owner of the node as a non-const reference. + * + * \param node Node to get the owner of. + * + * \return Owner of the given node. */ knot_dname_t *knot_node_get_owner(const knot_node_t *node); /*! - * \brief Returns the wildcard child of the node. - * - * \param node Node to get the owner of. + * \brief Sets the wildcard child flag of the node. * - * \return Wildcard child of the given node or NULL if it has none. + * \param node Node that has wildcard. */ -const knot_node_t *knot_node_wildcard_child(const knot_node_t *node); +void knot_node_set_wildcard_child(knot_node_t *node); /*! - * \brief Sets the wildcard child of the node. + * \brief Checks if node has a wildcard child. * - * \param node Node to set the wildcard child of. - * \param wildcard_child Wildcard child of the node. + * \param node Node to check. + * + * \retval > 0 if the node has a wildcard child. + * \retval 0 otherwise. */ -void knot_node_set_wildcard_child(knot_node_t *node, - knot_node_t *wildcard_child); +int knot_node_has_wildcard_child(const knot_node_t *node); -knot_node_t *knot_node_get_wildcard_child(const knot_node_t *node); +/*! + * \brief Clears the node's wildcard child flag. + * + * \param node Node to clear the flag in. + */ +void knot_node_clear_wildcard_child(knot_node_t *node); /*! * \brief Mark the node as a delegation point. diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index b80f4bd33286a40dbc19009832e75f2bfecf910b..6fee227fc8dc9a9c7365ad682b50b3505e53ecd1 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -304,9 +304,6 @@ static int check_rrsig_rdata(err_handler_t *handler, } if (knot_rrsig_type_covered(rrsig, 0) != rrset->type) { - /* zoneparser would not let this happen - * but to be on the safe side - */ err_handler_handle_error(handler, node, ZC_ERR_RRSIG_RDATA_TYPE_COVERED, info_str); @@ -1092,9 +1089,6 @@ void log_cyclic_errors_in_zone(err_handler_t *handler, /* Check it points somewhere first. */ if (knot_zone_contents_find_nsec3_node(zone, next_dname) == NULL) { - assert(knot_zone_contents_find_node(zone, - next_dname) == - NULL); err_handler_handle_error(handler, last_nsec3_node, ZC_ERR_NSEC3_RDATA_CHAIN, NULL); } else { @@ -1108,9 +1102,9 @@ void log_cyclic_errors_in_zone(err_handler_t *handler, /* Directly discard. */ knot_dname_free(&next_dname, NULL); - } else if (do_checks == 2 ) { + } else if (do_checks == SEM_CHECK_NSEC) { if (last_node == NULL) { - err_handler_handle_error(handler, last_node, + err_handler_handle_error(handler, zone->apex, ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC, NULL); return; } else { diff --git a/src/knot/zone/zone-contents.c b/src/knot/zone/zone-contents.c index 867b578f55078f9940c05747a702515731d1f9bc..b0fea95a56665c13f9e654d390dcab042a4df444 100644 --- a/src/knot/zone/zone-contents.c +++ b/src/knot/zone/zone-contents.c @@ -178,8 +178,12 @@ static int discover_additionals(struct rr_data *rr_data, /* Try to find node for the dname in the RDATA. */ dname = knot_rdata_name(rrs, i, rr_data->type); knot_zone_contents_find_dname(zone, dname, &node, &encloser, &prev); - if (node == NULL && encloser && encloser->wildcard_child) { - node = encloser->wildcard_child; + if (node == NULL && encloser + && knot_node_has_wildcard_child(encloser)) { + /* Find wildcard child in the zone. */ + node = knot_zone_contents_find_wildcard_child(zone, + encloser); + assert(node != NULL); } rr_data->additional[i] = (knot_node_t *)node; @@ -203,11 +207,14 @@ static int adjust_pointers(knot_node_t **tnode, void *data) args->first_node = node; } + // clear Removed NSEC flag so that no relicts remain + knot_node_clear_removed_nsec(node); + // check if this node is not a wildcard child of its parent if (knot_dname_is_wildcard(knot_node_owner(node))) { assert(knot_node_parent(node) != NULL); - knot_node_set_wildcard_child(knot_node_get_parent(node), node); + knot_node_set_wildcard_child(knot_node_get_parent(node)); } // set flags (delegation point, non-authoritative) @@ -554,7 +561,7 @@ dbg_zone_exec_detail( // check if the node is not wildcard child of the parent if (knot_dname_is_wildcard(knot_node_owner(node))) { - knot_node_set_wildcard_child(zone->apex, node); + knot_node_set_wildcard_child(zone->apex); } } else { while (parent != NULL && @@ -578,7 +585,7 @@ dbg_zone_exec_detail( /* Update node pointers. */ knot_node_set_parent(node, next_node); if (knot_dname_is_wildcard(knot_node_owner(node))) { - knot_node_set_wildcard_child(next_node, node); + knot_node_set_wildcard_child(next_node); } ++zone->node_count; @@ -1122,6 +1129,20 @@ const knot_node_t *knot_zone_contents_apex( /*----------------------------------------------------------------------------*/ +const knot_node_t *knot_zone_contents_find_wildcard_child( + const knot_zone_contents_t *contents, const knot_node_t *parent) +{ + if (contents == NULL || parent == NULL || parent->owner == NULL) { + return NULL; + } + + knot_dname_t wildcard[KNOT_DNAME_MAXLEN] = { 0x01, '*' }; + knot_dname_to_wire(wildcard + 2, parent->owner, KNOT_DNAME_MAXLEN - 2); + return knot_zone_contents_find_node(contents, wildcard); +} + +/*----------------------------------------------------------------------------*/ + static int knot_zone_contents_adjust_nodes(knot_zone_tree_t *nodes, knot_zone_adjust_arg_t *adjust_arg, knot_zone_tree_apply_cb_t callback) diff --git a/src/knot/zone/zone-contents.h b/src/knot/zone/zone-contents.h index 01ed95c234061b3de57c9f1a3d7e4db88d06e9a5..f25c8c3e3b2801a9e22a63b2cb2bb16ba668377b 100644 --- a/src/knot/zone/zone-contents.h +++ b/src/knot/zone/zone-contents.h @@ -198,6 +198,9 @@ int knot_zone_contents_find_nsec3_for_name( const knot_node_t *knot_zone_contents_apex( const knot_zone_contents_t *contents); +const knot_node_t *knot_zone_contents_find_wildcard_child( + const knot_zone_contents_t *contents, const knot_node_t *parent); + /*! * \brief Sets parent and previous pointers and node flags. (cheap operation) * For both normal and NSEC3 tree diff --git a/src/knot/zone/zone-create.c b/src/knot/zone/zone-create.c index 0a76151bbabcd3ef08a32320778b85885fa3534e..7c12851ca09c32cb774ff687a0db39b180d0fcf6 100644 --- a/src/knot/zone/zone-create.c +++ b/src/knot/zone/zone-create.c @@ -289,7 +289,7 @@ knot_zone_contents_t *zonefile_load(zloader_t *loader) assert(!knot_rrset_empty(&soa_rr)); // In this point, SOA has to exist const bool have_nsec3param = knot_node_rrtype_exists(zc->z->apex, KNOT_RRTYPE_NSEC3PARAM); - if (knot_zone_contents_is_signed(zc->z) && have_nsec3param) { + if (knot_zone_contents_is_signed(zc->z) && !have_nsec3param) { /* Set check level to DNSSEC. */ check_level = SEM_CHECK_NSEC; } else if (knot_zone_contents_is_signed(zc->z) && have_nsec3param) { diff --git a/tests-extra/tools/dnstest/server.py b/tests-extra/tools/dnstest/server.py index 87d1d3b37b851ffe7827e359faea681b1bd819d5..c1254f53d6c7ec96d4403c43ccb8cb72931c7311 100644 --- a/tests-extra/tools/dnstest/server.py +++ b/tests-extra/tools/dnstest/server.py @@ -878,6 +878,7 @@ class Knot(Server): s.item("zonefile-sync", "0") s.item("notify-timeout", "5") s.item("notify-retries", "5") + s.item("semantic-checks", "on") if self.disable_any: s.item("disable-any", "on") if self.dnssec_enable: