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