From 8bffcf8f01621b2be9252eed4d1c92d2220c08ea Mon Sep 17 00:00:00 2001 From: halderen Date: Mon, 1 Oct 2018 03:36:48 +0200 Subject: [PATCH] - state files now also have file magic string, to keep track of versions - additional configuration file for configuring the periodic tasks of the signer - embedded periodic clean/write tasks in signer process when in opendnssec.conf the parameter signer: output-zonefile-period: is set to 0 every time an output file is written. --- common/Makefile.am | 2 +- common/settings.c | 238 ++++++++++++++++++++++++++++++++ common/settings.h | 37 +++++ configure.ac | 1 + m4/acx_libyaml.m4 | 21 +++ signer/src/Makefile.am | 3 - signer/src/adapter/adapter.c | 10 +- signer/src/daemon/signertasks.c | 112 +++++++++++++-- signer/src/daemon/signertasks.h | 1 + signer/src/signer/zone.c | 2 + signer/src/signer/zone.h | 16 ++- signer/src/test/Makefile.am | 1 - signer/src/test/config.yaml | 2 + signer/src/test/opendnssec.conf | 2 + signer/src/test/signertest.c | 22 ++- signer/src/views/periodic.c | 106 -------------- signer/src/views/views.c | 6 + 17 files changed, 452 insertions(+), 130 deletions(-) create mode 100644 common/settings.c create mode 100644 common/settings.h create mode 100644 m4/acx_libyaml.m4 create mode 100644 signer/src/test/config.yaml create mode 100644 signer/src/test/opendnssec.conf delete mode 100644 signer/src/views/periodic.c diff --git a/common/Makefile.am b/common/Makefile.am index 6c12dbf71a..9d7d3c955d 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -29,4 +29,4 @@ libcompat_a_SOURCES = \ logging.c logging.h \ janitor.c janitor.h \ cfg.c cfg.h \ - confparser.c confparser.h + confparser.c confparser.h settings.c settings.h diff --git a/common/settings.c b/common/settings.c new file mode 100644 index 0000000000..804710eadf --- /dev/null +++ b/common/settings.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2018 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 +#include +#include +#include +#include +#include "duration.h" +#include "settings.h" + +static ods_cfg_handle defaulthandle = NULL; + +static yaml_node_t* +parselocate(yaml_document_t *document, yaml_node_t *node, const char* fmt, va_list ap, const char** lastp) +{ + char* arg; + yaml_node_pair_t* nodepair; + yaml_node_item_t* nodeitem; + yaml_node_t* child; + if (fmt == NULL) { + do { + arg = va_arg(ap, char*); + *lastp = arg; + if (arg != NULL) { + if (node && node->type == YAML_MAPPING_NODE) { + for (nodepair = node->data.mapping.pairs.start; nodepair < node->data.mapping.pairs.top; nodepair++) { + child = yaml_document_get_node(document, nodepair->key); + if (child && child->type == YAML_SCALAR_NODE) { + if (!strncmp(arg, child->data.scalar.value, child->data.scalar.length) && child->data.scalar.length == strlen(arg)) { + break; + } + } + } + if (nodepair < node->data.mapping.pairs.top) { + child = yaml_document_get_node(document, nodepair->value); + if (child) { + node = child; + } else { + return NULL; + } + } else { + return NULL; + } + } + } + } while (arg != NULL); + return node; + } + return NULL; +} + +static int +parsefunclong(void* user, const char* str, void* resultvalue) +{ + char* end; + long* resultlong = (long*) resultvalue; + errno = 0; + *resultlong = strtol(str, &end, 0); + if (errno) { + return 1; + } else { + return 0; + } +} + + +static int +parsefunccount(void* user, const char* str, void* resultvalue) +{ + char* end; + long* resultlong = (long*) resultvalue; + errno = 0; + if(*str == '#') { + ++str; + while(isspace(*str)) + ++str; + } + *resultlong = strtol(str, &end, 0); + if (errno) { + return 1; + } else { + return 0; + } +} + + +static int +parsefuncperiod(void* user, const char* str, void* resultvalue) +{ + duration_type* duration = duration_create_from_string(str); + if (duration) { + time_t period = duration2time(duration); + duration_cleanup(duration); + *(time_t*)resultvalue = period; + return 0; + } else + return 1; +} + +static int +parsescalar(yaml_document_t *document, size_t resultsize, void* resultvalue, void* defaultvalue, int (*parsefunc)(void*,const char*,void*), void* parsedata, const char* fmt, va_list ap) +{ + int len; + const char* last = "unknown"; + const char* str; + int result; + yaml_node_t* root; + yaml_node_t* node; + root = (document ? yaml_document_get_root_node(document) : NULL); + node = parselocate(document, root, fmt, ap, &last); + if (node) { + if (node->type == YAML_SCALAR_NODE) { + str = (const char*)node->data.scalar.value; + for (len = 0; len < node->data.scalar.length && isspace(str[len]); len++) + ; + str = &str[len]; + len = node->data.scalar.length - len; + while(len > 0 && isspace(str[len])) + --len; + str = strndup(str, len); + if(parsefunc(parsedata,str,resultvalue)) { + if (defaultvalue) + memcpy(resultvalue,defaultvalue,resultsize); + fprintf(stderr,"in configuration parameter %s unable unparseable input %s\n",last,str); + abort(); + result = -1; + } else { + result = 0; + } + free(str); + } else { + fprintf(stderr,"in configuration parameter %s unable to parse argument\n",last); + if (defaultvalue) + memcpy(resultvalue,defaultvalue,resultsize); + result = -1; + } + } else { + if (defaultvalue) { + memcpy(resultvalue,defaultvalue,resultsize); + result = 0; + } else { + fprintf(stderr,"in configuration parameter %s argument not found\n",last); + result = 1; + } + } + return result; +} + +int +ods_cfg_access(ods_cfg_handle* handleptr, const char* filename) +{ + FILE *input; + yaml_parser_t parser; + yaml_document_t* document; + if(handleptr == NULL) { + if(defaulthandle) { + yaml_document_delete((yaml_document_t*)defaulthandle); + free((void*)defaulthandle); + defaulthandle = NULL; + } + handleptr = &defaulthandle; + } else if(filename == NULL && *handleptr == NULL) { + yaml_document_delete((yaml_document_t*)*handleptr); + } + + yaml_parser_initialize(&parser); + input = fopen(filename, "r"); + if(input) { + yaml_parser_set_input_file(&parser, input); + document = malloc(sizeof(yaml_document_t)); + yaml_parser_load(&parser, document); + yaml_parser_delete(&parser); + fclose(input); + } else + document = NULL; + *handleptr = document; + return 0; +} + +int +ods_cfg_getlong(ods_cfg_handle handle, long* resultvalue, long* defaultvalue, const char* fmt, ...) +{ + int rc; + va_list ap; + yaml_document_t* document = (handle ? handle : defaulthandle); + va_start(ap, fmt); + rc = parsescalar(document, sizeof(long), resultvalue, defaultvalue, parsefunclong, NULL, fmt, ap); + va_end(ap); + return rc; +} + +int +ods_cfg_getcount(ods_cfg_handle handle, long* resultvalue, long* defaultvalue, const char* fmt, ...) +{ + int rc; + va_list ap; + yaml_document_t* document = (handle ? handle : defaulthandle); + va_start(ap, fmt); + rc = parsescalar(document, sizeof(long), resultvalue, defaultvalue, parsefunccount, NULL, fmt, ap); + va_end(ap); + return rc; +} + +int +ods_cfg_getperiod(ods_cfg_handle handle, long* resultvalue, long* defaultvalue, const char* fmt, ...) +{ + int rc; + va_list ap; + yaml_document_t* document = (handle ? handle : defaulthandle); + va_start(ap, fmt); + rc = parsescalar(document, sizeof(long), resultvalue, defaultvalue, parsefunccount, NULL, fmt, ap); + va_end(ap); + return rc; +} diff --git a/common/settings.h b/common/settings.h new file mode 100644 index 0000000000..2a7554fb91 --- /dev/null +++ b/common/settings.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 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. + */ + +#ifndef SETTINGS_H +#define SETTINGS_H + +typedef void* ods_cfg_handle; + +int ods_cfg_access(ods_cfg_handle*, const char* filename); +int ods_cfg_getlong(ods_cfg_handle, long* resultvalue, long* defaultvalue, const char* fmt,...); +int ods_cfg_getcount(ods_cfg_handle, long* resultvalue, long* defaultvalue, const char* fmt,...); +int ods_cfg_getperiod(ods_cfg_handle, long* resultvalue, long* defaultvalue, const char* fmt,...); + +#endif diff --git a/configure.ac b/configure.ac index 5f66913510..cba0b84a87 100644 --- a/configure.ac +++ b/configure.ac @@ -223,6 +223,7 @@ AC_CHECK_LIB(unwind, unw_backtrace, [AC_CHECK_HEADERS(libunwind.h, [AC_DEFINE([H ACX_LIBMICROHTTPD ACX_LIBJANSSON +ACX_LIBYAML AC_CONFIG_HEADER([common/config.h]) diff --git a/m4/acx_libyaml.m4 b/m4/acx_libyaml.m4 new file mode 100644 index 0000000000..7b939bcab3 --- /dev/null +++ b/m4/acx_libyaml.m4 @@ -0,0 +1,21 @@ +AC_DEFUN([ACX_LIBYAML],[ + AC_CHECK_FUNC( + [yaml_parser_initialize], + [ + AC_DEFINE(HAVE_YAML, 1, [Define if you have libjannson]) + ], + [ + AC_CHECK_LIB( + [yaml], + [yaml_parser_initialize], + [ + AC_DEFINE(HAVE_YAML, 1, [Define if you have libyaml]) + LIBS="$LIBS -lyaml" + ], + [ + AC_MSG_ERROR([No libyaml found]) + ] + ) + ] + ) +]) diff --git a/signer/src/Makefile.am b/signer/src/Makefile.am index 4fecde4030..11701c59d9 100644 --- a/signer/src/Makefile.am +++ b/signer/src/Makefile.am @@ -34,8 +34,6 @@ ods_signerd_SOURCES= ods-signerd.c \ parser/signconfparser.c parser/signconfparser.h \ parser/zonelistparser.c parser/zonelistparser.h \ hsm.c hsm.h \ - signer/denial.h \ - signer/domain.h \ signer/keys.c signer/keys.h \ signer/nsec3params.c signer/nsec3params.h \ signer/signconf.c signer/signconf.h \ @@ -68,7 +66,6 @@ ods_signerd_SOURCES= ods-signerd.c \ views/ringbuf.h \ views/rpc.c \ views/zoneoutput.c \ - views/periodic.c \ views/proto.h analyze: diff --git a/signer/src/adapter/adapter.c b/signer/src/adapter/adapter.c index cb3f4641fb..454d57c81b 100644 --- a/signer/src/adapter/adapter.c +++ b/signer/src/adapter/adapter.c @@ -192,10 +192,12 @@ adapter_write(zone_type* zone) names_viewreset(view); switch(zone->adoutbound->type) { case ADAPTER_FILE: - ods_log_verbose("[%s] write zone %s serial %u to output file " - "adapter %s", adapter_str, zone->name, - (zone->outboundserial ? *(zone->outboundserial) : 0), zone->adoutbound->configstr); - status = adfile_write(zone, view, zone->adoutbound->configstr); + if(!zone->operatingconf || zone->operatingconf->zonefile_freq==0) { + ods_log_verbose("[%s] write zone %s serial %u to output file " + "adapter %s", adapter_str, zone->name, + (zone->outboundserial ? *(zone->outboundserial) : 0), zone->adoutbound->configstr); + status = adfile_write(zone, view, zone->adoutbound->configstr); + } break; case ADAPTER_DNS: status = addns_write(zone, view); diff --git a/signer/src/daemon/signertasks.c b/signer/src/daemon/signertasks.c index 739761f5bd..fd7747d5f1 100644 --- a/signer/src/daemon/signertasks.c +++ b/signer/src/daemon/signertasks.c @@ -45,6 +45,7 @@ #include "util.h" #include "signertasks.h" #include "file.h" +#include "settings.h" /** * Queue RRset for signing. @@ -569,6 +570,82 @@ do_forcereadzone(task_type* task, const char* zonename, void* zonearg, void *con } } + +static const long default_statefile_freq = 1; +static const long default_zonefile_freq = 1; +static const long default_ixfr_history = 30; + +void +do_outputzonefile(zone_type* zone) +{ + names_view_type outputview; + char* filename; + char* tmpname; + + /* Write the zone as it currently stands */ + outputview = zone->outputview; + names_viewreset(outputview); + tmpname = ods_build_path(zone->adoutbound->configstr, ".tmp", 0, 0); + if(writezone(outputview, tmpname)) { + if (zone->adoutbound->error) { + ods_log_error("unable to write zone %s file %s", zone->name, filename); + zone->adoutbound->error = 0; + // status = ODS_STATUS_FWRITE_ERR; + } + } else { + if (rename((const char*) tmpname, zone->adoutbound->configstr) != 0) { + ods_log_error("unable to write file: failed to rename %s to %s (%s)", tmpname, filename, strerror(errno)); + // status = ODS_STATUS_RENAME_ERR; + } + } + free(tmpname); +} + +void +do_purgezone(zone_type* zone) +{ + int serial; + names_view_type baseview; + names_iterator iter; + recordset_type record; + + baseview = zone->baseview; + names_viewreset(baseview); + + /* find any items that are no longer worth preserving because they are + * outdated for too long (ie their last valid serial number is too far + * in the past. + */ + serial = zone->outboundserial - (zone->operatingconf ? zone->operatingconf->ixfr_history : 4); + for(iter=names_viewiterator(baseview,names_iteratoroutdated,serial); names_iterate(&iter,&record); names_advance(&iter, NULL)) { + names_remove(baseview, record); + } + if(names_viewcommit(baseview)) { + ods_log_error("Unable to clean zone, retrying next pass"); + } +} + +void +do_outputstatefile(zone_type* zone) +{ + /* Refresh the current state jounral file */ + struct stat statbuf; + names_view_type baseview; + char* filename; + + baseview = zone->baseview; + names_viewreset(baseview); + filename = ods_build_path(zone->name, ".state", 0, 1); + if(fstatat(AT_FDCWD, filename, &statbuf, 0)) { + if(errno == ENOENT) { + names_viewpersist(baseview, AT_FDCWD, filename); + } else { + ods_log_error("unable to create state file for zone %s", zone->name); + } + } + free(filename); +} + time_t do_writezone(task_type* task, const char* zonename, void* zonearg, void *contextarg) { @@ -581,25 +658,34 @@ do_writezone(task_type* task, const char* zonename, void* zonearg, void *context context->clock_in = time_now(); /* TODO this means something different */ /* perform write to output adapter task */ + if(zone->operatingconf == NULL) { + long defaultvalue; + ods_cfg_access(NULL, "opendnssec.conf"); + zone->operatingconf = malloc(sizeof(struct operatingconf)); + zone->operatingconf->statefile_timer = 0; + ods_cfg_getcount(NULL, &zone->operatingconf->statefile_freq, &default_statefile_freq, NULL, "signer", "output-statefile-period", NULL); + zone->operatingconf->zonefile_timer = 0; + ods_cfg_getcount(NULL, &zone->operatingconf->zonefile_freq, &default_zonefile_freq, NULL, "signer", "output-zonefile-period", NULL); + ods_cfg_getcount(NULL, &zone->operatingconf->ixfr_history, &default_ixfr_history, NULL, "signer", "output-ixfr-history", NULL); + } + + if(zone->operatingconf->statefile_timer > 0) { + if(--(zone->operatingconf->statefile_timer) == 0) { + zone->operatingconf->statefile_timer = zone->operatingconf->statefile_freq; + do_outputstatefile(zone); + } + } + names_viewreset(zone->outputview); status = tools_output(zone, engine); - struct stat statbuf; - char* filename = ods_build_path(zone->name, ".state", 0, 1); - if(fstatat(AT_FDCWD, filename, &statbuf, 0)) { - if(errno == ENOENT) { - names_viewpersist(zone->baseview, AT_FDCWD, filename); - } else { - ods_log_error("[%s] unable to create state file for zone %s", worker->name, task->owner); + if(zone->operatingconf->zonefile_timer > 0) { + if(--(zone->operatingconf->zonefile_timer) == 0) { + zone->operatingconf->zonefile_timer = zone->operatingconf->zonefile_freq; + do_outputzonefile(zone); } } - free(filename); - if (status != ODS_STATUS_OK) { - ods_log_crit("[%s] CRITICAL: failed to sign zone %s: %s", - worker->name, task->owner, ods_status2str(status)); - return schedule_DEFER; - } if (zone->signconf && duration2time(zone->signconf->sig_resign_interval)) { resign = context->clock_in + diff --git a/signer/src/daemon/signertasks.h b/signer/src/daemon/signertasks.h index 2c01269693..5a0dd785f2 100644 --- a/signer/src/daemon/signertasks.h +++ b/signer/src/daemon/signertasks.h @@ -51,6 +51,7 @@ time_t do_forcereadsignconf(task_type* task, const char* zonename, void* zonearg time_t do_signzone(task_type* task, const char* zonename, void* zonearg, void *contextarg); time_t do_readzone(task_type* task, const char* zonename, void* zonearg, void *contextarg); time_t do_forcereadzone(task_type* task, const char* zonename, void* zonearg, void *contextarg); +void do_purgezone(zone_type* zone); time_t do_writezone(task_type* task, const char* zonename, void* zonearg, void *contextarg); #endif /* SIGNERTASKS_H */ diff --git a/signer/src/signer/zone.c b/signer/src/signer/zone.c index 003e9b2bda..97c0512137 100644 --- a/signer/src/signer/zone.c +++ b/signer/src/signer/zone.c @@ -100,6 +100,7 @@ zone_create(char* name, ldns_rr_class klass) zone->notify = NULL; zone->zoneconfigvalid = 0; zone->signconf = signconf_create(); + zone->operatingconf = NULL; if (!zone->signconf) { ods_log_error("[%s] unable to create zone %s: signconf_create() " "failed", zone_str, name); @@ -487,6 +488,7 @@ zone_cleanup(zone_type* zone) free((void*)zone->nextserial); free((void*)zone->inboundserial); free((void*)zone->outboundserial); + free((void*)zone->operatingconf); zone->nextserial = NULL; zone->inboundserial = NULL; zone->outboundserial = NULL; diff --git a/signer/src/signer/zone.h b/signer/src/signer/zone.h index e78a52937f..2f7ccf9fab 100644 --- a/signer/src/signer/zone.h +++ b/signer/src/signer/zone.h @@ -54,6 +54,20 @@ typedef struct zone_struct zone_type; struct schedule_struct; +/* FIXME these operating configuration parameters should be better integrated + * At the moment we have enforcer supplied configuration parameters, which + * are per zone, but based on the KASP. And we have global parameters from + * the conf.xml. But we have no per-zone parameters that are not part of + * the KASP. + */ +struct operatingconf { + long statefile_freq; + long statefile_timer; + long zonefile_freq; + long zonefile_timer; + long ixfr_history; +}; + struct zone_struct { ldns_rdf* apex; /* wire format zone name */ ldns_rr_class klass; /* class */ @@ -72,6 +86,7 @@ struct zone_struct { adapter_type* adoutbound; /* outbound adapter */ /* from signconf.xml */ signconf_type* signconf; /* signer configuration values */ + struct operatingconf* operatingconf; names_view_type baseview; names_view_type inputview; @@ -80,7 +95,6 @@ struct zone_struct { names_view_type signview; names_view_type outputview; names_view_type changesview; - char *persistviews; uint32_t* nextserial; uint32_t* inboundserial; diff --git a/signer/src/test/Makefile.am b/signer/src/test/Makefile.am index 7fb4371e6b..02e2cb8fcd 100644 --- a/signer/src/test/Makefile.am +++ b/signer/src/test/Makefile.am @@ -66,7 +66,6 @@ signertest_LDADD = \ ../views/table.o \ ../views/views.o \ ../views/zoneoutput.o \ - ../views/periodic.o \ $(LIBHSM) $(LIBCOMPAT) \ @LDNS_LIBS@ @XML2_LIBS@ @PTHREAD_LIBS@ @RT_LIBS@ @SSL_LIBS@ @C_LIBS@ \ @CUNIT_LIBS@ diff --git a/signer/src/test/config.yaml b/signer/src/test/config.yaml new file mode 100644 index 0000000000..af1f320cd8 --- /dev/null +++ b/signer/src/test/config.yaml @@ -0,0 +1,2 @@ +logging: + verbosity: 3 diff --git a/signer/src/test/opendnssec.conf b/signer/src/test/opendnssec.conf new file mode 100644 index 0000000000..fc53c822a1 --- /dev/null +++ b/signer/src/test/opendnssec.conf @@ -0,0 +1,2 @@ +signer: + output-zonefile-period: 0 diff --git a/signer/src/test/signertest.c b/signer/src/test/signertest.c index 20ec944de4..0bb9e151b5 100644 --- a/signer/src/test/signertest.c +++ b/signer/src/test/signertest.c @@ -53,6 +53,7 @@ #include "daemon/metastorage.h" #include "views/httpd.h" #include "adapter/adutil.h" +#include "settings.h" #include "comparezone.h" @@ -415,6 +416,7 @@ makecall(const char* zone, const char* delegation, ...) return rpc; } + void testNothing(void) { @@ -445,6 +447,21 @@ testIterator(void) } +void +testConfig(void) +{ + long value; + int rc; + + ods_cfg_access(NULL,"config.yaml"); + + value = 0; + rc = ods_cfg_getlong(NULL, &value, NULL, NULL, "logging", "verbosity", NULL); + assert(rc == 0); + assert(value == 3); +} + + static void testAnnotateItem(const char* name, const char* expected) { @@ -458,6 +475,7 @@ testAnnotateItem(const char* name, const char* expected) names_recorddispose(record); } + void testAnnotate(void) { @@ -871,13 +889,14 @@ testDisposing(void) outputzone(zone); names_viewreset(zone->baseview); names_dumpviewinfo(stderr,7,&zone->baseview); - purgezone(zone); + do_purgezone(zone); disposezone(zone); } extern void testNothing(void); extern void testIterator(void); +extern void testConfig(void); extern void testAnnotate(void); extern void testStatefile(void); extern void testTransferfile(void); @@ -900,6 +919,7 @@ struct test_struct { } tests[] = { { "signer", "testNothing", "test nothing" }, { "signer", "testIterator", "test of iterator" }, + { "signer", "testConfig", "test config" }, { "signer", "testAnnotate", "test of denial annotation" }, { "signer", "testMarshalling", "test marshalling" }, { "signer", "testStatefile", "test statefile usage" }, diff --git a/signer/src/views/periodic.c b/signer/src/views/periodic.c deleted file mode 100644 index 48f71f3c36..0000000000 --- a/signer/src/views/periodic.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#define _LARGEFILE64_SOURCE -#define _GNU_SOURCE - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "uthash.h" -#include "utilities.h" -#include "logging.h" -#include "proto.h" - -#pragma GCC optimize ("O0") - -// number of ixfrs to keep - -#define NUMBER_OF_IXFRS 4 - -void -purgezone(zone_type* zone) -{ - char* tmpname; - recordset_type record; - names_iterator iter; - int serial = 4; - names_view_type baseview = zone->baseview; - - names_viewreset(baseview); - - /* find any items that are no longer worth preserving because they are - * outdated for too long (ie their last valid serial number is too far - * in the past. - */ - for(iter=names_viewiterator(baseview,names_iteratoroutdated,serial); names_iterate(&iter,&record); names_advance(&iter, NULL)) { - names_remove(baseview, record); - } - if(names_viewcommit(baseview)) { - abort(); // FIXME - } - - /* Refresh the current state jounral file */ - struct stat statbuf; - char* filename = ods_build_path(zone->name, ".state", 0, 1); - if(fstatat(AT_FDCWD, filename, &statbuf, 0)) { - if(errno == ENOENT) { - names_viewpersist(baseview, AT_FDCWD, filename); - } else { - ods_log_error("unable to create state file for zone %s", zone->name); - } - } - free(filename); - - /* Write the zone as it currently stands */ - names_view_type outputview = zone->outputview; - names_viewreset(outputview); - tmpname = ods_build_path(zone->adoutbound->configstr, ".tmp", 0, 0); - if (!tmpname) { - return ODS_STATUS_MALLOC_ERR; - } - if(writezone(outputview, tmpname)) { - if (zone->adoutbound->error) { - ods_log_error("unable to write zone %s file %s", zone->name, filename); - zone->adoutbound->error = 0; - // status = ODS_STATUS_FWRITE_ERR; - } - } else { - if (rename((const char*) tmpname, zone->adoutbound->configstr) != 0) { - ods_log_error("unable to write file: failed to rename %s to %s (%s)", tmpname, filename, strerror(errno)); - // status = ODS_STATUS_RENAME_ERR; - } - } - free(tmpname); -} diff --git a/signer/src/views/views.c b/signer/src/views/views.c index 03ea11430d..14997cca53 100644 --- a/signer/src/views/views.c +++ b/signer/src/views/views.c @@ -571,6 +571,8 @@ names_viewconfig(names_view_type view, signconf_type** signconf) return 0; } +static char filemagic[8] = "\0ODS-S1\n"; + int names_viewrestore(names_view_type view, const char* apex, int basefd, const char* filename) { @@ -578,6 +580,7 @@ names_viewrestore(names_view_type view, const char* apex, int basefd, const char recordset_type record; marshall_handle input; marshall_handle output; + char buffer[8]; view->zonedata.apex = strdup(apex); @@ -587,6 +590,8 @@ names_viewrestore(names_view_type view, const char* apex, int basefd, const char else fd = open(filename, O_RDWR|O_LARGEFILE); if(fd >= 0) { + read(fd,buffer,sizeof(buffer)); + assert(memcmp(buffer,filemagic,sizeof(filemagic))==0); input = marshallcreate(marshall_INPUT, fd); do { names_recordmarshall(&record, input); @@ -627,6 +632,7 @@ names_viewpersist(names_view_type view, int basefd, char* filename) CHECK((fd = openat(basefd, tmpfilename, O_CREAT|O_WRONLY|O_LARGEFILE|O_TRUNC,0666)) < 0); else CHECK((fd = open(tmpfilename, O_CREAT|O_WRONLY|O_LARGEFILE|O_TRUNC,0666)) < 0); + write(fd,filemagic,sizeof(filemagic)); marsh = marshallcreate(marshall_OUTPUT, fd); iter = names_indexiterator(view->indices[0]);