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 #include "knot/zone/node.h"
18 #include "libknot/libknot.h"
19 
additional_clear(additional_t * additional)20 void additional_clear(additional_t *additional)
21 {
22 	if (additional == NULL) {
23 		return;
24 	}
25 
26 	free(additional->glues);
27 	free(additional);
28 }
29 
additional_equal(additional_t * a,additional_t * b)30 bool additional_equal(additional_t *a, additional_t *b)
31 {
32 	if (a == NULL || b == NULL || a->count != b->count) {
33 		return false;
34 	}
35 	for (int i = 0; i < a->count; i++) {
36 		glue_t *ag = &a->glues[i], *bg = &b->glues[i];
37 		if (ag->ns_pos != bg->ns_pos || ag->optional != bg->optional ||
38 		    binode_first((zone_node_t *)ag->node) != binode_first((zone_node_t *)bg->node)) {
39 			return false;
40 		}
41 	}
42 	return true;
43 }
44 
45 /*! \brief Clears allocated data in RRSet entry. */
rr_data_clear(struct rr_data * data,knot_mm_t * mm)46 static void rr_data_clear(struct rr_data *data, knot_mm_t *mm)
47 {
48 	knot_rdataset_clear(&data->rrs, mm);
49 	memset(data, 0, sizeof(*data));
50 }
51 
52 /*! \brief Clears allocated data in RRSet entry. */
rr_data_from(const knot_rrset_t * rrset,struct rr_data * data,knot_mm_t * mm)53 static int rr_data_from(const knot_rrset_t *rrset, struct rr_data *data, knot_mm_t *mm)
54 {
55 	int ret = knot_rdataset_copy(&data->rrs, &rrset->rrs, mm);
56 	if (ret != KNOT_EOK) {
57 		return ret;
58 	}
59 	data->ttl = rrset->ttl;
60 	data->type = rrset->type;
61 	data->additional = NULL;
62 
63 	return KNOT_EOK;
64 }
65 
66 /*! \brief Adds RRSet to node directly. */
add_rrset_no_merge(zone_node_t * node,const knot_rrset_t * rrset,knot_mm_t * mm)67 static int add_rrset_no_merge(zone_node_t *node, const knot_rrset_t *rrset,
68                               knot_mm_t *mm)
69 {
70 	if (node == NULL) {
71 		return KNOT_EINVAL;
72 	}
73 
74 	const size_t prev_nlen = node->rrset_count * sizeof(struct rr_data);
75 	const size_t nlen = (node->rrset_count + 1) * sizeof(struct rr_data);
76 	void *p = mm_realloc(mm, node->rrs, nlen, prev_nlen);
77 	if (p == NULL) {
78 		return KNOT_ENOMEM;
79 	}
80 	node->rrs = p;
81 
82 	// ensure rrsets are sorted by rrtype
83 	struct rr_data *insert_pos = node->rrs, *end = node->rrs + node->rrset_count;
84 	while (insert_pos != end && insert_pos->type < rrset->type) {
85 		insert_pos++;
86 	}
87 	memmove(insert_pos + 1, insert_pos, (uint8_t *)end - (uint8_t *)insert_pos);
88 
89 	int ret = rr_data_from(rrset, insert_pos, mm);
90 	if (ret != KNOT_EOK) {
91 		return ret;
92 	}
93 	++node->rrset_count;
94 
95 	return KNOT_EOK;
96 }
97 
98 /*! \brief Checks if the added RR has the same TTL as the first RR in the node. */
ttl_changed(struct rr_data * node_data,const knot_rrset_t * rrset)99 static bool ttl_changed(struct rr_data *node_data, const knot_rrset_t *rrset)
100 {
101 	if (rrset->type == KNOT_RRTYPE_RRSIG || node_data->rrs.count == 0) {
102 		return false;
103 	}
104 
105 	return rrset->ttl != node_data->ttl;
106 }
107 
node_new(const knot_dname_t * owner,bool binode,bool second,knot_mm_t * mm)108 zone_node_t *node_new(const knot_dname_t *owner, bool binode, bool second, knot_mm_t *mm)
109 {
110 	zone_node_t *ret = mm_alloc(mm, (binode ? 2 : 1) * sizeof(zone_node_t));
111 	if (ret == NULL) {
112 		return NULL;
113 	}
114 	memset(ret, 0, sizeof(*ret));
115 
116 	if (owner) {
117 		ret->owner = knot_dname_copy(owner, mm);
118 		if (ret->owner == NULL) {
119 			mm_free(mm, ret);
120 			return NULL;
121 		}
122 	}
123 
124 	// Node is authoritative by default.
125 	ret->flags = NODE_FLAGS_AUTH;
126 
127 	if (binode) {
128 		ret->flags |= NODE_FLAGS_BINODE;
129 		if (second) {
130 			ret->flags |= NODE_FLAGS_DELETED;
131 		}
132 		memcpy(ret + 1, ret, sizeof(*ret));
133 		(ret + 1)->flags ^= NODE_FLAGS_SECOND | NODE_FLAGS_DELETED;
134 	}
135 
136 	return ret;
137 }
138 
binode_counterpart(zone_node_t * node)139 zone_node_t *binode_counterpart(zone_node_t *node)
140 {
141 	zone_node_t *counterpart = NULL;
142 
143 	assert(node == NULL || (node->flags & NODE_FLAGS_BINODE) || !(node->flags & NODE_FLAGS_SECOND));
144 	if (node != NULL && (node->flags & NODE_FLAGS_BINODE)) {
145 		if ((node->flags & NODE_FLAGS_SECOND)) {
146 			counterpart = node - 1;
147 			assert(!(counterpart->flags & NODE_FLAGS_SECOND));
148 		} else {
149 			counterpart = node + 1;
150 			assert((counterpart->flags & NODE_FLAGS_SECOND));
151 		}
152 		assert((counterpart->flags & NODE_FLAGS_BINODE));
153 	}
154 
155 	return counterpart;
156 }
157 
binode_unify(zone_node_t * node,bool free_deleted,knot_mm_t * mm)158 void binode_unify(zone_node_t *node, bool free_deleted, knot_mm_t *mm)
159 {
160 	zone_node_t *counter = binode_counterpart(node);
161 	if (counter != NULL) {
162 		if (counter->rrs != node->rrs) {
163 			for (uint16_t i = 0; i < counter->rrset_count; ++i) {
164 				if (!binode_additional_shared(node, counter->rrs[i].type)) {
165 					additional_clear(counter->rrs[i].additional);
166 				}
167 				if (!binode_rdata_shared(node, counter->rrs[i].type)) {
168 					rr_data_clear(&counter->rrs[i], mm);
169 				}
170 			}
171 			mm_free(mm, counter->rrs);
172 		}
173 		if (counter->nsec3_wildcard_name != node->nsec3_wildcard_name) {
174 			free(counter->nsec3_wildcard_name);
175 		}
176 		if (!(counter->flags & NODE_FLAGS_NSEC3_NODE) && node->nsec3_hash != counter->nsec3_hash) {
177 			free(counter->nsec3_hash);
178 		}
179 		assert(((node->flags ^ counter->flags) & NODE_FLAGS_SECOND));
180 		memcpy(counter, node, sizeof(*counter));
181 		counter->flags ^= NODE_FLAGS_SECOND;
182 
183 		if (free_deleted && (node->flags & NODE_FLAGS_DELETED)) {
184 			node_free(node, mm);
185 		}
186 	}
187 }
188 
binode_prepare_change(zone_node_t * node,knot_mm_t * mm)189 int binode_prepare_change(zone_node_t *node, knot_mm_t *mm)
190 {
191 	zone_node_t *counter = binode_counterpart(node);
192 	if (counter != NULL && counter->rrs == node->rrs && counter->rrs != NULL) {
193 		size_t rrlen = sizeof(struct rr_data) * counter->rrset_count;
194 		node->rrs = mm_alloc(mm, rrlen);
195 		if (node->rrs == NULL) {
196 			return KNOT_ENOMEM;
197 		}
198 		memcpy(node->rrs, counter->rrs, rrlen);
199 	}
200 	return KNOT_EOK;
201 }
202 
binode_rdata_shared(zone_node_t * node,uint16_t type)203 bool binode_rdata_shared(zone_node_t *node, uint16_t type)
204 {
205 	if (node == NULL || !(node->flags & NODE_FLAGS_BINODE)) {
206 		return false;
207 	}
208 	zone_node_t *counterpart = ((node->flags & NODE_FLAGS_SECOND) ? node - 1 : node + 1);
209 	if (counterpart->rrs == node->rrs) {
210 		return true;
211 	}
212 	knot_rdataset_t *r1 = node_rdataset(node, type), *r2 = node_rdataset(counterpart, type);
213 	return (r1 != NULL && r2 != NULL && r1->rdata == r2->rdata);
214 }
215 
node_type2addit(zone_node_t * node,uint16_t type)216 static additional_t *node_type2addit(zone_node_t *node, uint16_t type)
217 {
218 	for (uint16_t i = 0; i < node->rrset_count; i++) {
219 		if (node->rrs[i].type == type) {
220 			return node->rrs[i].additional;
221 		}
222 	}
223 	return NULL;
224 }
225 
binode_additional_shared(zone_node_t * node,uint16_t type)226 bool binode_additional_shared(zone_node_t *node, uint16_t type)
227 {
228 	if (node == NULL || !(node->flags & NODE_FLAGS_BINODE)) {
229 		return false;
230 	}
231 	zone_node_t *counter = ((node->flags & NODE_FLAGS_SECOND) ? node - 1 : node + 1);
232 	if (counter->rrs == node->rrs) {
233 		return true;
234 	}
235 	additional_t *a1 = node_type2addit(node, type), *a2 = node_type2addit(counter, type);
236 	return (a1 == a2);
237 }
238 
binode_additionals_unchanged(zone_node_t * node,zone_node_t * counterpart)239 bool binode_additionals_unchanged(zone_node_t *node, zone_node_t *counterpart)
240 {
241 	if (node == NULL || counterpart == NULL) {
242 		return false;
243 	}
244 	if (counterpart->rrs == node->rrs) {
245 		return true;
246 	}
247 	for (int i = 0; i < node->rrset_count; i++) {
248 		struct rr_data *rr = &node->rrs[i];
249 		if (knot_rrtype_additional_needed(rr->type)) {
250 			knot_rdataset_t *counterr = node_rdataset(counterpart, rr->type);
251 			if (counterr == NULL || counterr->rdata != rr->rrs.rdata) {
252 				return false;
253 			}
254 		}
255 	}
256 	for (int i = 0; i < counterpart->rrset_count; i++) {
257 		struct rr_data *rr = &counterpart->rrs[i];
258 		if (knot_rrtype_additional_needed(rr->type)) {
259 			knot_rdataset_t *counterr = node_rdataset(node, rr->type);
260 			if (counterr == NULL || counterr->rdata != rr->rrs.rdata) {
261 				return false;
262 			}
263 		}
264 	}
265 	return true;
266 }
267 
node_free_rrsets(zone_node_t * node,knot_mm_t * mm)268 void node_free_rrsets(zone_node_t *node, knot_mm_t *mm)
269 {
270 	if (node == NULL) {
271 		return;
272 	}
273 
274 	for (uint16_t i = 0; i < node->rrset_count; ++i) {
275 		additional_clear(node->rrs[i].additional);
276 		rr_data_clear(&node->rrs[i], mm);
277 	}
278 
279 	mm_free(mm, node->rrs);
280 	node->rrs = NULL;
281 	node->rrset_count = 0;
282 }
283 
node_free(zone_node_t * node,knot_mm_t * mm)284 void node_free(zone_node_t *node, knot_mm_t *mm)
285 {
286 	if (node == NULL) {
287 		return;
288 	}
289 
290 	knot_dname_free(node->owner, mm);
291 
292 	assert((node->flags & NODE_FLAGS_BINODE) || !(node->flags & NODE_FLAGS_SECOND));
293 	assert(binode_counterpart(node) == NULL ||
294 	       binode_counterpart(node)->nsec3_wildcard_name == node->nsec3_wildcard_name);
295 
296 	free(node->nsec3_wildcard_name);
297 	if (!(node->flags & NODE_FLAGS_NSEC3_NODE)) {
298 		free(node->nsec3_hash);
299 	}
300 
301 	if (node->rrs != NULL) {
302 		mm_free(mm, node->rrs);
303 	}
304 
305 	mm_free(mm, binode_node(node, false));
306 }
307 
node_add_rrset(zone_node_t * node,const knot_rrset_t * rrset,knot_mm_t * mm)308 int node_add_rrset(zone_node_t *node, const knot_rrset_t *rrset, knot_mm_t *mm)
309 {
310 	if (node == NULL || rrset == NULL) {
311 		return KNOT_EINVAL;
312 	}
313 
314 	node->flags &= ~NODE_FLAGS_RRSIGS_VALID;
315 
316 	for (uint16_t i = 0; i < node->rrset_count; ++i) {
317 		if (node->rrs[i].type == rrset->type) {
318 			struct rr_data *node_data = &node->rrs[i];
319 			const bool ttl_change = ttl_changed(node_data, rrset);
320 			if (ttl_change) {
321 				node_data->ttl = rrset->ttl;
322 			}
323 
324 			int ret = knot_rdataset_merge(&node_data->rrs,
325 			                              &rrset->rrs, mm);
326 			if (ret != KNOT_EOK) {
327 				return ret;
328 			} else {
329 				return ttl_change ? KNOT_ETTL : KNOT_EOK;
330 			}
331 		}
332 	}
333 
334 	// New RRSet (with one RR)
335 	return add_rrset_no_merge(node, rrset, mm);
336 }
337 
node_remove_rdataset(zone_node_t * node,uint16_t type)338 void node_remove_rdataset(zone_node_t *node, uint16_t type)
339 {
340 	if (node == NULL) {
341 		return;
342 	}
343 
344 	node->flags &= ~NODE_FLAGS_RRSIGS_VALID;
345 
346 	for (int i = 0; i < node->rrset_count; ++i) {
347 		if (node->rrs[i].type == type) {
348 			if (!binode_additional_shared(node, type)) {
349 				additional_clear(node->rrs[i].additional);
350 			}
351 			if (!binode_rdata_shared(node, type)) {
352 				rr_data_clear(&node->rrs[i], NULL);
353 			}
354 			memmove(node->rrs + i, node->rrs + i + 1,
355 			        (node->rrset_count - i - 1) * sizeof(struct rr_data));
356 			--node->rrset_count;
357 			return;
358 		}
359 	}
360 }
361 
node_remove_rrset(zone_node_t * node,const knot_rrset_t * rrset,knot_mm_t * mm)362 int node_remove_rrset(zone_node_t *node, const knot_rrset_t *rrset, knot_mm_t *mm)
363 {
364 	if (node == NULL || rrset == NULL) {
365 		return KNOT_EINVAL;
366 	}
367 
368 	knot_rdataset_t *node_rrs = node_rdataset(node, rrset->type);
369 	if (node_rrs == NULL) {
370 		return KNOT_ENOENT;
371 	}
372 
373 	node->flags &= ~NODE_FLAGS_RRSIGS_VALID;
374 
375 	int ret = knot_rdataset_subtract(node_rrs, &rrset->rrs, mm);
376 	if (ret != KNOT_EOK) {
377 		return ret;
378 	}
379 
380 	if (node_rrs->count == 0) {
381 		node_remove_rdataset(node, rrset->type);
382 	}
383 
384 	return KNOT_EOK;
385 }
386 
node_create_rrset(const zone_node_t * node,uint16_t type)387 knot_rrset_t *node_create_rrset(const zone_node_t *node, uint16_t type)
388 {
389 	if (node == NULL) {
390 		return NULL;
391 	}
392 
393 	for (uint16_t i = 0; i < node->rrset_count; ++i) {
394 		if (node->rrs[i].type == type) {
395 			knot_rrset_t rrset = node_rrset_at(node, i);
396 			return knot_rrset_copy(&rrset, NULL);
397 		}
398 	}
399 
400 	return NULL;
401 }
402 
node_rdataset(const zone_node_t * node,uint16_t type)403 knot_rdataset_t *node_rdataset(const zone_node_t *node, uint16_t type)
404 {
405 	if (node == NULL) {
406 		return NULL;
407 	}
408 
409 	for (uint16_t i = 0; i < node->rrset_count; ++i) {
410 		if (node->rrs[i].type == type) {
411 			return &node->rrs[i].rrs;
412 		}
413 	}
414 
415 	return NULL;
416 }
417 
node_rrtype_is_signed(const zone_node_t * node,uint16_t type)418 bool node_rrtype_is_signed(const zone_node_t *node, uint16_t type)
419 {
420 	if (node == NULL) {
421 		return false;
422 	}
423 
424 	const knot_rdataset_t *rrsigs = node_rdataset(node, KNOT_RRTYPE_RRSIG);
425 	if (rrsigs == NULL) {
426 		return false;
427 	}
428 
429 	uint16_t rrsigs_rdata_count = rrsigs->count;
430 	knot_rdata_t *rrsig = rrsigs->rdata;
431 	for (uint16_t i = 0; i < rrsigs_rdata_count; ++i) {
432 		if (knot_rrsig_type_covered(rrsig) == type) {
433 			return true;
434 		}
435 		rrsig = knot_rdataset_next(rrsig);
436 	}
437 
438 	return false;
439 }
440 
node_bitmap_equal(const zone_node_t * a,const zone_node_t * b)441 bool node_bitmap_equal(const zone_node_t *a, const zone_node_t *b)
442 {
443 	if (a == NULL || b == NULL || a->rrset_count != b->rrset_count) {
444 		return false;
445 	}
446 
447 	uint16_t i;
448 	// heuristics: try if they are equal including order
449 	for (i = 0; i < a->rrset_count; i++) {
450 		if (a->rrs[i].type != b->rrs[i].type) {
451 			break;
452 		}
453 	}
454 	if (i == a->rrset_count) {
455 		return true;
456 	}
457 
458 	for (i = 0; i < a->rrset_count; i++) {
459 		if (node_rdataset(b, a->rrs[i].type) == NULL) {
460 			return false;
461 		}
462 	}
463 	return true;
464 }
465