contents.h 10.5 KB
Newer Older
1
/*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
Lubos Slovak's avatar
Lubos Slovak committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15

    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/>.
 */
16 17 18 19 20 21 22 23 24 25
/*!
 * \file contents.h
 *
 * \author Lubos Slovak <lubos.slovak@nic.cz>
 *
 * \brief Zone contents structure and API for manipulating it.
 *
 * \addtogroup libknot
 * @{
 */
26

27
#pragma once
28

29
#include "common-knot/lists.h"
30
#include "libknot/rrtype/nsec3param.h"
31 32
#include "knot/zone/node.h"
#include "knot/zone/zone-tree.h"
33

34 35 36 37 38 39
struct zone_t;

enum zone_contents_find_dname_result {
	ZONE_NAME_FOUND = 1,
	ZONE_NAME_NOT_FOUND = 0
};
40

41 42
/*----------------------------------------------------------------------------*/

43
typedef struct zone_contents_t {
44
	zone_node_t *apex;       /*!< Apex node of the zone (holding SOA) */
45

46 47
	zone_tree_t *nodes;
	zone_tree_t *nsec3_nodes;
48

49
	knot_nsec3_params_t nsec3_params;
50
} zone_contents_t;
51

52 53 54
/*!
 * \brief Signature of callback for zone contents apply functions.
 */
55
typedef int (*zone_contents_apply_cb_t)(zone_node_t *node, void *data);
56

57 58
/*----------------------------------------------------------------------------*/

59
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name);
60

61
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n);
62

63
int zone_contents_remove_node(zone_contents_t *contents, const knot_dname_t *owner);
64

65
int zone_contents_remove_nsec3_node(zone_contents_t *contents, const knot_dname_t *owner);
66

67 68 69
/*!
 * \brief Tries to find a node with the specified name in the zone.
 *
70
 * \note This function is identical to zone_contents_get_node(), only it returns
71 72 73 74 75 76 77
 *       constant reference.
 *
 * \param zone Zone where the name should be searched for.
 * \param name Name to find.
 *
 * \return Corresponding node if found, NULL otherwise.
 */
78 79
const zone_node_t *zone_contents_find_node(const zone_contents_t *contents,
                                           const knot_dname_t *name);
80 81 82 83 84 85 86 87 88 89 90

/*!
 * \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.
 *
91 92
 * \retval ZONE_NAME_FOUND if node with owner \a name was found.
 * \retval ZONE_NAME_NOT_FOUND if it was not found.
Marek Vavrusa's avatar
Marek Vavrusa committed
93
 * \retval KNOT_EINVAL
94
 * \retval KNOT_EOUTOFZONE
95
 */
96
int zone_contents_find_dname(const zone_contents_t *contents,
97 98 99 100
                             const knot_dname_t *name,
                             const zone_node_t **node,
                             const zone_node_t **closest_encloser,
                             const zone_node_t **previous);
101 102 103 104 105 106

/*!
 * \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.
Marek Vavrusa's avatar
Marek Vavrusa committed
107
 *
108 109
 * \return Previous node in canonical order, or NULL if some parameter is wrong.
 */
110 111
const zone_node_t *zone_contents_find_previous(const zone_contents_t *contents,
                                               const knot_dname_t *name);
112 113 114 115 116

/*!
 * \brief Tries to find a node with the specified name among the NSEC3 nodes
 *        of the zone.
 *
117
 * \note This function is identical to zone_contents_get_nsec3_node(), only it
118 119 120 121 122 123 124
 *       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.
 */
125 126
const zone_node_t *zone_contents_find_nsec3_node(const zone_contents_t *contents,
                                                 const knot_dname_t *name);
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

/*!
 * \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.
 *
142 143
 * \retval ZONE_NAME_FOUND if the corresponding NSEC3 node was found.
 * \retval ZONE_NAME_NOT_FOUND if it was not found.
Marek Vavrusa's avatar
Marek Vavrusa committed
144
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
145 146 147
 * \retval KNOT_ENSEC3PAR
 * \retval KNOT_ECRYPTO
 * \retval KNOT_ERROR
148
 */
149 150 151 152
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);
153

154 155
const zone_node_t *zone_contents_find_wildcard_child(const zone_contents_t *contents,
                                                     const zone_node_t *parent);
156 157

/*!
158
 * \brief Sets parent and previous pointers and node flags. (cheap operation)
159
 *        For both normal and NSEC3 tree
160
 */
161
int zone_contents_adjust_pointers(zone_contents_t *contents);
162 163 164 165 166

/*!
 * \brief Sets parent and previous pointers, sets node flags and NSEC3 links.
 *        This has to be called before the zone can be served.
 *
167 168 169 170
 * \param first_nsec3_node First node in NSEC3 tree - needed in sem. checks.
 *        Will not be saved if set to NULL.
 * \param last_nsec3_node Last node in NSEC3 tree - needed in sem. checks.
 *        Will not be saved if set to NULL.
171 172
 * \param zone Zone to adjust domain names in.
 */
173
int zone_contents_adjust_full(zone_contents_t *contents,
174 175
                              zone_node_t **first_nsec3_node,
                              zone_node_t **last_nsec3_node);
176

177 178 179 180 181 182
/*!
 * \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
Lubos Slovak's avatar
Lubos Slovak committed
183
 * fail (error KNOT_ENSEC3PAR).
184 185 186 187 188 189
 *
 * \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.
 */
190
int zone_contents_load_nsec3param(zone_contents_t *contents);
191 192 193 194 195

/*!
 * \brief Returns the parsed NSEC3PARAM record of the zone.
 *
 * \note You must parse the NSEC3PARAM record prior to calling this function
196
 *       (zone_contents_load_nsec3param()).
197 198 199 200 201 202
 *
 * \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.
 *
203
 * \see zone_contents_load_nsec3param()
204
 */
205
const knot_nsec3_params_t *zone_contents_nsec3params(const zone_contents_t *contents);
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

/*!
 * \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.
 */
221
int zone_contents_tree_apply_inorder(zone_contents_t *zone,
222
                                     zone_contents_apply_cb_t function, void *data);
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

/*!
 * \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.
 */
239
int zone_contents_nsec3_apply_inorder(zone_contents_t *zone,
240
                                      zone_contents_apply_cb_t function, void *data);
241 242 243 244 245 246 247 248 249 250 251 252 253

/*!
 * \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.
 *
Lubos Slovak's avatar
Lubos Slovak committed
254
 * \retval KNOT_EOK
Marek Vavrusa's avatar
Marek Vavrusa committed
255
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
256
 * \retval KNOT_ENOMEM
257
 */
258
int zone_contents_shallow_copy(const zone_contents_t *from, zone_contents_t **to);
259

260
void zone_contents_free(zone_contents_t **contents);
261

262
void zone_contents_deep_free(zone_contents_t **contents);
263

264 265 266
/*! \brief Return zone SOA rdataset. */
const knot_rdataset_t *zone_contents_soa(const zone_contents_t *zone);

267 268
/*!
 * \brief Fetch zone serial.
Jan Včelák's avatar
Jan Včelák committed
269
 *
270
 * \param zone Zone.
Jan Včelák's avatar
Jan Včelák committed
271
 *
272 273
 * \return serial or 0
 */
274
uint32_t zone_contents_serial(const zone_contents_t *zone);
275

276

277 278 279
/*! \brief Calculate next serial. */
uint32_t zone_contents_next_serial(const zone_contents_t *zone, int policy);

280 281 282
/*!
 * \brief Return true if zone is signed.
 */
283
bool zone_contents_is_signed(const zone_contents_t *zone);
284

285 286 287
/*!
 * \brief Return true if zone is empty.
 */
288 289
bool zone_contents_is_empty(const zone_contents_t *zone);

290
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
291

292
zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
293

294
/*! @} */