diff options
Diffstat (limited to 'src/knot/zone/contents.h')
-rw-r--r-- | src/knot/zone/contents.h | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/knot/zone/contents.h b/src/knot/zone/contents.h new file mode 100644 index 0000000..8f1f160 --- /dev/null +++ b/src/knot/zone/contents.h @@ -0,0 +1,291 @@ +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "libdnssec/nsec.h" +#include "libknot/rrtype/nsec3param.h" +#include "knot/zone/node.h" +#include "knot/zone/zone-tree.h" + +enum zone_contents_find_dname_result { + ZONE_NAME_NOT_FOUND = 0, + ZONE_NAME_FOUND = 1 +}; + +typedef struct zone_contents { + zone_node_t *apex; /*!< Apex node of the zone (holding SOA) */ + + zone_tree_t *nodes; + zone_tree_t *nsec3_nodes; + + trie_t *adds_tree; // "additionals tree" for reverse lookup of nodes affected by additionals + + dnssec_nsec3_params_t nsec3_params; + size_t size; + uint32_t max_ttl; + bool dnssec; +} zone_contents_t; + +/*! + * \brief Allocate and create new zone contents. + * + * \param apex_name Name of the root node. + * \param use_binodes Zone trees shall consist of bi-nodes to enable zone updates. + * + * \return New contents or NULL on error. + */ +zone_contents_t *zone_contents_new(const knot_dname_t *apex_name, bool use_binodes); + +/*! + * \brief Returns zone tree for inserting given RR. + */ +zone_tree_t *zone_contents_tree_for_rr(zone_contents_t *contents, const knot_rrset_t *rr); + +/*! + * \brief Add an RR to contents. + * + * \param z Contents to add to. + * \param rr The RR to add. + * \param n Node to which the RR has been added to on success, unchanged otherwise. + * + * \return KNOT_E* + */ +int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n); + +/*! + * \brief Remove an RR from contents. + * + * \param z Contents to remove from. + * \param rr The RR to remove. + * \param n Node from which the RR to be removed from on success, unchanged otherwise. + * + * \return KNOT_E* + */ +int zone_contents_remove_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n); + +/*! + * \brief Tries to find a node with the specified name in the zone. + * + * \param contents Zone where the name should be searched for. + * \param name Name to find. + * + * \return Corresponding node if found, NULL otherwise. + */ +const zone_node_t *zone_contents_find_node(const zone_contents_t *contents, const knot_dname_t *name); + +/*! + * \brief Tries to find a node in the zone, also searching in NSEC3 tree. + * + * \param zone Zone where the name should be searched for. + * \param name Name to find. + * + * \return Normal or NSEC3 node, or NULL. + */ +const zone_node_t *zone_contents_node_or_nsec3(const zone_contents_t *zone, const knot_dname_t *name); + +/*! + * \brief Find a node in which the given rrset may be inserted, + * + * \param contents Zone contents. + * \param rrset RRSet to be inserted later. + * + * \return Existing node in zone which the RRSet may be inserted in; or NULL if none present. + */ +zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *contents, const knot_rrset_t *rrset); + +/*! + * \brief Tries to find a node by owner in the zone contents. + * + * \param[in] contents Zone to search for the name. + * \param[in] name Domain name to search for. + * \param[out] match Matching node or NULL. + * \param[out] closest Closest matching name in the zone. + * May match \a match if found exactly. + * \param[out] previous Previous domain name in canonical order. + * Always previous, won't match \a match. + * + * \note The encloser and previous mustn't be used directly for DNSSEC proofs. + * These nodes may be empty non-terminals or not authoritative. + * + * \retval ZONE_NAME_FOUND if node with owner \a name was found. + * \retval ZONE_NAME_NOT_FOUND if it was not found. + * \retval KNOT_EEMPTYZONE + * \retval KNOT_EINVAL + * \retval KNOT_EOUTOFZONE + */ +int zone_contents_find_dname(const zone_contents_t *contents, + const knot_dname_t *name, + const zone_node_t **match, + const zone_node_t **closest, + const zone_node_t **previous); + +/*! + * \brief Tries to find a node with the specified name among the NSEC3 nodes + * of the zone. + * + * \param contents Zone where the name should be searched for. + * \param name Name to find. + * + * \return Corresponding node if found, NULL otherwise. + */ +const zone_node_t *zone_contents_find_nsec3_node(const zone_contents_t *contents, + const knot_dname_t *name); + +/*! + * \brief Finds NSEC3 node and previous NSEC3 node in canonical order, + * corresponding to the given domain name. + * + * This functions creates a NSEC3 hash of \a name and tries to find NSEC3 node + * with the hashed domain name as owner. + * + * \param[in] contents Zone to search in. + * \param[in] name Domain name to get the corresponding NSEC3 nodes for. + * \param[out] nsec3_node NSEC3 node corresponding to \a name (if found, + * otherwise this may be an arbitrary NSEC3 node). + * \param[out] nsec3_previous The NSEC3 node immediately preceding hashed domain + * name corresponding to \a name in canonical order. + * + * \retval ZONE_NAME_FOUND if the corresponding NSEC3 node was found. + * \retval ZONE_NAME_NOT_FOUND if it was not found. + * \retval KNOT_EEMPTYZONE + * \retval KNOT_EINVAL + * \retval KNOT_ENSEC3PAR + * \retval KNOT_ECRYPTO + * \retval KNOT_ERROR + */ +int zone_contents_find_nsec3_for_name(const zone_contents_t *contents, + const knot_dname_t *name, + const zone_node_t **nsec3_node, + const zone_node_t **nsec3_previous); + +/*! + * \brief Finds NSEC3 node and previous NSEC3 node to specified NSEC3 name. + * + * Like previous function, but the NSEC3 hashed-name is already known. + * + * \param zone Zone contents to search in, + * \param nsec3_name NSEC3 name to be searched for. + * \param nsec3_node Out: NSEC3 node found. + * \param nsec3_previous Out: previous NSEC3 node. + * + * \return ZONE_NAME_FOUND, ZONE_NAME_NOT_FOUND, KNOT_E* + */ +int zone_contents_find_nsec3(const zone_contents_t *zone, + const knot_dname_t *nsec3_name, + const zone_node_t **nsec3_node, + const zone_node_t **nsec3_previous); + +/*! + * \brief For specified node, give a wildcard child if exists in zone. + * + * \param contents Zone contents. + * \param parent Given parent node. + * + * \return Node being a wildcard child; or NULL. + */ +const zone_node_t *zone_contents_find_wildcard_child(const zone_contents_t *contents, + const zone_node_t *parent); + +/*! + * \brief For given name, find either exactly matching node in zone, or a matching wildcard node. + * + * \param contents Zone contents to be searched in. + * \param find Name to be searched for. + * \param found Out: a node that either has owner "find" or is matching wildcard node. + * + * \return true iff found something + */ +bool zone_contents_find_node_or_wildcard(const zone_contents_t *contents, + const knot_dname_t *find, + const zone_node_t **found); + +/*! + * \brief Applies the given function to each regular node in the zone. + * + * \param contents Nodes of this zone will be used as parameters for the function. + * \param function Function to be applied to each node of the zone. + * \param data Arbitrary data to be passed to the function. + */ +int zone_contents_apply(zone_contents_t *contents, + zone_tree_apply_cb_t function, void *data); + +/*! + * \brief Applies the given function to each NSEC3 node in the zone. + * + * \param contents NSEC3 nodes of this zone will be used as parameters for the + * function. + * \param function Function to be applied to each node of the zone. + * \param data Arbitrary data to be passed to the function. + */ +int zone_contents_nsec3_apply(zone_contents_t *contents, + zone_tree_apply_cb_t function, void *data); + +/*! + * \brief Create new zone_contents by COW copy of zone trees. + * + * \param from Original zone. + * \param to Copy of the zone. + * + * \retval KNOT_EOK + * \retval KNOT_EEMPTYZONE + * \retval KNOT_EINVAL + * \retval KNOT_ENOMEM + */ +int zone_contents_cow(zone_contents_t *from, zone_contents_t **to); + +/*! + * \brief Deallocate directly owned data of zone contents. + * + * \param contents Zone contents to free. + */ +void zone_contents_free(zone_contents_t *contents); + +/*! + * \brief Deallocate node RRSets inside the trees, then call zone_contents_free. + * + * \param contents Zone contents to free. + */ +void zone_contents_deep_free(zone_contents_t *contents); + +/*! + * \brief Fetch zone serial. + * + * \param zone Zone. + * + * \return serial or 0 + */ +uint32_t zone_contents_serial(const zone_contents_t *zone); + +/*! + * \brief Adjust zone serial. + * + * Works only if there is a SOA in given contents. + * + * \param zone Zone. + * \param new_serial New serial to be set. + */ +void zone_contents_set_soa_serial(zone_contents_t *zone, uint32_t new_serial); + +/*! + * \brief Load parameters from NSEC3PARAM record into contents->nsec3param structure. + */ +int zone_contents_load_nsec3param(zone_contents_t *contents); + +/*! + * \brief Return true if zone is empty. + */ +bool zone_contents_is_empty(const zone_contents_t *zone); |