1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup dnsdbzone Zone related functions
36 * @ingroup dnsdb
37 * @brief Functions used to manipulate a zone
38 *
39 * Functions used to manipulate a zone
40 *
41 * @{
42 */
43
44 #ifndef _ZDB_ZONE_H
45 #define _ZDB_ZONE_H
46
47 #include <dnscore/input_stream.h>
48 #include <dnscore/output_stream.h>
49
50 #if HAS_DNSSEC_SUPPORT
51 #include <dnscore/dnskey.h>
52 #endif
53
54 #include <dnsdb/zdb_types.h>
55 #include <dnsdb/dnsrdata.h>
56
57 #include <dnsdb/zdb-zone-lock.h>
58 #include <dnsdb/zdb-zone-arc.h>
59
60 #if ZDB_HAS_NSEC3_SUPPORT
61 #include <dnsdb/nsec3_types.h>
62 #include <dnsdb/zdb_record.h>
63 #endif
64
65 #ifdef __cplusplus
66 extern "C"
67 {
68 #endif
69
70 #define ZDB_ZONETAG 0x454e4f5a52445a /* "ZDBZONE" */
71
72 /**
73 * @brief Get the zone with the given name
74 *
75 * Get the zone with the given name
76 *
77 * @param[in] db a pointer to the database
78 * @param[in] exact_match_origin the name of the zone
79 *
80 * @return a pointer to zone or NULL if the zone is not in the database
81 *
82 */
83
84 /* 2 USES */
85 zdb_zone *zdb_zone_find(zdb *db, dnsname_vector* exact_match_origin);
86
87 /**
88 * @brief Get the zone with the given name
89 *
90 * Get the zone with the given name
91 *
92 * @param[in] db a pointer to the database
93 * @param[in] name the name of the zone (dotted c-string)
94 *
95 * @return a pointer to zone or NULL if the zone is not in the database
96 *
97 */
98
99 zdb_zone *zdb_zone_find_from_name(zdb *db, const char* name);
100
101 /**
102 * @brief Adds a record to a zone
103 *
104 * Adds a record to a zone.
105 *
106 * @param[in] zone the zone
107 * @param[in] labels the stack of labels of the dns name
108 * @param[in] labels_top the index of the top of the stack (the level)
109 * @param[in] type the type of the record
110 * @param[in] ttlrdata the ttl and rdata of the record. NOTE: the zone becomes its new owner !!!
111 */
112
113 /* 2 USES */
114 void zdb_zone_record_add(zdb_zone* zone, dnslabel_vector_reference labels, s32 labels_top, u16 type, zdb_packed_ttlrdata* ttlrdata); /* class is implicit */
115
116 /**
117 * @brief Search for a record in a zone
118 *
119 * Search for a record in a zone
120 *
121 * @param[in] zone the zone
122 * @param[in] labels the stack of labels of the dns name
123 * @param[in] labels_top the index of the top of the stack (the level)
124 * @param[in] type the type of the record
125 */
126
127 /* 4 USES */
128 zdb_packed_ttlrdata* zdb_zone_record_find(zdb_zone *zone, dnslabel_vector_reference labels, s32 labels_top, u16 type);
129
130 /**
131 * Searches the zone for the zdb_rr_label of an fqdn if it exists.
132 *
133 * @param[in] zone the zone
134 * @parma[in] fqdn the fqdn of the the label
135 *
136 * @return a pointer the label, or NULL if it was not found.
137 */
138
139 zdb_rr_label* zdb_zone_find_label_from_fqdn(zdb_zone *zone, const u8 *fqdn);
140
141 /**
142 * @brief Creates a zone
143 *
144 * Creates a zone
145 *
146 * @param[in] zone a pointer to the zone
147 */
148
149 /* 2 USES */
150
151 zdb_zone *zdb_zone_create(const u8 *origin);
152
153 /*
154 * Sets a zone as invalid.
155 * This will put the (content of the) zone in a garbage to be freed at some point in the future (when nolonger used)
156 * Also an invalid zone ... the .axfr and journal files should probably be trashed
157 *
158 */
159
160 void zdb_zone_invalidate(zdb_zone *zone);
161
162
163 void zdb_zone_truncate_invalidate(zdb_zone *zone);
164
165 void zdb_zone_destroy_nolock(zdb_zone *zone);
166
167 /**
168 * @brief Destroys a zone and all its content
169 *
170 * Destroys a zone and all its content
171 *
172 * @param[in] zone a pointer to the zone
173 */
174
175 /* 10 USES */
176 void zdb_zone_destroy(zdb_zone *zone);
177
178 /**
179 * @brief Copies the soa of a zone to an soa_rdata structure.
180 *
181 * Copies the soa of a zone to an soa_rdata structure.
182 * No memory is allocated for the soa_rdata. If the zone is destroyed,
183 * the soa_rdata becomes invalid.
184 *
185 * @param[in] zone a pointer to the zone
186 * @param[out] soa_out a pointer to an soa_rdata structure
187 */
188
189 ya_result zdb_zone_getsoa(const zdb_zone *zone, soa_rdata *soa_out);
190
191 ya_result zdb_zone_getsoa_ttl_rdata(const zdb_zone* zone, u32 *ttl, u16 *rdata_size, const u8 **rdata);
192
193 /**
194 * @brief Retrieve the serial of a zone
195 *
196 * Retrieve the serial of a zone
197 *
198 * @param[in] zone a pointer to the zone
199 * @param[out] serial a pointer to an u32 that will get the serial
200 */
201
202 ya_result zdb_zone_getserial(const zdb_zone* zone, u32 *serial);
203
204 /**
205 * @brief Retrieve the minttl of a zone
206 *
207 * Retrieve the serial of a zone
208 *
209 * @param[in] zone a pointer to the zone
210 * @param[out] serial a pointer to an u32 that will get the minttl
211 */
212
zdb_zone_getminttl(const zdb_zone * zone,s32 * minttl)213 static inline void zdb_zone_getminttl(const zdb_zone *zone, s32 *minttl)
214 {
215 *minttl = zone->min_ttl;
216 }
217
218
219 #if ZDB_RECORDS_MAX_CLASS == 1
zdb_zone_getclass(const zdb_zone * zone)220 static inline u16 zdb_zone_getclass(const zdb_zone *zone)
221 {
222 (void)zone;
223 return CLASS_IN;
224 }
225
226 #else
zdb_zone_getclass(const zdb_zone * zone)227 static inline u16 zdb_zone_getclass(const zdb_zone *zone)
228 {
229 return zone->zclass;
230 }
231 #endif
232
233 ya_result zdb_zone_store_axfr(zdb_zone *zone, output_stream* os);
234
235 const zdb_packed_ttlrdata *zdb_zone_get_dnskey_rrset(zdb_zone *zone);
236
237
zdb_zone_get_flags(const zdb_zone * zone)238 static inline u8 zdb_zone_get_flags(const zdb_zone *zone)
239 {
240 //mutex_lock(&zone->lock_mutex);
241 u8 ret = zone->_flags;
242 //mutex_unlock(&zone->lock_mutex);
243 return ret;
244 }
245
zdb_zone_set_flags(zdb_zone * zone,u8 flags)246 static inline u8 zdb_zone_set_flags(zdb_zone *zone, u8 flags)
247 {
248 //mutex_lock(&zone->lock_mutex);
249 u8 ret = zone->_flags;
250 zone->_flags |= flags;
251 //mutex_unlock(&zone->lock_mutex);
252 return ret;
253 }
254
zdb_zone_clear_flags(zdb_zone * zone,u8 flags)255 static inline u8 zdb_zone_clear_flags(zdb_zone *zone, u8 flags)
256 {
257 //mutex_lock(&zone->lock_mutex);
258 u8 ret = zone->_flags;
259 zone->_flags &= ~flags;
260 //mutex_unlock(&zone->lock_mutex);
261 return ret;
262 }
263
zdb_zone_set_clear_flags(zdb_zone * zone,u8 set_flags,u8 clear_flags)264 static inline u8 zdb_zone_set_clear_flags(zdb_zone *zone, u8 set_flags, u8 clear_flags)
265 {
266 //mutex_lock(&zone->lock_mutex);
267 u8 ret = zone->_flags;
268 zone->_flags &= ~clear_flags;
269 zone->_flags |= set_flags;
270 //mutex_unlock(&zone->lock_mutex);
271 return ret;
272 }
273
274 /**
275 * Tells if the apex of the zone has an NSEC3 extension
276 *
277 * @param zone
278 * @return
279 */
280
zdb_zone_is_nsec3(const zdb_zone * zone)281 static inline bool zdb_zone_is_nsec3(const zdb_zone* zone)
282 {
283 #if ZDB_HAS_NSEC3_SUPPORT
284 return (zone->apex->_flags & ZDB_RR_LABEL_NSEC3) != 0;
285 #else
286 return FALSE;
287 #endif
288 }
289
290 /**
291 * Tells if the apex of the zone has an NSEC3 extension with opt-out
292 *
293 * @param zone
294 * @return
295 */
296
zdb_zone_is_nsec3_optout(const zdb_zone * zone)297 static inline bool zdb_zone_is_nsec3_optout(const zdb_zone* zone)
298 {
299 #if ZDB_HAS_NSEC3_SUPPORT
300 return ((zone->apex->_flags & ZDB_RR_LABEL_NSEC3_OPTOUT) != 0);
301 #else
302 return FALSE;
303 #endif
304 }
305
306 /**
307 * Tells if the apex of the zone has an NSEC3 extension without opt-out
308 *
309 * @param zone
310 * @return
311 */
312
zdb_zone_is_nsec3_optin(const zdb_zone * zone)313 static inline bool zdb_zone_is_nsec3_optin(const zdb_zone* zone)
314 {
315 #if ZDB_HAS_NSEC3_SUPPORT
316 return ((zone->apex->_flags & ZDB_RR_LABEL_NSEC3_OPTOUT) == 0);
317 #else
318 return FALSE;
319 #endif
320 }
321
322 #if ZDB_HAS_NSEC3_SUPPORT
323
324 /**
325 * Returns the nth nsec3 chain or NULL if the chain does not exists
326 *
327 * @param zone
328 * @param idx
329 * @return
330 */
331
zdb_zone_get_nsec3chain(const zdb_zone * zone,s8 idx)332 static inline nsec3_zone* zdb_zone_get_nsec3chain(const zdb_zone *zone, s8 idx)
333 {
334 nsec3_zone *n3 = zone->nsec.nsec3;
335 while(n3 != NULL && --idx >= 0)
336 {
337 n3 = n3->next;
338 }
339 return n3;
340 }
341
342 /**
343 * Tells if a zone has an NSEC3 chain
344 *
345 * @param zone
346 * @return
347 */
348
zdb_zone_has_nsec3_chain(const zdb_zone * zone)349 static inline bool zdb_zone_has_nsec3_chain(const zdb_zone *zone)
350 {
351 return zone->nsec.nsec3 != NULL;
352 }
353
354 /**
355 * Tells if a zone has an NSEC3 chain with opt-out
356 *
357 * @param zone
358 * @return
359 */
360
zdb_zone_has_nsec3_optout_chain(zdb_zone * zone)361 static inline bool zdb_zone_has_nsec3_optout_chain(zdb_zone *zone)
362 {
363 return (zone->nsec.nsec3 != NULL) && (zdb_zone_get_flags(zone) & ZDB_ZONE_HAS_OPTOUT_COVERAGE); /// and ?
364 }
365
zdb_zone_has_nsec3_records(const zdb_zone * zone)366 static inline bool zdb_zone_has_nsec3_records(const zdb_zone *zone)
367 {
368 nsec3_zone *n3 = zone->nsec.nsec3;
369 while(n3 != NULL)
370 {
371 if(n3->items != NULL)
372 {
373 return TRUE;
374 }
375 n3 = n3->next;
376 }
377 return FALSE;
378 }
379
zdb_zone_has_nsec3param_records(const zdb_zone * zone)380 static inline bool zdb_zone_has_nsec3param_records(const zdb_zone *zone)
381 {
382 return zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3PARAM) != NULL;
383 }
384
zdb_zone_maintenance_queued(zdb_zone * zone)385 static inline bool zdb_zone_maintenance_queued(zdb_zone *zone)
386 {
387 bool ret = (zdb_zone_get_flags(zone) & ZDB_ZONE_MAINTAIN_QUEUED) != 0;
388 return ret;
389 }
390
391 /**
392 * Returns TRUE if the zne was not already marked as maintained
393 */
394
zdb_zone_set_maintenance_queued(zdb_zone * zone)395 static inline bool zdb_zone_set_maintenance_queued(zdb_zone *zone)
396 {
397 bool not_already_set = (zdb_zone_set_flags(zone, ZDB_ZONE_MAINTAIN_QUEUED) & ZDB_ZONE_MAINTAIN_QUEUED) == 0;
398 return not_already_set;
399 }
400
zdb_zone_clear_maintenance_queued(zdb_zone * zone)401 static inline void zdb_zone_clear_maintenance_queued(zdb_zone *zone)
402 {
403 zdb_zone_clear_flags(zone, ZDB_ZONE_MAINTAIN_QUEUED);
404 }
405
406 #endif
407
408 /**
409 * Tells if the apex of the zone has an NSEC extension
410 *
411 * @param zone
412 * @return
413 */
414
zdb_zone_is_nsec(const zdb_zone * zone)415 static inline bool zdb_zone_is_nsec(const zdb_zone *zone)
416 {
417 #if ZDB_HAS_NSEC_SUPPORT
418 return (zone->apex->_flags & ZDB_RR_LABEL_NSEC) != 0;
419 #else
420 return FALSE;
421 #endif
422 }
423
424 #if ZDB_HAS_NSEC_SUPPORT
425 /**
426 * Tells if a zone has an NSEC chain
427 *
428 * @param zone
429 * @return
430 */
431
zdb_zone_has_nsec_chain(const zdb_zone * zone)432 static inline bool zdb_zone_has_nsec_chain(const zdb_zone *zone)
433 {
434 return zone->nsec.nsec != NULL;
435 }
436
zdb_zone_has_nsec_records(const zdb_zone * zone)437 static inline bool zdb_zone_has_nsec_records(const zdb_zone *zone)
438 {
439 return zdb_zone_has_nsec_chain(zone);
440 }
441
442 #endif
443
444 #if HAS_RRSIG_MANAGEMENT_SUPPORT
445
446 /**
447 * True for zones that are to be maintained.
448 * This covers DNSSEC zones, but also zones in the process of being
449 * DNSSEC.
450 *
451 * @param zone
452 * @return
453 */
454
zdb_zone_is_maintained(zdb_zone * zone)455 static inline bool zdb_zone_is_maintained(zdb_zone *zone)
456 {
457 bool ret = (zdb_zone_get_flags(zone) & ZDB_ZONE_MAINTAINED) != 0;
458 return ret;
459 }
460
zdb_zone_set_maintained(zdb_zone * zone,bool maintained)461 static inline void zdb_zone_set_maintained(zdb_zone *zone, bool maintained)
462 {
463 if(maintained)
464 {
465 zdb_zone_set_flags(zone, ZDB_ZONE_MAINTAINED);
466 }
467 else
468 {
469 zdb_zone_clear_flags(zone, ZDB_ZONE_MAINTAINED);
470 }
471 }
472
zdb_zone_is_maintenance_paused(zdb_zone * zone)473 static inline bool zdb_zone_is_maintenance_paused(zdb_zone *zone)
474 {
475 u8 flags = zdb_zone_get_flags(zone);
476 bool ret = (flags & (ZDB_ZONE_MAINTENANCE_PAUSED|ZDB_ZONE_MAINTAINED)) == ZDB_ZONE_MAINTENANCE_PAUSED;
477 return ret;
478 }
479
zdb_zone_set_maintenance_paused(zdb_zone * zone,bool maintenance_paused)480 static inline void zdb_zone_set_maintenance_paused(zdb_zone *zone, bool maintenance_paused)
481 {
482 mutex_lock(&zone->lock_mutex);
483 if(maintenance_paused)
484 {
485 zdb_zone_set_clear_flags(zone, ZDB_ZONE_MAINTENANCE_PAUSED, ZDB_ZONE_MAINTAINED);
486 }
487 else
488 {
489 zdb_zone_set_clear_flags(zone, ZDB_ZONE_MAINTAINED, ZDB_ZONE_MAINTENANCE_PAUSED);
490 }
491 mutex_unlock(&zone->lock_mutex);
492 }
493
zone_set_maintain_mode(zdb_zone * zone,u8 mode)494 static inline void zone_set_maintain_mode(zdb_zone *zone, u8 mode)
495 {
496 yassert((mode & ZDB_ZONE_MAINTAIN_MASK) == mode);
497 zdb_zone_set_clear_flags(zone, mode, ZDB_ZONE_MAINTAIN_MASK);
498 }
499
zone_get_maintain_mode(zdb_zone * zone)500 static inline u8 zone_get_maintain_mode(zdb_zone *zone)
501 {
502 u8 ret = zdb_zone_get_flags(zone) & ZDB_ZONE_MAINTAIN_MASK;
503 return ret;
504 }
505
506 #else // HAS_RRSIG_MANAGEMENT_SUPPORT
507
zdb_zone_is_maintained(const zdb_zone * zone)508 static inline bool zdb_zone_is_maintained(const zdb_zone *zone)
509 {
510 (void)zone;
511 return FALSE;
512 }
513
514
zone_get_maintain_mode(const zdb_zone * zone)515 static inline u8 zone_get_maintain_mode(const zdb_zone *zone)
516 {
517 (void)zone;
518 return 0;
519 }
520
zone_set_maintain_mode(zdb_zone * zone,u8 mode)521 static inline void zone_set_maintain_mode(zdb_zone *zone, u8 mode)
522 {
523 (void)zone;
524 (void)mode;
525 }
526
527 #endif
528
zdb_zone_is_dnssec(zdb_zone * zone)529 static inline bool zdb_zone_is_dnssec(zdb_zone *zone)
530 {
531 #if ZDB_HAS_DNSSEC_SUPPORT
532 return (zone->apex->_flags & (ZDB_RR_LABEL_NSEC | ZDB_RR_LABEL_NSEC3)) != 0;
533 #else
534 return FALSE;
535 #endif
536 }
537
zdb_zone_set_rrsig_push_allowed(zdb_zone * zone,bool allowed)538 static inline void zdb_zone_set_rrsig_push_allowed(zdb_zone *zone, bool allowed)
539 {
540 if(allowed)
541 {
542 zdb_zone_set_flags(zone, ZDB_ZONE_RRSIG_PUSH_ALLOWED);
543 }
544 else
545 {
546 zdb_zone_clear_flags(zone, ZDB_ZONE_RRSIG_PUSH_ALLOWED);
547 }
548 }
549
zdb_zone_get_rrsig_push_allowed(zdb_zone * zone)550 static inline bool zdb_zone_get_rrsig_push_allowed(zdb_zone *zone)
551 {
552 bool ret = zdb_zone_get_flags(zone) & ZDB_ZONE_RRSIG_PUSH_ALLOWED;
553 return ret;
554 }
555
556 bool zdb_zone_isinvalid(zdb_zone *zone);
557
zdb_zone_isvalid(zdb_zone * zone)558 static inline bool zdb_zone_isvalid(zdb_zone *zone)
559 {
560 return !zdb_zone_isinvalid(zone);
561 }
562
563 #if HAS_DNSSEC_SUPPORT
564
565 /**
566 * Adds a DNSKEY record in a zone from the dnssec_key object.
567 *
568 * @param key
569 * @return TRUE iff the record has been added
570 */
571
572
573 bool zdb_zone_add_dnskey_from_key(zdb_zone *zone, const dnssec_key *key);
574
575 /**
576 * Removes a DNSKEY record in a zone from the dnssec_key object.
577 *
578 * @param key
579 * @return TRUE iff the record has been found and removed
580 */
581
582
583 bool zdb_zone_remove_dnskey_from_key(zdb_zone *zone, const dnssec_key *key);
584
585 /**
586 *
587 * Returns TRUE iff the key is present as a record in the zone
588 *
589 * @param zone
590 * @param key
591 * @return
592 */
593
594 bool zdb_zone_contains_dnskey_record_for_key(zdb_zone *zone, const dnssec_key *key);
595
596 /**
597 * Returns TRUE iff there is at least one RRSIG record with the tag and algorithm of the key
598 *
599 * @param zone
600 * @param key
601 * @return
602 */
603
604 bool zdb_zone_apex_contains_rrsig_record_by_key(zdb_zone *zone, const dnssec_key *key);
605
606 void zdb_zone_update_keystore_keys_from_zone(zdb_zone *zone, u8 secondary_lock);
607
608 #endif
609
610 #if DEBUG
611
612 /**
613 * DEBUG
614 */
615
616 void zdb_zone_print_indented(zdb_zone* zone, output_stream *os, int indent);
617 void zdb_zone_print(zdb_zone *zone, output_stream *os);
618
619 #endif
620
621 #ifdef __cplusplus
622 }
623 #endif
624
625 #endif /* _ZDB_ZONE_H */
626
627 /** @} */
628