Commit 5e106d22 authored by Vitezslav Kriz's avatar Vitezslav Kriz Committed by Jan Včelák
Browse files

kzonecheck: split into two files

parent f73fb945
......@@ -407,7 +407,9 @@ knotc_LDADD = libknotd.la libknotus.la $(libedit_LIBS)
knot1to2_LDADD = libcontrib.la
kzonecheck_SOURCES = \
utils/kzonecheck/main.c
utils/kzonecheck/main.c \
utils/kzonecheck/zone_check.c \
utils/kzonecheck/zone_check.h
kzonecheck_LDADD = libknotd.la
......
......@@ -105,18 +105,45 @@ const char *zonechecks_error_messages[(-ZC_ERR_UNKNOWN) + 1] = {
[-ZC_ERR_DNAME_WILDCARD_SELF] =
"DNAME, wildcard pointing to itself",
/* ^
| Important errors (to be logged on first occurrence and counted) */
/* Below are errors of lesser importance, to be counted unless
specified otherwise */
[-ZC_ERR_GLUE_NODE] =
"GLUE, node with glue record missing",
[-ZC_ERR_GLUE_RECORD] =
"GLUE, record with glue address missing",
};
typedef struct semchecks_data {
zone_contents_t *zone;
err_handler_t *handler;
bool fatal_error;
const zone_node_t *next_nsec;
enum check_levels level;
} semchecks_data_t;
static void check_cname_multiple(const zone_node_t *node, semchecks_data_t *data);
static void check_dname(const zone_node_t *node, semchecks_data_t *data);
static void check_delegation(const zone_node_t *node, semchecks_data_t *data);
static void check_nsec(const zone_node_t *node, semchecks_data_t *data);
static void check_nsec3(const zone_node_t *node, semchecks_data_t *data);
static void check_rrsig(const zone_node_t *node, semchecks_data_t *data);
static void check_signed_rrsig(const zone_node_t *node, semchecks_data_t *data);
struct check_function {
void (*function)(const zone_node_t *, semchecks_data_t *);
enum check_levels level;
};
const struct check_function check_functions[] = {
{check_cname_multiple, SEM_CHECK_MANDATORY},
{check_dname, SEM_CHECK_MANDATORY},
{check_delegation, SEM_CHECK_OPTIONAL},
{check_rrsig, SEM_CHECK_NSEC | SEM_CHECK_NSEC3},
{check_signed_rrsig, SEM_CHECK_NSEC | SEM_CHECK_NSEC3},
{check_nsec, SEM_CHECK_NSEC},
{check_nsec3, SEM_CHECK_NSEC3},
};
const int check_functions_len = sizeof(check_functions)/sizeof(struct check_function);
void err_handler_init(err_handler_t *h)
{
memset(h, 0, sizeof(err_handler_t));
......@@ -380,10 +407,8 @@ static int check_rrsig_in_rrset(err_handler_t *handler,
ret = knot_synth_rrsig(rrset->type,
node_rdataset(node, KNOT_RRTYPE_RRSIG),
&rrsigs, NULL);
if (ret != KNOT_EOK) {
if (ret != KNOT_ENOENT) {
return ret;
}
if (ret != KNOT_EOK && ret != KNOT_ENOENT) {
return ret;
}
if (ret == KNOT_ENOENT) {
......@@ -556,6 +581,7 @@ static void check_rrsig(const zone_node_t *node, semchecks_data_t *data)
bool deleg = node->flags & NODE_FLAGS_DELEG;
knot_rrset_t dnskey_rrset = node_rrset(data->zone->apex, KNOT_RRTYPE_DNSKEY);
int rrset_count = node->rrset_count;
for (int i = 0; i < rrset_count; i++) {
knot_rrset_t rrset = node_rrset_at(node, i);
......@@ -566,7 +592,6 @@ static void check_rrsig(const zone_node_t *node, semchecks_data_t *data)
continue;
}
knot_rrset_t dnskey_rrset = node_rrset(data->zone->apex, KNOT_RRTYPE_DNSKEY);
check_rrsig_in_rrset(data->handler, data->zone, node,
&rrset, &dnskey_rrset);
}
......@@ -652,7 +677,7 @@ static void check_nsec(const zone_node_t *node,
/*!
* \brief Run semantic checks for node with DNSSEC-related types.
*/
static void check_nsec3(zone_node_t *node, semchecks_data_t *data)
static void check_nsec3(const zone_node_t *node, semchecks_data_t *data)
{
assert(node);
bool auth = !(node->flags & NODE_FLAGS_NONAUTH);
......@@ -919,24 +944,10 @@ static int do_checks_in_tree(zone_node_t *node, void *data)
{
struct semchecks_data *s_data = (semchecks_data_t *)data;
// mandatory checks
check_cname_multiple(node, s_data);
check_dname(node, s_data);
if (s_data->level & SEM_CHECK_OPTIONAL) {
check_delegation(node, s_data);
}
if (s_data->level & SEM_CHECK_NSEC) {
check_signed_rrsig(node, s_data);
check_rrsig(node, s_data);
check_nsec(node, s_data);
}
if(s_data->level & SEM_CHECK_NSEC3) {
check_signed_rrsig(node, s_data);
check_rrsig(node, s_data);
check_nsec3(node, s_data);
for (int i=0; i < check_functions_len; ++i) {
if (check_functions[i].level & s_data->level) {
check_functions[i].function(node, s_data);
}
}
return KNOT_EOK;
......
......@@ -122,15 +122,6 @@ typedef struct err_node {
char *data;
} err_node_t;
typedef struct semchecks_data {
zone_contents_t *zone;
err_handler_t *handler;
bool fatal_error;
const zone_node_t *next_nsec;
enum check_levels level;
} semchecks_data_t;
/*!
* \brief Inits semantic error handler. No optional events will be logged.
*
......@@ -146,8 +137,8 @@ void err_handler_init(err_handler_t *err_handler);
void err_handler_deinit(err_handler_t *h);
/*!
* \brief Called when error has been encountered in node. Will either log error
* or print it, depending on handler's options.
* \brief Called when error has been encountered in node. Will save error to
* list for future possibility to log it.
*
* \param handler Error handler.
* \param zone Zone content which is being checked.
......@@ -156,8 +147,7 @@ void err_handler_deinit(err_handler_t *h);
* \param data Additional info in string.
*
* \retval KNOT_EOK on success.
* \retval ZC_ERR_UNKNOWN if unknown error.
* \retval ZC_ERR_ALLOC if memory error.
* \retval KNOT_ENOMEM if memory error.
*/
int err_handler_handle_error(err_handler_t *handler,
const zone_contents_t *zone,
......@@ -169,9 +159,10 @@ int err_handler_handle_error(err_handler_t *handler,
* calls function that does the actual work.
*
* \param zone Zone to be searched / checked
* \param check_level Level of semantic checks.
* \param optional To do also optional check
* \param handler Semantic error handler.
* \param last_node Last checked node, that is a part of NSEC(3) chain.
* \param first_nsec3_node
* \param last_nsec3_node
*/
int zone_do_sem_checks(zone_contents_t *zone, bool optional,
err_handler_t *handler, zone_node_t *first_nsec3_node,
......
......@@ -19,92 +19,33 @@
#include <stdio.h>
#include "libknot/libknot.h"
#include "knot/zone/contents.h"
#include "knot/zone/zonefile.h"
#include "contrib/ucw/lists.h"
#include "utils/common/params.h"
#include "knot/common/log.h"
#include "utils/kzonecheck/zone_check.h"
#define PROGRAM_NAME "kzonecheck"
static void print_help(void)
{
printf("Usage: %s [parameters] <action> [action_args]\n"
printf("Usage: %s [parameters] <zonefile> \n"
"\n"
"Parameters:\n"
" -o, --origin <zone origin> blabla\n"
" (default blabla)\n"
" -o, --origin <zone_origin> Zone name\n"
" (default filename or\n"
" filename without trailing .zone)\n"
" -v, --verbose Enable debug output.\n"
" -h, --help Print the program help.\n"
" -V, --version Print the program version.\n"
"\n"
"Actions:\n",
"\n",
PROGRAM_NAME);
}
void print_errors(err_handler_t *handler)
{
err_node_t *n;
WALK_LIST(n, handler->error_list) {
if (n->error > (int)ZC_ERR_GLUE_RECORD) {
fprintf(stderr, "zone: [%s], semantic check, unknown error\n",
n->zone_name ? n->zone_name : "?");
return;
}
const char *errmsg = zonechecks_error_messages[-n->error];
fprintf(stderr ,"node: '%s' (%s%s%s)\n",
n->name ? n->name : "?",
errmsg ? errmsg : "unknown error",
n->data ? " " : "",
n->data ? n->data : "");
}
}
void print_statistics(err_handler_t *handler)
{
fprintf(stderr, "\nERRORS SUMMARY:\n\tCount\tError\n");
for(int i = ZC_ERR_UNKNOWN; i < ZC_ERR_LAST; ++i) {
if (handler->errors[-i] > 0) {
fprintf(stderr, "\t%u\t%s\n", handler->errors[-i], zonechecks_error_messages[-i]);
}
}
}
int zone_check(const char *zone_file, const knot_dname_t *zone_name)
{
zloader_t zl;
int ret = zonefile_open(&zl, zone_file, zone_name, true);
if (ret != KNOT_EOK) {
return ret;
}
zl.creator->master = true;
zone_contents_t *contents;
contents = zonefile_load(&zl);
print_errors(&zl.err_handler);
print_statistics(&zl.err_handler);
zonefile_close(&zl);
if (contents == NULL) {
return KNOT_ERROR;
}
zone_contents_deep_free(&contents);
return KNOT_EOK;
}
int main(int argc, char *argv[])
{
char *filename;
char *zonename = "";
char *zonename = NULL;
bool verbose = false;
FILE *outfile = stdout;
/* Long options. */
struct option opts[] = {
......@@ -139,17 +80,26 @@ int main(int argc, char *argv[])
/* Check if there's at least one remaining non-option. */
if (optind >= argc) {
fprintf(stderr, "Expected argument after options\n");
fprintf(outfile, "Expected argument (zone file) after options\n");
print_help();
return EXIT_FAILURE;
}
filename = argv[optind];
if (zonename == NULL) {
/* Get zone name from file name */
const char *ext = ".zone";
zonename = basename(filename);
if (strcmp(zonename+strlen(zonename)-strlen(ext), ext) == 0) {
zonename = strndup(zonename, strlen(zonename)-strlen(ext));
}
}
/* Set up simplified logging just to stdout/stderr. */
/* Set up simplified logging just to stdout */
log_init();
log_levels_set(LOGT_STDOUT, LOG_ANY, LOG_MASK(LOG_INFO) | LOG_MASK(LOG_NOTICE));
log_levels_set(LOGT_STDERR, LOG_ANY, LOG_UPTO(LOG_WARNING));
log_levels_set(LOGT_STDOUT, LOG_ANY, LOG_MASK(LOG_ERR));
log_levels_set(LOGT_STDERR, LOG_ANY, 0);
log_levels_set(LOGT_SYSLOG, LOG_ANY, 0);
log_flag_set(LOG_FNO_TIMESTAMP | LOG_FNO_INFO);
if (verbose) {
......@@ -157,12 +107,10 @@ int main(int argc, char *argv[])
}
knot_dname_t *dname = knot_dname_from_str_alloc(zonename);
int ret = zone_check(filename, dname);
printf("%d", ret);
int ret = zone_check(filename, dname, outfile);
free(dname);
return ret;
log_close();
return ret == KNOT_EOK ? EXIT_SUCCESS : EXIT_FAILURE;
}
/* Copyright (C) 2016 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "knot/zone/contents.h"
#include "knot/zone/zonefile.h"
#include "contrib/ucw/lists.h"
#include "utils/kzonecheck/zone_check.h"
void print_errors(err_handler_t *handler, FILE *outfile)
{
err_node_t *n;
WALK_LIST(n, handler->error_list) {
if (n->error > (int)ZC_ERR_GLUE_RECORD) {
fprintf(outfile, "zone: [%s], semantic check, unknown error\n",
n->zone_name ? n->zone_name : "?");
return;
}
const char *errmsg = zonechecks_error_messages[-n->error];
fprintf(outfile ,"node: '%s' (%s%s%s)\n",
n->name ? n->name : "?",
errmsg ? errmsg : "unknown error",
n->data ? " " : "",
n->data ? n->data : "");
}
}
void print_statistics(err_handler_t *handler, FILE *outfile)
{
fprintf(outfile, "\nERRORS SUMMARY:\n\tCount\tError\n");
for(int i = ZC_ERR_UNKNOWN; i < ZC_ERR_LAST; ++i) {
if (handler->errors[-i] > 0) {
fprintf(outfile, "\t%u\t%s\n", handler->errors[-i], zonechecks_error_messages[-i]);
}
}
}
int zone_check(const char *zone_file, const knot_dname_t *zone_name,
FILE *outfile)
{
zloader_t zl;
int ret = zonefile_open(&zl, zone_file, zone_name, true);
if (ret != KNOT_EOK) {
return ret;
}
zl.creator->master = true;
zone_contents_t *contents;
contents = zonefile_load(&zl);
print_errors(&zl.err_handler, outfile);
print_statistics(&zl.err_handler, outfile);
zonefile_close(&zl);
if (contents == NULL) {
return KNOT_ERROR;
}
zone_contents_deep_free(&contents);
return KNOT_EOK;
}
/* Copyright (C) 2016 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "libknot/libknot.h"
int zone_check(const char *zone_file, const knot_dname_t *zone_name,
FILE *outfile);
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