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