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