diff --git a/.gitignore b/.gitignore index c5f32d349057c9f07c6e13ce72c9cee72a47ef61..3d6e38e478b05257200c1eaac5c9f7ab7b6b619c 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,6 @@ /m4/ltsugar.m4 /m4/ltversion.m4 /m4/lt~obsolete.m4 -/src/tests/unittests_xfr /INSTALL /src/kdig /src/khost diff --git a/Knot.files b/Knot.files index 9dd8f5f4e6b7583ca51d04b87991dd925065d50c..bffc2aa25d6474addc68342434d34105d181c91c 100644 --- a/Knot.files +++ b/Knot.files @@ -129,6 +129,8 @@ src/knot/stat/gatherer.h src/knot/stat/stat-common.h src/knot/stat/stat.c src/knot/stat/stat.h +src/knot/zone/estimator.c +src/knot/zone/estimator.h src/knot/zone/semantic-check.c src/knot/zone/semantic-check.h src/knot/zone/zone-dump.c @@ -239,8 +241,6 @@ src/tests/libknot/wire_tests.h src/tests/libknot/ztree_tests.c src/tests/libknot/ztree_tests.h src/tests/unittests_main.c -src/tests/xfr_tests.c -src/tests/xfr_tests.h src/tests/zscanner/zscanner_tests.c src/tests/zscanner/zscanner_tests.h src/utils/common/exec.c @@ -281,5 +281,3 @@ src/zscanner/test/processing.h src/zscanner/test/tests.c src/zscanner/test/tests.h src/zscanner/test/zscanner-tool.c -src/knot/zone/estimator.c -src/knot/zone/estimator.h diff --git a/configure.ac b/configure.ac index 946050a4f6f9c9ca1302df6de80153f30b102b6d..9ae64978453ecdaa7d66c867afce058a795f6e06 100644 --- a/configure.ac +++ b/configure.ac @@ -68,7 +68,7 @@ AC_PROG_INSTALL # Check for Ragel AC_PATH_PROG([RAGEL], [ragel], [true]) AM_CONDITIONAL([HAVE_RAGEL], test "$RAGEL" != "true") - + # Set FSM type for Ragel AC_SUBST([FSM_TYPE], [-T0]) AC_ARG_ENABLE([fastparser], @@ -144,6 +144,11 @@ AC_ARG_ENABLE([recvmmsg], fi ]) +# Enable integrity check +AC_ARG_ENABLE([integrity-check], + AS_HELP_STRING([--enable-integrity-check], [enable integrity check in knotd via SIGUSR1]), + [AC_DEFINE([INTEGRITY_CHECK], [1], [integrity check in knotd])]) + # Check for link time optimizations support and predictive commoning AC_ARG_ENABLE([lto], AS_HELP_STRING([--enable-lto=yes|no], [enable link-time optimizations, enable if not broken for some extra speed [default=no]]), diff --git a/src/knot/main.c b/src/knot/main.c index d9e5db220dc25bed16d95153103c5ead3829d90c..963b0d8dc696cdf6a69302d960262061e25d896c 100644 --- a/src/knot/main.c +++ b/src/knot/main.c @@ -42,9 +42,14 @@ /* Signal flags. */ static volatile short sig_req_stop = 0; static volatile short sig_req_reload = 0; -static volatile short sig_req_refresh = 0; static volatile short sig_stopping = 0; +#ifdef INTEGRITY_CHECK +static volatile short sig_integrity_check = 0; +int check_iteration = 0; +char *zone = NULL; +#endif /* INTEGRITY_CHECK */ + // Cleanup handler static int do_cleanup(server_t *server, char *configf, char *pidf); @@ -57,12 +62,6 @@ void interrupt_handle(int s) return; } - // Refresh - if (s == SIGUSR2) { - sig_req_refresh = 1; - return; - } - // Stop server if (s == SIGINT || s == SIGTERM) { if (sig_stopping == 0) { @@ -72,6 +71,14 @@ void interrupt_handle(int s) exit(1); } } + +#ifdef INTEGRITY_CHECK + // Start zone integrity check + if (s == SIGUSR1) { + sig_integrity_check = 1; + return; + } +#endif /* INTEGRITY_CHECK */ } void help(void) @@ -80,6 +87,10 @@ void help(void) PACKAGE_NAME); printf("\nParameters:\n" " -c, --config [file] Select configuration file.\n" +#ifdef INTEGRITY_CHECK + " -z, --zone [zone] Set zone to check. Send SIGUSR1 to trigger\n" + " integrity check.\n" +#endif /* INTEGRITY_CHECK */ " -d, --daemonize Run server as a daemon.\n" " -v, --verbose Verbose mode - additional runtime information.\n" " -V, --version Print version of the server.\n" @@ -97,6 +108,9 @@ int main(int argc, char **argv) /* Long options. */ struct option opts[] = { {"config", required_argument, 0, 'c'}, +#ifdef INTEGRITY_CHECK + {"zone", required_argument, 0, 'z'}, +#endif /* INTEGRITY_CHECK */ {"daemonize", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, @@ -104,7 +118,11 @@ int main(int argc, char **argv) {0, 0, 0, 0} }; +#ifndef INTEGRITY_CHECK while ((c = getopt_long(argc, argv, "c:dvVh", opts, &li)) != -1) { +#else + while ((c = getopt_long(argc, argv, "c:z:dvVh", opts, &li)) != -1) { +#endif /* INTEGRITY_CHECK */ switch (c) { case 'c': @@ -124,6 +142,15 @@ int main(int argc, char **argv) free(config_fn); help(); return 0; +#ifdef INTEGRITY_CHECK + case 'z': + if (optarg[strlen(optarg) - 1] != '.') { + zone = strcdup(optarg, "."); + } else { + zone = strdup(optarg); + } + break; +#endif /* INTEGRITY_CHECK */ default: free(config_fn); help(); @@ -292,8 +319,9 @@ int main(int argc, char **argv) sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGHUP, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - sigaction(SIGUSR2, &sa, NULL); +#ifdef INTEGRITY_CHECK + sigaction(SIGUSR1, &sa, NULL); +#endif /* INTEGRITY_CHECK */ sa.sa_flags = 0; pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL); @@ -342,17 +370,29 @@ int main(int argc, char **argv) sig_req_reload = 0; server_reload(server, config_fn); } - if (sig_req_refresh) { - log_server_info("Refreshing slave zones...\n"); - sig_req_reload = 0; - int cf_ret = server_refresh(server); - if (cf_ret != KNOT_EOK) { - log_server_error("Couldn't refresh " - "slave zones - %s", - knot_strerror(cf_ret)); - } - +#ifdef INTEGRITY_CHECK + if (zone == NULL) + sig_integrity_check = 0; + if (sig_integrity_check) { + log_server_info("Starting integrity check of " + "zone: %s\n", zone); + knot_dname_t *zdn = + knot_dname_new_from_str(zone, + strlen(zone), + NULL); + knot_zone_t *z = + knot_zonedb_find_zone(server->nameserver->zone_db, + zdn); + int ic_ret = + knot_zone_contents_integrity_check(z->contents); + log_server_info("Integrity check: %d errors " + "discovered.\n", ic_ret); + knot_dname_free(&zdn); + log_server_info("Integrity check %d finished.\n", + check_iteration); + ++check_iteration; } +#endif /* INTEGRITY_CHECK */ } pthread_sigmask(SIG_UNBLOCK, &sa.sa_mask, NULL); diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 29733b777bebd28af8d69114662c44740ab8276a..bb381dcf10327818efe7cb28a2b40e1b35121e8f 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -3,8 +3,7 @@ ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 AM_CPPFLAGS = -I$(top_srcdir)/src/libknot -I$(top_srcdir)/src -DSYSCONFDIR='"$(sysconfdir)"' -DSBINDIR='"$(sbindir)"' check_PROGRAMS = \ - unittests \ - unittests_xfr + unittests TESTS = unittests @@ -63,12 +62,7 @@ unittests_SOURCES = \ libknot/sign_tests.h \ unittests_main.c -unittests_xfr_SOURCES = \ - xfr_tests.c \ - xfr_tests.h - unittests_LDADD = ../libknotd.la ../libknots.la @LIBOBJS@ -unittests_xfr_LDADD = ../libknotd.la ../libknot.la ../libknots.la @LIBOBJS@ sample_conf.rc: files/sample_conf $(top_srcdir)/resource.sh $(srcdir)/files/sample_conf >$@ diff --git a/src/tests/README b/src/tests/README deleted file mode 100644 index 1d9748b1542b4f701680cb261c11fe4e0f651eae..0000000000000000000000000000000000000000 --- a/src/tests/README +++ /dev/null @@ -1,4 +0,0 @@ -Unit testing ------------- - -Make assembles "unittest" binary with all of the planned tests included. diff --git a/src/tests/xfr_tests.c b/src/tests/xfr_tests.c deleted file mode 100644 index 5459d8f6e7c94f1b25fad352c43af0c8e5088dc3..0000000000000000000000000000000000000000 --- a/src/tests/xfr_tests.c +++ /dev/null @@ -1,379 +0,0 @@ -/* Copyright (C) 2011 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/>. - */ - -/* - * This test is basically a copy of the whole server, with following exceptions: - * - signal handler now handles one more signal - * SIGUSR1 is used to signal this - * binary that an integrity check should be done -*/ - -#include <config.h> -#include <time.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <getopt.h> -#include <assert.h> - -#include "knot/knot.h" -#include "knot/server/server.h" -#include "knot/ctl/process.h" -#include "knot/conf/conf.h" -#include "knot/conf/logconf.h" -#include "common/evqueue.h" -#include "knot/server/zones.h" - -/*----------------------------------------------------------------------------*/ - -/* Signal flags. */ -static volatile short sig_req_stop = 0; -static volatile short sig_req_reload = 0; -static volatile short sig_stopping = 0; -static volatile short sig_integrity_check = 0; - - -// SIGINT signal handler -void interrupt_handle(int s) -{ - // Reload configuration - if (s == SIGHUP) { - sig_req_reload = 1; - return; - } - - // Stop server - if (s == SIGINT || s == SIGTERM) { - if (sig_stopping == 0) { - sig_req_stop = 1; - sig_stopping = 1; - } else { - log_server_notice("OK! Exiting immediately.\n"); - exit(1); - } - } - - // Start zone integrity check - if (s == SIGUSR1) { - sig_integrity_check = 1; - return; - } -} - -void help(int argc, char **argv) -{ - printf("Usage: %sd [parameters]\n", - PACKAGE_NAME); - printf("Parameters:\n" - " -c, --config [file] Select configuration file.\n" - " -z, --zone [origin] Inspected zone origin.\n" - " -d, --daemonize Run server as a daemon.\n" - " -v, --verbose Verbose mode - additional runtime information.\n" - " -V, --version Print version of the server.\n" - " -h, --help Print help and usage.\n" - "Send SIGUSR1 to trigger integrity check.\n"); -} - -int main(int argc, char **argv) -{ - // Parse command line arguments - int check_iteration = 0; - int c = 0, li = 0; - int verbose = 0; - int daemonize = 0; - char *config_fn = NULL; - char *zone = NULL; - - /* Long options. */ - struct option opts[] = { - {"config", required_argument, 0, 'c'}, - {"zone", required_argument, 0, 'z'}, - {"daemonize", no_argument, 0, 'd'}, - {"verbose", no_argument, 0, 'v'}, - {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0} - }; - - while ((c = getopt_long(argc, argv, "c:z:dvVh", opts, &li)) != -1) { - switch (c) - { - case 'c': - config_fn = strdup(optarg); - break; - case 'd': - daemonize = 1; - break; - case 'v': - verbose = 1; - break; - case 'V': - printf("%s, version %s\n", "Knot DNS", PACKAGE_VERSION); - return 0; - case 'z': - if (optarg[strlen(optarg) - 1] != '.') { - zone = strcdup(optarg, "."); - } else { - zone = strdup(optarg); - } - break; - case 'h': - case '?': - default: - help(argc, argv); - return 1; - } - } - - // Now check if we want to daemonize - if (daemonize) { - if (daemon(1, 0) != 0) { - free(zone); - free(config_fn); - fprintf(stderr, "Daemonization failed, " - "shutting down...\n"); - return 1; - } - } - - // Register service and signal handler - struct sigaction emptyset; - memset(&emptyset, 0, sizeof(struct sigaction)); - emptyset.sa_handler = interrupt_handle; - sigemptyset(&emptyset.sa_mask); - emptyset.sa_flags = 0; - sigaction(SIGALRM, &emptyset, NULL); // Interrupt - - // Initialize log - log_init(); - - // Verbose mode - if (verbose) { - int mask = LOG_MASK(LOG_INFO)|LOG_MASK(LOG_DEBUG); - log_levels_add(LOGT_STDOUT, LOG_ANY, mask); - } - - // Initialize pseudorandom number generator - srand(time(0)); - - // Create server - server_t *server = server_create(); - - // Initialize configuration - rcu_read_lock(); - conf_add_hook(conf(), CONF_LOG, log_conf_hook, 0); - conf_add_hook(conf(), CONF_LOG, zones_ns_conf_hook, server->nameserver); - conf_add_hook(conf(), CONF_LOG, server_conf_hook, server); - rcu_read_unlock(); - - // Find implicit configuration file - if (!config_fn) { - config_fn = conf_find_default(); - } - - // Find absolute path for config file - if (config_fn[0] != '/') - { - // Get absolute path to cwd - size_t cwbuflen = 64; - char *cwbuf = malloc((cwbuflen + 2) * sizeof(char)); - while (getcwd(cwbuf, cwbuflen) == 0) { - cwbuflen *= 2; - cwbuf = realloc(cwbuf, (cwbuflen + 2) * sizeof(char)); - } - cwbuflen = strlen(cwbuf); - - // Append ending slash - if (cwbuf[cwbuflen - 1] != '/') { - cwbuf = strncat(cwbuf, "/", 1); - } - - // Assemble path to config file - char *abs_cfg = strcdup(cwbuf, config_fn); - free(config_fn); - free(cwbuf); - config_fn = abs_cfg; - } - - // Open configuration - log_server_info("Reading configuration '%s' ...\n", config_fn); - int conf_ret = conf_open(config_fn); - if (conf_ret != KNOT_EOK) { - if (conf_ret == KNOT_ENOENT) { - log_server_error("Couldn't open configuration file " - "'%s'.\n", config_fn); - } else { - log_server_error("Failed to load configuration '%s'.\n", - config_fn); - } - server_destroy(&server); - free(config_fn); - return 1; - } else { - log_server_info("Configured %d interfaces and %d zones.\n", - conf()->ifaces_count, conf()->zones_count); - } - log_server_info("\n"); - - // Create server instance - char* pidfile = pid_filename(); - - // Run server - int res = 0; - log_server_info("Starting server...\n"); - if ((res = server_start(server)) == KNOT_EOK) { - - // Save PID - int has_pid = 1; - int rc = pid_write(pidfile); - if (rc < 0) { - has_pid = 0; - log_server_warning("Failed to create " - "PID file '%s'.\n", pidfile); - } - - // Change directory if daemonized - if (daemonize) { - log_server_info("Server started as a daemon, " - "PID = %ld\n", (long)getpid()); - res = chdir("/"); - } else { - log_server_info("Server started in foreground, " - "PID = %ld\n", (long)getpid()); - } - if (has_pid) { - log_server_info("PID stored in %s\n", pidfile); - } else { - log_server_warning("Server running without PID file.\n"); - } - size_t zcount = server->nameserver->zone_db->zone_count; - if (!zcount) { - log_server_warning("Server started, but no zones served.\n"); - } - - // Setup signal handler - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = interrupt_handle; - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGUSR1, &sa, NULL); - sa.sa_flags = 0; - pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL); - - /* Run event loop. */ - evqueue_t *evq = evqueue_new(); - for(;;) { - pthread_sigmask(SIG_UNBLOCK, &sa.sa_mask, NULL); - int ret = evqueue_poll(evq, 0, 0); - pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL); - - /* Interrupts. */ - /*! \todo More robust way to exit evloop. - * Event loop should exit with a special - * event. - */ - if (sig_req_stop) { - sig_req_stop = 0; - server_stop(server); - break; - } - if (sig_req_reload) { - log_server_info("Reloading configuration...\n"); - sig_req_reload = 0; - int cf_ret = conf_open(config_fn); - switch (cf_ret) { - case KNOT_EOK: - log_server_info("Configuration " - "reloaded.\n"); - break; - case KNOT_ENOENT: - log_server_error("Configuration " - "file '%s' " - "not found.\n", - conf()->filename); - break; - default: - log_server_error("Configuration " - "reload failed.\n"); - break; - } - } - if (zone == NULL) sig_integrity_check = 0; - if (sig_integrity_check) { - log_server_info("Starting integrity check of zone: %s\n", zone); - knot_dname_t* zdn = knot_dname_new_from_str(zone, strlen(zone), NULL); - assert(zdn); - knot_zone_t *z = knot_zonedb_find_zone(server->nameserver->zone_db, zdn); - int ic_ret = knot_zone_contents_integrity_check(z->contents); - log_server_info("Integrity check: %d errors discovered.\n", ic_ret); - knot_dname_free(&zdn); - log_server_info("Integrity check %d finished.\n", check_iteration); - ++check_iteration; - } - - /* Events. */ - if (ret > 0) { - event_t ev; - if (evqueue_get(evq, &ev) == 0) { - dbg_server_verb("Event: " - "received new event.\n"); - if (ev.cb) { - ev.cb(&ev); - } - } - } - } - pthread_sigmask(SIG_UNBLOCK, &sa.sa_mask, NULL); - evqueue_free(&evq); - - if ((res = server_wait(server)) != KNOT_EOK) { - log_server_error("An error occured while " - "waiting for server to finish.\n"); - } else { - log_server_info("Server finished.\n"); - } - - } else { - log_server_fatal("An error occured while " - "starting the server.\n"); - } - - // Stop server and close log - server_destroy(&server); - - // Remove PID file - if (pid_remove(pidfile) < 0) { - log_server_warning("Failed to remove PID file.\n"); - } - - log_server_info("Shut down.\n"); - log_close(); - free(pidfile); - - // Free default config filename if exists - free(zone); - free(config_fn); - - if (!daemonize) { - fflush(stdout); - fflush(stderr); - } - - return res; -} diff --git a/src/tests/xfr_tests.h b/src/tests/xfr_tests.h deleted file mode 100644 index 29de11dd17d097c0defc00e3acb62336c9e2f49f..0000000000000000000000000000000000000000 --- a/src/tests/xfr_tests.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef XFR_TESTS_H -#define XFR_TESTS_H - -class xfr_tests -{ -public: - xfr_tests(); -}; - -#endif // XFR_TESTS_H