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 database Routines for database manipulations
36  *  @ingroup yadifad
37  *  @brief database functions
38  *
39  *  Implementation of routines for the database
40  *   - add zone file(s)
41  *   - clear zone file(s)
42  *   - print zone files(s)
43  *   - load db
44  *   - unload db
45  *   - lookup database result of a message
46  *
47  * @{
48  */
49 /*------------------------------------------------------------------------------
50  *
51  * USE INCLUDES */
52 
53 #define DATABASE_SERVICE_C 1
54 
55 #include "server-config.h"
56 
57 #define DATABASE_ZONE_RRSIG_THREAD_POOL 0 // now obsolete
58 
59 #include <dnscore/format.h>
60 #include <dnscore/serial.h>
61 #include <dnscore/threaded_queue.h>
62 #include <dnscore/thread_pool.h>
63 #include <dnscore/bytearray_output_stream.h>
64 #include <dnscore/file_input_stream.h>
65 #include <dnscore/fdtools.h>
66 #include <dnscore/tcp_io_stream.h>
67 
68 #include <dnscore/service.h>
69 #include <dnscore/async.h>
70 #include <dnscore/chroot.h>
71 #include <dnscore/ptr_set.h>
72 
73 #include <dnsdb/zdb_zone_label.h>
74 #include <dnsdb/zdb_zone.h>
75 #include <dnsdb/zdb_record.h>
76 #include <dnsdb/zdb_zone_write.h>
77 #include <dnsdb/zdb_icmtl.h>
78 #include <dnsdb/zdb_utils.h>
79 #include <dnsdb/zdb-zone-dnssec.h>
80 
81 #include <dnsdb/zdb_zone_load.h>
82 #include <dnsdb/zdb_zone_label.h>
83 #include <dnsdb/zdb-lock.h>
84 #include <dnsdb/zdb.h>
85 #include <dnsdb/zdb-zone-garbage.h>
86 
87 #define ZDB_JOURNAL_CODE 1
88 #include <dnsdb/journal.h>
89 
90 #include <dnscore/zone_reader_text.h>
91 #include <dnscore/zone_reader_axfr.h>
92 
93 extern logger_handle *g_server_logger;
94 #define MODULE_MSG_HANDLE g_server_logger
95 
96 #include "database-service.h"
97 #include "database-service-zone-desc-load.h"
98 #include "database-service-zone-desc-unload.h"
99 #include "database-service-zone-load.h"
100 #include "database-service-zone-unload.h"
101 #include "database-service-zone-mount.h"
102 #include "database-service-zone-unmount.h"
103 #include "database-service-zone-download.h"
104 #if HAS_RRSIG_MANAGEMENT_SUPPORT &&  ZDB_HAS_DNSSEC_SUPPORT
105 #include "database-service-zone-resignature.h"
106 #include "zone-signature-policy.h"
107 #endif
108 #include "database-service-zone-freeze.h"
109 #include "database-service-zone-unfreeze.h"
110 #include "database-service-zone-store.h"
111 
112 #include "server.h"
113 #include "notify.h"
114 #include "ixfr.h"
115 
116 #if HAS_CTRL
117 #include "ctrl.h"
118 #endif
119 
120 #include "zone-signature-policy.h"
121 
122 #include "server_error.h"
123 #include "zone_desc.h"
124 #include "config_error.h"
125 
126 #ifndef HAS_DYNUPDATE_DIFF_ENABLED
127 #error "HAS_DYNUPDATE_DIFF_ENABLED not defined"
128 #endif
129 
130 #define DBLOADQ_TAG 0x5144414f4c4244
131 #define DBMSGCB_TAG 0x424347534d4244
132 
133 //#define DATABASE_SERVICE_QUEUE_SIZE 0x4000
134 #define DATABASE_SERVICE_QUEUE_SIZE 0x1000000
135 #define DATABASE_SERVICE_DOWNLOAD_QUEUE_SIZE 0x10000
136 #define DATABASE_SERVICE_LOAD_QUEUE_SIZE 0x10000
137 #define DATABASE_SERVICE_UNLOAD_QUEUE_SIZE 0x10000
138 #define DATABASE_SERVICE_STORE_QUEUE_SIZE 0x10000
139 #define DATABASE_SERVICE_RESIGN_QUEUE_SIZE 0x10000
140 #define DATABASE_SERVICE_CALLBACK_QUEUE_SIZE 0x1000
141 
142 #if DEBUG
143 #define DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND 1
144 #else
145 #define DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND 0
146 #endif
147 
148 static void database_callback_run(database_message *message);
149 static void database_clear_drop_after_reload();
150 static void database_do_drop_after_reload();
151 
152 
153 static struct service_s database_handler = UNINITIALIZED_SERVICE;
154 static async_queue_s database_handler_queue;
155 static bool database_handler_initialised = FALSE;
156 static int database_service(struct service_worker_s *worker);
157 
158 /* Zone file variables */
159 zone_data_set database_zone_desc = {PTR_SET_DNSNAME_EMPTY, GROUP_MUTEX_INITIALIZER, 0};
160 /* Zones meant to be merged with zones */
161 
162 
163 static struct thread_pool_s *database_zone_load_thread_pool = NULL;
164 static struct thread_pool_s *database_zone_store_thread_pool = NULL;
165 static struct thread_pool_s *database_zone_unload_thread_pool = NULL;
166 static struct thread_pool_s *database_zone_download_thread_pool = NULL;
167 static struct thread_pool_s *database_callback_thread_pool = NULL;
168 
169 #if ZDB_HAS_DNSSEC_SUPPORT
170 #if HAS_RRSIG_MANAGEMENT_SUPPORT
171 static struct thread_pool_s *database_zone_resignature_thread_pool = NULL;
172 #if DATABASE_ZONE_RRSIG_THREAD_POOL
173 static struct thread_pool_s *database_zone_rrsig_thread_pool = NULL;
174 #endif
175 #endif
176 #endif
177 
178 static const u8 database_all_origins[] = "\003ALL\005ZONES";
179 
180 static const char* database_service_operation[DATABASE_SERVICE_OPERATION_COUNT]=
181 {
182     "NOTHING",
183 
184     "ZONE-DESC-LOAD",
185     "ZONE-DESC-UNLOAD",
186 
187     "ZONE-LOAD",
188     "ZONE-LOADED-EVENT",
189 
190     "ZONE-MOUNT",
191     "ZONE-MOUNTED-EVENT",
192 
193     "ZONE-UNMOUNT",
194     "ZONE-UNMOUNTED-EVENT",
195 
196     "ZONE-UNLOAD",
197     "ZONE-UNLOADED-EVENT",
198 
199     "ZONE-SAVE-TEXT",
200 
201     "ZONE-QUERY-AXFR",
202     "ZONE-QUERY-IXFR",
203 
204     "ZONE-DOWNLOADED-EVENT",
205 
206     "SET-DROP-AFTER-RELOAD",
207     "CLEAR-DROP-AFTER-RELOAD",
208     "DO-DROP-AFTER-RELOAD",
209 
210     "ZONE-RECONFIGURE-BEGIN",
211     "ZONE-RECONFIGURE-END",
212 
213     "ZONE-UPDATE-SIGNATURES",
214 
215     "ZONE-FREEZE",
216     "ZONE-UNFREEZE",
217 
218     "ZONE-PROCESS",
219 
220     "CALLBACK"
221 };
222 
223 static smp_int database_reconfigure_enable_count = SMP_INT_INITIALIZER;
224 
225 const char*
database_service_operation_get_name(u32 id)226 database_service_operation_get_name(u32 id)
227 {
228     if(id < DATABASE_SERVICE_OPERATION_COUNT)
229     {
230         return database_service_operation[id];
231     }
232 
233     return "?";
234 }
235 
236 static database_message *
database_load_message_alloc(const u8 * origin,u8 type)237 database_load_message_alloc(const u8 *origin, u8 type)
238 {
239     database_message *message;
240     ZALLOC_OBJECT_OR_DIE(message, database_message, DBLOADQ_TAG);
241     ZEROMEMORY(message, sizeof(database_message));
242 
243     message->origin = dnsname_dup(origin);
244     message->payload.type = type;
245 
246     return message;
247 }
248 
249 static void
database_load_message_free(database_message * message)250 database_load_message_free(database_message *message)
251 {
252     if(message != NULL)
253     {
254         dnsname_free(message->origin);
255         ZFREE_OBJECT(message);
256     }
257 }
258 
259 /**********************************************************************************************************************/
260 
261 static void database_service_finalize_destroy_threadpools();
262 
263 ya_result
database_service_init()264 database_service_init()
265 {
266     int err = SERVICE_ALREADY_INITIALISED;
267 
268     if(!database_handler_initialised)
269     {
270 #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
271         if(FAIL(err = database_service_zone_resignature_init()))
272         {
273             return err;
274         }
275 #endif
276         if(database_zone_load_thread_pool == NULL)
277         {
278             database_zone_load_thread_pool = thread_pool_init_ex(g_config->zone_load_thread_count, DATABASE_SERVICE_LOAD_QUEUE_SIZE, "dbload");
279 
280             if(database_zone_load_thread_pool == NULL)
281             {
282                 return SERVICE_INITIALISATION_ERROR;
283             }
284         }
285 
286         if(database_zone_store_thread_pool == NULL)
287         {
288             database_zone_store_thread_pool = thread_pool_init_ex(g_config->zone_store_thread_count, DATABASE_SERVICE_STORE_QUEUE_SIZE, "dbstore");
289 
290             if(database_zone_store_thread_pool == NULL)
291             {
292                 database_service_finalize_destroy_threadpools();
293                 return SERVICE_INITIALISATION_ERROR;
294             }
295         }
296 
297         if(database_zone_unload_thread_pool == NULL)
298         {
299             database_zone_unload_thread_pool = thread_pool_init_ex(1, DATABASE_SERVICE_UNLOAD_QUEUE_SIZE, "dbunload");
300 
301             if(database_zone_unload_thread_pool == NULL)
302             {
303                 database_service_finalize_destroy_threadpools();
304                 return SERVICE_INITIALISATION_ERROR;
305             }
306         }
307 
308         if(database_zone_download_thread_pool == NULL)
309         {
310             database_zone_download_thread_pool = thread_pool_init_ex(g_config->zone_download_thread_count, DATABASE_SERVICE_DOWNLOAD_QUEUE_SIZE, "dbdownld");
311 
312             if(database_zone_download_thread_pool == NULL)
313             {
314                 database_service_finalize_destroy_threadpools();
315                 return SERVICE_INITIALISATION_ERROR;
316             }
317         }
318 
319         if(database_callback_thread_pool == NULL)
320         {
321             database_callback_thread_pool = thread_pool_init_ex(1, DATABASE_SERVICE_CALLBACK_QUEUE_SIZE, "callback"); /// @note thread count MUST be set to 1
322 
323             if(database_callback_thread_pool == NULL)
324             {
325                 database_service_finalize_destroy_threadpools();
326                 return SERVICE_INITIALISATION_ERROR;
327             }
328         }
329 
330 #if ZDB_HAS_DNSSEC_SUPPORT
331 #if HAS_RRSIG_MANAGEMENT_SUPPORT
332         if(database_zone_resignature_thread_pool == NULL)
333         {
334             database_zone_resignature_thread_pool = thread_pool_init_ex((!g_config->hidden_master)?1:8, DATABASE_SERVICE_RESIGN_QUEUE_SIZE, "dbresign"); /// @note thread count MUST be set to 1
335 
336             if(database_zone_resignature_thread_pool == NULL)
337             {
338                 database_service_finalize_destroy_threadpools();
339                 return SERVICE_INITIALISATION_ERROR;
340             }
341         }
342 
343 #if DATABASE_ZONE_RRSIG_THREAD_POOL
344         if(database_zone_rrsig_thread_pool == NULL)
345         {
346             database_zone_rrsig_thread_pool = thread_pool_init_ex(/*g_config->dnssec_thread_count + 1*/2, 32, "dbrrsig");
347 
348             if(database_zone_rrsig_thread_pool == NULL)
349             {
350                 database_service_finalize_destroy_threadpools();
351                 return SERVICE_INITIALISATION_ERROR;
352             }
353         }
354 #endif
355 
356 #endif
357 #endif
358 
359         async_message_pool_init();
360 
361         if(ISOK(err = service_init_ex(&database_handler, database_service, "DBsrvice", 1)))
362         {
363             async_queue_init(&database_handler_queue, DATABASE_SERVICE_QUEUE_SIZE, 1, /*100000*/1, "dbsrvice");
364             database_handler_initialised = TRUE;
365         }
366     }
367 
368     return err;
369 }
370 
371 bool
database_service_started()372 database_service_started()
373 {
374     return database_handler_initialised && !service_stopped(&database_handler);
375 }
376 
377 ya_result
database_service_start()378 database_service_start()
379 {
380     int err = SERVICE_ALREADY_INITIALISED;
381 
382     if(database_handler_initialised)
383     {
384         if(service_stopped(&database_handler))
385         {
386             err = service_start(&database_handler);
387         }
388     }
389 
390     return err;
391 }
392 
393 ya_result
database_service_stop()394 database_service_stop()
395 {
396     int err = SERVICE_NOT_INITIALISED;
397 
398     if(database_handler_initialised)
399     {
400         if(!service_stopped(&database_handler))
401         {
402             err = service_stop(&database_handler);
403             service_wait(&database_handler);
404         }
405     }
406 
407     return err;
408 }
409 
410 static void database_service_message_clear(database_message *message);
411 
412 static void
database_service_finalize_destroy_threadpools()413 database_service_finalize_destroy_threadpools()
414 {
415     if(database_zone_load_thread_pool != NULL)
416     {
417         thread_pool_destroy(database_zone_load_thread_pool);
418         database_zone_load_thread_pool = NULL;
419     }
420 
421     if(database_zone_store_thread_pool != NULL)
422     {
423         thread_pool_destroy(database_zone_store_thread_pool);
424         database_zone_store_thread_pool = NULL;
425     }
426 
427     if(database_zone_unload_thread_pool != NULL)
428     {
429         thread_pool_destroy(database_zone_unload_thread_pool);
430         database_zone_unload_thread_pool = NULL;
431     }
432 
433     if(database_zone_download_thread_pool != NULL)
434     {
435         thread_pool_destroy(database_zone_download_thread_pool);
436         database_zone_download_thread_pool = NULL;
437     }
438 
439     if(database_callback_thread_pool != NULL)
440     {
441         thread_pool_destroy(database_callback_thread_pool);
442         database_callback_thread_pool = NULL;
443     }
444 
445 #if ZDB_HAS_DNSSEC_SUPPORT
446 #if HAS_RRSIG_MANAGEMENT_SUPPORT
447 
448     if(database_zone_resignature_thread_pool != NULL)
449     {
450         thread_pool_destroy(database_zone_resignature_thread_pool);
451         database_zone_resignature_thread_pool = NULL;
452     }
453 
454 #if DATABASE_ZONE_RRSIG_THREAD_POOL
455     if(database_zone_rrsig_thread_pool != NULL)
456     {
457         thread_pool_destroy(database_zone_rrsig_thread_pool);
458         database_zone_rrsig_thread_pool = NULL;
459     }
460 #endif
461 
462 #endif
463 #endif
464 }
465 
466 ya_result
database_service_finalize()467 database_service_finalize()
468 {
469     int err = SUCCESS;
470 
471     if(database_handler_initialised)
472     {
473 #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
474         database_service_zone_resignature_finalize();
475 #endif
476         zone_set_lock(&database_zone_desc); // unlock checked
477 
478         ptr_set_iterator iter;
479         ptr_set_iterator_init(&database_zone_desc.set, &iter);
480 
481         while(ptr_set_iterator_hasnext(&iter))
482         {
483             ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
484             zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value;
485 
486             zone_lock(zone_desc, ZONE_LOCK_UNLOAD);
487             zdb_zone *zone = zone_get_loaded_zone(zone_desc);
488             if(zone != NULL)
489             {
490                 alarm_close(zone->alarm_handle);
491                 zone->alarm_handle = ALARM_HANDLE_INVALID;
492                 zdb_zone_release(zone);
493             }
494 
495             zone_unlock(zone_desc, ZONE_LOCK_UNLOAD);
496         }
497 
498         zone_set_unlock(&database_zone_desc);
499 
500         err = database_service_stop();
501 
502         database_service_finalize_destroy_threadpools();
503 
504         service_finalize(&database_handler);
505 
506         while(!async_queue_empty(&database_handler_queue))
507         {
508             async_message_s *async = async_message_next(&database_handler_queue);
509             database_message *message = (database_message*)async->args;
510             if(message != NULL)
511             {
512                 log_debug("clearing message on %{dnsname}", message->origin);
513 
514                 database_service_message_clear(message);
515                 database_load_message_free(message);
516             }
517             else
518             {
519                 log_debug("clearing empty message");
520             }
521             async_message_release(async);
522         }
523 
524         async_queue_finalize(&database_handler_queue);
525 
526         database_service_run_garbage_collector();
527 
528         /// destroy all the descs
529 
530         log_debug("dropping zone settings");
531 
532         zone_free_all(&database_zone_desc);
533 
534         database_handler_initialised = FALSE;
535     }
536 
537     return err;
538 }
539 
540 /**********************************************************************************************************************/
541 
542 bool
database_origin_is_mounted(const u8 * origin)543 database_origin_is_mounted(const u8 *origin)
544 {
545     // get the zone
546     // look if it is valid or not
547 
548     zdb *db = g_config->database;
549     bool mounted = FALSE;
550 
551     zdb_lock(db, ZDB_MUTEX_READER);
552 
553     zdb_zone_label *zone_label = zdb_zone_label_find_from_dnsname_nolock(db, origin);
554     if(zone_label != NULL)
555     {
556         zdb_zone *zone = zone_label->zone; // OK (ARC)
557         mounted = zdb_zone_isvalid(zone);
558     }
559 
560     zdb_unlock(db, ZDB_MUTEX_READER);
561 
562     return mounted;
563 }
564 
565 bool
database_zone_desc_is_mounted(const u8 * origin)566 database_zone_desc_is_mounted(const u8 *origin)
567 {
568     // get the origin
569     // get the zone
570     // look if it is valid or not
571 
572     bool mounted = database_origin_is_mounted(origin);
573 
574     return mounted;
575 }
576 
577 
578 
579 static void
database_service_set_drop_after_reload()580 database_service_set_drop_after_reload()
581 {
582     zone_set_lock(&database_zone_desc); // unlock checked
583 
584     ptr_set_iterator iter;
585     ptr_set_iterator_init(&database_zone_desc.set, &iter);
586 
587     while(ptr_set_iterator_hasnext(&iter))
588     {
589         ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
590         zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value;
591 
592         zone_set_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD);
593     }
594 
595     zone_set_unlock(&database_zone_desc);
596 }
597 
598 static void
database_service_set_drop_after_reload_for_set(const ptr_set * fqdn_set)599 database_service_set_drop_after_reload_for_set(const ptr_set *fqdn_set)
600 {
601     if(fqdn_set != NULL)
602     {
603         zone_set_lock(&database_zone_desc); // unlock checked
604 
605         ptr_set_iterator iter;
606         ptr_set_iterator_init(fqdn_set, &iter);
607 
608         while(ptr_set_iterator_hasnext(&iter))
609         {
610             ptr_node *fqdn_node = ptr_set_iterator_next_node(&iter);
611             ptr_node *zone_node = ptr_set_find(&database_zone_desc.set, fqdn_node->key);
612             if(zone_node != NULL)
613             {
614                 zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value;
615                 if(zone_desc != NULL)
616                 {
617                     zone_set_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD);
618                     if(zone_desc->loaded_zone != NULL)
619                     {
620 #if HAS_RRSIG_MANAGEMENT_SUPPORT
621                         zdb_zone_set_maintained(zone_desc->loaded_zone, zdb_rr_label_flag_isclear(zone_desc->loaded_zone->apex, ZDB_ZONE_IS_SLAVE));
622 #else
623                         // the preprocessor exclusion could go around the 'if' but
624                         // I'd rather keep this as a "what to do when a zone has been loaded" marker
625 #endif
626                     }
627                 }
628             }
629         }
630 
631         zone_set_unlock(&database_zone_desc);
632     }
633     else
634     {
635         database_service_set_drop_after_reload();
636     }
637 }
638 
639 static void
database_service_clear_drop_after_reload()640 database_service_clear_drop_after_reload()
641 {
642     zone_set_lock(&database_zone_desc); // unlock checked
643 
644     ptr_set_iterator iter;
645     ptr_set_iterator_init(&database_zone_desc.set, &iter);
646 
647     while(ptr_set_iterator_hasnext(&iter))
648     {
649         ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
650         zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value;
651 
652         zone_clear_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD);
653     }
654 
655     zone_set_unlock(&database_zone_desc);
656 }
657 
658 
659 
660 static void
database_service_do_drop_after_reload()661 database_service_do_drop_after_reload()
662 {
663     log_debug1("database_service_do_drop_after_reload()");
664 
665     zone_set_lock(&database_zone_desc); // unlock checked
666 
667     ptr_set_iterator iter;
668     ptr_set_iterator_init(&database_zone_desc.set, &iter);
669 
670     while(ptr_set_iterator_hasnext(&iter))
671     {
672         ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
673         zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value;
674 
675         if((zone_get_status(zone_desc) & ZONE_STATUS_DROP_AFTER_RELOAD) != 0)
676         {
677             // drop the zone & zone desc
678 
679             log_debug2("database_service_do_drop_after_reload: queuing %{dnsname} for unload", zone_origin(zone_desc));
680 
681             database_zone_desc_unload(zone_origin(zone_desc));
682         }
683     }
684 
685     zone_set_unlock(&database_zone_desc);
686 
687     log_debug1("database_service_do_drop_after_reload() done");
688 }
689 
690 static ya_result
database_service_process_command(zone_desc_s * zone_desc,zone_command_s * command)691 database_service_process_command(zone_desc_s *zone_desc, zone_command_s* command)
692 {
693     ya_result ret = SUCCESS;
694 
695     switch(command->id)
696     {
697         case DATABASE_SERVICE_ZONE_DESC_UNLOAD:
698         {
699             database_service_zone_desc_unload(zone_desc);
700             break;
701         }
702 
703         case DATABASE_SERVICE_ZONE_LOAD:
704         {
705             database_service_zone_load(zone_desc);
706             break;
707         }
708         case DATABASE_SERVICE_ZONE_MOUNT:
709         {
710             database_service_zone_mount(zone_desc);
711             break;
712         }
713         case DATABASE_SERVICE_ZONE_UNMOUNT:
714         {
715             database_service_zone_unmount(zone_desc);
716             break;
717         }
718         case DATABASE_SERVICE_ZONE_UNLOAD:
719         {
720             database_service_zone_unload(zone_desc, command->parm.zone);
721             break;
722         }
723 #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
724         case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES:
725         {
726             ret = database_service_zone_dnssec_maintenance(zone_desc);
727             break;
728         }
729 #endif
730         case DATABASE_SERVICE_ZONE_FREEZE:
731         {
732             database_service_zone_freeze(zone_desc);
733             break;
734         }
735         case DATABASE_SERVICE_ZONE_UNFREEZE:
736         {
737             database_service_zone_unfreeze(zone_desc);
738             break;
739         }
740         case DATABASE_SERVICE_ZONE_SAVE_TEXT:
741         {
742             if(ISOK(ret = zone_lock(zone_desc, ZONE_LOCK_SAVE)))
743             {
744                 if(command->parm.ptr != NULL)
745                 {
746                     zone_set_status(zone_desc, ZONE_STATUS_MUST_CLEAR_JOURNAL);
747                 }
748 
749                 zone_unlock(zone_desc, ZONE_LOCK_SAVE);
750 
751                 database_service_zone_store(zone_desc); // text
752             }
753             else
754             {
755                 log_err("database_service_zone_store: failed to lock zone settings for '%{dnsname}'", zone_origin(zone_desc));
756             }
757             break;
758         }
759         case DATABASE_SERVICE_ZONE_PROCESSED:
760         {
761             break;
762         }
763         default:
764         {
765             ret = INVALID_STATE_ERROR;
766             log_err("unexpected command %d", command->id);
767         }
768     }
769 
770     return ret;
771 }
772 
database_service_message_clear_free_fqdn_node(ptr_node * node)773 static void database_service_message_clear_free_fqdn_node(ptr_node *node)
774 {
775     dnsname_zfree(node->key);
776 }
777 
778 static void
database_service_message_clear(database_message * message)779 database_service_message_clear(database_message *message)
780 {
781     switch(message->payload.type)
782     {
783         case DATABASE_SERVICE_ZONE_DESC_LOAD:
784         {
785             zone_release(message->payload.zone_desc_load.zone_desc);
786             message->payload.zone_desc_load.zone_desc = NULL;
787             break;
788         }
789         case DATABASE_SERVICE_ZONE_DESC_UNLOAD:
790         case DATABASE_SERVICE_ZONE_LOAD:
791         case DATABASE_SERVICE_ZONE_UNLOAD:
792         case DATABASE_SERVICE_ZONE_FREEZE:
793         case DATABASE_SERVICE_ZONE_UNFREEZE:
794         case DATABASE_SERVICE_QUERY_AXFR:
795         case DATABASE_SERVICE_QUERY_IXFR:
796         {
797             break;
798         }
799         case DATABASE_SERVICE_SET_DROP_AFTER_RELOAD:
800         {
801             if(message->payload.drop_after_reload.do_subset)
802             {
803                 ptr_set_callback_and_destroy(&message->payload.drop_after_reload.zone_set, database_service_message_clear_free_fqdn_node);
804             }
805             break;
806         }
807         case DATABASE_SERVICE_DO_DROP_AFTER_RELOAD:
808         {
809             break;
810         }
811         case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES:
812         {
813             if(message->payload.zone_update_signatures.expected_zone != NULL)
814             {
815                 zdb_zone_release(message->payload.zone_update_signatures.expected_zone);
816                 message->payload.zone_update_signatures.expected_zone = NULL;
817             }
818             zone_release(message->payload.zone_update_signatures.expected_zone_desc);
819             message->payload.zone_update_signatures.expected_zone_desc = NULL;
820             break;
821         }
822         case DATABASE_SERVICE_ZONE_LOADED_EVENT:
823         {
824             if(message->payload.zone_loaded_event.zone != NULL)
825             {
826                 zdb_zone_release(message->payload.zone_loaded_event.zone);
827                 message->payload.zone_loaded_event.zone = NULL;
828             }
829             break;
830         }
831         case DATABASE_SERVICE_ZONE_MOUNTED_EVENT:
832         {
833             if(message->payload.zone_mounted_event.zone != NULL)
834             {
835                 zdb_zone_release(message->payload.zone_mounted_event.zone);
836                 message->payload.zone_mounted_event.zone = NULL;
837             }
838 
839             zone_release(message->payload.zone_mounted_event.zone_desc);
840             message->payload.zone_mounted_event.zone_desc = NULL;
841             break;
842         }
843         case DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT:
844         {
845             zone_release(message->payload.zone_unmounted_event.zone_desc);
846             message->payload.zone_unmounted_event.zone_desc = NULL;
847             break;
848         }
849         case DATABASE_SERVICE_ZONE_UNLOADED_EVENT:
850         {
851             zone_release(message->payload.zone_unloaded_event.zone_desc);
852             message->payload.zone_unloaded_event.zone_desc = NULL;
853             break;
854         }
855         case DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT:
856         default:
857         {
858             break;
859         }
860         case DATABASE_SERVICE_ZONE_SAVE_TEXT:
861         case DATABASE_SERVICE_ZONE_PROCESSED:
862         {
863             break;
864         }
865         case DATABASE_SERVICE_CALLBACK:
866         {
867             message->payload.callback.callback(message->payload.callback.args, TRUE);
868             break;
869         }
870     }
871 }
872 
873 #if HAS_RRSIG_MANAGEMENT_SUPPORT
874 
875 static zone_desc_s *
database_service_on_update_zone_signatures_event(database_message * message)876 database_service_on_update_zone_signatures_event(database_message *message)
877 {
878     // desc
879     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
880 
881     // current zone desc is the one we wanted to update the signatures on ?
882 
883     if(zone_desc != NULL)
884     {
885         if(zone_desc == message->payload.zone_update_signatures.expected_zone_desc)
886         {
887             zone_lock(zone_desc, ZONE_LOCK_SERVICE);
888             zdb_zone *zone = zone_get_loaded_zone(zone_desc); // RC++
889             zone_unlock(zone_desc, ZONE_LOCK_SERVICE);
890 
891             if(zone != NULL)
892             {
893                 // zone is the one we wanted to update the signatures on ?
894 
895                 if(zone == message->payload.zone_update_signatures.expected_zone)
896                 {
897                     // check
898 
899                     log_debug("database: %{dnsname}: zone signature triggered", zone_origin(zone_desc));
900 
901                     zone_enqueue_command(zone_desc, DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES, NULL, FALSE);
902                 }
903                 else
904                 {
905                     log_warn("database: %{dnsname}: zone signature triggered for another instance of the zone, ignoring", zone_origin(zone_desc));
906 
907                     zone_release(zone_desc);
908                     zone_desc = NULL;
909                 }
910 
911                 zdb_zone_release(zone);
912 #if DEBUG
913                 zone = NULL;
914 #endif
915             }
916         }
917         else
918         {
919             log_warn("database: %{dnsname}: zone signature triggered for another instance of the zone settings, ignoring", zone_origin(message->payload.zone_update_signatures.expected_zone_desc));
920             zone_release(zone_desc);
921 #if DEBUG
922             zone_desc = NULL;
923 #endif
924         }
925     }
926     else  // zone_desc == NULL ie: shutdown, reconfigure
927     {
928         log_warn("database: %{dnsname}: zone signature triggered but zone settings are not available, ignoring", zone_origin(message->payload.zone_update_signatures.expected_zone_desc));
929     }
930 
931     zdb_zone_release(message->payload.zone_update_signatures.expected_zone);
932     message->payload.zone_update_signatures.expected_zone = NULL;
933     zone_release(message->payload.zone_update_signatures.expected_zone_desc);
934     message->payload.zone_update_signatures.expected_zone_desc = NULL;
935 
936     return zone_desc;
937 }
938 
939 #endif
940 
941 static zone_desc_s*
database_service_on_zone_mounted_event(database_message * message)942 database_service_on_zone_mounted_event(database_message* message)
943 {
944     // desc
945     zone_desc_s *zone_desc = message->payload.zone_mounted_event.zone_desc;
946 
947     if(ISOK(message->payload.zone_mounted_event.result_code))
948     {
949         log_info("database: %{dnsname}: zone successfully mounted", message->origin);
950 
951 #if ZDB_HAS_MASTER_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT
952         if(zone_desc->type == ZT_MASTER)
953         {
954             if((message->payload.zone_mounted_event.zone != NULL) &&
955                 zdb_zone_is_store_clear_journal_after_mount(message->payload.zone_mounted_event.zone))
956             {
957                 database_zone_store_ex(message->origin, TRUE);
958 
959                 zdb_zone_clear_store_clear_journal_after_mount(message->payload.zone_mounted_event.zone);
960             }
961 
962             // verify policies
963 
964             ya_result ret;
965 
966             if(ISOK(ret = zone_policy_process(zone_desc)))
967             {
968                 log_debug("database: %{dnsname}: on-mount policy process done", message->origin);
969             }
970             else
971             {
972                 log_err("database: %{dnsname}: on-mount policy process failed: %r", message->origin, ret);
973             }
974 
975             if((message->payload.zone_mounted_event.zone != NULL) && zdb_zone_is_maintained(message->payload.zone_mounted_event.zone))
976             {
977                 if(zone_maintains_dnssec(zone_desc))
978                 {
979                     if(message->payload.zone_mounted_event.zone != NULL)
980                     {
981                         zdb_zone_lock(message->payload.zone_mounted_event.zone, ZDB_ZONE_MUTEX_SIMPLEREADER);
982                         const zdb_packed_ttlrdata *dnskey_rrset = zdb_record_find(&message->payload.zone_mounted_event.zone->apex->resource_record_set, TYPE_DNSKEY); // zone is locked
983                         zdb_zone_unlock(message->payload.zone_mounted_event.zone, ZDB_ZONE_MUTEX_SIMPLEREADER);
984 
985                         if(dnskey_rrset != NULL)
986                         {
987                             log_info("database: %{dnsname}: signature maintenance initialisation", message->origin);
988 
989                             if((zdb_zone_get_flags(message->payload.zone_mounted_event.zone) & ZDB_ZONE_MAINTENANCE_ON_MOUNT) != 0)
990                             {
991                                 message->payload.zone_mounted_event.zone->progressive_signature_update.earliest_signature_expiration = 0;
992                                 database_zone_update_signatures(
993                                         message->origin,
994                                         message->payload.zone_mounted_event.zone_desc,
995                                         message->payload.zone_mounted_event.zone
996                                         );
997                             }
998                         }
999                         else
1000                         {
1001                             log_info("database: %{dnsname}: signature maintenance postponed until keys are activated", message->origin);
1002                         }
1003                     }
1004                     else
1005                     {
1006                         log_debug("database: %{dnsname}: no zone passed with mount event", message->origin);
1007                     }
1008                 }
1009                 else
1010                 {
1011                     log_info("database: %{dnsname}: signature maintenance disabled", message->origin);
1012                 }
1013             }
1014         }
1015         else // ... else slave ?
1016 #endif
1017         if(zone_desc->type == ZT_SLAVE)
1018         {
1019 
1020 #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT
1021             zdb_zone *zone = message->payload.zone_mounted_event.zone;
1022 
1023             u8 zone_dnssec_type = zone_policy_guess_dnssec_type(zone);
1024 
1025             switch(zone_dnssec_type)
1026             {
1027                 case ZONE_DNSSEC_FL_NOSEC:
1028                     log_debug("database: %{dnsname}: slave zone is not DNSSEC", message->origin);
1029                     break;
1030                 case ZONE_DNSSEC_FL_NSEC:
1031                     log_debug("database: %{dnsname}: slave zone is NSEC", message->origin);
1032                     break;
1033                 case ZONE_DNSSEC_FL_NSEC3:
1034                     log_debug("database: %{dnsname}: slave zone is NSEC3", message->origin);
1035                     break;
1036                 case ZONE_DNSSEC_FL_NSEC3_OPTOUT:
1037                     log_debug("database: %{dnsname}: slave zone is NSEC3 OPT-OUT", message->origin);
1038                     break;
1039             }
1040 
1041             zone_dnssec_status_update(zone);
1042 #endif
1043             database_zone_refresh_maintenance(g_config->database, message->origin, 0); // means next refresh from now // database_zone_refresh_maintenance_wih_zone(zone_desc->loaded_zone, 0);
1044         }
1045     }
1046     else
1047     {
1048         log_err("database: %{dnsname}: failed to mount the zone: %r", message->origin, message->payload.zone_mounted_event.result_code);
1049     }
1050 
1051     if(message->payload.zone_mounted_event.zone != NULL)
1052     {
1053         zdb_zone_clear_flags(message->payload.zone_mounted_event.zone, ZDB_ZONE_MAINTENANCE_ON_MOUNT);
1054 
1055         zdb_zone_release(message->payload.zone_mounted_event.zone);
1056         message->payload.zone_mounted_event.zone = NULL;
1057     }
1058 
1059     // do NOT release zone_desc
1060     message->payload.zone_mounted_event.zone_desc = NULL;
1061 
1062     // do not release zone_desc because we will try to push the event
1063 
1064     return zone_desc;
1065 }
1066 
1067 static zone_desc_s*
database_service_on_zone_loaded_event(database_message * message)1068 database_service_on_zone_loaded_event(database_message *message)
1069 {
1070     // desc
1071     zone_desc_s *zone_desc = message->payload.zone_loaded_event.zone_desc;
1072 
1073     if(ISOK(message->payload.zone_loaded_event.result_code))
1074     {
1075         if(message->payload.zone_loaded_event.result_code == 1)
1076         {
1077             log_info("database: %{dnsname}: zone successfully loaded", message->origin);
1078 
1079             if((message->payload.zone_mounted_event.zone != NULL) &&
1080                 zdb_zone_is_store_clear_journal_after_mount(message->payload.zone_mounted_event.zone))
1081             {
1082                 journal_truncate(zone_origin(zone_desc));
1083             }
1084 
1085             zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_MOUNT, NULL, FALSE);
1086         }
1087         else
1088         {
1089             log_debug("database: %{dnsname}: there was no need to load the zone", message->origin);
1090         }
1091     }
1092     else if((message->payload.zone_loaded_event.result_code == ZRE_NO_VALID_FILE_FOUND) && (zone_desc->type == ZT_SLAVE))
1093     {
1094         log_debug("database: %{dnsname}: no local copy of the zone is available: download required", message->origin);
1095     }
1096     else
1097     {
1098         if(message->payload.zone_loaded_event.result_code != STOPPED_BY_APPLICATION_SHUTDOWN)
1099         {
1100             log_err("database: %{dnsname}: failed to load the zone: %r", message->origin, message->payload.zone_loaded_event.result_code);
1101         }
1102         else
1103         {
1104             log_debug("database: %{dnsname}: zone load cancelled by shutdown", message->origin);
1105         }
1106     }
1107 
1108     if(message->payload.zone_loaded_event.zone != NULL)
1109     {
1110         zdb_zone_release(message->payload.zone_loaded_event.zone);
1111         message->payload.zone_loaded_event.zone = NULL;
1112     }
1113 
1114     return zone_desc;
1115 }
1116 
1117 static zone_desc_s*
database_service_on_zone_unmounted_event(database_message * message)1118 database_service_on_zone_unmounted_event(database_message *message)
1119 {
1120     // desc (both)
1121     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1122 
1123     log_info("database: %{dnsname}: zone successfully unmounted", message->origin);
1124 
1125     zone_release(message->payload.zone_unmounted_event.zone_desc);
1126     message->payload.zone_unmounted_event.zone_desc = NULL;
1127     return zone_desc;
1128 }
1129 
1130 static zone_desc_s *
database_service_on_zone_desc_unload(database_message * message)1131 database_service_on_zone_desc_unload(database_message *message)
1132 {
1133     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1134 
1135     if(zone_desc != NULL)
1136     {
1137         if((zone_get_status(zone_desc) & ZONE_STATUS_UNREGISTERING) == 0)
1138         {
1139             zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_DESC_UNLOAD, NULL, FALSE);
1140             zone_set_status(zone_desc, ZONE_STATUS_UNREGISTERING);
1141         }
1142         else
1143         {
1144             log_debug("database: %{dnsname}: cannot unload configuration: zone already unregistering", message->origin);
1145         }
1146     }
1147     else
1148     {
1149         log_debug("database: %{dnsname}: cannot unload configuration: zone is not registered", message->origin);
1150     }
1151 
1152     return zone_desc;
1153 }
1154 
1155 static zone_desc_s*
database_service_on_zone_load(database_message * message)1156 database_service_on_zone_load(database_message *message)
1157 {
1158     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1159 
1160     if(zone_desc != NULL)
1161     {
1162         log_debug("database: %{dnsname}: load, @%p", message->origin, zone_desc);
1163 
1164         if((zone_get_status(zone_desc) & (ZONE_STATUS_LOAD|ZONE_STATUS_LOADING)) == 0)
1165         {
1166             zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_LOAD, NULL, FALSE);
1167         }
1168         else
1169         {
1170             log_debug("database: %{dnsname}: ignoring load command for: already loading", message->origin);
1171         }
1172     }
1173     else
1174     {
1175         log_debug("database: %{dnsname}: cannot load: zone is not configured", message->origin);
1176     }
1177 
1178     return zone_desc;
1179 }
1180 
1181 static zone_desc_s *
database_service_on_service_zone_unload(database_message * message)1182 database_service_on_service_zone_unload(database_message *message)
1183 {
1184     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1185     if(zone_desc != NULL)
1186     {
1187         // zone has been acquired for this call
1188         // references are passed to the command
1189         zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNLOAD, message->payload.zone_unload.zone, TRUE);
1190         message->payload.zone_unload.zone = NULL;
1191     }
1192     else
1193     {
1194         if(message->payload.zone_unload.zone != NULL)
1195         {
1196             zdb_zone_release(message->payload.zone_unload.zone);
1197             message->payload.zone_unload.zone = NULL;
1198         }
1199 
1200         log_debug("database: %{dnsname}: cannot unload: zone is not configured", message->origin);
1201     }
1202 
1203     return zone_desc;
1204 }
1205 
1206 static zone_desc_s *
database_service_on_zone_freeze(database_message * message)1207 database_service_on_zone_freeze(database_message *message)
1208 {
1209     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1210     if(zone_desc != NULL)
1211     {
1212         zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_FREEZE, NULL, FALSE);
1213     }
1214     else
1215     {
1216         log_err("database: %{dnsname}: cannot freeze: zone is not configured", message->origin);
1217     }
1218 
1219     return zone_desc;
1220 }
1221 
1222 static zone_desc_s*
database_service_on_zone_unfreeze(database_message * message)1223 database_service_on_zone_unfreeze(database_message *message)
1224 {
1225     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1226     if(zone_desc != NULL)
1227     {
1228         zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNFREEZE, NULL, FALSE);
1229     }
1230     else
1231     {
1232         log_err("database: %{dnsname}: cannot unfreeze: zone is not configured", message->origin);
1233     }
1234 
1235     return zone_desc;
1236 }
1237 
1238 static zone_desc_s*
database_service_on_zone_store_text(database_message * message)1239 database_service_on_zone_store_text(database_message *message)
1240 {
1241     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1242 
1243     if(zone_desc != NULL)
1244     {
1245         zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_SAVE_TEXT, (message->payload.zone_store.clear)?(void*)1:(void*)0, FALSE);
1246     }
1247     else
1248     {
1249         log_err("database: %{dnsname}: cannot write to disk as text: zone is not configured", message->origin);
1250     }
1251 
1252     return zone_desc;
1253 }
1254 
1255 static zone_desc_s*
database_service_on_zone_downloaded_event(database_message * message)1256 database_service_on_zone_downloaded_event(database_message *message)
1257 {
1258     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1259 
1260     if(ISOK(message->payload.zone_downloaded_event.result_code))
1261     {
1262         //log_info("database: %{dnsname}: zone successfully downloaded (%{dnstype})", message->origin, &message->payload.zone_downloaded_event.download_type);
1263 
1264         if(message->payload.zone_downloaded_event.download_type != TYPE_NONE)
1265         {
1266             log_info("database: %{dnsname}: zone successfully downloaded", message->origin);
1267 
1268             if(message->payload.zone_downloaded_event.download_type == TYPE_AXFR)
1269             {
1270                 database_zone_load(message->origin); // the downloaded file can now be loaded
1271             }
1272         }
1273     }
1274     else
1275     {
1276         log_err("database: %{dnsname}: failed to download the zone: %r", message->origin, message->payload.zone_downloaded_event.result_code);
1277     }
1278 
1279     return zone_desc;
1280 }
1281 
1282 static zone_desc_s *
database_service_on_zone_unloaded_event(database_message * message)1283 database_service_on_zone_unloaded_event(database_message *message)
1284 {
1285     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1286 
1287     if(ISOK(message->payload.zone_unloaded_event.result_code))
1288     {
1289         log_info("database: %{dnsname}: zone successfully unloaded", message->origin);
1290     }
1291     else
1292     {
1293         log_err("database: %{dnsname}: failed to unload the zone: %r", message->origin, message->payload.zone_unloaded_event.result_code);
1294     }
1295 
1296     zone_release(message->payload.zone_unloaded_event.zone_desc);
1297     message->payload.zone_unloaded_event.zone_desc = NULL;
1298 
1299     return zone_desc;
1300 }
1301 
1302 static zone_desc_s*
database_serice_on_zone_processed(database_message * message)1303 database_serice_on_zone_processed(database_message *message)
1304 {
1305     zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin);
1306     if(zone_desc != NULL)
1307     {
1308         log_debug("database: %{dnsname}: processing done", message->origin);
1309     }
1310     else
1311     {
1312         log_debug("database: %{dnsname}: processed zone is not configured", message->origin);
1313     }
1314 
1315     return zone_desc;
1316 }
1317 
1318 static void
database_service_zone_destroyed_callback(const u8 * origin)1319 database_service_zone_destroyed_callback(const u8 *origin)
1320 {
1321     log_debug("database: %{dnsname}: memory freed", origin);
1322 
1323     zone_desc_s *zone_desc = zone_acquirebydnsname(origin);
1324     if(zone_desc != NULL)
1325     {
1326         zone_lock(zone_desc, ZONE_LOCK_LOAD);
1327         if((zone_get_status(zone_desc) & ZONE_STATUS_LOAD_AFTER_DROP) != 0)
1328         {
1329             zone_clear_status(zone_desc, ZONE_STATUS_LOAD_AFTER_DROP);
1330             // load the zone
1331             //database_service_zone_load(zone_desc);
1332 
1333             //zone_lock(zone_desc, ZONE_LOCK_LOAD);
1334             //zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_LOAD, NULL, TRUE);
1335             //zone_unlock(zone_desc, ZONE_LOCK_LOAD);
1336 
1337             database_zone_load(origin);
1338         }
1339         zone_unlock(zone_desc, ZONE_LOCK_LOAD);
1340     }
1341 }
1342 
1343 static int
database_service(struct service_worker_s * worker)1344 database_service(struct service_worker_s *worker)
1345 {
1346     zone_desc_s *zone_desc = NULL;
1347 
1348 #if DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND
1349     u64 sbmps_epoch_us = timeus();
1350     u32 sbmps_count = 0;
1351 #endif
1352     /*
1353      * while the program is running
1354      */
1355 
1356     log_info("database: service starting");
1357 
1358     zdb_zone_dnssec_keys_refresh();
1359 
1360     log_info("database: service started");
1361 
1362     bool running;
1363 
1364     zdb_zone_garbage_run_callback_add(database_service_zone_destroyed_callback);
1365 
1366     while((running = service_should_run(worker)) || !async_queue_empty(&database_handler_queue))
1367     {
1368         if(!zdb_zone_garbage_empty())
1369         {
1370             // do a zdb_zone_garbage_run in the background
1371             if(thread_pool_queue_size(database_zone_unload_thread_pool) == 0)
1372             {
1373                 database_service_run_garbage_collector();
1374             }
1375         }
1376 
1377         /*
1378          * dequeue command
1379          */
1380 
1381         zone_desc = NULL;
1382 
1383         async_message_s *async = async_message_next(&database_handler_queue);
1384 
1385         if(async == NULL)
1386         {
1387             continue;
1388         }
1389 
1390         database_message *message = (database_message*)async->args;
1391 
1392         if(message == NULL)
1393         {
1394             log_err("database: NULL message");
1395             continue;
1396         }
1397 
1398 #if DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND
1399         {
1400             u64 now = timeus();
1401             if(now - sbmps_epoch_us >= ONE_SECOND_US)
1402             {
1403                 double mps = sbmps_count;
1404                 mps *= ONE_SECOND_US_F;
1405                 mps /= (now - sbmps_epoch_us);
1406                 log_info("database: %12.3f msg/s", mps);
1407                 sbmps_epoch_us = now;
1408                 sbmps_count = 0;
1409             }
1410             sbmps_count++;
1411         }
1412 #endif
1413 
1414 #if DEBUG
1415         if(message->payload.type < DATABASE_SERVICE_OPERATION_COUNT)
1416         {
1417             log_debug("database: %{dnsname}: dequeued operation %s", message->origin, database_service_operation[message->payload.type]);
1418         }
1419         else
1420         {
1421             log_debug("database: %{dnsname}: dequeued operation #%d", message->origin, message->payload.type);
1422         }
1423 #endif
1424         /*
1425          * NULL => shutdown the thread
1426          */
1427 
1428         if(!running)
1429         {
1430             switch(message->payload.type)
1431             {
1432                 case DATABASE_SERVICE_ZONE_DESC_LOAD:
1433                 case DATABASE_SERVICE_ZONE_DESC_UNLOAD:
1434                 case DATABASE_SERVICE_ZONE_LOAD:
1435                 case DATABASE_SERVICE_ZONE_UNLOAD:
1436                 case DATABASE_SERVICE_ZONE_FREEZE:
1437                 case DATABASE_SERVICE_ZONE_UNFREEZE:
1438                 case DATABASE_SERVICE_QUERY_AXFR:
1439                 case DATABASE_SERVICE_QUERY_IXFR:
1440                 case DATABASE_SERVICE_SET_DROP_AFTER_RELOAD:
1441                 case DATABASE_SERVICE_DO_DROP_AFTER_RELOAD:
1442                 case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES:
1443                 case DATABASE_SERVICE_ZONE_LOADED_EVENT:
1444                 case DATABASE_SERVICE_ZONE_MOUNTED_EVENT:
1445                 case DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT:
1446                 case DATABASE_SERVICE_ZONE_UNLOADED_EVENT:
1447                 case DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT:
1448                 case DATABASE_SERVICE_CALLBACK:
1449                 default:
1450                 {
1451                     log_debug("database: shutting down: cleaning message %i", message->payload.type);
1452 
1453                     database_service_message_clear(message);
1454                     database_load_message_free(message);
1455                     async_message_release(async);
1456                     continue;
1457                 }
1458                 case DATABASE_SERVICE_ZONE_SAVE_TEXT:
1459                 case DATABASE_SERVICE_ZONE_PROCESSED:
1460                 {
1461                     log_debug("database: shutting down: not ignoring message %i", message->payload.type);
1462 
1463                     break;
1464                 }
1465             }
1466         }
1467 
1468         /*
1469          * load command ?
1470          */
1471 
1472         switch(message->payload.type)
1473         {
1474             case DATABASE_SERVICE_ZONE_DESC_LOAD:
1475             {
1476                 // desc
1477                 database_load_zone_desc(message->payload.zone_desc_load.zone_desc); // foreground
1478                 zone_release(message->payload.zone_desc_load.zone_desc);
1479                 message->payload.zone_desc_load.zone_desc = NULL;
1480                 break;
1481             }
1482 
1483             // DISPATCH TO THE ZONE DESCRIPTOR
1484 
1485             case DATABASE_SERVICE_ZONE_DESC_UNLOAD:
1486             {
1487                 zone_desc = database_service_on_zone_desc_unload(message);
1488 
1489                 break;
1490             }
1491             case DATABASE_SERVICE_ZONE_LOAD:
1492             {
1493                 zone_desc = database_service_on_zone_load(message);
1494                 break;
1495             }
1496 
1497             case DATABASE_SERVICE_ZONE_UNLOAD:
1498             {
1499                 zone_desc = database_service_on_service_zone_unload(message);
1500                 break;
1501             }
1502             case DATABASE_SERVICE_ZONE_FREEZE:
1503             {
1504                 zone_desc = database_service_on_zone_freeze(message);
1505                 break;
1506             }
1507             case DATABASE_SERVICE_ZONE_UNFREEZE:
1508             {
1509                 zone_desc = database_service_on_zone_unfreeze(message);
1510                 break;
1511             }
1512             case DATABASE_SERVICE_ZONE_SAVE_TEXT:
1513             {
1514                 zone_desc = database_service_on_zone_store_text(message);
1515                 break;
1516             }
1517             case DATABASE_SERVICE_QUERY_AXFR:
1518             {
1519                 // no desc
1520                 database_service_zone_axfr_query(message->origin); // background, triggers 'downloaded' event
1521 
1522                 break;
1523             }
1524 
1525             case DATABASE_SERVICE_QUERY_IXFR:
1526             {
1527                 // no desc
1528                 database_service_zone_ixfr_query(message->origin); // background, triggers 'downloaded' event
1529 
1530                 break;
1531             }
1532 
1533             case DATABASE_SERVICE_SET_DROP_AFTER_RELOAD:
1534             {
1535                 // no desc
1536                 // ZONE_STATUS_DROP_AFTER_RELOAD
1537 
1538                 if(message->payload.drop_after_reload.do_subset)
1539                 {
1540                     database_service_set_drop_after_reload_for_set(&message->payload.drop_after_reload.zone_set); // foreground
1541 
1542                     if(message->payload.drop_after_reload.do_subset)
1543                     {
1544                         ptr_set_callback_and_destroy(&message->payload.drop_after_reload.zone_set, database_service_message_clear_free_fqdn_node);
1545                     }
1546                 }
1547                 else
1548                 {
1549                     database_service_set_drop_after_reload();
1550                 }
1551 
1552                 break;
1553             }
1554 
1555             case DATABASE_SERVICE_DO_DROP_AFTER_RELOAD:
1556             {
1557                 // no desc
1558                 database_service_do_drop_after_reload(); // foreground
1559 
1560                 break;
1561             }
1562 
1563             case DATABASE_SERVICE_CLEAR_DROP_AFTER_RELOAD:
1564             {
1565                 database_service_clear_drop_after_reload(); // foreground
1566 
1567                 break;
1568             }
1569 
1570             //
1571 
1572 #if ZDB_HAS_DNSSEC_SUPPORT
1573 #if HAS_RRSIG_MANAGEMENT_SUPPORT
1574 
1575             case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES:
1576             {
1577                 zone_desc = database_service_on_update_zone_signatures_event(message);
1578                 break;
1579             }
1580 
1581 #endif
1582 #endif // ZDB_HAS_DNSSEC_SUPPORT
1583             // EVENTS
1584 
1585             case DATABASE_SERVICE_ZONE_LOADED_EVENT:
1586             {
1587                 zone_desc = database_service_on_zone_loaded_event(message);
1588                 break;
1589             }
1590 
1591             case DATABASE_SERVICE_ZONE_MOUNTED_EVENT:
1592             {
1593                 zone_desc = database_service_on_zone_mounted_event(message);
1594                 break;
1595             }
1596 
1597             case DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT:
1598             {
1599                 zone_desc = database_service_on_zone_unmounted_event(message);
1600                 break;
1601             }
1602             case DATABASE_SERVICE_ZONE_UNLOADED_EVENT:
1603             {
1604                 zone_desc = database_service_on_zone_unloaded_event(message);
1605                 break;
1606             }
1607 
1608             case DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT:
1609             {
1610                 zone_desc = database_service_on_zone_downloaded_event(message);
1611                 break;
1612             }
1613 
1614             case DATABASE_SERVICE_ZONE_PROCESSED:
1615             {
1616                 zone_desc = database_serice_on_zone_processed(message);
1617                 break;
1618             }
1619 
1620             case DATABASE_SERVICE_CALLBACK:
1621             {
1622                 log_debug("database: queuing %s callback from %llT", message->payload.callback.name, message->payload.callback.timestamp);
1623                 database_callback_run(message);
1624                 break;
1625             }
1626 
1627             default:
1628             {
1629                 break;
1630             }
1631         }
1632 
1633         if(zone_desc != NULL)
1634         {
1635             ya_result ret;
1636 
1637             if(FAIL(ret = zone_lock(zone_desc, ZONE_LOCK_SERVICE)))
1638             {
1639                 log_err("database: %{dnsname}: unable to lock zone: %r", message->origin, ret);
1640             }
1641 
1642 #if DEBUG
1643             log_debug("database: %{dnsname}: zone status: %x", message->origin, zone_get_status(zone_desc));
1644 #endif
1645 
1646             while((zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING) == 0)
1647             {
1648 #if DEBUG
1649                 zone_desc_log(g_server_logger, LOG_DEBUG, zone_desc, "database-service");
1650 #endif
1651                 zone_command_s* command = zone_dequeue_command(zone_desc);
1652 
1653                 if(command != NULL)
1654                 {
1655                     zone_set_status(zone_desc, ZONE_STATUS_PROCESSING);
1656                     zone_desc->last_processor = command->id;
1657 
1658                     log_debug("database: %{dnsname}: processing zone @%p (%s)", message->origin, zone_desc, database_service_operation_get_name(zone_desc->last_processor));
1659 
1660                     zone_unlock(zone_desc, ZONE_LOCK_SERVICE);
1661 
1662                     if(ISOK(ret = database_service_process_command(zone_desc, command)))
1663                     {
1664                         if(FAIL(zone_lock(zone_desc, ZONE_LOCK_SERVICE)))
1665                         {
1666                             log_err("database: %{dnsname}: zone cannot be locked", message->origin);
1667                         }
1668                     }
1669                     else
1670                     {
1671                         if((ret != FEATURE_NOT_SUPPORTED) && (ret != SERVICE_ALREADY_RUNNING))
1672                         {
1673                             log_err("database: %{dnsname}: cannot execute command: %08x: %r", message->origin, command->id, ret);
1674                         }
1675                         else
1676                         {
1677                             log_debug("database: %{dnsname}: cannot execute command: %08x: %r", message->origin, command->id, ret);
1678                         }
1679 
1680                         if(FAIL(ret = zone_lock(zone_desc, ZONE_LOCK_SERVICE)))
1681                         {
1682                             log_err("database: %{dnsname}: unable to re-lock zone following an internal error: %r", message->origin, ret);
1683                         }
1684 
1685                         zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING);
1686                     }
1687 
1688                     zone_command_free(command);
1689                 }
1690                 else
1691                 {
1692                     if(zone_get_status(zone_desc) & ZONE_STATUS_MARKED_FOR_DESTRUCTION)
1693                     {
1694                         log_debug("database: %{dnsname}: zone @%p is marked for destruction", zone_origin(zone_desc), zone_desc);
1695                     }
1696                     if(!(zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING))
1697                     {
1698                         zone_desc->last_processor = 0;
1699                     }
1700                     break;
1701                 }
1702             }
1703 
1704 #if DEBUG
1705             log_debug("database: %{dnsname}: zone @%p is processed by %s", message->origin, zone_desc, database_service_operation_get_name(zone_desc->last_processor));
1706 #endif
1707 
1708             zone_unlock(zone_desc, ZONE_LOCK_SERVICE);
1709             zone_release(zone_desc);
1710 #if DEBUG
1711             zone_desc = NULL;
1712 #endif
1713         }
1714 
1715         database_load_message_free(message);
1716         async_message_release(async);
1717     }
1718 
1719     zdb_zone_garbage_run_callback_remove(database_service_zone_destroyed_callback);
1720 
1721     service_set_stopping(worker);
1722 
1723     log_info("database: service stopped");
1724 
1725     return 0;
1726 }
1727 
1728 void
database_load_all_zones()1729 database_load_all_zones()
1730 {
1731     u8 buffer[4096];
1732 
1733     // builds a set of names to load, batch loads the names
1734     // iterates the above process until there are no names left to load
1735 
1736     zone_set_lock(&database_zone_desc);  // unlock checked
1737 
1738     ptr_node *node = ptr_set_get_first(&database_zone_desc.set);
1739 
1740     for(;;)
1741     {
1742         u8 *name = buffer;
1743         const u8 *last = NULL;
1744 
1745         for(; node != NULL; node = ptr_set_node_next(node))
1746         {
1747             zone_desc_s *zone_desc = (zone_desc_s *)node->value;
1748             int name_len = dnsname_len(zone_origin(zone_desc));
1749             if(name_len > (&buffer[sizeof(buffer)] - name))
1750             {
1751                 break;
1752             }
1753             memcpy(name, zone_origin(zone_desc), name_len);
1754             last = name;
1755             name += name_len;
1756         }
1757 
1758         zone_set_unlock(&database_zone_desc);
1759 
1760         if(last == NULL)
1761         {
1762             // no name has been inserted : nothing more to do
1763 
1764             break;
1765         }
1766 
1767         name = buffer;
1768 
1769         for(;;)
1770         {
1771             database_zone_load(name);
1772 
1773             if(name == last)
1774             {
1775                 break;
1776             }
1777 
1778             name += dnsname_len(name);
1779         }
1780 
1781         zone_set_lock(&database_zone_desc);  // unlock checked
1782 
1783         // get back the last name
1784 
1785         node = ptr_set_find(&database_zone_desc.set, last);
1786 
1787         if(node != NULL)
1788         {
1789             // and get the one that follows
1790 
1791             node = ptr_set_node_next(node);
1792         }
1793     }
1794 }
1795 
1796 void
database_zone_load(const u8 * origin)1797 database_zone_load(const u8 *origin)
1798 {
1799     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_LOAD", origin);
1800 
1801     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_LOAD);
1802 
1803     async_message_s *async = async_message_alloc();
1804     async->id = message->payload.type;
1805     async->args = message;
1806     async->handler = NULL;
1807     async->handler_args = NULL;
1808     async_message_call(&database_handler_queue, async);
1809 }
1810 
1811 #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT
1812 
1813 static void
database_zone_update_signatures_common(const u8 * origin,zone_desc_s * expected_zone_desc,zdb_zone * expected_zone)1814 database_zone_update_signatures_common(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone)
1815 {
1816     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES);
1817 
1818     zone_acquire(expected_zone_desc);
1819     zdb_zone_acquire(expected_zone);
1820 
1821     message->payload.zone_update_signatures.expected_zone_desc = expected_zone_desc;
1822     message->payload.zone_update_signatures.expected_zone = expected_zone;
1823 
1824     async_message_s *async = async_message_alloc();
1825     async->id = message->payload.type;
1826     async->args = message;
1827     async->handler = NULL;
1828     async->handler_args = NULL;
1829     async_message_call(&database_handler_queue, async);
1830 }
1831 
1832 void
database_zone_update_signatures_resume(const u8 * origin,zone_desc_s * expected_zone_desc,zdb_zone * expected_zone)1833 database_zone_update_signatures_resume(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone)
1834 {
1835     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES (resume)", origin);
1836     database_zone_update_signatures_common(origin, expected_zone_desc, expected_zone);
1837 }
1838 
1839 void
database_zone_update_signatures(const u8 * origin,zone_desc_s * expected_zone_desc,zdb_zone * expected_zone)1840 database_zone_update_signatures(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone)
1841 {
1842     if(expected_zone->progressive_signature_update.earliest_signature_expiration >= MAX_S32) // can only be == as it's an s32
1843     {
1844         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES ignored", origin);
1845         return;
1846     }
1847 
1848     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES", origin);
1849 
1850     if(zdb_zone_set_maintenance_queued(expected_zone))
1851     {
1852         database_zone_update_signatures_common(origin, expected_zone_desc, expected_zone);
1853     }
1854     else
1855     {
1856 #if DEBUG
1857         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES ignored (already queued)", origin);
1858 #endif
1859     }
1860 }
1861 
1862 void
database_zone_update_signatures_allow_queue(const u8 * origin,zone_desc_s * expected_zone_desc,zdb_zone * expected_zone)1863 database_zone_update_signatures_allow_queue(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone)
1864 {
1865     log_debug("database: %{dnsname}: maintenance done", expected_zone->origin);
1866     (void)origin;
1867     (void)expected_zone_desc;
1868     (void)expected_zone;
1869 }
1870 
1871 static ya_result
database_zone_update_signatures_alarm(void * args_,bool cancel)1872 database_zone_update_signatures_alarm(void *args_, bool cancel)
1873 {
1874     zdb_zone *zone = (zdb_zone*)args_;
1875     if(!cancel)
1876     {
1877         zone_desc_s *zone_desc = zone_acquirebydnsname(zone->origin);
1878 
1879         if(zone_desc != NULL)
1880         {
1881             log_debug("database: %{dnsname}: maintenance triggered by time", zone->origin);
1882 
1883             database_zone_update_signatures(zone->origin, zone_desc, zone);
1884             zone_release(zone_desc);
1885         }
1886     }
1887     zdb_zone_release(zone);
1888 
1889     return SUCCESS;
1890 }
1891 
1892 /**
1893  *
1894  * Sets an alarm to enqueue a zone maintenance at a given time (best effort)
1895  *
1896  * @param zone
1897  * @param at
1898  */
1899 
1900 void
database_zone_update_signatures_at(zdb_zone * zone,u32 at)1901 database_zone_update_signatures_at(zdb_zone *zone, u32 at)
1902 {
1903     log_debug("database: %{dnsname}: will enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES at %T", zone->origin, at);
1904 
1905     zdb_zone_acquire(zone);
1906     alarm_event_node *event = alarm_event_new(
1907                         at,
1908                         ALARM_KEY_ZONE_SIGNATURE_UPDATE,
1909                         database_zone_update_signatures_alarm,
1910                         zone,
1911                         ALARM_DUP_REMOVE_LATEST,
1912                         "database-service-zone-maintenance");
1913 
1914     alarm_set(zone->alarm_handle, event);
1915 }
1916 
1917 #endif
1918 
1919 void
database_zone_unload(zdb_zone * zone)1920 database_zone_unload(zdb_zone *zone)
1921 {
1922     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNLOAD", zone->origin);
1923 
1924     zdb_zone_acquire(zone);
1925 
1926     database_message *message = database_load_message_alloc(zone->origin, DATABASE_SERVICE_ZONE_UNLOAD);
1927     message->payload.zone_unload.zone = zone;
1928 
1929     async_message_s *async = async_message_alloc();
1930     async->id = message->payload.type;
1931     async->args = message;
1932     async->handler = NULL;
1933     async->handler_args = NULL;
1934     async_message_call(&database_handler_queue, async);
1935 }
1936 
database_zone_freeze(const u8 * origin)1937 void database_zone_freeze(const u8 *origin)
1938 {
1939     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_FREEZE", origin);
1940     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_FREEZE);
1941 
1942     async_message_s *async = async_message_alloc();
1943     async->id = message->payload.type;
1944     async->args = message;
1945     async->handler = NULL;
1946     async->handler_args = NULL;
1947     async_message_call(&database_handler_queue, async);
1948 }
1949 
database_zone_unfreeze(const u8 * origin)1950 void database_zone_unfreeze(const u8 *origin)
1951 {
1952     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNFREEZE", origin);
1953     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_UNFREEZE);
1954 
1955     async_message_s *async = async_message_alloc();
1956     async->id = message->payload.type;
1957     async->args = message;
1958     async->handler = NULL;
1959     async->handler_args = NULL;
1960     async_message_call(&database_handler_queue, async);
1961 }
1962 
database_zone_store_ex(const u8 * origin,bool clear)1963 void database_zone_store_ex(const u8 *origin, bool clear)
1964 {
1965     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_SAVE_TEXT (clear=%i)", origin, clear);
1966 
1967     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_SAVE_TEXT);
1968 
1969     async_message_s *async = async_message_alloc();
1970     async->id = message->payload.type;
1971     message->payload.zone_store.clear = clear;
1972     async->args = message;
1973     async->handler = NULL;
1974     async->handler_args = NULL;
1975     async_message_call(&database_handler_queue, async);
1976 }
1977 
database_zone_store(const u8 * origin)1978 void database_zone_store(const u8 *origin)
1979 {
1980     database_zone_store_ex(origin, FALSE);
1981 }
1982 
1983 void
database_zone_desc_load(zone_desc_s * zone_desc)1984 database_zone_desc_load(zone_desc_s *zone_desc)
1985 {
1986     if(zone_desc != NULL)
1987     {
1988         log_debug("database: %{dnsname}: loading settings", zone_origin(zone_desc));
1989 
1990 #if DEBUG
1991         zone_desc_log(MODULE_MSG_HANDLE, LOG_DEBUG, zone_desc, "database_zone_desc_load");
1992 #endif
1993 
1994         if(service_started(&database_handler))
1995         {
1996             log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DESC_LOAD", zone_origin(zone_desc));
1997 
1998             database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_DESC_LOAD);
1999             zone_acquire(zone_desc);
2000             message->payload.zone_desc_load.zone_desc = zone_desc;
2001 
2002             async_message_s *async = async_message_alloc();
2003             async->id = message->payload.type;
2004             async->args = message;
2005             async->handler = NULL;
2006             async->handler_args = NULL;
2007             async_message_call(&database_handler_queue, async);
2008         }
2009         else
2010         {
2011             log_debug("database: %{dnsname}: loading setting with offline database", zone_origin(zone_desc));
2012 
2013             database_load_zone_desc(zone_desc);
2014         }
2015     }
2016     else
2017     {
2018         log_err("database: loading settings asked for NULL settings");
2019     }
2020 }
2021 
2022 void
database_zone_desc_unload(const u8 * origin)2023 database_zone_desc_unload(const u8 *origin)
2024 {
2025     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DESC_UNLOAD", origin);
2026 
2027     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_DESC_UNLOAD);
2028 
2029     async_message_s *async = async_message_alloc();
2030     async->id = message->payload.type;
2031     async->args = message;
2032     async->handler = NULL;
2033     async->handler_args = NULL;
2034     async_message_call(&database_handler_queue, async);
2035 }
2036 
2037 void
database_zone_axfr_query(const u8 * origin)2038 database_zone_axfr_query(const u8 *origin)
2039 {
2040     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_AXFR", origin);
2041     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_AXFR);
2042 
2043     async_message_s *async = async_message_alloc();
2044     async->id = message->payload.type;
2045     async->args = message;
2046     async->handler = NULL;
2047     async->handler_args = NULL;
2048     async_message_call(&database_handler_queue, async);
2049 }
2050 
2051 static ya_result
database_zone_axfr_query_alarm(void * args,bool cancel)2052 database_zone_axfr_query_alarm(void *args, bool cancel)
2053 {
2054     async_message_s* async = (async_message_s*)args;
2055     database_message* message = (database_message*)async->args;
2056     if(!cancel)
2057     {
2058         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_AXFR (alarm)", message->origin);
2059         async_message_call(&database_handler_queue, async);
2060     }
2061     else
2062     {
2063         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_AXFR cancelled (alarm)", message->origin);
2064         database_load_message_free((database_message*)async->args);
2065         async_message_release(async);
2066     }
2067 
2068     return SUCCESS;
2069 }
2070 
2071 void
database_zone_axfr_query_at(const u8 * origin,time_t at)2072 database_zone_axfr_query_at(const u8 *origin, time_t at)
2073 {
2074     log_debug("database: %{dnsname}: will enqueue operation DATABASE_SERVICE_QUERY_AXFR at %T", origin, at);
2075 
2076     zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, origin);
2077 
2078     if(zone == NULL)
2079     {
2080         log_warn("database: %{dnsname}: arming AXFR query: zone not in database", origin);
2081         return;
2082     }
2083 
2084     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_AXFR);
2085     async_message_s *async = async_message_alloc();
2086     async->id = message->payload.type;
2087     async->args = message;
2088     async->handler = NULL;
2089     async->handler_args = NULL;
2090 
2091     alarm_event_node *event = alarm_event_new(
2092             at,
2093             ALARM_KEY_ZONE_AXFR_QUERY,
2094             database_zone_axfr_query_alarm,
2095             async,
2096             ALARM_DUP_REMOVE_LATEST,
2097             "database-zone-axfr-query-alarm");
2098 
2099     alarm_set(zone->alarm_handle, event);
2100 
2101     zdb_zone_release(zone);
2102 }
2103 
2104 
2105 void
database_zone_ixfr_query(const u8 * origin)2106 database_zone_ixfr_query(const u8 *origin)
2107 {
2108     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_IXFR", origin);
2109     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_IXFR);
2110 
2111     async_message_s *async = async_message_alloc();
2112     async->id = message->payload.type;
2113     async->args = message;
2114     async->handler = NULL;
2115     async->handler_args = NULL;
2116     async_message_call(&database_handler_queue, async);
2117 }
2118 
2119 static ya_result
database_zone_ixfr_query_alarm(void * args,bool cancel)2120 database_zone_ixfr_query_alarm(void *args, bool cancel)
2121 {
2122     async_message_s* async = (async_message_s*)args;
2123     database_message* message = (database_message*)async->args;
2124     if(!cancel)
2125     {
2126         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_IXFR (alarm)", message->origin);
2127         async_message_call(&database_handler_queue, async);
2128     }
2129     else
2130     {
2131         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_IXFR cancelled (alarm)", message->origin);
2132         database_load_message_free((database_message*)async->args);
2133         async_message_release(async);
2134     }
2135 
2136     return SUCCESS;
2137 }
2138 
2139 void
database_zone_ixfr_query_at(const u8 * origin,time_t at)2140 database_zone_ixfr_query_at(const u8 *origin, time_t at)
2141 {
2142     log_debug("database: %{dnsname}: will enqueue operation DATABASE_SERVICE_QUERY_IXFR at %T", origin, at);
2143 
2144     zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, origin);
2145 
2146     if(zone == NULL)
2147     {
2148         log_warn("database: %{dnsname}: arming IXFR query: zone not in database", origin);
2149         return;
2150     }
2151 
2152     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_IXFR);
2153     async_message_s *async = async_message_alloc();
2154     async->id = message->payload.type;
2155     async->args = message;
2156     async->handler = NULL;
2157     async->handler_args = NULL;
2158 
2159     alarm_event_node *event = alarm_event_new(
2160             at,
2161             ALARM_KEY_ZONE_AXFR_QUERY,
2162             database_zone_ixfr_query_alarm,
2163             async,
2164             ALARM_DUP_REMOVE_LATEST,
2165             "database-zone-ixfr-query-alarm");
2166 
2167     alarm_set(zone->alarm_handle, event);
2168 
2169     zdb_zone_release(zone);
2170 }
2171 
2172 
2173 
2174 #define DATABASE_ZONE_RECONFIGURE_ALL   3
2175 #define DATABASE_ZONE_RECONFIGURE_ZONES 2
2176 #define DATABASE_ZONE_RECONFIGURE_ZONE  1
2177 
2178 // keys+zones (a.k.a everything), zones, zone
2179 static smp_int database_zone_reconfigure_queued = SMP_INT_INITIALIZER;
2180 static ptr_set database_zone_reconfigure_fqdn = PTR_SET_DNSNAME_EMPTY;
2181 
2182 bool
database_zone_is_reconfigure_enabled()2183 database_zone_is_reconfigure_enabled()
2184 {
2185     return smp_int_get(&database_reconfigure_enable_count) > 0;
2186 }
2187 
2188 bool
database_zone_try_reconfigure_enable()2189 database_zone_try_reconfigure_enable()
2190 {
2191     bool ret = smp_int_setifequal(&database_reconfigure_enable_count, 0, 1);
2192     if(ret)
2193     {
2194         log_info("database: reconfigure started");
2195     }
2196     else
2197     {
2198         log_info("database: reconfigure already running");
2199     }
2200     return ret;
2201 }
2202 
2203 static void
database_zone_postpone_reconfigure_fqdn_destroy_cb(ptr_node * node)2204 database_zone_postpone_reconfigure_fqdn_destroy_cb(ptr_node *node)
2205 {
2206     dnsname_zfree(node->key);
2207     node->key = NULL;
2208     node->value = NULL;
2209 }
2210 
2211 static void
database_zone_postpone_reconfigure_fqdn_destroy()2212 database_zone_postpone_reconfigure_fqdn_destroy()
2213 {
2214     ptr_set_callback_and_destroy(&database_zone_reconfigure_fqdn, database_zone_postpone_reconfigure_fqdn_destroy_cb);
2215 }
2216 
2217 void
database_zone_postpone_reconfigure_all()2218 database_zone_postpone_reconfigure_all()
2219 {
2220     log_info("database: postponing reconfigure all");
2221 
2222     mutex_lock(&database_zone_reconfigure_queued.mutex);
2223     database_zone_reconfigure_queued.value = DATABASE_ZONE_RECONFIGURE_ALL;
2224     database_zone_postpone_reconfigure_fqdn_destroy();
2225     mutex_unlock(&database_zone_reconfigure_queued.mutex);
2226 }
2227 
2228 void
database_zone_postpone_reconfigure_zones()2229 database_zone_postpone_reconfigure_zones()
2230 {
2231     log_info("database: postponing reconfigure zones");
2232 
2233     mutex_lock(&database_zone_reconfigure_queued.mutex);
2234     if(database_zone_reconfigure_queued.value < DATABASE_ZONE_RECONFIGURE_ZONES)
2235     {
2236         database_zone_reconfigure_queued.value = DATABASE_ZONE_RECONFIGURE_ZONES;
2237         database_zone_postpone_reconfigure_fqdn_destroy();
2238     }
2239     mutex_unlock(&database_zone_reconfigure_queued.mutex);
2240 }
2241 
2242 void
database_zone_postpone_reconfigure_zone(const ptr_set * fqdn_set)2243 database_zone_postpone_reconfigure_zone(const ptr_set *fqdn_set)
2244 {
2245     log_info("database: postponing reconfigure of a set of zones");
2246 
2247     mutex_lock(&database_zone_reconfigure_queued.mutex);
2248     if(database_zone_reconfigure_queued.value <= DATABASE_ZONE_RECONFIGURE_ZONE)
2249     {
2250         database_zone_reconfigure_queued.value = DATABASE_ZONE_RECONFIGURE_ZONE;
2251         ptr_set_iterator iter;
2252         ptr_set_iterator_init(fqdn_set, &iter);
2253         while(ptr_set_iterator_hasnext(&iter))
2254         {
2255             ptr_node *src_node = ptr_set_iterator_next_node(&iter);
2256             ptr_node *node = ptr_set_insert(&database_zone_reconfigure_fqdn, src_node->key);
2257             if(node->value == NULL)
2258             {
2259                 node->key = dnsname_zdup((const u8*)src_node->key);
2260                 node->value = node->key;
2261             }
2262         }
2263     }
2264     mutex_unlock(&database_zone_reconfigure_queued.mutex);
2265 }
2266 
2267 
2268 
2269 static void
database_service_config_update_callback(void * args_,bool delete_only)2270 database_service_config_update_callback(void *args_, bool delete_only)
2271 {
2272     (void)args_;
2273     if(!delete_only)
2274     {
2275         log_debug("database: try running postponed reconfigure");
2276         yadifad_config_update(g_config->config_file);
2277     }
2278 }
2279 
2280 void
database_service_config_update()2281 database_service_config_update()
2282 {
2283     log_debug("database: will run postponed reconfigure");
2284     database_post_callback(database_service_config_update_callback, NULL, "reconfigure-update-all");
2285 }
2286 
2287 static void
database_service_config_update_all_zones_callback(void * args_,bool delete_only)2288 database_service_config_update_all_zones_callback(void *args_, bool delete_only)
2289 {
2290     (void)args_;
2291     if(!delete_only)
2292     {
2293         log_debug("database: try running postponed reconfigure all zones");
2294         yadifad_config_update_zone(g_config->config_file, NULL);
2295     }
2296 }
2297 
2298 void
database_service_config_update_all_zones()2299 database_service_config_update_all_zones()
2300 {
2301     log_debug("database: will run postponed reconfigure all zones");
2302     database_post_callback(database_service_config_update_all_zones_callback, NULL, "reconfigure-update-all-zones");
2303 }
2304 
2305 static void
database_service_config_update_zones_callback(void * args_,bool delete_only)2306 database_service_config_update_zones_callback(void *args_, bool delete_only)
2307 {
2308     ptr_set fqdn_set = {args_, ptr_set_dnsname_node_compare};
2309 
2310     if(!delete_only)
2311     {
2312         log_debug("database: try running postponed reconfigure some zones");
2313 
2314         yadifad_config_update_zone(g_config->config_file, &fqdn_set);
2315     }
2316 
2317     ptr_set_callback_and_destroy(&fqdn_set, database_zone_postpone_reconfigure_fqdn_destroy_cb);
2318 }
2319 
2320 void
database_service_config_update_zones(ptr_set * fqdn_set)2321 database_service_config_update_zones(ptr_set *fqdn_set)
2322 {
2323     yassert(fqdn_set->compare == ptr_set_dnsname_node_compare);
2324     log_debug("database: running postponed reconfigure of a set of zones");
2325     database_post_callback(database_service_config_update_zones_callback, fqdn_set->root, "reconfigure-update-some-zones");
2326 }
2327 
2328 void
database_zone_reconfigure_disable()2329 database_zone_reconfigure_disable()
2330 {
2331     log_info("database: reconfigure done");
2332 
2333     mutex_lock(&database_zone_reconfigure_queued.mutex);
2334 
2335     int queue = database_zone_reconfigure_queued.value;
2336     database_zone_reconfigure_queued.value = 0;
2337 
2338     ptr_set fqdn_set = database_zone_reconfigure_fqdn;  // move the tree
2339     database_zone_reconfigure_fqdn.root = NULL;
2340 
2341     mutex_unlock(&database_zone_reconfigure_queued.mutex);
2342 
2343     // a copy of the queue and the fqdns is ready
2344 
2345     smp_int_set(&database_reconfigure_enable_count, 0);
2346 
2347     switch(queue)
2348     {
2349         case DATABASE_ZONE_RECONFIGURE_ALL:
2350         {
2351             database_service_config_update();
2352             break;
2353         }
2354         case DATABASE_ZONE_RECONFIGURE_ZONES:
2355         {
2356             database_service_config_update_all_zones();
2357             break;
2358         }
2359         case DATABASE_ZONE_RECONFIGURE_ZONE:
2360         default:
2361         {
2362             if(!ptr_set_isempty(&fqdn_set))
2363             {
2364                 database_service_config_update_zones(&fqdn_set);
2365             }
2366             break;
2367         }
2368     }
2369 
2370     ptr_set_callback_and_destroy(&fqdn_set, database_zone_postpone_reconfigure_fqdn_destroy_cb);
2371 }
2372 
2373 void
database_set_drop_after_reload_for_set(const ptr_set * set)2374 database_set_drop_after_reload_for_set(const ptr_set* set)
2375 {
2376     log_debug("database: enqueue operation DATABASE_SERVICE_SET_DROP_AFTER_RELOAD of a subset");
2377     database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_SET_DROP_AFTER_RELOAD);
2378 
2379     if(set != NULL)
2380     {
2381         message->payload.drop_after_reload.zone_set.root = NULL;
2382         message->payload.drop_after_reload.zone_set.compare = ptr_set_dnsname_node_compare;
2383         message->payload.drop_after_reload.do_subset = TRUE;
2384 
2385         ptr_set_iterator iter;
2386         ptr_set_iterator_init(set, &iter);
2387         while(ptr_set_iterator_hasnext(&iter))
2388         {
2389             ptr_node *node = ptr_set_insert(&message->payload.drop_after_reload.zone_set, ptr_set_iterator_next_node(&iter)->key);
2390             node->key = dnsname_zdup(node->key);
2391         }
2392     }
2393     else
2394     {
2395         message->payload.drop_after_reload.do_subset = FALSE;
2396     }
2397 
2398     async_message_s *async = async_message_alloc();
2399     async->id = message->payload.type;
2400     async->args = message;
2401     async->handler = NULL;
2402     async->handler_args = NULL;
2403     async_message_call(&database_handler_queue, async);
2404 }
2405 
2406 static void
database_clear_drop_after_reload()2407 database_clear_drop_after_reload()
2408 {
2409     log_debug("database: enqueue operation DATABASE_SERVICE_CLEAR_DROP_AFTER_RELOAD");
2410     database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_CLEAR_DROP_AFTER_RELOAD);
2411 
2412     async_message_s *async = async_message_alloc();
2413     async->id = message->payload.type;
2414     async->args = message;
2415     async->handler = NULL;
2416     async->handler_args = NULL;
2417     async_message_call(&database_handler_queue, async);
2418 }
2419 
2420 static void
database_do_drop_after_reload()2421 database_do_drop_after_reload()
2422 {
2423     log_debug("database: enqueue operation DATABASE_SERVICE_DO_DROP_AFTER_RELOAD");
2424     database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_DO_DROP_AFTER_RELOAD);
2425 
2426     async_message_s *async = async_message_alloc();
2427     async->id = message->payload.type;
2428     async->args = message;
2429     async->handler = NULL;
2430     async->handler_args = NULL;
2431     async_message_call(&database_handler_queue, async);
2432 }
2433 
2434 /// Chain of events: reconfigure end (last part)
2435 
2436 static void
database_zone_reconfigure_disable_when_processed_part2(void * args_,bool delete_only)2437 database_zone_reconfigure_disable_when_processed_part2(void *args_, bool delete_only)
2438 {
2439     (void)args_;
2440     (void)delete_only;
2441     database_zone_reconfigure_disable();
2442 }
2443 
2444 /// Chain of events: reconfigure end (first part)
2445 
2446 static void
database_zone_reconfigure_disable_when_processed_part1(void * args_,bool delete_only)2447 database_zone_reconfigure_disable_when_processed_part1(void *args_, bool delete_only)
2448 {
2449     if(!delete_only)
2450     {
2451         if(args_ != NULL)
2452         {
2453             log_info("database: will drop marked zones not defined in current configuration");
2454             database_do_drop_after_reload();
2455         }
2456         else
2457         {
2458             log_info("database: will clear drop marked zone status");
2459             database_clear_drop_after_reload();
2460         }
2461     }
2462     else
2463     {
2464         log_info("database: deleting event ?");
2465     }
2466 
2467     database_post_callback(database_zone_reconfigure_disable_when_processed_part2, NULL, "reconfigure-queue-disable");
2468 }
2469 
2470 /**
2471  * Chain of events: reconfigure end (init)
2472  *
2473  * When the database will have finished processing the queue at its current state, a callback handling drop-after-reload will be called
2474  * Then, after this handling has been done, the reconfigure mode will be disabled (enabling configure again)
2475  *
2476  * @param do_drop_after_reload
2477  */
2478 
2479 void
database_zone_reconfigure_do_drop_and_disable(bool do_drop_after_reload)2480 database_zone_reconfigure_do_drop_and_disable(bool do_drop_after_reload)
2481 {
2482     if(do_drop_after_reload)
2483     {
2484         log_debug("database: will run reconfigure do drop and disable");
2485     }
2486     else
2487     {
2488         log_debug("database: will run reconfigure clear drop and disable");
2489     }
2490     void *args = do_drop_after_reload?(void*)1:(void*)0;
2491     database_post_callback(database_zone_reconfigure_disable_when_processed_part1, args, "reconfigure-queue-handle-drop-after-reload");
2492 }
2493 
2494 
2495 void
database_fire_zone_loaded(zone_desc_s * zone_desc,zdb_zone * zone,ya_result result_code)2496 database_fire_zone_loaded(zone_desc_s *zone_desc, zdb_zone *zone, ya_result result_code)
2497 {
2498     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_LOADED_EVENT (%r)", zone_origin(zone_desc), result_code);
2499     database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_LOADED_EVENT);
2500 
2501     zone_acquire(zone_desc);
2502     if(zone != NULL)
2503     {
2504         zdb_zone_acquire(zone);
2505     }
2506 
2507     message->payload.zone_loaded_event.zone_desc = zone_desc;
2508     message->payload.zone_loaded_event.zone = zone;
2509     message->payload.zone_loaded_event.result_code = result_code;
2510 
2511     async_message_s *async = async_message_alloc();
2512     async->id = message->payload.type;
2513     async->args = message;
2514     async->handler = NULL;
2515     async->handler_args = NULL;
2516     async_message_call(&database_handler_queue, async);
2517 }
2518 
2519 void
database_fire_zone_mounted(zone_desc_s * zone_desc,zdb_zone * zone,ya_result result_code)2520 database_fire_zone_mounted(zone_desc_s *zone_desc, zdb_zone *zone, ya_result result_code)
2521 {
2522     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_MOUNTED_EVENT (%r)", zone_origin(zone_desc), result_code);
2523     database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_MOUNTED_EVENT);
2524 
2525     zone_acquire(zone_desc);
2526     if(zone != NULL)
2527     {
2528         zdb_zone_acquire(zone);
2529     }
2530 
2531     message->payload.zone_mounted_event.zone_desc = zone_desc;
2532     message->payload.zone_mounted_event.zone = zone;
2533     message->payload.zone_mounted_event.result_code = result_code;
2534 
2535     async_message_s *async = async_message_alloc();
2536     async->id = message->payload.type;
2537     async->args = message;
2538     async->handler = NULL;
2539     async->handler_args = NULL;
2540     async_message_call(&database_handler_queue, async);
2541 }
2542 
2543 void
database_fire_zone_unloaded(zdb_zone * zone,ya_result result_code)2544 database_fire_zone_unloaded(zdb_zone *zone, ya_result result_code)
2545 {
2546     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNLOADED_EVENT (%r)", zone->origin, result_code);
2547     database_message *message = database_load_message_alloc(zone->origin, DATABASE_SERVICE_ZONE_UNLOADED_EVENT);
2548 
2549     zdb_zone_acquire(zone);
2550 
2551     message->payload.zone_unloaded_event.zone = zone;
2552     message->payload.zone_unloaded_event.result_code = result_code;
2553 
2554     async_message_s *async = async_message_alloc();
2555     async->id = message->payload.type;
2556     async->args = message;
2557     async->handler = NULL;
2558     async->handler_args = NULL;
2559     async_message_call(&database_handler_queue, async);
2560 }
2561 
2562 void
database_fire_zone_unmounted(zone_desc_s * zone_desc)2563 database_fire_zone_unmounted(zone_desc_s *zone_desc)
2564 {
2565     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT", zone_origin(zone_desc));
2566     database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT);
2567 
2568     zone_acquire(zone_desc);
2569 
2570     message->payload.zone_unmounted_event.zone_desc = zone_desc;
2571 
2572     async_message_s *async = async_message_alloc();
2573     async->id = message->payload.type;
2574     async->args = message;
2575     async->handler = NULL;
2576     async->handler_args = NULL;
2577     async_message_call(&database_handler_queue, async);
2578 }
2579 
2580 void
database_fire_zone_processed(zone_desc_s * zone_desc)2581 database_fire_zone_processed(zone_desc_s *zone_desc)
2582 {
2583     log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_PROCESSED", zone_origin(zone_desc));
2584     database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_PROCESSED);
2585 
2586     async_message_s *async = async_message_alloc();
2587     async->id = message->payload.type;
2588     async->args = message;
2589     async->handler = NULL;
2590     async->handler_args = NULL;
2591     async_message_call(&database_handler_queue, async);
2592 }
2593 
2594 void
database_post_callback(database_message_callback_function callback,void * args,const char * const name)2595 database_post_callback(database_message_callback_function callback, void *args, const char * const name)
2596 {
2597     log_debug("database: enqueue operation DATABASE_SERVICE_CALLBACK %s", name);
2598     database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_CALLBACK);
2599     message->payload.callback.callback = callback;
2600     message->payload.callback.args = args;
2601     message->payload.callback.timestamp = timeus();
2602     message->payload.callback.name = name;
2603 
2604     async_message_s *async = async_message_alloc();
2605     async->id = message->payload.type;
2606     async->args = message;
2607     async->handler = NULL;
2608     async->handler_args = NULL;
2609     async_message_call(&database_handler_queue, async);
2610 }
2611 
2612 void
database_fire_zone_downloaded(const u8 * origin,u16 qtype,u32 serial,ya_result result_code)2613 database_fire_zone_downloaded(const u8 *origin, u16 qtype, u32 serial, ya_result result_code)
2614 {
2615     if(ISOK(result_code))
2616     {
2617         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT type=%{dnstype} serial=%u (%r)", origin, &qtype, serial, result_code);
2618     }
2619     else
2620     {
2621         log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT (%r)", origin, result_code);
2622     }
2623 
2624     database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT);
2625     message->payload.zone_downloaded_event.download_type = qtype;
2626     message->payload.zone_downloaded_event.serial = serial;
2627     message->payload.zone_downloaded_event.result_code = result_code;
2628 
2629     async_message_s *async = async_message_alloc();
2630     async->id = message->payload.type;
2631     async->args = message;
2632     async->handler = NULL;
2633     async->handler_args = NULL;
2634     async_message_call(&database_handler_queue, async);
2635 }
2636 
2637 void
database_service_zone_load_queue_thread(thread_pool_function func,void * parm,thread_pool_task_counter * counter,const char * categoryname)2638 database_service_zone_load_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname)
2639 {
2640     thread_pool_enqueue_call(database_zone_load_thread_pool, func, parm, counter, categoryname);
2641 }
2642 
2643 void
database_service_zone_store_queue_thread(thread_pool_function func,void * parm,thread_pool_task_counter * counter,const char * categoryname)2644 database_service_zone_store_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter,
2645                                          const char *categoryname)
2646 {
2647     thread_pool_enqueue_call(database_zone_store_thread_pool, func, parm, counter, categoryname);
2648 }
2649 
2650 void
database_service_zone_unload_queue_thread(thread_pool_function func,void * parm,thread_pool_task_counter * counter,const char * categoryname)2651 database_service_zone_unload_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname)
2652 {
2653     thread_pool_enqueue_call(database_zone_unload_thread_pool, func, parm, counter, categoryname);
2654 }
2655 
2656 static void*
database_service_run_garbage_collector_thread(void * parms_)2657 database_service_run_garbage_collector_thread(void *parms_)
2658 {
2659     (void)parms_;
2660     zdb_zone_garbage_run();
2661     return NULL;
2662 }
2663 
2664 void
database_service_run_garbage_collector()2665 database_service_run_garbage_collector()
2666 {
2667     if(database_zone_unload_thread_pool != NULL)
2668     {
2669         thread_pool_enqueue_call(database_zone_unload_thread_pool, database_service_run_garbage_collector_thread, NULL, NULL, "garbage");
2670     }
2671 }
2672 
2673 static void*
database_callback_thread(void * parms_)2674 database_callback_thread(void *parms_)
2675 {
2676     database_message_callback_s *callback = (database_message_callback_s*)parms_;
2677 
2678     if(callback->type == DATABASE_SERVICE_CALLBACK)
2679     {
2680         log_debug("database: executing %s callback from %llT", callback->name, callback->timestamp);
2681         callback->callback(callback->args, FALSE);
2682         ZFREE_OBJECT(callback);
2683     }
2684     else
2685     {
2686         log_err("database: got an invalid callback");
2687     }
2688     return NULL;
2689 }
2690 
2691 static void
database_callback_run(database_message * message)2692 database_callback_run(database_message *message)
2693 {
2694     database_message_callback_s *cb;
2695     ZALLOC_OBJECT_OR_DIE(cb, database_message_callback_s, DBMSGCB_TAG);
2696     *cb = message->payload.callback;
2697     thread_pool_enqueue_call(database_callback_thread_pool, database_callback_thread, cb, NULL, "callback");
2698 }
2699 
2700 //
2701 
2702 void
database_service_zone_download_queue_thread(thread_pool_function func,void * parm,thread_pool_task_counter * counter,const char * categoryname)2703 database_service_zone_download_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname)
2704 {
2705     thread_pool_enqueue_call(database_zone_download_thread_pool, func, parm, counter, categoryname);
2706 }
2707 
2708 #if ZDB_HAS_DNSSEC_SUPPORT
2709 #if HAS_RRSIG_MANAGEMENT_SUPPORT
2710 void
database_service_zone_resignature_queue_thread(thread_pool_function func,void * parm,thread_pool_task_counter * counter,const char * categoryname)2711 database_service_zone_resignature_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname)
2712 {
2713     thread_pool_enqueue_call(database_zone_resignature_thread_pool, func, parm, counter, categoryname);
2714 }
2715 #endif
2716 #endif
2717 
2718 void
database_service_create_invalid_zones()2719 database_service_create_invalid_zones()
2720 {
2721     zone_set_lock(&database_zone_desc); // unlock checked
2722 
2723     if(!ptr_set_isempty(&database_zone_desc.set))
2724     {
2725         ptr_set_iterator iter;
2726         ptr_set_iterator_init(&database_zone_desc.set, &iter);
2727 
2728         while(ptr_set_iterator_hasnext(&iter))
2729         {
2730             ptr_node *zone_node = ptr_set_iterator_next_node(&iter);
2731             zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value;
2732 
2733             zdb_zone *invalid_zone = zdb_zone_create(zone_origin(zone_desc)); // RC = 1
2734             zdb_zone_invalidate(invalid_zone);
2735 
2736             zdb_zone *old_zone = zdb_set_zone(g_config->database, invalid_zone); // RC ++
2737             yassert(old_zone == NULL);
2738             (void)old_zone;
2739 
2740             zdb_zone_release(invalid_zone);
2741         }
2742     }
2743 
2744     zone_set_unlock(&database_zone_desc);
2745 }
2746 
2747 bool
database_service_is_running()2748 database_service_is_running()
2749 {
2750     return service_started(&database_handler);
2751 }
2752 
2753 /**
2754  * @}
2755  */
2756