OpenDNSSEC-signer  1.4.10
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 #include "libhsm.h"
48 
49 #include <errno.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 
137 static void
138 engine_start_cmdhandler(engine_type* engine)
139 {
140  ods_log_assert(engine);
141  ods_log_debug("[%s] start command handler", engine_str);
142  engine->cmdhandler->engine = engine;
144  cmdhandler_thread_start, engine->cmdhandler);
145 }
146 
151 static int
152 self_pipe_trick(engine_type* engine)
153 {
154  int sockfd, ret;
155  struct sockaddr_un servaddr;
156  const char* servsock_filename = ODS_SE_SOCKFILE;
157  ods_log_assert(engine);
158  ods_log_assert(engine->cmdhandler);
159  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
160  if (sockfd < 0) {
161  ods_log_error("[%s] unable to connect to command handler: "
162  "socket() failed (%s)", engine_str, strerror(errno));
163  return 1;
164  } else {
165  bzero(&servaddr, sizeof(servaddr));
166  servaddr.sun_family = AF_UNIX;
167  strncpy(servaddr.sun_path, servsock_filename,
168  sizeof(servaddr.sun_path) - 1);
169  ret = connect(sockfd, (const struct sockaddr*) &servaddr,
170  sizeof(servaddr));
171  if (ret != 0) {
172  ods_log_error("[%s] unable to connect to command handler: "
173  "connect() failed (%s)", engine_str, strerror(errno));
174  close(sockfd);
175  return 1;
176  } else {
177  /* self-pipe trick */
178  ods_writen(sockfd, "", 1);
179  close(sockfd);
180  }
181  }
182  return 0;
183 }
188 static void
189 engine_stop_cmdhandler(engine_type* engine)
190 {
191  ods_log_assert(engine);
192  if (!engine->cmdhandler || engine->cmdhandler_done) {
193  return;
194  }
195  ods_log_debug("[%s] stop command handler", engine_str);
196  engine->cmdhandler->need_to_exit = 1;
197  if (self_pipe_trick(engine) == 0) {
198  while (!engine->cmdhandler_done) {
199  ods_log_debug("[%s] waiting for command handler to exit...",
200  engine_str);
201  sleep(1);
202  }
203  } else {
204  ods_log_error("[%s] command handler self pipe trick failed, "
205  "unclean shutdown", engine_str);
206  }
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 }
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 }
245 
246 
251 static void*
252 xfrhandler_thread_start(void* arg)
253 {
254  xfrhandler_type* xfrhandler = (xfrhandler_type*) arg;
255  xfrhandler_start(xfrhandler);
256  return NULL;
257 }
258 static void
259 engine_start_xfrhandler(engine_type* engine)
260 {
261  if (!engine || !engine->xfrhandler) {
262  return;
263  }
264  ods_log_debug("[%s] start xfrhandler", engine_str);
265  engine->xfrhandler->engine = engine;
267  xfrhandler_thread_start, engine->xfrhandler);
268  /* This might be the wrong place to mark the xfrhandler started but
269  * if its isn't done here we might try to shutdown and stop it before
270  * it has marked itself started
271  */
272  engine->xfrhandler->started = 1;
273 }
274 static void
275 engine_stop_xfrhandler(engine_type* engine)
276 {
277  if (!engine || !engine->xfrhandler) {
278  return;
279  }
280  ods_log_debug("[%s] stop xfrhandler", engine_str);
281  engine->xfrhandler->need_to_exit = 1;
282  xfrhandler_signal(engine->xfrhandler);
283  ods_log_debug("[%s] join xfrhandler", engine_str);
284  if (engine->xfrhandler->started) {
286  engine->xfrhandler->started = 0;
287  }
288  engine->xfrhandler->engine = NULL;
289 }
290 
291 
296 static ods_status
297 engine_privdrop(engine_type* engine)
298 {
299  ods_status status = ODS_STATUS_OK;
300  uid_t uid = -1;
301  gid_t gid = -1;
302  ods_log_assert(engine);
303  ods_log_assert(engine->config);
304  ods_log_debug("[%s] drop privileges", engine_str);
305  if (engine->config->username && engine->config->group) {
306  ods_log_verbose("[%s] drop privileges to user %s, group %s",
307  engine_str, engine->config->username, engine->config->group);
308  } else if (engine->config->username) {
309  ods_log_verbose("[%s] drop privileges to user %s", engine_str,
310  engine->config->username);
311  } else if (engine->config->group) {
312  ods_log_verbose("[%s] drop privileges to group %s", engine_str,
313  engine->config->group);
314  }
315  if (engine->config->chroot) {
316  ods_log_verbose("[%s] chroot to %s", engine_str,
317  engine->config->chroot);
318  }
319  status = privdrop(engine->config->username, engine->config->group,
320  engine->config->chroot, &uid, &gid);
321  engine->uid = uid;
322  engine->gid = gid;
323  privclose(engine->config->username, engine->config->group);
324  return status;
325 }
326 
327 
332 static void
333 engine_create_workers(engine_type* engine)
334 {
335  size_t i = 0;
336  ods_log_assert(engine);
337  ods_log_assert(engine->config);
338  ods_log_assert(engine->allocator);
339  engine->workers = (worker_type**) allocator_alloc(engine->allocator,
340  ((size_t)engine->config->num_worker_threads) * sizeof(worker_type*));
341  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
342  engine->workers[i] = worker_create(engine->allocator, i,
343  WORKER_WORKER);
344  }
345 }
346 static void
347 engine_create_drudgers(engine_type* engine)
348 {
349  size_t i = 0;
350  ods_log_assert(engine);
351  ods_log_assert(engine->config);
352  ods_log_assert(engine->allocator);
353  engine->drudgers = (worker_type**) allocator_alloc(engine->allocator,
354  ((size_t)engine->config->num_signer_threads) * sizeof(worker_type*));
355  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
356  engine->drudgers[i] = worker_create(engine->allocator, i,
358  }
359 }
360 static void*
361 worker_thread_start(void* arg)
362 {
363  worker_type* worker = (worker_type*) arg;
365  worker_start(worker);
366  return NULL;
367 }
368 static void
369 engine_start_workers(engine_type* engine)
370 {
371  size_t i = 0;
372  ods_log_assert(engine);
373  ods_log_assert(engine->config);
374  ods_log_debug("[%s] start workers", engine_str);
375  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
376  engine->workers[i]->need_to_exit = 0;
377  engine->workers[i]->engine = (void*) engine;
378  ods_thread_create(&engine->workers[i]->thread_id, worker_thread_start,
379  engine->workers[i]);
380  }
381 }
382 void
384 {
385  size_t i = 0;
386  ods_log_assert(engine);
387  ods_log_assert(engine->config);
388  ods_log_debug("[%s] start drudgers", engine_str);
389  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
390  engine->drudgers[i]->need_to_exit = 0;
391  engine->drudgers[i]->engine = (void*) engine;
392  ods_thread_create(&engine->drudgers[i]->thread_id, worker_thread_start,
393  engine->drudgers[i]);
394  }
395 }
396 static void
397 engine_stop_workers(engine_type* engine)
398 {
399  int i = 0;
400  ods_log_assert(engine);
401  ods_log_assert(engine->config);
402  ods_log_debug("[%s] stop workers", engine_str);
403  /* tell them to exit and wake up sleepyheads */
404  for (i=0; i < engine->config->num_worker_threads; i++) {
405  engine->workers[i]->need_to_exit = 1;
406  worker_wakeup(engine->workers[i]);
407  }
408  ods_log_debug("[%s] notify workers", engine_str);
409  worker_notify_all(&engine->signq->q_lock, &engine->signq->q_nonfull);
410  /* head count */
411  for (i=0; i < engine->config->num_worker_threads; i++) {
412  ods_log_debug("[%s] join worker %d", engine_str, i+1);
413  ods_thread_join(engine->workers[i]->thread_id);
414  engine->workers[i]->engine = NULL;
415  }
416 }
417 void
419 {
420  int i = 0;
421  ods_log_assert(engine);
422  ods_log_assert(engine->config);
423  ods_log_debug("[%s] stop drudgers", engine_str);
424  /* tell them to exit and wake up sleepyheads */
425  for (i=0; i < engine->config->num_signer_threads; i++) {
426  engine->drudgers[i]->need_to_exit = 1;
427  }
428  ods_log_debug("[%s] notify drudgers", engine_str);
429  worker_notify_all(&engine->signq->q_lock, &engine->signq->q_threshold);
430  /* head count */
431  for (i=0; i < engine->config->num_signer_threads; i++) {
432  ods_log_debug("[%s] join drudger %d", engine_str, i+1);
433  ods_thread_join(engine->drudgers[i]->thread_id);
434  engine->drudgers[i]->engine = NULL;
435  }
436 }
437 
438 
443 void
445 {
446  size_t i = 0;
447  ods_log_assert(engine);
448  ods_log_assert(engine->config);
449  ods_log_debug("[%s] wake up workers", engine_str);
450  /* wake up sleepyheads */
451  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
452  worker_wakeup(engine->workers[i]);
453  }
454 }
455 
456 
461 static ods_status
462 engine_setup(engine_type* engine)
463 {
464  ods_status status = ODS_STATUS_OK;
465  struct sigaction action;
466  int sockets[2] = {0,0};
467 
468  ods_log_debug("[%s] setup signer engine", engine_str);
469  if (!engine || !engine->config) {
470  return ODS_STATUS_ASSERT_ERR;
471  }
472  /* set edns */
474 
475  /* create command handler (before chowning socket file) */
476  engine->cmdhandler = cmdhandler_create(engine->allocator,
477  engine->config->clisock_filename);
478  if (!engine->cmdhandler) {
480  }
481  engine->dnshandler = dnshandler_create(engine->allocator,
482  engine->config->interfaces);
483  engine->xfrhandler = xfrhandler_create(engine->allocator);
484  if (!engine->xfrhandler) {
486  }
487  if (engine->dnshandler) {
488  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
490  }
491  engine->xfrhandler->dnshandler.fd = sockets[0];
492  engine->dnshandler->xfrhandler.fd = sockets[1];
493  status = dnshandler_listen(engine->dnshandler);
494  if (status != ODS_STATUS_OK) {
495  ods_log_error("[%s] setup: unable to listen to sockets (%s)",
496  engine_str, ods_status2str(status));
498  }
499  }
500  /* privdrop */
501  engine->uid = privuid(engine->config->username);
502  engine->gid = privgid(engine->config->group);
503  /* TODO: does piddir exists? */
504  /* remove the chown stuff: piddir? */
505  ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
506  ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
507  ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
508  if (engine->config->log_filename && !engine->config->use_syslog) {
509  ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
510  }
511  if (engine->config->working_dir &&
512  chdir(engine->config->working_dir) != 0) {
513  ods_log_error("[%s] setup: unable to chdir to %s (%s)", engine_str,
514  engine->config->working_dir, strerror(errno));
515  return ODS_STATUS_CHDIR_ERR;
516  }
517  if (engine_privdrop(engine) != ODS_STATUS_OK) {
519  }
520  /* daemonize */
521  if (engine->daemonize) {
522  switch ((engine->pid = fork())) {
523  case -1: /* error */
524  ods_log_error("[%s] setup: unable to fork daemon (%s)",
525  engine_str, strerror(errno));
526  return ODS_STATUS_FORK_ERR;
527  case 0: /* child */
528  break;
529  default: /* parent */
530  engine_cleanup(engine);
531  engine = NULL;
532  xmlCleanupParser();
533  xmlCleanupGlobals();
534  xmlCleanupThreads();
535  exit(0);
536  }
537  if (setsid() == -1) {
538  ods_log_error("[%s] setup: unable to setsid daemon (%s)",
539  engine_str, strerror(errno));
540  return ODS_STATUS_SETSID_ERR;
541  }
542  }
543  engine->pid = getpid();
544  ods_log_verbose("[%s] running as pid %lu", engine_str,
545  (unsigned long) engine->pid);
546  /* catch signals */
547  signal_set_engine(engine);
548  action.sa_handler = (void (*)(int))signal_handler;
549  sigfillset(&action.sa_mask);
550  action.sa_flags = 0;
551  sigaction(SIGTERM, &action, NULL);
552  sigaction(SIGHUP, &action, NULL);
553  sigaction(SIGINT, &action, NULL);
554  sigaction(SIGILL, &action, NULL);
555  sigaction(SIGUSR1, &action, NULL);
556  sigaction(SIGALRM, &action, NULL);
557  sigaction(SIGCHLD, &action, NULL);
558  action.sa_handler = SIG_IGN;
559  sigaction(SIGPIPE, &action, NULL);
560  /* create workers/drudgers */
561  engine_create_workers(engine);
562  engine_create_drudgers(engine);
563  /* start cmd/dns/xfr handlers */
564  engine_start_cmdhandler(engine);
565  engine_start_dnshandler(engine);
566  engine_start_xfrhandler(engine);
567  tsig_handler_init(engine->allocator);
568  /* write pidfile */
569  if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
570  hsm_close();
572  }
573  /* setup done */
574  return ODS_STATUS_OK;
575 }
576 
577 
582 static int
583 engine_all_zones_processed(engine_type* engine)
584 {
585  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
586  zone_type* zone = NULL;
587 
588  ods_log_assert(engine);
589  ods_log_assert(engine->zonelist);
590  ods_log_assert(engine->zonelist->zones);
591 
592  node = ldns_rbtree_first(engine->zonelist->zones);
593  while (node && node != LDNS_RBTREE_NULL) {
594  zone = (zone_type*) node->key;
595  ods_log_assert(zone);
596  ods_log_assert(zone->db);
597  if (!zone->db->is_processed) {
598  return 0;
599  }
600  node = ldns_rbtree_next(node);
601  }
602  return 1;
603 }
604 
605 
610 static void
611 engine_run(engine_type* engine, int single_run)
612 {
613  if (!engine) {
614  return;
615  }
616  engine_start_workers(engine);
617  engine_start_drudgers(engine);
618 
619  lock_basic_lock(&engine->signal_lock);
620  engine->signal = SIGNAL_RUN;
621  lock_basic_unlock(&engine->signal_lock);
622 
623  while (!engine->need_to_exit && !engine->need_to_reload) {
624  lock_basic_lock(&engine->signal_lock);
625  engine->signal = signal_capture(engine->signal);
626  switch (engine->signal) {
627  case SIGNAL_RUN:
628  ods_log_assert(1);
629  break;
630  case SIGNAL_RELOAD:
631  ods_log_error("signer instructed to reload due to explicit signal");
632  engine->need_to_reload = 1;
633  break;
634  case SIGNAL_SHUTDOWN:
635  engine->need_to_exit = 1;
636  break;
637  default:
638  ods_log_warning("[%s] invalid signal %d captured, "
639  "keep running", engine_str, (int)engine->signal);
640  engine->signal = SIGNAL_RUN;
641  break;
642  }
643  lock_basic_unlock(&engine->signal_lock);
644 
645  if (single_run) {
646  engine->need_to_exit = engine_all_zones_processed(engine);
647  }
648  lock_basic_lock(&engine->signal_lock);
649  if (engine->signal == SIGNAL_RUN && !single_run) {
650  ods_log_debug("[%s] taking a break", engine_str);
651  lock_basic_sleep(&engine->signal_cond, &engine->signal_lock, 3600);
652  }
653  lock_basic_unlock(&engine->signal_lock);
654  }
655  ods_log_debug("[%s] signer halted", engine_str);
656  engine_stop_drudgers(engine);
657  engine_stop_workers(engine);
658 }
659 
660 
665 static void
666 set_notify_ns(zone_type* zone, const char* cmd)
667 {
668  const char* str = NULL;
669  const char* str2 = NULL;
670  char* token = NULL;
671  ods_log_assert(cmd);
672  ods_log_assert(zone);
673  ods_log_assert(zone->name);
674  ods_log_assert(zone->adoutbound);
675  if (zone->adoutbound->type == ADAPTER_FILE) {
676  str = ods_replace(cmd, "%zonefile", zone->adoutbound->configstr);
677  if (!str) {
678  ods_log_error("[%s] unable to set notify ns: replace zonefile failed",
679  engine_str);
680  }
681  str2 = ods_replace(str, "%zone", zone->name);
682  free((void*)str);
683  } else {
684  str2 = ods_replace(cmd, "%zone", zone->name);
685  }
686  if (str2) {
687  ods_str_trim((char*) str2);
688  str = str2;
689  if (*str) {
690  token = NULL;
691  while ((token = strtok((char*) str, " "))) {
692  if (*token) {
693  ods_str_list_add(&zone->notify_args, token);
694  }
695  str = NULL;
696  }
697  }
698  zone->notify_command = (char*) str2;
699  zone->notify_ns = zone->notify_args[0];
700  ods_log_debug("[%s] set notify ns: %s", engine_str, zone->notify_ns);
701  } else {
702  ods_log_error("[%s] unable to set notify ns: replace zone failed",
703  engine_str);
704  }
705 }
706 
707 
712 static int
713 dnsconfig_zone(engine_type* engine, zone_type* zone)
714 {
715  int numdns = 0;
716  ods_log_assert(engine);
717  ods_log_assert(engine->xfrhandler);
718  ods_log_assert(engine->xfrhandler->netio);
719  ods_log_assert(zone);
720  ods_log_assert(zone->adinbound);
721  ods_log_assert(zone->adoutbound);
722  ods_log_assert(zone->name);
723 
724  if (zone->adinbound->type == ADAPTER_DNS) {
725  /* zone transfer handler */
726  if (!zone->xfrd) {
727  ods_log_debug("[%s] add transfer handler for zone %s",
728  engine_str, zone->name);
729  zone->xfrd = xfrd_create((void*) engine->xfrhandler,
730  (void*) zone);
731  ods_log_assert(zone->xfrd);
733  &zone->xfrd->handler);
734  } else if (!zone->xfrd->serial_disk_acquired) {
735  xfrd_set_timer_now(zone->xfrd);
736  }
737  numdns++;
738  } else if (zone->xfrd) {
740  &zone->xfrd->handler);
741  xfrd_cleanup(zone->xfrd, 0);
742  zone->xfrd = NULL;
743  }
744  if (zone->adoutbound->type == ADAPTER_DNS) {
745  /* notify handler */
746  if (!zone->notify) {
747  ods_log_debug("[%s] add notify handler for zone %s",
748  engine_str, zone->name);
749  zone->notify = notify_create((void*) engine->xfrhandler,
750  (void*) zone);
751  ods_log_assert(zone->notify);
753  &zone->notify->handler);
754  }
755  numdns++;
756  } else if (zone->notify) {
758  &zone->notify->handler);
759  notify_cleanup(zone->notify);
760  zone->notify = NULL;
761  }
762  return numdns;
763 }
764 
765 
770 void
772 {
773  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
774  zone_type* zone = NULL;
775  zone_type* delzone = NULL;
776  task_type* task = NULL;
777  ods_status status = ODS_STATUS_OK;
778  unsigned wake_up = 0;
779  int warnings = 0;
780  time_t now = 0;
781 
782  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
783  return;
784  }
785  now = time_now();
786 
787  ods_log_debug("[%s] commit zone list changes", engine_str);
788  lock_basic_lock(&engine->zonelist->zl_lock);
789  node = ldns_rbtree_first(engine->zonelist->zones);
790  while (node && node != LDNS_RBTREE_NULL) {
791  zone = (zone_type*) node->data;
792  task = NULL; /* reset task */
793 
794  if (zone->zl_status == ZONE_ZL_REMOVED) {
795  node = ldns_rbtree_next(node);
796  lock_basic_lock(&zone->zone_lock);
797  delzone = zonelist_del_zone(engine->zonelist, zone);
798  if (delzone) {
800  task = unschedule_task(engine->taskq,
801  (task_type*) zone->task);
803  }
804  task_cleanup(task);
805  task = NULL;
808  &zone->xfrd->handler);
809  zone_cleanup(zone);
810  zone = NULL;
811  continue;
812  } else if (zone->zl_status == ZONE_ZL_ADDED) {
813  lock_basic_lock(&zone->zone_lock);
814  ods_log_assert(!zone->task);
815  /* set notify nameserver command */
816  if (engine->config->notify_command && !zone->notify_ns) {
817  set_notify_ns(zone, engine->config->notify_command);
818  }
819  /* create task */
820  task = task_create(TASK_SIGNCONF, now, zone);
822  if (!task) {
823  ods_log_crit("[%s] unable to create task for zone %s: "
824  "task_create() failed", engine_str, zone->name);
825  node = ldns_rbtree_next(node);
826  continue;
827  }
828  }
829  /* load adapter config */
830  status = adapter_load_config(zone->adinbound);
831  if (status != ODS_STATUS_OK) {
832  ods_log_error("[%s] unable to load config for inbound adapter "
833  "for zone %s: %s", engine_str, zone->name,
834  ods_status2str(status));
835  }
836  status = adapter_load_config(zone->adoutbound);
837  if (status != ODS_STATUS_OK) {
838  ods_log_error("[%s] unable to load config for outbound adapter "
839  "for zone %s: %s", engine_str, zone->name,
840  ods_status2str(status));
841  }
842  /* for dns adapters */
843  warnings += dnsconfig_zone(engine, zone);
844 
845  if (zone->zl_status == ZONE_ZL_ADDED) {
846  ods_log_assert(task);
847  lock_basic_lock(&zone->zone_lock);
848  zone->task = task;
850  /* TODO: task is reachable from other threads by means of
851  * zone->task. To fix this we need to nest the locks. But
852  * first investigate any possible deadlocks. */
854  status = schedule_task(engine->taskq, task, 0);
856  } else if (zl_changed == ODS_STATUS_OK) {
857  /* always try to update signconf */
858  lock_basic_lock(&zone->zone_lock);
859  status = zone_reschedule_task(zone, engine->taskq, TASK_SIGNCONF);
861  }
862  if (status != ODS_STATUS_OK) {
863  ods_log_crit("[%s] unable to schedule task for zone %s: %s",
864  engine_str, zone->name, ods_status2str(status));
865  } else {
866  wake_up = 1;
867  zone->zl_status = ZONE_ZL_OK;
868  }
869  node = ldns_rbtree_next(node);
870  }
872  if (engine->dnshandler) {
873  ods_log_debug("[%s] forward notify for all zones", engine_str);
875  (uint8_t*) ODS_SE_NOTIFY_CMD, strlen(ODS_SE_NOTIFY_CMD));
876  } else if (warnings) {
877  ods_log_warning("[%s] no dnshandler/listener configured, but zones "
878  "are configured with dns adapters: notify and zone transfer "
879  "requests will not work properly", engine_str);
880  }
881  if (wake_up) {
882  engine_wakeup_workers(engine);
883  }
884 }
885 
886 
891 static ods_status
892 engine_recover(engine_type* engine)
893 {
894  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
895  zone_type* zone = NULL;
896  ods_status status = ODS_STATUS_OK;
898 
899  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
900  ods_log_error("[%s] cannot recover zones: no engine or zonelist",
901  engine_str);
902  return ODS_STATUS_ERR; /* no need to update zones */
903  }
904  ods_log_assert(engine);
905  ods_log_assert(engine->zonelist);
906  ods_log_assert(engine->zonelist->zones);
907 
908  lock_basic_lock(&engine->zonelist->zl_lock);
909  /* [LOCK] zonelist */
910  node = ldns_rbtree_first(engine->zonelist->zones);
911  while (node && node != LDNS_RBTREE_NULL) {
912  zone = (zone_type*) node->data;
913 
915  lock_basic_lock(&zone->zone_lock);
916  status = zone_recover2(zone);
917  if (status == ODS_STATUS_OK) {
918  ods_log_assert(zone->task);
919  ods_log_assert(zone->db);
920  ods_log_assert(zone->signconf);
921  /* notify nameserver */
922  if (engine->config->notify_command && !zone->notify_ns) {
923  set_notify_ns(zone, engine->config->notify_command);
924  }
925  /* schedule task */
927  /* [LOCK] schedule */
928  status = schedule_task(engine->taskq, (task_type*) zone->task, 0);
929  /* [UNLOCK] schedule */
931 
932  if (status != ODS_STATUS_OK) {
933  ods_log_crit("[%s] unable to schedule task for zone %s: %s",
934  engine_str, zone->name, ods_status2str(status));
935  task_cleanup((task_type*) zone->task);
936  zone->task = NULL;
937  result = ODS_STATUS_OK; /* will trigger update zones */
938  } else {
939  ods_log_debug("[%s] recovered zone %s", engine_str,
940  zone->name);
941  /* recovery done */
942  zone->zl_status = ZONE_ZL_OK;
943  }
944  } else {
945  if (status != ODS_STATUS_UNCHANGED) {
946  ods_log_warning("[%s] unable to recover zone %s from backup,"
947  " performing full sign", engine_str, zone->name);
948  }
949  result = ODS_STATUS_OK; /* will trigger update zones */
950  }
952  node = ldns_rbtree_next(node);
953  }
954  /* [UNLOCK] zonelist */
956  return result;
957 }
958 
959 
964 void
965 engine_start(const char* cfgfile, int cmdline_verbosity, int daemonize,
966  int info, int single_run)
967 {
968  engine_type* engine = NULL;
969  int use_syslog = 0;
970  ods_status zl_changed = ODS_STATUS_UNCHANGED;
971  ods_status status = ODS_STATUS_OK;
972 
973  ods_log_assert(cfgfile);
974  ods_log_init(NULL, use_syslog, cmdline_verbosity);
975  ods_log_verbose("[%s] starting signer", engine_str);
976 
977  /* initialize */
978  xmlInitGlobals();
979  xmlInitParser();
980  xmlInitThreads();
981  engine = engine_create();
982  if (!engine) {
983  ods_fatal_exit("[%s] create failed", engine_str);
984  return;
985  }
986  engine->daemonize = daemonize;
987 
988  /* config */
989  engine->config = engine_config(engine->allocator, cfgfile,
990  cmdline_verbosity);
991  status = engine_config_check(engine->config);
992  if (status != ODS_STATUS_OK) {
993  ods_log_error("[%s] cfgfile %s has errors", engine_str, cfgfile);
994  goto earlyexit;
995  }
996  if (info) {
997  engine_config_print(stdout, engine->config); /* for debugging */
998  goto earlyexit;
999  }
1000  /* check pidfile */
1001  if (!util_check_pidfile(engine->config->pid_filename)) {
1002  exit(1);
1003  }
1004  /* open log */
1005  ods_log_init(engine->config->log_filename, engine->config->use_syslog,
1006  engine->config->verbosity);
1007  /* setup */
1008  tzset(); /* for portability */
1009  status = engine_setup(engine);
1010  if (status != ODS_STATUS_OK) {
1011  ods_log_error("[%s] setup failed: %s", engine_str,
1012  ods_status2str(status));
1013  if (status != ODS_STATUS_WRITE_PIDFILE_ERR) {
1014  /* command handler had not yet been started */
1015  engine->cmdhandler_done = 1;
1016  }
1017  goto earlyexit;
1018  }
1019 
1020  /* run */
1021  while (engine->need_to_exit == 0) {
1022  /* update zone list */
1023  lock_basic_lock(&engine->zonelist->zl_lock);
1024  zl_changed = zonelist_update(engine->zonelist,
1025  engine->config->zonelist_filename);
1026  engine->zonelist->just_removed = 0;
1027  engine->zonelist->just_added = 0;
1028  engine->zonelist->just_updated = 0;
1029  lock_basic_unlock(&engine->zonelist->zl_lock);
1030  /* start/reload */
1031  if (engine->need_to_reload) {
1032  ods_log_info("[%s] signer reloading", engine_str);
1033  fifoq_wipe(engine->signq);
1034  engine->need_to_reload = 0;
1035  } else {
1036  ods_log_info("[%s] signer started (version %s), pid %u",
1037  engine_str, PACKAGE_VERSION, engine->pid);
1038  if (hsm_open(engine->config->cfg_filename, hsm_check_pin) != HSM_OK) {
1039  char* error = hsm_get_error(NULL);
1040  if (error != NULL) {
1041  ods_log_error("[%s] %s", "hsm", error);
1042  free(error);
1043  }
1044  ods_log_error("[%s] opening hsm failed (for engine recover)", engine_str);
1045  break;
1046  }
1047  zl_changed = engine_recover(engine);
1048  hsm_close();
1049  }
1050  if (zl_changed == ODS_STATUS_OK ||
1051  zl_changed == ODS_STATUS_UNCHANGED) {
1052  engine_update_zones(engine, zl_changed);
1053  }
1054  if (hsm_open(engine->config->cfg_filename, hsm_check_pin) != HSM_OK) {
1055  char* error = hsm_get_error(NULL);
1056  if (error != NULL) {
1057  ods_log_error("[%s] %s", "hsm", error);
1058  free(error);
1059  }
1060  ods_log_error("[%s] opening hsm failed (for engine run)", engine_str);
1061  break;
1062  }
1063  engine_run(engine, single_run);
1064  hsm_close();
1065  }
1066 
1067  /* shutdown */
1068  ods_log_info("[%s] signer shutdown", engine_str);
1069  engine_stop_cmdhandler(engine);
1070  engine_stop_xfrhandler(engine);
1071  engine_stop_dnshandler(engine);
1072 
1073 earlyexit:
1074  if (engine && engine->config) {
1075  if (engine->config->pid_filename) {
1076  (void)unlink(engine->config->pid_filename);
1077  }
1078  if (engine->config->clisock_filename) {
1079  (void)unlink(engine->config->clisock_filename);
1080  }
1081  }
1083  engine_cleanup(engine);
1084  engine = NULL;
1085  ods_log_close();
1086  xmlCleanupParser();
1087  xmlCleanupGlobals();
1088  xmlCleanupThreads();
1089 }
1090 
1091 
1096 void
1098 {
1099  size_t i = 0;
1100  allocator_type* allocator;
1101  cond_basic_type signal_cond;
1102  lock_basic_type signal_lock;
1103  if (!engine) {
1104  return;
1105  }
1106  allocator = engine->allocator;
1107  signal_cond = engine->signal_cond;
1108  signal_lock = engine->signal_lock;
1109  if (engine->workers && engine->config) {
1110  for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
1111  worker_cleanup(engine->workers[i]);
1112  }
1113  allocator_deallocate(allocator, (void*) engine->workers);
1114  }
1115  if (engine->drudgers && engine->config) {
1116  for (i=0; i < (size_t) engine->config->num_signer_threads; i++) {
1117  worker_cleanup(engine->drudgers[i]);
1118  }
1119  allocator_deallocate(allocator, (void*) engine->drudgers);
1120  }
1121  zonelist_cleanup(engine->zonelist);
1122  schedule_cleanup(engine->taskq);
1123  fifoq_cleanup(engine->signq);
1124  cmdhandler_cleanup(engine->cmdhandler);
1125  dnshandler_cleanup(engine->dnshandler);
1126  xfrhandler_cleanup(engine->xfrhandler);
1127  engine_config_cleanup(engine->config);
1128  allocator_deallocate(allocator, (void*) engine);
1129  lock_basic_destroy(&signal_lock);
1130  lock_basic_off(&signal_cond);
1131  allocator_cleanup(allocator);
1132 }
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:798
#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:444
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:418
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:771
const char * configstr
Definition: adapter.h:60
cmdhandler_type * cmdhandler_create(allocator_type *allocator, const char *filename)
Definition: cmdhandler.c:882
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:836
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:770
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:964
void worker_cleanup(worker_type *worker)
Definition: worker.c:910
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:383
#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:158
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:965
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:896
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
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:835
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 fifoq_wipe(fifoq_type *q)
Definition: fifoq.c:72
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:1097
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:1031
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
uid_t uid
Definition: engine.h:70
xfrhandler_type * xfrhandler
Definition: engine.h:65
void dnshandler_cleanup(dnshandler_type *dnshandler)
Definition: dnshandler.c:295