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