00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #include "config.h"
00035 #include "daemon/cfg.h"
00036 #include "daemon/cmdhandler.h"
00037 #include "daemon/engine.h"
00038 #include "daemon/signal.h"
00039 #include "daemon/worker.h"
00040 #include "scheduler/schedule.h"
00041 #include "scheduler/task.h"
00042 #include "shared/allocator.h"
00043 #include "shared/file.h"
00044 #include "shared/locks.h"
00045 #include "shared/log.h"
00046 #include "shared/privdrop.h"
00047 #include "shared/status.h"
00048 #include "shared/util.h"
00049 #include "signer/zone.h"
00050 #include "signer/zonelist.h"
00051 #include "tools/zone_fetcher.h"
00052
00053 #include <errno.h>
00054 #include <libhsm.h>
00055 #include <libxml/parser.h>
00056 #include <signal.h>
00057 #include <stdio.h>
00058 #include <stdlib.h>
00059 #include <string.h>
00060 #include <strings.h>
00061 #include <sys/socket.h>
00062 #include <sys/types.h>
00063 #include <sys/un.h>
00064 #include <time.h>
00065 #include <unistd.h>
00066
00067 static const char* engine_str = "engine";
00068
00069
00074 static engine_type*
00075 engine_create(void)
00076 {
00077 engine_type* engine;
00078 allocator_type* allocator = allocator_create(malloc, free);
00079 if (!allocator) {
00080 return NULL;
00081 }
00082 engine = (engine_type*) allocator_alloc(allocator, sizeof(engine_type));
00083 if (!engine) {
00084 allocator_cleanup(allocator);
00085 return NULL;
00086 }
00087 engine->allocator = allocator;
00088 engine->config = NULL;
00089 engine->workers = NULL;
00090 engine->drudgers = NULL;
00091 engine->cmdhandler = NULL;
00092 engine->cmdhandler_done = 0;
00093 engine->pid = -1;
00094 engine->zfpid = -1;
00095 engine->uid = -1;
00096 engine->gid = -1;
00097 engine->daemonize = 0;
00098 engine->need_to_exit = 0;
00099 engine->need_to_reload = 0;
00100
00101 lock_basic_init(&engine->signal_lock);
00102 lock_basic_set(&engine->signal_cond);
00103 lock_basic_lock(&engine->signal_lock);
00104 engine->signal = SIGNAL_INIT;
00105 lock_basic_unlock(&engine->signal_lock);
00106
00107 engine->zonelist = zonelist_create(engine->allocator);
00108 if (!engine->zonelist) {
00109 engine_cleanup(engine);
00110 return NULL;
00111 }
00112 engine->taskq = schedule_create(engine->allocator);
00113 if (!engine->taskq) {
00114 engine_cleanup(engine);
00115 return NULL;
00116 }
00117 engine->signq = fifoq_create(engine->allocator);
00118 if (!engine->signq) {
00119 engine_cleanup(engine);
00120 return NULL;
00121 }
00122 return engine;
00123 }
00124
00125
00130 static void*
00131 cmdhandler_thread_start(void* arg)
00132 {
00133 cmdhandler_type* cmd = (cmdhandler_type*) arg;
00134 ods_thread_blocksigs();
00135 cmdhandler_start(cmd);
00136 return NULL;
00137 }
00138 static void
00139 engine_start_cmdhandler(engine_type* engine)
00140 {
00141 ods_log_assert(engine);
00142 ods_log_debug("[%s] start command handler", engine_str);
00143 engine->cmdhandler->engine = engine;
00144 ods_thread_create(&engine->cmdhandler->thread_id,
00145 cmdhandler_thread_start, engine->cmdhandler);
00146 return;
00147 }
00152 static int
00153 self_pipe_trick(engine_type* engine)
00154 {
00155 int sockfd, ret;
00156 struct sockaddr_un servaddr;
00157 const char* servsock_filename = ODS_SE_SOCKFILE;
00158
00159 ods_log_assert(engine);
00160 ods_log_assert(engine->cmdhandler);
00161
00162 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
00163 if (sockfd <= 0) {
00164 ods_log_error("[%s] cannot connect to command handler: "
00165 "socket() failed: %s\n", engine_str, strerror(errno));
00166 return 1;
00167 } else {
00168 bzero(&servaddr, sizeof(servaddr));
00169 servaddr.sun_family = AF_UNIX;
00170 strncpy(servaddr.sun_path, servsock_filename,
00171 sizeof(servaddr.sun_path) - 1);
00172
00173 ret = connect(sockfd, (const struct sockaddr*) &servaddr,
00174 sizeof(servaddr));
00175 if (ret != 0) {
00176 ods_log_error("[%s] cannot connect to command handler: "
00177 "connect() failed: %s\n", engine_str, strerror(errno));
00178 close(sockfd);
00179 return 1;
00180 } else {
00181
00182 ods_writen(sockfd, "", 1);
00183 close(sockfd);
00184 }
00185 }
00186 return 0;
00187 }
00192 static void
00193 engine_stop_cmdhandler(engine_type* engine)
00194 {
00195 ods_log_assert(engine);
00196 if (!engine->cmdhandler) {
00197 return;
00198 }
00199 ods_log_debug("[%s] stop command handler", engine_str);
00200 engine->cmdhandler->need_to_exit = 1;
00201 if (self_pipe_trick(engine) == 0) {
00202 while (!engine->cmdhandler_done) {
00203 ods_log_debug("[%s] waiting for command handler to exit...",
00204 engine_str);
00205 sleep(1);
00206 }
00207 } else {
00208 ods_log_error("[%s] command handler self pipe trick failed, "
00209 "unclean shutdown", engine_str);
00210 }
00211 return;
00212 }
00213
00214
00219 static ods_status
00220 engine_privdrop(engine_type* engine)
00221 {
00222 ods_status status = ODS_STATUS_OK;
00223 uid_t uid = -1;
00224 gid_t gid = -1;
00225
00226 ods_log_assert(engine);
00227 ods_log_assert(engine->config);
00228 ods_log_debug("[%s] drop privileges", engine_str);
00229
00230 if (engine->config->username && engine->config->group) {
00231 ods_log_verbose("[%s] drop privileges to user %s, group %s",
00232 engine_str, engine->config->username, engine->config->group);
00233 } else if (engine->config->username) {
00234 ods_log_verbose("[%s] drop privileges to user %s", engine_str,
00235 engine->config->username);
00236 } else if (engine->config->group) {
00237 ods_log_verbose("[%s] drop privileges to group %s", engine_str,
00238 engine->config->group);
00239 }
00240 if (engine->config->chroot) {
00241 ods_log_verbose("[%s] chroot to %s", engine_str,
00242 engine->config->chroot);
00243 }
00244 status = privdrop(engine->config->username, engine->config->group,
00245 engine->config->chroot, &uid, &gid);
00246 engine->uid = uid;
00247 engine->gid = gid;
00248 privclose(engine->config->username, engine->config->group);
00249 return status;
00250 }
00251
00252
00257 static void
00258 engine_create_workers(engine_type* engine)
00259 {
00260 size_t i = 0;
00261 ods_log_assert(engine);
00262 ods_log_assert(engine->config);
00263 ods_log_assert(engine->allocator);
00264 engine->workers = (worker_type**) allocator_alloc(engine->allocator,
00265 ((size_t)engine->config->num_worker_threads) * sizeof(worker_type*));
00266 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
00267 engine->workers[i] = worker_create(engine->allocator, i,
00268 WORKER_WORKER);
00269 }
00270 return;
00271 }
00272 static void
00273 engine_create_drudgers(engine_type* engine)
00274 {
00275 size_t i = 0;
00276 ods_log_assert(engine);
00277 ods_log_assert(engine->config);
00278 ods_log_assert(engine->allocator);
00279 engine->drudgers = (worker_type**) allocator_alloc(engine->allocator,
00280 ((size_t)engine->config->num_signer_threads) * sizeof(worker_type*));
00281 for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
00282 engine->drudgers[i] = worker_create(engine->allocator, i,
00283 WORKER_DRUDGER);
00284 }
00285 return;
00286 }
00287 static void*
00288 worker_thread_start(void* arg)
00289 {
00290 worker_type* worker = (worker_type*) arg;
00291 ods_thread_blocksigs();
00292 worker_start(worker);
00293 return NULL;
00294 }
00295 static void
00296 engine_start_workers(engine_type* engine)
00297 {
00298 size_t i = 0;
00299
00300 ods_log_assert(engine);
00301 ods_log_assert(engine->config);
00302 ods_log_debug("[%s] start workers", engine_str);
00303 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
00304 engine->workers[i]->need_to_exit = 0;
00305 engine->workers[i]->engine = (struct engine_struct*) engine;
00306 ods_thread_create(&engine->workers[i]->thread_id, worker_thread_start,
00307 engine->workers[i]);
00308 }
00309 return;
00310 }
00311 static void
00312 engine_start_drudgers(engine_type* engine)
00313 {
00314 size_t i = 0;
00315
00316 ods_log_assert(engine);
00317 ods_log_assert(engine->config);
00318 ods_log_debug("[%s] start drudgers", engine_str);
00319 for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
00320 engine->drudgers[i]->need_to_exit = 0;
00321 engine->drudgers[i]->engine = (struct engine_struct*) engine;
00322 ods_thread_create(&engine->drudgers[i]->thread_id, worker_thread_start,
00323 engine->drudgers[i]);
00324 }
00325 return;
00326 }
00327 static void
00328 engine_stop_workers(engine_type* engine)
00329 {
00330 size_t i = 0;
00331
00332 ods_log_assert(engine);
00333 ods_log_assert(engine->config);
00334 ods_log_debug("[%s] stop workers", engine_str);
00335
00336 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
00337 engine->workers[i]->need_to_exit = 1;
00338 worker_wakeup(engine->workers[i]);
00339 }
00340
00341 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
00342 ods_log_debug("[%s] join worker %i", engine_str, i+1);
00343 ods_thread_join(engine->workers[i]->thread_id);
00344 engine->workers[i]->engine = NULL;
00345 }
00346 return;
00347 }
00348 static void
00349 engine_stop_drudgers(engine_type* engine)
00350 {
00351 size_t i = 0;
00352
00353 ods_log_assert(engine);
00354 ods_log_assert(engine->config);
00355 ods_log_debug("[%s] stop drudgers", engine_str);
00356
00357 for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
00358 engine->drudgers[i]->need_to_exit = 1;
00359 }
00360 worker_notify_all(&engine->signq->q_lock, &engine->signq->q_threshold);
00361
00362
00363 for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
00364 ods_log_debug("[%s] join drudger %i", engine_str, i+1);
00365 ods_thread_join(engine->drudgers[i]->thread_id);
00366 engine->drudgers[i]->engine = NULL;
00367 }
00368 return;
00369 }
00370
00371
00376 void
00377 engine_wakeup_workers(engine_type* engine)
00378 {
00379 size_t i = 0;
00380
00381 ods_log_assert(engine);
00382 ods_log_assert(engine->config);
00383 ods_log_debug("[%s] wake up workers", engine_str);
00384
00385 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
00386 worker_wakeup(engine->workers[i]);
00387 }
00388 return;
00389 }
00390
00391
00396 static int
00397 start_zonefetcher(engine_type* engine)
00398 {
00399 pid_t zfpid = 0;
00400 int result = 0;
00401 char* zf_filename = NULL;
00402 char* zl_filename = NULL;
00403 char* log_filename = NULL;
00404 char* grp = NULL;
00405 char* usr = NULL;
00406 char* chrt = NULL;
00407 int use_syslog = 0;
00408 int verbosity = 0;
00409
00410 ods_log_assert(engine);
00411 ods_log_assert(engine->config);
00412
00413 if (!engine->config->zonefetch_filename) {
00414
00415 return 0;
00416 }
00417
00418 switch ((zfpid = fork())) {
00419 case -1:
00420 ods_log_error("failed to fork zone fetcher: %s",
00421 strerror(errno));
00422 return 1;
00423 case 0:
00424 break;
00425 default:
00426 engine->zfpid = zfpid;
00427 return 0;
00428 }
00429
00430 if (setsid() == -1) {
00431 ods_log_error("failed to setsid zone fetcher: %s",
00432 strerror(errno));
00433 return 1;
00434 }
00435
00436 ods_log_verbose("zone fetcher running as pid %lu",
00437 (unsigned long) getpid());
00438
00439 if (engine->config->zonefetch_filename) {
00440 zf_filename = strdup(engine->config->zonefetch_filename);
00441 }
00442 if (engine->config->zonelist_filename) {
00443 zl_filename = strdup(engine->config->zonelist_filename);
00444 }
00445 if (engine->config->group) {
00446 grp = strdup(engine->config->group);
00447 }
00448 if (engine->config->username) {
00449 usr = strdup(engine->config->username);
00450 }
00451 if (engine->config->chroot) {
00452 chrt = strdup(engine->config->chroot);
00453 }
00454 if (engine->config->log_filename) {
00455 log_filename = strdup(engine->config->log_filename);
00456 }
00457 use_syslog = engine->config->use_syslog;
00458 verbosity = engine->config->verbosity;
00459
00460 result = tools_zone_fetcher(zf_filename, zl_filename, grp, usr,
00461 chrt, log_filename, use_syslog, verbosity);
00462
00463 ods_log_verbose("zone fetcher done", result);
00464 if (zf_filename) { free((void*)zf_filename); }
00465 if (zl_filename) { free((void*)zl_filename); }
00466 if (grp) { free((void*)grp); }
00467 if (usr) { free((void*)usr); }
00468 if (chrt) { free((void*)chrt); }
00469 if (log_filename) { free((void*)log_filename); }
00470
00471 engine_cleanup(engine);
00472 engine = NULL;
00473 ods_log_close();
00474 xmlCleanupParser();
00475 xmlCleanupGlobals();
00476 xmlCleanupThreads();
00477 exit(result);
00478
00479 return 0;
00480 }
00481
00482
00487 static void
00488 reload_zonefetcher(engine_type* engine)
00489 {
00490 int result = 0;
00491
00492 ods_log_assert(engine);
00493 ods_log_assert(engine->config);
00494
00495 if (engine->config->zonefetch_filename) {
00496 if (engine->zfpid > 0) {
00497 result = kill(engine->zfpid, SIGHUP);
00498 if (result == -1) {
00499 ods_log_error("cannot reload zone fetcher: %s",
00500 strerror(errno));
00501 } else {
00502 ods_log_info("zone fetcher reloaded (pid=%i)", engine->zfpid);
00503 }
00504 } else {
00505 ods_log_error("cannot reload zone fetcher: process id unknown");
00506 }
00507 }
00508 return;
00509 }
00510
00511
00516 static void
00517 stop_zonefetcher(engine_type* engine)
00518 {
00519 int result = 0;
00520
00521 ods_log_assert(engine);
00522 ods_log_assert(engine->config);
00523
00524 if (engine->config->zonefetch_filename) {
00525 if (engine->zfpid > 0) {
00526 result = kill(engine->zfpid, SIGTERM);
00527 if (result == -1) {
00528 ods_log_error("cannot stop zone fetcher: %s", strerror(errno));
00529 } else {
00530 ods_log_info("zone fetcher stopped (pid=%i)", engine->zfpid);
00531 }
00532 engine->zfpid = -1;
00533 } else {
00534 ods_log_error("cannot stop zone fetcher: process id unknown");
00535 }
00536 }
00537 return;
00538 }
00539
00540
00545 static ods_status
00546 engine_init_adapters(engine_type* engine)
00547 {
00548 size_t i = 0;
00549 ods_status status = ODS_STATUS_OK;
00550
00551 ods_log_assert(engine);
00552 ods_log_assert(engine->config);
00553 ods_log_debug("[%s] initialize adapters", engine_str);
00554 for (i=0; i < (size_t) engine->config->num_adapters; i++) {
00555 status = adapter_init(engine->config->adapters[i]);
00556 if (status != ODS_STATUS_OK) {
00557 return status;
00558 }
00559 }
00560 return status;
00561 }
00562
00563
00568 static ods_status
00569 engine_setup(engine_type* engine)
00570 {
00571 struct sigaction action;
00572 int result = 0;
00573 ods_status status = ODS_STATUS_OK;
00574
00575 ods_log_debug("[%s] signer setup", engine_str);
00576 if (!engine || !engine->config) {
00577 return ODS_STATUS_ASSERT_ERR;
00578 }
00579
00580
00581 engine->cmdhandler = cmdhandler_create(engine->allocator,
00582 engine->config->clisock_filename);
00583 if (!engine->cmdhandler) {
00584 ods_log_error("[%s] create command handler to %s failed",
00585 engine_str, engine->config->clisock_filename);
00586 return ODS_STATUS_CMDHANDLER_ERR;
00587 }
00588
00589
00590 if (start_zonefetcher(engine) != 0) {
00591 ods_log_error("[%s] cannot start zonefetcher", engine_str);
00592 return ODS_STATUS_ERR;
00593 }
00594
00595
00596 status = engine_init_adapters(engine);
00597 if (status != ODS_STATUS_OK) {
00598 ods_log_error("[%s] initializing adapters failed", engine_str);
00599 return status;
00600 }
00601
00602
00603 engine->uid = privuid(engine->config->username);
00604 engine->gid = privgid(engine->config->group);
00605
00606
00607 ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
00608 ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
00609 ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
00610 if (engine->config->log_filename && !engine->config->use_syslog) {
00611 ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
00612 }
00613 if (engine->config->working_dir &&
00614 chdir(engine->config->working_dir) != 0) {
00615 ods_log_error("[%s] chdir to %s failed: %s", engine_str,
00616 engine->config->working_dir, strerror(errno));
00617 return ODS_STATUS_CHDIR_ERR;
00618 }
00619 if (engine_privdrop(engine) != ODS_STATUS_OK) {
00620 ods_log_error("[%s] unable to drop privileges", engine_str);
00621 return ODS_STATUS_PRIVDROP_ERR;
00622 }
00623
00624
00625 if (engine->daemonize) {
00626 switch ((engine->pid = fork())) {
00627 case -1:
00628 ods_log_error("[%s] unable to fork daemon: %s",
00629 engine_str, strerror(errno));
00630 return ODS_STATUS_FORK_ERR;
00631 case 0:
00632 break;
00633 default:
00634 engine_cleanup(engine);
00635 engine = NULL;
00636 xmlCleanupParser();
00637 xmlCleanupGlobals();
00638 xmlCleanupThreads();
00639 exit(0);
00640 }
00641 if (setsid() == -1) {
00642 ods_log_error("[%s] unable to setsid daemon (%s)",
00643 engine_str, strerror(errno));
00644 return ODS_STATUS_SETSID_ERR;
00645 }
00646 }
00647 engine->pid = getpid();
00648 ods_log_verbose("[%s] running as pid %lu", engine_str,
00649 (unsigned long) engine->pid);
00650
00651
00652 signal_set_engine(engine);
00653 action.sa_handler = signal_handler;
00654 sigfillset(&action.sa_mask);
00655 action.sa_flags = 0;
00656 sigaction(SIGHUP, &action, NULL);
00657 sigaction(SIGTERM, &action, NULL);
00658
00659
00660 result = hsm_open(engine->config->cfg_filename, hsm_prompt_pin, NULL);
00661 if (result != HSM_OK) {
00662 char *error = hsm_get_error(NULL);
00663 if (error != NULL) {
00664 ods_log_error("[%s] %s", engine_str, error);
00665 free(error);
00666 }
00667 ods_log_error("[%s] error initializing libhsm (errno %i)",
00668 engine_str, result);
00669 return ODS_STATUS_HSM_ERR;
00670 }
00671
00672
00673 engine_create_workers(engine);
00674 engine_create_drudgers(engine);
00675
00676
00677 engine_start_cmdhandler(engine);
00678
00679
00680 if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
00681 hsm_close();
00682 ods_log_error("[%s] unable to write pid file", engine_str);
00683 return ODS_STATUS_WRITE_PIDFILE_ERR;
00684 }
00685
00686 return ODS_STATUS_OK;
00687 }
00688
00689
00694 static int
00695 engine_all_zones_processed(engine_type* engine)
00696 {
00697 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00698 zone_type* zone = NULL;
00699
00700 ods_log_assert(engine);
00701 ods_log_assert(engine->zonelist);
00702 ods_log_assert(engine->zonelist->zones);
00703
00704 node = ldns_rbtree_first(engine->zonelist->zones);
00705 while (node && node != LDNS_RBTREE_NULL) {
00706 zone = (zone_type*) node->key;
00707 if (!zone->processed) {
00708 return 0;
00709 }
00710 node = ldns_rbtree_next(node);
00711 }
00712 return 1;
00713 }
00714
00715
00720 static void
00721 engine_run(engine_type* engine, int single_run)
00722 {
00723 if (!engine) {
00724 return;
00725 }
00726 ods_log_assert(engine);
00727
00728 engine_start_workers(engine);
00729 engine_start_drudgers(engine);
00730
00731 lock_basic_lock(&engine->signal_lock);
00732
00733 engine->signal = SIGNAL_RUN;
00734
00735 lock_basic_unlock(&engine->signal_lock);
00736
00737 while (!engine->need_to_exit && !engine->need_to_reload) {
00738 lock_basic_lock(&engine->signal_lock);
00739
00740 engine->signal = signal_capture(engine->signal);
00741 switch (engine->signal) {
00742 case SIGNAL_RUN:
00743 ods_log_assert(1);
00744 break;
00745 case SIGNAL_RELOAD:
00746 engine->need_to_reload = 1;
00747 break;
00748 case SIGNAL_SHUTDOWN:
00749 engine->need_to_exit = 1;
00750 break;
00751 default:
00752 ods_log_warning("[%s] invalid signal captured: %d, "
00753 "keep running", engine_str, signal);
00754 engine->signal = SIGNAL_RUN;
00755 break;
00756 }
00757
00758 lock_basic_unlock(&engine->signal_lock);
00759
00760 if (single_run) {
00761 engine->need_to_exit = engine_all_zones_processed(engine);
00762 }
00763
00764 lock_basic_lock(&engine->signal_lock);
00765
00766 if (engine->signal == SIGNAL_RUN && !single_run) {
00767 ods_log_debug("[%s] taking a break", engine_str);
00768 lock_basic_sleep(&engine->signal_cond, &engine->signal_lock, 3600);
00769 }
00770
00771 lock_basic_unlock(&engine->signal_lock);
00772 }
00773 ods_log_debug("[%s] signer halted", engine_str);
00774 engine_stop_drudgers(engine);
00775 engine_stop_workers(engine);
00776 return;
00777 }
00778
00779
00784 static void
00785 set_notify_ns(zone_type* zone, const char* cmd)
00786 {
00787 const char* str = NULL;
00788 const char* str2 = NULL;
00789
00790 ods_log_assert(cmd);
00791 ods_log_assert(zone);
00792 ods_log_assert(zone->name);
00793 ods_log_assert(zone->adoutbound);
00794
00795 if (zone->adoutbound->type == ADAPTER_FILE) {
00796 str = ods_replace(cmd, "%zonefile", zone->adoutbound->configstr);
00797 } else {
00798 str = cmd;
00799 }
00800
00801 str2 = ods_replace(str, "%zone", zone->name);
00802 free((void*)str);
00803 zone->notify_ns = (const char*) str2;
00804 ods_log_debug("[%s] set notify ns: %s", engine_str, zone->notify_ns);
00805 return;
00806 }
00807
00808
00813 void
00814 engine_update_zones(engine_type* engine)
00815 {
00816 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00817 zone_type* zone = NULL;
00818 zone_type* delzone = NULL;
00819 task_type* task = NULL;
00820 ods_status status = ODS_STATUS_OK;
00821 int wake_up = 0;
00822 time_t now;
00823
00824 if (!engine || !engine->zonelist || !engine->zonelist->zones) {
00825 ods_log_error("[%s] cannot update zones: no engine or zonelist",
00826 engine_str);
00827 return;
00828 }
00829 ods_log_assert(engine);
00830 ods_log_assert(engine->zonelist);
00831 ods_log_assert(engine->zonelist->zones);
00832
00833 now = time_now();
00834 reload_zonefetcher(engine);
00835
00836 lock_basic_lock(&engine->zonelist->zl_lock);
00837
00838 node = ldns_rbtree_first(engine->zonelist->zones);
00839 while (node && node != LDNS_RBTREE_NULL) {
00840 zone = (zone_type*) node->data;
00841 task = NULL;
00842
00843 if (zone->tobe_removed) {
00844 node = ldns_rbtree_next(node);
00845
00846 lock_basic_lock(&zone->zone_lock);
00847
00848 delzone = zonelist_del_zone(engine->zonelist, zone);
00849 if (delzone) {
00850 lock_basic_lock(&engine->taskq->schedule_lock);
00851
00852 task = unschedule_task(engine->taskq,
00853 (task_type*) zone->task);
00854
00855 lock_basic_unlock(&engine->taskq->schedule_lock);
00856 }
00857 task_cleanup(task);
00858 task = NULL;
00859
00860 lock_basic_unlock(&zone->zone_lock);
00861
00862 zone_cleanup(zone);
00863 zone = NULL;
00864 continue;
00865 } else if (zone->just_added) {
00866
00867 lock_basic_lock(&zone->zone_lock);
00868 ods_log_assert(!zone->task);
00869 zone->just_added = 0;
00870
00871 if (engine->config->notify_command && !zone->notify_ns) {
00872 set_notify_ns(zone, engine->config->notify_command);
00873 }
00874
00875 task = task_create(TASK_SIGNCONF, now, zone->name, zone);
00876 if (!task) {
00877 ods_log_crit("[%s] failed to create task for zone %s",
00878 engine_str, zone->name);
00879 } else {
00880 lock_basic_lock(&engine->taskq->schedule_lock);
00881
00882 status = schedule_task(engine->taskq, task, 0);
00883
00884 lock_basic_unlock(&engine->taskq->schedule_lock);
00885 wake_up = 1;
00886 }
00887
00888 zone->fetch = (engine->config->zonefetch_filename != NULL);
00889 lock_basic_unlock(&zone->zone_lock);
00890 } else if (zone->just_updated) {
00891 lock_basic_lock(&zone->zone_lock);
00892 ods_log_assert(zone->task);
00893 zone->just_updated = 0;
00894
00895 lock_basic_lock(&engine->taskq->schedule_lock);
00896
00897 task = unschedule_task(engine->taskq, (task_type*) zone->task);
00898 if (task != NULL) {
00899 ods_log_debug("[%s] reschedule task for zone %s", engine_str,
00900 zone->name);
00901 if (task->what != TASK_SIGNCONF) {
00902 task->halted = task->what;
00903 task->interrupt = TASK_SIGNCONF;
00904 }
00905 task->what = TASK_SIGNCONF;
00906 task->when = now;
00907 status = schedule_task(engine->taskq, task, 0);
00908 } else {
00909
00910 ods_log_debug("[%s] worker busy with zone %s, will update "
00911 "signconf as soon as possible", engine_str, zone->name);
00912 task = (task_type*) zone->task;
00913 task->interrupt = TASK_SIGNCONF;
00914
00915 }
00916
00917 lock_basic_unlock(&engine->taskq->schedule_lock);
00918 lock_basic_unlock(&zone->zone_lock);
00919
00920 wake_up = 1;
00921 }
00922
00923 zone->task = task;
00924 if (status != ODS_STATUS_OK) {
00925 ods_log_crit("[%s] failed to schedule task for zone %s: %s",
00926 engine_str, zone->name, ods_status2str(status));
00927 task_cleanup(task);
00928 zone->task = NULL;
00929 }
00930 node = ldns_rbtree_next(node);
00931 }
00932
00933 lock_basic_unlock(&engine->zonelist->zl_lock);
00934 if (wake_up) {
00935 engine_wakeup_workers(engine);
00936 }
00937 return;
00938 }
00939
00940
00945 static ods_status
00946 engine_recover(engine_type* engine)
00947 {
00948 ldns_rbnode_t* node = LDNS_RBTREE_NULL;
00949 zone_type* zone = NULL;
00950 ods_status status = ODS_STATUS_OK;
00951 ods_status result = ODS_STATUS_UNCHANGED;
00952
00953 if (!engine || !engine->zonelist || !engine->zonelist->zones) {
00954 ods_log_error("[%s] cannot update zones: no engine or zonelist",
00955 engine_str);
00956 return ODS_STATUS_OK;
00957 }
00958 ods_log_assert(engine);
00959 ods_log_assert(engine->zonelist);
00960 ods_log_assert(engine->zonelist->zones);
00961
00962 lock_basic_lock(&engine->zonelist->zl_lock);
00963
00964 node = ldns_rbtree_first(engine->zonelist->zones);
00965 while (node && node != LDNS_RBTREE_NULL) {
00966 zone = (zone_type*) node->data;
00967
00968 ods_log_assert(zone->just_added);
00969 status = zone_recover(zone);
00970 if (status == ODS_STATUS_OK) {
00971 ods_log_assert(zone->task);
00972 ods_log_assert(zone->zonedata);
00973 ods_log_assert(zone->signconf);
00974
00975 if (engine->config->notify_command && !zone->notify_ns) {
00976 set_notify_ns(zone, engine->config->notify_command);
00977 }
00978
00979 zone->fetch = (engine->config->zonefetch_filename != NULL);
00980
00981 lock_basic_lock(&engine->taskq->schedule_lock);
00982
00983 status = schedule_task(engine->taskq, (task_type*) zone->task, 0);
00984
00985 lock_basic_unlock(&engine->taskq->schedule_lock);
00986
00987 if (status != ODS_STATUS_OK) {
00988 ods_log_crit("[%s] unable to schedule task for zone %s: %s",
00989 engine_str, zone->name, ods_status2str(status));
00990 task_cleanup((task_type*) zone->task);
00991 zone->task = NULL;
00992 result = ODS_STATUS_OK;
00993 } else {
00994 ods_log_verbose("[%s] recovered zone %s", engine_str,
00995 zone->name);
00996
00997 zone->just_added = 0;
00998 }
00999 } else {
01000 if (status != ODS_STATUS_UNCHANGED) {
01001 ods_log_warning("[%s] unable to recover zone %s from backup,"
01002 " performing full sign", engine_str, zone->name);
01003 }
01004 result = ODS_STATUS_OK;
01005 }
01006 node = ldns_rbtree_next(node);
01007 }
01008
01009 lock_basic_unlock(&engine->zonelist->zl_lock);
01010 return result;
01011 }
01012
01013
01018 void
01019 engine_start(const char* cfgfile, int cmdline_verbosity, int daemonize,
01020 int info, int single_run)
01021 {
01022 engine_type* engine = NULL;
01023 int use_syslog = 0;
01024 ods_status zl_changed = ODS_STATUS_UNCHANGED;
01025 ods_status status = ODS_STATUS_OK;
01026 int close_hsm = 0;
01027
01028 ods_log_assert(cfgfile);
01029 ods_log_init(NULL, use_syslog, cmdline_verbosity);
01030 ods_log_verbose("[%s] starting signer", engine_str);
01031
01032
01033 xmlInitGlobals();
01034 xmlInitParser();
01035 xmlInitThreads();
01036 engine = engine_create();
01037 if (!engine) {
01038 ods_fatal_exit("[%s] create failed", engine_str);
01039 return;
01040 }
01041 engine->daemonize = daemonize;
01042
01043
01044 engine->config = engine_config(engine->allocator, cfgfile,
01045 cmdline_verbosity);
01046 status = engine_config_check(engine->config);
01047 if (status != ODS_STATUS_OK) {
01048 ods_log_error("[%s] cfgfile %s has errors", engine_str, cfgfile);
01049 goto earlyexit;
01050 }
01051 if (info) {
01052 engine_config_print(stdout, engine->config);
01053 goto earlyexit;
01054 }
01055
01056
01057 ods_log_init(engine->config->log_filename, engine->config->use_syslog,
01058 engine->config->verbosity);
01059
01060
01061 tzset();
01062 status = engine_setup(engine);
01063 if (status != ODS_STATUS_OK) {
01064 ods_log_error("[%s] setup failed: %s", engine_str,
01065 ods_status2str(status));
01066 engine->need_to_exit = 1;
01067 if (status != ODS_STATUS_WRITE_PIDFILE_ERR) {
01068
01069 engine->cmdhandler_done = 1;
01070 }
01071 } else {
01072
01073 close_hsm = 1;
01074 }
01075
01076
01077 while (engine->need_to_exit == 0) {
01078
01079 lock_basic_lock(&engine->zonelist->zl_lock);
01080
01081 zl_changed = zonelist_update(engine->zonelist,
01082 engine->config->zonelist_filename);
01083 engine->zonelist->just_removed = 0;
01084 engine->zonelist->just_added = 0;
01085 engine->zonelist->just_updated = 0;
01086
01087 lock_basic_unlock(&engine->zonelist->zl_lock);
01088
01089 if (engine->need_to_reload) {
01090 ods_log_info("[%s] signer reloading", engine_str);
01091 engine->need_to_reload = 0;
01092 } else {
01093 ods_log_info("[%s] signer started", engine_str);
01094 zl_changed = engine_recover(engine);
01095 }
01096
01097
01098 if (zl_changed == ODS_STATUS_OK) {
01099 ods_log_debug("[%s] commit zone list changes", engine_str);
01100 engine_update_zones(engine);
01101 ods_log_debug("[%s] signer configurations updated", engine_str);
01102 zl_changed = ODS_STATUS_UNCHANGED;
01103 }
01104
01105 engine_run(engine, single_run);
01106 }
01107
01108
01109 ods_log_info("[%s] signer shutdown", engine_str);
01110 stop_zonefetcher(engine);
01111 if (close_hsm) {
01112 hsm_close();
01113 }
01114 if (engine->cmdhandler != NULL) {
01115 engine_stop_cmdhandler(engine);
01116 }
01117
01118 earlyexit:
01119 if (engine && engine->config) {
01120 if (engine->config->pid_filename) {
01121 (void)unlink(engine->config->pid_filename);
01122 }
01123 if (engine->config->clisock_filename) {
01124 (void)unlink(engine->config->clisock_filename);
01125 }
01126 }
01127 engine_cleanup(engine);
01128 engine = NULL;
01129 ods_log_close();
01130 xmlCleanupParser();
01131 xmlCleanupGlobals();
01132 xmlCleanupThreads();
01133 return;
01134 }
01135
01136
01141 void
01142 engine_cleanup(engine_type* engine)
01143 {
01144 size_t i = 0;
01145 allocator_type* allocator;
01146 cond_basic_type signal_cond;
01147 lock_basic_type signal_lock;
01148
01149 if (!engine) {
01150 return;
01151 }
01152 allocator = engine->allocator;
01153 signal_cond = engine->signal_cond;
01154 signal_lock = engine->signal_lock;
01155
01156 if (engine->workers && engine->config) {
01157 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
01158 worker_cleanup(engine->workers[i]);
01159 }
01160 allocator_deallocate(allocator, (void*) engine->workers);
01161 }
01162 if (engine->drudgers && engine->config) {
01163 for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
01164 worker_cleanup(engine->drudgers[i]);
01165 }
01166 allocator_deallocate(allocator, (void*) engine->drudgers);
01167 }
01168 zonelist_cleanup(engine->zonelist);
01169 schedule_cleanup(engine->taskq);
01170 fifoq_cleanup(engine->signq);
01171 cmdhandler_cleanup(engine->cmdhandler);
01172 engine_config_cleanup(engine->config);
01173 allocator_deallocate(allocator, (void*) engine);
01174
01175 lock_basic_destroy(&signal_lock);
01176 lock_basic_off(&signal_cond);
01177 allocator_cleanup(allocator);
01178 return;
01179 }