OpenDNSSEC-signer  2.1.12
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 "duration.h"
36 #include "file.h"
37 #include "str.h"
38 #include "hsm.h"
39 #include "locks.h"
40 #include "log.h"
41 #include "privdrop.h"
42 #include "status.h"
43 #include "util.h"
44 #include "signer/zonelist.h"
45 #include "wire/tsig.h"
46 #include "libhsm.h"
47 #include "signertasks.h"
48 #include "signercommands.h"
49 
50 #include <ctype.h>
51 #include <errno.h>
52 #include <libxml/parser.h>
53 #include <signal.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <strings.h>
58 #include <sys/socket.h>
59 #include <sys/types.h>
60 #include <sys/un.h>
61 #include <time.h>
62 #include <unistd.h>
63 
64 static const char* engine_str = "engine";
65 
66 static engine_type* engine = NULL;
67 
72 static engine_type*
73 engine_create(void)
74 {
75  engine_type* engine;
76  CHECKALLOC(engine = (engine_type*) malloc(sizeof(engine_type)));
77  engine->config = NULL;
78  engine->workers = NULL;
79  engine->cmdhandler = NULL;
80  engine->dnshandler = NULL;
81  engine->xfrhandler = NULL;
82  engine->taskq = NULL;
83  engine->pid = -1;
84  engine->uid = -1;
85  engine->gid = -1;
86  engine->daemonize = 0;
87  engine->need_to_exit = 0;
88  engine->need_to_reload = 0;
89  pthread_mutex_init(&engine->signal_lock, NULL);
90  pthread_cond_init(&engine->signal_cond, NULL);
91  engine->zonelist = zonelist_create();
92  if (!engine->zonelist) {
93  engine_cleanup(engine);
94  return NULL;
95  }
96  if (!(engine->taskq = schedule_create())) {
97  engine_cleanup(engine);
98  return NULL;
99  }
100  schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_SIGNCONF, do_readsignconf);
101  schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_FORCESIGNCONF, do_forcereadsignconf);
102  schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_READ, do_readzone);
103  schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_FORCEREAD, do_forcereadzone);
104  schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_SIGN, do_signzone);
105  schedule_registertask(engine->taskq, TASK_CLASS_SIGNER, TASK_WRITE, do_writezone);
106  return engine;
107 }
108 
109 static void
110 engine_start_cmdhandler(engine_type* engine)
111 {
112  ods_log_debug("[%s] start command handler", engine_str);
113  janitor_thread_create(&engine->cmdhandler->thread_id, workerthreadclass, (janitor_runfn_t)cmdhandler_start, engine->cmdhandler);
114 }
115 
120 static void
121 engine_start_dnshandler(engine_type* engine)
122 {
123  if (!engine || !engine->dnshandler) {
124  return;
125  }
126  ods_log_debug("[%s] start dnshandler", engine_str);
127  engine->dnshandler->engine = engine;
128  janitor_thread_create(&engine->dnshandler->thread_id, handlerthreadclass, (janitor_runfn_t)dnshandler_start, engine->dnshandler);
129 }
130 static void
131 engine_stop_dnshandler(engine_type* engine)
132 {
133  if (!engine || !engine->dnshandler || !engine->dnshandler->thread_id) {
134  return;
135  }
136  ods_log_debug("[%s] stop dnshandler", engine_str);
137  engine->dnshandler->need_to_exit = 1;
138  dnshandler_signal(engine->dnshandler);
139  ods_log_debug("[%s] join dnshandler", engine_str);
140  janitor_thread_join(engine->dnshandler->thread_id);
141  engine->dnshandler->engine = NULL;
142 }
143 
144 
145 static void
146 engine_start_xfrhandler(engine_type* engine)
147 {
148  if (!engine || !engine->xfrhandler) {
149  return;
150  }
151  ods_log_debug("[%s] start xfrhandler", engine_str);
152  engine->xfrhandler->engine = engine;
153  /* This might be the wrong place to mark the xfrhandler started but
154  * if its isn't done here we might try to shutdown and stop it before
155  * it has marked itself started
156  */
157  engine->xfrhandler->started = 1;
158  janitor_thread_create(&engine->xfrhandler->thread_id, handlerthreadclass, (janitor_runfn_t)xfrhandler_start, engine->xfrhandler);
159 }
160 static void
161 engine_stop_xfrhandler(engine_type* engine)
162 {
163  if (!engine || !engine->xfrhandler) {
164  return;
165  }
166  ods_log_debug("[%s] stop xfrhandler", engine_str);
167  engine->xfrhandler->need_to_exit = 1;
168  xfrhandler_signal(engine->xfrhandler);
169  ods_log_debug("[%s] join xfrhandler", engine_str);
170  if (engine->xfrhandler->started) {
171  janitor_thread_join(engine->xfrhandler->thread_id);
172  engine->xfrhandler->started = 0;
173  }
174  engine->xfrhandler->engine = NULL;
175 }
176 
177 
182 static ods_status
183 engine_privdrop(engine_type* engine)
184 {
185  ods_status status = ODS_STATUS_OK;
186  uid_t uid = -1;
187  gid_t gid = -1;
188  ods_log_assert(engine);
189  ods_log_assert(engine->config);
190  ods_log_debug("[%s] drop privileges", engine_str);
191  if (engine->config->username && engine->config->group) {
192  ods_log_verbose("[%s] drop privileges to user %s, group %s",
193  engine_str, engine->config->username, engine->config->group);
194  } else if (engine->config->username) {
195  ods_log_verbose("[%s] drop privileges to user %s", engine_str,
196  engine->config->username);
197  } else if (engine->config->group) {
198  ods_log_verbose("[%s] drop privileges to group %s", engine_str,
199  engine->config->group);
200  }
201  if (engine->config->chroot) {
202  ods_log_verbose("[%s] chroot to %s", engine_str,
203  engine->config->chroot);
204  }
205  status = privdrop(engine->config->username, engine->config->group,
206  engine->config->chroot, &uid, &gid);
207  engine->uid = uid;
208  engine->gid = gid;
209  privclose(engine->config->username, engine->config->group);
210  return status;
211 }
212 
213 
218 static void
219 engine_create_workers(engine_type* engine)
220 {
221  char* name;
222  int i;
223  int numTotalWorkers;
224  int threadCount = 0;
225  ods_log_assert(engine);
226  ods_log_assert(engine->config);
227  numTotalWorkers = engine->config->num_worker_threads + engine->config->num_signer_threads;
228  CHECKALLOC(engine->workers = (worker_type**) malloc(numTotalWorkers * sizeof(worker_type*)));
229  for (i=0; i < engine->config->num_worker_threads; i++) {
230  asprintf(&name, "worker[%d]", i+1);
231  engine->workers[threadCount++] = worker_create(name, engine->taskq);
232  }
233  for (i=0; i < engine->config->num_signer_threads; i++) {
234  asprintf(&name, "drudger[%d]", i+1);
235  engine->workers[threadCount++] = worker_create(name, engine->taskq);
236  }
237 }
238 
239 static void
240 engine_start_workers(engine_type* engine)
241 {
242  int i;
243  int threadCount = 0;
244  struct worker_context* context;
245  ods_log_assert(engine);
246  ods_log_assert(engine->config);
247  ods_log_debug("[%s] start workers", engine_str);
248  for (i=0; i < engine->config->num_worker_threads; i++,threadCount++) {
249  CHECKALLOC(context = malloc(sizeof(struct worker_context)));
250  context->engine = engine;
251  context->worker = engine->workers[threadCount];
252  context->signq = engine->taskq->signq;
253  engine->workers[threadCount]->need_to_exit = 0;
254  engine->workers[threadCount]->context = context;
255  janitor_thread_create(&engine->workers[threadCount]->thread_id, workerthreadclass, (janitor_runfn_t)worker_start, engine->workers[threadCount]);
256  }
257  for (i=0; i < engine->config->num_signer_threads; i++,threadCount++) {
258  engine->workers[threadCount]->need_to_exit = 0;
259  janitor_thread_create(&engine->workers[threadCount]->thread_id, workerthreadclass, (janitor_runfn_t)drudge, engine->workers[threadCount]);
260  }
261 }
262 
263 static void
264 engine_stop_threads(engine_type* engine)
265 {
266  int i;
267  int numTotalWorkers;
268  ods_log_assert(engine);
269  ods_log_assert(engine->config);
270  ods_log_debug("[%s] stop workers and drudgers", engine_str);
272  for (i=0; i < numTotalWorkers; i++) {
273  engine->workers[i]->need_to_exit = 1;
274  }
275  ods_log_debug("[%s] notify workers and drudgers", engine_str);
276  schedule_release_all(engine->taskq);
277 
278  for (i=0; i < numTotalWorkers; i++) {
279  ods_log_debug("[%s] join worker %d", engine_str, i+1);
280  janitor_thread_join(engine->workers[i]->thread_id);
281  free(engine->workers[i]->context);
282  }
283 }
284 
285 
290 void
292 {
293  size_t i = 0;
294  ods_log_assert(engine);
295  ods_log_assert(engine->config);
296  ods_log_debug("[%s] wake up workers", engine_str);
297  /* wake up sleepyheads */
298  schedule_release_all(engine->taskq);
299 }
300 
301 static void
302 signal_handler(sig_atomic_t sig)
303 {
304  switch (sig) {
305  case SIGHUP:
306  if (engine) {
307  engine->need_to_reload = 1;
308  pthread_mutex_lock(&engine->signal_lock);
309  pthread_cond_signal(&engine->signal_cond);
310  pthread_mutex_unlock(&engine->signal_lock);
311  }
312  break;
313  case SIGINT:
314  case SIGTERM:
315  if (engine) {
316  engine->need_to_exit = 1;
317  pthread_mutex_lock(&engine->signal_lock);
318  pthread_cond_signal(&engine->signal_cond);
319  pthread_mutex_unlock(&engine->signal_lock);
320  }
321  break;
322  default:
323  break;
324  }
325 }
326 
331 static ods_status
332 engine_setup(void)
333 {
334  ods_status status = ODS_STATUS_OK;
335  struct sigaction action;
336  int sockets[2] = {0,0};
337  int pipefd[2];
338  char buff = '\0';
339  int fd, error;
340 
341  ods_log_debug("[%s] setup signer engine", engine_str);
342  if (!engine || !engine->config) {
343  return ODS_STATUS_ASSERT_ERR;
344  }
345  /* set edns */
347 
348  /* create command handler (before chowning socket file) */
349  engine->cmdhandler = cmdhandler_create(engine->config->clisock_filename, signercommands, engine, NULL, NULL);
350  if (!engine->cmdhandler) {
351  return ODS_STATUS_CMDHANDLER_ERR;
352  }
353  engine->dnshandler = dnshandler_create(engine->config->interfaces);
354  engine->xfrhandler = xfrhandler_create();
355  if (!engine->xfrhandler) {
356  return ODS_STATUS_XFRHANDLER_ERR;
357  }
358  if (engine->dnshandler) {
359  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
360  return ODS_STATUS_XFRHANDLER_ERR;
361  }
362  engine->xfrhandler->dnshandler.fd = sockets[0];
363  engine->dnshandler->xfrhandler.fd = sockets[1];
364  status = dnshandler_listen(engine->dnshandler);
365  if (status != ODS_STATUS_OK) {
366  ods_log_error("[%s] setup: unable to listen to sockets (%s)",
367  engine_str, ods_status2str(status));
368  return ODS_STATUS_XFRHANDLER_ERR;
369  }
370  }
371  /* privdrop */
372  engine->uid = privuid(engine->config->username);
373  engine->gid = privgid(engine->config->group);
374  /* TODO: does piddir exists? */
375  /* remove the chown stuff: piddir? */
376  ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
377  ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
378  ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
379  if (engine->config->log_filename && !engine->config->use_syslog) {
380  ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
381  }
382  if (engine->config->working_dir &&
383  chdir(engine->config->working_dir) != 0) {
384  ods_log_error("[%s] setup: unable to chdir to %s (%s)", engine_str,
385  engine->config->working_dir, strerror(errno));
386  return ODS_STATUS_CHDIR_ERR;
387  }
388  if (engine_privdrop(engine) != ODS_STATUS_OK) {
389  return ODS_STATUS_PRIVDROP_ERR;
390  }
391  /* daemonize */
392  if (engine->daemonize) {
393  if (pipe(pipefd)) {
394  ods_log_error("[%s] unable to pipe: %s", engine_str, strerror(errno));
395  return ODS_STATUS_PIPE_ERR;
396  }
397  switch ((engine->pid = fork())) {
398  case -1: /* error */
399  ods_log_error("[%s] setup: unable to fork daemon (%s)",
400  engine_str, strerror(errno));
401  return ODS_STATUS_FORK_ERR;
402  case 0: /* child */
403  close(pipefd[0]);
404  break;
405  default: /* parent */
406  engine_cleanup(engine);
407  engine = NULL;
408  xmlCleanupParser();
409  xmlCleanupGlobals();
410  close(pipefd[1]);
411  while (read(pipefd[0], &buff, 1) != -1) {
412  if (buff <= 1) break;
413  printf("%c", buff);
414  }
415  close(pipefd[0]);
416  if (buff == '\1') {
417  ods_log_debug("[%s] signerd started successfully", engine_str);
418  exit(0);
419  }
420  ods_log_error("[%s] fail to start signerd completely", engine_str);
421  exit(1);
422  }
423  if (setsid() == -1) {
424  ods_log_error("[%s] setup: unable to setsid daemon (%s)",
425  engine_str, strerror(errno));
426  const char *err = "unable to setsid daemon: ";
427  ods_writen(pipefd[1], err, strlen(err));
428  ods_writeln(pipefd[1], strerror(errno));
429  write(pipefd[1], "\0", 1);
430  close(pipefd[1]);
431  return ODS_STATUS_SETSID_ERR;
432  }
433  }
434  engine->pid = getpid();
435  /* write pidfile */
436  if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
437  if (engine->daemonize) {
438  ods_writeln(pipefd[1], "Unable to write pid file");
439  write(pipefd[1], "\0", 1);
440  close(pipefd[1]);
441  }
442  return ODS_STATUS_WRITE_PIDFILE_ERR;
443  }
444  /* setup done */
445  ods_log_verbose("[%s] running as pid %lu", engine_str,
446  (unsigned long) engine->pid);
447  /* catch signals */
448  action.sa_handler = (void (*)(int))signal_handler;
449  sigfillset(&action.sa_mask);
450  action.sa_flags = 0;
451  sigaction(SIGTERM, &action, NULL);
452  sigaction(SIGHUP, &action, NULL);
453  sigaction(SIGINT, &action, NULL);
454  sigaction(SIGILL, &action, NULL);
455  sigaction(SIGUSR1, &action, NULL);
456  sigaction(SIGALRM, &action, NULL);
457  sigaction(SIGCHLD, &action, NULL);
458  action.sa_handler = SIG_IGN;
459  sigaction(SIGPIPE, &action, NULL);
460  /* create workers/drudgers */
461  engine_create_workers(engine);
462  /* start cmd/dns/xfr handlers */
463  engine_start_cmdhandler(engine);
464  engine_start_dnshandler(engine);
465  engine_start_xfrhandler(engine);
467  if (engine->daemonize) {
468  write(pipefd[1], "\1", 1);
469  close(pipefd[1]);
470  }
471  return ODS_STATUS_OK;
472 }
473 
474 
479 static void
480 engine_run(engine_type* engine)
481 {
482  if (!engine) {
483  return;
484  }
485  engine_start_workers(engine);
486 
487  while (!engine->need_to_exit && !engine->need_to_reload) {
488  /* We must use locking here to avoid race conditions. We want
489  * to sleep indefinitely and want to wake up on signal. This
490  * is to make sure we never mis the signal. */
491  pthread_mutex_lock(&engine->signal_lock);
492  if (!engine->need_to_exit && !engine->need_to_reload) {
493  /* TODO: this silly. We should be handling the commandhandler
494  * connections. No reason to spawn that as a thread.
495  * Also it would be easier to wake up the command hander
496  * as signals will reach it if it is the main thread! */
497  ods_log_debug("[%s] taking a break", engine_str);
498  pthread_cond_wait(&engine->signal_cond, &engine->signal_lock);
499  }
500  pthread_mutex_unlock(&engine->signal_lock);
501  }
502  ods_log_debug("[%s] signer halted", engine_str);
503  engine_stop_threads(engine);
504 }
505 
506 
511 static void
512 set_notify_ns(zone_type* zone, const char* cmd)
513 {
514  const char* str = NULL;
515  const char* str2 = NULL;
516  char* token = NULL;
517  ods_log_assert(cmd);
518  ods_log_assert(zone);
519  ods_log_assert(zone->name);
520  ods_log_assert(zone->adoutbound);
521  if (zone->adoutbound->type == ADAPTER_FILE) {
522  str = ods_replace(cmd, "%zonefile", zone->adoutbound->configstr);
523  if (!str) {
524  ods_log_error("[%s] unable to set notify ns: replace zonefile failed",
525  engine_str);
526  }
527  str2 = ods_replace(str, "%zone", zone->name);
528  free((void*)str);
529  } else {
530  str2 = ods_replace(cmd, "%zone", zone->name);
531  }
532  if (str2) {
533  ods_str_trim((char*) str2, 1);
534  str = str2;
535  if (*str) {
536  token = NULL;
537  while ((token = strtok((char*) str, " "))) {
538  if (*token) {
539  ods_str_list_add(&zone->notify_args, token);
540  }
541  str = NULL;
542  }
543  }
544  zone->notify_command = (char*) str2;
545  zone->notify_ns = zone->notify_args[0];
546  ods_log_debug("[%s] set notify ns: %s", engine_str, zone->notify_ns);
547  } else {
548  ods_log_error("[%s] unable to set notify ns: replace zone failed",
549  engine_str);
550  }
551 }
552 
553 
558 static int
559 dnsconfig_zone(engine_type* engine, zone_type* zone)
560 {
561  int numdns = 0;
562  ods_log_assert(engine);
563  ods_log_assert(engine->xfrhandler);
564  ods_log_assert(engine->xfrhandler->netio);
565  ods_log_assert(zone);
566  ods_log_assert(zone->adinbound);
567  ods_log_assert(zone->adoutbound);
568  ods_log_assert(zone->name);
569 
570  if (zone->adinbound->type == ADAPTER_DNS) {
571  /* zone transfer handler */
572  if (!zone->xfrd) {
573  ods_log_debug("[%s] add transfer handler for zone %s",
574  engine_str, zone->name);
575  zone->xfrd = xfrd_create((void*) engine->xfrhandler,
576  (void*) zone);
577  ods_log_assert(zone->xfrd);
579  &zone->xfrd->handler);
580  } else if (!zone->xfrd->serial_disk_acquired) {
581  xfrd_set_timer_now(zone->xfrd);
582  }
583  numdns++;
584  } else if (zone->xfrd) {
586  &zone->xfrd->handler);
587  xfrd_cleanup(zone->xfrd, 0);
588  zone->xfrd = NULL;
589  }
590  if (zone->adoutbound->type == ADAPTER_DNS) {
591  /* notify handler */
592  if (!zone->notify) {
593  ods_log_debug("[%s] add notify handler for zone %s",
594  engine_str, zone->name);
595  zone->notify = notify_create((void*) engine->xfrhandler,
596  (void*) zone);
597  ods_log_assert(zone->notify);
599  &zone->notify->handler);
600  }
601  numdns++;
602  } else if (zone->notify) {
604  &zone->notify->handler);
605  notify_cleanup(zone->notify);
606  zone->notify = NULL;
607  }
608  return numdns;
609 }
610 
611 
616 void
617 engine_update_zones(engine_type* engine, ods_status zl_changed)
618 {
619  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
620  zone_type* zone = NULL;
621  ods_status status = ODS_STATUS_OK;
622  unsigned wake_up = 0;
623  int warnings = 0;
624 
625  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
626  return;
627  }
628 
629  ods_log_debug("[%s] commit zone list changes", engine_str);
630  pthread_mutex_lock(&engine->zonelist->zl_lock);
631  node = ldns_rbtree_first(engine->zonelist->zones);
632  while (node && node != LDNS_RBTREE_NULL) {
633  zone = (zone_type*) node->data;
634 
635  if (zone->zl_status == ZONE_ZL_REMOVED) {
636  node = ldns_rbtree_next(node);
637  pthread_mutex_lock(&zone->zone_lock);
638  zonelist_del_zone(engine->zonelist, zone);
639  schedule_unscheduletask(engine->taskq, schedule_WHATEVER, zone->name);
640  pthread_mutex_unlock(&zone->zone_lock);
642  &zone->xfrd->handler);
643  zone_cleanup(zone);
644  zone = NULL;
645  continue;
646  } else if (zone->zl_status == ZONE_ZL_ADDED) {
647  pthread_mutex_lock(&zone->zone_lock);
648  /* set notify nameserver command */
649  if (engine->config->notify_command && !zone->notify_ns) {
650  set_notify_ns(zone, engine->config->notify_command);
651  }
652  pthread_mutex_unlock(&zone->zone_lock);
653  }
654  /* load adapter config */
655  status = adapter_load_config(zone->adinbound);
656  if (status != ODS_STATUS_OK) {
657  ods_log_error("[%s] unable to load config for inbound adapter "
658  "for zone %s: %s", engine_str, zone->name,
659  ods_status2str(status));
660  }
661  status = adapter_load_config(zone->adoutbound);
662  if (status != ODS_STATUS_OK) {
663  ods_log_error("[%s] unable to load config for outbound adapter "
664  "for zone %s: %s", engine_str, zone->name,
665  ods_status2str(status));
666  }
667  /* for dns adapters */
668  warnings += dnsconfig_zone(engine, zone);
669 
670  if (zone->zl_status == ZONE_ZL_ADDED) {
671  schedule_scheduletask(engine->taskq, TASK_SIGNCONF, zone->name, zone, &zone->zone_lock, 0);
672  } else if (zl_changed == ODS_STATUS_OK) {
673  schedule_scheduletask(engine->taskq, TASK_FORCESIGNCONF, zone->name, zone, &zone->zone_lock, 0);
674  }
675  if (status != ODS_STATUS_OK) {
676  ods_log_crit("[%s] unable to schedule task for zone %s: %s",
677  engine_str, zone->name, ods_status2str(status));
678  } else {
679  wake_up = 1;
680  zone->zl_status = ZONE_ZL_OK;
681  }
682  node = ldns_rbtree_next(node);
683  }
684  pthread_mutex_unlock(&engine->zonelist->zl_lock);
685  if (engine->dnshandler) {
686  ods_log_debug("[%s] forward notify for all zones", engine_str);
688  (uint8_t*) ODS_SE_NOTIFY_CMD, strlen(ODS_SE_NOTIFY_CMD));
689  } else if (warnings) {
690  ods_log_warning("[%s] no dnshandler/listener configured, but zones "
691  "are configured with dns adapters: notify and zone transfer "
692  "requests will not work properly", engine_str);
693  }
694  if (wake_up) {
695  engine_wakeup_workers(engine);
696  }
697 }
698 
699 
704 static ods_status
705 engine_recover(engine_type* engine)
706 {
707  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
708  zone_type* zone = NULL;
709  ods_status status = ODS_STATUS_OK;
710  ods_status result = ODS_STATUS_UNCHANGED;
711 
712  if (!engine || !engine->zonelist || !engine->zonelist->zones) {
713  ods_log_error("[%s] cannot recover zones: no engine or zonelist",
714  engine_str);
715  return ODS_STATUS_ERR; /* no need to update zones */
716  }
717  ods_log_assert(engine);
718  ods_log_assert(engine->zonelist);
719  ods_log_assert(engine->zonelist->zones);
720 
721  pthread_mutex_lock(&engine->zonelist->zl_lock);
722  /* [LOCK] zonelist */
723  node = ldns_rbtree_first(engine->zonelist->zones);
724  while (node && node != LDNS_RBTREE_NULL) {
725  zone = (zone_type*) node->data;
726 
727  ods_log_assert(zone->zl_status == ZONE_ZL_ADDED);
728  pthread_mutex_lock(&zone->zone_lock);
729  status = zone_recover2(engine, zone);
730  if (status == ODS_STATUS_OK) {
731  ods_log_assert(zone->db);
732  ods_log_assert(zone->signconf);
733  /* notify nameserver */
734  if (engine->config->notify_command && !zone->notify_ns) {
735  set_notify_ns(zone, engine->config->notify_command);
736  }
737  if (status != ODS_STATUS_OK) {
738  ods_log_crit("[%s] unable to schedule task for zone %s: %s",
739  engine_str, zone->name, ods_status2str(status));
740  result = ODS_STATUS_OK; /* will trigger update zones */
741  } else {
742  ods_log_debug("[%s] recovered zone %s", engine_str,
743  zone->name);
744  /* recovery done */
745  zone->zl_status = ZONE_ZL_OK;
746  }
747  } else {
748  if (status != ODS_STATUS_UNCHANGED) {
749  ods_log_warning("[%s] unable to recover zone %s from backup,"
750  " performing full sign", engine_str, zone->name);
751  }
752  result = ODS_STATUS_OK; /* will trigger update zones */
753  }
754  pthread_mutex_unlock(&zone->zone_lock);
755  node = ldns_rbtree_next(node);
756  }
757  /* [UNLOCK] zonelist */
758  pthread_mutex_unlock(&engine->zonelist->zl_lock);
759  return result;
760 }
761 
762 
767 int
768 engine_start(const char* cfgfile, int cmdline_verbosity, int daemonize, int info)
769 {
770  ods_status zl_changed = ODS_STATUS_UNCHANGED;
771  ods_status status = ODS_STATUS_OK;
772 
773  engine = engine_create();
774  if (!engine) {
775  ods_fatal_exit("[%s] create failed", engine_str);
776  return 1;
777  }
778  engine->daemonize = daemonize;
779 
780  /* config */
781  engine->config = engine_config(cfgfile, cmdline_verbosity);
782  status = engine_config_check(engine->config);
783  if (status != ODS_STATUS_OK) {
784  ods_log_error("[%s] cfgfile %s has errors", engine_str, cfgfile);
785  goto earlyexit;
786  }
787  if (info) {
788  char* stacktrace;
789  char* stacktraceptr;
790  stacktrace = janitor_backtrace_string();
791  stacktraceptr = strchr(stacktrace,'\n');
792  if(stacktraceptr)
793  *stacktraceptr = '\0';
794  stacktraceptr = stacktrace;
795  while(*stacktraceptr && isspace(*stacktraceptr))
796  ++stacktraceptr;
797  fprintf(stdout, "Stacktrace check: %s\n",stacktraceptr);
798  free(stacktrace);
799  fprintf(stdout, "Configuration:\n");
800  engine_config_print(stdout, engine->config); /* for debugging */
801  goto earlyexit;
802  }
803  /* check pidfile */
804  if (!util_check_pidfile(engine->config->pid_filename)) {
805  exit(1);
806  }
807  /* setup */
808  status = engine_setup();
809  if (status != ODS_STATUS_OK) {
810  ods_log_error("[%s] setup failed: %s", engine_str,
811  ods_status2str(status));
812  goto earlyexit;
813  }
814 
815  /* run */
816  while (engine->need_to_exit == 0) {
817  /* update zone list */
818  pthread_mutex_lock(&engine->zonelist->zl_lock);
819  zl_changed = zonelist_update(engine->zonelist,
820  engine->config->zonelist_filename);
821  engine->zonelist->just_removed = 0;
822  engine->zonelist->just_added = 0;
823  engine->zonelist->just_updated = 0;
824  pthread_mutex_unlock(&engine->zonelist->zl_lock);
825  /* start/reload */
826  if (engine->need_to_reload) {
827  ods_log_info("[%s] signer reloading", engine_str);
828  engine->need_to_reload = 0;
829  } else {
830  ods_log_info("[%s] signer started (version %s), pid %u",
831  engine_str, PACKAGE_VERSION, engine->pid);
832  if (hsm_open2(engine->config->repositories, hsm_check_pin) != HSM_OK) {
833  char* error = hsm_get_error(NULL);
834  if (error != NULL) {
835  ods_log_error("[%s] %s", "hsm", error);
836  free(error);
837  }
838  ods_log_error("[%s] opening hsm failed (for engine recover)", engine_str);
839  break;
840  }
841  zl_changed = engine_recover(engine);
842  hsm_close();
843  }
844  if (zl_changed == ODS_STATUS_OK ||
845  zl_changed == ODS_STATUS_UNCHANGED) {
846  engine_update_zones(engine, zl_changed);
847  }
848  if (hsm_open2(engine->config->repositories, hsm_check_pin) != HSM_OK) {
849  char* error = hsm_get_error(NULL);
850  if (error != NULL) {
851  ods_log_error("[%s] %s", "hsm", error);
852  free(error);
853  }
854  ods_log_error("[%s] opening hsm failed (for engine run)", engine_str);
855  break;
856  }
857  engine_run(engine);
858  hsm_close();
859  }
860 
861  /* shutdown */
862  ods_log_info("[%s] signer shutdown", engine_str);
863  cmdhandler_stop(engine->cmdhandler);
864  engine_stop_xfrhandler(engine);
865  engine_stop_dnshandler(engine);
866 
867 earlyexit:
868  if (engine && engine->config) {
869  if (engine->config->pid_filename) {
870  (void)unlink(engine->config->pid_filename);
871  }
872  if (engine->config->clisock_filename) {
873  (void)unlink(engine->config->clisock_filename);
874  }
875  }
877  engine_cleanup(engine);
878  engine = NULL;
879 
880  return status;
881 }
882 
883 
888 void
890 {
891  int i;
892  int numTotalWorkers;
893 
894  if (!engine) {
895  return;
896  }
897  if (engine->config) {
898  numTotalWorkers = engine->config->num_worker_threads + engine->config->num_signer_threads;
899  if (engine->workers) {
900  for (i=0; i < (size_t) numTotalWorkers; i++) {
901  worker_cleanup(engine->workers[i]);
902  }
903  free(engine->workers);
904  }
905  zonelist_cleanup(engine->zonelist);
906  schedule_cleanup(engine->taskq);
907  cmdhandler_cleanup(engine->cmdhandler);
910  engine_config_cleanup(engine->config);
911  pthread_mutex_destroy(&engine->signal_lock);
912  pthread_cond_destroy(&engine->signal_cond);
913  }
914  free(engine);
915 }
ods_status adapter_load_config(adapter_type *adapter)
Definition: adapter.c:99
@ ADAPTER_DNS
Definition: adapter.h:42
@ ADAPTER_FILE
Definition: adapter.h:41
engineconfig_type * engine_config(const char *cfgfile, int cmdline_verbosity)
Definition: cfg.c:51
void engine_config_cleanup(engineconfig_type *config)
Definition: cfg.c:243
void engine_config_print(FILE *out, engineconfig_type *config)
Definition: cfg.c:146
ods_status engine_config_check(engineconfig_type *config)
Definition: cfg.c:110
void dnshandler_signal(dnshandler_type *dnshandler)
Definition: dnshandler.c:218
ods_status dnshandler_listen(dnshandler_type *dnshandler)
Definition: dnshandler.c:106
void dnshandler_start(dnshandler_type *dnshandler)
Definition: dnshandler.c:125
void dnshandler_cleanup(dnshandler_type *dnshandler)
Definition: dnshandler.c:277
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
Definition: dnshandler.c:231
dnshandler_type * dnshandler_create(listener_type *interfaces)
Definition: dnshandler.c:51
#define ODS_SE_NOTIFY_CMD
Definition: dnshandler.h:48
void edns_init(edns_data_type *data, uint16_t max_length)
Definition: edns.c:64
#define EDNS_MAX_MESSAGE_LEN
Definition: edns.h:47
void engine_wakeup_workers(engine_type *engine)
Definition: engine.c:291
void engine_cleanup(engine_type *engine)
Definition: engine.c:889
int engine_start(const char *cfgfile, int cmdline_verbosity, int daemonize, int info)
Definition: engine.c:768
void engine_update_zones(engine_type *engine, ods_status zl_changed)
Definition: engine.c:617
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:72
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:53
notify_type * notify_create(xfrhandler_type *xfrhandler, zone_type *zone)
Definition: notify.c:100
void notify_cleanup(notify_type *notify)
Definition: notify.c:600
struct cmd_func_block ** signercommands
time_t do_forcereadzone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:388
time_t do_readzone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:343
void drudge(worker_type *worker)
Definition: signertasks.c:152
time_t do_forcereadsignconf(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:239
time_t do_readsignconf(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:209
time_t do_signzone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:268
time_t do_writezone(task_type *task, const char *zonename, void *zonearg, void *contextarg)
Definition: signertasks.c:426
adapter_mode type
Definition: adapter.h:58
const char * configstr
Definition: adapter.h:60
netio_handler_type xfrhandler
Definition: dnshandler.h:58
janitor_thread_t thread_id
Definition: dnshandler.h:52
engine_type * engine
Definition: dnshandler.h:53
unsigned need_to_exit
Definition: dnshandler.h:59
edns_data_type edns
Definition: engine.h:72
zonelist_type * zonelist
Definition: engine.h:69
schedule_type * taskq
Definition: engine.h:54
xfrhandler_type * xfrhandler
Definition: engine.h:71
pthread_mutex_t signal_lock
Definition: engine.h:67
pid_t pid
Definition: engine.h:57
gid_t gid
Definition: engine.h:59
cmdhandler_type * cmdhandler
Definition: engine.h:55
pthread_cond_t signal_cond
Definition: engine.h:66
int need_to_reload
Definition: engine.h:63
int daemonize
Definition: engine.h:61
uid_t uid
Definition: engine.h:58
int need_to_exit
Definition: engine.h:62
dnshandler_type * dnshandler
Definition: engine.h:70
worker_type ** workers
Definition: engine.h:53
engineconfig_type * config
Definition: engine.h:52
const char * chroot
Definition: cfg.h:57
listener_type * interfaces
Definition: cfg.h:46
const char * notify_command
Definition: cfg.h:52
const char * group
Definition: cfg.h:56
const char * clisock_filename
Definition: cfg.h:53
const char * working_dir
Definition: cfg.h:54
hsm_repository_t * repositories
Definition: cfg.h:47
int num_worker_threads
Definition: cfg.h:59
int use_syslog
Definition: cfg.h:58
const char * pid_filename
Definition: cfg.h:51
const char * zonelist_filename
Definition: cfg.h:49
const char * log_filename
Definition: cfg.h:50
int num_signer_threads
Definition: cfg.h:60
const char * username
Definition: cfg.h:55
netio_handler_type handler
Definition: notify.h:63
worker_type * worker
Definition: signertasks.h:40
engine_type * engine
Definition: signertasks.h:39
fifoq_type * signq
Definition: signertasks.h:41
time_t serial_disk_acquired
Definition: xfrd.h:118
netio_handler_type handler
Definition: xfrd.h:124
netio_type * netio
Definition: xfrhandler.h:60
unsigned started
Definition: xfrhandler.h:73
janitor_thread_t thread_id
Definition: xfrhandler.h:54
engine_type * engine
Definition: xfrhandler.h:55
unsigned need_to_exit
Definition: xfrhandler.h:72
netio_handler_type dnshandler
Definition: xfrhandler.h:70
char * notify_command
Definition: zone.h:65
signconf_type * signconf
Definition: zone.h:77
notify_type * notify
Definition: zone.h:83
char ** notify_args
Definition: zone.h:67
const char * notify_ns
Definition: zone.h:66
namedb_type * db
Definition: zone.h:79
adapter_type * adinbound
Definition: zone.h:74
zone_zl_status zl_status
Definition: zone.h:72
xfrd_type * xfrd
Definition: zone.h:82
const char * name
Definition: zone.h:69
pthread_mutex_t zone_lock
Definition: zone.h:86
adapter_type * adoutbound
Definition: zone.h:75
int just_updated
Definition: zonelist.h:48
int just_removed
Definition: zonelist.h:49
pthread_mutex_t zl_lock
Definition: zonelist.h:50
ldns_rbtree_t * zones
Definition: zonelist.h:45
ods_status tsig_handler_init()
Definition: tsig.c:116
void tsig_handler_cleanup(void)
Definition: tsig.c:135
xfrd_type * xfrd_create(xfrhandler_type *xfrhandler, zone_type *zone)
Definition: xfrd.c:315
void xfrd_set_timer_now(xfrd_type *xfrd)
Definition: xfrd.c:454
void xfrd_cleanup(xfrd_type *xfrd, int backup)
Definition: xfrd.c:2180
void xfrhandler_cleanup(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:198
void xfrhandler_start(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:110
xfrhandler_type * xfrhandler_create()
Definition: xfrhandler.c:52
void xfrhandler_signal(xfrhandler_type *xfrhandler)
Definition: xfrhandler.c:159
void zone_cleanup(zone_type *zone)
Definition: zone.c:759
ods_status zone_recover2(engine_type *engine, zone_type *zone)
Definition: zone.c:792
@ ZONE_ZL_REMOVED
Definition: zone.h:37
@ ZONE_ZL_ADDED
Definition: zone.h:35
@ ZONE_ZL_OK
Definition: zone.h:34
void zonelist_del_zone(zonelist_type *zlist, zone_type *zone)
Definition: zonelist.c:238
ods_status zonelist_update(zonelist_type *zl, const char *zlfile)
Definition: zonelist.c:342
void zonelist_cleanup(zonelist_type *zl)
Definition: zonelist.c:432
zonelist_type * zonelist_create()
Definition: zonelist.c:74