OpenDNSSEC-signer  1.4.3
engine.c
Go to the documentation of this file.
1 /*
2  * $Id: engine.c 7194 2013-07-23 10:46:46Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "daemon/cfg.h"
36 #include "daemon/engine.h"
37 #include "daemon/signal.h"
38 #include "shared/allocator.h"
39 #include "shared/duration.h"
40 #include "shared/file.h"
41 #include "shared/hsm.h"
42 #include "shared/locks.h"
43 #include "shared/log.h"
44 #include "shared/privdrop.h"
45 #include "shared/status.h"
46 #include "shared/util.h"
47 #include "signer/zonelist.h"
48 #include "wire/tsig.h"
49 
50 #include <errno.h>
51 #include <libhsm.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 
64 static const char* engine_str = "engine";
65 
66 
71 static engine_type*
72 engine_create(void)
73 {
74  engine_type* engine;
75  allocator_type* allocator = allocator_create(malloc, free);
76  if (!allocator) {
77  ods_log_error("[%s] unable to create engine: allocator_create() "
78  "failed", engine_str);
79  return NULL;
80  }
81  engine = (engine_type*) allocator_alloc(allocator, sizeof(engine_type));
82  if (!engine) {
83  ods_log_error("[%s] unable to create engine: allocator_alloc() "
84  "failed", engine_str);
85  allocator_cleanup(allocator);
86  return NULL;
87  }
88  engine->allocator = allocator;
89  engine->config = NULL;
90  engine->workers = NULL;
91  engine->drudgers = NULL;
92  engine->cmdhandler = NULL;
93  engine->cmdhandler_done = 0;
94  engine->dnshandler = NULL;
95  engine->xfrhandler = NULL;
96  engine->pid = -1;
97  engine->uid = -1;
98  engine->gid = -1;
99  engine->daemonize = 0;
100  engine->need_to_exit = 0;
101  engine->need_to_reload = 0;
102  lock_basic_init(&engine->signal_lock);
103  lock_basic_set(&engine->signal_cond);
104  lock_basic_lock(&engine->signal_lock);
105  engine->signal = SIGNAL_INIT;
106  lock_basic_unlock(&engine->signal_lock);
107  engine->zonelist = zonelist_create(engine->allocator);
108  if (!engine->zonelist) {
109  engine_cleanup(engine);
110  return NULL;
111  }
112  engine->taskq = schedule_create(engine->allocator);
113  if (!engine->taskq) {
114  engine_cleanup(engine);
115  return NULL;
116  }
117  engine->signq = fifoq_create(engine->allocator);
118  if (!engine->signq) {
119  engine_cleanup(engine);
120  return NULL;
121  }
122  return engine;
123 }
124 
125 
130 static void*
131 cmdhandler_thread_start(void* arg)
132 {
133  cmdhandler_type* cmd = (cmdhandler_type*) arg;
135  cmdhandler_start(cmd);
136  return NULL;
137 }
138 static void
139 engine_start_cmdhandler(engine_type* engine)
140 {
141  ods_log_assert(engine);
142  ods_log_debug("[%s] start command handler", engine_str);
143  engine->cmdhandler->engine = engine;
145  cmdhandler_thread_start, engine->cmdhandler);
146  return;
147 }
152 static int
153 self_pipe_trick(engine_type* engine)
154 {
155  int sockfd, ret;
156  struct sockaddr_un servaddr;
157  const char* servsock_filename = ODS_SE_SOCKFILE;
158  ods_log_assert(engine);
159  ods_log_assert(engine->cmdhandler);
160  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
161  if (sockfd < 0) {
162  ods_log_error("[%s] unable to connect to command handler: "
163  "socket() failed (%s)", engine_str, strerror(errno));
164  return 1;
165  } else {
166  bzero(&servaddr, sizeof(servaddr));
167  servaddr.sun_family = AF_UNIX;
168  strncpy(servaddr.sun_path, servsock_filename,
169  sizeof(servaddr.sun_path) - 1);
170  ret = connect(sockfd, (const struct sockaddr*) &servaddr,
171  sizeof(servaddr));
172  if (ret != 0) {
173  ods_log_error("[%s] unable to connect to command handler: "
174  "connect() failed (%s)", engine_str, strerror(errno));
175  close(sockfd);
176  return 1;
177  } else {
178  /* self-pipe trick */
179  ods_writen(sockfd, "", 1);
180  close(sockfd);
181  }
182  }
183  return 0;
184 }
189 static void
190 engine_stop_cmdhandler(engine_type* engine)
191 {
192  ods_log_assert(engine);
193  if (!engine->cmdhandler) {
194  return;
195  }
196  ods_log_debug("[%s] stop command handler", engine_str);
197  engine->cmdhandler->need_to_exit = 1;
198  if (self_pipe_trick(engine) == 0) {
199  while (!engine->cmdhandler_done) {
200  ods_log_debug("[%s] waiting for command handler to exit...",
201  engine_str);
202  sleep(1);
203  }
204  } else {
205  ods_log_error("[%s] command handler self pipe trick failed, "
206  "unclean shutdown", engine_str);
207  }
208  return;
209 }
210 
211 
216 static void*
217 dnshandler_thread_start(void* arg)
218 {
219  dnshandler_type* dnshandler = (dnshandler_type*) arg;
220  dnshandler_start(dnshandler);
221  return NULL;
222 }
223 static void
224 engine_start_dnshandler(engine_type* engine)
225 {
226  if (!engine || !engine->dnshandler) {
227  return;
228  }
229  ods_log_debug("[%s] start dnshandler", engine_str);
230  engine->dnshandler->engine = engine;
232  dnshandler_thread_start, engine->dnshandler);
233  return;
234 }
235 static void
236 engine_stop_dnshandler(engine_type* engine)
237 {
238  if (!engine || !engine->dnshandler || !engine->dnshandler->thread_id) {
239  return;
240  }
241  ods_log_debug("[%s] stop dnshandler", engine_str);
242  engine->dnshandler->need_to_exit = 1;
243  dnshandler_signal(engine->dnshandler);
244  ods_log_debug("[%s] join dnshandler", engine_str);
246  engine->dnshandler->engine = NULL;
247  return;
248 }
249 
250 
255 static void*
256 xfrhandler_thread_start(void* arg)
257 {
258  xfrhandler_type* xfrhandler = (xfrhandler_type*) arg;
259  xfrhandler_start(xfrhandler);
260  return NULL;
261 }
262 static void
263 engine_start_xfrhandler(engine_type* engine)
264 {
265  if (!engine || !engine->xfrhandler) {
266  return;
267  }
268  ods_log_debug("[%s] start xfrhandler", engine_str);
269  engine->xfrhandler->engine = engine;
271  xfrhandler_thread_start, engine->xfrhandler);
272  /* This might be the wrong place to mark the xfrhandler started but
273  * if its isn't done here we might try to shutdown and stop it before
274  * it has marked itself started
275  */
276  engine->xfrhandler->started = 1;
277  return;
278 }
279 static void
280 engine_stop_xfrhandler(engine_type* engine)
281 {
282  if (!engine || !engine->xfrhandler) {
283  return;
284  }
285  ods_log_debug("[%s] stop xfrhandler", engine_str);
286  engine->xfrhandler->need_to_exit = 1;
287  xfrhandler_signal(engine->xfrhandler);
288  ods_log_debug("[%s] join xfrhandler", engine_str);
289  if (engine->xfrhandler->started) {
291  engine->xfrhandler->started = 0;
292  }
293  engine->xfrhandler->engine = NULL;
294  return;
295 }
296 
297 
302 static ods_status
303 engine_privdrop(engine_type* engine)
304 {
305  ods_status status = ODS_STATUS_OK;
306  uid_t uid = -1;
307  gid_t gid = -1;
308  ods_log_assert(engine);
309  ods_log_assert(engine->config);
310  ods_log_debug("[%s] drop privileges", engine_str);
311  if (engine->config->username && engine->config->group) {
312  ods_log_verbose("[%s] drop privileges to user %s, group %s",
313  engine_str, engine->config->username, engine->config->group);
314  } else if (engine->config->username) {
315  ods_log_verbose("[%s] drop privileges to user %s", engine_str,
316  engine->config->username);
317  } else if (engine->config->group) {
318  ods_log_verbose("[%s] drop privileges to group %s", engine_str,
319  engine->config->group);
320  }
321  if (engine->config->chroot) {
322  ods_log_verbose("[%s] chroot to %s", engine_str,
323  engine->config->chroot);
324  }
325  status = privdrop(engine->config->username, engine->config->group,
326  engine->config->chroot, &uid, &gid);
327  engine->uid = uid;
328  engine->gid = gid;
329  privclose(engine->config->username, engine->config->group);
330  return status;
331 }
332 
333 
338 static void
339 engine_create_workers(engine_type* engine)
340 {
341  size_t i = 0;
342  ods_log_assert(engine);
343  ods_log_assert(engine->config);
344  ods_log_assert(engine->allocator);
345  engine->workers = (worker_type**) allocator_alloc(engine->allocator,
346  ((size_t)engine->config->num_worker_threads) * sizeof(worker_type*));
347  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
348  engine->workers[i] = worker_create(engine->allocator, i,
349  WORKER_WORKER);
350  }
351  return;
352 }
353 static void
354 engine_create_drudgers(engine_type* engine)
355 {
356  size_t i = 0;
357  ods_log_assert(engine);
358  ods_log_assert(engine->config);
359  ods_log_assert(engine->allocator);
360  engine->drudgers = (worker_type**) allocator_alloc(engine->allocator,
361  ((size_t)engine->config->num_signer_threads) * sizeof(worker_type*));
362  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
363  engine->drudgers[i] = worker_create(engine->allocator, i,
365  }
366  return;
367 }
368 static void*
369 worker_thread_start(void* arg)
370 {
371  worker_type* worker = (worker_type*) arg;
373  worker_start(worker);
374  return NULL;
375 }
376 static void
377 engine_start_workers(engine_type* engine)
378 {
379  size_t i = 0;
380  ods_log_assert(engine);
381  ods_log_assert(engine->config);
382  ods_log_debug("[%s] start workers", engine_str);
383  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
384  engine->workers[i]->need_to_exit = 0;
385  engine->workers[i]->engine = (void*) engine;
386  ods_thread_create(&engine->workers[i]->thread_id, worker_thread_start,
387  engine->workers[i]);
388  }
389  return;
390 }
391 void
393 {
394  size_t i = 0;
395  ods_log_assert(engine);
396  ods_log_assert(engine->config);
397  ods_log_debug("[%s] start drudgers", engine_str);
398  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
399  engine->drudgers[i]->need_to_exit = 0;
400  engine->drudgers[i]->engine = (void*) engine;
401  ods_thread_create(&engine->drudgers[i]->thread_id, worker_thread_start,
402  engine->drudgers[i]);
403  }
404  return;
405 }
406 static void
407 engine_stop_workers(engine_type* engine)
408 {
409  size_t i = 0;
410  ods_log_assert(engine);
411  ods_log_assert(engine->config);
412  ods_log_debug("[%s] stop workers", engine_str);
413  /* tell them to exit and wake up sleepyheads */
414  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
415  engine->workers[i]->need_to_exit = 1;
416  worker_wakeup(engine->workers[i]);
417  }
418  ods_log_debug("[%s] notify workers", engine_str);
419  worker_notify_all(&engine->signq->q_lock, &engine->signq->q_nonfull);
420  /* head count */
421  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
422  ods_log_debug("[%s] join worker %i", engine_str, i+1);
423  ods_thread_join(engine->workers[i]->thread_id);
424  engine->workers[i]->engine = NULL;
425  }
426  return;
427 }
428 void
430 {
431  size_t i = 0;
432  ods_log_assert(engine);
433  ods_log_assert(engine->config);
434  ods_log_debug("[%s] stop drudgers", engine_str);
435  /* tell them to exit and wake up sleepyheads */
436  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
437  engine->drudgers[i]->need_to_exit = 1;
438  }
439  ods_log_debug("[%s] notify drudgers", engine_str);
440  worker_notify_all(&engine->signq->q_lock, &engine->signq->q_threshold);
441  /* head count */
442  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
443  ods_log_debug("[%s] join drudger %i", engine_str, i+1);
444  ods_thread_join(engine->drudgers[i]->thread_id);
445  engine->drudgers[i]->engine = NULL;
446  }
447  return;
448 }
449 
450 
455 void
457 {
458  size_t i = 0;
459  ods_log_assert(engine);
460  ods_log_assert(engine->config);
461  ods_log_debug("[%s] wake up workers", engine_str);
462  /* wake up sleepyheads */
463  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
464  worker_wakeup(engine->workers[i]);
465  }
466  return;
467 }
468 
469 
474 static ods_status
475 engine_setup(engine_type* engine)
476 {
477  ods_status status = ODS_STATUS_OK;
478  struct sigaction action;
479  int result = 0;
480  int sockets[2] = {0,0};
481 
482  ods_log_debug("[%s] setup signer engine", engine_str);
483  if (!engine || !engine->config) {
484  return ODS_STATUS_ASSERT_ERR;
485  }
486  /* set edns */
488 
489  /* create command handler (before chowning socket file) */
490  engine->cmdhandler = cmdhandler_create(engine->allocator,
491  engine->config->clisock_filename);
492  if (!engine->cmdhandler) {
494  }
495  engine->dnshandler = dnshandler_create(engine->allocator,
496  engine->config->interfaces);
497  engine->xfrhandler = xfrhandler_create(engine->allocator);
498  if (!engine->xfrhandler) {
500  }
501  if (engine->dnshandler) {
502  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
504  }
505  engine->xfrhandler->dnshandler.fd = sockets[0];
506  engine->dnshandler->xfrhandler.fd = sockets[1];
507  status = dnshandler_listen(engine->dnshandler);
508  if (status != ODS_STATUS_OK) {
509  ods_log_error("[%s] setup: unable to listen to sockets (%s)",
510  engine_str, ods_status2str(status));
511  }
512  }
513  /* privdrop */
514  engine->uid = privuid(engine->config->username);
515  engine->gid = privgid(engine->config->group);
516  /* TODO: does piddir exists? */
517  /* remove the chown stuff: piddir? */
518  ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
519  ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
520  ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
521  if (engine->config->log_filename && !engine->config->use_syslog) {
522  ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
523  }
524  if (engine->config->working_dir &&
525  chdir(engine->config->working_dir) != 0) {
526  ods_log_error("[%s] setup: unable to chdir to %s (%s)", engine_str,
527  engine->config->working_dir, strerror(errno));
528  return ODS_STATUS_CHDIR_ERR;
529  }
530  if (engine_privdrop(engine) != ODS_STATUS_OK) {
532  }
533  /* daemonize */
534  if (engine->daemonize) {
535  switch ((engine->pid = fork())) {
536  case -1: /* error */
537  ods_log_error("[%s] setup: unable to fork daemon (%s)",
538  engine_str, strerror(errno));
539  return ODS_STATUS_FORK_ERR;
540  case 0: /* child */
541  break;
542  default: /* parent */
543  engine_cleanup(engine);
544  engine = NULL;
545  xmlCleanupParser();
546  xmlCleanupGlobals();
547  xmlCleanupThreads();
548  exit(0);
549  }
550  if (setsid() == -1) {
551  ods_log_error("[%s] setup: unable to setsid daemon (%s)",
552  engine_str, strerror(errno));
553  return ODS_STATUS_SETSID_ERR;
554  }
555  }
556  engine->pid = getpid();
557  ods_log_verbose("[%s] running as pid %lu", engine_str,
558  (unsigned long) engine->pid);
559  /* catch signals */
560  signal_set_engine(engine);
561  action.sa_handler = signal_handler;
562  sigfillset(&action.sa_mask);
563  action.sa_flags = 0;
564  sigaction(SIGTERM, &action, NULL);
565  sigaction(SIGHUP, &action, NULL);
566  sigaction(SIGINT, &action, NULL);
567  sigaction(SIGILL, &action, NULL);
568  sigaction(SIGUSR1, &action, NULL);
569  sigaction(SIGALRM, &action, NULL);
570  sigaction(SIGCHLD, &action, NULL);
571  action.sa_handler = SIG_IGN;
572  sigaction(SIGPIPE, &action, NULL);
573  /* set up hsm */ /* LEAK */
574  result = lhsm_open(engine->config->cfg_filename);
575  if (result != HSM_OK) {
576  return ODS_STATUS_HSM_ERR;
577  }
578  /* create workers/drudgers */
579  engine_create_workers(engine);
580  engine_create_drudgers(engine);
581  /* start cmd/dns/xfr handlers */
582  engine_start_cmdhandler(engine);
583  engine_start_dnshandler(engine);
584  engine_start_xfrhandler(engine);
585  tsig_handler_init(engine->allocator);
586  /* write pidfile */
587  if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
588  hsm_close();
590  }
591  /* setup done */
592  return ODS_STATUS_OK;
593 }
594 
595 
600 static int
601 engine_all_zones_processed(engine_type* engine)
602 {
603  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
604  zone_type* zone = NULL;
605 
606  ods_log_assert(engine);
607  ods_log_assert(engine->zonelist);
608  ods_log_assert(engine->zonelist->zones);
609 
610  node = ldns_rbtree_first(engine->zonelist->zones);
611  while (node && node != LDNS_RBTREE_NULL) {
612  zone = (zone_type*) node->key;
613  ods_log_assert(zone);
614  ods_log_assert(zone->db);
615  if (!zone->db->is_processed) {
616  return 0;
617  }
618  node = ldns_rbtree_next(node);
619  }
620  return 1;
621 }
622 
623 
628 static void
629 engine_run(engine_type* engine, int single_run)
630 {
631  if (!engine) {
632  return;
633  }
634  engine_start_workers(engine);
635  engine_start_drudgers(engine);
636 
637  lock_basic_lock(&engine->signal_lock);
638  engine->signal = SIGNAL_RUN;
639  lock_basic_unlock(&engine->signal_lock);
640 
641  while (!engine->need_to_exit && !engine->need_to_reload) {
642  lock_basic_lock(&engine->signal_lock);
643  engine->signal = signal_capture(engine->signal);
644  switch (engine->signal) {
645  case SIGNAL_RUN:
646  ods_log_assert(1);
647  break;
648  case SIGNAL_RELOAD:
649  engine->need_to_reload = 1;
650  break;
651  case SIGNAL_SHUTDOWN:
652  engine->need_to_exit = 1;
653  break;
654  default:
655  ods_log_warning("[%s] invalid signal %d captured, "
656  "keep running", engine_str, signal);
657  engine->signal = SIGNAL_RUN;
658  break;
659  }
660  lock_basic_unlock(&engine->signal_lock);
661 
662  if (single_run) {
663  engine->need_to_exit = engine_all_zones_processed(engine);
664  }
665  lock_basic_lock(&engine->signal_lock);
666  if (engine->signal == SIGNAL_RUN && !single_run) {
667  ods_log_debug("[%s] taking a break", engine_str);
668  lock_basic_sleep(&engine->signal_cond, &engine->signal_lock, 3600);
669  }
670  lock_basic_unlock(&engine->signal_lock);
671  }
672  ods_log_debug("[%s] signer halted", engine_str);
673  engine_stop_drudgers(engine);
674  engine_stop_workers(engine);
675  (void)lhsm_reopen(engine->config->cfg_filename);
676  return;
677 }
678 
679 
684 static void
685 set_notify_ns(zone_type* zone, const char* cmd)
686 {
687  const char* str = NULL;
688  const char* str2 = NULL;
689  char* token = NULL;
690  ods_log_assert(cmd);
691  ods_log_assert(zone);
692  ods_log_assert(zone->name);
693  ods_log_assert(zone->adoutbound);
694  if (zone->adoutbound->type == ADAPTER_FILE) {
695  str = ods_replace(cmd, "%zonefile", zone->adoutbound->configstr);
696  if (!str) {
697  ods_log_error("[%s] unable to set notify ns: replace zonefile failed",
698  engine_str);
699  }
700  str2 = ods_replace(str, "%zone", zone->name);
701  free((void*)str);
702  } else {
703  str2 = ods_replace(cmd, "%zone", zone->name);
704  }
705  if (str2) {
706  ods_str_trim((char*) str2);
707  str = str2;
708  if (*str) {
709  token = NULL;
710  while ((token = strtok((char*) str, " "))) {
711  if (*token) {
712  ods_str_list_add(&zone->notify_args, token);
713  }
714  str = NULL;
715  }
716  }
717  zone->notify_command = (char*) str2;
718  zone->notify_ns = zone->notify_args[0];
719  ods_log_debug("[%s] set notify ns: %s", engine_str, zone->notify_ns);
720  } else {
721  ods_log_error("[%s] unable to set notify ns: replace zone failed",
722  engine_str);
723  }
724  return;
725 }
726 
727 
732 static int
733 dnsconfig_zone(engine_type* engine, zone_type* zone)
734 {
735  int numdns = 0;
736  ods_log_assert(engine);
737  ods_log_assert(engine->xfrhandler);
738  ods_log_assert(engine->xfrhandler->netio);
739  ods_log_assert(zone);
740  ods_log_assert(zone->adinbound);
741  ods_log_assert(zone->adoutbound);
742  ods_log_assert(zone->name);
743 
744  if (zone->adinbound->type == ADAPTER_DNS) {
745  /* zone transfer handler */
746  if (!zone->xfrd) {
747  ods_log_debug("[%s] add transfer handler for zone %s",
748  engine_str, zone->name);
749  zone->xfrd = xfrd_create((void*) engine->xfrhandler,
750  (void*) zone);
751  ods_log_assert(zone->xfrd);
753  &zone->xfrd->handler);
754  } else if (!zone->xfrd->serial_disk_acquired) {
755  xfrd_set_timer_now(zone->xfrd);
756  }
757  numdns++;
758  } else if (zone->xfrd) {
760  &zone->xfrd->handler);
761  xfrd_cleanup(zone->xfrd);
762  zone->xfrd = NULL;
763  }
764  if (zone->adoutbound->type == ADAPTER_DNS) {
765  /* notify handler */
766  if (!zone->notify) {
767  ods_log_debug("[%s] add notify handler for zone %s",
768  engine_str, zone->name);
769  zone->notify = notify_create((void*) engine->xfrhandler,
770  (void*) zone);
771  ods_log_assert(zone->notify);
773  &zone->notify->handler);
774  }
775  numdns++;
776  } else if (zone->notify) {
778  &zone->notify->handler);
779  notify_cleanup(zone->notify);
780  zone->notify = NULL;
781  }
782  return numdns;
783 }
784 
785 
790 void
792 {
793  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
794  zone_type* zone = NULL;
795  zone_type* delzone = NULL;
796  task_type* task = NULL;
797  ods_status status = ODS_STATUS_OK;
798  unsigned wake_up = 0;
799  int warnings = 0;
800  time_t now = 0;
801 
802  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
803  return;
804  }
805  now = time_now();
806 
807  ods_log_debug("[%s] commit zone list changes", engine_str);
808  lock_basic_lock(&engine->zonelist->zl_lock);
809  node = ldns_rbtree_first(engine->zonelist->zones);
810  while (node && node != LDNS_RBTREE_NULL) {
811  zone = (zone_type*) node->data;
812  task = NULL; /* reset task */
813 
814  if (zone->zl_status == ZONE_ZL_REMOVED) {
815  node = ldns_rbtree_next(node);
816  lock_basic_lock(&zone->zone_lock);
817  delzone = zonelist_del_zone(engine->zonelist, zone);
818  if (delzone) {
820  task = unschedule_task(engine->taskq,
821  (task_type*) zone->task);
823  }
824  task_cleanup(task);
825  task = NULL;
828  &zone->xfrd->handler);
829  zone_cleanup(zone);
830  zone = NULL;
831  continue;
832  } else if (zone->zl_status == ZONE_ZL_ADDED) {
833  lock_basic_lock(&zone->zone_lock);
834  ods_log_assert(!zone->task);
835  /* set notify nameserver command */
836  if (engine->config->notify_command && !zone->notify_ns) {
837  set_notify_ns(zone, engine->config->notify_command);
838  }
839  /* create task */
840  task = task_create(TASK_SIGNCONF, now, zone);
842  if (!task) {
843  ods_log_crit("[%s] unable to create task for zone %s: "
844  "task_create() failed", engine_str, zone->name);
845  node = ldns_rbtree_next(node);
846  continue;
847  }
848  }
849  /* load adapter config */
850  status = adapter_load_config(zone->adinbound);
851  if (status != ODS_STATUS_OK) {
852  ods_log_error("[%s] unable to load config for inbound adapter "
853  "for zone %s: %s", engine_str, zone->name,
854  ods_status2str(status));
855  }
856  status = adapter_load_config(zone->adoutbound);
857  if (status != ODS_STATUS_OK) {
858  ods_log_error("[%s] unable to load config for outbound adapter "
859  "for zone %s: %s", engine_str, zone->name,
860  ods_status2str(status));
861  }
862  /* for dns adapters */
863  warnings += dnsconfig_zone(engine, zone);
864 
865  if (zone->zl_status == ZONE_ZL_ADDED) {
866  ods_log_assert(task);
867  lock_basic_lock(&zone->zone_lock);
868  zone->task = task;
871  status = schedule_task(engine->taskq, task, 0);
873  } else if (zl_changed == ODS_STATUS_OK) {
874  /* always try to update signconf */
875  lock_basic_lock(&zone->zone_lock);
876  status = zone_reschedule_task(zone, engine->taskq, TASK_SIGNCONF);
878  }
879  if (status != ODS_STATUS_OK) {
880  ods_log_crit("[%s] unable to schedule task for zone %s: %s",
881  engine_str, zone->name, ods_status2str(status));
882  } else {
883  wake_up = 1;
884  zone->zl_status = ZONE_ZL_OK;
885  }
886  node = ldns_rbtree_next(node);
887  }
889  if (engine->dnshandler) {
891  (uint8_t*) ODS_SE_NOTIFY_CMD, strlen(ODS_SE_NOTIFY_CMD));
892  } else if (warnings) {
893  ods_log_warning("[%s] no dnshandler/listener configured, but zones "
894  "are configured with dns adapters: notify and zone transfer "
895  "requests will not work properly", engine_str);
896  }
897  if (wake_up) {
898  engine_wakeup_workers(engine);
899  }
900  return;
901 }
902 
903 
908 static ods_status
909 engine_recover(engine_type* engine)
910 {
911  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
912  zone_type* zone = NULL;
913  ods_status status = ODS_STATUS_OK;
915 
916  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
917  ods_log_error("[%s] cannot recover zones: no engine or zonelist",
918  engine_str);
919  return ODS_STATUS_ERR; /* no need to update zones */
920  }
921  ods_log_assert(engine);
922  ods_log_assert(engine->zonelist);
923  ods_log_assert(engine->zonelist->zones);
924 
925  lock_basic_lock(&engine->zonelist->zl_lock);
926  /* [LOCK] zonelist */
927  node = ldns_rbtree_first(engine->zonelist->zones);
928  while (node && node != LDNS_RBTREE_NULL) {
929  zone = (zone_type*) node->data;
930 
932  lock_basic_lock(&zone->zone_lock);
933  status = zone_recover2(zone);
934  if (status == ODS_STATUS_OK) {
935  ods_log_assert(zone->task);
936  ods_log_assert(zone->db);
937  ods_log_assert(zone->signconf);
938  /* notify nameserver */
939  if (engine->config->notify_command && !zone->notify_ns) {
940  set_notify_ns(zone, engine->config->notify_command);
941  }
942  /* schedule task */
944  /* [LOCK] schedule */
945  status = schedule_task(engine->taskq, (task_type*) zone->task, 0);
946  /* [UNLOCK] schedule */
948 
949  if (status != ODS_STATUS_OK) {
950  ods_log_crit("[%s] unable to schedule task for zone %s: %s",
951  engine_str, zone->name, ods_status2str(status));
952  task_cleanup((task_type*) zone->task);
953  zone->task = NULL;
954  result = ODS_STATUS_OK; /* will trigger update zones */
955  } else {
956  ods_log_debug("[%s] recovered zone %s", engine_str,
957  zone->name);
958  /* recovery done */
959  zone->zl_status = ZONE_ZL_OK;
960  }
961  } else {
962  if (status != ODS_STATUS_UNCHANGED) {
963  ods_log_warning("[%s] unable to recover zone %s from backup,"
964  " performing full sign", engine_str, zone->name);
965  }
966  result = ODS_STATUS_OK; /* will trigger update zones */
967  }
969  node = ldns_rbtree_next(node);
970  }
971  /* [UNLOCK] zonelist */
973  return result;
974 }
975 
976 
981 void
982 engine_start(const char* cfgfile, int cmdline_verbosity, int daemonize,
983  int info, int single_run)
984 {
985  engine_type* engine = NULL;
986  int use_syslog = 0;
987  ods_status zl_changed = ODS_STATUS_UNCHANGED;
988  ods_status status = ODS_STATUS_OK;
989  int close_hsm = 0;
990 
991  ods_log_assert(cfgfile);
992  ods_log_init(NULL, use_syslog, cmdline_verbosity);
993  ods_log_verbose("[%s] starting signer", engine_str);
994 
995  /* initialize */
996  xmlInitGlobals();
997  xmlInitParser();
998  xmlInitThreads();
999  engine = engine_create();
1000  if (!engine) {
1001  ods_fatal_exit("[%s] create failed", engine_str);
1002  return;
1003  }
1004  engine->daemonize = daemonize;
1005 
1006  /* config */
1007  engine->config = engine_config(engine->allocator, cfgfile,
1008  cmdline_verbosity);
1009  status = engine_config_check(engine->config);
1010  if (status != ODS_STATUS_OK) {
1011  ods_log_error("[%s] cfgfile %s has errors", engine_str, cfgfile);
1012  goto earlyexit;
1013  }
1014  if (info) {
1015  engine_config_print(stdout, engine->config); /* for debugging */
1016  goto earlyexit;
1017  }
1018  /* check pidfile */
1019  if (!util_check_pidfile(engine->config->pid_filename)) {
1020  exit(1);
1021  }
1022  /* open log */
1023  ods_log_init(engine->config->log_filename, engine->config->use_syslog,
1024  engine->config->verbosity);
1025  /* setup */
1026  tzset(); /* for portability */
1027  status = engine_setup(engine);
1028  if (status != ODS_STATUS_OK) {
1029  ods_log_error("[%s] setup failed: %s", engine_str,
1030  ods_status2str(status));
1031  engine->need_to_exit = 1;
1032  if (status != ODS_STATUS_WRITE_PIDFILE_ERR) {
1033  /* command handler had not yet been started */
1034  engine->cmdhandler_done = 1;
1035  }
1036  } else {
1037  /* setup ok, mark hsm open */
1038  close_hsm = 1;
1039  }
1040 
1041  /* run */
1042  while (engine->need_to_exit == 0) {
1043  /* update zone list */
1044  lock_basic_lock(&engine->zonelist->zl_lock);
1045  zl_changed = zonelist_update(engine->zonelist,
1046  engine->config->zonelist_filename);
1047  engine->zonelist->just_removed = 0;
1048  engine->zonelist->just_added = 0;
1049  engine->zonelist->just_updated = 0;
1050  lock_basic_unlock(&engine->zonelist->zl_lock);
1051  /* start/reload */
1052  if (engine->need_to_reload) {
1053  ods_log_info("[%s] signer reloading", engine_str);
1054  engine->need_to_reload = 0;
1055  } else {
1056  ods_log_info("[%s] signer started (version %s), pid %u",
1057  engine_str, PACKAGE_VERSION, engine->pid);
1058  zl_changed = engine_recover(engine);
1059  }
1060  if (zl_changed == ODS_STATUS_OK ||
1061  zl_changed == ODS_STATUS_UNCHANGED) {
1062  engine_update_zones(engine, zl_changed);
1063  }
1064  engine_run(engine, single_run);
1065  }
1066 
1067  /* shutdown */
1068  ods_log_info("[%s] signer shutdown", engine_str);
1069  if (close_hsm) {
1070  ods_log_verbose("[%s] close hsm", engine_str);
1071  hsm_close();
1072  }
1073  if (!engine->cmdhandler_done) {
1074  engine_stop_xfrhandler(engine);
1075  engine_stop_dnshandler(engine);
1076  engine_stop_cmdhandler(engine);
1077  }
1078 
1079 earlyexit:
1080  if (engine && engine->config) {
1081  if (engine->config->pid_filename) {
1082  (void)unlink(engine->config->pid_filename);
1083  }
1084  if (engine->config->clisock_filename) {
1085  (void)unlink(engine->config->clisock_filename);
1086  }
1087  }
1089  engine_cleanup(engine);
1090  engine = NULL;
1091  ods_log_close();
1092  xmlCleanupParser();
1093  xmlCleanupGlobals();
1094  xmlCleanupThreads();
1095  return;
1096 }
1097 
1098 
1103 void
1105 {
1106  size_t i = 0;
1107  allocator_type* allocator;
1108  cond_basic_type signal_cond;
1109  lock_basic_type signal_lock;
1110  if (!engine) {
1111  return;
1112  }
1113  allocator = engine->allocator;
1114  signal_cond = engine->signal_cond;
1115  signal_lock = engine->signal_lock;
1116  if (engine->workers && engine->config) {
1117  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
1118  worker_cleanup(engine->workers[i]);
1119  }
1120  allocator_deallocate(allocator, (void*) engine->workers);
1121  }
1122  if (engine->drudgers && engine->config) {
1123  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
1124  worker_cleanup(engine->drudgers[i]);
1125  }
1126  allocator_deallocate(allocator, (void*) engine->drudgers);
1127  }
1128  zonelist_cleanup(engine->zonelist);
1129  schedule_cleanup(engine->taskq);
1130  fifoq_cleanup(engine->signq);
1131  cmdhandler_cleanup(engine->cmdhandler);
1132  dnshandler_cleanup(engine->dnshandler);
1133  xfrhandler_cleanup(engine->xfrhandler);
1134  engine_config_cleanup(engine->config);
1135  allocator_deallocate(allocator, (void*) engine);
1136  lock_basic_destroy(&signal_lock);
1137  lock_basic_off(&signal_cond);
1138  allocator_cleanup(allocator);
1139  return;
1140 }
edns_data_type edns
Definition: engine.h:68
void engine_config_cleanup(engineconfig_type *config)
Definition: cfg.c:253
void engine_config_print(FILE *out, engineconfig_type *config)
Definition: cfg.c:159
#define lock_basic_off(cond)
Definition: locks.h:100
int num_signer_threads
Definition: cfg.h:65
void tsig_handler_cleanup(void)
Definition: tsig.c:157
void zone_cleanup(zone_type *zone)
Definition: zone.c:741
#define ODS_SE_NOTIFY_CMD
Definition: dnshandler.h:48
zonelist_type * zonelist
Definition: engine.h:62
gid_t privgid(const char *groupname)
Definition: privdrop.c:114
void engine_wakeup_workers(engine_type *engine)
Definition: engine.c:456
void ods_thread_blocksigs(void)
Definition: locks.c:150
const char * cfg_filename
Definition: cfg.h:53
#define ods_thread_join(thr)
Definition: locks.h:106
unsigned need_to_exit
Definition: worker.h:67
void engine_stop_drudgers(engine_type *engine)
Definition: engine.c:429
void privclose(const char *username, const char *groupname)
Definition: privdrop.c:314
void ods_log_debug(const char *format,...)
Definition: log.c:272
int just_updated
Definition: zonelist.h:55
notify_type * notify_create(void *xfrhandler, void *zone)
Definition: notify.c:95
#define lock_basic_destroy(lock)
Definition: locks.h:92
ods_status dnshandler_listen(dnshandler_type *dnshandler)
Definition: dnshandler.c:110
cond_basic_type signal_cond
Definition: engine.h:80
cond_basic_type q_threshold
Definition: fifoq.h:68
void * allocator_alloc(allocator_type *allocator, size_t size)
Definition: allocator.c:68
char * notify_command
Definition: zone.h:74
const char * zonelist_filename
Definition: cfg.h:54
void xfrhandler_cleanup(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:216
void engine_update_zones(engine_type *engine, ods_status zl_changed)
Definition: engine.c:791
const char * configstr
Definition: adapter.h:62
cmdhandler_type * cmdhandler_create(allocator_type *allocator, const char *filename)
Definition: cmdhandler.c:823
netio_type * netio
Definition: xfrhandler.h:60
lock_basic_type q_lock
Definition: fifoq.h:67
void ods_fatal_exit(const char *format,...)
Definition: log.c:384
sig_atomic_t signal
Definition: engine.h:79
ods_status adapter_load_config(adapter_type *adapter)
Definition: adapter.c:116
unsigned need_to_exit
Definition: xfrhandler.h:71
ods_status zone_recover2(zone_type *zone)
Definition: zone.c:779
void * engine
Definition: worker.h:55
ods_status schedule_task(schedule_type *schedule, task_type *task, int log)
Definition: schedule.c:148
void signal_set_engine(void *engine)
Definition: signal.c:53
void ods_log_info(const char *format,...)
Definition: log.c:304
const char * group
Definition: cfg.h:61
allocator_type * allocator
Definition: engine.h:58
ldns_rbtree_t * zones
Definition: zonelist.h:52
enum ods_enum_status ods_status
Definition: status.h:91
void worker_start(worker_type *worker)
Definition: worker.c:760
lock_basic_type zone_lock
Definition: zone.h:97
ods_thread_type thread_id
Definition: cmdhandler.h:50
void ods_log_error(const char *format,...)
Definition: log.c:336
const char * ods_status2str(ods_status status)
Definition: status.c:112
adapter_mode type
Definition: adapter.h:60
zone_zl_status zl_status
Definition: zone.h:81
int just_removed
Definition: zonelist.h:56
ods_status tsig_handler_init(allocator_type *allocator)
Definition: tsig.c:135
void cmdhandler_start(cmdhandler_type *cmdhandler)
Definition: cmdhandler.c:905
void worker_cleanup(worker_type *worker)
Definition: worker.c:898
void ods_str_list_add(char ***list, char *str)
Definition: file.c:577
netio_handler_type dnshandler
Definition: xfrhandler.h:69
void engine_start_drudgers(engine_type *engine)
Definition: engine.c:392
#define lock_basic_set(cond)
Definition: locks.h:96
void notify_cleanup(notify_type *notify)
Definition: notify.c:582
adapter_type * adoutbound
Definition: zone.h:84
uid_t privuid(const char *username)
Definition: privdrop.c:71
#define SIGNAL_RELOAD
Definition: signal.h:43
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:60
void fifoq_cleanup(fifoq_type *q)
Definition: fifoq.c:158
void ods_log_crit(const char *format,...)
Definition: log.c:352
const char * log_filename
Definition: cfg.h:55
lock_basic_type signal_lock
Definition: engine.h:81
const char * clisock_filename
Definition: cfg.h:58
engineconfig_type * engine_config(allocator_type *allocator, const char *cfgfile, int cmdline_verbosity)
Definition: cfg.c:54
sig_atomic_t signal_capture(sig_atomic_t dflsig)
Definition: signal.c:102
#define lock_basic_lock(lock)
Definition: locks.h:93
void ods_str_trim(char *str)
Definition: file.c:538
zone_type * zonelist_del_zone(zonelist_type *zlist, zone_type *zone)
Definition: zonelist.c:244
engineconfig_type * config
Definition: engine.h:59
namedb_type * db
Definition: zone.h:88
int util_write_pidfile(const char *pidfile, pid_t pid)
Definition: util.c:335
int num_worker_threads
Definition: cfg.h:64
void dnshandler_signal(dnshandler_type *dnshandler)
Definition: dnshandler.c:235
allocator_type * allocator_create(void *(*allocator)(size_t size), void(*deallocator)(void *))
Definition: allocator.c:49
#define lock_basic_sleep(cond, lock, sleep)
Definition: locks.h:97
void xfrhandler_start(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:120
worker_type ** workers
Definition: engine.h:60
unsigned need_to_exit
Definition: dnshandler.h:61
void engine_start(const char *cfgfile, int cmdline_verbosity, int daemonize, int info, int single_run)
Definition: engine.c:982
int lock_basic_type
Definition: locks.h:90
unsigned is_processed
Definition: namedb.h:58
void worker_notify_all(lock_basic_type *lock, cond_basic_type *condition)
Definition: worker.c:884
const char * notify_command
Definition: cfg.h:57
int util_check_pidfile(const char *pidfile)
Definition: util.c:285
worker_type ** drudgers
Definition: engine.h:61
signconf_type * signconf
Definition: zone.h:86
int lhsm_reopen(const char *filename)
Definition: hsm.c:71
gid_t gid
Definition: engine.h:73
adapter_type * adinbound
Definition: zone.h:83
ssize_t ods_writen(int fd, const void *vptr, size_t n)
Definition: file.c:262
void task_cleanup(task_type *task)
Definition: task.c:277
void worker_wakeup(worker_type *worker)
Definition: worker.c:823
fifoq_type * fifoq_create(allocator_type *allocator)
Definition: fifoq.c:48
char ** notify_args
Definition: zone.h:76
void xfrhandler_signal(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:176
task_type * unschedule_task(schedule_type *schedule, task_type *task)
Definition: schedule.c:193
#define EDNS_MAX_MESSAGE_LEN
Definition: edns.h:49
pid_t pid
Definition: engine.h:71
cmdhandler_type * cmdhandler
Definition: engine.h:65
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:86
xfrhandler_type * xfrhandler_create(allocator_type *allocator)
Definition: xfrhandler.c:54
void xfrd_cleanup(xfrd_type *xfrd)
Definition: xfrd.c:1793
void ods_log_close(void)
Definition: log.c:138
ods_status zone_reschedule_task(zone_type *zone, schedule_type *taskq, task_id what)
Definition: zone.c:189
ods_status privdrop(const char *username, const char *groupname, const char *newroot, uid_t *puid, gid_t *pgid)
Definition: privdrop.c:157
const char * notify_ns
Definition: zone.h:75
netio_handler_type xfrhandler
Definition: dnshandler.h:60
void ods_chown(const char *file, uid_t uid, gid_t gid, int getdir)
Definition: file.c:502
const char * working_dir
Definition: cfg.h:59
int use_syslog
Definition: cfg.h:63
void ods_log_verbose(const char *format,...)
Definition: log.c:288
ods_status engine_config_check(engineconfig_type *config)
Definition: cfg.c:123
dnshandler_type * dnshandler_create(allocator_type *allocator, listener_type *interfaces)
Definition: dnshandler.c:53
#define lock_basic_init(lock)
Definition: locks.h:91
void xfrd_set_timer_now(xfrd_type *xfrd)
Definition: xfrd.c:241
const char * username
Definition: cfg.h:60
void allocator_cleanup(allocator_type *allocator)
Definition: allocator.c:153
void edns_init(edns_data_type *data, uint16_t max_length)
Definition: edns.c:75
listener_type * interfaces
Definition: cfg.h:52
const char * name
Definition: zone.h:78
schedule_type * taskq
Definition: engine.h:63
void zonelist_cleanup(zonelist_type *zl)
Definition: zonelist.c:448
worker_type * worker_create(allocator_type *allocator, int num, worker_id type)
Definition: worker.c:74
unsigned started
Definition: xfrhandler.h:72
void engine_cleanup(engine_type *engine)
Definition: engine.c:1104
void allocator_deallocate(allocator_type *allocator, void *data)
Definition: allocator.c:137
void schedule_cleanup(schedule_type *schedule)
Definition: schedule.c:359
int daemonize
Definition: engine.h:75
#define SIGNAL_RUN
Definition: signal.h:41
ods_status zonelist_update(zonelist_type *zl, const char *zlfile)
Definition: zonelist.c:352
lock_basic_type schedule_lock
Definition: schedule.h:65
int need_to_exit
Definition: engine.h:76
void signal_handler(sig_atomic_t sig)
Definition: signal.c:65
notify_type * notify
Definition: zone.h:92
void * task
Definition: zone.h:94
ods_thread_type thread_id
Definition: dnshandler.h:54
zonelist_type * zonelist_create(allocator_type *allocator)
Definition: zonelist.c:77
fifoq_type * signq
Definition: engine.h:64
cond_basic_type q_nonfull
Definition: fifoq.h:69
void dnshandler_start(dnshandler_type *dnshandler)
Definition: dnshandler.c:129
netio_handler_type handler
Definition: notify.h:63
#define ods_log_assert(x)
Definition: log.h:156
#define ods_thread_create(thr, func, arg)
Definition: locks.h:103
netio_handler_type handler
Definition: xfrd.h:119
void ods_log_init(const char *filename, int use_syslog, int verbosity)
Definition: log.c:83
ods_thread_type thread_id
Definition: worker.h:54
#define SIGNAL_SHUTDOWN
Definition: signal.h:44
int need_to_reload
Definition: engine.h:77
xfrd_type * xfrd_create(void *xfrhandler, void *zone)
Definition: xfrd.c:97
xfrd_type * xfrd
Definition: zone.h:91
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
Definition: dnshandler.c:249
schedule_type * schedule_create(allocator_type *allocator)
Definition: schedule.c:50
const char * pid_filename
Definition: cfg.h:56
const char * chroot
Definition: cfg.h:62
#define lock_basic_unlock(lock)
Definition: locks.h:94
const char * ods_replace(const char *str, const char *oldstr, const char *newstr)
Definition: file.c:371
void ods_log_warning(const char *format,...)
Definition: log.c:320
void cmdhandler_cleanup(cmdhandler_type *cmdhandler)
Definition: cmdhandler.c:972
time_t serial_disk_acquired
Definition: xfrd.h:114
lock_basic_type zl_lock
Definition: zonelist.h:57
ods_thread_type thread_id
Definition: xfrhandler.h:54
int cmdhandler_done
Definition: engine.h:69
task_type * task_create(task_id what, time_t when, void *zone)
Definition: task.c:50
time_t time_now(void)
Definition: duration.c:515
#define SIGNAL_INIT
Definition: signal.h:42
dnshandler_type * dnshandler
Definition: engine.h:66
int lhsm_open(const char *filename)
Definition: hsm.c:46
uid_t uid
Definition: engine.h:72
xfrhandler_type * xfrhandler
Definition: engine.h:67
void dnshandler_cleanup(dnshandler_type *dnshandler)
Definition: dnshandler.c:296