contents.h 11.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/lists.h"
30
#include "libknot/rdata/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
	knot_zone_tree_t *nodes;
	knot_zone_tree_t *nsec3_nodes;
48

49
	knot_nsec3_params_t nsec3_params;
Jan Včelák's avatar
Jan Včelák committed
50

Lubos Slovak's avatar
Lubos Slovak committed
51
	/*!
Daniel Salzman's avatar
Daniel Salzman committed
52 53
	 * \todo Unify the use of this field - authoritative nodes vs. all.
	 */
54
	size_t node_count;
55

56
	/*! \brief Various flags
Jan Včelák's avatar
Jan Včelák committed
57
	 *
58 59
	 * Two rightmost bits denote zone contents generation.
	 *
60
	 * Possible values:
61 62 63
	 * - 00 - Original version of the zone. Old nodes should be used.
	 * - 01 - New (updated) zone. New nodes should be used.
	 * - 10 - New (updated) zone, but exactly the stored nodes should be
64
	 *        used, no matter their generation.
65 66 67 68
	 *
	 * The third bit denotes whether ANY queries are enabled or disabled:
	 * - 1xx - ANY queries disabled
	 * - 0xx - ANY queries enabled
69
	 */
70
	uint8_t flags;
71
} zone_contents_t;
72

73 74
/*!< \brief Helper linked list list for CNAME loop checking */
typedef struct cname_chain {
75
	const zone_node_t *node;
76 77 78
	struct cname_chain *next;
} cname_chain_t;

79 80 81
/*!
 * \brief Signature of callback for zone contents apply functions.
 */
82
typedef int (*zone_contents_apply_cb_t)(zone_node_t *node, void *data);
83

84 85
/*----------------------------------------------------------------------------*/

86
zone_contents_t *zone_contents_new(const knot_dname_t *apex_name);
87

88 89
int zone_contents_gen_is_old(const zone_contents_t *contents);
int zone_contents_gen_is_new(const zone_contents_t *contents);
90

91 92
void zone_contents_set_gen_old(zone_contents_t *contents);
void zone_contents_set_gen_new(zone_contents_t *contents);
93

94
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, zone_node_t **n);
95

96
int zone_contents_remove_node(zone_contents_t *contents, const knot_dname_t *owner);
97

98
int zone_contents_remove_nsec3_node(zone_contents_t *contents, const knot_dname_t *owner);
99

100 101 102
/*!
 * \brief Tries to find a node with the specified name in the zone.
 *
103
 * \note This function is identical to zone_contents_get_node(), only it returns
104 105 106 107 108 109 110
 *       constant reference.
 *
 * \param zone Zone where the name should be searched for.
 * \param name Name to find.
 *
 * \return Corresponding node if found, NULL otherwise.
 */
111 112
const zone_node_t *zone_contents_find_node(const zone_contents_t *contents,
                                           const knot_dname_t *name);
113 114 115 116 117 118 119 120 121 122 123

/*!
 * \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.
 *
124 125
 * \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
126
 * \retval KNOT_EINVAL
127
 * \retval KNOT_EOUTOFZONE
128
 */
129
int zone_contents_find_dname(const zone_contents_t *contents,
130 131 132 133
                             const knot_dname_t *name,
                             const zone_node_t **node,
                             const zone_node_t **closest_encloser,
                             const zone_node_t **previous);
134 135 136 137 138 139

/*!
 * \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
140
 *
141 142
 * \return Previous node in canonical order, or NULL if some parameter is wrong.
 */
143 144
const zone_node_t *zone_contents_find_previous(const zone_contents_t *contents,
                                               const knot_dname_t *name);
145 146 147 148 149

/*!
 * \brief Tries to find a node with the specified name among the NSEC3 nodes
 *        of the zone.
 *
150
 * \note This function is identical to zone_contents_get_nsec3_node(), only it
151 152 153 154 155 156 157
 *       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.
 */
158 159
const zone_node_t *zone_contents_find_nsec3_node(const zone_contents_t *contents,
                                                 const knot_dname_t *name);
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

/*!
 * \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.
 *
175 176
 * \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
177
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
178 179 180
 * \retval KNOT_ENSEC3PAR
 * \retval KNOT_ECRYPTO
 * \retval KNOT_ERROR
181
 */
182 183 184 185
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);
186

187 188
const zone_node_t *zone_contents_find_wildcard_child(const zone_contents_t *contents,
                                                     const zone_node_t *parent);
189 190

/*!
191
 * \brief Sets parent and previous pointers and node flags. (cheap operation)
192
 *        For both normal and NSEC3 tree
193
 */
194
int zone_contents_adjust_pointers(zone_contents_t *contents);
195 196 197 198 199

/*!
 * \brief Sets parent and previous pointers, sets node flags and NSEC3 links.
 *        This has to be called before the zone can be served.
 *
200 201 202 203
 * \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.
204 205
 * \param zone Zone to adjust domain names in.
 */
206
int zone_contents_adjust_full(zone_contents_t *contents,
207 208
                              zone_node_t **first_nsec3_node,
                              zone_node_t **last_nsec3_node);
209

210 211 212 213 214 215
/*!
 * \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
216
 * fail (error KNOT_ENSEC3PAR).
217 218 219 220 221 222
 *
 * \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.
 */
223
int zone_contents_load_nsec3param(zone_contents_t *contents);
224 225 226 227 228

/*!
 * \brief Returns the parsed NSEC3PARAM record of the zone.
 *
 * \note You must parse the NSEC3PARAM record prior to calling this function
229
 *       (zone_contents_load_nsec3param()).
230 231 232 233 234 235
 *
 * \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.
 *
236
 * \see zone_contents_load_nsec3param()
237
 */
238
const knot_nsec3_params_t *zone_contents_nsec3params(const zone_contents_t *contents);
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253

/*!
 * \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.
 */
254
int zone_contents_tree_apply_inorder(zone_contents_t *zone,
255
                                     zone_contents_apply_cb_t function, void *data);
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

/*!
 * \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.
 */
272
int zone_contents_nsec3_apply_inorder(zone_contents_t *zone,
273
                                      zone_contents_apply_cb_t function, void *data);
274 275 276 277 278 279 280 281 282 283 284 285 286

/*!
 * \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
287
 * \retval KNOT_EOK
Marek Vavrusa's avatar
Marek Vavrusa committed
288
 * \retval KNOT_EINVAL
Lubos Slovak's avatar
Lubos Slovak committed
289
 * \retval KNOT_ENOMEM
290
 */
291
int zone_contents_shallow_copy(const zone_contents_t *from, zone_contents_t **to);
292

293
void zone_contents_free(zone_contents_t **contents);
294

295
void zone_contents_deep_free(zone_contents_t **contents);
296

297 298 299
/*! \brief Return zone SOA rdataset. */
const knot_rdataset_t *zone_contents_soa(const zone_contents_t *zone);

300 301
/*!
 * \brief Fetch zone serial.
Jan Včelák's avatar
Jan Včelák committed
302
 *
303
 * \param zone Zone.
Jan Včelák's avatar
Jan Včelák committed
304
 *
305 306
 * \return serial or 0
 */
307
uint32_t zone_contents_serial(const zone_contents_t *zone);
308

309

310 311 312
/*! \brief Calculate next serial. */
uint32_t zone_contents_next_serial(const zone_contents_t *zone, int policy);

313 314 315
/*!
 * \brief Return true if zone is signed.
 */
316
bool zone_contents_is_signed(const zone_contents_t *zone);
317

318 319 320
/*!
 * \brief Return true if zone is empty.
 */
321 322
bool zone_contents_is_empty(const zone_contents_t *zone);

323
zone_node_t *zone_contents_get_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
324

325
zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *zone, const knot_rrset_t *rrset);
326

327
/*! @} */