OpenDNSSEC-signer 2.1.10
engine.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 NLNet Labs. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
32#include "config.h"
33#include "daemon/cfg.h"
34#include "daemon/engine.h"
35#include "duration.h"
36#include "file.h"
37#include "str.h"
38#include "hsm.h"
39#include "locks.h"
40#include "log.h"
41#include "privdrop.h"
42#include "status.h"
43#include "util.h"
44#include "signer/zonelist.h"
45#include "wire/tsig.h"
46#include "libhsm.h"
47#include "signertasks.h"
48#include "signercommands.h"
49
50#include <errno.h>
51#include <libxml/parser.h>
52#include <signal.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <strings.h>
57#include <sys/socket.h>
58#include <sys/types.h>
59#include <sys/un.h>
60#include <time.h>
61#include <unistd.h>
62
63static const char* engine_str = "engine";
64
65static engine_type* engine = NULL;
66
71static engine_type*
72engine_create(void)
73{
74 engine_type* engine;
75 CHECKALLOC(engine = (engine_type*) malloc(sizeof(engine_type)));
76 engine->config = NULL;
77 engine->workers = NULL;
78 engine->cmdhandler = NULL;
79 engine->dnshandler = NULL;
80 engine->xfrhandler = NULL;
81 engine->taskq = NULL;
82 engine->pid = -1;
83 engine->uid = -1;
84 engine->gid = -1;
85 engine->daemonize = 0;
86 engine->need_to_exit = 0;
87 engine->need_to_reload = 0;
88 pthread_mutex_init(&engine->signal_lock, NULL);
89 pthread_cond_init(&engine->signal_cond, NULL);
90 engine->zonelist = zonelist_create();
91 if (!engine->zonelist) {
92 engine_cleanup(engine);
93 return NULL;
94 }
95 if (!(engine->taskq = schedule_create())) {
96 engine_cleanup(engine);
97 return NULL;
98 }
99 schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_SIGNCONF, do_readsignconf);
100 schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_FORCESIGNCONF, do_forcereadsignconf);
101 schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_READ, do_readzone);
102 schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_FORCEREAD, do_forcereadzone);
103 schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_SIGN, do_signzone);
104 schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_WRITE, do_writezone);
105 return engine;
106}
107
108static void
109engine_start_cmdhandler(engine_type* engine)
110{
111 ods_log_debug("[%s] start command handler", engine_str);
112 janitor_thread_create(&engine->cmdhandler->thread_id, workerthreadclass, (janitor_runfn_t)cmdhandler_start, engine->cmdhandler);
113}
114
119static void
120engine_start_dnshandler(engine_type* engine)
121{
122 if (!engine || !engine->dnshandler) {
123 return;
124 }
125 ods_log_debug("[%s] start dnshandler", engine_str);
126 engine->dnshandler->engine = engine;
127 janitor_thread_create(&engine->dnshandler->thread_id, handlerthreadclass, (janitor_runfn_t)dnshandler_start, engine->dnshandler);
128}
129static void
130engine_stop_dnshandler(engine_type* engine)
131{
132 if (!engine || !engine->dnshandler || !engine->dnshandler->thread_id) {
133 return;
134 }
135 ods_log_debug("[%s] stop dnshandler", engine_str);
136 engine->dnshandler->need_to_exit = 1;
138 ods_log_debug("[%s] join dnshandler", engine_str);
139 janitor_thread_join(engine->dnshandler->thread_id);
140 engine->dnshandler->engine = NULL;
141}
142
143
144static void
145engine_start_xfrhandler(engine_type* engine)
146{
147 if (!engine || !engine->xfrhandler) {
148 return;
149 }
150 ods_log_debug("[%s] start xfrhandler", engine_str);
151 engine->xfrhandler->engine = engine;
152 /* This might be the wrong place to mark the xfrhandler started but
153 * if its isn't done here we might try to shutdown and stop it before
154 * it has marked itself started
155 */
156 engine->xfrhandler->started = 1;
157 janitor_thread_create(&engine->xfrhandler->thread_id, handlerthreadclass, (janitor_runfn_t)xfrhandler_start, engine->xfrhandler);
158}
159static void
160engine_stop_xfrhandler(engine_type* engine)
161{
162 if (!engine || !engine->xfrhandler) {
163 return;
164 }
165 ods_log_debug("[%s] stop xfrhandler", engine_str);
166 engine->xfrhandler->need_to_exit = 1;
168 ods_log_debug("[%s] join xfrhandler", engine_str);
169 if (engine->xfrhandler->started) {
170 janitor_thread_join(engine->xfrhandler->thread_id);
171 engine->xfrhandler->started = 0;
172 }
173 engine->xfrhandler->engine = NULL;
174}
175
176
181static ods_status
182engine_privdrop(engine_type* engine)
183{
184 ods_status status = ODS_STATUS_OK;
185 uid_t uid = -1;
186 gid_t gid = -1;
187 ods_log_assert(engine);
188 ods_log_assert(engine->config);
189 ods_log_debug("[%s] drop privileges", engine_str);
190 if (engine->config->username && engine->config->group) {
191 ods_log_verbose("[%s] drop privileges to user %s, group %s",
192 engine_str, engine->config->username, engine->config->group);
193 } else if (engine->config->username) {
194 ods_log_verbose("[%s] drop privileges to user %s", engine_str,
195 engine->config->username);
196 } else if (engine->config->group) {
197 ods_log_verbose("[%s] drop privileges to group %s", engine_str,
198 engine->config->group);
199 }
200 if (engine->config->chroot) {
201 ods_log_verbose("[%s] chroot to %s", engine_str,
202 engine->config->chroot);
203 }
204 status = privdrop(engine->config->username, engine->config->group,
205 engine->config->chroot, &uid, &gid);
206 engine->uid = uid;
207 engine->gid = gid;
208 privclose(engine->config->username, engine->config->group);
209 return status;
210}
211
212
217static void
218engine_create_workers(engine_type* engine)
219{
220 char* name;
221 int i;
222 int numTotalWorkers;
223 int threadCount = 0;
224 ods_log_assert(engine);
225 ods_log_assert(engine->config);
226 numTotalWorkers = engine->config->num_worker_threads + engine->config->num_signer_threads;
227 CHECKALLOC(engine->workers = (worker_type**) malloc(numTotalWorkers * sizeof(worker_type*)));
228 for (i=0; i < engine->config->num_worker_threads; i++) {
229 asprintf(&name, "worker[%d]", i+1);
230 engine->workers[threadCount++] = worker_create(name, engine->taskq);
231 }
232 for (i=0; i < engine->config->num_signer_threads; i++) {
233 asprintf(&name, "drudger[%d]", i+1);
234 engine->workers[threadCount++] = worker_create(name, engine->taskq);
235 }
236}
237
238static void
239engine_start_workers(engine_type* engine)
240{
241 int i;
242 int threadCount = 0;
243 struct worker_context* context;
244 ods_log_assert(engine);
245 ods_log_assert(engine->config);
246 ods_log_debug("[%s] start workers", engine_str);
247 for (i=0; i < engine->config->num_worker_threads; i++,threadCount++) {
248 CHECKALLOC(context = malloc(sizeof(struct worker_context)));
249 context->engine = engine;
250 context->worker = engine->workers[threadCount];
251 context->signq = engine->taskq->signq;
252 engine->workers[threadCount]->need_to_exit = 0;
253 engine->workers[threadCount]->context = context;
254 janitor_thread_create(&engine->workers[threadCount]->thread_id, workerthreadclass, (janitor_runfn_t)worker_start, engine->workers[threadCount]);
255 }
256 for (i=0; i < engine->config->num_signer_threads; i++,threadCount++) {
257 engine->workers[threadCount]->need_to_exit = 0;
258 janitor_thread_create(&engine->workers[threadCount]->thread_id, workerthreadclass, (janitor_runfn_t)drudge, engine->workers[threadCount]);
259 }
260}
261
262static void
263engine_stop_threads(engine_type* engine)
264{
265 int i;
266 int numTotalWorkers;
267 ods_log_assert(engine);
268 ods_log_assert(engine->config);
269 ods_log_debug("[%s] stop workers and drudgers", engine_str);
271 for (i=0; i < numTotalWorkers; i++) {
272 engine->workers[i]->need_to_exit = 1;
273 }
274 ods_log_debug("[%s] notify workers and drudgers", engine_str);
275 schedule_release_all(engine->taskq);
276
277 for (i=0; i < numTotalWorkers; i++) {
278 ods_log_debug("[%s] join worker %d", engine_str, i+1);
279 janitor_thread_join(engine->workers[i]->thread_id);
280 free(engine->workers[i]->context);
281 }
282}
283
284
289void
291{
292 size_t i = 0;
293 ods_log_assert(engine);
294 ods_log_assert(engine->config);
295 ods_log_debug("[%s] wake up workers", engine_str);
296 /* wake up sleepyheads */
297 schedule_release_all(engine->taskq);
298}
299
300static void
301signal_handler(sig_atomic_t sig)
302{
303 switch (sig) {
304 case SIGHUP:
305 if (engine) {
307 pthread_mutex_lock(&engine->signal_lock);
308 pthread_cond_signal(&engine->signal_cond);
309 pthread_mutex_unlock(&engine->signal_lock);
310 }
311 break;
312 case SIGINT:
313 case SIGTERM:
314 if (engine) {
315 engine->need_to_exit = 1;
316 pthread_mutex_lock(&engine->signal_lock);
317 pthread_cond_signal(&engine->signal_cond);
318 pthread_mutex_unlock(&engine->signal_lock);
319 }
320 break;
321 default:
322 break;
323 }
324}
325
330static ods_status
331engine_setup(void)
332{
333 ods_status status = ODS_STATUS_OK;
334 struct sigaction action;
335 int sockets[2] = {0,0};
336 int pipefd[2];
337 char buff = '\0';
338 int fd, error;
339
340 ods_log_debug("[%s] setup signer engine", engine_str);
341 if (!engine || !engine->config) {
342 return ODS_STATUS_ASSERT_ERR;
343 }
344 /* set edns */
346
347 /* create command handler (before chowning socket file) */
348 engine->cmdhandler = cmdhandler_create(engine->config->clisock_filename, signercommands, engine, NULL, NULL);
349 if (!engine->cmdhandler) {
350 return ODS_STATUS_CMDHANDLER_ERR;
351 }
352 engine->dnshandler = dnshandler_create(engine->config->interfaces);
353 engine->xfrhandler = xfrhandler_create();
354 if (!engine->xfrhandler) {
355 return ODS_STATUS_XFRHANDLER_ERR;
356 }
357 if (engine->dnshandler) {
358 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
359 return ODS_STATUS_XFRHANDLER_ERR;
360 }
361 engine->xfrhandler->dnshandler.fd = sockets[0];
362 engine->dnshandler->xfrhandler.fd = sockets[1];
363 status = dnshandler_listen(engine->dnshandler);
364 if (status != ODS_STATUS_OK) {
365 ods_log_error("[%s] setup: unable to listen to sockets (%s)",
366 engine_str, ods_status2str(status));
367 return ODS_STATUS_XFRHANDLER_ERR;
368 }
369 }
370 /* privdrop */
371 engine->uid = privuid(engine->config->username);
372 engine->gid = privgid(engine->config->group);
373 /* TODO: does piddir exists? */
374 /* remove the chown stuff: piddir? */
375 ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
376 ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
377 ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
378 if (engine->config->log_filename && !engine->config->use_syslog) {
379 ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
380 }
381 if (engine->config->working_dir &&
382 chdir(engine->config->working_dir) != 0) {
383 ods_log_error("[%s] setup: unable to chdir to %s (%s)", engine_str,
384 engine->config->working_dir, strerror(errno));
385 return ODS_STATUS_CHDIR_ERR;
386 }
387 if (engine_privdrop(engine) != ODS_STATUS_OK) {
388 return ODS_STATUS_PRIVDROP_ERR;
389 }
390 /* daemonize */
391 if (engine->daemonize) {
392 if (pipe(pipefd)) {
393 ods_log_error("[%s] unable to pipe: %s", engine_str, strerror(errno));
394 return ODS_STATUS_PIPE_ERR;
395 }
396 switch ((engine->pid = fork())) {
397 case -1: /* error */
398 ods_log_error("[%s] setup: unable to fork daemon (%s)",
399 engine_str, strerror(errno));
400 return ODS_STATUS_FORK_ERR;
401 case 0: /* child */
402 close(pipefd[0]);
403 break;
404 default: /* parent */
405 engine_cleanup(engine);
406 engine = NULL;
407 xmlCleanupParser();
408 xmlCleanupGlobals();
409 close(pipefd[1]);
410 while (read(pipefd[0], &buff, 1) != -1) {
411 if (buff <= 1) break;
412 printf("%c", buff);
413 }
414 close(pipefd[0]);
415 if (buff == '\1') {
416 ods_log_debug("[%s] signerd started successfully", engine_str);
417 exit(0);
418 }
419 ods_log_error("[%s] fail to start signerd completely", engine_str);
420 exit(1);
421 }
422 if (setsid() == -1) {
423 ods_log_error("[%s] setup: unable to setsid daemon (%s)",
424 engine_str, strerror(errno));
425 const char *err = "unable to setsid daemon: ";
426 ods_writen(pipefd[1], err, strlen(err));
427 ods_writeln(pipefd[1], strerror(errno));
428 write(pipefd[1], "\0", 1);
429 close(pipefd[1]);
430 return ODS_STATUS_SETSID_ERR;
431 }
432 }
433 engine->pid = getpid();
434 /* write pidfile */
435 if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
436 if (engine->daemonize) {
437 ods_writeln(pipefd[1], "Unable to write pid file");
438 write(pipefd[1], "\0", 1);
439 close(pipefd[1]);
440 }
441 return ODS_STATUS_WRITE_PIDFILE_ERR;
442 }
443 /* setup done */
444 ods_log_verbose("[%s] running as pid %lu", engine_str,
445 (unsigned long) engine->pid);
446 /* catch signals */
447 action.sa_handler = (void (*)(int))signal_handler;
448 sigfillset(&action.sa_mask);
449 action.sa_flags = 0;
450 sigaction(SIGTERM, &action, NULL);
451 sigaction(SIGHUP, &action, NULL);
452 sigaction(SIGINT, &action, NULL);
453 sigaction(SIGILL, &action, NULL);
454 sigaction(SIGUSR1, &action, NULL);
455 sigaction(SIGALRM, &action, NULL);
456 sigaction(SIGCHLD, &action, NULL);
457 action.sa_handler = SIG_IGN;
458 sigaction(SIGPIPE, &action, NULL);
459 /* create workers/drudgers */
460 engine_create_workers(engine);
461 /* start cmd/dns/xfr handlers */
462 engine_start_cmdhandler(engine);
463 engine_start_dnshandler(engine);
464 engine_start_xfrhandler(engine);
466 if (engine->daemonize) {
467 write(pipefd[1], "\1", 1);
468 close(pipefd[1]);
469 }
470 return ODS_STATUS_OK;
471}
472
473
478static void
479engine_run(engine_type* engine)
480{
481 if (!engine) {
482 return;
483 }
484 engine_start_workers(engine);
485
486 while (!engine->need_to_exit && !engine->need_to_reload) {
487 /* We must use locking here to avoid race conditions. We want
488 * to sleep indefinitely and want to wake up on signal. This
489 * is to make sure we never mis the signal. */
490 pthread_mutex_lock(&engine->signal_lock);
491 if (!engine->need_to_exit && !engine->need_to_reload) {
492 /* TODO: this silly. We should be handling the commandhandler
493 * connections. No reason to spawn that as a thread.
494 * Also it would be easier to wake up the command hander
495 * as signals will reach it if it is the main thread! */
496 ods_log_debug("[%s] taking a break", engine_str);
497 pthread_cond_wait(&engine->signal_cond, &engine->signal_lock);
498 }
499 pthread_mutex_unlock(&engine->signal_lock);
500 }
501 ods_log_debug("[%s] signer halted", engine_str);
502 engine_stop_threads(engine);
503}
504
505
510static void
511set_notify_ns(zone_type* zone, const char* cmd)
512{
513 const char* str = NULL;
514 const char* str2 = NULL;
515 char* token = NULL;
516 ods_log_assert(cmd);
517 ods_log_assert(zone);
518 ods_log_assert(zone->name);
519 ods_log_assert(zone->adoutbound);
520 if (zone->adoutbound->type == ADAPTER_FILE) {
521 str = ods_replace(cmd, "%zonefile", zone->adoutbound->configstr);
522 if (!str) {
523 ods_log_error("[%s] unable to set notify ns: replace zonefile failed",
524 engine_str);
525 }
526 str2 = ods_replace(str, "%zone", zone->name);
527 free((void*)str);
528 } else {
529 str2 = ods_replace(cmd, "%zone", zone->name);
530 }
531 if (str2) {
532 ods_str_trim((char*) str2, 1);
533 str = str2;
534 if (*str) {
535 token = NULL;
536 while ((token = strtok((char*) str, " "))) {
537 if (*token) {
538 ods_str_list_add(&zone->notify_args, token);
539 }
540 str = NULL;
541 }
542 }
543 zone->notify_command = (char*) str2;
544 zone->notify_ns = zone->notify_args[0];
545 ods_log_debug("[%s] set notify ns: %s", engine_str, zone->notify_ns);
546 } else {
547 ods_log_error("[%s] unable to set notify ns: replace zone failed",
548 engine_str);
549 }
550}
551
552
557static int
558dnsconfig_zone(engine_type* engine, zone_type* zone)
559{
560 int numdns = 0;
561 ods_log_assert(engine);
562 ods_log_assert(engine->xfrhandler);
563 ods_log_assert(engine->xfrhandler->netio);
564 ods_log_assert(zone);
565 ods_log_assert(zone->adinbound);
566 ods_log_assert(zone->adoutbound);
567 ods_log_assert(zone->name);
568
569 if (zone->adinbound->type == ADAPTER_DNS) {
570 /* zone transfer handler */
571 if (!zone->xfrd) {
572 ods_log_debug("[%s] add transfer handler for zone %s",
573 engine_str, zone->name);
574 zone->xfrd = xfrd_create((void*) engine->xfrhandler,
575 (void*) zone);
576 ods_log_assert(zone->xfrd);
578 &zone->xfrd->handler);
579 } else if (!zone->xfrd->serial_disk_acquired) {
581 }
582 numdns++;
583 } else if (zone->xfrd) {
585 &zone->xfrd->handler);
586 xfrd_cleanup(zone->xfrd, 0);
587 zone->xfrd = NULL;
588 }
589 if (zone->adoutbound->type == ADAPTER_DNS) {
590 /* notify handler */
591 if (!zone->notify) {
592 ods_log_debug("[%s] add notify handler for zone %s",
593 engine_str, zone->name);
594 zone->notify = notify_create((void*) engine->xfrhandler,
595 (void*) zone);
596 ods_log_assert(zone->notify);
598 &zone->notify->handler);
599 }
600 numdns++;
601 } else if (zone->notify) {
603 &zone->notify->handler);
604 notify_cleanup(zone->notify);
605 zone->notify = NULL;
606 }
607 return numdns;
608}
609
610
615void
616engine_update_zones(engine_type* engine, ods_status zl_changed)
617{
618 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
619 zone_type* zone = NULL;
620 ods_status status = ODS_STATUS_OK;
621 unsigned wake_up = 0;
622 int warnings = 0;
623
624 if (!engine || !engine->zonelist || !engine->zonelist->zones) {
625 return;
626 }
627
628 ods_log_debug("[%s] commit zone list changes", engine_str);
629 pthread_mutex_lock(&engine->zonelist->zl_lock);
630 node = ldns_rbtree_first(engine->zonelist->zones);
631 while (node && node != LDNS_RBTREE_NULL) {
632 zone = (zone_type*) node->data;
633
634 if (zone->zl_status == ZONE_ZL_REMOVED) {
635 node = ldns_rbtree_next(node);
636 pthread_mutex_lock(&zone->zone_lock);
637 zonelist_del_zone(engine->zonelist, zone);
638 schedule_unscheduletask(engine->taskq, schedule_WHATEVER, zone->name);
639 pthread_mutex_unlock(&zone->zone_lock);
641 &zone->xfrd->handler);
642 zone_cleanup(zone);
643 zone = NULL;
644 continue;
645 } else if (zone->zl_status == ZONE_ZL_ADDED) {
646 pthread_mutex_lock(&zone->zone_lock);
647 /* set notify nameserver command */
648 if (engine->config->notify_command && !zone->notify_ns) {
649 set_notify_ns(zone, engine->config->notify_command);
650 }
651 pthread_mutex_unlock(&zone->zone_lock);
652 }
653 /* load adapter config */
654 status = adapter_load_config(zone->adinbound);
655 if (status != ODS_STATUS_OK) {
656 ods_log_error("[%s] unable to load config for inbound adapter "
657 "for zone %s: %s", engine_str, zone->name,
658 ods_status2str(status));
659 }
660 status = adapter_load_config(zone->adoutbound);
661 if (status != ODS_STATUS_OK) {
662 ods_log_error("[%s] unable to load config for outbound adapter "
663 "for zone %s: %s", engine_str, zone->name,
664 ods_status2str(status));
665 }
666 /* for dns adapters */
667 warnings += dnsconfig_zone(engine, zone);
668
669 if (zone->zl_status == ZONE_ZL_ADDED) {
670 schedule_scheduletask(engine->taskq, TASK_SIGNCONF, zone->name, zone, &zone->zone_lock, 0);
671 } else if (zl_changed == ODS_STATUS_OK) {
672 schedule_scheduletask(engine->taskq, TASK_FORCESIGNCONF, zone->name, zone, &zone->zone_lock, 0);
673 }
674 if (status != ODS_STATUS_OK) {
675 ods_log_crit("[%s] unable to schedule task for zone %s: %s",
676 engine_str, zone->name, ods_status2str(status));
677 } else {
678 wake_up = 1;
679 zone->zl_status = ZONE_ZL_OK;
680 }
681 node = ldns_rbtree_next(node);
682 }
683 pthread_mutex_unlock(&engine->zonelist->zl_lock);
684 if (engine->dnshandler) {
685 ods_log_debug("[%s] forward notify for all zones", engine_str);
687 (uint8_t*) ODS_SE_NOTIFY_CMD, strlen(ODS_SE_NOTIFY_CMD));
688 } else if (warnings) {
689 ods_log_warning("[%s] no dnshandler/listener configured, but zones "
690 "are configured with dns adapters: notify and zone transfer "
691 "requests will not work properly", engine_str);
692 }
693 if (wake_up) {
694 engine_wakeup_workers(engine);
695 }
696}
697
698
703static ods_status
704engine_recover(engine_type* engine)
705{
706 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
707 zone_type* zone = NULL;
708 ods_status status = ODS_STATUS_OK;
709 ods_status result = ODS_STATUS_UNCHANGED;
710
711 if (!engine || !engine->zonelist || !engine->zonelist->zones) {
712 ods_log_error("[%s] cannot recover zones: no engine or zonelist",
713 engine_str);
714 return ODS_STATUS_ERR; /* no need to update zones */
715 }
716 ods_log_assert(engine);
717 ods_log_assert(engine->zonelist);
718 ods_log_assert(engine->zonelist->zones);
719
720 pthread_mutex_lock(&engine->zonelist->zl_lock);
721 /* [LOCK] zonelist */
722 node = ldns_rbtree_first(engine->zonelist->zones);
723 while (node && node != LDNS_RBTREE_NULL) {
724 zone = (zone_type*) node->data;
725
726 ods_log_assert(zone->zl_status == ZONE_ZL_ADDED);
727 pthread_mutex_lock(&zone->zone_lock);
728 status = zone_recover2(engine, zone);
729 if (status == ODS_STATUS_OK) {
730 ods_log_assert(zone->db);
731 ods_log_assert(zone->signconf);
732 /* notify nameserver */
733 if (engine->config->notify_command && !zone->notify_ns) {
734 set_notify_ns(zone, engine->config->notify_command);
735 }
736 if (status != ODS_STATUS_OK) {
737 ods_log_crit("[%s] unable to schedule task for zone %s: %s",
738 engine_str, zone->name, ods_status2str(status));
739 result = ODS_STATUS_OK; /* will trigger update zones */
740 } else {
741 ods_log_debug("[%s] recovered zone %s", engine_str,
742 zone->name);
743 /* recovery done */
744 zone->zl_status = ZONE_ZL_OK;
745 }
746 } else {
747 if (status != ODS_STATUS_UNCHANGED) {
748 ods_log_warning("[%s] unable to recover zone %s from backup,"
749 " performing full sign", engine_str, zone->name);
750 }
751 result = ODS_STATUS_OK; /* will trigger update zones */
752 }
753 pthread_mutex_unlock(&zone->zone_lock);
754 node = ldns_rbtree_next(node);
755 }
756 /* [UNLOCK] zonelist */
757 pthread_mutex_unlock(&engine->zonelist->zl_lock);
758 return result;
759}
760
761
766int
767engine_start(const char* cfgfile, int cmdline_verbosity, int daemonize, int info)
768{
769 ods_status zl_changed = ODS_STATUS_UNCHANGED;
770 ods_status status = ODS_STATUS_OK;
771
772 engine = engine_create();
773 if (!engine) {
774 ods_fatal_exit("[%s] create failed", engine_str);
775 return 1;
776 }
777 engine->daemonize = daemonize;
778
779 /* config */
780 engine->config = engine_config(cfgfile, cmdline_verbosity);
781 status = engine_config_check(engine->config);
782 if (status != ODS_STATUS_OK) {
783 ods_log_error("[%s] cfgfile %s has errors", engine_str, cfgfile);
784 goto earlyexit;
785 }
786 if (info) {
787 engine_config_print(stdout, engine->config); /* for debugging */
788 goto earlyexit;
789 }
790 /* check pidfile */
791 if (!util_check_pidfile(engine->config->pid_filename)) {
792 exit(1);
793 }
794 /* setup */
795 status = engine_setup();
796 if (status != ODS_STATUS_OK) {
797 ods_log_error("[%s] setup failed: %s", engine_str,
798 ods_status2str(status));
799 goto earlyexit;
800 }
801
802 /* run */
803 while (engine->need_to_exit == 0) {
804 /* update zone list */
805 pthread_mutex_lock(&engine->zonelist->zl_lock);
806 zl_changed = zonelist_update(engine->zonelist,
807 engine->config->zonelist_filename);
808 engine->zonelist->just_removed = 0;
809 engine->zonelist->just_added = 0;
810 engine->zonelist->just_updated = 0;
811 pthread_mutex_unlock(&engine->zonelist->zl_lock);
812 /* start/reload */
813 if (engine->need_to_reload) {
814 ods_log_info("[%s] signer reloading", engine_str);
815 engine->need_to_reload = 0;
816 } else {
817 ods_log_info("[%s] signer started (version %s), pid %u",
818 engine_str, PACKAGE_VERSION, engine->pid);
819 if (hsm_open2(engine->config->repositories, hsm_check_pin) != HSM_OK) {
820 char* error = hsm_get_error(NULL);
821 if (error != NULL) {
822 ods_log_error("[%s] %s", "hsm", error);
823 free(error);
824 }
825 ods_log_error("[%s] opening hsm failed (for engine recover)", engine_str);
826 break;
827 }
828 zl_changed = engine_recover(engine);
829 hsm_close();
830 }
831 if (zl_changed == ODS_STATUS_OK ||
832 zl_changed == ODS_STATUS_UNCHANGED) {
833 engine_update_zones(engine, zl_changed);
834 }
835 if (hsm_open2(engine->config->repositories, hsm_check_pin) != HSM_OK) {
836 char* error = hsm_get_error(NULL);
837 if (error != NULL) {
838 ods_log_error("[%s] %s", "hsm", error);
839 free(error);
840 }
841 ods_log_error("[%s] opening hsm failed (for engine run)", engine_str);
842 break;
843 }
844 engine_run(engine);
845 hsm_close();
846 }
847
848 /* shutdown */
849 ods_log_info("[%s] signer shutdown", engine_str);
850 cmdhandler_stop(engine->cmdhandler);
851 engine_stop_xfrhandler(engine);
852 engine_stop_dnshandler(engine);
853
854earlyexit:
855 if (engine && engine->config) {
856 if (engine->config->pid_filename) {
857 (void)unlink(engine->config->pid_filename);
858 }
859 if (engine->config->clisock_filename) {
860 (void)unlink(engine->config->clisock_filename);
861 }
862 }
864 engine_cleanup(engine);
865 engine = NULL;
866
867 return status;
868}
869
870
875void
877{
878 int i;
879 int numTotalWorkers;
880
881 if (!engine) {
882 return;
883 }
884 if (engine->config) {
885 numTotalWorkers = engine->config->num_worker_threads + engine->config->num_signer_threads;
886 if (engine->workers) {
887 for (i=0; i < (size_t) numTotalWorkers; i++) {
888 worker_cleanup(engine->workers[i]);
889 }
890 free(engine->workers);
891 }
892 zonelist_cleanup(engine->zonelist);
893 schedule_cleanup(engine->taskq);
894 cmdhandler_cleanup(engine->cmdhandler);
898 pthread_mutex_destroy(&engine->signal_lock);
899 pthread_cond_destroy(&engine->signal_cond);
900 }
901 free(engine);
902}
ods_status adapter_load_config(adapter_type *adapter)
Definition: adapter.c:99
@ ADAPTER_DNS
Definition: adapter.h:42
@ ADAPTER_FILE
Definition: adapter.h:41
void engine_config_cleanup(engineconfig_type *config)
Definition: cfg.c:243
void engine_config_print(FILE *out, engineconfig_type *config)
Definition: cfg.c:146
ods_status engine_config_check(engineconfig_type *config)
Definition: cfg.c:110
engineconfig_type * engine_config(const char *cfgfile, int cmdline_verbosity)
Definition: cfg.c:51
void dnshandler_signal(dnshandler_type *dnshandler)
Definition: dnshandler.c:218
dnshandler_type * dnshandler_create(listener_type *interfaces)
Definition: dnshandler.c:51
ods_status dnshandler_listen(dnshandler_type *dnshandler)
Definition: dnshandler.c:106
void dnshandler_start(dnshandler_type *dnshandler)
Definition: dnshandler.c:125
void dnshandler_cleanup(dnshandler_type *dnshandler)
Definition: dnshandler.c:277
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
Definition: dnshandler.c:231
#define ODS_SE_NOTIFY_CMD
Definition: dnshandler.h:48
void edns_init(edns_data_type *data, uint16_t max_length)
Definition: edns.c:64
#define EDNS_MAX_MESSAGE_LEN
Definition: edns.h:47
void engine_wakeup_workers(engine_type *engine)
Definition: engine.c:290
void engine_cleanup(engine_type *engine)
Definition: engine.c:876
int engine_start(const char *cfgfile, int cmdline_verbosity, int daemonize, int info)
Definition: engine.c:767
void engine_update_zones(engine_type *engine, ods_status zl_changed)
Definition: engine.c:616
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:72
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:53
notify_type * notify_create(xfrhandler_type *xfrhandler, zone_type *zone)
Definition: notify.c:100
void notify_cleanup(notify_type *notify)
Definition: notify.c:600
struct cmd_func_block ** signercommands
time_t do_forcereadzone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:388
time_t do_readzone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:343
void drudge(worker_type *worker)
Definition: signertasks.c:152
time_t do_forcereadsignconf(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:239
time_t do_readsignconf(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:209
time_t do_signzone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:268
time_t do_writezone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:426
adapter_mode type
Definition: adapter.h:58
const char * configstr
Definition: adapter.h:60
netio_handler_type xfrhandler
Definition: dnshandler.h:58
janitor_thread_t thread_id
Definition: dnshandler.h:52
engine_type * engine
Definition: dnshandler.h:53
unsigned need_to_exit
Definition: dnshandler.h:59
edns_data_type edns
Definition: engine.h:72
zonelist_type * zonelist
Definition: engine.h:69
schedule_type * taskq
Definition: engine.h:54
xfrhandler_type * xfrhandler
Definition: engine.h:71
pthread_mutex_t signal_lock
Definition: engine.h:67
pid_t pid
Definition: engine.h:57
gid_t gid
Definition: engine.h:59
cmdhandler_type * cmdhandler
Definition: engine.h:55
pthread_cond_t signal_cond
Definition: engine.h:66
int need_to_reload
Definition: engine.h:63
int daemonize
Definition: engine.h:61
uid_t uid
Definition: engine.h:58
int need_to_exit
Definition: engine.h:62
dnshandler_type * dnshandler
Definition: engine.h:70
worker_type ** workers
Definition: engine.h:53
engineconfig_type * config
Definition: engine.h:52
const char * chroot
Definition: cfg.h:57
listener_type * interfaces
Definition: cfg.h:46
const char * notify_command
Definition: cfg.h:52
const char * group
Definition: cfg.h:56
const char * clisock_filename
Definition: cfg.h:53
const char * working_dir
Definition: cfg.h:54
hsm_repository_t * repositories
Definition: cfg.h:47
int num_worker_threads
Definition: cfg.h:59
int use_syslog
Definition: cfg.h:58
const char * pid_filename
Definition: cfg.h:51
const char * zonelist_filename
Definition: cfg.h:49
const char * log_filename
Definition: cfg.h:50
int num_signer_threads
Definition: cfg.h:60
const char * username
Definition: cfg.h:55
netio_handler_type handler
Definition: notify.h:63
worker_type * worker
Definition: signertasks.h:40
engine_type * engine
Definition: signertasks.h:39
fifoq_type * signq
Definition: signertasks.h:41
time_t serial_disk_acquired
Definition: xfrd.h:118
netio_handler_type handler
Definition: xfrd.h:124
netio_type * netio
Definition: xfrhandler.h:60
unsigned started
Definition: xfrhandler.h:73
janitor_thread_t thread_id
Definition: xfrhandler.h:54
engine_type * engine
Definition: xfrhandler.h:55
unsigned need_to_exit
Definition: xfrhandler.h:72
netio_handler_type dnshandler
Definition: xfrhandler.h:70
char * notify_command
Definition: zone.h:65
signconf_type * signconf
Definition: zone.h:77
notify_type * notify
Definition: zone.h:83
char ** notify_args
Definition: zone.h:67
const char * notify_ns
Definition: zone.h:66
namedb_type * db
Definition: zone.h:79
adapter_type * adinbound
Definition: zone.h:74
zone_zl_status zl_status
Definition: zone.h:72
xfrd_type * xfrd
Definition: zone.h:82
const char * name
Definition: zone.h:69
pthread_mutex_t zone_lock
Definition: zone.h:86
adapter_type * adoutbound
Definition: zone.h:75
int just_updated
Definition: zonelist.h:48
int just_removed
Definition: zonelist.h:49
pthread_mutex_t zl_lock
Definition: zonelist.h:50
ldns_rbtree_t * zones
Definition: zonelist.h:45
ods_status tsig_handler_init()
Definition: tsig.c:116
void tsig_handler_cleanup(void)
Definition: tsig.c:135
void xfrd_set_timer_now(xfrd_type *xfrd)
Definition: xfrd.c:454
xfrd_type * xfrd_create(xfrhandler_type *xfrhandler, zone_type *zone)
Definition: xfrd.c:315
void xfrd_cleanup(xfrd_type *xfrd, int backup)
Definition: xfrd.c:2179
void xfrhandler_cleanup(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:198
void xfrhandler_start(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:110
xfrhandler_type * xfrhandler_create()
Definition: xfrhandler.c:52
void xfrhandler_signal(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:159
void zone_cleanup(zone_type *zone)
Definition: zone.c:759
ods_status zone_recover2(engine_type *engine, zone_type *zone)
Definition: zone.c:792
@ ZONE_ZL_REMOVED
Definition: zone.h:37
@ ZONE_ZL_ADDED
Definition: zone.h:35
@ ZONE_ZL_OK
Definition: zone.h:34
zonelist_type * zonelist_create()
Definition: zonelist.c:74
void zonelist_del_zone(zonelist_type *zlist, zone_type *zone)
Definition: zonelist.c:238
ods_status zonelist_update(zonelist_type *zl, const char *zlfile)
Definition: zonelist.c:342
void zonelist_cleanup(zonelist_type *zl)
Definition: zonelist.c:432