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 zone Routines for zone_data struct
36  *  @ingroup yadifad
37  *  @brief zone functions
38  *
39  *  Implementation of routines for the zone_data struct
40  *   - add
41  *   - adjust
42  *   - init
43  *   - parse
44  *   - print
45  *   - remove database
46  *
47  * @{
48  */
49 /*------------------------------------------------------------------------------
50  *
51  * USE INCLUDES */
52 #include "server-config.h"
53 #include <string.h>
54 #include <arpa/inet.h>		/* or netinet/in.h */
55 
56 #include <dnscore/format.h>
57 #include <dnscore/timeformat.h>
58 #include <dnscore/logger.h>
59 #include <dnscore/mutex.h>
60 #include <dnscore/ptr_vector.h>
61 #include <dnscore/parsing.h>
62 
63 #if DEBUG
64 #include <dnscore/u64_set.h>
65 #endif
66 
67 #include <dnsdb/zdb-config-features.h> // else we get a chicken-egg issue on the following include
68 
69 #if ZDB_HAS_DNSSEC_SUPPORT
70 #include <dnsdb/dnssec-keystore.h>
71 #include "dnssec-policy.h"
72 #include <dnsdb/nsec3.h>
73 #endif
74 
75 #include "server.h"
76 #include "zone.h"
77 #include "server_error.h"
78 #include "config_error.h"
79 #include "database-service.h"
80 #include "zone-signature-policy.h"
81 
82 #define ZONEDATA_TAG 0x41544144454e4f5a
83 #define ZDORIGIN_TAG 0x4e494749524f445a
84 
85 #define DEBUG_ARC   0
86 
87 #ifndef NAME_MAX
88 #define NAME_MAX 1024
89 #endif
90 
91 #define MODULE_MSG_HANDLE g_server_logger
92 
93 /* Zone file variables */
94 extern zone_data_set database_zone_desc;
95 
96 
97 static mutex_t zone_desc_rc_mtx = MUTEX_INITIALIZER;
98 
99 #if DEBUG
100 static u64_set zone_desc_tracked_set = U64_SET_EMPTY;
101 static u64 zone_desc_next_id = 0;
102 #endif
103 
104 static const char* type_to_name[4] =
105 {
106     "hint",
107     "master",
108     "slave",
109     "stub"
110 };
111 
112 static const char *dnssec_to_name[4] =
113 {
114     "nosec",
115     "nsec",
116     "nsec3",
117     "nsec3-optout"
118 };
119 
120 
121 
122 /*------------------------------------------------------------------------------
123  * STATIC PROTOTYPES */
124 
125 /*------------------------------------------------------------------------------
126  * FUNCTIONS */
127 
128 void
zone_set_lock(zone_data_set * dset)129 zone_set_lock(zone_data_set *dset)
130 {
131     group_mutex_lock(&dset->lock, GROUP_MUTEX_READ);
132 }
133 
134 void
zone_set_unlock(zone_data_set * dset)135 zone_set_unlock(zone_data_set *dset)
136 {
137     group_mutex_unlock(&dset->lock, GROUP_MUTEX_READ);
138 }
139 
140 void
zone_set_writer_lock(zone_data_set * dset)141 zone_set_writer_lock(zone_data_set *dset)
142 {
143     group_mutex_lock(&dset->lock, GROUP_MUTEX_WRITE);
144 }
145 
146 void
zone_set_writer_unlock(zone_data_set * dset)147 zone_set_writer_unlock(zone_data_set *dset)
148 {
149     group_mutex_unlock(&dset->lock, GROUP_MUTEX_WRITE);
150 }
151 
152 #if HAS_DYNAMIC_PROVISIONING
153 bool
zone_data_is_clone(zone_desc_s * desc)154 zone_data_is_clone(zone_desc_s *desc)
155 {
156     return (desc != NULL) && ((desc->dynamic_provisioning.flags & ZONE_CTRL_FLAG_CLONE) != 0);
157 }
158 #endif
159 
160 static int
zone_dnsname_compare(const void * node_a,const void * node_b)161 zone_dnsname_compare(const void *node_a, const void *node_b)
162 {
163     const u8 *m_a = (const u8*)node_a;
164     const u8 *m_b = (const u8*)node_b;
165 
166     return dnsname_compare(m_a, m_b);
167 }
168 
169 void
zone_init(zone_data_set * dset)170 zone_init(zone_data_set *dset)
171 {
172     dset->set.root = NULL;
173     dset->set.compare = zone_dnsname_compare;
174     group_mutex_init(&dset->lock);
175 }
176 
177 void
zone_finalize(zone_data_set * dset)178 zone_finalize(zone_data_set *dset)
179 {
180     group_mutex_destroy(&dset->lock);
181     dset->set.root = NULL;
182     dset->set.compare = zone_dnsname_compare;
183 }
184 
185 /** @brief Initializing zone_data variable
186  *
187  *  The function not only initialize a new zone_data struct, but if needed
188  *  will add the struct to the linked list
189  *
190  *  @param[in,out] dst the new zone_data struct
191  *
192  *  @retval OK
193  */
194 
195 zone_desc_s *
zone_alloc()196 zone_alloc()
197 {
198     zone_desc_s *zone_desc;
199 
200     /* Alloc & clear zone_data structure */
201     ZALLOC_OBJECT_OR_DIE( zone_desc, zone_desc_s, ZONEDATA_TAG);
202     ZEROMEMORY(zone_desc, sizeof(zone_desc_s));
203 
204     bpqueue_init(&zone_desc->commands);
205 
206     mutex_init(&zone_desc->lock);
207     cond_init(&zone_desc->lock_cond);
208 
209     zone_desc->qclass = CLASS_IN;
210 
211 #if ZDB_HAS_DNSSEC_SUPPORT
212 #if HAS_RRSIG_MANAGEMENT_SUPPORT
213 
214     zone_desc->signature.sig_validity_interval = MAX_S32;
215 
216     zone_desc->signature.sig_validity_regeneration = MAX_S32;
217     /*
218      * The validity of newly generated signature will be off by at most this
219      */
220 
221     zone_desc->signature.sig_validity_jitter = MAX_S32;
222 
223     zone_desc->signature.scheduled_sig_invalid_first = MAX_S32;
224 
225 #if HAS_MASTER_SUPPORT
226     ptr_set_init(&zone_desc->dnssec_policy_processed_key_suites);
227     zone_desc->dnssec_policy_processed_key_suites.compare = ptr_set_asciizp_node_compare;
228 #endif
229 
230 #endif
231 
232 #endif
233 
234     zone_desc->rc = 1;
235 
236 #if DEBUG
237     zone_desc->instance_time_us = timeus();
238     mutex_lock(&zone_desc_rc_mtx);
239     zone_desc->instance_id = zone_desc_next_id++;
240     u64_node* node = u64_set_insert(&zone_desc_tracked_set, zone_desc->instance_id);
241     node->value = zone_desc;
242     mutex_unlock(&zone_desc_rc_mtx);
243 #endif
244 
245     log_debug6("new: ?@%p", zone_desc);
246 
247     return zone_desc;
248 }
249 
250 /** \brief
251  *  Frees a zone data
252  *
253  *  @param[in] src is a * to the zone data
254  */
255 
256 zone_desc_s *
zone_clone(zone_desc_s * zone_desc)257 zone_clone(zone_desc_s *zone_desc)
258 {
259     zone_desc_s *clone = zone_alloc();
260 
261     memcpy(clone, zone_desc, sizeof(zone_desc_s));
262 
263     clone->masters = host_address_copy_list(zone_desc->masters);
264     clone->notifies = host_address_copy_list(zone_desc->notifies);
265 
266 #if HAS_ACL_SUPPORT
267     /*
268     acl_unmerge_access_control(&zone_setup->ac, &g_config->ac); COMMENTED OUT
269     acl_access_control_clear(&zone_setup->ac);                COMMENTED OUT
270     */
271 #endif
272 
273     /* Free memory */
274     clone->domain = strdup(zone_domain(zone_desc));
275     clone->file_name = strdup(zone_desc->file_name);
276     clone->_origin = dnsname_dup(zone_origin(zone_desc));
277 
278     clone->rc = 1;
279 
280 #if HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
281     if(clone->dnssec_policy != NULL)
282     {
283         dnssec_policy_acquire(clone->dnssec_policy);
284     }
285 #endif
286 
287     log_debug6("clone: %{dnsname}@%p of @%p rc=%i", zone_origin(zone_desc), clone, zone_desc, zone_desc->rc);
288 
289     return clone;
290 }
291 
292 void
zone_acquire(zone_desc_s * zone_desc)293 zone_acquire(zone_desc_s *zone_desc)
294 {
295     mutex_lock(&zone_desc_rc_mtx);
296 #if DEBUG && DEBUG_ARC
297     s32 old_rc = zone_desc->rc;
298     s32 rc =
299 #endif
300     ++zone_desc->rc;
301     mutex_unlock(&zone_desc_rc_mtx);
302 #if DEBUG && DEBUG_ARC
303     log_debug6("acquire: %{dnsname}@%p rc=%i", zone_origin(zone_desc), zone_desc, rc);
304     char prefix[80];
305     snformat(prefix, sizeof(prefix), "acquire: %{dnsname}@%p", zone_origin(zone_desc), zone_desc);
306     log_debug7("%s: RC from %i to %i", prefix, old_rc, rc);
307     debug_log_stacktrace(g_server_logger, MSG_DEBUG7, prefix);
308 #endif
309 }
310 
311 
312 void
zone_dump_allocated()313 zone_dump_allocated()
314 {
315 #if DEBUG
316     mutex_lock(&zone_desc_rc_mtx);
317 
318     u64_set_iterator iter;
319     u64_set_iterator_init(&zone_desc_tracked_set, &iter);
320     while(u64_set_iterator_hasnext(&iter))
321     {
322         u64_node *node = u64_set_iterator_next_node(&iter);
323         zone_desc_s *zone_desc = (zone_desc_s*)node->value;
324 
325         u32 status_flags = zone_get_status(zone_desc);
326         format_writer status_flags_fw = {zone_desc_status_flags_long_format, &status_flags};
327         log_debug1("zone dump: %p #%llu, %llu, rc=%u, %{dnsname} status=%w",zone_desc, zone_desc->instance_id, zone_desc->instance_time_us, zone_desc->rc, zone_origin(zone_desc), &status_flags_fw);
328     }
329 
330     mutex_unlock(&zone_desc_rc_mtx);
331 #else
332     // not implemented
333 #endif
334 }
335 
336 /**
337  *
338  * Decrements reference and eventually destroys the zone desc
339  *
340  * @param zone_desc
341  */
342 
343 void
zone_release(zone_desc_s * zone_desc)344 zone_release(zone_desc_s *zone_desc)
345 {
346     // note: the zone MUST be locked by the caller
347 
348     if(zone_desc != NULL)
349     {
350         mutex_lock(&zone_desc_rc_mtx);
351 #if DEBUG && DEBUG_ARC
352         s32 old_rc = zone_desc->rc;
353 #endif
354         s32 rc = --zone_desc->rc;
355         mutex_unlock(&zone_desc_rc_mtx);
356 
357 #if DEBUG && DEBUG_ARC
358         log_debug6("release: %{dnsname}@%p rc=%i", zone_origin(zone_desc), zone_desc, rc);
359 
360         char prefix[80];
361         snformat(prefix, sizeof(prefix), "release: %{dnsname}@%p", zone_origin(zone_desc), zone_desc);
362         log_debug7("%s: RC from %i to %i", prefix, old_rc, rc);
363         debug_log_stacktrace(g_server_logger, MSG_DEBUG7, prefix);
364 #endif
365 
366         if(rc <= 0)
367         {
368             log_debug7("zone_free(%p): '%s' (%i)", zone_desc, zone_domain(zone_desc), rc);
369 
370             if(zone_desc->loaded_zone != NULL)
371             {
372                 alarm_close(zone_desc->loaded_zone->alarm_handle);
373                 zone_desc->loaded_zone->alarm_handle = ALARM_HANDLE_INVALID;
374                 zdb_zone_release(zone_desc->loaded_zone);
375                 zone_desc->loaded_zone = NULL;
376             }
377 
378 #if DEBUG
379             log_debug7("zone_free(%p): '%s' #%llu %llu", zone_desc, zone_domain(zone_desc), zone_desc->instance_id, zone_desc->instance_time_us);
380             mutex_lock(&zone_desc_rc_mtx);
381             u64_set_delete(&zone_desc_tracked_set, zone_desc->instance_id);
382             mutex_unlock(&zone_desc_rc_mtx);
383 #endif
384 
385             host_address_delete_list(zone_desc->masters);
386             zone_desc->masters = NULL;
387 
388             host_address_delete_list(zone_desc->notifies);
389             zone_desc->notifies = NULL;
390 
391 #if HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
392             if(zone_desc->dnssec_policy != NULL)
393             {
394                 dnssec_policy_release(zone_desc->dnssec_policy);
395                 zone_desc->dnssec_policy = NULL;
396             }
397 #endif
398 
399 #if HAS_ACL_SUPPORT
400             acl_unmerge_access_control(&zone_desc->ac);
401             acl_access_control_clear(&zone_desc->ac);
402 #endif
403             // Free the  memory
404 
405             free(zone_desc->domain);
406             free(zone_desc->file_name);
407             free(zone_desc->_origin);
408 
409             cond_finalize(&zone_desc->lock_cond);
410             mutex_destroy(&zone_desc->lock);
411 
412 #if DEBUG
413             memset(zone_desc, 0xfe, sizeof(zone_desc_s));
414 #endif
415             ZFREE_OBJECT(zone_desc);
416         }
417     }
418 }
419 
420 void
zone_remove_all_matching(zone_data_set * dset,zone_data_matching_callback * matchcallback)421 zone_remove_all_matching(zone_data_set *dset, zone_data_matching_callback *matchcallback)
422 {
423     if(dset != NULL)
424     {
425         zone_set_lock(dset); // unlock checked
426         ptr_vector candidates = PTR_VECTOR_EMPTY;
427         ptr_set_iterator iter;
428         ptr_set_iterator_init(&dset->set, &iter);
429 
430         while(ptr_set_iterator_hasnext(&iter))
431         {
432             ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
433             zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value;
434 
435             if(zone_desc != NULL)
436             {
437                 if(matchcallback(zone_desc))
438                 {
439                     ptr_vector_append(&candidates, zone_desc);
440                 }
441             }
442         }
443 
444         for(s32 i = 0; i <= candidates.offset; i++)
445         {
446             zone_desc_s *zone_desc = (zone_desc_s*)candidates.data[i];
447             ptr_set_delete(&dset->set, zone_origin(zone_desc));
448             zone_release(zone_desc);
449         }
450 
451         ptr_vector_destroy(&candidates);
452 
453         zone_set_unlock(dset);
454     }
455 }
456 
457 #if 1 // NOT USED
458 /** \brief Frees all elements of the collection
459  *
460  *  @param[in] src the collection
461  *
462  *  @return NONE
463  */
464 void
zone_free_all(zone_data_set * dset)465 zone_free_all(zone_data_set *dset)
466 {
467     if(dset != NULL)
468     {
469         zone_set_lock(dset); // unlock checked
470 
471         ptr_set_iterator iter;
472         ptr_set_iterator_init(&dset->set, &iter);
473 
474         while(ptr_set_iterator_hasnext(&iter))
475         {
476             ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
477             zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value;
478 
479             if(zone_desc != NULL)
480             {
481 #if DEBUG
482                 // status should be idle
483 
484                 mutex_lock(&zone_desc_rc_mtx);
485                 s32 rc = zone_desc->rc;
486                 mutex_unlock(&zone_desc_rc_mtx);
487 #if DEBUG
488                 zone_lock(zone_desc, ZONE_LOCK_LOAD);
489                 zdb_zone *zone = zone_set_loaded_zone(zone_desc, NULL);
490                 if(zone != NULL)
491                 {
492                     zdb_zone_release(zone);
493                 }
494                 zone_unlock(zone_desc, ZONE_LOCK_LOAD);
495 #endif
496                 if(rc != 1)
497                 {
498                     if(rc > 0)
499                     {
500                         log_debug5("zone: warning, zone %{dnsname} has RC=%i", zone_origin(zone_desc), rc);
501                     }
502                     else
503                     {
504                         log_debug5("zone: warning, zone ? has RC=%i", rc);
505                     }
506                 }
507 #endif
508                 zone_release(zone_desc);
509             }
510         }
511 
512         ptr_set_destroy(&dset->set);
513 
514         zone_set_unlock(dset);
515     }
516 }
517 #endif
518 
519 ya_result
zone_complete_settings(zone_desc_s * zone_desc)520 zone_complete_settings(zone_desc_s *zone_desc)
521 {
522     // type
523 
524     if(zone_desc->type == ZT_SLAVE)
525     {
526         if(zone_desc->masters == NULL /* || address_matched(zone_desc->masters, g_config->listen, g_config->port) */)
527         {
528             return DATABASE_ZONE_MISSING_MASTER;
529         }
530     }
531 #if HAS_MASTER_SUPPORT
532     else if(zone_desc->type == ZT_MASTER)
533     {
534         if(zone_desc->file_name == NULL || zone_desc->file_name[0] == '\0')
535         {
536             return ZONE_LOAD_MASTER_ZONE_FILE_UNDEFINED;
537         }
538     }
539 #endif
540     else // zone type is not supported
541     {
542         return DATABASE_ZONE_MISSING_TYPE;
543     }
544 
545     // origin
546 
547     if(zone_origin(zone_desc) == NULL)
548     {
549         if(zone_desc->domain == NULL)
550         {
551             return DATABASE_ZONE_MISSING_DOMAIN;
552         }
553 
554         // else the origin can be set from the domain
555 
556         // set the domain to lower case
557 
558         char *p = zone_desc->domain;
559         while(*p != 0)
560         {
561             *p = tolower(*p);
562             p++;
563         }
564 
565         ya_result return_code;
566 
567         MALLOC_OR_DIE(u8*, zone_desc->_origin, strlen(zone_domain(zone_desc)) + 2, ZDORIGIN_TAG);
568 
569         if(FAIL(return_code = cstr_to_dnsname(zone_desc->_origin, zone_domain(zone_desc))))
570         {
571             free(zone_desc->_origin);
572             zone_desc->_origin = NULL;
573 
574             return return_code;
575         }
576     }
577 
578 #if HAS_ACL_SUPPORT
579     // acl
580 
581     acl_merge_access_control(&zone_desc->ac, g_config->ac);
582 #endif
583 
584 #if ZDB_HAS_DNSSEC_SUPPORT
585     if(zone_desc->keys_path != NULL)
586     {
587         dnssec_keystore_add_domain(zone_origin(zone_desc), zone_desc->keys_path);
588     }
589 #endif
590 
591     return SUCCESS;
592 }
593 
594 #define ZONE_DESC_COMPARE_FIELD_PTR(field_a_, field_b_, comparator_, flag_)   \
595     if(field_a_ != field_b_)                                        \
596     {                                                               \
597         if((field_a_ != NULL) && (field_b_ != NULL))                \
598         {                                                           \
599             if(comparator_(field_a_, field_b_) != 0)                \
600             {                                                       \
601                 return_code |= flag_;                               \
602             }                                                       \
603         }                                                           \
604         else                                                        \
605         {                                                           \
606             return_code |= flag_;                                   \
607         }                                                           \
608     }
609 
610 #define ZONE_DESC_EQUALS_FIELD_PTR(field_a_, field_b_, comparator_, flag_)   \
611     if(field_a_ != field_b_)                                        \
612     {                                                               \
613         if((field_a_ != NULL) && (field_b_ != NULL))                \
614         {                                                           \
615             if(!comparator_(field_a_, field_b_))                     \
616             {                                                       \
617                 return_code |= flag_;                               \
618             }                                                       \
619         }                                                           \
620         else                                                        \
621         {                                                           \
622             return_code |= flag_;                                   \
623         }                                                           \
624     }
625 
626 s32
zone_desc_match(const zone_desc_s * a,const zone_desc_s * b)627 zone_desc_match(const zone_desc_s *a, const zone_desc_s *b)
628 {
629     u32 return_code = 0;
630 
631     if(a == b)
632     {
633         return 0;
634     }
635 
636     if((a == NULL) || (b == NULL))
637     {
638         return MIN_S32;
639     }
640 
641     ZONE_DESC_COMPARE_FIELD_PTR(a->_origin, b->_origin, dnsname_compare, ZONE_DESC_MATCH_ORIGIN);
642     ZONE_DESC_COMPARE_FIELD_PTR(zone_domain(a),zone_domain(b),strcmp, ZONE_DESC_MATCH_DOMAIN);
643     if((a->file_name != NULL) && (b->file_name != NULL))
644     {
645         ZONE_DESC_COMPARE_FIELD_PTR(a->file_name,b->file_name,strcmp, ZONE_DESC_MATCH_FILE_NAME);
646     }
647     else if(a->file_name != b->file_name)
648     {
649         return_code |= ZONE_DESC_MATCH_FILE_NAME;
650     }
651     ZONE_DESC_EQUALS_FIELD_PTR(a->masters,b->masters,host_address_list_equals, ZONE_DESC_MATCH_MASTERS);
652     ZONE_DESC_EQUALS_FIELD_PTR(a->notifies,b->notifies,host_address_list_equals, ZONE_DESC_MATCH_NOTIFIES);
653 
654 #if HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
655     if(a->dnssec_policy != b->dnssec_policy)
656     {
657         return_code |= ZONE_DESC_MATCH_DNSSEC_POLICIES;
658     }
659 #endif
660 
661 #if HAS_ACL_SUPPORT
662     if(!acl_address_control_equals(&a->ac, &b->ac))
663     {
664         return_code |= ZONE_DESC_MATCH_ACL;
665     }
666 #endif
667 
668 #if HAS_CTRL
669     if(memcmp(&a->dynamic_provisioning, &b->dynamic_provisioning, sizeof(dynamic_provisioning_s)) != 0)
670     {
671         return_code |= ZONE_DESC_MATCH_DYNAMIC;
672     }
673 
674     ZONE_DESC_EQUALS_FIELD_PTR(a->slaves,b->slaves,host_address_list_equals, ZONE_DESC_MATCH_SLAVES);
675 #endif
676     /*
677     if(memcmp(&a->refresh, &b->refresh, sizeof(zone_data_refresh)) != 0)
678     {
679         return_code |= ZONE_DESC_MATCH_REFRESH;
680     }
681     */
682     if(memcmp(&a->notify, &b->notify, sizeof(zone_notify_s)) != 0)
683     {
684         return_code |= ZONE_DESC_MATCH_NOTIFY;
685     }
686 
687 #if HAS_DNSSEC_SUPPORT
688     if(a->dnssec_mode != b->dnssec_mode)
689     {
690         return_code |= ZONE_DESC_MATCH_DNSSEC_MODE;
691     }
692 #endif
693 
694     if(a->type != b->type)
695     {
696         return_code |= ZONE_DESC_MATCH_TYPE;
697     }
698 
699     return return_code;
700 }
701 
702 /**
703  * Adds the zone in the collection (if it's not there already)
704  * The zone must have at least it's domain set
705  */
706 
707 ya_result
zone_register(zone_data_set * dset,zone_desc_s * zone_desc)708 zone_register(zone_data_set *dset, zone_desc_s *zone_desc)
709 {
710     zone_complete_settings(zone_desc);
711 
712     if(zone_origin(zone_desc) == NULL)
713     {
714         if(zone_desc->domain == NULL)
715         {
716             log_err("config: zone: ?: no domain set (not loaded)", zone_domain(zone_desc));
717 
718             return DATABASE_ZONE_MISSING_DOMAIN;
719         }
720     }
721 
722     zone_set_writer_lock(dset);
723 
724     ptr_node *zone_desc_node = ptr_set_find(&dset->set, zone_origin(zone_desc));
725 
726     if(zone_desc_node != NULL)
727     {
728         // already known
729 
730         zone_desc_s *current_zone_desc = (zone_desc_s*)zone_desc_node->value;
731 
732         s32 zone_desc_match_bitmap = ~0;
733 
734         if(current_zone_desc == zone_desc)
735         {
736             // already
737             log_debug("zone: %{dnsname} has already been set", zone_origin(zone_desc));
738 
739             zone_set_writer_unlock(dset);
740 
741             return SUCCESS;
742         }
743         else if((zone_desc_match_bitmap = zone_desc_match(zone_desc, current_zone_desc)) == 0)
744         {
745             // already
746             log_debug("zone: %{dnsname} has already been set this way", zone_origin(zone_desc));
747 
748             zone_set_writer_unlock(dset);
749 
750             return DATABASE_ZONE_CONFIG_CLONE;
751         }
752         else
753         {
754             /*
755              * compare the zones are decide (overwrite or replace ?)
756              *
757              * if the zones are equals : no operation
758              * if the zones differs ...
759              *   ask for a reload of the desc
760              *
761              */
762 
763             log_err("zone: %{dnsname} has been set in two different way (bitmap=%08x) (ignoring duplicate)", zone_origin(zone_desc), zone_desc_match_bitmap);
764 
765             zone_set_writer_unlock(dset);
766 
767             return DATABASE_ZONE_CONFIG_DUP;
768         }
769     }
770     else
771     {
772         log_debug("zone: %{dnsname} is a new zone", zone_origin(zone_desc));
773 
774         zone_desc->_status_flags = ZONE_STATUS_STARTING_UP;
775     }
776 
777     if(zone_desc->type == ZT_SLAVE)
778     {
779         log_debug1("zone: %{dnsname} is a slave, verifying master settings", zone_origin(zone_desc));
780 
781         if(zone_desc->masters == NULL /* || address_matched(zone_desc->masters, g_config->listen, g_config->port) */)
782         {
783             zone_set_writer_unlock(dset);
784 
785             log_err("zone: %{dnsname} has no master setting (not loaded)", zone_origin(zone_desc));
786 
787             free(zone_desc->_origin);
788             zone_desc->_origin = NULL;
789 
790             return DATABASE_ZONE_MISSING_MASTER;
791         }
792 
793         log_debug("zone: %{dnsname} is a slave, master is %{hostaddr}", zone_origin(zone_desc), zone_desc->masters);
794     }
795 
796     ya_result return_value;
797 
798     ptr_node *node = ptr_set_insert(&dset->set, zone_desc->_origin);
799 
800     if(node->value == NULL)
801     {
802         //log_info("zone: the zone %{dnsname} has been registered", zone_origin(zone_desc));
803 
804         node->value = zone_desc;
805 
806         ++dset->set_count;
807 
808         return_value = SUCCESS;
809     }
810     else
811     {
812         // already
813         //log_err("zone: the zone %{dnsname} has already been set", zone_origin(zone_desc));
814 
815         free(zone_desc->_origin);
816         zone_desc->_origin = NULL;
817 
818         return_value = DATABASE_ZONE_CONFIG_DUP;
819     }
820 
821     zone_set_writer_unlock(dset);
822 
823     return return_value;
824 }
825 
826 /**
827  * Removes the zone with the given origin from the collection.
828  * Returns a pointer to the zone. (The caller may destroy it if
829  * he wants)
830  */
831 
832 zone_desc_s *
zone_unregister(zone_data_set * dset,const u8 * origin)833 zone_unregister(zone_data_set *dset, const u8 *origin)
834 {
835     zone_desc_s *zone_desc = NULL;
836 
837     zone_set_writer_lock(dset);
838 
839     ptr_node *node = ptr_set_find(&dset->set, origin);
840 
841     if(node != NULL)
842     {
843         zone_desc = (zone_desc_s*)node->value;
844 
845         if(zone_desc != NULL)
846         {
847             ptr_set_delete(&dset->set, origin);
848             --dset->set_count;
849         }
850     }
851 
852     zone_set_writer_unlock(dset);
853 
854     return zone_desc;
855 }
856 
857 /**
858  * returns the zone_data from the zone config that's just after the name
859  * in lexicographic order
860  *
861  * @param name
862  * @return
863  */
864 
865 zone_desc_s*
zone_getafterdnsname(const u8 * name)866 zone_getafterdnsname(const u8 *name)
867 {
868     zone_desc_s *zone_desc = NULL;
869 
870     zone_set_lock(&database_zone_desc); // unlock checked
871 
872     ptr_node *zone_node = ptr_set_find(&database_zone_desc.set, name);
873 
874     if(zone_node != NULL)
875     {
876         zone_node = ptr_set_node_next(zone_node);
877 
878         if(zone_node != NULL)
879         {
880             zone_desc = (zone_desc_s*)zone_node->value;
881             zone_acquire(zone_desc);
882         }
883     }
884 
885     zone_set_unlock(&database_zone_desc);
886 
887     return zone_desc;
888 }
889 
890 zone_desc_s*
zone_acquirebydnsname(const u8 * name)891 zone_acquirebydnsname(const u8 *name)
892 {
893     zone_desc_s *zone_desc = NULL;
894 
895     zone_set_lock(&database_zone_desc); // unlock checked
896 
897     ptr_node *zone_node = ptr_set_find(&database_zone_desc.set, name);
898 
899     if(zone_node != NULL)
900     {
901         zone_desc = (zone_desc_s*)zone_node->value;
902         zone_acquire(zone_desc);
903     }
904 
905     zone_set_unlock(&database_zone_desc);
906 
907     return zone_desc;
908 }
909 
910 
911 
912 
913 
914 void
zone_setloading(zone_desc_s * zone_desc,bool v)915 zone_setloading(zone_desc_s *zone_desc, bool v)
916 {
917     const u32 mask = ZONE_STATUS_LOADING;
918 
919     if(v)
920     {
921         zone_set_status(zone_desc, mask);
922     }
923     else
924     {
925         zone_clear_status(zone_desc, mask);
926     }
927 }
928 
929 void
zone_setmustsavefile(zone_desc_s * zone_desc,bool v)930 zone_setmustsavefile(zone_desc_s *zone_desc, bool v)
931 {
932     const u32 mask = ZONE_STATUS_SAVETO_ZONE_FILE;
933 
934     if(v)
935     {
936         zone_set_status(zone_desc, mask);
937     }
938     else
939     {
940         zone_clear_status(zone_desc, mask);
941     }
942 }
943 
944 void
zone_setmustsaveaxfr(zone_desc_s * zone_desc,bool v)945 zone_setmustsaveaxfr(zone_desc_s *zone_desc, bool v)
946 {
947     const u32 mask = ZONE_STATUS_SAVETO_AXFR_FILE;
948 
949     if(v)
950     {
951         zone_set_status(zone_desc, mask);
952     }
953     else
954     {
955         zone_clear_status(zone_desc, mask);
956     }
957 }
958 
959 void
zone_setsavingfile(zone_desc_s * zone_desc,bool v)960 zone_setsavingfile(zone_desc_s *zone_desc, bool v)
961 {
962     const u32 mask = ZONE_STATUS_SAVING_ZONE_FILE;
963 
964     if(v)
965     {
966         zone_set_status(zone_desc, mask);
967     }
968     else
969     {
970         zone_clear_status(zone_desc, mask);
971     }
972 }
973 
974 void
zone_setsavingaxfr(zone_desc_s * zone_desc,bool v)975 zone_setsavingaxfr(zone_desc_s *zone_desc, bool v)
976 {
977     const u32 mask = ZONE_STATUS_SAVING_AXFR_FILE;
978 
979     if(v)
980     {
981         zone_set_status(zone_desc, mask);
982     }
983     else
984     {
985         zone_clear_status(zone_desc, mask);
986     }
987 }
988 
989 void
zone_setstartingup(zone_desc_s * zone_desc,bool v)990 zone_setstartingup(zone_desc_s *zone_desc, bool v)
991 {
992     const u32 mask = ZONE_STATUS_STARTING_UP;
993 
994     if(v)
995     {
996         zone_set_status(zone_desc, mask);
997     }
998     else
999     {
1000         zone_clear_status(zone_desc, mask);
1001     }
1002 }
1003 
1004 bool
zone_isidle(zone_desc_s * zone_desc)1005 zone_isidle(zone_desc_s *zone_desc)
1006 {
1007     return (zone_get_status(zone_desc) & ZONE_STATUS_BUSY) == 0;
1008 }
1009 
1010 bool
zone_isfrozen(zone_desc_s * zone_desc)1011 zone_isfrozen(zone_desc_s *zone_desc)
1012 {
1013     return (zone_get_status(zone_desc) & ZONE_STATUS_FROZEN) != 0;
1014 }
1015 
1016 
1017 
1018 bool
zone_isloading(zone_desc_s * zone_desc)1019 zone_isloading(zone_desc_s *zone_desc)
1020 {
1021     return ((zone_get_status(zone_desc) & ZONE_STATUS_LOADING) != 0);
1022 }
1023 
1024 bool
zone_mustsavefile(zone_desc_s * zone_desc)1025 zone_mustsavefile(zone_desc_s *zone_desc)
1026 {
1027     return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVETO_ZONE_FILE) != 0);
1028 }
1029 
1030 bool
zone_mustsaveaxfr(zone_desc_s * zone_desc)1031 zone_mustsaveaxfr(zone_desc_s *zone_desc)
1032 {
1033     return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVETO_AXFR_FILE) != 0);
1034 }
1035 
1036 bool
zone_issavingfile(zone_desc_s * zone_desc)1037 zone_issavingfile(zone_desc_s *zone_desc)
1038 {
1039     return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVING_ZONE_FILE) != 0);
1040 }
1041 
1042 bool
zone_issavingaxfr(zone_desc_s * zone_desc)1043 zone_issavingaxfr(zone_desc_s *zone_desc)
1044 {
1045     return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVING_AXFR_FILE) != 0);
1046 }
1047 
1048 bool
zone_isstartingup(zone_desc_s * zone_desc)1049 zone_isstartingup(zone_desc_s *zone_desc)
1050 {
1051     return ((zone_get_status(zone_desc) & ZONE_STATUS_STARTING_UP) != 0);
1052 }
1053 
1054 bool
zone_isdynamicupdating(zone_desc_s * zone_desc)1055 zone_isdynamicupdating(zone_desc_s *zone_desc)
1056 {
1057     return ((zone_get_status(zone_desc) & ZONE_STATUS_DYNAMIC_UPDATING) != 0);
1058 }
1059 
1060 bool
zone_canbeedited(zone_desc_s * zone_desc)1061 zone_canbeedited(zone_desc_s *zone_desc)
1062 {
1063     return ((zone_get_status(zone_desc) & (ZONE_STATUS_STARTING_UP|ZONE_STATUS_DYNAMIC_UPDATING|ZONE_STATUS_SAVING_AXFR_FILE|ZONE_STATUS_SAVING_ZONE_FILE|ZONE_STATUS_LOADING)) == 0);
1064 }
1065 
1066 bool
zone_ismaster(zone_desc_s * zone_desc)1067 zone_ismaster(zone_desc_s *zone_desc)
1068 {
1069     return zone_desc->type == ZT_MASTER;
1070 }
1071 
1072 ya_result
zone_wait_unlocked(zone_desc_s * zone_desc)1073 zone_wait_unlocked(zone_desc_s *zone_desc)
1074 {
1075     log_debug6("zone_wait_unlocked(%{dnsname}@%p) ...", zone_origin(zone_desc), zone_desc);
1076 
1077     mutex_lock(&zone_desc->lock);
1078 
1079     if((zone_desc->lock_owner_count | zone_desc->lock_wait_count) != 0)
1080     {
1081         do
1082         {
1083             cond_wait(&zone_desc->lock_cond, &zone_desc->lock);
1084         }
1085         while((zone_desc->lock_owner_count | zone_desc->lock_wait_count) != 0);
1086     }
1087 
1088     log_debug6("zone_wait_unlocked(%{dnsname}@%p) done", zone_origin(zone_desc), zone_desc);
1089 
1090     cond_notify(&zone_desc->lock_cond);
1091 
1092     mutex_unlock(&zone_desc->lock);
1093 
1094 
1095     return SUCCESS;
1096 }
1097 
1098 bool
zone_is_obsolete(zone_desc_s * zone_desc)1099 zone_is_obsolete(zone_desc_s *zone_desc)
1100 {
1101     bool r;
1102 
1103     mutex_lock(&zone_desc->lock);
1104 
1105     r = ((zone_desc->lock_owner_count | zone_desc->lock_wait_count) == 0) &&
1106         ((zone_get_status(zone_desc) & (ZONE_STATUS_UNREGISTERING|ZONE_STATUS_MARKED_FOR_DESTRUCTION)) != 0);
1107 
1108     cond_notify(&zone_desc->lock_cond);
1109     mutex_unlock(&zone_desc->lock);
1110 
1111     return r;
1112 }
1113 
1114 ya_result
zone_try_lock(zone_desc_s * zone_desc,u8 owner_id)1115 zone_try_lock(zone_desc_s *zone_desc, u8 owner_id)
1116 {
1117 #if DEBUG
1118     log_debug6("zone_try_lock(%{dnsname}@%p, %u", zone_origin(zone_desc), zone_desc, owner_id);
1119     debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_try_lock");
1120 #endif
1121 
1122     ya_result return_value = LOCK_TIMEOUT;
1123 
1124     mutex_lock(&zone_desc->lock);
1125 
1126     if((zone_desc->lock_owner == ZONE_LOCK_NOBODY) || (zone_desc->lock_owner == owner_id))
1127     {
1128         zone_desc->lock_owner = owner_id & 0x7f;
1129 
1130         zone_desc->lock_owner_count++;
1131 
1132         return_value = owner_id;
1133     }
1134 
1135     cond_notify(&zone_desc->lock_cond);
1136 
1137     mutex_unlock(&zone_desc->lock);
1138 
1139     return return_value;
1140 }
1141 
1142 ya_result
zone_lock(zone_desc_s * zone_desc,u8 owner_id)1143 zone_lock(zone_desc_s *zone_desc, u8 owner_id)
1144 {
1145     ya_result return_value = LOCK_FAILED;
1146 
1147 #if DEBUG
1148     log_debug6("zone_lock(%{dnsname}@%p, %02x)", zone_origin(zone_desc), zone_desc, owner_id);
1149     debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_lock");
1150 #endif
1151 
1152     mutex_lock(&zone_desc->lock);
1153 
1154     if((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id))
1155     {
1156         zone_desc->lock_wait_count++;
1157 
1158         do
1159         {
1160             cond_wait(&zone_desc->lock_cond, &zone_desc->lock);
1161         }
1162         while((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id));
1163 
1164         zone_desc->lock_wait_count--;
1165     }
1166 
1167     zone_desc->lock_owner = owner_id & 0x7f;
1168     zone_desc->lock_owner_count++;
1169 
1170     return_value = owner_id;
1171 
1172 #if ZONE_LOCK_HAS_OWNER_ID
1173     zone_desc->lock_last_owner_tid = thread_self();
1174 #endif
1175 
1176     if((owner_id & 0x80) == 0)
1177     {
1178         cond_notify(&zone_desc->lock_cond);
1179     }
1180 
1181     mutex_unlock(&zone_desc->lock);
1182 
1183     return return_value;
1184 }
1185 
1186 ya_result
zone_try_lock_wait(zone_desc_s * zone_desc,u64 usec,u8 owner_id)1187 zone_try_lock_wait(zone_desc_s *zone_desc, u64 usec, u8 owner_id)
1188 {
1189     ya_result return_value = LOCK_FAILED;
1190 
1191 #if DEBUG
1192     log_debug6("zone_try_lock_wait(%{dnsname}@%p, %llu, %02x)", zone_origin(zone_desc), zone_desc, usec, owner_id);
1193     debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_try_lock_wait");
1194 #endif
1195 
1196     mutex_lock(&zone_desc->lock);
1197 
1198     if((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id))
1199     {
1200         zone_desc->lock_wait_count++;
1201 
1202         s64 start = timeus();
1203 
1204         do
1205         {
1206             cond_timedwait(&zone_desc->lock_cond, &zone_desc->lock, usec);
1207 
1208             s64 now = timeus();
1209 
1210             if(now - start >= (s64)usec)
1211             {
1212                 cond_notify(&zone_desc->lock_cond);
1213                 mutex_unlock(&zone_desc->lock);
1214                 return LOCK_TIMEOUT;
1215             }
1216         }
1217         while((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id));
1218 
1219         zone_desc->lock_wait_count--;
1220     }
1221 
1222     zone_desc->lock_owner = owner_id & 0x7f;
1223     zone_desc->lock_owner_count++;
1224 
1225     return_value = owner_id;
1226 
1227 #if ZONE_LOCK_HAS_OWNER_ID
1228     zone_desc->lock_last_owner_tid = thread_self();
1229 #endif
1230 
1231     if((owner_id & 0x80) == 0)
1232     {
1233         cond_notify(&zone_desc->lock_cond);
1234     }
1235 
1236     mutex_unlock(&zone_desc->lock);
1237 
1238     return return_value;
1239 }
1240 
1241 void
zone_unlock(zone_desc_s * zone_desc,u8 owner_mark)1242 zone_unlock(zone_desc_s *zone_desc, u8 owner_mark)
1243 {
1244 #if DEBUG
1245     log_debug6("zone_unlock(%{dnsname}@%p, %02x)", zone_origin(zone_desc), zone_desc, owner_mark);
1246     debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_unlock");
1247 #endif
1248 
1249     mutex_lock(&zone_desc->lock);
1250 
1251     yassert(zone_desc->lock_owner == (owner_mark & 0x7f));
1252     yassert(zone_desc->lock_owner_count > 0);
1253 
1254     if((--zone_desc->lock_owner_count) == 0)
1255     {
1256         zone_desc->lock_owner = ZONE_LOCK_NOBODY;
1257     }
1258 
1259 #if ZONE_LOCK_HAS_OWNER_ID
1260     thread_t tid = thread_self();
1261     if(zone_desc->lock_last_owner_tid == tid)
1262     {
1263         zone_desc->lock_last_owner_tid = 0;
1264     }
1265 #endif
1266 
1267     cond_notify(&zone_desc->lock_cond);
1268 
1269     mutex_unlock(&zone_desc->lock);
1270 
1271     (void)owner_mark; // silence warning on NDEBUG builds
1272 }
1273 
1274 bool
zone_islocked(zone_desc_s * zone_desc)1275 zone_islocked(zone_desc_s *zone_desc)
1276 {
1277     mutex_lock(&zone_desc->lock);
1278     bool ret = (zone_desc->lock_owner != ZONE_LOCK_NOBODY);
1279     mutex_unlock(&zone_desc->lock);
1280 
1281     return ret;
1282 }
1283 
1284 /**
1285  * Sets non-static values in a zone descriptor
1286  *
1287  * @param zone_desc
1288  */
1289 
1290 void
zone_setdefaults(zone_desc_s * zone_desc)1291 zone_setdefaults(zone_desc_s *zone_desc)
1292 {
1293     u32 port;
1294 
1295     if(FAIL(parse_u32_check_range(g_config->server_port, &port, 1, MAX_U16, BASE_10)))
1296     {
1297         port = DNS_DEFAULT_PORT;
1298     }
1299 
1300     zone_desc->_status_flags = ZONE_STATUS_STARTING_UP;
1301 
1302 #if HAS_ACL_SUPPORT
1303     acl_merge_access_control(&zone_desc->ac, g_config->ac);
1304 #endif
1305 
1306 #if HAS_RRSIG_MANAGEMENT_SUPPORT && HAS_DNSSEC_SUPPORT
1307 
1308     /*
1309      * The newly generated signatures will be valid for that amount of days
1310      */
1311 
1312     if(zone_desc->signature.sig_validity_interval == MAX_S32)
1313     {
1314         zone_desc->signature.sig_validity_interval = MIN(g_config->sig_validity_interval, SIGNATURE_VALIDITY_INTERVAL_MAX);  /* days */
1315     }
1316 
1317     if(zone_desc->signature.sig_validity_regeneration == MAX_S32)
1318     {
1319         zone_desc->signature.sig_validity_regeneration = MIN(g_config->sig_validity_regeneration, SIGNATURE_VALIDITY_REGENERATION_MAX);
1320     }
1321 
1322     /*
1323      * The validity of newly generated signature will be off by at most this
1324      */
1325 
1326     if(zone_desc->signature.sig_validity_jitter == MAX_S32)
1327     {
1328         zone_desc->signature.sig_validity_jitter = MIN(g_config->sig_validity_jitter, SIGNATURE_VALIDITY_JITTER_MAX);
1329     }
1330 
1331     /*
1332      * The first epoch when a signature will be marked as invalid.
1333      */
1334 
1335     zone_desc->signature.sig_invalid_first = MAX_S32;
1336 
1337     zone_desc->signature.scheduled_sig_invalid_first = MAX_S32;
1338 #endif
1339 
1340 #if HAS_DYNAMIC_PROVISIONING
1341     memset(&zone_desc->dynamic_provisioning, 0, sizeof(dynamic_provisioning_s));
1342     //zone->dynamic_provisioning.flags |= ZONE_CTRL_FLAG_GENERATE_ZONE;
1343 #endif
1344 
1345     zone_desc->notify.retry_count = atoi(S_NOTIFY_RETRY_COUNT);
1346     zone_desc->notify.retry_period = atoi(S_NOTIFY_RETRY_PERIOD) * 60;
1347     zone_desc->notify.retry_period_increase = atoi(S_NOTIFY_RETRY_PERIOD_INCREASE) * 60;
1348 
1349     host_address_set_default_port_value(zone_desc->masters, ntohs(port));
1350     host_address_set_default_port_value(zone_desc->notifies, ntohs(port));
1351 
1352     // seems incorrect here : acl_access_control_copy(&zone_desc->ac, &g_config->ac);
1353 }
1354 
1355 /**
1356  * Merges the settings of a zone into another zone descriptor.
1357  *
1358  * @param desc_zone_desc
1359  * @param src_zone_desc
1360  * @return 0 if the zone are equals
1361  *         1 if some parts have been edited
1362  *         or an error code
1363  */
1364 
1365 ya_result
zone_setwithzone(zone_desc_s * desc_zone_desc,zone_desc_s * src_zone_desc)1366 zone_setwithzone(zone_desc_s *desc_zone_desc, zone_desc_s *src_zone_desc)
1367 {
1368     bool changed = FALSE;
1369 
1370     if(desc_zone_desc->domain != NULL)
1371     {
1372         if(strcmp(zone_domain(desc_zone_desc), zone_domain(src_zone_desc)) != 0)
1373         {
1374             log_debug1("zone_setwithzone: domain does not match '%s'!='%s'", zone_domain(desc_zone_desc), zone_domain(src_zone_desc));
1375             return INVALID_STATE_ERROR;
1376         }
1377     }
1378     else
1379     {
1380         desc_zone_desc->domain = strdup(zone_domain(src_zone_desc));
1381         desc_zone_desc->qclass = src_zone_desc->qclass;
1382         desc_zone_desc->type = src_zone_desc->type;
1383 #if ZDB_HAS_DNSSEC_SUPPORT
1384         desc_zone_desc->dnssec_mode = src_zone_desc->dnssec_mode;
1385 #endif
1386         desc_zone_desc->dynamic_provisioning.flags = desc_zone_desc->dynamic_provisioning.flags;
1387         desc_zone_desc->_origin = dnsname_dup(zone_origin(src_zone_desc));
1388         desc_zone_desc->_status_flags = src_zone_desc->_status_flags;
1389         if(src_zone_desc->file_name != NULL)
1390         {
1391             desc_zone_desc->file_name = strdup(src_zone_desc->file_name);
1392         }
1393 
1394         changed = TRUE;
1395     }
1396 
1397 #if HAS_ACL_SUPPORT
1398     acl_access_control_copy(&desc_zone_desc->ac, &src_zone_desc->ac);
1399 #endif
1400 
1401 #if HAS_RRSIG_MANAGEMENT_SUPPORT && HAS_DNSSEC_SUPPORT
1402 
1403     /*
1404      * The newly generated signatures will be valid for that amount of days
1405      */
1406 
1407     if(desc_zone_desc->signature.sig_validity_interval != src_zone_desc->signature.sig_validity_interval)
1408     {
1409         desc_zone_desc->signature.sig_validity_interval = src_zone_desc->signature.sig_validity_interval;
1410         changed = TRUE;
1411     }
1412 
1413     if(desc_zone_desc->signature.sig_validity_regeneration != src_zone_desc->signature.sig_validity_regeneration)
1414     {
1415         desc_zone_desc->signature.sig_validity_regeneration = src_zone_desc->signature.sig_validity_regeneration;
1416         changed = TRUE;
1417     }
1418 
1419     if(desc_zone_desc->signature.sig_validity_jitter != src_zone_desc->signature.sig_validity_jitter)
1420     {
1421         desc_zone_desc->signature.sig_validity_jitter = src_zone_desc->signature.sig_validity_jitter;
1422         changed = TRUE;
1423     }
1424 
1425     /*
1426      * The first epoch when a signature will be marked as invalid.
1427      */
1428 
1429     if(desc_zone_desc->signature.sig_invalid_first != src_zone_desc->signature.sig_invalid_first)
1430     {
1431         desc_zone_desc->signature.sig_invalid_first = src_zone_desc->signature.sig_invalid_first;
1432         changed = TRUE;
1433     }
1434 
1435     if(desc_zone_desc->signature.scheduled_sig_invalid_first != src_zone_desc->signature.scheduled_sig_invalid_first)
1436     {
1437         desc_zone_desc->signature.scheduled_sig_invalid_first = src_zone_desc->signature.scheduled_sig_invalid_first;
1438         changed = TRUE;
1439     }
1440 
1441 #endif
1442 
1443 #if HAS_DYNAMIC_PROVISIONING
1444     if(memcmp(&desc_zone_desc->dynamic_provisioning, &src_zone_desc->dynamic_provisioning, sizeof(dynamic_provisioning_s)) != 0)
1445     {
1446         memcpy(&desc_zone_desc->dynamic_provisioning, &src_zone_desc->dynamic_provisioning, sizeof(dynamic_provisioning_s));
1447         changed = TRUE;
1448     }
1449 #endif
1450 
1451     if(desc_zone_desc->notify.retry_count != src_zone_desc->notify.retry_count)
1452     {
1453         desc_zone_desc->notify.retry_count = src_zone_desc->notify.retry_count;
1454         changed = TRUE;
1455     }
1456 
1457     if(desc_zone_desc->notify.retry_period != src_zone_desc->notify.retry_period)
1458     {
1459         desc_zone_desc->notify.retry_period = src_zone_desc->notify.retry_period;
1460         changed = TRUE;
1461     }
1462 
1463     if(desc_zone_desc->notify.retry_period_increase != src_zone_desc->notify.retry_period_increase)
1464     {
1465         desc_zone_desc->notify.retry_period_increase = src_zone_desc->notify.retry_period_increase;
1466         changed = TRUE;
1467     }
1468 
1469     if(desc_zone_desc->flags != src_zone_desc->flags)
1470     {
1471         desc_zone_desc->flags = src_zone_desc->flags;
1472         changed = TRUE;
1473     }
1474 
1475     changed |= host_address_update_host_address_list(&desc_zone_desc->masters, src_zone_desc->masters);
1476     changed |= host_address_update_host_address_list(&desc_zone_desc->notifies, src_zone_desc->notifies);
1477     changed |= host_address_update_host_address_list(&desc_zone_desc->slaves, src_zone_desc->slaves);
1478 
1479     if(src_zone_desc->file_name != NULL)
1480     {
1481         if(strcmp(desc_zone_desc->file_name, src_zone_desc->file_name) != 0)
1482         {
1483             free(desc_zone_desc->file_name);
1484             desc_zone_desc->file_name = strdup(src_zone_desc->file_name);
1485             changed = TRUE;
1486         }
1487     }
1488 
1489 #if HAS_MASTER_SUPPORT
1490     // master zone without a file name ...
1491 
1492     if((desc_zone_desc->file_name == NULL) && (desc_zone_desc->type == ZT_MASTER))
1493     {
1494         desc_zone_desc->dynamic_provisioning.flags |= ZONE_CTRL_FLAG_GENERATE_ZONE;
1495         changed = TRUE;
1496     }
1497 #endif
1498 
1499     return (changed)?1:0;   // 1 if changed, 0 is no operation performed
1500 }
1501 
1502 
1503 
1504 /**
1505  *
1506  * helper formatting tool to print the zone descriptor status flags as a chain of characters
1507  *
1508  * @param value
1509  * @param os
1510  * @param padding
1511  * @param pad_char
1512  * @param left_justified
1513  * @param reserved_for_method_parameters
1514  */
1515 
1516 #ifdef SHORT_VERSION_IS_LESS_CLEAR
1517 
1518 
1519 /**
1520  * used by zone_desc_status_flags_format
1521  */
1522 
1523 static const char status_letters[32] = "IclL"
1524                                        "MUdD"
1525                                        "zZaA"
1526                                        "sSeE"
1527                                        "RxX#"
1528                                        "f---"
1529                                        "T---"
1530                                        "ur/!";
1531 
1532 static void
zone_desc_status_flags_format(const void * value,output_stream * os,s32 padding,char pad_char,bool left_justified,void * reserved_for_method_parameters)1533 zone_desc_status_flags_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters)
1534 {
1535     (void)padding;
1536     (void)pad_char;
1537     (void)left_justified;
1538     (void)reserved_for_method_parameters;
1539     u32 status = *((u32*)value);
1540     const char *p = status_letters;
1541     if(status == 0)
1542     {
1543         output_stream_write(os, (const u8*)"i", 1);
1544     }
1545     else
1546     {
1547         do
1548         {
1549             if(status & 1)
1550             {
1551                 output_stream_write(os, p, 1);
1552             }
1553 
1554             p++;
1555             status >>= 1;
1556         }
1557         while(status != 0);
1558     }
1559 }
1560 
1561 #endif
1562 
1563 /**
1564  * used by zone_desc_status_flags_long_format
1565  */
1566 
1567 static const char *status_words[32] =
1568 {
1569     //"IDLE",
1570     "STARTING-UP",              // 0
1571     "MODIFIED",
1572     "LOAD",
1573     "LOADING",
1574     "MOUNTING",
1575     "UNMOUNTING",                // 5
1576     "DROP",
1577     "DROPPING",
1578     "SAVETO-ZONE-FILE",
1579     "SAVING-ZONE-FILE",
1580     "SAVETO-AXFR-FILE",          // 10
1581     "SAVING-AXFR-FILE",
1582     "SIGNATURES-UPDATE",
1583     "SIGNATURES-UPDATING",
1584     "DYNAMIC-UPDATE",
1585     "DYNAMIC-UPDATING",         // 15
1586     "READONLY",
1587     "DOWNLOAD-XFR-FILE",
1588     "DOWNLOADING-XFR-FILE",
1589     "DROP-AFTER-RELOAD",
1590     "FROZEN",                   // 20
1591     "?",
1592     "?",
1593     "?",
1594     "DOWNLOADED",
1595     "?",                        // 25
1596     "?",
1597     "?",
1598     "ZONE-STATUS-UNREGISTERING",
1599     "REGISTERED",
1600     "MARKED-FOR-DESTRUCTION",
1601     "PROCESSING"
1602 };
1603 
1604 void
zone_desc_status_flags_long_format(const void * value,output_stream * os,s32 padding,char pad_char,bool left_justified,void * reserved_for_method_parameters)1605 zone_desc_status_flags_long_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters)
1606 {
1607     (void)padding;
1608     (void)pad_char;
1609     (void)left_justified;
1610     (void)reserved_for_method_parameters;
1611     u32 status = *((u32*)value);
1612     const char **p = status_words;
1613     if(status == 0)
1614     {
1615         output_stream_write(os, (const u8*)"IDLE", 4);
1616     }
1617     else
1618     {
1619         do
1620         {
1621             if(status & 1)
1622             {
1623                 const char *word = *p;
1624                 output_stream_write(os, word, strlen(word));
1625                 output_stream_write(os, (const char*)" ", 1);
1626             }
1627 
1628             p++;
1629             status >>= 1;
1630         }
1631         while(status != 0);
1632     }
1633 }
1634 
1635 #if HAS_ACL_SUPPORT
1636 /**
1637  *
1638  * helper formatting tool to print the ACL fields of the zone descriptor
1639  *
1640  * @param value
1641  * @param os
1642  * @param padding
1643  * @param pad_char
1644  * @param left_justified
1645  * @param reserved_for_method_parameters
1646  */
1647 
1648 static void
zone_desc_ams_format(const void * value,output_stream * os,s32 padding,char pad_char,bool left_justified,void * reserved_for_method_parameters)1649 zone_desc_ams_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters)
1650 {
1651     (void)padding;
1652     (void)pad_char;
1653     (void)left_justified;
1654     (void)reserved_for_method_parameters;
1655     address_match_set *ams = (address_match_set*)value;
1656     acl_address_match_set_to_stream(os, ams);
1657 }
1658 
1659 #endif
1660 
1661 void
zone_desc_log(logger_handle * handle,u32 level,const zone_desc_s * zone_desc,const char * text)1662 zone_desc_log(logger_handle* handle, u32 level, const zone_desc_s *zone_desc, const char *text)
1663 {
1664     if(text == NULL)
1665     {
1666         text = "NULL";
1667     }
1668 
1669     if(zone_desc == NULL)
1670     {
1671         logger_handle_msg(handle, level, "%s: NULL", text);
1672         return;
1673     }
1674 
1675     logger_handle_msg(handle, level, "%s: %{dnsname} @%p '%s' file='%s'",
1676             text, FQDNNULL(zone_origin(zone_desc)), zone_desc, STRNULL(zone_domain(zone_desc)), STRNULL(zone_desc->file_name));
1677     u32 status_flags = zone_get_status(zone_desc);
1678     //format_writer status_flags_fw = {zone_desc_status_flags_format, &status_flags};
1679     format_writer status_flags_fw = {zone_desc_status_flags_long_format, &status_flags};
1680     logger_handle_msg(handle, level, "%s: %{dnsname} status=%w",
1681             text, FQDNNULL(zone_origin(zone_desc)), &status_flags_fw);
1682 #if ZDB_HAS_DNSSEC_SUPPORT
1683     logger_handle_msg(handle, level, "%s: %{dnsname} dnssec=%s type=%s flags=%x lock=%02hhx #olock=%d #wlock=%d",
1684             text, FQDNNULL(zone_origin(zone_desc)), zone_dnssec_to_name(zone_desc->dnssec_mode), zone_type_to_name(zone_desc->type),
1685             zone_desc->flags, zone_desc->lock_owner, zone_desc->lock_owner_count, zone_desc->lock_wait_count);
1686 #else
1687     logger_handle_msg(handle, level, "%s: %{dnsname} type=%s flags=%x lock=%02hhx #olock=%d #wlock=%d",
1688             text, FQDNNULL(zone_origin(zone_desc)), zone_type_to_name(zone_desc->type),
1689             zone_desc->flags, zone_desc->lock_owner, zone_desc->lock_owner_count, zone_desc->lock_wait_count);
1690 #endif
1691     logger_handle_msg(handle, level, "%s: %{dnsname} refreshed=%d retried=%d next=%d",
1692             text, FQDNNULL(zone_origin(zone_desc)), zone_desc->refresh.refreshed_time, zone_desc->refresh.retried_time, zone_desc->refresh.zone_update_next_time);
1693 
1694 #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
1695 
1696     u32 sig_invalid_first = zone_desc->signature.sig_invalid_first;
1697     u32 scheduled_sig_invalid_first = zone_desc->signature.scheduled_sig_invalid_first;
1698 
1699     logger_handle_msg(handle, level, "%s: %{dnsname} interval=%d jitter=%d regeneration=%d invalid=%T scheduled-update=%T",
1700             text, FQDNNULL(zone_origin(zone_desc)),
1701             zone_desc->signature.sig_validity_interval,
1702             zone_desc->signature.sig_validity_jitter,
1703             zone_desc->signature.sig_validity_regeneration,
1704             sig_invalid_first,
1705             scheduled_sig_invalid_first);
1706 
1707     if(zone_desc->dnssec_policy != NULL)
1708     {
1709         logger_handle_msg(handle, level, "%s: %{dnsname} dnssec-policy: '%s'", text, FQDNNULL(zone_origin(zone_desc)), STRNULL(zone_desc->dnssec_policy->name));
1710     }
1711     else
1712     {
1713         logger_handle_msg(handle, level, "%s: %{dnsname} dnssec-policy: none", text, FQDNNULL(zone_origin(zone_desc)));
1714     }
1715 
1716 #endif
1717 
1718     logger_handle_msg(handle, level, "%s: %{dnsname} master=%{hostaddr}",
1719             text, FQDNNULL(zone_origin(zone_desc)), zone_desc->masters);
1720     logger_handle_msg(handle, level, "%s: %{dnsname} notified=%{hostaddrlist}",
1721             text, FQDNNULL(zone_origin(zone_desc)), zone_desc->notifies);
1722 
1723 #if HAS_ACL_SUPPORT
1724     format_writer status_ams_fw = {zone_desc_ams_format, &zone_desc->ac.allow_query};
1725     logger_handle_msg(handle, level, "%s: %{dnsname} allow query=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw);
1726 
1727     status_ams_fw.value = &zone_desc->ac.allow_update;
1728     logger_handle_msg(handle, level, "%s: %{dnsname} allow update=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw);
1729 
1730     status_ams_fw.value = &zone_desc->ac.allow_update_forwarding;
1731     logger_handle_msg(handle, level, "%s: %{dnsname} allow update forwarding=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw);
1732 
1733     status_ams_fw.value = &zone_desc->ac.allow_transfer;
1734     logger_handle_msg(handle, level, "%s: %{dnsname} allow transfer=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw);
1735 
1736     status_ams_fw.value = &zone_desc->ac.allow_notify;
1737     logger_handle_msg(handle, level, "%s: %{dnsname} allow notify=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw);
1738 #endif
1739 
1740 #if HAS_DYNAMIC_PROVISIONING
1741 
1742 #if HAS_ACL_SUPPORT
1743     status_ams_fw.value = &zone_desc->ac.allow_control;
1744 
1745     logger_handle_msg(handle, level, "%s: %{dnsname} allow control=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw);
1746 #endif
1747 
1748     logger_handle_msg(handle, level, "%s: %{dnsname} + dp v=%hx flags=%hx expire=%x refresh=%x retry=%x ts=%x:%x",
1749             text, FQDNNULL(zone_origin(zone_desc)),
1750             zone_desc->dynamic_provisioning.version,
1751             zone_desc->dynamic_provisioning.flags,
1752             zone_desc->dynamic_provisioning.expire,
1753             zone_desc->dynamic_provisioning.refresh,
1754             zone_desc->dynamic_provisioning.retry,
1755             zone_desc->dynamic_provisioning.timestamp,
1756             zone_desc->dynamic_provisioning.timestamp_lo);
1757     logger_handle_msg(handle, level, "%s: %{dnsname} + dp slaves=%{hostaddrlist}",
1758             text, FQDNNULL(zone_origin(zone_desc)), zone_desc->slaves);
1759 
1760     u32 command_count = zone_desc->commands.size;
1761     bpqueue_node_s *command_node = zone_desc->commands.first;
1762     for(u32 i = 0; i < command_count; i++)
1763     {
1764         zone_command_s *cmd = (zone_command_s*)command_node->data;
1765         logger_handle_msg(handle, level, "%s: %{dnsname} @%p & [%-2i] (%i) %s",
1766                 text, FQDNNULL(zone_origin(zone_desc)), zone_desc,
1767                 i, command_node->priority, database_service_operation_get_name(cmd->id));
1768 
1769         command_node = command_node->next;
1770     }
1771 
1772 #endif
1773 }
1774 
1775 void
zone_desc_log_all(logger_handle * handle,u32 level,zone_data_set * dset,const char * text)1776 zone_desc_log_all(logger_handle* handle, u32 level, zone_data_set *dset, const char *text)
1777 {
1778     zone_set_lock(dset); // unlock checked
1779 
1780     if(!ptr_set_isempty(&dset->set))
1781     {
1782         ptr_set_iterator iter;
1783         ptr_set_iterator_init(&dset->set, &iter);
1784 
1785         while(ptr_set_iterator_hasnext(&iter))
1786         {
1787             ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
1788             zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value;
1789 
1790             zone_desc_log(handle, level, zone_desc, text);
1791         }
1792 
1793         zone_set_unlock(dset);
1794     }
1795     else
1796     {
1797         zone_set_unlock(dset);
1798 
1799 #if DEBUG
1800         log_debug("zone_desc_log_all: %s set is empty", text);
1801 #endif
1802     }
1803 }
1804 
1805 /**
1806  *
1807  * Calls the callback for all zone_desc.
1808  *
1809  * @param cb
1810  * @param args
1811  */
1812 
1813 ya_result
zone_desc_for_all(zone_desc_for_all_callback * cb,void * args)1814 zone_desc_for_all(zone_desc_for_all_callback *cb, void *args)
1815 {
1816     ya_result ret = SUCCESS;
1817 
1818     zone_set_lock(&database_zone_desc); // unlock checked
1819 
1820     if(!ptr_set_isempty(&database_zone_desc.set))
1821     {
1822         ptr_set_iterator iter;
1823         ptr_set_iterator_init(&database_zone_desc.set, &iter);
1824 
1825         while(ptr_set_iterator_hasnext(&iter))
1826         {
1827             ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
1828             zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value;
1829 
1830             if(FAIL(ret = cb(zone_desc, args)))
1831             {
1832                 return ret;
1833             }
1834         }
1835     }
1836 
1837     zone_set_unlock(&database_zone_desc);
1838 
1839     return ret;
1840 }
1841 
1842 const char*
zone_type_to_name(zone_type t)1843 zone_type_to_name(zone_type t)
1844 {
1845     if((t >= ZT_HINT) && (t <= ZT_STUB))
1846     {
1847         return type_to_name[t];
1848     }
1849 
1850     return "invalid";
1851 }
1852 
1853 const char*
zone_dnssec_to_name(u32 dnssec_flags)1854 zone_dnssec_to_name(u32 dnssec_flags)
1855 {
1856     dnssec_flags &= ZONE_DNSSEC_FL_MASK;
1857     if(dnssec_flags < 4)
1858     {
1859         return dnssec_to_name[dnssec_flags];
1860     }
1861 
1862     return "invalid";
1863 }
1864 
1865 void
zone_enqueue_command(zone_desc_s * zone_desc,u32 id,void * parm,bool has_priority)1866 zone_enqueue_command(zone_desc_s *zone_desc, u32 id, void* parm, bool has_priority)
1867 {
1868     if(!has_priority && ((zone_get_status(zone_desc) & ZONE_STATUS_MARKED_FOR_DESTRUCTION) != 0))
1869     {
1870         log_err("tried to queue to a zone marked for destruction");
1871         return;
1872     }
1873 
1874 #if DEBUG
1875     log_debug("zone_desc: enqueue command %{dnsname}@%p=%i %c %s",
1876     zone_origin(zone_desc), zone_desc, zone_desc->rc, (has_priority)?'H':'L', database_service_operation_get_name(id));
1877 #endif
1878 
1879     if(zone_desc->commands_bits & (1 << id))
1880     {
1881 #if DEBUG
1882         log_debug("zone_desc: enqueue command %{dnsname}@%p=%i %c %s: already queued",
1883                   zone_origin(zone_desc), zone_desc, zone_desc->rc, (has_priority)?'H':'L', database_service_operation_get_name(id));
1884 #endif
1885         return; // already queued
1886     }
1887 
1888     zone_command_s *cmd;
1889     ZALLOC_OBJECT_OR_DIE( cmd, zone_command_s, ZONECMD_TAG);
1890     cmd->parm.ptr = parm;
1891     cmd->id = id;
1892     bpqueue_enqueue(&zone_desc->commands, cmd, (has_priority)?0:1);
1893 }
1894 
1895 zone_command_s*
zone_dequeue_command(zone_desc_s * zone_desc)1896 zone_dequeue_command(zone_desc_s *zone_desc)
1897 {
1898     zone_command_s *cmd = (zone_command_s*)bpqueue_dequeue(&zone_desc->commands);
1899 
1900 #if DEBUG
1901     if(cmd != NULL)
1902     {
1903         log_debug("zone_desc: dequeue command %{dnsname}@%p=%i - %s",
1904                 zone_origin(zone_desc), zone_desc, zone_desc->rc, database_service_operation_get_name(cmd->id));
1905     }
1906     else
1907     {
1908         log_debug("zone_desc: dequeue command %{dnsname}@%p=%i - NULL",
1909                 zone_origin(zone_desc), zone_desc, zone_desc->rc);
1910     }
1911 #endif
1912 
1913     if(cmd != NULL)
1914     {
1915         zone_desc->commands_bits &= ~(1 << cmd->id);
1916     }
1917 
1918     return cmd;
1919 }
1920 
1921 void
zone_command_free(zone_command_s * cmd)1922 zone_command_free(zone_command_s *cmd)
1923 {
1924     ZFREE_OBJECT(cmd);
1925 }
1926 
1927 zdb_zone *
zone_get_loaded_zone(zone_desc_s * zone_desc)1928 zone_get_loaded_zone(zone_desc_s *zone_desc)
1929 {
1930     yassert(zone_islocked(zone_desc));
1931 
1932     zdb_zone *zone = zone_desc->loaded_zone; // OK
1933     if(zone != NULL)
1934     {
1935         zdb_zone_acquire(zone);
1936     }
1937     return zone;
1938 }
1939 
1940 zdb_zone *
zone_set_loaded_zone(zone_desc_s * zone_desc,zdb_zone * zone)1941 zone_set_loaded_zone(zone_desc_s *zone_desc, zdb_zone *zone)
1942 {
1943     yassert(zone_islocked(zone_desc));
1944 
1945     zdb_zone *old_zone = zone_desc->loaded_zone; // OK
1946     if(zone != NULL)
1947     {
1948         zdb_zone_acquire(zone);
1949     }
1950     zone_desc->loaded_zone = zone; // OK
1951 
1952     return old_zone;
1953 }
1954 
1955 bool
zone_has_loaded_zone(zone_desc_s * zone_desc)1956 zone_has_loaded_zone(zone_desc_s *zone_desc)
1957 {
1958     yassert(zone_islocked(zone_desc));
1959 
1960     zdb_zone *zone = zone_desc->loaded_zone; // OK
1961     return zone != NULL;
1962 }
1963 
1964 void
zone_set_status(zone_desc_s * zone_desc,u32 flags)1965 zone_set_status(zone_desc_s *zone_desc, u32 flags)
1966 {
1967 #if DEBUG
1968     log_debug("zone: %{dnsname}: %p: status %08x + %08x -> %08x", zone_origin(zone_desc), zone_desc, zone_desc->_status_flags, flags, zone_desc->_status_flags|flags);
1969 #endif
1970     zone_desc->_status_flags |= flags;
1971 }
1972 
1973 u32
zone_get_set_status(zone_desc_s * zone_desc,u32 flags)1974 zone_get_set_status(zone_desc_s *zone_desc, u32 flags)
1975 {
1976 #if DEBUG
1977     log_debug("zone: %{dnsname}: %p: status %08x + %08x -> %08x", zone_origin(zone_desc), zone_desc, zone_desc->_status_flags, flags, zone_desc->_status_flags|flags);
1978 #endif
1979     u32 ret = zone_desc->_status_flags & flags;
1980     zone_desc->_status_flags |= flags;
1981     return ret;
1982 }
1983 
1984 void
zone_clear_status(zone_desc_s * zone_desc,u32 flags)1985 zone_clear_status(zone_desc_s *zone_desc, u32 flags)
1986 {
1987 #if DEBUG
1988     log_debug("zone: %{dnsname}: %p: status %08x - %08x -> %08x", zone_origin(zone_desc), zone_desc, zone_desc->_status_flags, flags, zone_desc->_status_flags&~flags);
1989 #endif
1990 
1991     zone_desc->_status_flags &= ~flags;
1992     if((flags & ZONE_STATUS_PROCESSING) == 0)
1993     {
1994         // poke
1995         database_fire_zone_processed(zone_desc);
1996     }
1997 }
1998 
1999 u32
zone_get_status(const zone_desc_s * zone_desc)2000 zone_get_status(const zone_desc_s *zone_desc)
2001 {
2002     return zone_desc->_status_flags;
2003 }
2004 
2005 #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
2006 void
zone_dnssec_status_update(zdb_zone * zone)2007 zone_dnssec_status_update(zdb_zone *zone)
2008 {
2009     u8 zone_dnssec_type = zone_policy_guess_dnssec_type(zone);
2010     u8 maintain_mode = zone_get_maintain_mode(zone);
2011 
2012     bool update_chain0 = FALSE;
2013 
2014     switch(zone_dnssec_type)
2015     {
2016         case ZONE_DNSSEC_FL_NOSEC:
2017         {
2018             if((maintain_mode & ZDB_ZONE_MAINTAIN_MASK) != 0)
2019             {
2020                 zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC | ZDB_RR_LABEL_NSEC3 | ZDB_RR_LABEL_NSEC3_OPTOUT));
2021                 zone_set_maintain_mode(zone, 0);
2022             }
2023             break;
2024         }
2025         case ZONE_DNSSEC_FL_NSEC:
2026         {
2027             if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC) == 0)
2028             {
2029                 zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC);
2030                 zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC3 | ZDB_RR_LABEL_NSEC3_OPTOUT));
2031                 zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC);
2032             }
2033             break;
2034         }
2035         case ZONE_DNSSEC_FL_NSEC3:
2036         {
2037             if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC3) == 0)
2038             {
2039                 zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC3);
2040                 zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC | ZDB_RR_LABEL_NSEC3_OPTOUT));
2041                 zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3);
2042                 update_chain0 = TRUE;
2043             }
2044             break;
2045         }
2046         case ZONE_DNSSEC_FL_NSEC3_OPTOUT:
2047         {
2048             if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC3) == 0)
2049             {
2050                 zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC3 | ZDB_RR_LABEL_NSEC3_OPTOUT);
2051                 zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC));
2052                 zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT);
2053                 update_chain0 = TRUE;
2054             }
2055             break;
2056         }
2057     }
2058 
2059     if(update_chain0)
2060     {
2061         zdb_zone_lock(zone, ZDB_ZONE_MUTEX_LOAD);
2062         nsec3_zone_update_chain0_links(zone);
2063         zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_LOAD);
2064     }
2065 }
2066 
2067 u8
zone_policy_guess_dnssec_type(zdb_zone * zone)2068 zone_policy_guess_dnssec_type(zdb_zone *zone)
2069 {
2070     u8 zone_dnssec_type = ZONE_DNSSEC_FL_NOSEC;
2071 
2072     if(zdb_zone_has_nsec_records(zone))
2073     {
2074         zone_dnssec_type = ZONE_DNSSEC_FL_NSEC;
2075     }
2076     else if(zdb_zone_has_nsec3_records(zone))
2077     {
2078         if(zdb_zone_has_nsec3_optout_chain(zone))
2079         {
2080             zone_dnssec_type = ZONE_DNSSEC_FL_NSEC3_OPTOUT;
2081         }
2082         else
2083         {
2084              zone_dnssec_type = ZONE_DNSSEC_FL_NSEC3;
2085         }
2086     }
2087 
2088     return zone_dnssec_type;
2089 }
2090 
2091 bool
zone_policy_key_suite_is_marked_processed(zone_desc_s * zone_desc,const struct dnssec_policy_key_suite * kr)2092 zone_policy_key_suite_is_marked_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr)
2093 {
2094     mutex_lock(&zone_desc->lock);
2095     ptr_node *node = ptr_set_find(&zone_desc->dnssec_policy_processed_key_suites, kr->name);
2096     mutex_unlock(&zone_desc->lock);
2097     return node != NULL;
2098 }
2099 
2100 bool
zone_policy_key_suite_mark_processed(zone_desc_s * zone_desc,const struct dnssec_policy_key_suite * kr)2101 zone_policy_key_suite_mark_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr)
2102 {
2103     bool ret = FALSE;
2104     mutex_lock(&zone_desc->lock);
2105     ptr_node *node = ptr_set_insert(&zone_desc->dnssec_policy_processed_key_suites, kr->name);
2106 
2107     if(node->value != NULL)
2108     {
2109         node->value = (struct dnssec_policy_key_suite*)kr;
2110         ret = TRUE;
2111     }
2112     mutex_unlock(&zone_desc->lock);
2113     return ret;
2114 }
2115 
2116 void
zone_policy_key_suite_unmark_processed(zone_desc_s * zone_desc,const struct dnssec_policy_key_suite * kr)2117 zone_policy_key_suite_unmark_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr)
2118 {
2119     mutex_lock(&zone_desc->lock);
2120     ptr_set_delete(&zone_desc->dnssec_policy_processed_key_suites, kr->name);
2121     mutex_unlock(&zone_desc->lock);
2122 }
2123 
2124 #endif
2125 
2126 /** @} */
2127