OpenDNSSEC-signer  1.4.5
tools.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/dnshandler.h"
34 #include "adapter/adapter.h"
35 #include "shared/log.h"
36 #include "signer/tools.h"
37 #include "signer/zone.h"
38 
39 #include <errno.h>
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <unistd.h>
43 
44 static const char* tools_str = "tools";
45 
46 
53 {
54  ods_status status = ODS_STATUS_OK;
55  signconf_type* new_signconf = NULL;
56 
57  ods_log_assert(zone);
58  ods_log_assert(zone->name);
59  status = zone_load_signconf(zone, &new_signconf);
60  if (status == ODS_STATUS_OK) {
61  ods_log_assert(new_signconf);
62  /* Denial of Existence Rollover? */
63  if (signconf_compare_denial(zone->signconf, new_signconf)
64  == TASK_NSECIFY) {
69  namedb_wipe_denial(zone->db);
71  namedb_init_denials(zone->db);
72  }
73  /* all ok, switch signer configuration */
75  ods_log_debug("[%s] zone %s switch to new signconf", tools_str,
76  zone->name);
77  zone->signconf = new_signconf;
78  signconf_log(zone->signconf, zone->name);
79  zone->default_ttl = (uint32_t) duration2time(zone->signconf->soa_min);
80  } else if (status != ODS_STATUS_UNCHANGED) {
81  ods_log_error("[%s] unable to load signconf for zone %s: %s",
82  tools_str, zone->name, ods_status2str(status));
83  }
84  return status;
85 }
86 
87 
94 {
95  ods_status status = ODS_STATUS_OK;
96  time_t start = 0;
97  time_t end = 0;
98 
99  ods_log_assert(zone);
100  ods_log_assert(zone->name);
101  ods_log_assert(zone->adinbound);
102  ods_log_assert(zone->signconf);
103  /* Key Rollover? */
104  status = zone_publish_dnskeys(zone);
105  if (status != ODS_STATUS_OK) {
106  ods_log_error("[%s] unable to read zone %s: failed to "
107  "publish dnskeys (%s)", tools_str, zone->name,
108  ods_status2str(status));
109  zone_rollback_dnskeys(zone);
111  namedb_rollback(zone->db, 0);
112  return status;
113  }
114  /* Denial of Existence Rollover? */
115  status = zone_publish_nsec3param(zone);
116  if (status != ODS_STATUS_OK) {
117  ods_log_error("[%s] unable to read zone %s: failed to "
118  "publish nsec3param (%s)", tools_str, zone->name,
119  ods_status2str(status));
120  zone_rollback_dnskeys(zone);
122  namedb_rollback(zone->db, 0);
123  return status;
124  }
125 
126  if (zone->stats) {
128  zone->stats->sort_done = 0;
129  zone->stats->sort_count = 0;
130  zone->stats->sort_time = 0;
132  }
133  /* Input Adapter */
134  start = time(NULL);
135  status = adapter_read((void*)zone);
136  if (status != ODS_STATUS_OK && status != ODS_STATUS_UNCHANGED) {
137  if (status == ODS_STATUS_XFRINCOMPLETE) {
138  ods_log_info("[%s] read zone %s: xfr in progress",
139  tools_str, zone->name);
140  } else {
141  ods_log_error("[%s] unable to read zone %s: adapter failed (%s)",
142  tools_str, zone->name, ods_status2str(status));
143  }
144  zone_rollback_dnskeys(zone);
146  namedb_rollback(zone->db, 0);
147  }
148  end = time(NULL);
149  if ((status == ODS_STATUS_OK || status == ODS_STATUS_UNCHANGED)
150  && zone->stats) {
152  zone->stats->start_time = start;
153  zone->stats->sort_time = (end-start);
154  zone->stats->sort_done = 1;
156  }
157  return status;
158 }
159 
160 
165 static void
166 ods_closeall(int fd)
167 {
168  int fdlimit = sysconf(_SC_OPEN_MAX);
169  while (fd < fdlimit) {
170  close(fd++);
171  }
172  return;
173 }
174 
175 
182 {
183  ods_status status = ODS_STATUS_OK;
184  ods_log_assert(engine);
185  ods_log_assert(engine->config);
186  ods_log_assert(zone);
187  ods_log_assert(zone->db);
188  ods_log_assert(zone->name);
189  ods_log_assert(zone->signconf);
190  ods_log_assert(zone->adoutbound);
191  /* prepare */
192  if (zone->stats) {
194  if (zone->stats->sort_done == 0 &&
195  (zone->stats->sig_count <= zone->stats->sig_soa_count)) {
196  ods_log_verbose("[%s] skip write zone %s serial %u (zone not "
197  "changed)", tools_str, zone->name?zone->name:"(null)",
198  zone->db->intserial);
199  stats_clear(zone->stats);
201  zone->db->intserial =
202  zone->db->outserial;
203  return ODS_STATUS_OK;
204  }
206  }
207  /* Output Adapter */
208  status = adapter_write((void*)zone);
209  if (status != ODS_STATUS_OK) {
210  ods_log_error("[%s] unable to write zone %s: adapter failed (%s)",
211  tools_str, zone->name, ods_status2str(status));
212  return status;
213  }
214  zone->db->outserial = zone->db->intserial;
215  zone->db->is_initialized = 1;
216  zone->db->have_serial = 1;
217  lock_basic_lock(&zone->ixfr->ixfr_lock);
218  ixfr_purge(zone->ixfr);
220  /* kick the nameserver */
221  if (zone->notify_ns) {
222  int status;
223  pid_t pid, wpid;
224  ods_log_verbose("[%s] notify nameserver: %s", tools_str,
225  zone->notify_ns);
227  switch ((pid = fork())) {
228  case -1: /* error */
229  ods_log_error("[%s] notify nameserver failed: unable to fork "
230  "(%s)", tools_str, strerror(errno));
231  return ODS_STATUS_FORK_ERR;
232  case 0: /* child */
234  ods_closeall(0);
236  execvp(zone->notify_ns, zone->notify_args);
238  ods_log_error("[%s] notify nameserver failed: execv() failed "
239  "(%s)", tools_str, strerror(errno));
240  exit(1);
241  break;
242  default: /* parent */
243  ods_log_debug("[%s] notify nameserver process forked",
244  tools_str);
246  while((wpid = waitpid(pid, &status, 0)) <= 0) {
247  if (errno != EINTR) {
248  break;
249  }
250  }
251  if (wpid == -1) {
252  ods_log_error("[%s] notify nameserver failed: waitpid() ",
253  "failed (%s)", tools_str, strerror(errno));
254  } else if (!WIFEXITED(status)) {
255  ods_log_error("[%s] notify nameserver failed: notify ",
256  "command did not terminate normally", tools_str);
257  } else {
258  ods_log_verbose("[%s] notify nameserver ok", tools_str);
259  }
260  break;
261  }
262  }
263  /* log stats */
264  if (zone->stats) {
266  zone->stats->end_time = time(NULL);
267  ods_log_debug("[%s] log stats for zone %s serial %u", tools_str,
268  zone->name?zone->name:"(null)", (unsigned) zone->db->outserial);
269  stats_log(zone->stats, zone->name, zone->db->outserial,
270  zone->signconf->nsec_type);
271  stats_clear(zone->stats);
273  }
274  if (engine->dnshandler) {
276  strlen(ODS_SE_NOTIFY_CMD));
277  }
278  return status;
279 }