tools.c
Go to the documentation of this file.
/*
* Copyright (c) 2009 NLNet Labs. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#include "daemon/dnshandler.h"
#include "adapter/adapter.h"
#include "log.h"
#include "signer/tools.h"
#include "signer/zone.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
static const char* tools_str = "tools";
ods_status
tools_signconf(zone_type* zone)
{
ods_status status = ODS_STATUS_OK;
signconf_type* new_signconf = NULL;
ods_log_assert(zone);
ods_log_assert(zone->name);
status = zone_load_signconf(zone, &new_signconf);
if (status == ODS_STATUS_OK) {
ods_log_assert(new_signconf);
/* Denial of Existence Rollover? */
if (signconf_compare_denial(zone->signconf, new_signconf)
== TASK_NSECIFY) {
namedb_wipe_denial(zone->db);
namedb_cleanup_denials(zone->db);
namedb_init_denials(zone->db);
}
/* all ok, switch signer configuration */
signconf_cleanup(zone->signconf);
ods_log_debug("[%s] zone %s switch to new signconf", tools_str,
zone->name);
zone->signconf = new_signconf;
signconf_log(zone->signconf, zone->name);
zone->default_ttl = (uint32_t) duration2time(zone->signconf->soa_min);
} else if (status != ODS_STATUS_UNCHANGED) {
ods_log_error("[%s] unable to load signconf for zone %s: %s",
tools_str, zone->name, ods_status2str(status));
}
return status;
}
ods_status
tools_input(zone_type* zone)
{
ods_status status = ODS_STATUS_OK;
time_t start = 0;
time_t end = 0;
ods_log_assert(zone);
ods_log_assert(zone->name);
ods_log_assert(zone->adinbound);
ods_log_assert(zone->signconf);
/* Key Rollover? */
status = zone_publish_dnskeys(zone, 0);
if (status != ODS_STATUS_OK) {
ods_log_error("[%s] unable to read zone %s: failed to "
"publish dnskeys (%s)", tools_str, zone->name,
ods_status2str(status));
zone_rollback_dnskeys(zone);
zone_rollback_nsec3param(zone);
namedb_rollback(zone->db, 0);
return status;
}
/* Denial of Existence Rollover? */
if (!zone->signconf->passthrough)
status = zone_publish_nsec3param(zone);
if (status != ODS_STATUS_OK) {
ods_log_error("[%s] unable to read zone %s: failed to "
"publish nsec3param (%s)", tools_str, zone->name,
ods_status2str(status));
zone_rollback_dnskeys(zone);
zone_rollback_nsec3param(zone);
namedb_rollback(zone->db, 0);
return status;
}
if (zone->stats) {
pthread_mutex_lock(&zone->stats->stats_lock);
zone->stats->sort_done = 0;
zone->stats->sort_count = 0;
zone->stats->sort_time = 0;
pthread_mutex_unlock(&zone->stats->stats_lock);
}
/* Input Adapter */
start = time(NULL);
status = adapter_read((void*)zone);
if (status != ODS_STATUS_OK && status != ODS_STATUS_UNCHANGED) {
if (status == ODS_STATUS_XFRINCOMPLETE) {
ods_log_info("[%s] read zone %s: xfr in progress",
tools_str, zone->name);
} else {
ods_log_error("[%s] unable to read zone %s: adapter failed (%s)",
tools_str, zone->name, ods_status2str(status));
}
zone_rollback_dnskeys(zone);
zone_rollback_nsec3param(zone);
namedb_rollback(zone->db, 0);
}
end = time(NULL);
if ((status == ODS_STATUS_OK || status == ODS_STATUS_UNCHANGED)
&& zone->stats) {
pthread_mutex_lock(&zone->stats->stats_lock);
zone->stats->start_time = start;
zone->stats->sort_time = (end-start);
zone->stats->sort_done = 1;
pthread_mutex_unlock(&zone->stats->stats_lock);
}
return status;
}
static void
ods_closeall(int fd)
{
int fdlimit = sysconf(_SC_OPEN_MAX);
while (fd < fdlimit) {
close(fd++);
}
}
ods_status
tools_output(zone_type* zone, engine_type* engine)
{
ods_status status = ODS_STATUS_OK;
ods_log_assert(engine);
ods_log_assert(engine->config);
ods_log_assert(zone);
ods_log_assert(zone->db);
ods_log_assert(zone->name);
ods_log_assert(zone->signconf);
ods_log_assert(zone->adoutbound);
/* prepare */
if (zone->stats) {
pthread_mutex_lock(&zone->stats->stats_lock);
if (zone->stats->sort_done == 0 &&
(zone->stats->sig_count <= zone->stats->sig_soa_count)) {
ods_log_verbose("[%s] skip write zone %s serial %u (zone not "
"changed)", tools_str, zone->name?zone->name:"(null)",
zone->db->intserial);
stats_clear(zone->stats);
pthread_mutex_unlock(&zone->stats->stats_lock);
zone->db->intserial =
zone->db->outserial;
return ODS_STATUS_OK;
}
pthread_mutex_unlock(&zone->stats->stats_lock);
}
/* Output Adapter */
status = adapter_write((void*)zone);
if (status != ODS_STATUS_OK) {
ods_log_error("[%s] unable to write zone %s: adapter failed (%s)",
tools_str, zone->name, ods_status2str(status));
return status;
}
zone->db->outserial = zone->db->intserial;
zone->db->is_initialized = 1;
zone->db->have_serial = 1;
pthread_mutex_lock(&zone->ixfr->ixfr_lock);
ixfr_purge(zone->ixfr, zone->name);
pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
/* kick the nameserver */
if (zone->notify_ns) {
int pid_status;
pid_t pid, wpid;
ods_log_verbose("[%s] notify nameserver: %s", tools_str,
zone->notify_ns);
switch ((pid = fork())) {
case -1: /* error */
ods_log_error("[%s] notify nameserver failed: unable to fork "
"(%s)", tools_str, strerror(errno));
return ODS_STATUS_FORK_ERR;
case 0: /* child */
ods_closeall(0);
execvp(zone->notify_ns, zone->notify_args);
ods_log_error("[%s] notify nameserver failed: execv() failed "
"(%s)", tools_str, strerror(errno));
exit(1);
break;
default: /* parent */
ods_log_debug("[%s] notify nameserver process forked",
tools_str);
while((wpid = waitpid(pid, &pid_status, 0)) <= 0) {
if (errno != EINTR) {
break;
}
}
if (wpid == -1) {
ods_log_error("[%s] notify nameserver failed: waitpid() "
"failed (%s)", tools_str, strerror(errno));
} else if (!WIFEXITED(pid_status)) {
ods_log_error("[%s] notify nameserver failed: notify "
"command did not terminate normally", tools_str);
} else {
ods_log_verbose("[%s] notify nameserver ok", tools_str);
}
break;
}
}
/* log stats */
if (zone->stats) {
pthread_mutex_lock(&zone->stats->stats_lock);
zone->stats->end_time = time(NULL);
ods_log_debug("[%s] log stats for zone %s serial %u", tools_str,
zone->name?zone->name:"(null)", (unsigned) zone->db->outserial);
stats_log(zone->stats, zone->name, zone->db->outserial,
zone->signconf->nsec_type);
stats_clear(zone->stats);
pthread_mutex_unlock(&zone->stats->stats_lock);
}
if (engine->dnshandler) {
ods_log_debug("[%s] forward a notify", tools_str);
dnshandler_fwd_notify(engine->dnshandler, (uint8_t*) ODS_SE_NOTIFY_CMD,
strlen(ODS_SE_NOTIFY_CMD));
}
return status;
}
adapter_write
ods_status adapter_write(zone_type *zone)
Definition adapter.c:179
adapter_read
ods_status adapter_read(zone_type *zone)
Definition adapter.c:147
adapter.h
dnshandler_fwd_notify
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
Definition dnshandler.c:231
dnshandler.h
ODS_SE_NOTIFY_CMD
#define ODS_SE_NOTIFY_CMD
Definition dnshandler.h:48
engine_type
struct engine_struct engine_type
Definition engine.h:38
ixfr_purge
void ixfr_purge(ixfr_type *ixfr, char const *zonename)
Definition ixfr.c:237
namedb_rollback
void namedb_rollback(namedb_type *db, unsigned keepsc)
Definition namedb.c:847
namedb_cleanup_denials
void namedb_cleanup_denials(namedb_type *db)
Definition namedb.c:1116
namedb_init_denials
void namedb_init_denials(namedb_type *db)
Definition namedb.c:95
namedb_wipe_denial
void namedb_wipe_denial(namedb_type *db)
Definition namedb.c:979
signconf_compare_denial
task_id signconf_compare_denial(signconf_type *a, signconf_type *b)
Definition signconf.c:355
signconf_log
void signconf_log(signconf_type *sc, const char *name)
Definition signconf.c:388
signconf_cleanup
void signconf_cleanup(signconf_type *sc)
Definition signconf.c:470
signconf_type
struct signconf_struct signconf_type
Definition signconf.h:33
stats_log
void stats_log(stats_type *stats, const char *name, uint32_t serial, ldns_rr_type nsec_type)
Definition stats.c:76
stats_clear
void stats_clear(stats_type *stats)
Definition stats.c:54
ixfr_struct::ixfr_lock
pthread_mutex_t ixfr_lock
Definition ixfr.h:64
namedb_struct::have_serial
unsigned have_serial
Definition namedb.h:60
namedb_struct::is_initialized
unsigned is_initialized
Definition namedb.h:57
namedb_struct::intserial
uint32_t intserial
Definition namedb.h:54
namedb_struct::outserial
uint32_t outserial
Definition namedb.h:55
signconf_struct::soa_min
duration_type * soa_min
Definition signconf.h:67
signconf_struct::nsec_type
ldns_rr_type nsec_type
Definition signconf.h:55
signconf_struct::passthrough
int passthrough
Definition signconf.h:44
stats_struct::stats_lock
pthread_mutex_t stats_lock
Definition stats.h:63
stats_struct::sig_soa_count
uint32_t sig_soa_count
Definition stats.h:57
stats_struct::sig_count
uint32_t sig_count
Definition stats.h:56
stats_struct::sort_done
int sort_done
Definition stats.h:53
stats_struct::end_time
time_t end_time
Definition stats.h:62
stats_struct::sort_count
uint32_t sort_count
Definition stats.h:51
stats_struct::sort_time
time_t sort_time
Definition stats.h:52
stats_struct::start_time
time_t start_time
Definition stats.h:61
zone_struct::signconf
signconf_type * signconf
Definition zone.h:77
zone_struct::notify_args
char ** notify_args
Definition zone.h:67
zone_struct::default_ttl
uint32_t default_ttl
Definition zone.h:63
zone_struct::notify_ns
const char * notify_ns
Definition zone.h:66
zone_struct::stats
stats_type * stats
Definition zone.h:85
zone_struct::db
namedb_type * db
Definition zone.h:79
zone_struct::adinbound
adapter_type * adinbound
Definition zone.h:74
zone_struct::ixfr
ixfr_type * ixfr
Definition zone.h:80
zone_struct::name
const char * name
Definition zone.h:69
zone_struct::adoutbound
adapter_type * adoutbound
Definition zone.h:75
tools_signconf
ods_status tools_signconf(zone_type *zone)
Definition tools.c:52
tools_output
ods_status tools_output(zone_type *zone, engine_type *engine)
Definition tools.c:181
tools_input
ods_status tools_input(zone_type *zone)
Definition tools.c:93
tools.h
zone_rollback_nsec3param
void zone_rollback_nsec3param(zone_type *zone)
Definition zone.c:369
zone_publish_dnskeys
ods_status zone_publish_dnskeys(zone_type *zone, int skip_hsm_access)
Definition zone.c:186
zone_rollback_dnskeys
void zone_rollback_dnskeys(zone_type *zone)
Definition zone.c:279
zone_load_signconf
ods_status zone_load_signconf(zone_type *zone, signconf_type **new_signconf)
Definition zone.c:133
zone_publish_nsec3param
ods_status zone_publish_nsec3param(zone_type *zone)
Definition zone.c:306
zone.h
zone_type
struct zone_struct zone_type
Definition zone.h:41