contents.h 9.16 KB
Newer Older
1
/*  Copyright (C) 2018 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

    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
14
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
Lubos Slovak's avatar
Lubos Slovak committed
15
 */
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 "libdnssec/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
	uint32_t max_ttl;
46
	bool dnssec;
47
} zone_contents_t;
48

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

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

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

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

85 86 87 88 89 90 91 92 93
/*!
 * \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);
94

95 96 97
/*!
 * \brief Tries to find a node with the specified name in the zone.
 *
98
 * \param contents Zone where the name should be searched for.
99 100 101 102
 * \param name Name to find.
 *
 * \return Corresponding node if found, NULL otherwise.
 */
103 104 105
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);
106 107

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

/*!
 * \brief Tries to find a node with the specified name among the NSEC3 nodes
 *        of the zone.
 *
136
 * \note This function is identical to zone_contents_get_nsec3_node(), only it
137 138
 *       returns constant reference.
 *
139
 * \param contents Zone where the name should be searched for.
140 141 142 143
 * \param name Name to find.
 *
 * \return Corresponding node if found, NULL otherwise.
 */
144 145
const zone_node_t *zone_contents_find_nsec3_node(const zone_contents_t *contents,
                                                 const knot_dname_t *name);
146 147 148 149 150 151 152 153

/*!
 * \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.
 *
154
 * \param[in] contents Zone to search in.
155 156 157 158 159 160
 * \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.
 *
161 162
 * \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
163
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
164 165 166
 * \retval KNOT_ENSEC3PAR
 * \retval KNOT_ECRYPTO
 * \retval KNOT_ERROR
167
 */
168 169 170 171
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);
172

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

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

/*!
 * \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
188
 * \param contents Zone contents to be adjusted.
189
 */
190
int zone_contents_adjust_full(zone_contents_t *contents);
191

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

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

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

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

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

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

254 255 256 257 258 259 260 261 262 263
/*!
 * \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);

264 265 266
/*!
 * \brief Return true if zone is empty.
 */
267 268
bool zone_contents_is_empty(const zone_contents_t *zone);

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

278 279 280 281 282 283 284 285 286 287
/*!
 * \brief Obtain maximal TTL above all the records in zone.
 *
 * The value is also stored in zone_contents structure.
 *
 * \param zone   Zone in question.
 * \return Maximal TTL.
 */
uint32_t zone_contents_max_ttl(zone_contents_t *zone);

288
/*! @} */