contents.h 8.56 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
#pragma once
18

19
#include "libdnssec/nsec.h"
20
#include "libknot/rrtype/nsec3param.h"
21 22
#include "knot/zone/node.h"
#include "knot/zone/zone-tree.h"
23

24
enum zone_contents_find_dname_result {
25 26
	ZONE_NAME_NOT_FOUND = 0,
	ZONE_NAME_FOUND     = 1
27
};
28

29
typedef struct zone_contents {
30
	zone_node_t *apex;       /*!< Apex node of the zone (holding SOA) */
31

32 33
	zone_tree_t *nodes;
	zone_tree_t *nsec3_nodes;
34

35
	dnssec_nsec3_params_t nsec3_params;
36
	size_t size;
37
	uint32_t max_ttl;
38
	bool dnssec;
39
} zone_contents_t;
40

41 42 43
/*!
 * \brief Signature of callback for zone contents apply functions.
 */
44
typedef int (*zone_contents_apply_cb_t)(zone_node_t *node, void *data);
45

46 47 48 49 50 51 52
/*!
 * \brief Allocate and create new zone contents.
 *
 * \param apex_name  Name of the root node.
 *
 * \return New contents or NULL on error.
 */
53
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name);
54

55 56 57 58 59 60 61 62 63 64
/*!
 * \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);
65

66 67 68 69 70 71 72 73 74 75 76
/*!
 * \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);

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

87 88 89
/*!
 * \brief Tries to find a node with the specified name in the zone.
 *
90
 * \param contents Zone where the name should be searched for.
91 92 93 94
 * \param name Name to find.
 *
 * \return Corresponding node if found, NULL otherwise.
 */
95 96 97
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);
98 99

/*!
100
 * \brief Tries to find a node by owner in the zone contents.
101
 *
102 103 104 105 106 107 108 109 110 111
 * \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.
112
 *
113 114
 * \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
115
 * \retval KNOT_EINVAL
116
 * \retval KNOT_EOUTOFZONE
117
 */
118
int zone_contents_find_dname(const zone_contents_t *contents,
119
                             const knot_dname_t *name,
120 121
                             const zone_node_t **match,
                             const zone_node_t **closest,
122
                             const zone_node_t **previous);
123 124 125 126 127

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

/*!
 * \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.
 *
146
 * \param[in] contents Zone to search in.
147 148 149 150 151 152
 * \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.
 *
153 154
 * \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
155
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
156 157 158
 * \retval KNOT_ENSEC3PAR
 * \retval KNOT_ECRYPTO
 * \retval KNOT_ERROR
159
 */
160 161 162 163
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);
164

165 166
const zone_node_t *zone_contents_find_wildcard_child(const zone_contents_t *contents,
                                                     const zone_node_t *parent);
167 168 169 170

/*!
 * \brief Applies the given function to each regular node in the zone.
 *
171
 * \param contents Nodes of this zone will be used as parameters for the function.
172 173 174
 * \param function Function to be applied to each node of the zone.
 * \param data Arbitrary data to be passed to the function.
 */
175 176
int zone_contents_apply(zone_contents_t *contents,
                        zone_contents_apply_cb_t function, void *data);
177 178 179 180

/*!
 * \brief Applies the given function to each NSEC3 node in the zone.
 *
181 182
 * \param contents NSEC3 nodes of this zone will be used as parameters for the
 *                 function.
183 184 185
 * \param function Function to be applied to each node of the zone.
 * \param data Arbitrary data to be passed to the function.
 */
186 187
int zone_contents_nsec3_apply(zone_contents_t *contents,
                              zone_contents_apply_cb_t function, void *data);
188 189 190 191 192 193 194 195 196 197 198 199 200

/*!
 * \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
201
 * \retval KNOT_EOK
Marek Vavrusa's avatar
Marek Vavrusa committed
202
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
203
 * \retval KNOT_ENOMEM
204
 */
205
int zone_contents_shallow_copy(const zone_contents_t *from, zone_contents_t **to);
206

207 208 209 210 211
/*!
 * \brief Deallocate directly owned data of zone contents.
 *
 * \param contents  Zone contents to free.
 */
212
void zone_contents_free(zone_contents_t *contents);
213

214 215 216 217 218
/*!
 * \brief Deallocate node RRSets inside the trees, then call zone_contents_free.
 *
 * \param contents  Zone contents to free.
 */
219
void zone_contents_deep_free(zone_contents_t *contents);
220

221 222
/*!
 * \brief Fetch zone serial.
Jan Včelák's avatar
Jan Včelák committed
223
 *
224
 * \param zone Zone.
Jan Včelák's avatar
Jan Včelák committed
225
 *
226 227
 * \return serial or 0
 */
228
uint32_t zone_contents_serial(const zone_contents_t *zone);
229

230 231 232 233 234 235 236 237 238 239
/*!
 * \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);

240 241 242
/*!
 * \brief Return true if zone is empty.
 */
243 244
bool zone_contents_is_empty(const zone_contents_t *zone);

245 246 247 248 249 250 251
/*!
 * \brief Measure zone contents size.
 *
 * Size is measured in uncompressed wire format. Measured size is saved into
 * zone contents structure.
 * \return Measured size
 */
252 253
size_t zone_contents_measure_size(zone_contents_t *zone);

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