52#include <libxml/parser.h>
58#include <sys/socket.h>
64static const char* engine_str =
"engine";
77 engine->config = NULL;
78 engine->workers = NULL;
79 engine->cmdhandler = NULL;
80 engine->dnshandler = NULL;
81 engine->xfrhandler = NULL;
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);
92 if (!engine->zonelist) {
96 if (!(engine->taskq = schedule_create())) {
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);
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);
123 if (!engine || !engine->dnshandler) {
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);
133 if (!engine || !engine->dnshandler || !engine->dnshandler->thread_id) {
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;
148 if (!engine || !engine->xfrhandler) {
151 ods_log_debug(
"[%s] start xfrhandler", engine_str);
152 engine->xfrhandler->engine = engine;
157 engine->xfrhandler->started = 1;
158 janitor_thread_create(&engine->xfrhandler->thread_id, handlerthreadclass, (janitor_runfn_t)
xfrhandler_start, engine->xfrhandler);
163 if (!engine || !engine->xfrhandler) {
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;
174 engine->xfrhandler->engine = NULL;
185 ods_status status = ODS_STATUS_OK;
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);
201 if (engine->config->chroot) {
202 ods_log_verbose(
"[%s] chroot to %s", engine_str,
203 engine->config->chroot);
205 status = privdrop(engine->config->username, engine->config->group,
206 engine->config->chroot, &uid, &gid);
209 privclose(engine->config->username, engine->config->group);
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);
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);
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++) {
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]);
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]);
268 ods_log_assert(engine);
269 ods_log_assert(engine->config);
270 ods_log_debug(
"[%s] stop workers and drudgers", engine_str);
271 numTotalWorkers = engine->config->num_worker_threads + engine->config->num_signer_threads;
272 for (i=0; i < numTotalWorkers; i++) {
273 engine->workers[i]->need_to_exit = 1;
275 ods_log_debug(
"[%s] notify workers and drudgers", engine_str);
276 schedule_release_all(engine->taskq);
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);
294 ods_log_assert(engine);
295 ods_log_assert(engine->config);
296 ods_log_debug(
"[%s] wake up workers", engine_str);
298 schedule_release_all(engine->taskq);
302signal_handler(sig_atomic_t sig)
307 engine->need_to_reload = 1;
308 pthread_mutex_lock(&engine->signal_lock);
309 pthread_cond_signal(&engine->signal_cond);
310 pthread_mutex_unlock(&engine->signal_lock);
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);
334 ods_status status = ODS_STATUS_OK;
335 struct sigaction action;
336 int sockets[2] = {0,0};
341 ods_log_debug(
"[%s] setup signer engine", engine_str);
342 if (!engine || !engine->config) {
343 return ODS_STATUS_ASSERT_ERR;
349 engine->cmdhandler = cmdhandler_create(engine->config->clisock_filename,
signercommands, engine, NULL, NULL);
350 if (!engine->cmdhandler) {
351 return ODS_STATUS_CMDHANDLER_ERR;
355 if (!engine->xfrhandler) {
356 return ODS_STATUS_XFRHANDLER_ERR;
358 if (engine->dnshandler) {
359 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
360 return ODS_STATUS_XFRHANDLER_ERR;
362 engine->xfrhandler->dnshandler.fd = sockets[0];
363 engine->dnshandler->xfrhandler.fd = sockets[1];
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;
372 engine->uid = privuid(engine->config->username);
373 engine->gid = privgid(engine->config->group);
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);
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;
388 if (engine_privdrop(engine) != ODS_STATUS_OK) {
389 return ODS_STATUS_PRIVDROP_ERR;
392 if (engine->daemonize) {
394 ods_log_error(
"[%s] unable to pipe: %s", engine_str, strerror(errno));
395 return ODS_STATUS_PIPE_ERR;
397 switch ((engine->pid = fork())) {
399 ods_log_error(
"[%s] setup: unable to fork daemon (%s)",
400 engine_str, strerror(errno));
401 return ODS_STATUS_FORK_ERR;
411 while (read(pipefd[0], &buff, 1) != -1) {
412 if (buff <= 1)
break;
417 ods_log_debug(
"[%s] signerd started successfully", engine_str);
420 ods_log_error(
"[%s] fail to start signerd completely", engine_str);
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);
431 return ODS_STATUS_SETSID_ERR;
434 engine->pid = getpid();
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);
442 return ODS_STATUS_WRITE_PIDFILE_ERR;
445 ods_log_verbose(
"[%s] running as pid %lu", engine_str,
446 (
unsigned long) engine->pid);
448 action.sa_handler = (void (*)(int))signal_handler;
449 sigfillset(&action.sa_mask);
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);
461 engine_create_workers(engine);
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);
471 return ODS_STATUS_OK;
485 engine_start_workers(engine);
487 while (!engine->need_to_exit && !engine->need_to_reload) {
491 pthread_mutex_lock(&engine->signal_lock);
492 if (!engine->need_to_exit && !engine->need_to_reload) {
497 ods_log_debug(
"[%s] taking a break", engine_str);
498 pthread_cond_wait(&engine->signal_cond, &engine->signal_lock);
500 pthread_mutex_unlock(&engine->signal_lock);
502 ods_log_debug(
"[%s] signer halted", engine_str);
503 engine_stop_threads(engine);
512set_notify_ns(
zone_type* zone,
const char* cmd)
514 const char* str = NULL;
515 const char* str2 = NULL;
518 ods_log_assert(zone);
519 ods_log_assert(zone->
name);
524 ods_log_error(
"[%s] unable to set notify ns: replace zonefile failed",
527 str2 = ods_replace(str,
"%zone", zone->
name);
530 str2 = ods_replace(cmd,
"%zone", zone->
name);
533 ods_str_trim((
char*) str2, 1);
537 while ((token = strtok((
char*) str,
" "))) {
546 ods_log_debug(
"[%s] set notify ns: %s", engine_str, zone->
notify_ns);
548 ods_log_error(
"[%s] unable to set notify ns: replace zone failed",
562 ods_log_assert(engine);
563 ods_log_assert(engine->xfrhandler);
564 ods_log_assert(engine->xfrhandler->netio);
565 ods_log_assert(zone);
568 ods_log_assert(zone->
name);
573 ods_log_debug(
"[%s] add transfer handler for zone %s",
574 engine_str, zone->
name);
577 ods_log_assert(zone->
xfrd);
584 }
else if (zone->
xfrd) {
593 ods_log_debug(
"[%s] add notify handler for zone %s",
594 engine_str, zone->
name);
597 ods_log_assert(zone->
notify);
602 }
else if (zone->
notify) {
619 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
621 ods_status status = ODS_STATUS_OK;
622 unsigned wake_up = 0;
625 if (!engine || !engine->zonelist || !engine->zonelist->zones) {
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) {
636 node = ldns_rbtree_next(node);
639 schedule_unscheduletask(engine->taskq, schedule_WHATEVER, zone->
name);
649 if (engine->config->notify_command && !zone->
notify_ns) {
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));
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));
668 warnings += dnsconfig_zone(engine, zone);
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);
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));
682 node = ldns_rbtree_next(node);
684 pthread_mutex_unlock(&engine->zonelist->zl_lock);
685 if (engine->dnshandler) {
686 ods_log_debug(
"[%s] forward notify for all zones", engine_str);
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);
707 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
709 ods_status status = ODS_STATUS_OK;
710 ods_status result = ODS_STATUS_UNCHANGED;
712 if (!engine || !engine->zonelist || !engine->zonelist->zones) {
713 ods_log_error(
"[%s] cannot recover zones: no engine or zonelist",
715 return ODS_STATUS_ERR;
717 ods_log_assert(engine);
718 ods_log_assert(engine->zonelist);
719 ods_log_assert(engine->zonelist->zones);
721 pthread_mutex_lock(&engine->zonelist->zl_lock);
723 node = ldns_rbtree_first(engine->zonelist->zones);
724 while (node && node != LDNS_RBTREE_NULL) {
730 if (status == ODS_STATUS_OK) {
731 ods_log_assert(zone->
db);
734 if (engine->config->notify_command && !zone->
notify_ns) {
735 set_notify_ns(zone, engine->config->notify_command);
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;
742 ods_log_debug(
"[%s] recovered zone %s", engine_str,
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);
752 result = ODS_STATUS_OK;
755 node = ldns_rbtree_next(node);
758 pthread_mutex_unlock(&engine->zonelist->zl_lock);
768engine_start(
const char* cfgfile,
int cmdline_verbosity,
int daemonize,
int info)
770 ods_status zl_changed = ODS_STATUS_UNCHANGED;
771 ods_status status = ODS_STATUS_OK;
773 engine = engine_create();
775 ods_fatal_exit(
"[%s] create failed", engine_str);
778 engine->daemonize = daemonize;
783 if (status != ODS_STATUS_OK) {
784 ods_log_error(
"[%s] cfgfile %s has errors", engine_str, cfgfile);
790 stacktrace = janitor_backtrace_string();
791 stacktraceptr = strchr(stacktrace,
'\n');
793 *stacktraceptr =
'\0';
794 stacktraceptr = stacktrace;
795 while(*stacktraceptr && isspace(*stacktraceptr))
797 fprintf(stdout,
"Stacktrace check: %s\n",stacktraceptr);
799 fprintf(stdout,
"Configuration:\n");
804 if (!util_check_pidfile(engine->config->pid_filename)) {
808 status = engine_setup();
809 if (status != ODS_STATUS_OK) {
810 ods_log_error(
"[%s] setup failed: %s", engine_str,
811 ods_status2str(status));
816 while (engine->need_to_exit == 0) {
818 pthread_mutex_lock(&engine->zonelist->zl_lock);
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);
826 if (engine->need_to_reload) {
827 ods_log_info(
"[%s] signer reloading", engine_str);
828 engine->need_to_reload = 0;
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);
835 ods_log_error(
"[%s] %s",
"hsm", error);
838 ods_log_error(
"[%s] opening hsm failed (for engine recover)", engine_str);
841 zl_changed = engine_recover(engine);
844 if (zl_changed == ODS_STATUS_OK ||
845 zl_changed == ODS_STATUS_UNCHANGED) {
848 if (hsm_open2(engine->config->repositories, hsm_check_pin) != HSM_OK) {
849 char* error = hsm_get_error(NULL);
851 ods_log_error(
"[%s] %s",
"hsm", error);
854 ods_log_error(
"[%s] opening hsm failed (for engine run)", engine_str);
862 ods_log_info(
"[%s] signer shutdown", engine_str);
863 cmdhandler_stop(engine->cmdhandler);
864 engine_stop_xfrhandler(engine);
865 engine_stop_dnshandler(engine);
868 if (engine && engine->config) {
869 if (engine->config->pid_filename) {
870 (void)unlink(engine->config->pid_filename);
872 if (engine->config->clisock_filename) {
873 (void)unlink(engine->config->clisock_filename);
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]);
903 free(engine->workers);
906 schedule_cleanup(engine->taskq);
907 cmdhandler_cleanup(engine->cmdhandler);
911 pthread_mutex_destroy(&engine->signal_lock);
912 pthread_cond_destroy(&engine->signal_cond);
ods_status adapter_load_config(adapter_type *adapter)
void engine_config_cleanup(engineconfig_type *config)
void engine_config_print(FILE *out, engineconfig_type *config)
ods_status engine_config_check(engineconfig_type *config)
engineconfig_type * engine_config(const char *cfgfile, int cmdline_verbosity)
void dnshandler_signal(dnshandler_type *dnshandler)
dnshandler_type * dnshandler_create(listener_type *interfaces)
ods_status dnshandler_listen(dnshandler_type *dnshandler)
void dnshandler_start(dnshandler_type *dnshandler)
void dnshandler_cleanup(dnshandler_type *dnshandler)
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
#define ODS_SE_NOTIFY_CMD
void edns_init(edns_data_type *data, uint16_t max_length)
#define EDNS_MAX_MESSAGE_LEN
void engine_wakeup_workers(engine_type *engine)
void engine_cleanup(engine_type *engine)
int engine_start(const char *cfgfile, int cmdline_verbosity, int daemonize, int info)
void engine_update_zones(engine_type *engine, ods_status zl_changed)
struct engine_struct engine_type
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
notify_type * notify_create(xfrhandler_type *xfrhandler, zone_type *zone)
void notify_cleanup(notify_type *notify)
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)
netio_handler_type handler
time_t serial_disk_acquired
netio_handler_type handler
pthread_mutex_t zone_lock
adapter_type * adoutbound
ods_status tsig_handler_init()
void tsig_handler_cleanup(void)
void xfrd_set_timer_now(xfrd_type *xfrd)
xfrd_type * xfrd_create(xfrhandler_type *xfrhandler, zone_type *zone)
void xfrd_cleanup(xfrd_type *xfrd, int backup)
void xfrhandler_cleanup(xfrhandler_type *xfrhandler)
void xfrhandler_start(xfrhandler_type *xfrhandler)
xfrhandler_type * xfrhandler_create()
void xfrhandler_signal(xfrhandler_type *xfrhandler)
void zone_cleanup(zone_type *zone)
ods_status zone_recover2(engine_type *engine, zone_type *zone)
struct zone_struct zone_type
zonelist_type * zonelist_create()
void zonelist_del_zone(zonelist_type *zlist, zone_type *zone)
ods_status zonelist_update(zonelist_type *zl, const char *zlfile)
void zonelist_cleanup(zonelist_type *zl)