OpenDNSSEC-signer  1.4.9
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 || engine->cmdhandler_done) {
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 }
207 
208 
213 static void*
214 dnshandler_thread_start(void* arg)
215 {
216  dnshandler_type* dnshandler = (dnshandler_type*) arg;
217  dnshandler_start(dnshandler);
218  return NULL;
219 }
220 static void
221 engine_start_dnshandler(engine_type* engine)
222 {
223  if (!engine || !engine->dnshandler) {
224  return;
225  }
226  ods_log_debug("[%s] start dnshandler", engine_str);
227  engine->dnshandler->engine = engine;
229  dnshandler_thread_start, engine->dnshandler);
230  return;
231 }
232 static void
233 engine_stop_dnshandler(engine_type* engine)
234 {
235  if (!engine || !engine->dnshandler || !engine->dnshandler->thread_id) {
236  return;
237  }
238  ods_log_debug("[%s] stop dnshandler", engine_str);
239  engine->dnshandler->need_to_exit = 1;
240  dnshandler_signal(engine->dnshandler);
241  ods_log_debug("[%s] join dnshandler", engine_str);
243  engine->dnshandler->engine = NULL;
244  return;
245 }
246 
247 
252 static void*
253 xfrhandler_thread_start(void* arg)
254 {
255  xfrhandler_type* xfrhandler = (xfrhandler_type*) arg;
256  xfrhandler_start(xfrhandler);
257  return NULL;
258 }
259 static void
260 engine_start_xfrhandler(engine_type* engine)
261 {
262  if (!engine || !engine->xfrhandler) {
263  return;
264  }
265  ods_log_debug("[%s] start xfrhandler", engine_str);
266  engine->xfrhandler->engine = engine;
268  xfrhandler_thread_start, engine->xfrhandler);
269  /* This might be the wrong place to mark the xfrhandler started but
270  * if its isn't done here we might try to shutdown and stop it before
271  * it has marked itself started
272  */
273  engine->xfrhandler->started = 1;
274  return;
275 }
276 static void
277 engine_stop_xfrhandler(engine_type* engine)
278 {
279  if (!engine || !engine->xfrhandler) {
280  return;
281  }
282  ods_log_debug("[%s] stop xfrhandler", engine_str);
283  engine->xfrhandler->need_to_exit = 1;
284  xfrhandler_signal(engine->xfrhandler);
285  ods_log_debug("[%s] join xfrhandler", engine_str);
286  if (engine->xfrhandler->started) {
288  engine->xfrhandler->started = 0;
289  }
290  engine->xfrhandler->engine = NULL;
291  return;
292 }
293 
294 
299 static ods_status
300 engine_privdrop(engine_type* engine)
301 {
302  ods_status status = ODS_STATUS_OK;
303  uid_t uid = -1;
304  gid_t gid = -1;
305  ods_log_assert(engine);
306  ods_log_assert(engine->config);
307  ods_log_debug("[%s] drop privileges", engine_str);
308  if (engine->config->username && engine->config->group) {
309  ods_log_verbose("[%s] drop privileges to user %s, group %s",
310  engine_str, engine->config->username, engine->config->group);
311  } else if (engine->config->username) {
312  ods_log_verbose("[%s] drop privileges to user %s", engine_str,
313  engine->config->username);
314  } else if (engine->config->group) {
315  ods_log_verbose("[%s] drop privileges to group %s", engine_str,
316  engine->config->group);
317  }
318  if (engine->config->chroot) {
319  ods_log_verbose("[%s] chroot to %s", engine_str,
320  engine->config->chroot);
321  }
322  status = privdrop(engine->config->username, engine->config->group,
323  engine->config->chroot, &uid, &gid);
324  engine->uid = uid;
325  engine->gid = gid;
326  privclose(engine->config->username, engine->config->group);
327  return status;
328 }
329 
330 
335 static void
336 engine_create_workers(engine_type* engine)
337 {
338  size_t i = 0;
339  ods_log_assert(engine);
340  ods_log_assert(engine->config);
341  ods_log_assert(engine->allocator);
342  engine->workers = (worker_type**) allocator_alloc(engine->allocator,
343  ((size_t)engine->config->num_worker_threads) * sizeof(worker_type*));
344  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
345  engine->workers[i] = worker_create(engine->allocator, i,
346  WORKER_WORKER);
347  }
348  return;
349 }
350 static void
351 engine_create_drudgers(engine_type* engine)
352 {
353  size_t i = 0;
354  ods_log_assert(engine);
355  ods_log_assert(engine->config);
356  ods_log_assert(engine->allocator);
357  engine->drudgers = (worker_type**) allocator_alloc(engine->allocator,
358  ((size_t)engine->config->num_signer_threads) * sizeof(worker_type*));
359  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
360  engine->drudgers[i] = worker_create(engine->allocator, i,
362  }
363  return;
364 }
365 static void*
366 worker_thread_start(void* arg)
367 {
368  worker_type* worker = (worker_type*) arg;
370  worker_start(worker);
371  return NULL;
372 }
373 static void
374 engine_start_workers(engine_type* engine)
375 {
376  size_t i = 0;
377  ods_log_assert(engine);
378  ods_log_assert(engine->config);
379  ods_log_debug("[%s] start workers", engine_str);
380  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
381  engine->workers[i]->need_to_exit = 0;
382  engine->workers[i]->engine = (void*) engine;
383  ods_thread_create(&engine->workers[i]->thread_id, worker_thread_start,
384  engine->workers[i]);
385  }
386  return;
387 }
388 void
390 {
391  size_t i = 0;
392  ods_log_assert(engine);
393  ods_log_assert(engine->config);
394  ods_log_debug("[%s] start drudgers", engine_str);
395  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
396  engine->drudgers[i]->need_to_exit = 0;
397  engine->drudgers[i]->engine = (void*) engine;
398  ods_thread_create(&engine->drudgers[i]->thread_id, worker_thread_start,
399  engine->drudgers[i]);
400  }
401  return;
402 }
403 static void
404 engine_stop_workers(engine_type* engine)
405 {
406  size_t i = 0;
407  ods_log_assert(engine);
408  ods_log_assert(engine->config);
409  ods_log_debug("[%s] stop workers", engine_str);
410  /* tell them to exit and wake up sleepyheads */
411  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
412  engine->workers[i]->need_to_exit = 1;
413  worker_wakeup(engine->workers[i]);
414  }
415  ods_log_debug("[%s] notify workers", engine_str);
416  worker_notify_all(&engine->signq->q_lock, &engine->signq->q_nonfull);
417  /* head count */
418  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
419  ods_log_debug("[%s] join worker %i", engine_str, i+1);
420  ods_thread_join(engine->workers[i]->thread_id);
421  engine->workers[i]->engine = NULL;
422  }
423  return;
424 }
425 void
427 {
428  size_t i = 0;
429  ods_log_assert(engine);
430  ods_log_assert(engine->config);
431  ods_log_debug("[%s] stop drudgers", engine_str);
432  /* tell them to exit and wake up sleepyheads */
433  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
434  engine->drudgers[i]->need_to_exit = 1;
435  }
436  ods_log_debug("[%s] notify drudgers", engine_str);
437  worker_notify_all(&engine->signq->q_lock, &engine->signq->q_threshold);
438  /* head count */
439  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
440  ods_log_debug("[%s] join drudger %i", engine_str, i+1);
441  ods_thread_join(engine->drudgers[i]->thread_id);
442  engine->drudgers[i]->engine = NULL;
443  }
444  return;
445 }
446 
447 
452 void
454 {
455  size_t i = 0;
456  ods_log_assert(engine);
457  ods_log_assert(engine->config);
458  ods_log_debug("[%s] wake up workers", engine_str);
459  /* wake up sleepyheads */
460  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
461  worker_wakeup(engine->workers[i]);
462  }
463  return;
464 }
465 
466 
471 static ods_status
472 engine_setup(engine_type* engine)
473 {
474  ods_status status = ODS_STATUS_OK;
475  struct sigaction action;
476  int result = 0;
477  int sockets[2] = {0,0};
478 
479  ods_log_debug("[%s] setup signer engine", engine_str);
480  if (!engine || !engine->config) {
481  return ODS_STATUS_ASSERT_ERR;
482  }
483  /* set edns */
485 
486  /* create command handler (before chowning socket file) */
487  engine->cmdhandler = cmdhandler_create(engine->allocator,
488  engine->config->clisock_filename);
489  if (!engine->cmdhandler) {
491  }
492  engine->dnshandler = dnshandler_create(engine->allocator,
493  engine->config->interfaces);
494  engine->xfrhandler = xfrhandler_create(engine->allocator);
495  if (!engine->xfrhandler) {
497  }
498  if (engine->dnshandler) {
499  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
501  }
502  engine->xfrhandler->dnshandler.fd = sockets[0];
503  engine->dnshandler->xfrhandler.fd = sockets[1];
504  status = dnshandler_listen(engine->dnshandler);
505  if (status != ODS_STATUS_OK) {
506  ods_log_error("[%s] setup: unable to listen to sockets (%s)",
507  engine_str, ods_status2str(status));
508  }
509  }
510  /* privdrop */
511  engine->uid = privuid(engine->config->username);
512  engine->gid = privgid(engine->config->group);
513  /* TODO: does piddir exists? */
514  /* remove the chown stuff: piddir? */
515  ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
516  ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
517  ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
518  if (engine->config->log_filename && !engine->config->use_syslog) {
519  ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
520  }
521  if (engine->config->working_dir &&
522  chdir(engine->config->working_dir) != 0) {
523  ods_log_error("[%s] setup: unable to chdir to %s (%s)", engine_str,
524  engine->config->working_dir, strerror(errno));
525  return ODS_STATUS_CHDIR_ERR;
526  }
527  if (engine_privdrop(engine) != ODS_STATUS_OK) {
529  }
530  /* daemonize */
531  if (engine->daemonize) {
532  switch ((engine->pid = fork())) {
533  case -1: /* error */
534  ods_log_error("[%s] setup: unable to fork daemon (%s)",
535  engine_str, strerror(errno));
536  return ODS_STATUS_FORK_ERR;
537  case 0: /* child */
538  break;
539  default: /* parent */
540  engine_cleanup(engine);
541  engine = NULL;
542  xmlCleanupParser();
543  xmlCleanupGlobals();
544  xmlCleanupThreads();
545  exit(0);
546  }
547  if (setsid() == -1) {
548  ods_log_error("[%s] setup: unable to setsid daemon (%s)",
549  engine_str, strerror(errno));
550  return ODS_STATUS_SETSID_ERR;
551  }
552  }
553  engine->pid = getpid();
554  ods_log_verbose("[%s] running as pid %lu", engine_str,
555  (unsigned long) engine->pid);
556  /* catch signals */
557  signal_set_engine(engine);
558  action.sa_handler = (void (*)(int))signal_handler;
559  sigfillset(&action.sa_mask);
560  action.sa_flags = 0;
561  sigaction(SIGTERM, &action, NULL);
562  sigaction(SIGHUP, &action, NULL);
563  sigaction(SIGINT, &action, NULL);
564  sigaction(SIGILL, &action, NULL);
565  sigaction(SIGUSR1, &action, NULL);
566  sigaction(SIGALRM, &action, NULL);
567  sigaction(SIGCHLD, &action, NULL);
568  action.sa_handler = SIG_IGN;
569  sigaction(SIGPIPE, &action, NULL);
570  /* set up hsm */ /* LEAK */
571  result = lhsm_open(engine->config->cfg_filename);
572  if (result != HSM_OK) {
573  return ODS_STATUS_HSM_ERR;
574  }
575  /* create workers/drudgers */
576  engine_create_workers(engine);
577  engine_create_drudgers(engine);
578  /* start cmd/dns/xfr handlers */
579  engine_start_cmdhandler(engine);
580  engine_start_dnshandler(engine);
581  engine_start_xfrhandler(engine);
582  tsig_handler_init(engine->allocator);
583  /* write pidfile */
584  if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
585  hsm_close();
587  }
588  /* setup done */
589  return ODS_STATUS_OK;
590 }
591 
592 
597 static int
598 engine_all_zones_processed(engine_type* engine)
599 {
600  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
601  zone_type* zone = NULL;
602 
603  ods_log_assert(engine);
604  ods_log_assert(engine->zonelist);
605  ods_log_assert(engine->zonelist->zones);
606 
607  node = ldns_rbtree_first(engine->zonelist->zones);
608  while (node && node != LDNS_RBTREE_NULL) {
609  zone = (zone_type*) node->key;
610  ods_log_assert(zone);
611  ods_log_assert(zone->db);
612  if (!zone->db->is_processed) {
613  return 0;
614  }
615  node = ldns_rbtree_next(node);
616  }
617  return 1;
618 }
619 
620 
625 static void
626 engine_run(engine_type* engine, int single_run)
627 {
628  if (!engine) {
629  return;
630  }
631  engine_start_workers(engine);
632  engine_start_drudgers(engine);
633 
634  lock_basic_lock(&engine->signal_lock);
635  engine->signal = SIGNAL_RUN;
636  lock_basic_unlock(&engine->signal_lock);
637 
638  while (!engine->need_to_exit && !engine->need_to_reload) {
639  lock_basic_lock(&engine->signal_lock);
640  engine->signal = signal_capture(engine->signal);
641  switch (engine->signal) {
642  case SIGNAL_RUN:
643  ods_log_assert(1);
644  break;
645  case SIGNAL_RELOAD:
646  engine->need_to_reload = 1;
647  break;
648  case SIGNAL_SHUTDOWN:
649  engine->need_to_exit = 1;
650  break;
651  default:
652  ods_log_warning("[%s] invalid signal %d captured, "
653  "keep running", engine_str, signal);
654  engine->signal = SIGNAL_RUN;
655  break;
656  }
657  lock_basic_unlock(&engine->signal_lock);
658 
659  if (single_run) {
660  engine->need_to_exit = engine_all_zones_processed(engine);
661  }
662  lock_basic_lock(&engine->signal_lock);
663  if (engine->signal == SIGNAL_RUN && !single_run) {
664  ods_log_debug("[%s] taking a break", engine_str);
665  lock_basic_sleep(&engine->signal_cond, &engine->signal_lock, 3600);
666  }
667  lock_basic_unlock(&engine->signal_lock);
668  }
669  ods_log_debug("[%s] signer halted", engine_str);
670  engine_stop_drudgers(engine);
671  engine_stop_workers(engine);
672  (void)lhsm_reopen(engine->config->cfg_filename);
673  return;
674 }
675 
676 
681 static void
682 set_notify_ns(zone_type* zone, const char* cmd)
683 {
684  const char* str = NULL;
685  const char* str2 = NULL;
686  char* token = NULL;
687  ods_log_assert(cmd);
688  ods_log_assert(zone);
689  ods_log_assert(zone->name);
690  ods_log_assert(zone->adoutbound);
691  if (zone->adoutbound->type == ADAPTER_FILE) {
692  str = ods_replace(cmd, "%zonefile", zone->adoutbound->configstr);
693  if (!str) {
694  ods_log_error("[%s] unable to set notify ns: replace zonefile failed",
695  engine_str);
696  }
697  str2 = ods_replace(str, "%zone", zone->name);
698  free((void*)str);
699  } else {
700  str2 = ods_replace(cmd, "%zone", zone->name);
701  }
702  if (str2) {
703  ods_str_trim((char*) str2);
704  str = str2;
705  if (*str) {
706  token = NULL;
707  while ((token = strtok((char*) str, " "))) {
708  if (*token) {
709  ods_str_list_add(&zone->notify_args, token);
710  }
711  str = NULL;
712  }
713  }
714  zone->notify_command = (char*) str2;
715  zone->notify_ns = zone->notify_args[0];
716  ods_log_debug("[%s] set notify ns: %s", engine_str, zone->notify_ns);
717  } else {
718  ods_log_error("[%s] unable to set notify ns: replace zone failed",
719  engine_str);
720  }
721  return;
722 }
723 
724 
729 static int
730 dnsconfig_zone(engine_type* engine, zone_type* zone)
731 {
732  int numdns = 0;
733  ods_log_assert(engine);
734  ods_log_assert(engine->xfrhandler);
735  ods_log_assert(engine->xfrhandler->netio);
736  ods_log_assert(zone);
737  ods_log_assert(zone->adinbound);
738  ods_log_assert(zone->adoutbound);
739  ods_log_assert(zone->name);
740 
741  if (zone->adinbound->type == ADAPTER_DNS) {
742  /* zone transfer handler */
743  if (!zone->xfrd) {
744  ods_log_debug("[%s] add transfer handler for zone %s",
745  engine_str, zone->name);
746  zone->xfrd = xfrd_create((void*) engine->xfrhandler,
747  (void*) zone);
748  ods_log_assert(zone->xfrd);
750  &zone->xfrd->handler);
751  } else if (!zone->xfrd->serial_disk_acquired) {
752  xfrd_set_timer_now(zone->xfrd);
753  }
754  numdns++;
755  } else if (zone->xfrd) {
757  &zone->xfrd->handler);
758  xfrd_cleanup(zone->xfrd, 0);
759  zone->xfrd = NULL;
760  }
761  if (zone->adoutbound->type == ADAPTER_DNS) {
762  /* notify handler */
763  if (!zone->notify) {
764  ods_log_debug("[%s] add notify handler for zone %s",
765  engine_str, zone->name);
766  zone->notify = notify_create((void*) engine->xfrhandler,
767  (void*) zone);
768  ods_log_assert(zone->notify);
770  &zone->notify->handler);
771  }
772  numdns++;
773  } else if (zone->notify) {
775  &zone->notify->handler);
776  notify_cleanup(zone->notify);
777  zone->notify = NULL;
778  }
779  return numdns;
780 }
781 
782 
787 void
789 {
790  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
791  zone_type* zone = NULL;
792  zone_type* delzone = NULL;
793  task_type* task = NULL;
794  ods_status status = ODS_STATUS_OK;
795  unsigned wake_up = 0;
796  int warnings = 0;
797  time_t now = 0;
798 
799  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
800  return;
801  }
802  now = time_now();
803 
804  ods_log_debug("[%s] commit zone list changes", engine_str);
805  lock_basic_lock(&engine->zonelist->zl_lock);
806  node = ldns_rbtree_first(engine->zonelist->zones);
807  while (node && node != LDNS_RBTREE_NULL) {
808  zone = (zone_type*) node->data;
809  task = NULL; /* reset task */
810 
811  if (zone->zl_status == ZONE_ZL_REMOVED) {
812  node = ldns_rbtree_next(node);
813  lock_basic_lock(&zone->zone_lock);
814  delzone = zonelist_del_zone(engine->zonelist, zone);
815  if (delzone) {
817  task = unschedule_task(engine->taskq,
818  (task_type*) zone->task);
820  }
821  task_cleanup(task);
822  task = NULL;
825  &zone->xfrd->handler);
826  zone_cleanup(zone);
827  zone = NULL;
828  continue;
829  } else if (zone->zl_status == ZONE_ZL_ADDED) {
830  lock_basic_lock(&zone->zone_lock);
831  ods_log_assert(!zone->task);
832  /* set notify nameserver command */
833  if (engine->config->notify_command && !zone->notify_ns) {
834  set_notify_ns(zone, engine->config->notify_command);
835  }
836  /* create task */
837  task = task_create(TASK_SIGNCONF, now, zone);
839  if (!task) {
840  ods_log_crit("[%s] unable to create task for zone %s: "
841  "task_create() failed", engine_str, zone->name);
842  node = ldns_rbtree_next(node);
843  continue;
844  }
845  }
846  /* load adapter config */
847  status = adapter_load_config(zone->adinbound);
848  if (status != ODS_STATUS_OK) {
849  ods_log_error("[%s] unable to load config for inbound adapter "
850  "for zone %s: %s", engine_str, zone->name,
851  ods_status2str(status));
852  }
853  status = adapter_load_config(zone->adoutbound);
854  if (status != ODS_STATUS_OK) {
855  ods_log_error("[%s] unable to load config for outbound adapter "
856  "for zone %s: %s", engine_str, zone->name,
857  ods_status2str(status));
858  }
859  /* for dns adapters */
860  warnings += dnsconfig_zone(engine, zone);
861 
862  if (zone->zl_status == ZONE_ZL_ADDED) {
863  ods_log_assert(task);
864  lock_basic_lock(&zone->zone_lock);
865  zone->task = task;
867  /* TODO: task is reachable from other threads by means of
868  * zone->task. To fix this we need to nest the locks. But
869  * first investigate any possible deadlocks. */
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) {
890  ods_log_debug("[%s] forward notify for all zones", engine_str);
892  (uint8_t*) ODS_SE_NOTIFY_CMD, strlen(ODS_SE_NOTIFY_CMD));
893  } else if (warnings) {
894  ods_log_warning("[%s] no dnshandler/listener configured, but zones "
895  "are configured with dns adapters: notify and zone transfer "
896  "requests will not work properly", engine_str);
897  }
898  if (wake_up) {
899  engine_wakeup_workers(engine);
900  }
901  return;
902 }
903 
904 
909 static ods_status
910 engine_recover(engine_type* engine)
911 {
912  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
913  zone_type* zone = NULL;
914  ods_status status = ODS_STATUS_OK;
916 
917  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
918  ods_log_error("[%s] cannot recover zones: no engine or zonelist",
919  engine_str);
920  return ODS_STATUS_ERR; /* no need to update zones */
921  }
922  ods_log_assert(engine);
923  ods_log_assert(engine->zonelist);
924  ods_log_assert(engine->zonelist->zones);
925 
926  lock_basic_lock(&engine->zonelist->zl_lock);
927  /* [LOCK] zonelist */
928  node = ldns_rbtree_first(engine->zonelist->zones);
929  while (node && node != LDNS_RBTREE_NULL) {
930  zone = (zone_type*) node->data;
931 
933  lock_basic_lock(&zone->zone_lock);
934  status = zone_recover2(zone);
935  if (status == ODS_STATUS_OK) {
936  ods_log_assert(zone->task);
937  ods_log_assert(zone->db);
938  ods_log_assert(zone->signconf);
939  /* notify nameserver */
940  if (engine->config->notify_command && !zone->notify_ns) {
941  set_notify_ns(zone, engine->config->notify_command);
942  }
943  /* schedule task */
945  /* [LOCK] schedule */
946  status = schedule_task(engine->taskq, (task_type*) zone->task, 0);
947  /* [UNLOCK] schedule */
949 
950  if (status != ODS_STATUS_OK) {
951  ods_log_crit("[%s] unable to schedule task for zone %s: %s",
952  engine_str, zone->name, ods_status2str(status));
953  task_cleanup((task_type*) zone->task);
954  zone->task = NULL;
955  result = ODS_STATUS_OK; /* will trigger update zones */
956  } else {
957  ods_log_debug("[%s] recovered zone %s", engine_str,
958  zone->name);
959  /* recovery done */
960  zone->zl_status = ZONE_ZL_OK;
961  }
962  } else {
963  if (status != ODS_STATUS_UNCHANGED) {
964  ods_log_warning("[%s] unable to recover zone %s from backup,"
965  " performing full sign", engine_str, zone->name);
966  }
967  result = ODS_STATUS_OK; /* will trigger update zones */
968  }
970  node = ldns_rbtree_next(node);
971  }
972  /* [UNLOCK] zonelist */
974  return result;
975 }
976 
977 
982 void
983 engine_start(const char* cfgfile, int cmdline_verbosity, int daemonize,
984  int info, int single_run)
985 {
986  engine_type* engine = NULL;
987  int use_syslog = 0;
988  ods_status zl_changed = ODS_STATUS_UNCHANGED;
989  ods_status status = ODS_STATUS_OK;
990  int close_hsm = 0;
991 
992  ods_log_assert(cfgfile);
993  ods_log_init(NULL, use_syslog, cmdline_verbosity);
994  ods_log_verbose("[%s] starting signer", engine_str);
995 
996  /* initialize */
997  xmlInitGlobals();
998  xmlInitParser();
999  xmlInitThreads();
1000  engine = engine_create();
1001  if (!engine) {
1002  ods_fatal_exit("[%s] create failed", engine_str);
1003  return;
1004  }
1005  engine->daemonize = daemonize;
1006 
1007  /* config */
1008  engine->config = engine_config(engine->allocator, cfgfile,
1009  cmdline_verbosity);
1010  status = engine_config_check(engine->config);
1011  if (status != ODS_STATUS_OK) {
1012  ods_log_error("[%s] cfgfile %s has errors", engine_str, cfgfile);
1013  goto earlyexit;
1014  }
1015  if (info) {
1016  engine_config_print(stdout, engine->config); /* for debugging */
1017  goto earlyexit;
1018  }
1019  /* check pidfile */
1020  if (!util_check_pidfile(engine->config->pid_filename)) {
1021  exit(1);
1022  }
1023  /* open log */
1024  ods_log_init(engine->config->log_filename, engine->config->use_syslog,
1025  engine->config->verbosity);
1026  /* setup */
1027  tzset(); /* for portability */
1028  status = engine_setup(engine);
1029  if (status != ODS_STATUS_OK) {
1030  ods_log_error("[%s] setup failed: %s", engine_str,
1031  ods_status2str(status));
1032  engine->need_to_exit = 1;
1033  if (status != ODS_STATUS_WRITE_PIDFILE_ERR) {
1034  /* command handler had not yet been started */
1035  engine->cmdhandler_done = 1;
1036  }
1037  } else {
1038  /* setup ok, mark hsm open */
1039  close_hsm = 1;
1040  }
1041 
1042  /* run */
1043  while (engine->need_to_exit == 0) {
1044  /* update zone list */
1045  lock_basic_lock(&engine->zonelist->zl_lock);
1046  zl_changed = zonelist_update(engine->zonelist,
1047  engine->config->zonelist_filename);
1048  engine->zonelist->just_removed = 0;
1049  engine->zonelist->just_added = 0;
1050  engine->zonelist->just_updated = 0;
1051  lock_basic_unlock(&engine->zonelist->zl_lock);
1052  /* start/reload */
1053  if (engine->need_to_reload) {
1054  ods_log_info("[%s] signer reloading", engine_str);
1055  engine->need_to_reload = 0;
1056  } else {
1057  ods_log_info("[%s] signer started (version %s), pid %u",
1058  engine_str, PACKAGE_VERSION, engine->pid);
1059  zl_changed = engine_recover(engine);
1060  }
1061  if (zl_changed == ODS_STATUS_OK ||
1062  zl_changed == ODS_STATUS_UNCHANGED) {
1063  engine_update_zones(engine, zl_changed);
1064  }
1065  engine_run(engine, single_run);
1066  }
1067 
1068  /* shutdown */
1069  ods_log_info("[%s] signer shutdown", engine_str);
1070  if (close_hsm) {
1071  ods_log_verbose("[%s] close hsm", engine_str);
1072  hsm_close();
1073  }
1074  engine_stop_cmdhandler(engine);
1075  engine_stop_xfrhandler(engine);
1076  engine_stop_dnshandler(engine);
1077 
1078 earlyexit:
1079  if (engine && engine->config) {
1080  if (engine->config->pid_filename) {
1081  (void)unlink(engine->config->pid_filename);
1082  }
1083  if (engine->config->clisock_filename) {
1084  (void)unlink(engine->config->clisock_filename);
1085  }
1086  }
1088  engine_cleanup(engine);
1089  engine = NULL;
1090  ods_log_close();
1091  xmlCleanupParser();
1092  xmlCleanupGlobals();
1093  xmlCleanupThreads();
1094  return;
1095 }
1096 
1097 
1102 void
1104 {
1105  size_t i = 0;
1106  allocator_type* allocator;
1107  cond_basic_type signal_cond;
1108  lock_basic_type signal_lock;
1109  if (!engine) {
1110  return;
1111  }
1112  allocator = engine->allocator;
1113  signal_cond = engine->signal_cond;
1114  signal_lock = engine->signal_lock;
1115  if (engine->workers && engine->config) {
1116  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
1117  worker_cleanup(engine->workers[i]);
1118  }
1119  allocator_deallocate(allocator, (void*) engine->workers);
1120  }
1121  if (engine->drudgers && engine->config) {
1122  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
1123  worker_cleanup(engine->drudgers[i]);
1124  }
1125  allocator_deallocate(allocator, (void*) engine->drudgers);
1126  }
1127  zonelist_cleanup(engine->zonelist);
1128  schedule_cleanup(engine->taskq);
1129  fifoq_cleanup(engine->signq);
1130  cmdhandler_cleanup(engine->cmdhandler);
1131  dnshandler_cleanup(engine->dnshandler);
1132  xfrhandler_cleanup(engine->xfrhandler);
1133  engine_config_cleanup(engine->config);
1134  allocator_deallocate(allocator, (void*) engine);
1135  lock_basic_destroy(&signal_lock);
1136  lock_basic_off(&signal_cond);
1137  allocator_cleanup(allocator);
1138  return;
1139 }
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:101
int num_signer_threads
Definition: cfg.h:63
void tsig_handler_cleanup(void)
Definition: tsig.c:156
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:453
void ods_thread_blocksigs(void)
Definition: locks.c:173
const char * cfg_filename
Definition: cfg.h:51
#define ods_thread_join(thr)
Definition: locks.h:107
unsigned need_to_exit
Definition: worker.h:65
void engine_stop_drudgers(engine_type *engine)
Definition: engine.c:426
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:101
#define lock_basic_destroy(lock)
Definition: locks.h:93
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:216
void engine_update_zones(engine_type *engine, ods_status zl_changed)
Definition: engine.c:788
const char * configstr
Definition: adapter.h:60
cmdhandler_type * cmdhandler_create(allocator_type *allocator, const char *filename)
Definition: cmdhandler.c:881
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:70
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:963
void worker_cleanup(worker_type *worker)
Definition: worker.c:898
void ods_str_list_add(char ***list, char *str)
Definition: file.c:595
netio_handler_type dnshandler
Definition: xfrhandler.h:68
void engine_start_drudgers(engine_type *engine)
Definition: engine.c:389
#define lock_basic_set(cond)
Definition: locks.h:97
void notify_cleanup(notify_type *notify)
Definition: notify.c:590
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:101
#define lock_basic_lock(lock)
Definition: locks.h:94
void ods_str_trim(char *str)
Definition: file.c:556
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:98
void xfrhandler_start(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:119
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:983
int lock_basic_type
Definition: locks.h:91
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:265
void task_cleanup(task_type *task)
Definition: task.c:275
void xfrd_cleanup(xfrd_type *xfrd, int backup)
Definition: xfrd.c:2196
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:175
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:520
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:92
void xfrd_set_timer_now(xfrd_type *xfrd)
Definition: xfrd.c:472
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:71
void engine_cleanup(engine_type *engine)
Definition: engine.c:1103
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:104
netio_handler_type handler
Definition: xfrd.h:123
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:316
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:95
const char * ods_replace(const char *str, const char *oldstr, const char *newstr)
Definition: file.c:374
void ods_log_warning(const char *format,...)
Definition: log.c:318
void cmdhandler_cleanup(cmdhandler_type *cmdhandler)
Definition: cmdhandler.c:1030
time_t serial_disk_acquired
Definition: xfrd.h:117
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:295