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