OpenDNSSEC-signer  1.4.1
tools.c
Go to the documentation of this file.
1 /*
2  * $Id: tools.c 7154 2013-06-13 13:56:19Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "daemon/dnshandler.h"
36 #include "adapter/adapter.h"
37 #include "shared/log.h"
38 #include "signer/tools.h"
39 #include "signer/zone.h"
40 
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <unistd.h>
45 
46 static const char* tools_str = "tools";
47 
48 
55 {
56  ods_status status = ODS_STATUS_OK;
57  signconf_type* new_signconf = NULL;
58  task_id denial_what = TASK_NONE;
59 
60  ods_log_assert(zone);
61  ods_log_assert(zone->name);
62  status = zone_load_signconf(zone, &new_signconf);
63  if (status == ODS_STATUS_OK) {
64  ods_log_assert(new_signconf);
65  /* Denial of Existence Rollover? */
66  denial_what = signconf_compare_denial(zone->signconf, new_signconf);
67  if (denial_what == TASK_NSECIFY) {
68  /* or NSEC -> NSEC3, or NSEC3 -> NSEC, or NSEC3PARAM changed */
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  ods_log_error("[%s] unable to read zone %s: adapter failed (%s)",
138  tools_str, zone->name, ods_status2str(status));
139  zone_rollback_dnskeys(zone);
141  namedb_rollback(zone->db, 0);
142  }
143  end = time(NULL);
144  if ((status == ODS_STATUS_OK || status == ODS_STATUS_UNCHANGED)
145  && zone->stats) {
147  zone->stats->start_time = start;
148  zone->stats->sort_time = (end-start);
149  zone->stats->sort_done = 1;
151  }
152  return status;
153 }
154 
155 
160 static void
161 ods_closeall(int fd)
162 {
163  int fdlimit = sysconf(_SC_OPEN_MAX);
164  while (fd < fdlimit) {
165  close(fd++);
166  }
167  return;
168 }
169 
170 
177 {
178  ods_status status = ODS_STATUS_OK;
179  ods_log_assert(engine);
180  ods_log_assert(engine->config);
181  ods_log_assert(zone);
182  ods_log_assert(zone->db);
183  ods_log_assert(zone->name);
184  ods_log_assert(zone->signconf);
185  ods_log_assert(zone->adoutbound);
186  /* prepare */
187  if (zone->stats) {
189  if (zone->stats->sort_done == 0 &&
190  (zone->stats->sig_count <= zone->stats->sig_soa_count)) {
191  ods_log_verbose("[%s] skip write zone %s serial %u (zone not "
192  "changed)", tools_str, zone->name?zone->name:"(null)",
193  zone->db->intserial);
194  stats_clear(zone->stats);
196  zone->db->intserial =
197  zone->db->outserial;
198  return ODS_STATUS_OK;
199  }
201  }
202  /* Output Adapter */
203  status = adapter_write((void*)zone);
204  if (status != ODS_STATUS_OK) {
205  ods_log_error("[%s] unable to write zone %s: adapter failed (%s)",
206  tools_str, zone->name, ods_status2str(status));
207  return status;
208  }
209  zone->db->outserial = zone->db->intserial;
210  zone->db->is_initialized = 1;
211  lock_basic_lock(&zone->ixfr->ixfr_lock);
212  ixfr_purge(zone->ixfr);
214  /* kick the nameserver */
215  if (zone->notify_ns) {
216  int status;
217  pid_t pid, wpid;
218  ods_log_verbose("[%s] notify nameserver: %s", tools_str,
219  zone->notify_ns);
221  switch ((pid = fork())) {
222  case -1: /* error */
223  ods_log_error("[%s] notify nameserver failed: unable to fork "
224  "(%s)", tools_str, strerror(errno));
225  return ODS_STATUS_FORK_ERR;
226  case 0: /* child */
228  ods_closeall(0);
230  execvp(zone->notify_ns, zone->notify_args);
232  ods_log_error("[%s] notify nameserver failed: execv() failed "
233  "(%s)", tools_str, strerror(errno));
234  exit(1);
235  break;
236  default: /* parent */
237  ods_log_debug("[%s] notify nameserver process forked",
238  tools_str);
240  while((wpid = waitpid(pid, &status, 0)) <= 0) {
241  if (errno != EINTR) {
242  break;
243  }
244  }
245  if (wpid == -1) {
246  ods_log_error("[%s] notify nameserver failed: waitpid() ",
247  "failed (%s)", tools_str, strerror(errno));
248  } else if (!WIFEXITED(status)) {
249  ods_log_error("[%s] notify nameserver failed: notify ",
250  "command did not terminate normally", tools_str);
251  } else {
252  ods_log_verbose("[%s] notify nameserver ok", tools_str);
253  }
254  break;
255  }
256  }
257  if (engine->dnshandler) {
259  strlen(ODS_SE_NOTIFY_CMD));
260  }
261  /* log stats */
262  if (zone->stats) {
264  zone->stats->end_time = time(NULL);
265  ods_log_debug("[%s] log stats for zone %s", tools_str,
266  zone->name?zone->name:"(null)");
267  stats_log(zone->stats, zone->name, zone->signconf->nsec_type);
268  stats_clear(zone->stats);
270  }
271  return status;
272 }