summaryrefslogtreecommitdiff
path: root/src/libknot/zone/zone-contents.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libknot/zone/zone-contents.h')
-rw-r--r--src/libknot/zone/zone-contents.h556
1 files changed, 556 insertions, 0 deletions
diff --git a/src/libknot/zone/zone-contents.h b/src/libknot/zone/zone-contents.h
new file mode 100644
index 0000000..2856f76
--- /dev/null
+++ b/src/libknot/zone/zone-contents.h
@@ -0,0 +1,556 @@
+/*!
+ * \file zone-contents.h
+ *
+ * \author Lubos Slovak <lubos.slovak@nic.cz>
+ *
+ * \brief Zone contents structure and API for manipulating it.
+ *
+ * \addtogroup libknot
+ * @{
+ */
+/* Copyright (C) 2011 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _KNOT_ZONE_CONTENTS_H_
+#define _KNOT_ZONE_CONTENTS_H_
+
+//#include <time.h>
+
+#include "zone/node.h"
+#include "dname.h"
+#include "nsec3.h"
+#include "zone/dname-table.h"
+#include "common/tree.h"
+#include "hash/cuckoo-hash-table.h"
+
+#include "zone-tree.h"
+
+struct knot_zone;
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct knot_zone_contents_t {
+ knot_node_t *apex; /*!< Apex node of the zone (holding SOA) */
+
+ ck_hash_table_t *table; /*!< Hash table for holding zone nodes. */
+ knot_zone_tree_t *nodes;
+ knot_zone_tree_t *nsec3_nodes;
+
+ /*!
+ * \todo Unify the use of this field - authoritative nodes vs. all.
+ */
+ uint node_count;
+
+ knot_dname_table_t *dname_table;
+
+ knot_nsec3_params_t nsec3_params;
+
+ /*! \brief Generation of the zone during update.
+ *
+ * Possible values:
+ * - 0 - Original version of the zone. Old nodes should be used.
+ * - 1 - New (updated) zone. New nodes should be used.
+ * - -1 - New (updated) zone, but exactly the stored nodes should be
+ * used, no matter their generation.
+ */
+ short generation;
+
+ struct knot_zone *zone;
+} knot_zone_contents_t;
+
+/*----------------------------------------------------------------------------*/
+
+knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
+ uint node_count,
+ int use_domain_table,
+ struct knot_zone *zone);
+
+time_t knot_zone_contents_version(const knot_zone_contents_t *contents);
+
+void knot_zone_contents_set_version(knot_zone_contents_t *contents,
+ time_t version);
+
+//short knot_zone_contents_generation(const knot_zone_contents_t *contents);
+
+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);
+int knot_zone_contents_gen_is_finished(const knot_zone_contents_t *contents);
+
+//void knot_zone_contents_switch_generation(knot_zone_contents_t *contents);
+
+void knot_zone_contents_set_gen_old(knot_zone_contents_t *contents);
+void knot_zone_contents_set_gen_new(knot_zone_contents_t *contents);
+void knot_zone_contents_set_gen_new_finished(knot_zone_contents_t *contents);
+
+uint16_t knot_zone_contents_class(const knot_zone_contents_t *contents);
+
+/*!
+ * \brief Adds a node to the given zone.
+ *
+ * Checks if the node belongs to the zone, i.e. if its owner is a subdomain of
+ * the zone's apex. It thus also forbids adding node with the same name as the
+ * zone apex.
+ *
+ * \warning This function may destroy domain names saved in the node, that
+ * are already present in the zone.
+ *
+ * \param zone Zone to add the node into.
+ * \param node Node to add into the zone.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_EBADARG
+ * \retval KNOT_EBADZONE
+ * \retval KNOT_EHASH
+ */
+int knot_zone_contents_add_node(knot_zone_contents_t *contents,
+ knot_node_t *node, int create_parents,
+ uint8_t flags, int use_domain_table);
+
+/*!
+ * \brief Adds a RRSet to the given zone.
+ *
+ * Checks if the RRSet belongs to the zone, i.e. if its owner is a subdomain of
+ * the zone's apex. The RRSet is inserted only if the node is given, or if
+ * a node where the RRSet should belong is found in the zone.
+ *
+ * \warning The function does not check if the node is already inserted in the
+ * zone, just assumes that it is.
+ * \warning This function may destroy domain names saved in the RRSet, that
+ * are already present in the zone.
+ *
+ * \param zone Zone to add the node into.
+ * \param rrset RRSet to add into the zone.
+ * \param node Node the RRSet should be inserted into. (Should be a node of the
+ * given zone.) If set to NULL, the function will find proper node
+ * and set it to this parameter.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_EBADARG
+ * \retval KNOT_EBADZONE
+ */
+int knot_zone_contents_add_rrset(knot_zone_contents_t *contents,
+ knot_rrset_t *rrset,
+ knot_node_t **node,
+ knot_rrset_dupl_handling_t dupl,
+ int use_domain_table);
+
+int knot_zone_contents_add_rrsigs(knot_zone_contents_t *contents,
+ knot_rrset_t *rrsigs,
+ knot_rrset_t **rrset, knot_node_t **node,
+ knot_rrset_dupl_handling_t dupl,
+ int use_domain_table);
+
+/*!
+ * \brief Adds a node holding NSEC3 records to the given zone.
+ *
+ * Checks if the node belongs to the zone, i.e. if its owner is a subdomain of
+ * the zone's apex. It does not check if the node really contains any NSEC3
+ * records, nor if the name is a hash (as there is actually no way of
+ * determining this).
+ *
+ * \param zone Zone to add the node into.
+ * \param node Node to add into the zone.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_EBADARG
+ * \retval KNOT_EBADZONE
+ */
+int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *contents,
+ knot_node_t *node, int create_parents,
+ uint8_t flags, int use_domain_table);
+
+int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *contents,
+ knot_rrset_t *rrset,
+ knot_node_t **node,
+ knot_rrset_dupl_handling_t dupl,
+ int use_domain_table);
+
+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);
+
+//knot_zone_tree_node_t *knot_zone_contents_remove_node(
+// knot_zone_contents_t *contents, const knot_node_t *node);
+
+int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents,
+ const knot_node_t *node, knot_zone_tree_node_t **removed);
+
+/*!
+ * \warning Always call knot_zone_adjust_dnames() prior to calling this
+ * function. Otherwise the node count would not be set.
+ *
+ * \note Currently, all nodes (even non-authoritative) are inserted into the
+ * hash table.
+ */
+int knot_zone_contents_create_and_fill_hash_table(
+ knot_zone_contents_t *contents);
+
+/*!
+ * \brief Tries to find a node with the specified name in the zone.
+ *
+ * \param zone Zone where the name should be searched for.
+ * \param name Name to find.
+ *
+ * \return Corresponding node if found, NULL otherwise.
+ */
+knot_node_t *knot_zone_contents_get_node(
+ const knot_zone_contents_t *contents, const knot_dname_t *name);
+
+/*!
+ * \brief Tries to find a node with the specified name among the NSEC3 nodes
+ * of the zone.
+ *
+ * \param zone Zone where the name should be searched for.
+ * \param name Name to find.
+ *
+ * \return Corresponding node if found, NULL otherwise.
+ */
+knot_node_t *knot_zone_contents_get_nsec3_node(
+ const knot_zone_contents_t *contents, const knot_dname_t *name);
+
+/*!
+ * \brief Tries to find a node with the specified name in the zone.
+ *
+ * \note This function is identical to knot_zone_contents_get_node(), only it returns
+ * constant reference.
+ *
+ * \param zone Zone where the name should be searched for.
+ * \param name Name to find.
+ *
+ * \return Corresponding node if found, NULL otherwise.
+ */
+const knot_node_t *knot_zone_contents_find_node(
+ const knot_zone_contents_t *contents, const knot_dname_t *name);
+
+/*!
+ * \brief Tries to find domain name in the given zone using AVL tree.
+ *
+ * \param[in] zone Zone to search for the name.
+ * \param[in] name Domain name to search for.
+ * \param[out] node The found node (if it was found, otherwise it may contain
+ * arbitrary node).
+ * \param[out] closest_encloser Closest encloser of the given name in the zone.
+ * \param[out] previous Previous domain name in canonical order.
+ *
+ * \retval KNOT_ZONE_NAME_FOUND if node with owner \a name was found.
+ * \retval KNOT_ZONE_NAME_NOT_FOUND if it was not found.
+ * \retval KNOT_EBADARG
+ * \retval KNOT_EBADZONE
+ */
+int knot_zone_contents_find_dname(const knot_zone_contents_t *contents,
+ const knot_dname_t *name,
+ const knot_node_t **node,
+ const knot_node_t **closest_encloser,
+ const knot_node_t **previous);
+
+/*!
+ * \brief Finds previous name in canonical order to the given name in the zone.
+ *
+ * \param zone Zone to search for the name.
+ * \param name Domain name to find the previous domain name of.
+ *
+ * \return Previous node in canonical order, or NULL if some parameter is wrong.
+ */
+const knot_node_t *knot_zone_contents_find_previous(
+ const knot_zone_contents_t *contents, const knot_dname_t *name);
+
+knot_node_t *knot_zone_contents_get_previous(
+ const knot_zone_contents_t *contents, const knot_dname_t *name);
+
+const knot_node_t *knot_zone_contents_find_previous_nsec3(
+ const knot_zone_contents_t *contents, const knot_dname_t *name);
+
+knot_node_t *knot_zone_contents_get_previous_nsec3(
+ const knot_zone_contents_t *contents, const knot_dname_t *name);
+
+#ifdef USE_HASH_TABLE
+/*!
+ * \brief Tries to find domain name in the given zone using the hash table.
+ *
+ * \param[in] zone Zone to search for the name.
+ * \param[in] name Domain name to search for.
+ * \param[out] node The found node (if it was found, otherwise it may contain
+ * arbitrary node).
+ * \param[out] closest_encloser Closest encloser of the given name in the zone.
+ * \param[out] previous Previous domain name in canonical order.
+ *
+ * \retval KNOT_ZONE_NAME_FOUND if node with owner \a name was found.
+ * \retval KNOT_ZONE_NAME_NOT_FOUND if it was not found.
+ * \retval KNOT_EBADARG
+ * \retval KNOT_EBADZONE
+ */
+int knot_zone_contents_find_dname_hash(const knot_zone_contents_t *contents,
+ const knot_dname_t *name,
+ const knot_node_t **node,
+ const knot_node_t **closest_encloser);
+#endif
+
+/*!
+ * \brief Tries to find a node with the specified name among the NSEC3 nodes
+ * of the zone.
+ *
+ * \note This function is identical to knot_zone_contents_get_nsec3_node(), only it
+ * returns constant reference.
+ *
+ * \param zone Zone where the name should be searched for.
+ * \param name Name to find.
+ *
+ * \return Corresponding node if found, NULL otherwise.
+ */
+const knot_node_t *knot_zone_contents_find_nsec3_node(
+ const knot_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] zone 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 KNOT_ZONE_NAME_FOUND if the corresponding NSEC3 node was found.
+ * \retval KNOT_ZONE_NAME_NOT_FOUND if it was not found.
+ * \retval KNOT_EBADARG
+ * \retval KNOT_ENSEC3PAR
+ * \retval KNOT_ECRYPTO
+ * \retval KNOT_ERROR
+ */
+int knot_zone_contents_find_nsec3_for_name(
+ const knot_zone_contents_t *contents,
+ const knot_dname_t *name,
+ const knot_node_t **nsec3_node,
+ const knot_node_t **nsec3_previous,
+ int check_ver);
+/*!
+ * \brief Returns the apex node of the zone.
+ *
+ * \param zone Zone to get the apex of.
+ *
+ * \return Zone apex node.
+ */
+const knot_node_t *knot_zone_contents_apex(
+ const knot_zone_contents_t *contents);
+
+knot_node_t *knot_zone_contents_get_apex(
+ const knot_zone_contents_t *contents);
+
+//knot_dname_t *knot_zone_contents_name(
+// const knot_zone_contents_t *contents);
+
+/*!
+ * \brief Optimizes zone by replacing domain names in RDATA with references to
+ * domain names present in zone (as node owners).
+ *
+ * \param zone Zone to adjust domain names in.
+ */
+int knot_zone_contents_adjust(knot_zone_contents_t *contents, int check_ver);
+
+/*!
+ * \brief Parses the NSEC3PARAM record stored in the zone.
+ *
+ * This function properly fills in the nsec3_params field of the zone structure
+ * according to data stored in the NSEC3PARAM record. This is necessary to do
+ * before any NSEC3 operations on the zone are requested, otherwise they will
+ * fail (error KNOT_ENSEC3PAR).
+ *
+ * \note If there is no NSEC3PARAM record in the zone, this function clears
+ * the nsec3_params field of the zone structure (fills it with zeros).
+ *
+ * \param zone Zone to get the NSEC3PARAM record from.
+ */
+int knot_zone_contents_load_nsec3param(knot_zone_contents_t *contents);
+
+/*!
+ * \brief Checks if the zone uses NSEC3.
+ *
+ * This function will return 0 if the NSEC3PARAM record was not parse prior to
+ * calling it.
+ *
+ * \param zone Zone to check.
+ *
+ * \retval <> 0 if the zone uses NSEC3.
+ * \retval 0 if it does not.
+ *
+ * \see knot_zone_contents_load_nsec3param()
+ */
+int knot_zone_contents_nsec3_enabled(const knot_zone_contents_t *contents);
+
+/*!
+ * \brief Returns the parsed NSEC3PARAM record of the zone.
+ *
+ * \note You must parse the NSEC3PARAM record prior to calling this function
+ * (knot_zone_contents_load_nsec3param()).
+ *
+ * \param zone Zone to get the NSEC3PARAM record from.
+ *
+ * \return Parsed NSEC3PARAM from the zone or NULL if the zone does not use
+ * NSEC3 or the record was not parsed before.
+ *
+ * \see knot_zone_contents_load_nsec3param()
+ */
+const knot_nsec3_params_t *knot_zone_contents_nsec3params(
+ const knot_zone_contents_t *contents);
+
+/*!
+ * \brief Applies the given function to each regular node in the zone.
+ *
+ * This function uses post-order depth-first forward traversal, i.e. the
+ * function is first recursively applied to subtrees and then to the root.
+ *
+ * \param zone 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 knot_zone_contents_tree_apply_postorder(knot_zone_contents_t *contents,
+ void (*function)(knot_node_t *node, void *data),
+ void *data);
+
+/*!
+ * \brief Applies the given function to each regular node in the zone.
+ *
+ * This function uses in-order depth-first forward traversal, i.e. the function
+ * is first recursively applied to left subtree, then to the root and then to
+ * the right subtree.
+ *
+ * \note This implies that the zone is stored in a binary tree. Is there a way
+ * to make this traversal independent on the underlying structure?
+ *
+ * \param zone 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 knot_zone_contents_tree_apply_inorder(knot_zone_contents_t *contents,
+ void (*function)(knot_node_t *node, void *data),
+ void *data);
+
+/*!
+ * \brief Applies the given function to each regular node in the zone.
+ *
+ * This function uses in-order depth-first reverse traversal, i.e. the function
+ * is first recursively applied to right subtree, then to the root and then to
+ * the left subtree.
+ *
+ * \note This implies that the zone is stored in a binary tree. Is there a way
+ * to make this traversal independent on the underlying structure?
+ *
+ * \param zone 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 knot_zone_contents_tree_apply_inorder_reverse(
+ knot_zone_contents_t *contents,
+ void (*function)(knot_node_t *node, void *data), void *data);
+
+/*!
+ * \brief Applies the given function to each NSEC3 node in the zone.
+ *
+ * This function uses post-order depth-first forward traversal, i.e. the
+ * function is first recursively applied to subtrees and then to the root.
+ *
+ * \param zone 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 knot_zone_contents_nsec3_apply_postorder(knot_zone_contents_t *contents,
+ void (*function)(knot_node_t *node, void *data),
+ void *data);
+
+/*!
+ * \brief Applies the given function to each NSEC3 node in the zone.
+ *
+ * This function uses in-order depth-first forward traversal, i.e. the function
+ * is first recursively applied to left subtree, then to the root and then to
+ * the right subtree.
+ *
+ * \note This implies that the zone is stored in a binary tree. Is there a way
+ * to make this traversal independent on the underlying structure?
+ *
+ * \param zone 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 knot_zone_contents_nsec3_apply_inorder(knot_zone_contents_t *contents,
+ void (*function)(knot_node_t *node, void *data),
+ void *data);
+
+/*!
+ * \brief Applies the given function to each NSEC3 node in the zone.
+ *
+ * This function uses in-order depth-first reverse traversal, i.e. the function
+ * is first recursively applied to right subtree, then to the root and then to
+ * the left subtree.
+ *
+ * \note This implies that the zone is stored in a binary tree. Is there a way
+ * to make this traversal independent on the underlying structure?
+ *
+ * \param zone 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 knot_zone_contents_nsec3_apply_inorder_reverse(
+ knot_zone_contents_t *contents,
+ void (*function)(knot_node_t *node, void *data), void *data);
+
+knot_zone_tree_t *knot_zone_contents_get_nodes(
+ knot_zone_contents_t *contents);
+
+knot_zone_tree_t *knot_zone_contents_get_nsec3_nodes(
+ knot_zone_contents_t *contents);
+
+ck_hash_table_t *knot_zone_contents_get_hash_table(
+ knot_zone_contents_t *contents);
+
+int knot_zone_contents_dname_table_apply(knot_zone_contents_t *contents,
+ void (*function)(knot_dname_t *,
+ void *),
+ void *data);
+
+/*!
+ * \brief Creates a shallow copy of the zone (no stored data are copied).
+ *
+ * This function creates a new zone structure in \a to, creates new trees for
+ * regular nodes and for NSEC3 nodes, creates new hash table and a new domain
+ * table. It also fills these structures with the exact same data as the
+ * original zone is - no copying of stored data is done, just pointers are
+ * copied.
+ *
+ * \param from Original zone.
+ * \param to Copy of the zone.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_EBADARG
+ * \retval KNOT_ENOMEM
+ */
+int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
+ knot_zone_contents_t **to);
+
+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);
+
+#endif
+
+/*! @} */