Commit 9da902d0 authored by Filip Siroky's avatar Filip Siroky Committed by Daniel Salzman

kzonecheck: add option to change time for which is zone checked

parent 5b1e54ae
......@@ -48,6 +48,11 @@ Please, refer to the \fBsemantic\-checks\fP configuration option in
Zone origin. If not specified, the origin is determined from the file name
(possibly removing the \fB\&.zone\fP suffix).
.TP
\fB\-t\fP, \fB\-\-time\fP \fItime\fP
Current time specification. Use UNIX timestamp, YYYYMMDDHHmmSS
format, or [+/\-]\fItime\fP[unit] format, where unit can be \fBY\fP, \fBM\fP,
\fBD\fP, \fBh\fP, \fBm\fP, or \fBs\fP\&. Default is current UNIX timestamp.
.TP
\fB\-v\fP, \fB\-\-verbose\fP
Enable debug output.
.TP
......
......@@ -25,6 +25,11 @@ Options
Zone origin. If not specified, the origin is determined from the file name
(possibly removing the ``.zone`` suffix).
**-t**, **--time** *time*
Current time specification. Use UNIX timestamp, YYYYMMDDHHmmSS
format, or [+/-]\ *time*\ [unit] format, where unit can be **Y**, **M**,
**D**, **h**, **m**, or **s**. Default is current UNIX timestamp.
**-v**, **--verbose**
Enable debug output.
......
......@@ -158,7 +158,7 @@ static int xfr_validate(zone_contents_t *zone, struct refresh_data *data)
{
err_handler_logger_t handler;
handler._cb.cb = err_handler_logger;
int ret = zone_do_sem_checks(zone, false, &handler._cb);
int ret = zone_do_sem_checks(zone, false, &handler._cb, time(NULL));
if (ret != KNOT_EOK) {
// error is logged by the error handler
return ret;
......
......@@ -120,6 +120,7 @@ typedef struct semchecks_data {
bool fatal_error;
const zone_node_t *next_nsec;
enum check_levels level;
time_t time;
} semchecks_data_t;
static int check_cname_multiple(const zone_node_t *node, semchecks_data_t *data);
......@@ -170,7 +171,7 @@ static int check_rrsig_rdata(err_handler_t *handler,
const zone_node_t *node,
const knot_rdataset_t *rrsig,
size_t rr_pos,
const knot_rrset_t *rrset)
const knot_rrset_t *rrset, time_t context)
{
/* Prepare additional info string. */
char info_str[50] = { '\0' };
......@@ -231,10 +232,8 @@ static int check_rrsig_rdata(err_handler_t *handler,
}
}
/* Check for expired signature. */
if (knot_rrsig_sig_expiration(rrsig, rr_pos) < time(NULL)) {
if (knot_rrsig_sig_expiration(rrsig, rr_pos) < context) {
ret = handler->cb(handler, zone, node,
ZC_ERR_RRSIG_RDATA_EXPIRATION,
info_str);
......@@ -280,7 +279,7 @@ static int check_signed_rrsig(const zone_node_t *node, semchecks_data_t *data)
static int check_rrsig_in_rrset(err_handler_t *handler,
const zone_contents_t *zone,
const zone_node_t *node,
const knot_rrset_t *rrset)
const knot_rrset_t *rrset, time_t context)
{
if (handler == NULL || node == NULL || rrset == NULL) {
return KNOT_EINVAL;
......@@ -315,7 +314,7 @@ static int check_rrsig_in_rrset(err_handler_t *handler,
}
for (uint16_t i = 0; ret == KNOT_EOK && i < (&rrsigs)->rr_count; ++i) {
ret = check_rrsig_rdata(handler, zone, node, &rrsigs, i, rrset);
ret = check_rrsig_rdata(handler, zone, node, &rrsigs, i, rrset, context);
}
knot_rdataset_clear(&rrsigs, NULL);
......@@ -398,7 +397,8 @@ static int check_rrsig(const zone_node_t *node, semchecks_data_t *data)
continue;
}
ret = check_rrsig_in_rrset(data->handler, data->zone, node, &rrset);
ret = check_rrsig_in_rrset(data->handler, data->zone, node, &rrset,
data->time);
}
return ret;
}
......@@ -810,9 +810,9 @@ static int do_checks_in_tree(zone_node_t *node, void *data)
}
int zone_do_sem_checks(zone_contents_t *zone, bool optional,
err_handler_t *handler)
err_handler_t *handler, time_t time)
{
if (!zone || !handler) {
if (zone == NULL || handler == NULL) {
return KNOT_EINVAL;
}
......@@ -822,7 +822,8 @@ int zone_do_sem_checks(zone_contents_t *zone, bool optional,
.next_nsec = zone->apex,
.fatal_error = false,
.level = MANDATORY,
};
.time = time,
};
if (optional) {
data.level |= OPTIONAL;
......@@ -846,7 +847,6 @@ int zone_do_sem_checks(zone_contents_t *zone, bool optional,
if (data.level & NSEC) {
check_nsec_cyclic(&data);
}
if (data.fatal_error) {
return KNOT_ESEMCHECK;
}
......
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -13,23 +13,11 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief DNS zone semantic checks.
*
* \addtogroup zone
* @{
*/
#pragma once
#include "knot/zone/node.h"
#include "knot/zone/contents.h"
#include "contrib/ucw/lists.h"
#include "libknot/mm_ctx.h"
/*!
*\brief Internal error constants. General errors are added for convenience,
......@@ -111,14 +99,14 @@ struct err_handler {
*
* Errors are logged in error handler.
*
* \param zone Zone to be searched / checked
* \param optional To do also optional check
* \param handler Semantic error handler.
* \param zone Zone to be searched / checked.
* \param optional To do also optional check.
* \param handler Semantic error handler.
* \param time Check zone at given time (rrsig expiration).
*
* \retval KNOT_EOK no error found
* \retval KNOT_ESEMCHECK found semantic error
* \retval KNOT_EINVAL or other error
*/
int zone_do_sem_checks(zone_contents_t *zone, bool optional,
err_handler_t *handler);
/*! @} */
err_handler_t *handler, time_t time);
......@@ -35,7 +35,7 @@ int zone_load_contents(conf_t *conf, const knot_dname_t *zone_name,
zloader_t zl;
char *zonefile = conf_zonefile(conf, zone_name);
conf_val_t val = conf_zone_get(conf, C_SEM_CHECKS, zone_name);
int ret = zonefile_open(&zl, zonefile, zone_name, conf_bool(&val));
int ret = zonefile_open(&zl, zonefile, zone_name, conf_bool(&val), time(NULL));
err_handler_logger_t handler;
memset(&handler, 0, sizeof(handler));
......
......@@ -166,7 +166,7 @@ static void process_data(zs_scanner_t *scanner)
}
int zonefile_open(zloader_t *loader, const char *source,
const knot_dname_t *origin, bool semantic_checks)
const knot_dname_t *origin, bool semantic_checks, time_t time)
{
if (!loader) {
return KNOT_EINVAL;
......@@ -219,6 +219,7 @@ int zonefile_open(zloader_t *loader, const char *source,
loader->source = strdup(source);
loader->creator = zc;
loader->semantic_checks = semantic_checks;
loader->time = time;
return KNOT_EOK;
}
......@@ -265,7 +266,7 @@ zone_contents_t *zonefile_load(zloader_t *loader)
}
ret = zone_do_sem_checks(zc->z, loader->semantic_checks,
loader->err_handler);
loader->err_handler, loader->time);
if (ret != KNOT_EOK) {
ERROR(zname, "failed to load zone, file '%s' (%s)",
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -13,12 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \addtogroup zone
* @{
*/
#pragma once
......@@ -46,6 +40,7 @@ typedef struct zloader {
err_handler_t *err_handler; /*!< Semantic checks error handler. */
zcreator_t *creator; /*!< Loader context. */
zs_scanner_t scanner; /*!< Zone scanner. */
time_t time; /*!< time for zone check. */
} zloader_t;
typedef struct {
......@@ -64,12 +59,13 @@ int err_handler_logger(err_handler_t *handler, const zone_contents_t *zone,
* \param source Source file name.
* \param origin Zone origin.
* \param semantic_checks Perform semantic checks.
* \param time Time for semantic check.
*
* \retval Initialized loader on success.
* \retval NULL on error.
*/
int zonefile_open(zloader_t *loader, const char *source,
const knot_dname_t *origin, bool semantic_checks);
const knot_dname_t *origin, bool semantic_checks, time_t time);
/*!
* \brief Loads zone from a zone file.
......@@ -112,5 +108,3 @@ void zonefile_close(zloader_t *loader);
* \return KNOT_E*
*/
int zcreator_step(zcreator_t *zl, const knot_rrset_t *rr);
/*! @} */
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -14,14 +14,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <getopt.h>
#include <stdio.h>
#include <libgen.h>
#include "contrib/time.h"
#include "libknot/libknot.h"
#include "utils/common/params.h"
#include "knot/common/log.h"
#include "utils/common/params.h"
#include "utils/kzonecheck/zone_check.h"
#define PROGRAM_NAME "kzonecheck"
......@@ -32,7 +31,9 @@ static void print_help(void)
"\n"
"Parameters:\n"
" -o, --origin <zone_origin> Zone name.\n"
" (default filename or filename without .zone)\n"
" (default filename without .zone)\n"
" -t, --time <timestamp> Current time specification.\n"
" (default current UNIX time)\n"
" -v, --verbose Enable debug output.\n"
" -h, --help Print the program help.\n"
" -V, --version Print the program version.\n"
......@@ -44,11 +45,12 @@ int main(int argc, char *argv[])
{
const char *origin = NULL;
bool verbose = false;
FILE *outfile = stdout;
knot_time_t check_time = (knot_time_t)time(NULL);
/* Long options. */
struct option opts[] = {
{ "origin", required_argument, NULL, 'o' },
{ "time", required_argument, NULL, 't' },
{ "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
......@@ -57,7 +59,7 @@ int main(int argc, char *argv[])
/* Parse command line arguments */
int opt = 0;
while ((opt = getopt_long(argc, argv, "o:vVh", opts, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "o:t:vVh", opts, NULL)) != -1) {
switch (opt) {
case 'o':
origin = optarg;
......@@ -71,6 +73,13 @@ int main(int argc, char *argv[])
case 'V':
print_version(PROGRAM_NAME);
return EXIT_SUCCESS;
case 't':
if (knot_time_parse("YMDhms|#|+-#U|+-#",
optarg, &check_time) != KNOT_EOK) {
fprintf(stderr, "Unknown time format.\n");
return EXIT_FAILURE;
}
break;
default:
print_help();
return EXIT_FAILURE;
......@@ -79,7 +88,7 @@ int main(int argc, char *argv[])
/* Check if there's at least one remaining non-option. */
if (optind >= argc) {
fprintf(outfile, "Expected zone file name.\n");
fprintf(stderr, "Expected zone file name.\n");
print_help();
return EXIT_FAILURE;
}
......@@ -112,7 +121,7 @@ int main(int argc, char *argv[])
knot_dname_t *dname = knot_dname_from_str_alloc(zonename);
free(zonename);
int ret = zone_check(filename, dname, outfile);
int ret = zone_check(filename, dname, stdout, (time_t)check_time);
knot_dname_free(&dname, NULL);
log_close();
......@@ -120,7 +129,7 @@ int main(int argc, char *argv[])
switch (ret) {
case KNOT_EOK:
if (verbose) {
fprintf(outfile, "No semantic error found.\n");
fprintf(stdout, "No semantic error found.\n");
}
return EXIT_SUCCESS;
case KNOT_ESEMCHECK:
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,7 +19,6 @@
#include "knot/zone/contents.h"
#include "knot/zone/zonefile.h"
#include "contrib/ucw/lists.h"
#include "utils/kzonecheck/zone_check.h"
typedef struct {
......@@ -78,10 +77,10 @@ static void print_statistics(err_handler_stats_t *handler)
}
int zone_check(const char *zone_file, const knot_dname_t *zone_name,
FILE *outfile)
FILE *outfile, time_t time)
{
zloader_t zl;
int ret = zonefile_open(&zl, zone_file, zone_name, true);
int ret = zonefile_open(&zl, zone_file, zone_name, true, time);
if (ret != KNOT_EOK) {
return ret;
}
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,4 +19,4 @@
#include "libknot/libknot.h"
int zone_check(const char *zone_file, const knot_dname_t *zone_name,
FILE *outfile);
FILE *outfile, time_t time);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment