contents.h 8.85 KB
Newer Older
Daniel Salzman's avatar
Daniel Salzman committed
1
/*  Copyright (C) 2016 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
 * \file
18
 *
19
 * Zone contents structure and API for manipulating it.
20
 *
21
 * \addtogroup zone
22 23
 * @{
 */
24

25
#pragma once
26

27
#include "dnssec/nsec.h"
28
#include "libknot/rrtype/nsec3param.h"
29 30
#include "knot/zone/node.h"
#include "knot/zone/zone-tree.h"
31

32
enum zone_contents_find_dname_result {
33 34
	ZONE_NAME_NOT_FOUND = 0,
	ZONE_NAME_FOUND     = 1
35
};
36

37
typedef struct zone_contents {
38
	zone_node_t *apex;       /*!< Apex node of the zone (holding SOA) */
39

40 41
	zone_tree_t *nodes;
	zone_tree_t *nsec3_nodes;
42

43
	dnssec_nsec3_params_t nsec3_params;
44
	size_t size;
45
} zone_contents_t;
46

47 48 49
/*!
 * \brief Signature of callback for zone contents apply functions.
 */
50
typedef int (*zone_contents_apply_cb_t)(zone_node_t *node, void *data);
51

52 53 54 55 56 57 58
/*!
 * \brief Allocate and create new zone contents.
 *
 * \param apex_name  Name of the root node.
 *
 * \return New contents or NULL on error.
 */
59
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name);
60

61 62 63 64 65 66 67 68 69 70
/*!
 * \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);
71

72 73 74 75 76 77 78 79 80 81 82
/*!
 * \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);

83 84 85 86 87 88 89 90 91
/*!
 * \brief Get the node with this RR (the RR's owner).
 *
 * \param zone   Contents to add to.
 * \param rrset  The RR to add.
 *
 * \return The searched node if it exists, a new added empty node or NULL on error.
 */
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
92

93 94 95
/*!
 * \brief Tries to find a node with the specified name in the zone.
 *
96
 * \note This function is identical to zone_contents_get_node(), only it returns
97 98 99 100 101 102 103
 *       constant reference.
 *
 * \param zone Zone where the name should be searched for.
 * \param name Name to find.
 *
 * \return Corresponding node if found, NULL otherwise.
 */
104 105 106
const zone_node_t *zone_contents_find_node(const zone_contents_t *contents, const knot_dname_t *name);

zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *contents, const knot_rrset_t *rrset);
107 108

/*!
109
 * \brief Tries to find a node by owner in the zone contents.
110
 *
111 112 113 114 115 116 117 118 119 120
 * \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.
121
 *
122 123
 * \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
124
 * \retval KNOT_EINVAL
125
 * \retval KNOT_EOUTOFZONE
126
 */
127
int zone_contents_find_dname(const zone_contents_t *contents,
128
                             const knot_dname_t *name,
129 130
                             const zone_node_t **match,
                             const zone_node_t **closest,
131
                             const zone_node_t **previous);
132 133 134 135 136

/*!
 * \brief Tries to find a node with the specified name among the NSEC3 nodes
 *        of the zone.
 *
137
 * \note This function is identical to zone_contents_get_nsec3_node(), only it
138 139 140 141 142 143 144
 *       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.
 */
145 146
const zone_node_t *zone_contents_find_nsec3_node(const zone_contents_t *contents,
                                                 const knot_dname_t *name);
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

/*!
 * \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.
 *
162 163
 * \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
164
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
165 166 167
 * \retval KNOT_ENSEC3PAR
 * \retval KNOT_ECRYPTO
 * \retval KNOT_ERROR
168
 */
169 170 171 172
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);
173

174 175
const zone_node_t *zone_contents_find_wildcard_child(const zone_contents_t *contents,
                                                     const zone_node_t *parent);
176 177

/*!
178
 * \brief Sets parent and previous pointers and node flags. (cheap operation)
179
 *        For both normal and NSEC3 tree
Daniel Salzman's avatar
Daniel Salzman committed
180 181
 *
 * \param contents Zone contents to be adjusted.
182
 */
183
int zone_contents_adjust_pointers(zone_contents_t *contents);
184 185 186 187 188

/*!
 * \brief Sets parent and previous pointers, sets node flags and NSEC3 links.
 *        This has to be called before the zone can be served.
 *
Jan Včelák's avatar
Jan Včelák committed
189
 * \param contents Zone contents to be adjusted.
190
 */
191
int zone_contents_adjust_full(zone_contents_t *contents);
192

193 194 195
/*!
 * \brief Applies the given function to each regular node in the zone.
 *
196
 * \param contents Nodes of this zone will be used as parameters for the function.
197 198 199
 * \param function Function to be applied to each node of the zone.
 * \param data Arbitrary data to be passed to the function.
 */
200 201
int zone_contents_apply(zone_contents_t *contents,
                        zone_contents_apply_cb_t function, void *data);
202 203 204 205

/*!
 * \brief Applies the given function to each NSEC3 node in the zone.
 *
206 207
 * \param contents NSEC3 nodes of this zone will be used as parameters for the
 *                 function.
208 209 210
 * \param function Function to be applied to each node of the zone.
 * \param data Arbitrary data to be passed to the function.
 */
211 212
int zone_contents_nsec3_apply(zone_contents_t *contents,
                              zone_contents_apply_cb_t function, void *data);
213 214 215 216 217 218 219 220 221 222 223 224 225

/*!
 * \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
226
 * \retval KNOT_EOK
Marek Vavrusa's avatar
Marek Vavrusa committed
227
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
228
 * \retval KNOT_ENOMEM
229
 */
230
int zone_contents_shallow_copy(const zone_contents_t *from, zone_contents_t **to);
231

232 233 234 235 236
/*!
 * \brief Deallocate directly owned data of zone contents.
 *
 * \param contents  Zone contents to free.
 */
237
void zone_contents_free(zone_contents_t **contents);
238

239 240 241 242 243
/*!
 * \brief Deallocate node RRSets inside the trees, then call zone_contents_free.
 *
 * \param contents  Zone contents to free.
 */
244
void zone_contents_deep_free(zone_contents_t **contents);
245

246 247
/*!
 * \brief Fetch zone serial.
Jan Včelák's avatar
Jan Včelák committed
248
 *
249
 * \param zone Zone.
Jan Včelák's avatar
Jan Včelák committed
250
 *
251 252
 * \return serial or 0
 */
253
uint32_t zone_contents_serial(const zone_contents_t *zone);
254 255 256 257

/*!
 * \brief Return true if zone is signed.
 */
258
bool zone_contents_is_signed(const zone_contents_t *zone);
259

260 261 262
/*!
 * \brief Return true if zone is empty.
 */
263 264
bool zone_contents_is_empty(const zone_contents_t *zone);

265 266 267 268 269 270 271
/*!
 * \brief Measure zone contents size.
 *
 * Size is measured in uncompressed wire format. Measured size is saved into
 * zone contents structure.
 * \return Measured size
 */
272 273
size_t zone_contents_measure_size(zone_contents_t *zone);

274
/*! @} */