1 /*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 
3     This program is free software: you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation, either version 3 of the License, or
6     (at your option) any later version.
7 
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12 
13     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/>.
15  */
16 
17 #pragma once
18 
19 #include "contrib/macros.h"
20 #include "contrib/mempattern.h"
21 #include "libknot/descriptor.h"
22 #include "libknot/dname.h"
23 #include "libknot/rrset.h"
24 #include "libknot/rdataset.h"
25 
26 struct rr_data;
27 
28 /*!
29  * \brief Structure representing one node in a domain name tree, i.e. one domain
30  *        name in a zone.
31  */
32 typedef struct zone_node {
33 	knot_dname_t *owner; /*!< Domain name being the owner of this node. */
34 	struct zone_node *parent; /*!< Parent node in the name hierarchy. */
35 
36 	/*! \brief Array with data of RRSets belonging to this node. */
37 	struct rr_data *rrs;
38 
39 	/*!
40 	 * \brief Previous node in canonical order. Only authoritative
41 	 *        nodes or delegation points are referenced by this.
42 	 */
43 	struct zone_node *prev;
44 	union {
45 		knot_dname_t *nsec3_hash; /*! Name of the NSEC3 corresponding to this node. */
46 		struct zone_node *nsec3_node; /*! NSEC3 node corresponding to this node.
47 		\warning This always points to first part of that bi-node!
48 		assert(!(node->nsec3_node & NODE_FLAGS_SECOND)); */
49 	};
50 	knot_dname_t *nsec3_wildcard_name; /*! Name of NSEC3 node proving wildcard nonexistence. */
51 	uint32_t children; /*!< Count of children nodes in DNS hierarchy. */
52 	uint16_t rrset_count; /*!< Number of RRSets stored in the node. */
53 	uint16_t flags; /*!< \ref node_flags enum. */
54 } zone_node_t;
55 
56 /*!< \brief Glue node context. */
57 typedef struct {
58 	const zone_node_t *node; /*!< Glue node. */
59 	uint16_t ns_pos; /*!< Corresponding NS record position (for compression). */
60 	bool optional; /*!< Optional glue indicator. */
61 } glue_t;
62 
63 /*!< \brief Additional data. */
64 typedef struct {
65 	glue_t *glues; /*!< Glue data. */
66 	uint16_t count; /*!< Number of glue nodes. */
67 } additional_t;
68 
69 /*!< \brief Structure storing RR data. */
70 struct rr_data {
71 	uint32_t ttl; /*!< RRSet TTL. */
72 	uint16_t type; /*!< RR type of data. */
73 	knot_rdataset_t rrs; /*!< Data of given type. */
74 	additional_t *additional; /*!< Additional nodes with glues. */
75 };
76 
77 /*! \brief Flags used to mark nodes with some property. */
78 enum node_flags {
79 	/*! \brief Node is authoritative, default. */
80 	NODE_FLAGS_AUTH =            0 << 0,
81 	/*! \brief Node is a delegation point (i.e. marking a zone cut). */
82 	NODE_FLAGS_DELEG =           1 << 0,
83 	/*! \brief Node is not authoritative (i.e. below a zone cut). */
84 	NODE_FLAGS_NONAUTH =         1 << 1,
85 	/*! \brief RRSIGs in node have been cryptographically validated by Knot. */
86 	NODE_FLAGS_RRSIGS_VALID =    1 << 2,
87 	/*! \brief Node is empty and will be deleted after update. */
88 	NODE_FLAGS_EMPTY =           1 << 3,
89 	/*! \brief Node has a wildcard child. */
90 	NODE_FLAGS_WILDCARD_CHILD =  1 << 4,
91 	/*! \brief Is this NSEC3 node compatible with zone's NSEC3PARAMS ? */
92 	NODE_FLAGS_IN_NSEC3_CHAIN =  1 << 5,
93 	/*! \brief Node is the zone Apex. */
94 	NODE_FLAGS_APEX =            1 << 6,
95 	/*! \brief The nsec3_node pointer is valid and and nsec3_hash pointer invalid. */
96 	NODE_FLAGS_NSEC3_NODE =      1 << 7,
97 	/*! \brief Is this i bi-node? */
98 	NODE_FLAGS_BINODE =          1 << 8, // this value shall be fixed
99 	/*! \brief Is this the second half of bi-node? */
100 	NODE_FLAGS_SECOND =          1 << 9, // this value shall be fixed
101 	/*! \brief The node shall be deleted. It's just not because it's a bi-node and the counterpart still exists. */
102 	NODE_FLAGS_DELETED =         1 << 10,
103 	/*! \brief The node or some node in subtree has some authoritative data in it (possibly also DS at deleg). */
104 	NODE_FLAGS_SUBTREE_AUTH =    1 << 11,
105 	/*! \brief The node or some node in subtree has any data in it, possibly just insec deleg. */
106 	NODE_FLAGS_SUBTREE_DATA =    1 << 12,
107 };
108 
109 typedef void (*node_addrem_cb)(zone_node_t *, void *);
110 typedef zone_node_t *(*node_new_cb)(const knot_dname_t *, void *);
111 
112 /*!
113  * \brief Clears additional structure.
114  *
115  * \param additional  Additional to clear.
116  */
117 void additional_clear(additional_t *additional);
118 
119 /*!
120  * \brief Compares additional structures on equivalency.
121  */
122 bool additional_equal(additional_t *a, additional_t *b);
123 
124 /*!
125  * \brief Creates and initializes new node structure.
126  *
127  * \param owner  Node's owner, will be duplicated.
128  * \param binode Create bi-node.
129  * \param second The second part of the bi-node shall be used now.
130  * \param mm     Memory context to use.
131  *
132  * \return Newly created node or NULL if an error occurred.
133  */
134 zone_node_t *node_new(const knot_dname_t *owner, bool binode, bool second, knot_mm_t *mm);
135 
136 /*!
137  * \brief Synchronize contents of both binode's nodes.
138  *
139  * \param node           Pointer to either of nodes in a binode.
140  * \param free_deleted   When the unified node has DELETED flag, free it afterwards.
141  * \param mm             Memory context.
142  */
143 void binode_unify(zone_node_t *node, bool free_deleted, knot_mm_t *mm);
144 
145 /*!
146  * \brief This must be called before any change to either of the bi-node's node's rdatasets.
147  */
148 int binode_prepare_change(zone_node_t *node, knot_mm_t *mm);
149 
150 /*!
151  * \brief Get the correct node of a binode.
152  *
153  * \param node     Pointer to either of nodes in a binode.
154  * \param second   Get the second node (first otherwise).
155  *
156  * \return Pointer to correct node.
157  */
binode_node(zone_node_t * node,bool second)158 inline static zone_node_t *binode_node(zone_node_t *node, bool second)
159 {
160 	if (unlikely(node == NULL || !(node->flags & NODE_FLAGS_BINODE))) {
161 		assert(node == NULL || !(node->flags & NODE_FLAGS_SECOND));
162 		return node;
163 	}
164 	return node + (second - (int)((node->flags & NODE_FLAGS_SECOND) >> 9));
165 }
166 
binode_first(zone_node_t * node)167 inline static zone_node_t *binode_first(zone_node_t *node)
168 {
169 	return binode_node(node, false);
170 }
171 
binode_node_as(zone_node_t * node,const zone_node_t * as)172 inline static zone_node_t *binode_node_as(zone_node_t *node, const zone_node_t *as)
173 {
174 	assert(node == NULL || (as->flags & NODE_FLAGS_BINODE) == (node->flags & NODE_FLAGS_BINODE));
175 	return binode_node(node, (as->flags & NODE_FLAGS_SECOND));
176 }
177 
178 /*!
179  * \brief Return the other node from a bi-node.
180  *
181  * \param node   A node in a bi-node.
182  *
183  * \return The counterpart node in the same bi-node.
184  */
185 zone_node_t *binode_counterpart(zone_node_t *node);
186 
187 /*!
188  * \brief Return true if the rdataset of specified type is shared (shallow-copied) among both parts of bi-node.
189  */
190 bool binode_rdata_shared(zone_node_t *node, uint16_t type);
191 
192 /*!
193  * \brief Return true if the additionals to rdataset of specified type are shared among both parts of bi-node.
194  */
195 bool binode_additional_shared(zone_node_t *node, uint16_t type);
196 
197 /*!
198  * \brief Return true if the additionals are unchanged between two nodes (usually a bi-node).
199  */
200 bool binode_additionals_unchanged(zone_node_t *node, zone_node_t *counterpart);
201 
202 /*!
203  * \brief Destroys allocated data within the node
204  *        structure, but not the node itself.
205  *
206  * \param node  Node that contains data to be destroyed.
207  * \param mm    Memory context to use.
208  */
209 void node_free_rrsets(zone_node_t *node, knot_mm_t *mm);
210 
211 /*!
212  * \brief Destroys the node structure.
213  *
214  * Does not destroy the data within the node.
215  *
216  * \param node  Node to be destroyed.
217  * \param mm    Memory context to use.
218  */
219 void node_free(zone_node_t *node, knot_mm_t *mm);
220 
221 /*!
222  * \brief Adds an RRSet to the node. All data are copied. Owner and class are
223  *        not used at all.
224  *
225  * \param node     Node to add the RRSet to.
226  * \param rrset    RRSet to add.
227  * \param mm       Memory context to use.
228  *
229  * \return KNOT_E*
230  * \retval KNOT_ETTL  RRSet TTL was updated.
231  */
232 int node_add_rrset(zone_node_t *node, const knot_rrset_t *rrset, knot_mm_t *mm);
233 
234 /*!
235  * \brief Removes data for given RR type from node.
236  *
237  * \param node  Node we want to delete from.
238  * \param type  RR type to delete.
239  */
240 void node_remove_rdataset(zone_node_t *node, uint16_t type);
241 
242 /*!
243  * \brief Remove all RRs from RRSet from the node.
244  *
245  * \param node    Node to remove from.
246  * \param rrset   RRSet with RRs to be removed.
247  * \param mm      Memory context.
248  *
249  * \return KNOT_E*
250  */
251 int node_remove_rrset(zone_node_t *node, const knot_rrset_t *rrset, knot_mm_t *mm);
252 
253 /*!
254  * \brief Returns the RRSet of the given type from the node. RRSet is allocated.
255  *
256  * \param node  Node to get the RRSet from.
257  * \param type  RR type of the RRSet to retrieve.
258  *
259  * \return RRSet from node \a node having type \a type, or NULL if no such
260  *         RRSet exists in this node.
261  */
262 knot_rrset_t *node_create_rrset(const zone_node_t *node, uint16_t type);
263 
264 /*!
265  * \brief Gets rdata set structure of given type from node.
266  *
267  * \param node  Node to get data from.
268  * \param type  RR type of data to get.
269  *
270  * \return Pointer to data if found, NULL otherwise.
271  */
272 knot_rdataset_t *node_rdataset(const zone_node_t *node, uint16_t type);
273 
274 /*!
275  * \brief Returns parent node (fixing bi-node issue) of given node.
276  */
node_parent(const zone_node_t * node)277 inline static zone_node_t *node_parent(const zone_node_t *node)
278 {
279 	return binode_node_as(node->parent, node);
280 }
281 
282 /*!
283  * \brief Returns previous (lexicographically in same zone tree) node (fixing bi-node issue) of given node.
284  */
node_prev(const zone_node_t * node)285 inline static zone_node_t *node_prev(const zone_node_t *node)
286 {
287 	return binode_node_as(node->prev, node);
288 }
289 
290 /*!
291  * \brief Return node referenced by a glue.
292  *
293  * \param glue                Glue in question.
294  * \param another_zone_node   Another node from the same zone.
295  *
296  * \return Glue node.
297  */
glue_node(const glue_t * glue,const zone_node_t * another_zone_node)298 inline static const zone_node_t *glue_node(const glue_t *glue, const zone_node_t *another_zone_node)
299 {
300 	return binode_node_as((zone_node_t *)glue->node, another_zone_node);
301 }
302 
303 /*!
304  * \brief Add a flag to this node and all (grand-)parents until the flag is present.
305  */
node_set_flag_hierarch(zone_node_t * node,uint16_t fl)306 inline static void node_set_flag_hierarch(zone_node_t *node, uint16_t fl)
307 {
308 	for (zone_node_t *i = node; i != NULL && (i->flags & fl) != fl; i = node_parent(i)) {
309 		i->flags |= fl;
310 	}
311 }
312 
313 /*!
314  * \brief Checks whether node contains any RRSIG for given type.
315  *
316  * \param node  Node to check in.
317  * \param type  Type to check for.
318  *
319  * \return True/False.
320  */
321 bool node_rrtype_is_signed(const zone_node_t *node, uint16_t type);
322 
323 /*!
324  * \brief Checks whether node contains RRSet for given type.
325  *
326  * \param node  Node to check in.
327  * \param type  Type to check for.
328  *
329  * \return True/False.
330  */
node_rrtype_exists(const zone_node_t * node,uint16_t type)331 inline static bool node_rrtype_exists(const zone_node_t *node, uint16_t type)
332 {
333 	return node_rdataset(node, type) != NULL;
334 }
335 
336 /*!
337  * \brief Checks whether node is empty. Node is empty when NULL or when no
338  *        RRSets are in it.
339  *
340  * \param node  Node to check in.
341  *
342  * \return True/False.
343  */
node_empty(const zone_node_t * node)344 inline static bool node_empty(const zone_node_t *node)
345 {
346 	return node == NULL || node->rrset_count == 0;
347 }
348 
349 /*!
350  * \brief Check whether two nodes have equal set of rrtypes.
351  *
352  * \param a  A node.
353  * \param b  Another node.
354  *
355  * \return True/False.
356  */
357 bool node_bitmap_equal(const zone_node_t *a, const zone_node_t *b);
358 
359 /*!
360  * \brief Returns RRSet structure initialized with data from node.
361  *
362  * \param node   Node containing RRSet.
363  * \param type   RRSet type we want to get.
364  *
365  * \return RRSet structure with wanted type, or empty RRSet.
366  */
node_rrset(const zone_node_t * node,uint16_t type)367 static inline knot_rrset_t node_rrset(const zone_node_t *node, uint16_t type)
368 {
369 	knot_rrset_t rrset;
370 	for (uint16_t i = 0; node && i < node->rrset_count; ++i) {
371 		if (node->rrs[i].type == type) {
372 			struct rr_data *rr_data = &node->rrs[i];
373 			knot_rrset_init(&rrset, node->owner, type, KNOT_CLASS_IN,
374 			                rr_data->ttl);
375 			rrset.rrs = rr_data->rrs;
376 			rrset.additional = rr_data->additional;
377 			return rrset;
378 		}
379 	}
380 	knot_rrset_init_empty(&rrset);
381 	return rrset;
382 }
383 
384 /*!
385  * \brief Returns RRSet structure initialized with data from node at position
386  *        equal to \a pos.
387  *
388  * \param node  Node containing RRSet.
389  * \param pos   RRSet position we want to get.
390  *
391  * \return RRSet structure with data from wanted position, or empty RRSet.
392  */
node_rrset_at(const zone_node_t * node,size_t pos)393 static inline knot_rrset_t node_rrset_at(const zone_node_t *node, size_t pos)
394 {
395 	knot_rrset_t rrset;
396 	if (node == NULL || pos >= node->rrset_count) {
397 		knot_rrset_init_empty(&rrset);
398 		return rrset;
399 	}
400 
401 	struct rr_data *rr_data = &node->rrs[pos];
402 	knot_rrset_init(&rrset, node->owner, rr_data->type, KNOT_CLASS_IN,
403 	                rr_data->ttl);
404 	rrset.rrs = rr_data->rrs;
405 	rrset.additional = rr_data->additional;
406 	return rrset;
407 }
408 
409 /*!
410  * \brief Return the relevant NSEC3 node (if specified by adjusting), or NULL.
411  */
node_nsec3_get(const zone_node_t * node)412 static inline zone_node_t *node_nsec3_get(const zone_node_t *node)
413 {
414 	if (!(node->flags & NODE_FLAGS_NSEC3_NODE) || node->nsec3_node == NULL) {
415 		return NULL;
416 	} else {
417 		return binode_node_as(node->nsec3_node, node);
418 	}
419 }
420