diff options
author | Ondřej Surý <ondrej@sury.org> | 2013-07-15 15:08:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2013-07-15 15:08:40 +0200 |
commit | 93f582ba0ad3d1f69b796b70660ccfd1530303f1 (patch) | |
tree | 0481b211d97122e6c6c2ff35ec3a5b74b88b9dfc /src | |
parent | 124965832295a277b9ca6ae9fac4f45a74a36b2a (diff) | |
download | knot-upstream/1.3.0_rc4.tar.gz |
New upstream version 1.3.0~rc4upstream/1.3.0_rc4
Diffstat (limited to 'src')
52 files changed, 1038 insertions, 2668 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a542399..46fe292 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,8 +8,8 @@ noinst_LTLIBRARIES = libknot.la libknotd.la libknots.la libzscanner.la # $(YACC) will generate header file AM_CPPFLAGS = -I$(top_srcdir)/src/libknot -DSYSCONFDIR='"$(sysconfdir)"' \ - -DSBINDIR='"$(sbindir)"' -DSTORAGE_DIR='"${storage_dir}"' \ - -DRUN_DIR='"${run_dir}"' + -DSBINDIR='"$(sbindir)"' -DCONFIG_DIR='"${config_dir}"' \ + -DSTORAGE_DIR='"${storage_dir}"' -DRUN_DIR='"${run_dir}"' AM_YFLAGS = -d libknotd_la_YFLAGS = -pcf_ -d libknotd_la_LFLAGS = # TODO: reentrant parser, prefix @@ -218,12 +218,6 @@ libknots_la_SOURCES = \ common/prng.c \ common/fdset.h \ common/fdset.c \ - common/fdset_poll.h \ - common/fdset_poll.c \ - common/fdset_kqueue.h \ - common/fdset_kqueue.c \ - common/fdset_epoll.h \ - common/fdset_epoll.c \ common/getline.h \ common/getline.c \ common/log.c \ @@ -316,5 +310,6 @@ zscanner_tool_LDADD = libknots.la libknot.la libknotd.la libzscanner.la @LIBOBJS # Create storage and run-time directories install-data-hook: + $(INSTALL) -d $(DESTDIR)/@config_dir@ $(INSTALL) -d $(DESTDIR)/@run_dir@ $(INSTALL) -d $(DESTDIR)/@storage_dir@ diff --git a/src/Makefile.in b/src/Makefile.in index 90f5050..b6494fd 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -118,10 +118,9 @@ am_libknots_la_OBJECTS = common/slab/slab.lo common/libtap/tap.lo \ common/evsched.lo common/acl.lo common/sockaddr.lo \ common/ref.lo common/errors.lo common/errcode.lo \ common/dSFMT.lo common/prng.lo common/fdset.lo \ - common/fdset_poll.lo common/fdset_kqueue.lo \ - common/fdset_epoll.lo common/getline.lo common/log.lo \ - common/mempool.lo common/hattrie/ahtable.lo \ - common/hattrie/hat-trie.lo common/hattrie/murmurhash3.lo + common/getline.lo common/log.lo common/mempool.lo \ + common/hattrie/ahtable.lo common/hattrie/hat-trie.lo \ + common/hattrie/murmurhash3.lo libknots_la_OBJECTS = $(am_libknots_la_OBJECTS) libzscanner_la_DEPENDENCIES = @LIBOBJS@ am_libzscanner_la_OBJECTS = zscanner/file_loader.lo \ @@ -326,6 +325,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RAGEL = @RAGEL@ RANLIB = @RANLIB@ +RELEASE_DATE = @RELEASE_DATE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -353,6 +353,7 @@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +config_dir = @config_dir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -398,8 +399,8 @@ noinst_LTLIBRARIES = libknot.la libknotd.la libknots.la libzscanner.la # $(YACC) will generate header file AM_CPPFLAGS = -I$(top_srcdir)/src/libknot -DSYSCONFDIR='"$(sysconfdir)"' \ - -DSBINDIR='"$(sbindir)"' -DSTORAGE_DIR='"${storage_dir}"' \ - -DRUN_DIR='"${run_dir}"' + -DSBINDIR='"$(sbindir)"' -DCONFIG_DIR='"${config_dir}"' \ + -DSTORAGE_DIR='"${storage_dir}"' -DRUN_DIR='"${run_dir}"' AM_YFLAGS = -d libknotd_la_YFLAGS = -pcf_ -d @@ -595,12 +596,6 @@ libknots_la_SOURCES = \ common/prng.c \ common/fdset.h \ common/fdset.c \ - common/fdset_poll.h \ - common/fdset_poll.c \ - common/fdset_kqueue.h \ - common/fdset_kqueue.c \ - common/fdset_epoll.h \ - common/fdset_epoll.c \ common/getline.h \ common/getline.c \ common/log.c \ @@ -992,12 +987,6 @@ common/prng.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/fdset.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) -common/fdset_poll.lo: common/$(am__dirstamp) \ - common/$(DEPDIR)/$(am__dirstamp) -common/fdset_kqueue.lo: common/$(am__dirstamp) \ - common/$(DEPDIR)/$(am__dirstamp) -common/fdset_epoll.lo: common/$(am__dirstamp) \ - common/$(DEPDIR)/$(am__dirstamp) common/getline.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/log.lo: common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) @@ -1282,12 +1271,6 @@ mostlyclean-compile: -rm -f common/evsched.lo -rm -f common/fdset.$(OBJEXT) -rm -f common/fdset.lo - -rm -f common/fdset_epoll.$(OBJEXT) - -rm -f common/fdset_epoll.lo - -rm -f common/fdset_kqueue.$(OBJEXT) - -rm -f common/fdset_kqueue.lo - -rm -f common/fdset_poll.$(OBJEXT) - -rm -f common/fdset_poll.lo -rm -f common/getline.$(OBJEXT) -rm -f common/getline.lo -rm -f common/hattrie/ahtable.$(OBJEXT) @@ -1467,9 +1450,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/evqueue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/evsched.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset_epoll.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset_kqueue.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset_poll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/getline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/heap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/lists.Plo@am__quote@ @@ -2009,6 +1989,7 @@ uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS # Create storage and run-time directories install-data-hook: + $(INSTALL) -d $(DESTDIR)/@config_dir@ $(INSTALL) -d $(DESTDIR)/@run_dir@ $(INSTALL) -d $(DESTDIR)/@storage_dir@ diff --git a/src/common/errcode.c b/src/common/errcode.c index c03b473..b555805 100644 --- a/src/common/errcode.c +++ b/src/common/errcode.c @@ -76,7 +76,6 @@ const error_table_t knot_error_msgs[] = { /* Control states. */ { KNOT_CTL_STOP, "Stopping server." }, - { KNOT_CTL_RESTART, "Restarting server." }, /* Network errors. */ { KNOT_NET_EADDR, "Bad address or host name." }, diff --git a/src/common/errcode.h b/src/common/errcode.h index 13d1943..69f6ed5 100644 --- a/src/common/errcode.h +++ b/src/common/errcode.h @@ -95,7 +95,6 @@ enum knot_error { /* Control states. */ KNOT_CTL_STOP, /*!< Stop requested. */ - KNOT_CTL_RESTART, /*!< Restart requested. */ /* Network errors. */ KNOT_NET_EADDR, diff --git a/src/common/evqueue.c b/src/common/evqueue.c index 097d177..4b89554 100644 --- a/src/common/evqueue.c +++ b/src/common/evqueue.c @@ -22,9 +22,6 @@ #include "common/evqueue.h" #include "common/fdset.h" -/*! \brief Singleton application-wide event queue. */ -evqueue_t *s_evqueue = 0; - evqueue_t *evqueue_new() { evqueue_t* q = malloc(sizeof(evqueue_t)); diff --git a/src/common/evqueue.h b/src/common/evqueue.h index ffb3860..794b2d5 100644 --- a/src/common/evqueue.h +++ b/src/common/evqueue.h @@ -178,23 +178,6 @@ int evqueue_get(evqueue_t *q, event_t *ev); */ int evqueue_add(evqueue_t *q, const event_t *ev); -/* Singleton event queue pointer. */ -extern evqueue_t *s_evqueue; - -/*! - * \brief Event queue singleton. - */ -static inline evqueue_t *evqueue() { - return s_evqueue; -} - -/*! - * \brief Set event queue singleton. - */ -static inline void evqueue_set(evqueue_t *q) { - s_evqueue = q; -} - #endif /* _KNOTD_COMMON_EVQUEUE_H_ */ /*! @} */ diff --git a/src/common/fdset.c b/src/common/fdset.c index 3b4b75a..5f93d27 100644 --- a/src/common/fdset.c +++ b/src/common/fdset.c @@ -15,12 +15,11 @@ */ #include <config.h> -#include <dlfcn.h> +#include <stdlib.h> #include <string.h> -#include <stdio.h> #include <time.h> -#include <stdlib.h> #include "common/fdset.h" +#include "common.h" /* Workarounds for clock_gettime() not available on some platforms. */ #ifdef HAVE_CLOCK_GETTIME @@ -34,171 +33,137 @@ typedef struct timeval timev_t; #error Neither clock_gettime() nor gettimeofday() found. At least one is required. #endif -struct fdset_backend_t _fdset_backend = { - NULL -}; +/* Realloc memory or return error (part of fdset_resize). */ +#define MEM_RESIZE(tmp, p, n) \ + if ((tmp = realloc((p), (n))) == NULL) \ + return KNOT_ENOMEM; \ + (p) = tmp; -/*! \brief Set backend implementation. */ -static void fdset_set_backend(struct fdset_backend_t *backend) { - memcpy(&_fdset_backend, backend, sizeof(struct fdset_backend_t)); +static int fdset_resize(fdset_t *set, unsigned size) +{ + void *tmp = NULL; + MEM_RESIZE(tmp, set->ctx, size * sizeof(void*)); + MEM_RESIZE(tmp, set->pfd, size * sizeof(struct pollfd)); + MEM_RESIZE(tmp, set->timeout, size * sizeof(timev_t)); + set->size = size; + return KNOT_EOK; } -/* Linux epoll API. */ -#ifdef HAVE_EPOLL_WAIT - #include "common/fdset_epoll.h" -#endif /* HAVE_EPOLL_WAIT */ - -/* BSD kqueue API */ -#ifdef HAVE_KQUEUE - #include "common/fdset_kqueue.h" -#endif /* HAVE_KQUEUE */ - -/* POSIX poll API */ -#ifdef HAVE_POLL - #include "common/fdset_poll.h" -#endif /* HAVE_POLL */ - -/*! \brief Bootstrap polling subsystem (it is called automatically). */ -void __attribute__ ((constructor)) fdset_init() +int fdset_init(fdset_t *set, unsigned size) { - /* Preference: epoll */ -#ifdef HAVE_EPOLL_WAIT - if (dlsym(RTLD_DEFAULT, "epoll_wait") != 0) { - fdset_set_backend(&FDSET_EPOLL); - return; + if (set == NULL) { + return KNOT_EINVAL; } -#endif - /* Preference: kqueue */ -#ifdef HAVE_KQUEUE - if (dlsym(RTLD_DEFAULT, "kqueue") != 0) { - fdset_set_backend(&FDSET_KQUEUE); - return; - } -#endif + memset(set, 0, sizeof(fdset_t)); + return fdset_resize(set, size); +} - /* Fallback: poll */ -#ifdef HAVE_POLL - if (dlsym(RTLD_DEFAULT, "poll") != 0) { - fdset_set_backend(&FDSET_POLL); - return; +int fdset_clear(fdset_t* set) +{ + if (set == NULL) { + return KNOT_EINVAL; } -#endif - /* This shouldn't happen. */ - fprintf(stderr, "fdset: fatal error - no valid fdset backend found\n"); - return; + free(set->ctx); + free(set->pfd); + free(set->timeout); + memset(set, 0, sizeof(fdset_t)); + return KNOT_EOK; } -/*! - * \brief Compare file descriptors. - * - * \param a File descriptor. - * \param b File descriptor. - * - * \retval -1 if a < b - * \retval 0 if a == b - * \retval 1 if a > b - */ -static inline int fdset_compare(void *a, void *b) +int fdset_add(fdset_t *set, int fd, unsigned events, void *ctx) { - if (a > b) return 1; - if (a < b) return -1; - return 0; -} - -fdset_t *fdset_new() { - fdset_t* set = _fdset_backend.fdset_new(); - fdset_base_t *base = (fdset_base_t*)set; - if (base != NULL) { - /* Create atimes list. */ - base->atimes = skip_create_list(fdset_compare); - if (base->atimes == NULL) { - fdset_destroy(set); - set = NULL; - } + if (set == NULL || fd < 0) { + return KNOT_EINVAL; } - return set; + + /* Realloc needed. */ + if (set->n == set->size && fdset_resize(set, set->size + FDSET_INIT_SIZE)) + return KNOT_ENOMEM; + + /* Initialize. */ + int i = set->n++; + set->pfd[i].fd = fd; + set->pfd[i].events = events; + set->pfd[i].revents = 0; + set->ctx[i] = ctx; + set->timeout[i] = 0; + + /* Return index to this descriptor. */ + return i; } -int fdset_destroy(fdset_t* fdset) { - fdset_base_t *base = (fdset_base_t*)fdset; - if (base != NULL && base->atimes != NULL) { - skip_destroy_list(&base->atimes, NULL, free); +int fdset_remove(fdset_t *set, unsigned i) +{ + if (set == NULL || i >= set->n) { + return KNOT_EINVAL; } - return _fdset_backend.fdset_destroy(fdset); -} -int fdset_remove(fdset_t *fdset, int fd) { - fdset_base_t *base = (fdset_base_t*)fdset; - if (base != NULL && base->atimes != NULL) { - skip_remove(base->atimes, (void*)((size_t)fd), NULL, free); + /* Decrement number of elms. */ + --set->n; + + /* Nothing else if it is the last one. + * Move last -> i if some remain. */ + unsigned last = set->n; /* Already decremented */ + if (i < last) { + set->pfd[i] = set->pfd[last]; + set->timeout[i] = set->timeout[last]; + set->ctx[i] = set->ctx[last]; } - return _fdset_backend.fdset_remove(fdset, fd); + + return KNOT_EOK; } -int fdset_set_watchdog(fdset_t* fdset, int fd, int interval) +int fdset_set_watchdog(fdset_t* set, int i, int interval) { - fdset_base_t *base = (fdset_base_t*)fdset; - if (base == NULL || base->atimes == NULL) { - return -1; + if (set == NULL || i >= set->n) { + return KNOT_EINVAL; } /* Lift watchdog if interval is negative. */ if (interval < 0) { - skip_remove(base->atimes, (void*)((size_t)fd), NULL, free); - return 0; - } - - /* Find if exists. */ - timev_t *ts = NULL; - ts = (timev_t*)skip_find(base->atimes, (void*)((size_t)fd)); - if (ts == NULL) { - ts = malloc(sizeof(timev_t)); - if (ts == NULL) { - return -1; - } - skip_insert(base->atimes, (void*)((size_t)fd), (void*)ts, NULL); + set->timeout[i] = 0; + return KNOT_EOK; } /* Update clock. */ - if (time_now(ts) < 0) { - return -1; - } + timev_t now; + if (time_now(&now) < 0) + return KNOT_ERROR; - ts->tv_sec += interval; /* Only seconds precision. */ - return 0; + set->timeout[i] = now.tv_sec + interval; /* Only seconds precision. */ + return KNOT_EOK; } -int fdset_sweep(fdset_t* fdset, void(*cb)(fdset_t*, int, void*), void *data) +int fdset_sweep(fdset_t* set, fdset_sweep_cb_t cb, void *data) { - fdset_base_t *base = (fdset_base_t*)fdset; - if (base == NULL || base->atimes == NULL) { - return -1; + if (set == NULL || cb == NULL) { + return KNOT_EINVAL; } /* Get time threshold. */ timev_t now; if (time_now(&now) < 0) { - return -1; + return KNOT_ERROR; } - /* Inspect all nodes. */ - int sweeped = 0; - const skip_node_t *n = skip_first(base->atimes); - while (n != NULL) { - const skip_node_t* pnext = skip_next(n); - - /* Evaluate */ - timev_t *ts = (timev_t*)n->value; - if (ts->tv_sec <= now.tv_sec) { - cb(fdset, (int)(((ssize_t)n->key)), data); - ++sweeped; + unsigned i = 0; + while (i < set->n) { + + /* Check sweep state, remove if requested. */ + if (set->timeout[i] > 0 && set->timeout[i] <= now.tv_sec) { + if (cb(set, i, data) == FDSET_SWEEP) { + if (fdset_remove(set, i) == KNOT_EOK) + continue; /* Stay on the index. */ + } } - n = pnext; + + /* Next descriptor. */ + ++i; } - return sweeped; + return KNOT_EOK; } /* OpenBSD compatibility. */ diff --git a/src/common/fdset.h b/src/common/fdset.h index e1facdb..f0ef849 100644 --- a/src/common/fdset.h +++ b/src/common/fdset.h @@ -18,12 +18,7 @@ * * \author Marek Vavrusa <marek.vavrusa@nic.cz> * - * \brief Wrapper for native I/O multiplexing. - * - * Selects best implementation according to config. - * - poll() - * - epoll() - * - kqueue() + * \brief I/O multiplexing with context and timeouts for each fd. * * \addtogroup common_lib * @{ @@ -32,88 +27,36 @@ #ifndef _KNOTD_FDSET_H_ #define _KNOTD_FDSET_H_ +#include <config.h> #include <stddef.h> -#ifdef HAVE_SYS_SELECT_H - #include <sys/select.h> -#endif -#ifdef HAVE_SYS_TIME_H - #include <sys/time.h> -#endif -#ifdef HAVE_SIGNAL_H - #include <signal.h> -#endif -#include "skip-list.h" -#include "mempattern.h" - -/*! \brief Waiting for completion constants. */ -enum fdset_wait_t { - OS_EV_FOREVER = -1, /*!< Wait forever. */ - OS_EV_NOWAIT = 0 /*!< Return immediately. */ +#include <poll.h> +#include <sys/time.h> +#include <signal.h> + +#define FDSET_INIT_SIZE 256 /* Resize step. */ + +/*! \brief Set of filedescriptors with associated context and timeouts. */ +typedef struct fdset { + unsigned n; /*!< Active fds. */ + unsigned size; /*!< Array size (allocated). */ + void* *ctx; /*!< Context for each fd. */ + struct pollfd *pfd; /*!< poll state for each fd */ + time_t *timeout; /*!< Timeout for each fd (seconds precision). */ +} fdset_t; + +/*! \brief Mark-and-sweep state. */ +enum fdset_sweep_state { + FDSET_KEEP, + FDSET_SWEEP }; -/*! \brief Base for implementation-specific fdsets. */ -typedef struct fdset_base_t { - skip_list_t *atimes; -} fdset_base_t; +/*! \brief Sweep callback (set, index, data) */ +typedef enum fdset_sweep_state (*fdset_sweep_cb_t)(fdset_t*, int, void*); /*! - * \brief Opaque pointer to implementation-specific fdset data. - * \warning Implementation MUST have fdset_base_t member on the first place. - * Example: - * struct fdset_t { - * fdset_base_t base; - * ...other members... - * } + * \brief Initialize fdset to given size. */ -typedef struct fdset_t fdset_t; - -/*! \brief Unified event types. */ -enum fdset_event_t { - OS_EV_READ = 1 << 0, /*!< Readable event. */ - OS_EV_WRITE = 1 << 1, /*!< Writeable event. */ - OS_EV_ERROR = 1 << 2 /*!< Error event. */ -}; - -/*! \brief File descriptor set iterator. */ -typedef struct fdset_it_t { - int fd; /*!< Current file descriptor. */ - int events; /*!< Returned events. */ - size_t pos; /* Internal usage. */ -} fdset_it_t; - -/*! - * \brief File descriptor set implementation backend. - * \note Functions documentation following. - * \internal - */ -struct fdset_backend_t -{ - fdset_t* (*fdset_new)(); - int (*fdset_destroy)(fdset_t*); - int (*fdset_add)(fdset_t*, int, int); - int (*fdset_remove)(fdset_t*, int); - int (*fdset_wait)(fdset_t*, int); - int (*fdset_begin)(fdset_t*, fdset_it_t*); - int (*fdset_end)(fdset_t*, fdset_it_t*); - int (*fdset_next)(fdset_t*, fdset_it_t*); - const char* (*fdset_method)(); -}; - -/*! - * \brief Selected backend. - * \internal - */ -extern struct fdset_backend_t _fdset_backend; - -/*! - * \brief Create new fdset. - * - * FDSET implementation depends on system. - * - * \retval Pointer to initialized FDSET structure if successful. - * \retval NULL on error. - */ -fdset_t *fdset_new(); +int fdset_init(fdset_t *set, unsigned size); /*! * \brief Destroy FDSET. @@ -121,125 +64,61 @@ fdset_t *fdset_new(); * \retval 0 if successful. * \retval -1 on error. */ -int fdset_destroy(fdset_t* fdset); +int fdset_clear(fdset_t* set); /*! * \brief Add file descriptor to watched set. * - * \param fdset Target set. + * \param set Target set. * \param fd Added file descriptor. * \param events Mask of watched events. + * \param ctx Context (optional). * - * \retval 0 if successful. + * \retval index of the added fd if successful. * \retval -1 on errors. */ -static inline int fdset_add(fdset_t *fdset, int fd, int events) { - return _fdset_backend.fdset_add(fdset, fd, events); -} - +int fdset_add(fdset_t *set, int fd, unsigned events, void *ctx); /*! * \brief Remove file descriptor from watched set. * - * \param fdset Target set. - * \param fd File descriptor to be removed. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_remove(fdset_t *fdset, int fd); - -/*! - * \brief Poll set for new events. - * - * \param fdset Target set. - * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds). - * - * \retval Number of events if successful. - * \retval -1 on errors. - */ -static inline int fdset_wait(fdset_t *fdset, int timeout) { - return _fdset_backend.fdset_wait(fdset, timeout); -} - -/*! - * \brief Set event iterator to the beginning of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -static inline int fdset_begin(fdset_t *fdset, fdset_it_t *it) { - return _fdset_backend.fdset_begin(fdset, it); -} - -/*! - * \brief Set event iterator to the end of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. + * \param set Target set. + * \param i Index of the removed fd. * * \retval 0 if successful. * \retval -1 on errors. */ -static inline int fdset_end(fdset_t *fdset, fdset_it_t *it) { - return _fdset_backend.fdset_end(fdset, it); -} - -/*! - * \brief Set event iterator to the next event. - * - * Event iterator fd will be set to -1 if next event doesn't exist. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -static inline int fdset_next(fdset_t *fdset, fdset_it_t *it) { - return _fdset_backend.fdset_next(fdset, it); -} - -/*! - * \brief Returned name of underlying poll method. - * - * \retval Name if successful. - * \retval NULL if no method was loaded (shouldn't happen). - */ -static inline const char* fdset_method() { - return _fdset_backend.fdset_method(); -} +int fdset_remove(fdset_t *set, unsigned i); /*! * \brief Set file descriptor watchdog interval. * - * Descriptors without activity in given interval - * can be disposed with fdset_sweep(). + * Set time (interval from now) after which the associated file descriptor + * should be sweeped (see fdset_sweep). Good example is setting a grace period + * of N seconds between socket activity. If socket is not active within + * <now, now + interval>, it is sweeped and potentially closed. * - * \param fdset Target set. - * \param fd File descriptor. + * \param set Target set. + * \param i Index for the file descriptor. * \param interval Allowed interval without activity (seconds). - * <0 removes watchdog interval. + * -1 disables watchdog timer * * \retval 0 if successful. * \retval -1 on errors. */ -int fdset_set_watchdog(fdset_t* fdset, int fd, int interval); +int fdset_set_watchdog(fdset_t* set, int i, int interval); /*! * \brief Sweep file descriptors with exceeding inactivity period. * * \param fdset Target set. * \param cb Callback for sweeped descriptors. - * \param data Custom data for sweep operation. + * \param data Pointer to extra data. * * \retval number of sweeped descriptors. * \retval -1 on errors. */ -int fdset_sweep(fdset_t* fdset, void(*cb)(fdset_t*, int, void*), void *data); +int fdset_sweep(fdset_t* set, fdset_sweep_cb_t cb, void *data); /*! * \brief pselect(2) compatibility wrapper. diff --git a/src/common/fdset_epoll.c b/src/common/fdset_epoll.c deleted file mode 100644 index f889dd3..0000000 --- a/src/common/fdset_epoll.c +++ /dev/null @@ -1,205 +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/>. - */ - -#include <config.h> - -#ifdef HAVE_EPOLL_WAIT - -#include <sys/epoll.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> - -#include "fdset_epoll.h" -#include "skip-list.h" - -#define OS_FDS_CHUNKSIZE 8 /*!< Number of pollfd structs in a chunk. */ - -struct fdset_t { - fdset_base_t _base; - int epfd; - struct epoll_event *events; - size_t nfds; - size_t reserved; - size_t polled; -}; - -fdset_t *fdset_epoll_new() -{ - fdset_t *set = malloc(sizeof(fdset_t)); - if (set) { - /* Blank memory. */ - memset(set, 0, sizeof(fdset_t)); - - /* Create epoll fd. */ - set->epfd = epoll_create(OS_FDS_CHUNKSIZE); - } - - return set; -} - -int fdset_epoll_destroy(fdset_t * fdset) -{ - if(fdset == NULL) { - return -1; - } - - /* Teardown epoll. */ - close(fdset->epfd); - - /* OK if NULL. */ - free(fdset->events); - free(fdset); - return 0; -} - -int fdset_epoll_add(fdset_t *fdset, int fd, int events) -{ - if (fdset == NULL || fd < 0 || events <= 0) { - return -1; - } - - /* Realloc needed. */ - if (mreserve((char **)&fdset->events, sizeof(struct epoll_event), - fdset->nfds + 1, OS_FDS_CHUNKSIZE, &fdset->reserved) < 0) { - return -1; - } - - /* Add to epoll set. */ - struct epoll_event ev; - memset(&ev, 0, sizeof(struct epoll_event)); - ev.events = EPOLLIN; - ev.data.fd = fd; - if (epoll_ctl(fdset->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { - return -1; - } - - ++fdset->nfds; - return 0; -} - -int fdset_epoll_remove(fdset_t *fdset, int fd) -{ - if (fdset == NULL || fd < 0) { - return -1; - } - - /* Attempt to remove from set. */ - struct epoll_event ev; - memset(&ev, 0, sizeof(struct epoll_event)); - if (epoll_ctl(fdset->epfd, EPOLL_CTL_DEL, fd, &ev) < 0) { - return -1; - } - - /* Overwrite current item. */ - --fdset->nfds; - - /* Trim excessive memory if possible (retval is not interesting). */ - mreserve((char **)&fdset->events, sizeof(struct epoll_event), - fdset->nfds + 1, OS_FDS_CHUNKSIZE, &fdset->reserved); - - return 0; -} - -int fdset_epoll_wait(fdset_t *fdset, int timeout) -{ - if (fdset == NULL || fdset->nfds < 1 || fdset->events == NULL) { - return -1; - } - - /* Poll new events. */ - fdset->polled = 0; - int nfds = epoll_wait(fdset->epfd, fdset->events, fdset->nfds, timeout); - - /* Check. */ - if (nfds < 0) { - return -1; - } - - /* Events array is ordered from 0 to nfds. */ - fdset->polled = nfds; - return nfds; -} - -int fdset_epoll_begin(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL) { - return -1; - } - - /* Find first. */ - it->pos = 0; - return fdset_next(fdset, it); -} - -int fdset_epoll_end(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL || fdset->nfds < 1) { - return -1; - } - - /* Check for polled events. */ - if (fdset->polled < 1) { - it->fd = -1; - it->pos = 0; - return -1; - } - - /* No end found, ends on the beginning. */ - size_t nid = fdset->polled - 1; - it->fd = fdset->events[nid].data.fd; - it->pos = nid; - it->events = 0; - return -1; -} - -int fdset_epoll_next(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL || fdset->nfds < 1) { - return -1; - } - - /* Check boundaries. */ - if (it->pos >= fdset->polled || it->pos >= fdset->nfds) { - return -1; - } - - /* Select next. */ - size_t nid = it->pos++; - it->fd = fdset->events[nid].data.fd; - it->events = 0; - return 0; -} - -const char* fdset_epoll_method() -{ - return "epoll"; -} - -/* Package APIs. */ -struct fdset_backend_t FDSET_EPOLL = { - .fdset_new = fdset_epoll_new, - .fdset_destroy = fdset_epoll_destroy, - .fdset_add = fdset_epoll_add, - .fdset_remove = fdset_epoll_remove, - .fdset_wait = fdset_epoll_wait, - .fdset_begin = fdset_epoll_begin, - .fdset_end = fdset_epoll_end, - .fdset_next = fdset_epoll_next, - .fdset_method = fdset_epoll_method -}; - -#endif diff --git a/src/common/fdset_epoll.h b/src/common/fdset_epoll.h deleted file mode 100644 index 58f25f8..0000000 --- a/src/common/fdset_epoll.h +++ /dev/null @@ -1,132 +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/>. - */ -/*! - * \file fdset_epoll.h - * - * \author Marek Vavrusa <marek.vavrusa@nic.cz> - * - * \brief Wrapper for epoll I/O multiplexing. - * - * \addtogroup common_lib - * @{ - */ - -#ifndef _KNOTD_FDSET_EPOLL_H_ -#define _KNOTD_FDSET_EPOLL_H_ - -#include "fdset.h" - -/*! - * \brief Create new fdset. - * - * Linux epoll() backend. - * - * \retval Pointer to initialized FDSET structure if successful. - * \retval NULL on error. - */ -fdset_t *fdset_epoll_new(); - -/*! - * \brief Destroy FDSET. - * - * \retval 0 if successful. - * \retval -1 on error. - */ -int fdset_epoll_destroy(fdset_t * fdset); - -/*! - * \brief Add file descriptor to watched set. - * - * \param fdset Target set. - * \param fd Added file descriptor. - * \param events Mask of watched events. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_epoll_add(fdset_t *fdset, int fd, int events); - -/*! - * \brief Remove file descriptor from watched set. - * - * \param fdset Target set. - * \param fd File descriptor to be removed. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_epoll_remove(fdset_t *fdset, int fd); - -/*! - * \brief Poll set for new events. - * - * \param fdset Target set. - * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds). - * - * \retval Number of events if successful. - * \retval -1 on errors. - */ -int fdset_epoll_wait(fdset_t *fdset, int timeout); - -/*! - * \brief Set event iterator to the beginning of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_epoll_begin(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Set event iterator to the end of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_epoll_end(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Set event iterator to the next event. - * - * Event iterator fd will be set to -1 if next event doesn't exist. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_epoll_next(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Returned name of epoll method. - * - * \retval Name if successful. - * \retval NULL if no method was loaded (shouldn't happen). - */ -const char* fdset_epoll_method(); - -/*! \brief Exported API. */ -extern struct fdset_backend_t FDSET_EPOLL; - -#endif /* _KNOTD_FDSET_EPOLL_H_ */ - -/*! @} */ diff --git a/src/common/fdset_kqueue.c b/src/common/fdset_kqueue.c deleted file mode 100644 index 7c52f71..0000000 --- a/src/common/fdset_kqueue.c +++ /dev/null @@ -1,260 +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/>. - */ - -#include <config.h> -#ifdef HAVE_KQUEUE - -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/event.h> -#include <sys/time.h> -#include <time.h> - -#include "fdset_kqueue.h" - -#define OS_FDS_CHUNKSIZE 8 /*!< Number of pollfd structs in a chunk. */ -#define OS_FDS_KEEPCHUNKS 32 /*!< Will attempt to free memory when reached. */ - -struct fdset_t { - fdset_base_t _base; - int kq; - struct kevent *events; - struct kevent *revents; - size_t nfds; - size_t reserved; - size_t rreserved; - size_t polled; -}; - -fdset_t *fdset_kqueue_new() -{ - fdset_t *set = malloc(sizeof(fdset_t)); - if (set) { - /* Blank memory. */ - memset(set, 0, sizeof(fdset_t)); - - /* Create kqueue fd. */ - set->kq = kqueue(); - if (set->kq < 0) { - free(set); - set = 0; - } - } - - return set; -} - -int fdset_kqueue_destroy(fdset_t * fdset) -{ - if(fdset == NULL) { - return -1; - } - - /* Teardown kqueue. */ - close(fdset->kq); - - /* OK if NULL. */ - free(fdset->revents); - free(fdset->events); - free(fdset); - return 0; -} - -int fdset_kqueue_add(fdset_t *fdset, int fd, int events) -{ - if (fdset == NULL || fd < 0 || events <= 0) { - return -1; - } - - /* Realloc needed. */ - int ret = 0; - ret += mreserve((char **)&fdset->events, sizeof(struct kevent), - fdset->nfds + 1, OS_FDS_CHUNKSIZE, &fdset->reserved); - ret += mreserve((char **)&fdset->revents, sizeof(struct kevent), - fdset->nfds + 1, OS_FDS_CHUNKSIZE, &fdset->rreserved); - if (ret != 0) { - return ret; - } - - /* Add to kqueue set. */ - int evfilt = EVFILT_READ; - EV_SET(&fdset->events[fdset->nfds], fd, evfilt, - EV_ADD|EV_ENABLE, 0, 0, 0); - memset(fdset->revents + fdset->nfds, 0, sizeof(struct kevent)); - - ++fdset->nfds; - return 0; -} - -int fdset_kqueue_remove(fdset_t *fdset, int fd) -{ - if (fdset == NULL || fd < 0) { - return -1; - } - - /* Find in set. */ - int pos = -1; - for (int i = 0; i < fdset->nfds; ++i) { - if (fdset->events[i].ident == fd) { - pos = i; - break; - } - } - - if (pos < 0) { - return -1; - } - - /* Remove filters. */ - EV_SET(&fdset->events[pos], fd, EVFILT_READ, - EV_DISABLE|EV_DELETE, 0, 0, 0); - - /* Attempt to remove from set. */ - size_t remaining = ((fdset->nfds - pos) - 1) * sizeof(struct kevent); - memmove(fdset->events + pos, fdset->events + (pos + 1), remaining); - - /* Attempt to remove from revents set. */ - pos = -1; - for (int i = 0; i < fdset->nfds; ++i) { - if (fdset->events[i].ident == fd) { - pos = i; - break; - } - } - if (pos >= 0) { - size_t remaining = ((fdset->nfds - pos) - 1) * sizeof(struct kevent); - memmove(fdset->revents + pos, fdset->revents + (pos + 1), remaining); - } - - - /* Overwrite current item. */ - --fdset->nfds; - - /* Trim excessive memory if possible (retval is not interesting). */ - mreserve((char **)&fdset->events, sizeof(struct kevent), - fdset->nfds, OS_FDS_CHUNKSIZE, &fdset->reserved); - mreserve((char **)&fdset->revents, sizeof(struct kevent), - fdset->nfds, OS_FDS_CHUNKSIZE, &fdset->rreserved); - - return 0; -} - -int fdset_kqueue_wait(fdset_t *fdset, int timeout) -{ - if (fdset == NULL || fdset->nfds < 1 || fdset->events == NULL) { - return -1; - } - - /* Set timeout. */ - struct timespec tmval; - struct timespec *tm = NULL; - if (timeout == 0) { - tmval.tv_sec = tmval.tv_nsec = 0; - tm = &tmval; - } else if (timeout > 0) { - tmval.tv_sec = timeout / 1000; /* ms -> s */ - timeout -= tmval.tv_sec * 1000; /* Cut off */ - tmval.tv_nsec = timeout * 1000000L; /* ms -> ns */ - tm = &tmval; - } - - /* Poll new events. */ - fdset->polled = 0; - int nfds = kevent(fdset->kq, fdset->events, fdset->nfds, - fdset->revents, fdset->nfds, tm); - - /* Check. */ - if (nfds < 0) { - return -1; - } - - /* Events array is ordered from 0 to nfds. */ - fdset->polled = nfds; - return nfds; -} - -int fdset_kqueue_begin(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL) { - return -1; - } - - /* Find first. */ - it->pos = 0; - it->fd = -1; - return fdset_next(fdset, it); -} - -int fdset_kqueue_end(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL || fdset->nfds < 1) { - return -1; - } - - /* Check for polled events. */ - if (fdset->polled < 1) { - it->fd = -1; - it->pos = 0; - return -1; - } - - /* No end found, ends on the beginning. */ - size_t nid = fdset->polled - 1; - it->fd = fdset->revents[nid].ident; - it->pos = nid; - it->events = 0; /*! \todo Map events. */ - return -1; -} - -int fdset_kqueue_next(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL || fdset->polled < 1) { - return -1; - } - - /* Check boundaries. */ - if (it->pos >= fdset->polled || it->pos >= fdset->nfds) { - return -1; - } - - /* Select next. */ - size_t nid = it->pos++; - it->fd = fdset->revents[nid].ident; - it->events = 0; /*! \todo Map events. */ - return 0; -} - -const char* fdset_kqueue_method() -{ - return "kqueue"; -} - -/* Package APIs. */ -struct fdset_backend_t FDSET_KQUEUE = { - .fdset_new = fdset_kqueue_new, - .fdset_destroy = fdset_kqueue_destroy, - .fdset_add = fdset_kqueue_add, - .fdset_remove = fdset_kqueue_remove, - .fdset_wait = fdset_kqueue_wait, - .fdset_begin = fdset_kqueue_begin, - .fdset_end = fdset_kqueue_end, - .fdset_next = fdset_kqueue_next, - .fdset_method = fdset_kqueue_method -}; - -#endif diff --git a/src/common/fdset_kqueue.h b/src/common/fdset_kqueue.h deleted file mode 100644 index 4b650a7..0000000 --- a/src/common/fdset_kqueue.h +++ /dev/null @@ -1,132 +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/>. - */ -/*! - * \file fdset_kqueue.h - * - * \author Marek Vavrusa <marek.vavrusa@nic.cz> - * - * \brief Wrapper for kqueue I/O multiplexing. - * - * \addtogroup common_lib - * @{ - */ - -#ifndef _KNOTD_FDSET_KQUEUE_H_ -#define _KNOTD_FDSET_KQUEUE_H_ - -#include "fdset.h" - -/*! - * \brief Create new fdset. - * - * BSD kqueue() backend. - * - * \retval Pointer to initialized FDSET structure if successful. - * \retval NULL on error. - */ -fdset_t *fdset_kqueue_new(); - -/*! - * \brief Destroy FDSET. - * - * \retval 0 if successful. - * \retval -1 on error. - */ -int fdset_kqueue_destroy(fdset_t * fdset); - -/*! - * \brief Add file descriptor to watched set. - * - * \param fdset Target set. - * \param fd Added file descriptor. - * \param events Mask of watched events. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_kqueue_add(fdset_t *fdset, int fd, int events); - -/*! - * \brief Remove file descriptor from watched set. - * - * \param fdset Target set. - * \param fd File descriptor to be removed. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_kqueue_remove(fdset_t *fdset, int fd); - -/*! - * \brief Poll set for new events. - * - * \param fdset Target set. - * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds). - * - * \retval Number of events if successful. - * \retval -1 on errors. - */ -int fdset_kqueue_wait(fdset_t *fdset, int timeout); - -/*! - * \brief Set event iterator to the beginning of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_kqueue_begin(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Set event iterator to the end of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_kqueue_end(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Set event iterator to the next event. - * - * Event iterator fd will be set to -1 if next event doesn't exist. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_kqueue_next(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Returned name of kqueue method. - * - * \retval Name if successful. - * \retval NULL if no method was loaded (shouldn't happen). - */ -const char* fdset_kqueue_method(); - -/*! \brief Exported API. */ -extern struct fdset_backend_t FDSET_KQUEUE; - -#endif /* _KNOTD_FDSET_KQUEUE_H_ */ - -/*! @} */ diff --git a/src/common/fdset_poll.c b/src/common/fdset_poll.c deleted file mode 100644 index e16ae11..0000000 --- a/src/common/fdset_poll.c +++ /dev/null @@ -1,218 +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/>. - */ - -#include <config.h> - -#ifdef HAVE_POLL - -#include <stdlib.h> -#include <string.h> -#include <sys/poll.h> -#include <stddef.h> - -#include "common/fdset_poll.h" - -#define OS_FDS_CHUNKSIZE 8 /*!< Number of pollfd structs in a chunk. */ - -struct fdset_t { - fdset_base_t _base; - struct pollfd *fds; - nfds_t nfds; - size_t reserved; - size_t polled; - size_t begin; -}; - -fdset_t *fdset_poll_new() -{ - fdset_t *set = malloc(sizeof(fdset_t)); - if (set != NULL) { - memset(set, 0, sizeof(fdset_t)); - } - - return set; -} - -int fdset_poll_destroy(fdset_t * fdset) -{ - if(fdset == NULL) { - return -1; - } - - /* OK if NULL. */ - free(fdset->fds); - free(fdset); - return 0; -} - -int fdset_poll_add(fdset_t *fdset, int fd, int events) -{ - if (fdset == NULL || fd < 0 || events <= 0) { - return -1; - } - - /* Realloc needed. */ - if (mreserve((char **)&fdset->fds, sizeof(struct pollfd), - fdset->nfds + 1, OS_FDS_CHUNKSIZE, &fdset->reserved) < 0) { - return -1; - } - - /* Append. */ - int nid = fdset->nfds++; - fdset->fds[nid].fd = fd; - fdset->fds[nid].events = POLLIN; - fdset->fds[nid].revents = 0; - return 0; -} - -int fdset_poll_remove(fdset_t *fdset, int fd) -{ - if (fdset == NULL || fd < 0) { - return -1; - } - - /* Find file descriptor. */ - unsigned found = 0; - size_t pos = 0; - for (size_t i = 0; i < fdset->nfds; ++i) { - if (fdset->fds[i].fd == fd) { - found = 1; - pos = i; - break; - } - } - - /* Check. */ - if (!found) { - return -1; - } - - /* Overwrite current item. */ - size_t remaining = ((fdset->nfds - pos) - 1) * sizeof(struct pollfd); - memmove(fdset->fds + pos, fdset->fds + (pos + 1), remaining); - --fdset->nfds; - - /* Trim excessive memory if possible (retval is not interesting). */ - mreserve((char **)&fdset->fds, sizeof(struct pollfd), fdset->nfds, - OS_FDS_CHUNKSIZE, &fdset->reserved); - - return 0; -} - -int fdset_poll_wait(fdset_t *fdset, int timeout) -{ - if (fdset == NULL || fdset->nfds < 1 || fdset->fds == NULL) { - return -1; - } - - /* Initialize pointers. */ - fdset->polled = 0; - fdset->begin = 0; - - /* Poll for events. */ - int ret = poll(fdset->fds, fdset->nfds, timeout); - if (ret < 0) { - return -1; - } - - /* Set pointers for iterating. */ - fdset->polled = ret; - fdset->begin = 0; - return ret; -} - -int fdset_poll_begin(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL) { - return -1; - } - - /* Find first. */ - it->pos = 0; - return fdset_next(fdset, it); -} - -int fdset_poll_end(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL || fdset->nfds < 1) { - return -1; - } - - /* Check for polled events. */ - if (fdset->polled < 1) { - it->fd = -1; - it->pos = 0; - return -1; - } - - /* Trace last matching item from the end. */ - struct pollfd* pfd = fdset->fds + fdset->nfds - 1; - while (pfd != fdset->fds) { - if (pfd->events & pfd->revents) { - it->fd = pfd->fd; - it->pos = pfd - fdset->fds; - return 0; - } - } - - /* No end found, ends on the beginning. */ - it->fd = -1; - it->pos = 0; - return -1; -} - -int fdset_poll_next(fdset_t *fdset, fdset_it_t *it) -{ - if (fdset == NULL || it == NULL || fdset->nfds < 1) { - return -1; - } - - /* Find next with matching flags. */ - for (; it->pos < fdset->nfds; ++it->pos) { - struct pollfd* pfd = fdset->fds + it->pos; - if (pfd->events & pfd->revents) { - it->fd = pfd->fd; - it->events = pfd->revents; - ++it->pos; /* Next will start after current. */ - return 0; - } - } - - /* No matching event found. */ - it->fd = -1; - it->pos = 0; - return -1; -} - -const char* fdset_poll_method() -{ - return "poll"; -} - -/* Package APIs. */ -struct fdset_backend_t FDSET_POLL = { - .fdset_new = fdset_poll_new, - .fdset_destroy = fdset_poll_destroy, - .fdset_add = fdset_poll_add, - .fdset_remove = fdset_poll_remove, - .fdset_wait = fdset_poll_wait, - .fdset_begin = fdset_poll_begin, - .fdset_end = fdset_poll_end, - .fdset_next = fdset_poll_next, - .fdset_method = fdset_poll_method -}; - -#endif diff --git a/src/common/fdset_poll.h b/src/common/fdset_poll.h deleted file mode 100644 index 68e9e69..0000000 --- a/src/common/fdset_poll.h +++ /dev/null @@ -1,132 +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/>. - */ -/*! - * \file fdset_poll.h - * - * \author Marek Vavrusa <marek.vavrusa@nic.cz> - * - * \brief Wrapper for poll I/O multiplexing. - * - * \addtogroup common_lib - * @{ - */ - -#ifndef _KNOTD_FDSET_POLL_H_ -#define _KNOTD_FDSET_POLL_H_ - -#include "fdset.h" - -/*! - * \brief Create new fdset. - * - * POSIX poll() backend. - * - * \retval Pointer to initialized FDSET structure if successful. - * \retval NULL on error. - */ -fdset_t *fdset_poll_new(); - -/*! - * \brief Destroy FDSET. - * - * \retval 0 if successful. - * \retval -1 on error. - */ -int fdset_poll_destroy(fdset_t * fdset); - -/*! - * \brief Add file descriptor to watched set. - * - * \param fdset Target set. - * \param fd Added file descriptor. - * \param events Mask of watched events. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_poll_add(fdset_t *fdset, int fd, int events); - -/*! - * \brief Remove file descriptor from watched set. - * - * \param fdset Target set. - * \param fd File descriptor to be removed. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_poll_remove(fdset_t *fdset, int fd); - -/*! - * \brief Poll set for new events. - * - * \param fdset Target set. - * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds). - * - * \retval Number of events if successful. - * \retval -1 on errors. - */ -int fdset_poll_wait(fdset_t *fdset, int timeout); - -/*! - * \brief Set event iterator to the beginning of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_poll_begin(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Set event iterator to the end of last polled events. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_poll_end(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Set event iterator to the next event. - * - * Event iterator fd will be set to -1 if next event doesn't exist. - * - * \param fdset Target set. - * \param it Event iterator. - * - * \retval 0 if successful. - * \retval -1 on errors. - */ -int fdset_poll_next(fdset_t *fdset, fdset_it_t *it); - -/*! - * \brief Returned name of poll method. - * - * \retval Name if successful. - * \retval NULL if no method was loaded (shouldn't happen). - */ -const char* fdset_poll_method(); - -/*! \brief Exported API. */ -extern struct fdset_backend_t FDSET_POLL; - -#endif /* _KNOTD_FDSET_POLL_H_ */ - -/*! @} */ diff --git a/src/config.h.in b/src/config.h.in index 656c8ef..73c4e3f 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -39,9 +39,6 @@ /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H -/* Define to 1 if you have the `epoll_wait' function. */ -#undef HAVE_EPOLL_WAIT - /* Define to 1 if you have the `fgetln' function. */ #undef HAVE_FGETLN @@ -54,9 +51,6 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `kqueue' function. */ -#undef HAVE_KQUEUE - /* Define to 1 if you have the `madvise' function. */ #undef HAVE_MADVISE @@ -157,6 +151,9 @@ declarations. */ #undef HAVE_VISIBILITY +/* integrity check in knotd */ +#undef INTEGRITY_CHECK + /* Server debug. */ #undef KNOTD_SERVER_DEBUG diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y index 663adad..9b277ab 100644 --- a/src/knot/conf/cf-parse.y +++ b/src/knot/conf/cf-parse.y @@ -531,11 +531,7 @@ system: | system NSID TEXT ';' { new_config->nsid = $3.t; new_config->nsid_len = strlen(new_config->nsid); } | system STORAGE TEXT ';' { new_config->storage = $3.t; } | system RUNDIR TEXT ';' { new_config->rundir = $3.t; } - | system PIDFILE TEXT ';' { - fprintf(stderr, "warning: Config option 'system.pidfile' is deprecated " - "and has no effect. Use 'rundir' instead.\n"); - free($3.t); - } + | system PIDFILE TEXT ';' { new_config->pidfile = $3.t; } | system KEY TSIG_ALGO_NAME TEXT ';' { fprintf(stderr, "warning: Config option 'system.key' is deprecated " "and has no effect.\n"); @@ -989,7 +985,8 @@ log_start: | log_start log_file '{' log_src '}' ; -log: LOG '{' log_start log_end; +log: LOG { new_config->logs_count = 0; } '{' log_start log_end + ; ctl_listen_start: LISTEN_ON { conf_init_iface(scanner, NULL, -1); } diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c index 9ed354a..9830c04 100644 --- a/src/knot/conf/conf.c +++ b/src/knot/conf/conf.c @@ -249,7 +249,8 @@ static int conf_process(conf_t *conf) } /* Default parallel transfers. */ - if (conf->xfers <= 0) conf->xfers = CONFIG_XFERS; + if (conf->xfers <= 0) + conf->xfers = CONFIG_XFERS; // Postprocess zones int ret = KNOT_EOK; @@ -393,7 +394,7 @@ void __attribute__ ((constructor)) conf_init() map->prios = LOG_MASK(LOG_WARNING)|LOG_MASK(LOG_ERR); add_tail(&log->map, &map->n); add_tail(&s_config->logs, &log->n); - ++s_config->logs_count; + s_config->logs_count = 1; /* Stderr */ log = malloc(sizeof(conf_log_t)); @@ -529,6 +530,7 @@ conf_t *conf_new(const char* path) c->xfers = -1; c->rrl_slip = -1; c->build_diffs = 0; /* Disable by default. */ + c->logs_count = -1; /* ACLs. */ c->ctl.acl = acl_new(ACL_DENY, "remote_ctl"); @@ -633,7 +635,7 @@ void conf_truncate(conf_t *conf, int unload_hooks) WALK_LIST_DELSAFE(n, nxt, conf->logs) { conf_free_log((conf_log_t*)n); } - conf->logs_count = 0; + conf->logs_count = -1; init_list(&conf->logs); // Free remote interfaces @@ -680,6 +682,10 @@ void conf_truncate(conf_t *conf, int unload_hooks) free(conf->rundir); conf->rundir = 0; } + if (conf->pidfile) { + free(conf->pidfile); + conf->pidfile = 0; + } if (conf->nsid) { free(conf->nsid); conf->nsid = 0; diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h index 57b250e..30075c3 100644 --- a/src/knot/conf/conf.h +++ b/src/knot/conf/conf.h @@ -194,7 +194,8 @@ typedef struct conf_t { char *hostname; /*!< Host name to return on CH TXT hostname.{bind,server} */ char *version; /*!< Version for CH TXT version.{bind|server} */ char *storage; /*!< Persistent storage path for databases and such. */ - char *rundir; /*!< Run-time directory path. */ + char *rundir; /*!< Run-time directory path. */ + char *pidfile; /*!< PID file location. */ char *nsid; /*!< Server's NSID. */ size_t nsid_len;/*!< Server's NSID length. */ int workers; /*!< Number of workers per interface. */ diff --git a/src/knot/conf/libknotd_la-cf-parse.c b/src/knot/conf/libknotd_la-cf-parse.c index 52280ca..2cea00d 100644 --- a/src/knot/conf/libknotd_la-cf-parse.c +++ b/src/knot/conf/libknotd_la-cf-parse.c @@ -830,16 +830,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 280 +#define YYLAST 281 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 66 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 34 +#define YYNNTS 35 /* YYNRULES -- Number of rules. */ -#define YYNRULES 146 +#define YYNRULES 147 /* YYNRULES -- Number of states. */ -#define YYNSTATES 290 +#define YYNSTATES 291 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -903,14 +903,14 @@ static const yytype_uint16 yyprhs[] = 356, 361, 366, 371, 376, 381, 386, 391, 394, 398, 403, 408, 413, 418, 423, 428, 433, 438, 443, 444, 446, 450, 454, 455, 459, 461, 464, 465, 466, 472, - 478, 483, 485, 487, 490, 496, 501, 507, 511, 513, - 516, 519, 522, 525, 528, 531, 534 + 478, 479, 485, 487, 489, 492, 498, 503, 509, 513, + 515, 518, 521, 524, 527, 530, 533, 536 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 67, 0, -1, 68, 3, -1, -1, 68, 99, -1, + 67, 0, -1, 68, 3, -1, -1, 68, 100, -1, -1, 5, -1, 24, -1, 58, -1, 56, -1, 59, -1, 53, -1, -1, 70, 49, 7, 60, -1, 70, 48, 50, 60, -1, 70, 48, 50, 61, 7, 60, @@ -957,13 +957,13 @@ static const yytype_int8 yyrhs[] = 8, 60, -1, -1, 88, -1, 89, 59, 65, -1, 89, 59, 60, -1, -1, 90, 58, 89, -1, 57, -1, 27, 5, -1, -1, -1, 94, 91, 62, 90, - 63, -1, 94, 92, 62, 90, 63, -1, 56, 62, - 94, 93, -1, 55, -1, 54, -1, 53, 62, -1, - 98, 96, 62, 70, 63, -1, 98, 96, 5, 60, - -1, 98, 97, 62, 84, 63, -1, 98, 97, 83, - -1, 60, -1, 72, 63, -1, 71, 63, -1, 73, - 63, -1, 76, 63, -1, 80, 63, -1, 87, 63, - -1, 95, 63, -1, 98, 63, -1 + 63, -1, 94, 92, 62, 90, 63, -1, -1, 56, + 96, 62, 94, 93, -1, 55, -1, 54, -1, 53, + 62, -1, 99, 97, 62, 70, 63, -1, 99, 97, + 5, 60, -1, 99, 98, 62, 84, 63, -1, 99, + 98, 83, -1, 60, -1, 72, 63, -1, 71, 63, + -1, 73, 63, -1, 76, 63, -1, 80, 63, -1, + 87, 63, -1, 95, 63, -1, 99, 63, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ @@ -971,19 +971,19 @@ static const yytype_uint16 yyrline[] = { 0, 448, 448, 450, 452, 455, 456, 457, 458, 459, 460, 461, 464, 465, 472, 480, 493, 501, 517, 518, - 526, 527, 528, 529, 530, 531, 532, 533, 534, 539, - 544, 551, 572, 573, 574, 575, 576, 577, 578, 579, - 583, 584, 635, 636, 637, 638, 639, 640, 643, 644, - 651, 660, 669, 683, 692, 701, 715, 723, 727, 731, - 738, 739, 747, 750, 752, 753, 757, 761, 762, 766, - 769, 772, 775, 778, 783, 784, 785, 786, 787, 788, - 791, 792, 793, 796, 797, 825, 826, 827, 828, 829, - 830, 831, 832, 849, 853, 854, 855, 856, 857, 858, - 859, 860, 861, 862, 863, 864, 871, 881, 882, 883, - 884, 885, 886, 887, 888, 895, 902, 909, 912, 921, - 922, 923, 926, 927, 933, 956, 983, 987, 988, 989, - 992, 995, 999, 1005, 1006, 1013, 1019, 1020, 1023, 1023, - 1023, 1023, 1023, 1023, 1023, 1023, 1023 + 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, + 540, 547, 568, 569, 570, 571, 572, 573, 574, 575, + 579, 580, 631, 632, 633, 634, 635, 636, 639, 640, + 647, 656, 665, 679, 688, 697, 711, 719, 723, 727, + 734, 735, 743, 746, 748, 749, 753, 757, 758, 762, + 765, 768, 771, 774, 779, 780, 781, 782, 783, 784, + 787, 788, 789, 792, 793, 821, 822, 823, 824, 825, + 826, 827, 828, 845, 849, 850, 851, 852, 853, 854, + 855, 856, 857, 858, 859, 860, 867, 877, 878, 879, + 880, 881, 882, 883, 884, 891, 898, 905, 908, 917, + 918, 919, 922, 923, 929, 952, 979, 983, 984, 985, + 988, 988, 992, 996, 1002, 1003, 1010, 1016, 1017, 1020, + 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020 }; #endif @@ -1008,7 +1008,7 @@ static const char *const yytname[] = "group_member", "group", "group_start", "groups", "zone_acl_start", "zone_acl_item", "zone_acl_list", "zone_acl", "zone_start", "zone", "zones", "log_prios_start", "log_prios", "log_src", "log_dest", - "log_file", "log_end", "log_start", "log", "ctl_listen_start", + "log_file", "log_end", "log_start", "log", "$@1", "ctl_listen_start", "ctl_allow_start", "control", "conf", 0 }; #endif @@ -1044,8 +1044,8 @@ static const yytype_uint8 yyr1[] = 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 89, 89, 89, 90, 90, 91, 92, 93, 94, 94, 94, - 95, 96, 97, 98, 98, 98, 98, 98, 99, 99, - 99, 99, 99, 99, 99, 99, 99 + 96, 95, 97, 98, 99, 99, 99, 99, 99, 100, + 100, 100, 100, 100, 100, 100, 100, 100 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -1064,8 +1064,8 @@ static const yytype_uint8 yyr2[] = 4, 4, 4, 4, 4, 4, 4, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 3, 3, 0, 3, 1, 2, 0, 0, 5, 5, - 4, 1, 1, 2, 5, 4, 5, 3, 1, 2, - 2, 2, 2, 2, 2, 2, 2 + 0, 5, 1, 1, 2, 5, 4, 5, 3, 1, + 2, 2, 2, 2, 2, 2, 2, 2 }; /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. @@ -1074,43 +1074,44 @@ static const yytype_uint8 yyr2[] = static const yytype_uint8 yydefact[] = { 3, 0, 0, 1, 2, 0, 0, 0, 0, 0, - 0, 0, 0, 138, 5, 0, 0, 42, 0, 85, - 0, 0, 4, 20, 40, 60, 67, 107, 18, 133, - 127, 6, 7, 11, 9, 8, 10, 140, 0, 0, + 0, 0, 130, 139, 5, 0, 0, 42, 0, 85, + 0, 0, 4, 20, 40, 60, 67, 107, 18, 134, + 0, 6, 7, 11, 9, 8, 10, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 139, 0, 141, 43, - 47, 45, 44, 46, 142, 0, 66, 143, 0, 93, + 0, 0, 0, 0, 0, 0, 140, 0, 142, 43, + 47, 45, 44, 46, 143, 0, 66, 144, 0, 93, 0, 86, 87, 0, 0, 0, 0, 0, 0, 0, - 91, 89, 88, 90, 144, 0, 0, 145, 132, 131, - 146, 0, 80, 126, 12, 0, 0, 0, 0, 0, + 91, 89, 88, 90, 145, 0, 0, 146, 133, 132, + 147, 0, 80, 127, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 69, 70, 73, 71, 72, - 0, 108, 80, 0, 12, 83, 137, 0, 124, 0, - 0, 130, 0, 22, 23, 21, 25, 24, 26, 0, - 30, 31, 27, 28, 32, 33, 34, 35, 37, 36, - 38, 39, 0, 0, 62, 64, 0, 92, 109, 111, - 114, 115, 116, 117, 113, 112, 110, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 83, 96, 135, - 0, 0, 75, 79, 77, 76, 78, 0, 125, 122, - 122, 0, 0, 19, 29, 41, 0, 0, 0, 0, - 61, 68, 0, 97, 100, 99, 105, 106, 101, 102, - 104, 103, 98, 0, 134, 0, 136, 82, 81, 0, + 0, 108, 80, 0, 12, 83, 138, 126, 0, 22, + 23, 21, 25, 24, 26, 0, 30, 31, 27, 28, + 32, 33, 34, 35, 37, 36, 38, 39, 0, 0, + 62, 64, 0, 92, 109, 111, 114, 115, 116, 117, + 113, 112, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 83, 96, 136, 0, 0, 75, 79, + 77, 76, 78, 0, 0, 124, 0, 0, 131, 0, + 0, 19, 29, 41, 0, 0, 0, 0, 61, 68, + 0, 97, 100, 99, 105, 106, 101, 102, 104, 103, + 98, 0, 135, 0, 137, 82, 81, 125, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 65, 95, 84, 118, 128, 129, 14, 0, 16, - 0, 13, 56, 50, 0, 0, 53, 0, 0, 49, - 59, 57, 58, 119, 123, 0, 0, 0, 0, 0, - 0, 0, 15, 17, 52, 51, 55, 54, 121, 120 + 65, 95, 84, 0, 0, 14, 0, 16, 0, 13, + 56, 50, 0, 0, 53, 0, 0, 49, 59, 57, + 58, 118, 128, 129, 0, 0, 0, 0, 0, 0, + 119, 123, 15, 17, 52, 51, 55, 54, 0, 121, + 120 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 2, 38, 152, 14, 15, 16, 65, 173, - 17, 175, 176, 68, 18, 142, 207, 146, 201, 85, - 86, 19, 273, 274, 239, 149, 150, 151, 93, 20, - 91, 92, 21, 22 + -1, 1, 2, 38, 148, 14, 15, 16, 65, 169, + 17, 171, 172, 68, 18, 142, 203, 146, 197, 85, + 86, 19, 280, 281, 253, 206, 207, 208, 147, 20, + 30, 91, 92, 21, 22 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing @@ -1119,43 +1120,44 @@ static const yytype_int16 yydefgoto[] = static const yytype_int16 yypact[] = { -47, 30, 72, -47, -47, -25, 12, 22, 42, 58, - 67, 68, 69, -47, 14, 93, 0, 23, 1, 3, + 67, 68, -47, -47, 14, 93, 0, 23, 1, 3, 5, -42, -47, -47, -47, -47, -47, -47, -47, -47, - -47, -47, -47, -47, -47, -47, -47, -47, 91, 119, + 69, -47, -47, -47, -47, -47, -47, -47, 91, 119, 149, 150, 38, 152, 52, 151, 154, 155, 156, 157, 158, 159, 161, 9, 162, 163, -47, 143, -47, -47, -47, -47, -47, -47, -47, 101, -47, -47, 102, -47, 107, -47, -47, 164, 165, 166, 170, 87, 71, 168, -47, -47, -47, -47, -47, 110, 113, -47, -47, -47, - -47, -4, 117, -18, -47, 120, 121, 122, 123, 124, + -47, -4, 117, -47, -47, 120, 121, 122, 123, 124, 125, 181, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 194, -47, 195, 196, 142, 144, 145, 146, 147, 148, 153, 160, 167, -47, 198, 199, 200, 204, 205, 92, 78, -47, -47, -47, -47, -47, - 206, -47, 169, 172, -47, -47, -5, 209, -47, 171, - 173, -47, -46, -47, -47, -47, -47, -47, -47, 174, - -47, -47, -47, -47, -47, -47, -47, -47, -47, -47, - -47, -47, 176, 40, -47, -47, 28, -47, -47, -47, - -47, -47, -47, -47, -47, -47, -47, 177, 178, 179, - 180, 182, 183, 184, 185, 186, 187, -47, -5, -47, - -34, 2, -47, -47, -47, -47, -47, -40, -47, -47, - -47, 51, 208, -47, -47, -47, 212, 61, 211, -1, - -47, -47, 195, -47, -47, -47, -47, -47, -47, -47, - -47, -47, -47, 6, -47, 188, -47, -47, -47, -17, - -11, 62, 66, 189, 190, -38, 57, 191, 192, 193, - 197, -47, -47, -47, -47, -47, -47, -47, 214, -47, - 215, -47, -47, -47, 216, 217, -47, 218, 219, -47, - -47, -47, -47, -47, 201, 202, 203, 207, 210, 213, - 220, -20, -47, -47, -47, -47, -47, -47, -47, -47 + 206, -47, 169, 172, -47, -47, -5, -18, -46, -47, + -47, -47, -47, -47, -47, 173, -47, -47, -47, -47, + -47, -47, -47, -47, -47, -47, -47, -47, 174, 40, + -47, -47, 28, -47, -47, -47, -47, -47, -47, -47, + -47, -47, -47, 175, 176, 177, 178, 179, 180, 182, + 183, 184, 185, -47, -5, -47, -34, 2, -47, -47, + -47, -47, -47, -40, 209, -47, 186, 187, -47, 51, + 208, -47, -47, -47, 212, 61, 211, -1, -47, -47, + 195, -47, -47, -47, -47, -47, -47, -47, -47, -47, + -47, 6, -47, 190, -47, -47, -47, -47, -47, -47, + 62, 66, 191, 192, -38, 57, 193, 197, 201, 202, + -47, -47, -47, -17, -11, -47, 214, -47, 215, -47, + -47, -47, 216, 217, -47, 218, 219, -47, -47, -47, + -47, -47, -47, -47, 203, 207, 210, 213, 220, 221, + -47, 171, -47, -47, -47, -47, -47, -47, -20, -47, + -47 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -47, -47, -47, -47, 75, -47, -47, -47, -47, -47, - -47, 7, -47, -47, -47, -47, -47, 86, 33, -47, - -47, -47, -47, -47, 31, -47, -47, -47, -47, -47, - -47, -47, -47, -47 + -47, 8, -47, -47, -47, -47, -47, 99, 36, -47, + -47, -47, -47, -47, 7, -47, -47, -47, -47, -47, + -47, -47, -47, -47, -47 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -1164,35 +1166,35 @@ static const yytype_int8 yypgoto[] = #define YYTABLE_NINF -75 static const yytype_int16 yytable[] = { - 202, 143, 211, 212, 248, 57, 66, 235, 69, 147, - 70, 235, 88, 89, 211, 212, 110, 213, 111, 31, - 237, 90, 263, 264, 71, 238, 265, 72, 59, 234, - 3, 73, 74, 75, 76, 77, 78, 23, 32, 148, - 288, 254, 79, 98, 99, 289, 255, 254, 203, 249, - 250, 204, 256, 205, 206, -74, 80, 216, 144, 81, - -74, 82, 83, 58, 67, 236, 84, 33, 87, 252, + 198, 143, 209, 210, 247, 57, 66, 233, 69, 204, + 70, 233, 88, 89, 209, 210, 110, 211, 111, 31, + 235, 90, 261, 262, 71, 236, 263, 72, 59, 232, + 3, 73, 74, 75, 76, 77, 78, 23, 32, 205, + 289, 271, 79, 98, 99, 290, 272, 271, 199, 248, + 249, 200, 273, 201, 202, -74, 80, 214, 144, 81, + -74, 82, 83, 58, 67, 234, 84, 33, 87, 251, 34, 101, 35, 36, 24, 4, 60, 37, 124, 61, - 125, 62, 63, 5, 25, 194, 64, 195, 217, 218, - 6, 221, 219, 222, 122, 123, 7, 8, 9, 192, - 193, 241, 242, 220, 26, 39, 40, 41, 42, 43, - 44, 245, 246, 45, 46, 47, 48, 266, 267, 10, - 27, 268, 257, 258, 95, 11, 259, 260, 12, 28, - 29, 30, 13, 49, 50, 51, 52, 53, 54, 55, + 125, 62, 63, 5, 25, 190, 64, 191, 215, 216, + 6, 219, 217, 220, 122, 123, 7, 8, 9, 188, + 189, 240, 241, 218, 26, 39, 40, 41, 42, 43, + 44, 244, 245, 45, 46, 47, 48, 264, 265, 10, + 27, 266, 255, 256, 95, 11, 257, 258, 12, 28, + 29, 93, 13, 49, 50, 51, 52, 53, 54, 55, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 94, 96, 97, 56, 100, 102, 103, 104, 105, 114, 115, 116, 106, 107, 108, 109, 112, 113, 117, 127, 120, 118, 119, 141, 121, 126, 145, - 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, - 174, 177, 178, 187, 179, 180, 181, 182, 183, 188, - 189, 190, 191, 184, 208, 243, 196, 244, 247, 200, - 185, 275, 276, 277, 278, 279, 280, 186, 198, 251, - 233, 197, 199, 209, 214, 210, 215, 223, 224, 225, - 226, 240, 227, 228, 229, 230, 231, 232, 253, 261, - 262, 269, 270, 271, 0, 0, 0, 272, 0, 0, - 281, 0, 282, 283, 0, 0, 0, 284, 0, 0, - 285, 0, 0, 286, 0, 0, 0, 0, 0, 0, - 287 + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 170, 173, 174, 183, 175, 176, 177, 178, 179, 184, + 185, 186, 187, 180, 237, 242, 192, 243, 246, 196, + 181, 274, 275, 276, 277, 278, 279, 182, 250, 231, + 288, 193, 195, 212, 213, 221, 222, 223, 224, 225, + 226, 194, 227, 228, 229, 230, 254, 0, 238, 239, + 252, 259, 260, 267, 0, 0, 0, 268, 0, 0, + 0, 269, 270, 282, 0, 0, 0, 283, 0, 0, + 284, 0, 0, 285, 0, 0, 0, 0, 0, 0, + 286, 287 }; #define yypact_value_is_default(yystate) \ @@ -1225,13 +1227,13 @@ static const yytype_int16 yycheck[] = 60, 60, 60, 60, 60, 60, 60, 60, 60, 5, 5, 5, 60, 5, 60, 60, 60, 60, 60, 10, 10, 7, 7, 60, 5, 7, 10, 5, 7, 144, - 60, 7, 7, 7, 7, 7, 7, 60, 142, 222, - 197, 62, 60, 62, 60, 62, 60, 60, 60, 60, - 60, 210, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 7, 7, 7, 7, 7, 7, 60, 220, 193, + 59, 62, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 142, 60, 60, 60, 60, 239, -1, 62, 62, 60, 60, 60, 60, -1, -1, -1, 60, -1, -1, - 59, -1, 60, 60, -1, -1, -1, 60, -1, -1, + -1, 60, 60, 60, -1, -1, -1, 60, -1, -1, 60, -1, -1, 60, -1, -1, -1, -1, -1, -1, - 60 + 60, 60 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1240,33 +1242,34 @@ static const yytype_uint8 yystos[] = { 0, 67, 68, 0, 3, 11, 18, 24, 25, 26, 47, 53, 56, 60, 71, 72, 73, 76, 80, 87, - 95, 98, 99, 62, 62, 62, 62, 62, 62, 62, - 62, 5, 24, 53, 56, 58, 59, 63, 69, 12, + 95, 99, 100, 62, 62, 62, 62, 62, 62, 62, + 96, 5, 24, 53, 56, 58, 59, 63, 69, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 40, 41, 42, 43, 44, 45, 46, 63, 5, 63, 5, 53, 56, 58, 59, 63, 74, 5, 63, 79, 5, 7, 21, 24, 28, 29, 30, 31, 32, 33, 39, 53, 56, 58, 59, 63, 85, 86, 63, 54, 55, - 63, 96, 97, 94, 62, 5, 5, 5, 5, 6, + 63, 97, 98, 62, 62, 5, 5, 5, 5, 6, 5, 19, 7, 5, 5, 5, 8, 8, 8, 7, 7, 9, 7, 7, 19, 62, 62, 64, 10, 10, 7, 7, 7, 8, 7, 9, 10, 62, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 63, 81, 5, 62, 62, 83, 27, 57, 91, - 92, 93, 70, 60, 60, 60, 60, 60, 60, 5, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 5, 75, 5, 77, 78, 5, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 5, 10, 10, - 7, 7, 7, 8, 7, 9, 10, 62, 83, 60, - 70, 84, 5, 53, 56, 58, 59, 82, 5, 62, - 62, 48, 49, 63, 60, 60, 17, 48, 49, 52, - 63, 63, 65, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 84, 63, 5, 63, 60, 65, 90, - 90, 50, 51, 7, 5, 50, 51, 7, 5, 50, - 51, 77, 63, 60, 58, 63, 63, 60, 61, 60, - 61, 60, 60, 60, 61, 64, 60, 61, 64, 60, - 60, 60, 60, 88, 89, 7, 7, 7, 7, 7, - 7, 59, 60, 60, 60, 60, 60, 60, 60, 65 + 39, 63, 81, 5, 62, 62, 83, 94, 70, 60, + 60, 60, 60, 60, 60, 5, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 5, 75, + 5, 77, 78, 5, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 5, 10, 10, 7, 7, 7, 8, + 7, 9, 10, 62, 83, 60, 70, 84, 5, 53, + 56, 58, 59, 82, 27, 57, 91, 92, 93, 48, + 49, 63, 60, 60, 17, 48, 49, 52, 63, 63, + 65, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 84, 63, 5, 63, 60, 65, 5, 62, 62, + 50, 51, 7, 5, 50, 51, 7, 5, 50, 51, + 77, 63, 60, 90, 90, 60, 61, 60, 61, 60, + 60, 60, 61, 64, 60, 61, 64, 60, 60, 60, + 60, 58, 63, 63, 7, 7, 7, 7, 7, 7, + 88, 89, 60, 60, 60, 60, 60, 60, 59, 60, + 65 }; #define yyerrok (yyerrstatus = 0) @@ -2297,17 +2300,13 @@ yyreduce: /* Line 1806 of yacc.c */ #line 534 "cf-parse.y" - { - fprintf(stderr, "warning: Config option 'system.pidfile' is deprecated " - "and has no effect. Use 'rundir' instead.\n"); - free((yyvsp[(3) - (4)].tok).t); - } + { new_config->pidfile = (yyvsp[(3) - (4)].tok).t; } break; case 29: /* Line 1806 of yacc.c */ -#line 539 "cf-parse.y" +#line 535 "cf-parse.y" { fprintf(stderr, "warning: Config option 'system.key' is deprecated " "and has no effect.\n"); @@ -2318,7 +2317,7 @@ yyreduce: case 30: /* Line 1806 of yacc.c */ -#line 544 "cf-parse.y" +#line 540 "cf-parse.y" { if ((yyvsp[(3) - (4)].tok).i <= 0) { cf_error(scanner, "worker count must be greater than 0\n"); @@ -2331,7 +2330,7 @@ yyreduce: case 31: /* Line 1806 of yacc.c */ -#line 551 "cf-parse.y" +#line 547 "cf-parse.y" { new_config->uid = new_config->gid = -1; // Invalidate char* dpos = strchr((yyvsp[(3) - (4)].tok).t, '.'); // Find uid.gid format @@ -2358,63 +2357,63 @@ yyreduce: case 32: /* Line 1806 of yacc.c */ -#line 572 "cf-parse.y" +#line 568 "cf-parse.y" { new_config->max_conn_idle = (yyvsp[(3) - (4)].tok).i; } break; case 33: /* Line 1806 of yacc.c */ -#line 573 "cf-parse.y" +#line 569 "cf-parse.y" { new_config->max_conn_hs = (yyvsp[(3) - (4)].tok).i; } break; case 34: /* Line 1806 of yacc.c */ -#line 574 "cf-parse.y" +#line 570 "cf-parse.y" { new_config->max_conn_reply = (yyvsp[(3) - (4)].tok).i; } break; case 35: /* Line 1806 of yacc.c */ -#line 575 "cf-parse.y" +#line 571 "cf-parse.y" { new_config->rrl = (yyvsp[(3) - (4)].tok).i; } break; case 36: /* Line 1806 of yacc.c */ -#line 576 "cf-parse.y" +#line 572 "cf-parse.y" { new_config->rrl_size = (yyvsp[(3) - (4)].tok).l; } break; case 37: /* Line 1806 of yacc.c */ -#line 577 "cf-parse.y" +#line 573 "cf-parse.y" { new_config->rrl_size = (yyvsp[(3) - (4)].tok).i; } break; case 38: /* Line 1806 of yacc.c */ -#line 578 "cf-parse.y" +#line 574 "cf-parse.y" { new_config->rrl_slip = (yyvsp[(3) - (4)].tok).i; } break; case 39: /* Line 1806 of yacc.c */ -#line 579 "cf-parse.y" +#line 575 "cf-parse.y" { new_config->xfers = (yyvsp[(3) - (4)].tok).i; } break; case 41: /* Line 1806 of yacc.c */ -#line 584 "cf-parse.y" +#line 580 "cf-parse.y" { /* Check algorithm length. */ if (knot_tsig_digest_length((yyvsp[(3) - (5)].tok).alg) == 0) { @@ -2470,42 +2469,42 @@ yyreduce: case 43: /* Line 1806 of yacc.c */ -#line 636 "cf-parse.y" +#line 632 "cf-parse.y" { conf_start_remote(scanner, (yyvsp[(1) - (1)].tok).t); } break; case 44: /* Line 1806 of yacc.c */ -#line 637 "cf-parse.y" +#line 633 "cf-parse.y" { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 45: /* Line 1806 of yacc.c */ -#line 638 "cf-parse.y" +#line 634 "cf-parse.y" { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 46: /* Line 1806 of yacc.c */ -#line 639 "cf-parse.y" +#line 635 "cf-parse.y" { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 47: /* Line 1806 of yacc.c */ -#line 640 "cf-parse.y" +#line 636 "cf-parse.y" { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 49: /* Line 1806 of yacc.c */ -#line 644 "cf-parse.y" +#line 640 "cf-parse.y" { if (this_remote->port != 0) { cf_error(scanner, "only one port definition is allowed in remote section\n"); @@ -2518,7 +2517,7 @@ yyreduce: case 50: /* Line 1806 of yacc.c */ -#line 651 "cf-parse.y" +#line 647 "cf-parse.y" { if (this_remote->address != 0) { cf_error(scanner, "only one address is allowed in remote section\n"); @@ -2533,7 +2532,7 @@ yyreduce: case 51: /* Line 1806 of yacc.c */ -#line 660 "cf-parse.y" +#line 656 "cf-parse.y" { if (this_remote->address != 0) { cf_error(scanner, "only one address is allowed in remote section\n"); @@ -2548,7 +2547,7 @@ yyreduce: case 52: /* Line 1806 of yacc.c */ -#line 669 "cf-parse.y" +#line 665 "cf-parse.y" { if (this_remote->address != 0) { cf_error(scanner, "only one address is allowed in remote section\n"); @@ -2568,7 +2567,7 @@ yyreduce: case 53: /* Line 1806 of yacc.c */ -#line 683 "cf-parse.y" +#line 679 "cf-parse.y" { if (this_remote->address != 0) { cf_error(scanner, "only one address is allowed in remote section\n"); @@ -2583,7 +2582,7 @@ yyreduce: case 54: /* Line 1806 of yacc.c */ -#line 692 "cf-parse.y" +#line 688 "cf-parse.y" { if (this_remote->address != 0) { cf_error(scanner, "only one address is allowed in remote section\n"); @@ -2598,7 +2597,7 @@ yyreduce: case 55: /* Line 1806 of yacc.c */ -#line 701 "cf-parse.y" +#line 697 "cf-parse.y" { if (this_remote->address != 0) { cf_error(scanner, "only one address is allowed in remote section\n"); @@ -2618,7 +2617,7 @@ yyreduce: case 56: /* Line 1806 of yacc.c */ -#line 715 "cf-parse.y" +#line 711 "cf-parse.y" { if (this_remote->key != 0) { cf_error(scanner, "only one TSIG key definition is allowed in remote section\n"); @@ -2632,7 +2631,7 @@ yyreduce: case 57: /* Line 1806 of yacc.c */ -#line 723 "cf-parse.y" +#line 719 "cf-parse.y" { sockaddr_set(&this_remote->via, AF_INET, (yyvsp[(3) - (4)].tok).t, 0); free((yyvsp[(3) - (4)].tok).t); @@ -2642,7 +2641,7 @@ yyreduce: case 58: /* Line 1806 of yacc.c */ -#line 727 "cf-parse.y" +#line 723 "cf-parse.y" { sockaddr_set(&this_remote->via, AF_INET6, (yyvsp[(3) - (4)].tok).t, 0); free((yyvsp[(3) - (4)].tok).t); @@ -2652,7 +2651,7 @@ yyreduce: case 59: /* Line 1806 of yacc.c */ -#line 731 "cf-parse.y" +#line 727 "cf-parse.y" { conf_remote_set_via(scanner, (yyvsp[(3) - (4)].tok).t); free((yyvsp[(3) - (4)].tok).t); @@ -2662,7 +2661,7 @@ yyreduce: case 61: /* Line 1806 of yacc.c */ -#line 739 "cf-parse.y" +#line 735 "cf-parse.y" { if (this_remote->address == 0) { cf_error(scanner, "remote '%s' has no defined address", this_remote->name); @@ -2673,21 +2672,21 @@ yyreduce: case 62: /* Line 1806 of yacc.c */ -#line 747 "cf-parse.y" +#line 743 "cf-parse.y" { conf_add_member_into_group(scanner, (yyvsp[(1) - (1)].tok).t); } break; case 66: /* Line 1806 of yacc.c */ -#line 757 "cf-parse.y" +#line 753 "cf-parse.y" { conf_start_group(scanner, (yyvsp[(1) - (1)].tok).t); } break; case 69: /* Line 1806 of yacc.c */ -#line 766 "cf-parse.y" +#line 762 "cf-parse.y" { this_list = &this_zone->acl.xfr_in; } @@ -2696,7 +2695,7 @@ yyreduce: case 70: /* Line 1806 of yacc.c */ -#line 769 "cf-parse.y" +#line 765 "cf-parse.y" { this_list = &this_zone->acl.xfr_out; } @@ -2705,7 +2704,7 @@ yyreduce: case 71: /* Line 1806 of yacc.c */ -#line 772 "cf-parse.y" +#line 768 "cf-parse.y" { this_list = &this_zone->acl.notify_in; } @@ -2714,7 +2713,7 @@ yyreduce: case 72: /* Line 1806 of yacc.c */ -#line 775 "cf-parse.y" +#line 771 "cf-parse.y" { this_list = &this_zone->acl.notify_out; } @@ -2723,7 +2722,7 @@ yyreduce: case 73: /* Line 1806 of yacc.c */ -#line 778 "cf-parse.y" +#line 774 "cf-parse.y" { this_list = &this_zone->acl.update_in; } @@ -2732,42 +2731,42 @@ yyreduce: case 75: /* Line 1806 of yacc.c */ -#line 784 "cf-parse.y" +#line 780 "cf-parse.y" { conf_acl_item(scanner, (yyvsp[(1) - (1)].tok).t); } break; case 76: /* Line 1806 of yacc.c */ -#line 785 "cf-parse.y" +#line 781 "cf-parse.y" { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 77: /* Line 1806 of yacc.c */ -#line 786 "cf-parse.y" +#line 782 "cf-parse.y" { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 78: /* Line 1806 of yacc.c */ -#line 787 "cf-parse.y" +#line 783 "cf-parse.y" { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 79: /* Line 1806 of yacc.c */ -#line 788 "cf-parse.y" +#line 784 "cf-parse.y" { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 84: /* Line 1806 of yacc.c */ -#line 797 "cf-parse.y" +#line 793 "cf-parse.y" { /* Find existing node in remotes. */ node* r = 0; conf_iface_t* found = 0; @@ -2799,49 +2798,49 @@ yyreduce: case 86: /* Line 1806 of yacc.c */ -#line 826 "cf-parse.y" +#line 822 "cf-parse.y" { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 87: /* Line 1806 of yacc.c */ -#line 827 "cf-parse.y" +#line 823 "cf-parse.y" { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 88: /* Line 1806 of yacc.c */ -#line 828 "cf-parse.y" +#line 824 "cf-parse.y" { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 89: /* Line 1806 of yacc.c */ -#line 829 "cf-parse.y" +#line 825 "cf-parse.y" { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 90: /* Line 1806 of yacc.c */ -#line 830 "cf-parse.y" +#line 826 "cf-parse.y" { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 91: /* Line 1806 of yacc.c */ -#line 831 "cf-parse.y" +#line 827 "cf-parse.y" { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); } break; case 92: /* Line 1806 of yacc.c */ -#line 832 "cf-parse.y" +#line 828 "cf-parse.y" { if ((yyvsp[(1) - (3)].tok).i < 0 || (yyvsp[(1) - (3)].tok).i > 255) { cf_error(scanner, "rfc2317 origin prefix '%ld' out of bounds", (yyvsp[(1) - (3)].tok).i); @@ -2864,70 +2863,70 @@ yyreduce: case 93: /* Line 1806 of yacc.c */ -#line 849 "cf-parse.y" +#line 845 "cf-parse.y" { conf_zone_start(scanner, (yyvsp[(1) - (1)].tok).t); } break; case 97: /* Line 1806 of yacc.c */ -#line 856 "cf-parse.y" +#line 852 "cf-parse.y" { this_zone->file = (yyvsp[(3) - (4)].tok).t; } break; case 98: /* Line 1806 of yacc.c */ -#line 857 "cf-parse.y" +#line 853 "cf-parse.y" { this_zone->build_diffs = (yyvsp[(3) - (4)].tok).i; } break; case 99: /* Line 1806 of yacc.c */ -#line 858 "cf-parse.y" +#line 854 "cf-parse.y" { this_zone->enable_checks = (yyvsp[(3) - (4)].tok).i; } break; case 100: /* Line 1806 of yacc.c */ -#line 859 "cf-parse.y" +#line 855 "cf-parse.y" { this_zone->disable_any = (yyvsp[(3) - (4)].tok).i; } break; case 101: /* Line 1806 of yacc.c */ -#line 860 "cf-parse.y" +#line 856 "cf-parse.y" { this_zone->dbsync_timeout = (yyvsp[(3) - (4)].tok).i; } break; case 102: /* Line 1806 of yacc.c */ -#line 861 "cf-parse.y" +#line 857 "cf-parse.y" { this_zone->dbsync_timeout = (yyvsp[(3) - (4)].tok).i; } break; case 103: /* Line 1806 of yacc.c */ -#line 862 "cf-parse.y" +#line 858 "cf-parse.y" { new_config->ixfr_fslimit = (yyvsp[(3) - (4)].tok).l; } break; case 104: /* Line 1806 of yacc.c */ -#line 863 "cf-parse.y" +#line 859 "cf-parse.y" { this_zone->ixfr_fslimit = (yyvsp[(3) - (4)].tok).i; } break; case 105: /* Line 1806 of yacc.c */ -#line 864 "cf-parse.y" +#line 860 "cf-parse.y" { if ((yyvsp[(3) - (4)].tok).i < 1) { cf_error(scanner, "notify retries must be positive integer"); @@ -2940,7 +2939,7 @@ yyreduce: case 106: /* Line 1806 of yacc.c */ -#line 871 "cf-parse.y" +#line 867 "cf-parse.y" { if ((yyvsp[(3) - (4)].tok).i < 1) { cf_error(scanner, "notify timeout must be positive integer"); @@ -2953,42 +2952,42 @@ yyreduce: case 109: /* Line 1806 of yacc.c */ -#line 883 "cf-parse.y" +#line 879 "cf-parse.y" { new_config->disable_any = (yyvsp[(3) - (4)].tok).i; } break; case 110: /* Line 1806 of yacc.c */ -#line 884 "cf-parse.y" +#line 880 "cf-parse.y" { new_config->build_diffs = (yyvsp[(3) - (4)].tok).i; } break; case 111: /* Line 1806 of yacc.c */ -#line 885 "cf-parse.y" +#line 881 "cf-parse.y" { new_config->zone_checks = (yyvsp[(3) - (4)].tok).i; } break; case 112: /* Line 1806 of yacc.c */ -#line 886 "cf-parse.y" +#line 882 "cf-parse.y" { new_config->ixfr_fslimit = (yyvsp[(3) - (4)].tok).l; } break; case 113: /* Line 1806 of yacc.c */ -#line 887 "cf-parse.y" +#line 883 "cf-parse.y" { new_config->ixfr_fslimit = (yyvsp[(3) - (4)].tok).i; } break; case 114: /* Line 1806 of yacc.c */ -#line 888 "cf-parse.y" +#line 884 "cf-parse.y" { if ((yyvsp[(3) - (4)].tok).i < 1) { cf_error(scanner, "notify retries must be positive integer"); @@ -3001,7 +3000,7 @@ yyreduce: case 115: /* Line 1806 of yacc.c */ -#line 895 "cf-parse.y" +#line 891 "cf-parse.y" { if ((yyvsp[(3) - (4)].tok).i < 1) { cf_error(scanner, "notify timeout must be positive integer"); @@ -3014,7 +3013,7 @@ yyreduce: case 116: /* Line 1806 of yacc.c */ -#line 902 "cf-parse.y" +#line 898 "cf-parse.y" { if ((yyvsp[(3) - (4)].tok).i < 1) { cf_error(scanner, "zonefile sync timeout must be positive integer"); @@ -3027,14 +3026,14 @@ yyreduce: case 117: /* Line 1806 of yacc.c */ -#line 909 "cf-parse.y" +#line 905 "cf-parse.y" { new_config->dbsync_timeout = (yyvsp[(3) - (4)].tok).i; } break; case 118: /* Line 1806 of yacc.c */ -#line 912 "cf-parse.y" +#line 908 "cf-parse.y" { this_logmap = malloc(sizeof(conf_log_map_t)); this_logmap->source = 0; @@ -3046,21 +3045,21 @@ yyreduce: case 120: /* Line 1806 of yacc.c */ -#line 922 "cf-parse.y" +#line 918 "cf-parse.y" { this_logmap->prios |= (yyvsp[(2) - (3)].tok).i; } break; case 121: /* Line 1806 of yacc.c */ -#line 923 "cf-parse.y" +#line 919 "cf-parse.y" { this_logmap->prios |= (yyvsp[(2) - (3)].tok).i; } break; case 123: /* Line 1806 of yacc.c */ -#line 927 "cf-parse.y" +#line 923 "cf-parse.y" { this_logmap->source = (yyvsp[(2) - (3)].tok).i; this_logmap = 0; @@ -3070,7 +3069,7 @@ yyreduce: case 124: /* Line 1806 of yacc.c */ -#line 933 "cf-parse.y" +#line 929 "cf-parse.y" { /* Find already existing rule. */ this_log = 0; @@ -3097,7 +3096,7 @@ yyreduce: case 125: /* Line 1806 of yacc.c */ -#line 956 "cf-parse.y" +#line 952 "cf-parse.y" { /* Find already existing rule. */ this_log = 0; @@ -3128,38 +3127,45 @@ yyreduce: case 126: /* Line 1806 of yacc.c */ -#line 983 "cf-parse.y" +#line 979 "cf-parse.y" { } break; - case 131: + case 130: /* Line 1806 of yacc.c */ -#line 995 "cf-parse.y" - { conf_init_iface(scanner, NULL, -1); } +#line 988 "cf-parse.y" + { new_config->logs_count = 0; } break; case 132: /* Line 1806 of yacc.c */ -#line 999 "cf-parse.y" +#line 992 "cf-parse.y" + { conf_init_iface(scanner, NULL, -1); } + break; + + case 133: + +/* Line 1806 of yacc.c */ +#line 996 "cf-parse.y" { this_list = &new_config->ctl.allow; } break; - case 133: + case 134: /* Line 1806 of yacc.c */ -#line 1005 "cf-parse.y" +#line 1002 "cf-parse.y" { new_config->ctl.have = true; } break; - case 134: + case 135: /* Line 1806 of yacc.c */ -#line 1006 "cf-parse.y" +#line 1003 "cf-parse.y" { if (this_iface->address == 0) { cf_error(scanner, "control interface has no defined address"); @@ -3169,10 +3175,10 @@ yyreduce: } break; - case 135: + case 136: /* Line 1806 of yacc.c */ -#line 1013 "cf-parse.y" +#line 1010 "cf-parse.y" { this_iface->address = (yyvsp[(3) - (4)].tok).t; this_iface->family = AF_UNIX; @@ -3184,7 +3190,7 @@ yyreduce: /* Line 1806 of yacc.c */ -#line 3188 "knot/conf/libknotd_la-cf-parse.c" +#line 3194 "knot/conf/libknotd_la-cf-parse.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -3415,6 +3421,6 @@ yyreturn: /* Line 2067 of yacc.c */ -#line 1025 "cf-parse.y" +#line 1022 "cf-parse.y" diff --git a/src/knot/conf/logconf.c b/src/knot/conf/logconf.c index 427e762..4f59755 100644 --- a/src/knot/conf/logconf.c +++ b/src/knot/conf/logconf.c @@ -34,13 +34,15 @@ int log_conf_hook(const struct conf_t *conf, void *data) int ret = 0; UNUSED(data); - // Check if log declaration exists, otherwise ignore - if (conf->logs_count < 1) { - return KNOT_EINVAL; + // Use defaults if no 'log' section is configured. + if (conf->logs_count < 0) { + log_close(); + log_init(); + return KNOT_EOK; } // Find maximum log facility id - node *n = 0; size_t files = 0; + node *n = NULL; size_t files = 0; WALK_LIST(n, conf->logs) { conf_log_t* log = (conf_log_t*)n; if (log->type == LOGT_FILE) { @@ -55,8 +57,7 @@ int log_conf_hook(const struct conf_t *conf, void *data) } // Setup logs - int loaded_sections = 0; - n = 0; + n = NULL; WALK_LIST(n, conf->logs) { // Calculate offset @@ -71,13 +72,6 @@ int log_conf_hook(const struct conf_t *conf, void *data) } } - // Auto-assign fatal errors to syslog or stderr - if (facility <= LOGT_STDERR) { - int mask = LOG_MASK(LOG_FATAL); - log_levels_add(facility, LOG_ANY, mask); - loaded_sections |= 1 << facility; - } - // Setup sources mapping node *m = 0; WALK_LIST(m, log->map) { @@ -88,14 +82,5 @@ int log_conf_hook(const struct conf_t *conf, void *data) } } - // Load defaults for syslog or stderr - int bmask = LOG_MASK(LOG_ERR)|LOG_MASK(LOG_FATAL); - if (!(loaded_sections & (1 << LOGT_SYSLOG))) { - log_levels_set(LOGT_SYSLOG, LOG_ANY, bmask); - } - if (!(loaded_sections & (1 << LOGT_STDERR))) { - log_levels_set(LOGT_STDERR, LOG_ANY, bmask); - } - return KNOT_EOK; } diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c index 73c6058..e2c42a1 100644 --- a/src/knot/ctl/knotc_main.c +++ b/src/knot/ctl/knotc_main.c @@ -79,7 +79,6 @@ typedef struct knot_cmd { /* Forward decls. */ static int cmd_stop(int argc, char *argv[], unsigned flags); -static int cmd_restart(int argc, char *argv[], unsigned flags); static int cmd_reload(int argc, char *argv[], unsigned flags); static int cmd_refresh(int argc, char *argv[], unsigned flags); static int cmd_flush(int argc, char *argv[], unsigned flags); @@ -92,7 +91,6 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags); /*! \brief Table of remote commands. */ knot_cmd_t knot_cmd_tbl[] = { {&cmd_stop, 0, "stop", "", "\t\tStop server."}, - {&cmd_restart, 0, "restart", "", "\tRestart server."}, {&cmd_reload, 0, "reload", "", "\tReload configuration and changed zones."}, {&cmd_refresh, 0, "refresh", "[zone]", "\tRefresh slave zone (all if not specified)."}, {&cmd_flush, 0, "flush", "", "\t\tFlush journal and update zone files."}, @@ -406,7 +404,6 @@ int main(int argc, char **argv) char *default_config = conf_find_default(); /* Remote server descriptor. */ - int ret = KNOT_EOK; const char *r_addr = NULL; int r_port = -1; knot_tsig_key_t r_key; @@ -441,23 +438,19 @@ int main(int argc, char **argv) r_port = atoi(optarg); break; case 'y': - ret = tsig_parse_str(&r_key, optarg); - if (ret != KNOT_EOK) { + if (tsig_parse_str(&r_key, optarg) != KNOT_EOK) { + rc = 1; log_server_error("Couldn't parse TSIG key '%s' " "\n", optarg); - knot_tsig_key_free(&r_key); - log_close(); - return 1; + goto exit; } break; case 'k': - ret = tsig_parse_file(&r_key, optarg); - if (ret != KNOT_EOK) { + if (tsig_parse_file(&r_key, optarg) != KNOT_EOK) { + rc = 1; log_server_error("Couldn't parse TSIG key file " "'%s'\n", optarg); - knot_tsig_key_free(&r_key); - log_close(); - return 1; + goto exit; } break; case 'w': @@ -551,18 +544,15 @@ int main(int argc, char **argv) if (strchr(r_addr, ':')) ctl_if->family = AF_INET6; - /* Check if address could be a UNIX socket. */ - if (strchr(r_addr, '/')) { - /* Check if file is really a socket. */ - struct stat st; - if (stat(r_addr, &st) == 0 && !S_ISSOCK(st.st_mode)) { - log_server_warning("Address '%s' is not a " - "UNIX socket.\n", r_addr); - } - + /* Is a valid UNIX socket or at least contains slash ? */ + struct stat st; + bool has_slash = strchr(r_addr, '/') != NULL; + bool is_file = stat(r_addr, &st) == 0; + if (has_slash || (is_file && S_ISSOCK(st.st_mode))) { ctl_if->family = AF_UNIX; r_port = 0; /* Override. */ } + } if (r_port > -1) ctl_if->port = r_port; @@ -593,15 +583,6 @@ static int cmd_stop(int argc, char *argv[], unsigned flags) return cmd_remote("stop", KNOT_RRTYPE_TXT, 0, NULL); } -static int cmd_restart(int argc, char *argv[], unsigned flags) -{ - UNUSED(argc); - UNUSED(argv); - UNUSED(flags); - - return cmd_remote("restart", KNOT_RRTYPE_TXT, 0, NULL); -} - static int cmd_reload(int argc, char *argv[], unsigned flags) { UNUSED(argc); @@ -787,24 +768,26 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags) process_error, &est); if (loader == NULL) { + rc = 1; log_zone_error("Could not load zone.\n"); hattrie_apply_rev(est.node_table, estimator_free_trie_node, NULL); hattrie_apply_rev(est.dname_table, estimator_free_trie_node, NULL); hattrie_free(est.node_table); hattrie_free(est.dname_table); - return KNOT_ERROR; + break; } /* Do a parser run, but do not actually create the zone. */ int ret = file_loader_process(loader); if (ret != KNOT_EOK) { + rc = 1; log_zone_error("Failed to parse zone.\n"); hattrie_apply_rev(est.node_table, estimator_free_trie_node, NULL); hattrie_apply_rev(est.dname_table, estimator_free_trie_node, NULL); hattrie_free(est.node_table); hattrie_free(est.dname_table); file_loader_free(loader); - return KNOT_ERROR; + break; } /* Only size of ahtables inside trie's nodes is missing. */ @@ -830,7 +813,7 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags) total_size += zone_size; } - if (argc == 0) { // for all zones + if (rc == 0 && argc == 0) { // for all zones log_zone_info("Estimated memory consumption for all zones is %zuMB.\n", total_size); } diff --git a/src/knot/ctl/process.c b/src/knot/ctl/process.c index f5db3ca..564fff2 100644 --- a/src/knot/ctl/process.c +++ b/src/knot/ctl/process.c @@ -39,8 +39,12 @@ char* pid_filename() /* Read configuration. */ char* ret = NULL; - if (conf() && conf()->rundir != NULL) { - ret = strcdup(conf()->rundir, "/knot.pid"); + + if (conf()) { + if (conf()->pidfile != NULL) + ret = strdup(conf()->pidfile); + else if (conf()->rundir != NULL) + ret = strcdup(conf()->rundir, "/knot.pid"); } rcu_read_unlock(); diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c index 7de68b5..2234bca 100644 --- a/src/knot/ctl/remote.c +++ b/src/knot/ctl/remote.c @@ -59,7 +59,6 @@ typedef struct remote_cmd_t { /* Forward decls. */ static int remote_c_stop(server_t *s, remote_cmdargs_t* a); -static int remote_c_restart(server_t *s, remote_cmdargs_t* a); static int remote_c_reload(server_t *s, remote_cmdargs_t* a); static int remote_c_refresh(server_t *s, remote_cmdargs_t* a); static int remote_c_status(server_t *s, remote_cmdargs_t* a); @@ -69,7 +68,6 @@ static int remote_c_flush(server_t *s, remote_cmdargs_t* a); /*! \brief Table of remote commands. */ struct remote_cmd_t remote_cmd_tbl[] = { { "stop", &remote_c_stop }, - { "restart", &remote_c_restart }, { "reload", &remote_c_reload }, { "refresh", &remote_c_refresh }, { "status", &remote_c_status }, @@ -177,18 +175,6 @@ static int remote_c_stop(server_t *s, remote_cmdargs_t* a) } /*! - * \brief Remote command 'restart' handler. - * - * QNAME: restart - * DATA: NULL - */ -static int remote_c_restart(server_t *s, remote_cmdargs_t* a) -{ - UNUSED(a); - return KNOT_CTL_RESTART; -} - -/*! * \brief Remote command 'reload' handler. * * QNAME: reload @@ -416,14 +402,15 @@ int remote_unbind(int r) int remote_poll(int r) { - if (r < 0) { - return -1; - } - /* Wait for events. */ fd_set rfds; FD_ZERO(&rfds); - FD_SET(r, &rfds); + if (r > -1) { + FD_SET(r, &rfds); + } else { + r = -1; /* Make sure n == r + 1 == 0 */ + } + return fdset_pselect(r + 1, &rfds, NULL, NULL, NULL, NULL); } diff --git a/src/knot/knot.h b/src/knot/knot.h index fb0f9fd..0f517a9 100644 --- a/src/knot/knot.h +++ b/src/knot/knot.h @@ -30,36 +30,20 @@ #include <signal.h> #include <stdint.h> -/* - * Common types and constants. - */ - -#define PROJECT_EXENAME "knotd" -#define PROJECT_EXEC SBINDIR "/" PROJECT_EXENAME /*!< \brief Project executable. */ -#define PID_FILE "knot.pid" /*!< \brief Server PID file name. */ - -/* - * Server. - */ +#include "common/print.h" +#include "common/log.h" +#include "common/errcode.h" +#include "knot/other/debug.h" #define CPU_ESTIMATE_MAGIC 0 /*!< \brief Extra threads to the number of cores.*/ #define DEFAULT_THR_COUNT 2 /*!< \brief Default thread count. */ -#define TCP_BACKLOG_SIZE 10 /*!< \brief TCP listen backlog size. */ +#define TCP_BACKLOG_SIZE 10 /*!< \brief TCP listen backlog size. */ #define XFR_THREADS_COUNT 3 /*!< \brief Number of threads for XFR handler. */ #define RECVMMSG_BATCHLEN 64 /*!< \brief Define for recvmmsg() batch size. */ ///*! \brief If defined, the statistics module will be enabled. */ //#define STAT_COMPILE -/* - * Common includes. - */ - -#include "common/print.h" -#include "common/log.h" -#include "common/errcode.h" -#include "knot/other/debug.h" - /* Workarounds for clock_gettime() not available on some platforms. */ #ifdef HAVE_CLOCK_GETTIME #define time_now(x) clock_gettime(CLOCK_MONOTONIC, (x)) diff --git a/src/knot/main.c b/src/knot/main.c index c5e693c..610b21f 100644 --- a/src/knot/main.c +++ b/src/knot/main.c @@ -41,11 +41,15 @@ /* Signal flags. */ static volatile short sig_req_stop = 0; -static volatile short sig_req_rst = 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); @@ -58,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) { @@ -73,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) @@ -81,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" @@ -98,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'}, @@ -105,12 +118,25 @@ 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': config_fn = strdup(optarg); break; +#ifdef INTEGRITY_CHECK + case 'z': + if (optarg[strlen(optarg) - 1] != '.') { + zone = strcdup(optarg, "."); + } else { + zone = strdup(optarg); + } + break; +#endif /* INTEGRITY_CHECK */ case 'd': daemonize = 1; break; @@ -152,9 +178,6 @@ int main(int argc, char **argv) sigaction(SIGPIPE, &emptyset, NULL); // Mask rcu_register_thread(); - // Setup event queue - evqueue_set(evqueue_new()); - // Initialize log log_init(); @@ -297,12 +320,14 @@ int main(int argc, char **argv) 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); /* Bind to control interface. */ - uint8_t buf[65535]; /*! \todo #2035 should be on heap */ + uint8_t buf[SOCKET_MTU_SZ]; size_t buflen = sizeof(buf); int remote = -1; if (conf()->ctl.iface != NULL) { @@ -316,9 +341,6 @@ int main(int argc, char **argv) ctl_if->address, (char*)buf); remote = remote_bind(ctl_if); } - if (remote < 0) - remote = evqueue()->fds[EVQUEUE_READFD]; - /* Run event loop. */ for(;;) { @@ -331,8 +353,6 @@ int main(int argc, char **argv) ret = remote_process(server, conf()->ctl.iface, remote, buf, buflen); switch(ret) { - case KNOT_CTL_RESTART: - sig_req_rst = 1; /* Fall through */ case KNOT_CTL_STOP: sig_req_stop = 1; break; @@ -351,23 +371,40 @@ 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); /* Close remote control interface */ if (remote > -1) { close(remote); + + /* Remove control socket. */ + conf_iface_t *ctl_if = conf()->ctl.iface; + if (ctl_if && ctl_if->family == AF_UNIX) + unlink(conf()->ctl.iface->address); } if ((server_wait(server)) != KNOT_EOK) { @@ -392,6 +429,10 @@ int main(int argc, char **argv) log_server_warning("Failed to remove PID file.\n"); do_cleanup(server, config_fn, pidf); +#ifdef INTEGRITY_CHECK + free(zone); +#endif /* INTEGRITY_CHECK */ + if (!daemonize) { fflush(stdout); fflush(stderr); @@ -404,10 +445,6 @@ int main(int argc, char **argv) free(cwd); } - /* Restart hook. */ - if (sig_req_rst) - return execvp(PROJECT_EXEC, argv); - return res; } @@ -424,8 +461,5 @@ static int do_cleanup(server_t *server, char *configf, char *pidf) /* Unhook from RCU */ rcu_unregister_thread(); - /* Free event loop. */ - evqueue_t *q = evqueue(); - evqueue_free(&q); return 1; } diff --git a/src/knot/server/server.c b/src/knot/server/server.c index cef3801..7244d3c 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -629,18 +629,15 @@ int server_conf_hook(const struct conf_t *conf, void *data) return ret; } -ref_t *server_set_ifaces(server_t *s, fdset_t **fds, int *count, int type) +ref_t *server_set_ifaces(server_t *s, fdset_t *fds, int type) { iface_t *i = NULL; - *count = 0; rcu_read_lock(); - fdset_destroy(*fds); - *fds = fdset_new(); + fdset_clear(fds); if (s->ifaces) { WALK_LIST(i, s->ifaces->l) { - fdset_add(*fds, i->fd[type], OS_EV_READ); - *count += 1; + fdset_add(fds, i->fd[type], POLLIN, NULL); } } diff --git a/src/knot/server/server.h b/src/knot/server/server.h index 84a32e3..a766b0b 100644 --- a/src/knot/server/server.h +++ b/src/knot/server/server.h @@ -236,11 +236,10 @@ int server_conf_hook(const struct conf_t *conf, void *data); * \brief Update fdsets from current interfaces list. * \param s Server. * \param fds Filedescriptor set. - * \param count Number of ifaces (will be set to N). * \param type I/O type (UDP/TCP). * \return new interface list */ -ref_t *server_set_ifaces(server_t *s, fdset_t **fds, int *count, int type); +ref_t *server_set_ifaces(server_t *s, fdset_t *fds, int type); #endif // _KNOTD_SERVER_H_ diff --git a/src/knot/server/socket.h b/src/knot/server/socket.h index 1849f1d..371977a 100644 --- a/src/knot/server/socket.h +++ b/src/knot/server/socket.h @@ -39,9 +39,7 @@ #include "common/sockaddr.h" /*! \brief Socket-related constants. */ -typedef enum { - SOCKET_MTU_SZ = 65535, /*!< Maximum MTU size. */ -} socket_const_t; +#define SOCKET_MTU_SZ 65535 /*!< Maximum MTU size. */ /*! * \brief Create socket. diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c index f8fe90b..1f18abf 100644 --- a/src/knot/server/tcp-handler.c +++ b/src/knot/server/tcp-handler.c @@ -39,13 +39,10 @@ #include "libknot/nameserver/name-server.h" #include "libknot/util/wire.h" -/* Defines */ -#define TCP_BUFFER_SIZE 65535 /*! Do not change, as it is used for maximum DNS/TCP packet size. */ - /*! \brief TCP worker data. */ typedef struct tcp_worker_t { iohandler_t *ioh; /*!< Shortcut to I/O handler. */ - fdset_t *fdset; /*!< File descriptor set. */ + fdset_t set; /*!< File descriptor set. */ int pipe[2]; /*!< Master-worker signalization pipes. */ } tcp_worker_t; @@ -83,17 +80,19 @@ static int tcp_reply(int fd, uint8_t *qbuf, size_t resp_len) } /*! \brief Sweep TCP connection. */ -static void tcp_sweep(fdset_t *set, int fd, void* data) +static enum fdset_sweep_state tcp_sweep(fdset_t *set, int i, void *data) { UNUSED(data); + assert(set && i < set->n && i >= 0); + int fd = set->pfd[i].fd; char r_addr[SOCKADDR_STRLEN] = { '\0' }; int r_port = 0; struct sockaddr_storage addr; socklen_t len = sizeof(addr); if (getpeername(fd, (struct sockaddr*)&addr, &len) < 0) { dbg_net("tcp: sweep getpeername() on invalid socket=%d\n", fd); - return; + return FDSET_SWEEP; } /* Translate */ @@ -111,8 +110,8 @@ static void tcp_sweep(fdset_t *set, int fd, void* data) log_server_notice("Connection with '%s@%d' was terminated due to " "inactivity.\n", r_addr, r_port); - fdset_remove(set, fd); close(fd); + return FDSET_SWEEP; } /*! @@ -324,13 +323,34 @@ int tcp_accept(int fd) return incoming; } +/*! \brief Read a descriptor from the pipe and assign it to given fdset. */ +static int tcp_loop_assign(int pipe, fdset_t *set) +{ + /* Read socket descriptor from pipe. */ + int client, next_id; + if (read(pipe, &client, sizeof(int)) != sizeof(int)) { + return KNOT_ENOENT; + } + + /* Assign to fdset. */ + next_id = fdset_add(set, client, POLLIN, NULL); + if (next_id < 0) { + socket_close(client); + return next_id; /* Contains errno. */ + } + + /* Update watchdog timer. */ + rcu_read_lock(); + fdset_set_watchdog(set, next_id, conf()->max_conn_hs); + rcu_read_unlock(); + return next_id; +} + tcp_worker_t* tcp_worker_create() { tcp_worker_t *w = malloc(sizeof(tcp_worker_t)); - if (w == NULL) { - dbg_net("tcp: out of memory when creating worker\n"); + if (w == NULL) return NULL; - } /* Create signal pipes. */ memset(w, 0, sizeof(tcp_worker_t)); @@ -340,16 +360,14 @@ tcp_worker_t* tcp_worker_create() } /* Create fdset. */ - w->fdset = fdset_new(); - if (!w->fdset) { + if (fdset_init(&w->set, FDSET_INIT_SIZE) != KNOT_EOK) { close(w->pipe[0]); close(w->pipe[1]); free(w); return NULL; } - fdset_add(w->fdset, w->pipe[0], OS_EV_READ); - + fdset_add(&w->set, w->pipe[0], POLLIN, NULL); return w; } @@ -359,8 +377,8 @@ void tcp_worker_free(tcp_worker_t* w) return; } - /* Destroy fdset. */ - fdset_destroy(w->fdset); + /* Clear fdset. */ + fdset_clear(&w->set); /* Close pipe write end and worker. */ close(w->pipe[0]); @@ -394,15 +412,21 @@ int tcp_send(int fd, uint8_t *msg, size_t msglen) int uncork = setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork)); #endif + /* Flags. */ + int flags = 0; +#ifdef MSG_NOSIGNAL + flags |= MSG_NOSIGNAL; +#endif + /* Send message size. */ unsigned short pktsize = htons(msglen); - int sent = send(fd, &pktsize, sizeof(pktsize), 0); + int sent = send(fd, &pktsize, sizeof(pktsize), flags); if (sent < 0) { return KNOT_ERROR; } /* Send message data. */ - sent = send(fd, msg, msglen, 0); + sent = send(fd, msg, msglen, flags); if (sent < 0) { return KNOT_ERROR; } @@ -421,9 +445,15 @@ int tcp_send(int fd, uint8_t *msg, size_t msglen) int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr) { + /* Flags. */ + int flags = MSG_WAITALL; +#ifdef MSG_NOSIGNAL + flags |= MSG_NOSIGNAL; +#endif + /* Receive size. */ unsigned short pktsize = 0; - int n = recv(fd, &pktsize, sizeof(unsigned short), MSG_WAITALL); + int n = recv(fd, &pktsize, sizeof(unsigned short), flags); if (n < 0) { if (errno == EAGAIN) { return KNOT_EAGAIN; @@ -455,7 +485,7 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr) } /* Receive payload. */ - n = recv(fd, buf, pktsize, MSG_WAITALL); + n = recv(fd, buf, pktsize, flags); if (n < 0) { if (errno == EAGAIN) { return KNOT_EAGAIN; @@ -481,23 +511,22 @@ int tcp_loop_master(dthread_t *thread) tcp_worker_t **workers = h->data; /* Prepare structures for bound sockets. */ - fdset_it_t it; - fdset_t *fds = NULL; ref_t *ref = NULL; - int if_cnt = 0; + fdset_t set; + fdset_init(&set, conf()->ifaces_count); /* Accept connections. */ - int id = 0; - dbg_net("tcp: created 1 master with %d workers, backend is '%s' \n", - unit->size - 1, fdset_method()); + int id = 0, ret = 0; + dbg_net("tcp: created 1 master with %d workers\n", unit->size - 1); for(;;) { /* Check handler state. */ if (knot_unlikely(st->s & ServerReload)) { st->s &= ~ServerReload; ref_release(ref); - ref = server_set_ifaces(h->server, &fds, &if_cnt, IO_TCP); - if (if_cnt == 0) break; + ref = server_set_ifaces(h->server, &set, IO_TCP); + if (set.n == 0) /* Terminate on zero interfaces. */ + break; } /* Check for cancellation. */ @@ -506,35 +535,34 @@ int tcp_loop_master(dthread_t *thread) } /* Wait for events. */ - int nfds = fdset_wait(fds, OS_EV_FOREVER); + int nfds = poll(set.pfd, set.n, -1); if (nfds <= 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; break; } - fdset_begin(fds, &it); - while(nfds > 0) { - /* Accept client. */ - int client = tcp_accept(it.fd); - if (client > -1) { - /* Add to worker in RR fashion. */ - if (write(workers[id]->pipe[1], &client, sizeof(int)) < 0) { - dbg_net("tcp: failed to register fd=%d to worker=%d\n", - client, id); - close(client); - continue; - } - id = get_next_rr(id, unit->size - 1); - } + for (unsigned i = 0; nfds > 0 && i < set.n; ++i) { + /* Skip inactive. */ + if (!(set.pfd[i].revents & POLLIN)) + continue; - if (fdset_next(fds, &it) != 0) { - break; - } + /* Accept client. */ + --nfds; /* One less active event. */ + int client = tcp_accept(set.pfd[i].fd); + if (client < 0) + continue; + + /* Add to worker in RR fashion. */ + id = get_next_rr(id, unit->size - 1); + ret = write(workers[id]->pipe[1], &client, sizeof(int)); + if (ret < 0) + close(client); } } dbg_net("tcp: master thread finished\n"); - fdset_destroy(fds); + fdset_clear(&set); ref_release(ref); return KNOT_EOK; @@ -542,18 +570,6 @@ int tcp_loop_master(dthread_t *thread) int tcp_loop_worker(dthread_t *thread) { - tcp_worker_t *w = thread->data; - if (!w) { - return KNOT_EINVAL; - } - - /* Allocate buffer for requests. */ - uint8_t *qbuf = malloc(TCP_BUFFER_SIZE); - if (qbuf == NULL) { - dbg_net("tcp: failed to allocate buffers for TCP worker\n"); - return KNOT_EINVAL; - } - /* Drop all capabilities on workers. */ #ifdef HAVE_CAP_NG_H if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) { @@ -562,84 +578,74 @@ int tcp_loop_worker(dthread_t *thread) } #endif /* HAVE_CAP_NG_H */ - /* Next sweep time. */ + uint8_t *qbuf = malloc(SOCKET_MTU_SZ); + tcp_worker_t *w = thread->data; + if (w == NULL || qbuf == NULL) { + free(qbuf); + return KNOT_EINVAL; + } + + /* Accept clients. */ + dbg_net("tcp: worker %p started\n", w); + fdset_t *set = &w->set; timev_t next_sweep; time_now(&next_sweep); next_sweep.tv_sec += TCP_SWEEP_INTERVAL; - - /* Accept clients. */ - dbg_net_verb("tcp: worker %p started\n", w); for (;;) { /* Cancellation point. */ - if (dt_is_cancelled(thread)) { + if (dt_is_cancelled(thread)) break; - } /* Wait for events. */ - int nfds = fdset_wait(w->fdset, (TCP_SWEEP_INTERVAL * 1000)/2); - if (nfds < 0) { + int nfds = poll(set->pfd, set->n, TCP_SWEEP_INTERVAL * 1000); + if (nfds < 0) continue; - } /* Establish timeouts. */ rcu_read_lock(); int max_idle = conf()->max_conn_idle; - int max_hs = conf()->max_conn_hs; rcu_read_unlock(); /* Process incoming events. */ - dbg_net_verb("tcp: worker %p registered %d events\n", - w, nfds); - fdset_it_t it; - fdset_begin(w->fdset, &it); - while(nfds > 0) { - - /* Handle incoming clients. */ - if (it.fd == w->pipe[0]) { - int client = 0; - if (read(it.fd, &client, sizeof(int)) < 0) { - continue; - } + unsigned i = 0; + while (nfds > 0 && i < set->n) { - dbg_net_verb("tcp: worker %p registered " - "client %d\n", - w, client); - fdset_add(w->fdset, client, OS_EV_READ); - fdset_set_watchdog(w->fdset, client, max_hs); - dbg_net("tcp: watchdog for fd=%d set to %ds\n", - client, max_hs); + if (!(set->pfd[i].revents & set->pfd[i].events)) { + /* Skip inactive. */ + ++i; + continue; } else { - /* Handle other events. */ - int ret = tcp_handle(w, it.fd, qbuf, - TCP_BUFFER_SIZE); + /* One less active event. */ + --nfds; + } + + /* Register new TCP client or process a query. */ + int fd = set->pfd[i].fd; + if (fd == w->pipe[0]) { + tcp_loop_assign(fd, set); + } else { + int ret = tcp_handle(w, fd, qbuf, SOCKET_MTU_SZ); if (ret == KNOT_EOK) { - fdset_set_watchdog(w->fdset, it.fd, - max_idle); - dbg_net("tcp: watchdog for fd=%d " - "set to %ds\n", - it.fd, max_idle); + /* Update socket activity timer. */ + fdset_set_watchdog(set, i, max_idle); } - /*! \todo Refactor to allow erase on iterator.*/ if (ret == KNOT_ECONNREFUSED) { - fdset_remove(w->fdset, it.fd); - close(it.fd); - break; + fdset_remove(set, i); + close(fd); + continue; /* Stay on the same index. */ } - } - /* Check if next exists. */ - if (fdset_next(w->fdset, &it) != 0) { - break; - } + /* Next active. */ + ++i; } /* Sweep inactive. */ timev_t now; if (time_now(&now) == 0) { if (now.tv_sec >= next_sweep.tv_sec) { - fdset_sweep(w->fdset, &tcp_sweep, NULL); + fdset_sweep(set, &tcp_sweep, NULL); memcpy(&next_sweep, &now, sizeof(next_sweep)); next_sweep.tv_sec += TCP_SWEEP_INTERVAL; } @@ -648,7 +654,7 @@ int tcp_loop_worker(dthread_t *thread) /* Stop whole unit. */ free(qbuf); - dbg_net_verb("tcp: worker %p finished\n", w); + dbg_net("tcp: worker %p finished\n", w); return KNOT_EOK; } diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c index c7c1abf..90b0a42 100644 --- a/src/knot/server/xfr-handler.c +++ b/src/knot/server/xfr-handler.c @@ -44,9 +44,9 @@ #include "libknot/rrset.h" /* Constants */ -#define XFR_CHUNKLEN 3 /*! Number of requests assigned in a single pass. */ +#define XFR_MAX_TASKS 1024 /*! Maximum pending tasks. */ +#define XFR_CHUNKLEN 16 /*! Number of requests assigned in a single pass. */ #define XFR_SWEEP_INTERVAL 2 /*! [seconds] between sweeps. */ -#define XFR_BUFFER_SIZE 65535 /*! Do not change this - maximum value for UDP packet length. */ #define XFR_MSG_DLTTR 9 /*! Index of letter differentiating IXFR/AXFR in log msg. */ /* Messages */ @@ -62,14 +62,37 @@ static knot_lookup_table_t xfr_type_table[] = { { XFR_TYPE_AIN, NULL } }; static knot_lookup_table_t xfr_result_table[] = { - { XFR_TYPE_AIN, "Started" }, - { XFR_TYPE_IIN, "Started" }, - { XFR_TYPE_SOA, "Query issued" }, - { XFR_TYPE_NOTIFY, "Query issued" }, - { XFR_TYPE_FORWARD, "Forwarded query" }, + { XFR_TYPE_AIN, "Started." }, + { XFR_TYPE_IIN, "Started." }, + { XFR_TYPE_SOA, "Query issued." }, + { XFR_TYPE_NOTIFY, "Query issued." }, + { XFR_TYPE_FORWARD, "Forwarded query." }, { XFR_TYPE_AIN, NULL } }; +/* Limits. */ +static bool xfr_pending_incr(xfrhandler_t *xfr) +{ + bool ret = false; + pthread_mutex_lock(&xfr->pending_mx); + rcu_read_lock(); + if (xfr->pending < conf()->xfers) { + ++xfr->pending; + ret = true; + } + rcu_read_unlock(); + pthread_mutex_unlock(&xfr->pending_mx); + + return ret; +} + +static void xfr_pending_decr(xfrhandler_t *xfr) +{ + pthread_mutex_lock(&xfr->pending_mx); + --xfr->pending; + pthread_mutex_unlock(&xfr->pending_mx); +} + /* I/O wrappers */ static int xfr_send_tcp(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen) @@ -84,28 +107,6 @@ static int xfr_recv_tcp(int fd, sockaddr_t *addr, uint8_t *buf, size_t buflen) static int xfr_recv_udp(int fd, sockaddr_t *addr, uint8_t *buf, size_t buflen) { return recvfrom(fd, buf, buflen, 0, (struct sockaddr *)addr, &addr->len); } -/* Context fetching. */ - -static knot_ns_xfr_t* xfr_task_get(xfrworker_t *w, int fd) -{ - value_t *val = ahtable_tryget(w->pool.t, (const char*)&fd, sizeof(int)); - if (!val) return NULL; - return *val; -} - -static void xfr_task_set(xfrworker_t *w, int fd, knot_ns_xfr_t *rq) -{ - fdset_add(w->pool.fds, fd, OS_EV_READ); - value_t *val = ahtable_get(w->pool.t, (const char*)&fd, sizeof(int)); - *val = rq; -} - -static void xfr_task_clear(xfrworker_t *w, int fd) -{ - ahtable_del(w->pool.t, (const char*)&fd, sizeof(int)); - fdset_remove(w->pool.fds, fd); -} - /*! \brief Wrapper function for answering AXFR/OUT. */ static int xfr_answer_axfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr) { @@ -241,10 +242,8 @@ static int xfr_task_setsig(knot_ns_xfr_t *rq, knot_tsig_key_t *key) static int xfr_task_connect(knot_ns_xfr_t *rq) { /* Create socket by type. */ - int stype = SOCK_DGRAM; - if (rq->flags & XFR_FLAG_TCP) { - stype = SOCK_STREAM; - } + int ret = 0; + int stype = (rq->flags & XFR_FLAG_TCP) ? SOCK_STREAM : SOCK_DGRAM; int fd = socket_create(sockaddr_family(&rq->addr), stype, 0); if (fd < 0) { return KNOT_ERROR; @@ -257,14 +256,22 @@ static int xfr_task_connect(knot_ns_xfr_t *rq) return KNOT_ERROR; } } + /* Connect if TCP. */ if (rq->flags & XFR_FLAG_TCP) { - if (connect(fd, (struct sockaddr *)&rq->addr, rq->addr.len) < 0) { + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) + ; /* Go silently with blocking if it fails. */ + + ret = connect(fd, (struct sockaddr *)&rq->addr, rq->addr.len); + if (ret != 0 && errno != EINPROGRESS) { socket_close(fd); return KNOT_ECONNREFUSED; } } + /* Set up for UDP as well to trigger 'send query' event. */ + rq->flags |= XFR_FLAG_CONNECTING; + /* Store new socket descriptor. */ rq->session = fd; return KNOT_EOK; @@ -299,15 +306,12 @@ static void xfr_task_cleanup(knot_ns_xfr_t *rq) hattrie_clear(rq->lookup_tree); } -/*! \brief Close and free task. */ -static int xfr_task_close(xfrworker_t *w, int fd) +/*! \brief End task properly and free it. */ +static int xfr_task_close(knot_ns_xfr_t *rq) { - knot_ns_xfr_t *rq = xfr_task_get(w, fd); - if (!rq) return KNOT_ENOENT; - /* Update xfer state. */ + zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone); if (rq->type == XFR_TYPE_AIN || rq->type == XFR_TYPE_IIN) { - zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone); pthread_mutex_lock(&zd->lock); if (zd->xfr_in.state == XFR_PENDING) { zd->xfr_in.state = XFR_IDLE; @@ -315,15 +319,25 @@ static int xfr_task_close(xfrworker_t *w, int fd) pthread_mutex_unlock(&zd->lock); } + /* Reschedule failed bootstrap. */ + if (rq->type == XFR_TYPE_AIN && !knot_zone_contents(rq->zone)) { + int tmr_s = AXFR_BOOTSTRAP_RETRY * tls_rand(); + event_t *ev = zd->xfr_in.timer; + if (ev) { + evsched_cancel(ev->parent, ev); + evsched_schedule(ev->parent, ev, tmr_s); + } + log_zone_notice("%s Bootstrap failed, next attempt in %d seconds.\n", + rq->msg, tmr_s / 1000); + } + /* Close socket and free task. */ - xfr_task_clear(w, fd); xfr_task_free(rq); - socket_close(fd); return KNOT_EOK; } /*! \brief Timeout handler. */ -static int xfr_task_expire(fdset_t *fds, knot_ns_xfr_t *rq) +static int xfr_task_expire(fdset_t *set, int i, knot_ns_xfr_t *rq) { /* Fetch related zone (refcounted, no RCU). */ knot_zone_t *zone = (knot_zone_t *)rq->zone; @@ -335,7 +349,7 @@ static int xfr_task_expire(fdset_t *fds, knot_ns_xfr_t *rq) case XFR_TYPE_NOTIFY: if ((long)--rq->data > 0) { /* Retries */ notify_create_request(contents, rq->wire, &rq->wire_size); - fdset_set_watchdog(fds, rq->session, NOTIFY_TIMEOUT); + fdset_set_watchdog(set, i, NOTIFY_TIMEOUT); rq->send(rq->session, &rq->addr, rq->wire, rq->wire_size); log_zone_info("%s Query issued (serial %u).\n", rq->msg, knot_zone_serial(contents)); @@ -370,14 +384,6 @@ static int xfr_task_start(knot_ns_xfr_t *rq) return KNOT_ECONNREFUSED; } - /* Connect to remote. */ - if (rq->session <= 0) { - ret = xfr_task_connect(rq); - if (ret != KNOT_EOK) { - return ret; - } - } - /* Prepare TSIG key if set. */ int add_tsig = 0; if (rq->tsig_key) { @@ -437,20 +443,13 @@ static int xfr_task_start(knot_ns_xfr_t *rq) return KNOT_EOK; } -static int xfr_task_process(xfrworker_t *w, knot_ns_xfr_t* rq, uint8_t *buf, size_t buflen) +static int xfr_task_is_transfer(knot_ns_xfr_t *rq) { - /* Check if not already processing, zone is refcounted. */ - zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone); - - /* Check if the zone is not discarded. */ - if (!zd || knot_zone_flags(rq->zone) & KNOT_ZONE_DISCARDED) { - dbg_xfr_verb("xfr: request on a discarded zone, ignoring\n"); - return KNOT_EINVAL; - } - - /* Update XFR message prefix. */ - xfr_task_setmsg(rq, NULL); + return rq->type == XFR_TYPE_AIN || rq->type == XFR_TYPE_IIN; +} +static void xfr_async_setbuf(knot_ns_xfr_t *rq, uint8_t *buf, size_t buflen) +{ /* Update request. */ rq->wire = buf; rq->wire_size = buflen; @@ -461,17 +460,81 @@ static int xfr_task_process(xfrworker_t *w, knot_ns_xfr_t* rq, uint8_t *buf, siz rq->send = &xfr_send_tcp; rq->recv = &xfr_recv_tcp; } +} + +static int xfr_async_start(fdset_t *set, knot_ns_xfr_t *rq) +{ + /* Update XFR message prefix. */ + int ret = KNOT_EOK; + xfr_task_setmsg(rq, NULL); + + /* Connect to remote. */ + if (rq->session <= 0) + ret = xfr_task_connect(rq); + + /* Add to set. */ + if (ret == KNOT_EOK) { + unsigned flags = POLLIN; + if (rq->flags & XFR_FLAG_CONNECTING) + flags = POLLOUT; + int next_id = fdset_add(set, rq->session, flags, rq); + if (next_id >= 0) { + /* Set default connection timeout. */ + rcu_read_lock(); + fdset_set_watchdog(set, next_id, conf()->max_conn_reply); + rcu_read_unlock(); + } else { + /* Or refuse if failed. */ + ret = KNOT_ECONNREFUSED; + } + } + + return ret; +} + +static int xfr_async_state(knot_ns_xfr_t *rq) +{ + /* Check socket status. */ + int err = EINVAL; + socklen_t len = sizeof(int); + if (getsockopt(rq->session, SOL_SOCKET, SO_ERROR, &err, &len) < 0) + return KNOT_ERROR; + if (err != 0) + return knot_map_errno(err); + return KNOT_EOK; +} + +static int xfr_async_finish(fdset_t *set, unsigned id) +{ + /* Drop back to synchronous mode. */ + int ret = KNOT_EOK; + knot_ns_xfr_t *rq = (knot_ns_xfr_t *)set->ctx[id]; + if ((ret = xfr_async_state(rq)) == KNOT_EOK) { + rq->flags &= ~XFR_FLAG_CONNECTING; + set->pfd[id].events = POLLIN; + if (fcntl(set->pfd[id].fd, F_SETFL, 0) < 0) + ; + } else { + /* Do not attempt to start on broken connection. */ + return KNOT_ECONNREFUSED; + } + + /* Check if the zone is not discarded. */ + zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone); + if (!zd || knot_zone_flags(rq->zone) & KNOT_ZONE_DISCARDED) { + dbg_xfr_verb("xfr: request on a discarded zone, ignoring\n"); + return KNOT_EINVAL; + } /* Handle request. */ dbg_xfr("%s processing request type '%d'\n", rq->msg, rq->type); - int ret = xfr_task_start(rq); + ret = xfr_task_start(rq); const char *msg = knot_strerror(ret); knot_lookup_table_t *xd = knot_lookup_by_id(xfr_result_table, rq->type); if (xd && ret == KNOT_EOK) { msg = xd->name; } - int bootstrap_fail = 0; switch(rq->type) { case XFR_TYPE_AIN: case XFR_TYPE_IIN: @@ -480,36 +543,28 @@ static int xfr_task_process(xfrworker_t *w, knot_ns_xfr_t* rq, uint8_t *buf, siz pthread_mutex_lock(&zd->lock); zd->xfr_in.state = XFR_IDLE; pthread_mutex_unlock(&zd->lock); - bootstrap_fail = !knot_zone_contents(rq->zone); } break; - case XFR_TYPE_NOTIFY: /* Send on first timeout <0,5>s. */ - fdset_set_watchdog(w->pool.fds, rq->session, (int)(tls_rand() * 5)); - xfr_task_set(w, rq->session, rq); + case XFR_TYPE_NOTIFY: + /* This is a bit of a hack to adapt NOTIFY lifetime tracking. + * When NOTIFY event enters handler, it shouldn't be sent immediately. + * To accomodate for this, <0, 5>s random delay is set on + * event startup, so the first query fires when this timer + * expires. */ + fdset_set_watchdog(set, id, (int)(tls_rand() * 5)); return KNOT_EOK; case XFR_TYPE_SOA: case XFR_TYPE_FORWARD: - fdset_set_watchdog(w->pool.fds, rq->session, conf()->max_conn_reply); + fdset_set_watchdog(set, id, conf()->max_conn_reply); break; default: break; } if (ret == KNOT_EOK) { - xfr_task_set(w, rq->session, rq); - log_server_info("%s %s.\n", rq->msg, msg); - } else if (bootstrap_fail){ - int tmr_s = AXFR_BOOTSTRAP_RETRY * tls_rand(); - event_t *ev = zd->xfr_in.timer; - if (ev) { - evsched_cancel(ev->parent, ev); - evsched_schedule(ev->parent, ev, tmr_s); - } - log_zone_notice("%s Bootstrap failed, next " - "attempt in %d seconds.\n", - rq->msg, tmr_s / 1000); + log_server_info("%s %s\n", rq->msg, msg); } else { - log_server_error("%s %s.\n", rq->msg, msg); + log_server_error("%s %s\n", rq->msg, msg); } return ret; @@ -745,16 +800,11 @@ static int xfr_task_xfer(xfrworker_t *w, knot_ns_xfr_t *rq) /* Only for successful xfers. */ if (ret > 0) { ret = xfr_task_finalize(w, rq); - if (ret != KNOT_EOK && !knot_zone_contents(rq->zone)) { - - /* AXFR bootstrap timeout. */ - zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone); - int tmr_s = AXFR_BOOTSTRAP_RETRY * tls_rand(); - zd->xfr_in.bootstrap_retry = tmr_s; - log_zone_info("%s Next attempt to bootstrap " - "in %d seconds.\n", - rq->msg, tmr_s / 1000); - } else if (ret == KNOT_EBUSY && rq->type == XFR_TYPE_IIN) { + + /* EBUSY on incremental transfer has a special meaning and + * is caused by a journal not able to free up space for incoming + * transfer, thus forcing to start a new full zone transfer. */ + if (ret == KNOT_EBUSY && rq->type == XFR_TYPE_IIN) { return xfr_start_axfr(w, rq, diff_nospace_msg); } else { @@ -763,7 +813,7 @@ static int xfr_task_xfer(xfrworker_t *w, knot_ns_xfr_t *rq) } /* Update REFRESH/RETRY */ - zones_schedule_refresh(rq->zone, 0); + zones_schedule_refresh(rq->zone, REFRESH_DEFAULT); ret = KNOT_ECONNREFUSED; /* Disconnect */ } @@ -801,37 +851,36 @@ static int xfr_process_event(xfrworker_t *w, knot_ns_xfr_t *rq) } } -/*! \brief Sweep non-replied connection. */ -static void xfr_sweep(fdset_t *set, int fd, void *data) +/*! \brief Sweep inactive connection. */ +static enum fdset_sweep_state xfr_sweep(fdset_t *set, int i, void *data) { - dbg_xfr("xfr: sweeping fd=%d\n", fd); - if (!set || !data) { - dbg_xfr("xfr: invalid sweep operation on NULL worker or set\n"); - return; - } - xfrworker_t *w = (xfrworker_t *)data; - knot_ns_xfr_t *rq = xfr_task_get(w, fd); - if (!rq) { - dbg_xfr("xfr: NULL data to sweep\n"); - return; - } + assert(set && i < set->n && i >= 0); + + knot_ns_xfr_t *rq = set->ctx[i]; + xfrhandler_t *xfr = (xfrhandler_t *)data; - /* Skip non-sweepable types. */ + /* Expire only UDP requests. */ int ret = KNOT_ECONNREFUSED; switch(rq->type) { case XFR_TYPE_SOA: case XFR_TYPE_NOTIFY: case XFR_TYPE_FORWARD: - ret = xfr_task_expire(set, rq); + ret = xfr_task_expire(set, i, rq); break; default: break; } + /* Close if not valid anymore. */ if (ret != KNOT_EOK) { - xfr_task_close(w, fd); - --w->pending; + if (xfr_task_is_transfer(rq)) + xfr_pending_decr(xfr); + xfr_task_close(rq); + socket_close(set->pfd[i].fd); + return FDSET_SWEEP; } + + return FDSET_KEEP; } /*! \brief Check TSIG if exists. */ @@ -969,7 +1018,7 @@ int xfr_worker(dthread_t *thread) xfrhandler_t *xfr = w->master; /* Buffer for answering. */ - size_t buflen = XFR_BUFFER_SIZE; + size_t buflen = SOCKET_MTU_SZ; uint8_t* buf = malloc(buflen); if (buf == NULL) { dbg_xfr("xfr: failed to allocate buffer for XFR worker\n"); @@ -981,84 +1030,113 @@ int xfr_worker(dthread_t *thread) time_now(&next_sweep); next_sweep.tv_sec += XFR_SWEEP_INTERVAL; - int limit = XFR_CHUNKLEN * 3; - if (conf() && conf()->xfers > 0) { - limit = conf()->xfers; + /* Approximate thread capacity limits. */ + unsigned threads = w->master->unit->size; + unsigned thread_capacity = XFR_MAX_TASKS / threads; + + /* Set of connections. */ + fdset_t set; + int ret = fdset_init(&set, thread_capacity); + if (ret != KNOT_EOK) { + free(buf); + return ret; } - unsigned thread_capacity = limit / w->master->unit->size; - if (thread_capacity < 1) thread_capacity = 1; - w->pool.fds = fdset_new(); - w->pool.t = ahtable_create(); - w->pending = 0; /* Accept requests. */ - int ret = 0; dbg_xfr_verb("xfr: worker=%p starting\n", w); for (;;) { /* Populate pool with new requests. */ - if (w->pending <= thread_capacity) { - pthread_mutex_lock(&xfr->mx); - unsigned was_pending = w->pending; - while (!EMPTY_LIST(xfr->queue)) { - knot_ns_xfr_t *rq = HEAD(xfr->queue); - rem_node(&rq->n); + unsigned newconns = 0; + for (;;) { + /* Do not exceed thread capacity. */ + if (set.n >= thread_capacity || newconns > XFR_CHUNKLEN) + break; - /* Unlock queue and process request. */ + /* Tak first request. */ + pthread_mutex_lock(&xfr->mx); + if (EMPTY_LIST(xfr->queue)) { pthread_mutex_unlock(&xfr->mx); - ret = xfr_task_process(w, rq, buf, buflen); - if (ret == KNOT_EOK) ++w->pending; - else xfr_task_free(rq); - pthread_mutex_lock(&xfr->mx); + break; + } - if (w->pending - was_pending > XFR_CHUNKLEN) - break; + + /* Limit number of transfers. */ + knot_ns_xfr_t *rq = HEAD(xfr->queue); + unsigned is_transfer = xfr_task_is_transfer(rq); + if (is_transfer && !xfr_pending_incr(xfr)) { + pthread_mutex_unlock(&xfr->mx); + break; } + + rem_node(&rq->n); pthread_mutex_unlock(&xfr->mx); + + /* Start asynchronous connect. */ + xfr_async_setbuf(rq, buf, buflen); + if (xfr_async_start(&set, rq) != KNOT_EOK) { + if (is_transfer) + xfr_pending_decr(xfr); + xfr_task_close(rq); + break; + } + + ++newconns; } /* Check pending threads. */ - if (dt_is_cancelled(thread) || w->pending == 0) { + if (dt_is_cancelled(thread) || set.n == 0) { break; } /* Poll fdset. */ - int nfds = fdset_wait(w->pool.fds, (XFR_SWEEP_INTERVAL/2) * 1000); + int nfds = poll(set.pfd, set.n, XFR_SWEEP_INTERVAL * 1000); if (nfds < 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; break; } /* Iterate fdset. */ - fdset_it_t it; - fdset_begin(w->pool.fds, &it); - while(nfds > 0) { - - /* Find data. */ - knot_ns_xfr_t *rq = xfr_task_get(w, it.fd); - dbg_xfr_verb("xfr: worker=%p processing event on " - "fd=%d data=%p.\n", - w, it.fd, rq); - if (rq) { + unsigned i = 0; + while (nfds > 0 && i < set.n && !dt_is_cancelled(thread)) { + + if (!(set.pfd[i].revents & set.pfd[i].events)) { + /* Skip inactive. */ + ++i; + continue; + } else { + /* One less active event. */ + --nfds; + } + + /* Process pending tasks. */ + knot_ns_xfr_t *rq = (knot_ns_xfr_t *)set.ctx[i]; + if (rq->flags & XFR_FLAG_CONNECTING) { + ret = xfr_async_finish(&set, i); + } else { ret = xfr_process_event(w, rq); - if (ret != KNOT_EOK) { - xfr_task_close(w, it.fd); - --w->pending; - --it.pos; /* Reset iterator */ - } } - /* Next fd. */ - if (fdset_next(w->pool.fds, &it) < 0) { - break; + /* Check task state. */ + if (ret != KNOT_EOK) { + if (xfr_task_is_transfer(rq)) + xfr_pending_decr(xfr); + xfr_task_close(rq); + socket_close(set.pfd[i].fd); + fdset_remove(&set, i); + continue; /* Stay on the same index. */ } + + /* Next active. */ + ++i; } /* Sweep inactive. */ timev_t now; if (time_now(&now) == 0) { if (now.tv_sec >= next_sweep.tv_sec) { - fdset_sweep(w->pool.fds, &xfr_sweep, w); + fdset_sweep(&set, &xfr_sweep, xfr); memcpy(&next_sweep, &now, sizeof(next_sweep)); next_sweep.tv_sec += XFR_SWEEP_INTERVAL; } @@ -1066,22 +1144,17 @@ int xfr_worker(dthread_t *thread) } /* Cancel existing connections. */ - size_t keylen = 0; - ahtable_iter_t i; - ahtable_iter_begin(w->pool.t, &i, false); - while (!ahtable_iter_finished(&i)) { - int *key = (int *)ahtable_iter_key(&i, &keylen); - xfr_task_close(w, *key); - ahtable_iter_next(&i); - } - ahtable_iter_free(&i); - - /* Destroy data structures. */ - fdset_destroy(w->pool.fds); - ahtable_free(w->pool.t); - free(buf); + for (unsigned i = 0; i < set.n; ++i) { + knot_ns_xfr_t *rq = (knot_ns_xfr_t *)set.ctx[i]; + socket_close(set.pfd[i].fd); + if (xfr_task_is_transfer(rq)) + xfr_pending_decr(xfr); + xfr_task_free(rq); + } dbg_xfr_verb("xfr: worker=%p finished.\n", w); + fdset_clear(&set); + free(buf); return KNOT_EOK; } @@ -1115,6 +1188,7 @@ xfrhandler_t *xfr_create(size_t thrcount, knot_nameserver_t *ns) /* Create tasks structure and mutex. */ pthread_mutex_init(&xfr->mx, 0); + pthread_mutex_init(&xfr->pending_mx, 0); init_list(&xfr->queue); /* Assign worker threads. */ @@ -1133,6 +1207,7 @@ int xfr_free(xfrhandler_t *xfr) } /* Free RR mutex. */ + pthread_mutex_destroy(&xfr->pending_mx); pthread_mutex_destroy(&xfr->mx); /* Free pending queue. */ diff --git a/src/knot/server/xfr-handler.h b/src/knot/server/xfr-handler.h index 2042605..f0b0487 100644 --- a/src/knot/server/xfr-handler.h +++ b/src/knot/server/xfr-handler.h @@ -48,11 +48,6 @@ enum xfrstate_t { */ typedef struct xfrworker_t { - struct { - ahtable_t *t; - fdset_t *fds; - } pool; - unsigned pending; struct xfrhandler_t *master; /*! \brief Worker master. */ } xfrworker_t; @@ -62,6 +57,8 @@ typedef struct xfrworker_t typedef struct xfrhandler_t { list queue; + unsigned pending; /*!< \brief Pending transfers. */ + pthread_mutex_t pending_mx; pthread_mutex_t mx; /*!< \brief Tasks synchronisation. */ knot_nameserver_t *ns; dt_unit_t *unit; /*!< \brief Threading unit. */ diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c index d1a3bf6..e1c295f 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -449,27 +449,33 @@ static int zones_zonefile_sync_ev(event_t *e) return KNOT_EINVAL; } - /* Execute zonefile sync. */ - journal_t *j = journal_retain(zd->ixfr_db); - int ret = zones_zonefile_sync(zone, j); - journal_release(j); + /* Only on zones with valid contents (non empty). */ + int ret = KNOT_EOK; + if (knot_zone_contents(zone)) { + /* Synchronize journal. */ + journal_t *j = journal_retain(zd->ixfr_db); + ret = zones_zonefile_sync(zone, j); + journal_release(j); - rcu_read_lock(); - if (ret == KNOT_EOK) { - log_zone_info("Applied differences of '%s' to zonefile.\n", - zd->conf->name); - } else if (ret != KNOT_ERANGE) { - log_zone_warning("Failed to apply differences of '%s' " - "to zonefile.\n", - zd->conf->name); + rcu_read_lock(); + if (ret == KNOT_EOK) { + log_zone_info("Applied differences of '%s' to zonefile.\n", + zd->conf->name); + } else if (ret != KNOT_ERANGE) { + log_zone_warning("Failed to apply differences of '%s' " + "to zonefile.\n", zd->conf->name); + } + rcu_read_unlock(); } /* Reschedule. */ - evsched_schedule(e->parent, e, zd->conf->dbsync_timeout * 1000); + rcu_read_lock(); + int next_timeout = zd->conf->dbsync_timeout * 1000; dbg_zones("zones: next IXFR database SYNC of '%s' in %d seconds\n", - zd->conf->name, zd->conf->dbsync_timeout); + zd->conf->name, next_timeout / 1000); rcu_read_unlock(); + evsched_schedule(e->parent, e, next_timeout); return ret; } @@ -2495,7 +2501,7 @@ int zones_process_response(knot_nameserver_t *nameserver, /* No updates available. */ if (ret == 0) { - zones_schedule_refresh(zone, 0); + zones_schedule_refresh(zone, REFRESH_DEFAULT); rcu_read_unlock(); return KNOT_EUPTODATE; } @@ -2698,8 +2704,7 @@ int zones_ns_conf_hook(const struct conf_t *conf, void *data) /* REFRESH zones. */ for (unsigned i = 0; i < knot_zonedb_zone_count(ns->zone_db); ++i) { - /* Refresh new slave zones (almost) immediately. */ - zones_schedule_refresh(zones[i], tls_rand() * 500 + i/2); + zones_schedule_refresh(zones[i], 0); /* Now. */ zones_schedule_notify(zones[i]); } @@ -3177,7 +3182,7 @@ int zones_schedule_notify(knot_zone_t *zone) return KNOT_EOK; } -int zones_schedule_refresh(knot_zone_t *zone, unsigned time) +int zones_schedule_refresh(knot_zone_t *zone, int64_t time) { if (!zone || !zone->data) { return KNOT_EINVAL; @@ -3206,18 +3211,17 @@ int zones_schedule_refresh(knot_zone_t *zone, unsigned time) if (zd->xfr_in.has_master) { /* Schedule REFRESH timer. */ - uint32_t refresh_tmr = time; - if (refresh_tmr == 0) { - if (knot_zone_contents(zone)) { - refresh_tmr = zones_jitter(zones_soa_refresh(zone)); - } else { - refresh_tmr = zd->xfr_in.bootstrap_retry; - } + if (time < 0) { + if (knot_zone_contents(zone)) + time = zones_jitter(zones_soa_refresh(zone)); + else + time = zd->xfr_in.bootstrap_retry; } + zd->xfr_in.timer = evsched_schedule_cb(sch, zones_refresh_ev, - zone, refresh_tmr); + zone, time); dbg_zones("zone: REFRESH '%s' set to %u\n", - zd->conf->name, refresh_tmr); + zd->conf->name, time); zd->xfr_in.state = XFR_SCHED; } rcu_read_unlock(); diff --git a/src/knot/server/zones.h b/src/knot/server/zones.h index 5045d50..2260e01 100644 --- a/src/knot/server/zones.h +++ b/src/knot/server/zones.h @@ -46,6 +46,10 @@ #define IXFR_DBSYNC_TIMEOUT (60*1000) /*!< Database sync timeout = 60s. */ #define AXFR_BOOTSTRAP_RETRY (30*1000) /*!< Interval between AXFR BS retries. */ +enum { + REFRESH_DEFAULT = -1 /* Use time value from zone structure. */ +}; + /*! * \brief Zone-related data. */ @@ -302,13 +306,13 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs, * REFRESH/RETRY/EXPIRE timers are updated according to SOA. * * \param zone Related zone. - * \param time Specific time or 0 for default. + * \param time Specific time or REFRESH_DEFAULT for default. * * \retval KNOT_EOK * \retval KNOT_EINVAL * \retval KNOT_ERROR */ -int zones_schedule_refresh(knot_zone_t *zone, unsigned time); +int zones_schedule_refresh(knot_zone_t *zone, int64_t time); /*! * \brief Schedule NOTIFY after zone update. diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index 1d3c5c4..efbe953 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -606,6 +606,7 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, err_handler_handle_error(handler, node, ZC_ERR_NSEC3_UNSECURED_DELEGATION, NULL); + return KNOT_EOK; } else { /* Unsecured delegation, check whether it is part of * opt-out span */ @@ -623,7 +624,7 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, if (nsec3_node == NULL) { /* Probably should not ever happen */ - return ZC_ERR_NSEC3_NOT_FOUND; + return KNOT_ERROR; } assert(nsec3_previous); @@ -643,6 +644,8 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, err_handler_handle_error(handler, node, ZC_ERR_NSEC3_UNSECURED_DELEGATION_OPT, NULL); + /* We cannot continue from here. */ + return KNOT_EOK; } } } diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c index ac414f1..ec8375a 100644 --- a/src/knot/zone/zone-load.c +++ b/src/knot/zone/zone-load.c @@ -55,7 +55,7 @@ static int rrset_list_add(rrset_list_t **head, knot_rrset_t *rrsig) tmp->data = rrsig; *head = tmp; } - + dbg_zp_verb("zp: rrset_add: Added RRSIG %p to list.\n", rrsig); return KNOT_EOK; @@ -80,7 +80,7 @@ static void rrset_list_delete(rrset_list_t **head) } *head = NULL; - + dbg_zp("zp: list_delete: List deleleted.\n"); } @@ -121,9 +121,9 @@ static int find_rrset_for_rrsig_in_node(knot_zone_contents_t *zone, return KNOT_ERROR; } } - + assert(tmp_rrset); - + if (tmp_rrset->ttl != rrsig->ttl) { char *name = knot_dname_to_str(tmp_rrset->owner); assert(name); @@ -165,7 +165,7 @@ static knot_node_t *create_node(knot_zone_contents_t *zone, knot_strerror(ret)); return NULL; } - + assert(current_rrset->owner == node->owner); return node; @@ -223,7 +223,7 @@ static size_t calculate_item_size(const knot_rrset_t *rrset, scanner->r_data_blocks[i]; } } - + return size; } @@ -233,16 +233,16 @@ static int add_rdata_to_rr(knot_rrset_t *rrset, const scanner_t *scanner) dbg_zp("zp: add_rdata_to_rr: No RRSet.\n"); return KNOT_EINVAL; } - + parser_context_t *parser = scanner->data; - + const rdata_descriptor_t *desc = get_rdata_descriptor(knot_rrset_type(rrset)); assert(desc); - + dbg_zp_detail("zp: add_rdata_to_rr: Adding type %d, RRSet has %d RRs.\n", rrset->type, rrset->rdata_count); - + size_t rdlen = calculate_item_size(rrset, scanner); size_t offset = 0; uint8_t *rdata = knot_rrset_create_rdata(rrset, rdlen); @@ -250,7 +250,7 @@ static int add_rdata_to_rr(knot_rrset_t *rrset, const scanner_t *scanner) dbg_zp("zp: create_rdata: Could not create RR.\n"); return KNOT_ENOMEM; } - + for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) { int item = desc->block_types[i]; if (descriptor_item_is_dname(item)) { @@ -293,7 +293,7 @@ dbg_zp_exec_detail( scanner->r_data_blocks[i]; } } - + return KNOT_EOK; } @@ -309,23 +309,23 @@ static void process_rr(const scanner_t *scanner) knot_zone_contents_t *contents = parser->current_zone; knot_dname_t *current_owner = NULL; knot_rrset_t *current_rrset = NULL; - if (parser->last_node && - (scanner->r_owner_length == parser->last_node->owner->size) && - (strncmp((char *)parser->last_node->owner->name, - (char *)scanner->r_owner, scanner->r_owner_length) == 0)) { - // no need to create new dname; - current_owner = parser->last_node->owner; + if (parser->last_node && + (scanner->r_owner_length == parser->last_node->owner->size) && + (strncmp((char *)parser->last_node->owner->name, + (char *)scanner->r_owner, scanner->r_owner_length) == 0)) { + // no need to create new dname; + current_owner = parser->last_node->owner; knot_dname_retain(current_owner); - } else { - current_owner = - knot_dname_new_from_wire(scanner->r_owner, - scanner->r_owner_length, - NULL); - if (current_owner == NULL) { + } else { + current_owner = + knot_dname_new_from_wire(scanner->r_owner, + scanner->r_owner_length, + NULL); + if (current_owner == NULL) { parser->ret = KNOT_ERROR; return; } - knot_dname_to_lower(current_owner); + knot_dname_to_lower(current_owner); /*!< \todo * If name is already in the table, we might not need to create * dname object, just compare wires. @@ -333,30 +333,30 @@ static void process_rr(const scanner_t *scanner) knot_zone_contents_insert_dname_into_table(¤t_owner, parser->lookup_tree); } - + /*!< \todo Do not create RRSet each time - merging needs to be sorted though. */ current_rrset = knot_rrset_new(current_owner, scanner->r_type, scanner->r_class, scanner->r_ttl); knot_dname_release(current_owner); - + assert(current_owner); assert(current_rrset); parser->current_rrset = current_rrset; - + int ret = add_rdata_to_rr(current_rrset, scanner); if (ret != KNOT_EOK) { log_zone_error("Cannot add RDATA to zone, load failed.\n"); parser->ret = ret; return; } - + dbg_zp_verb("zp: process_rr: Processing type: %d.\n", parser->current_rrset->type); assert(current_rrset->rdata_count); - + /* Node add/get functions. */ int (*node_add_func)(knot_zone_contents_t *, knot_node_t *, int, uint8_t); @@ -431,12 +431,12 @@ static void process_rr(const scanner_t *scanner) parser->last_node); rrset_list_delete(&parser->node_rrsigs); } - + /* The node might however been created previously. */ parser->last_node = knot_zone_contents_get_node(contents, knot_rrset_owner(current_rrset)); - + if (parser->last_node == NULL) { /* Try NSEC3 tree. */ if (current_rrset->type == KNOT_RRTYPE_NSEC3 || @@ -448,7 +448,7 @@ static void process_rr(const scanner_t *scanner) current_rrset)); } } - + if (parser->last_node == NULL) { /* Still NULL, node has to be created. */ if ((parser->last_node = create_node(contents, @@ -472,12 +472,12 @@ static void process_rr(const scanner_t *scanner) parser->ret = KNOT_ERROR; return; } - + dbg_zp_verb("zp: process_rr: RRSIG proccesed successfully.\n"); parser->ret = KNOT_EOK; return; } - + /*! \todo Move RRSIG and RRSet handling to funtions. */ assert(current_rrset->type != KNOT_RRTYPE_RRSIG); @@ -520,13 +520,13 @@ static void process_rr(const scanner_t *scanner) return; } } - + if (current_rrset->type != KNOT_RRTYPE_RRSIG) { /* * If there's already an RRSet of this type in a node, check - * that TTLs are the same, if not, give warning a change TTL. + * that TTLs are the same, if not, give warning a change TTL. */ - const knot_rrset_t *rrset_in_node = + const knot_rrset_t *rrset_in_node = knot_node_rrset(node, current_rrset->type); if (rrset_in_node && current_rrset->ttl != rrset_in_node->ttl) { @@ -536,7 +536,7 @@ static void process_rr(const scanner_t *scanner) /* Actual change will happen in merge. */ } } - + ret = knot_zone_contents_add_rrset(contents, current_rrset, &node, KNOT_RRSET_DUPL_MERGE); @@ -568,40 +568,40 @@ static void process_rr(const scanner_t *scanner) parser->ret = KNOT_EMALF; return; } - + parser->last_node = node; - + dbg_zp_verb("zp: process_rr: RRSet %p processed successfully.\n", parser->current_rrset); parser->ret = KNOT_EOK; } -int knot_zload_open(zloader_t **dst, const char *source, const char *origin, +int knot_zload_open(zloader_t **dst, const char *source, const char *origin, int semantic_checks) { if (!dst || !source || !origin) { dbg_zload("zload: open: Bad arguments.\n"); return KNOT_EINVAL; } - + *dst = NULL; - + /* Check zone file. */ struct stat st; if (stat(source, &st) < 0) { return knot_map_errno(errno); } - + /* Create context. */ parser_context_t *context = xmalloc(sizeof(parser_context_t)); - + /* Create trie for DNAME duplicits. */ context->lookup_tree = hattrie_create(); if (context->lookup_tree == NULL) { free(context); return KNOT_ENOMEM; } - + context->origin_from_config = knot_dname_new_from_str(origin, strlen(origin), NULL); assert(context->origin_from_config); @@ -616,7 +616,7 @@ int knot_zload_open(zloader_t **dst, const char *source, const char *origin, context->current_zone = knot_zone_get_contents(zone); context->node_rrsigs = NULL; context->ret = KNOT_EOK; - + /* Create file loader. */ file_loader_t *loader = file_loader_create(source, origin, KNOT_CLASS_IN, 3600, @@ -628,17 +628,17 @@ int knot_zload_open(zloader_t **dst, const char *source, const char *origin, free(context); return KNOT_ERROR; } - + /* Allocate new loader. */ zloader_t *zl = xmalloc(sizeof(zloader_t)); - + zl->source = strdup(source); zl->origin = strdup(origin); zl->file_loader = loader; zl->context = context; zl->semantic_checks = semantic_checks; *dst = zl; - + /* Log all information for now - possibly more config options. */ zl->err_handler = handler_new(1, 1, 1, 1, 1); if (zl->err_handler == NULL) { @@ -647,9 +647,9 @@ int knot_zload_open(zloader_t **dst, const char *source, const char *origin, "Semantic check skipped for zone %s\n", origin); } - + context->err_handler = zl->err_handler; - + return KNOT_EOK; } @@ -660,7 +660,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader) dbg_zload("zload: load: NULL loader!\n"); return NULL; } - + parser_context_t *c = loader->context; assert(c); file_loader_process(loader->file_loader); @@ -676,7 +676,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader) knot_zone_deep_free(&zone_to_free); return NULL; } - + if (loader->file_loader->scanner->error_counter > 0) { log_zone_error("Zone could not be loaded due to %"PRIu64" errors" " encountered.\n", @@ -686,7 +686,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader) knot_zone_deep_free(&zone_to_free); return NULL; } - + if (knot_zone_contents_apex(c->current_zone) == NULL || knot_node_rrset(knot_zone_contents_apex(c->current_zone), KNOT_RRTYPE_SOA) == NULL) { log_zone_error("No SOA record in the zone file.\n"); @@ -695,13 +695,13 @@ knot_zone_t *knot_zload_load(zloader_t *loader) knot_zone_deep_free(&zone_to_free); return NULL; } - + knot_node_t *first_nsec3_node = NULL; knot_node_t *last_nsec3_node = NULL; rrset_list_delete(&c->node_rrsigs); knot_zone_contents_adjust(c->current_zone, &first_nsec3_node, &last_nsec3_node, 0); - + if (loader->semantic_checks) { int check_level = 1; const knot_rrset_t *soa_rr = @@ -724,7 +724,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader) log_zone_info("Semantic checks completed for zone=%s\n", zname); free(zname); } - + return c->current_zone->zone; } @@ -733,9 +733,9 @@ void knot_zload_close(zloader_t *loader) if (!loader) { return; } - + hattrie_free(loader->context->lookup_tree); - + file_loader_free(loader->file_loader); free(loader->source); diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c index 4a95240..ee956e7 100644 --- a/src/libknot/nameserver/name-server.c +++ b/src/libknot/nameserver/name-server.c @@ -1753,7 +1753,7 @@ static inline int ns_referral(const knot_node_t *node, && knot_query_dnssec_requested( knot_packet_query(resp))) { ret = ns_add_rrsigs(ds_rrset, resp, node->owner, - knot_response_add_rrset_authority, + knot_response_add_rrset_answer, 1); } } else { @@ -1919,7 +1919,6 @@ static int ns_answer_from_node(const knot_node_t *node, } } } else { // else put authority NS - assert(previous == NULL); assert(closest_encloser == knot_node_parent(node) || !knot_dname_is_wildcard(knot_node_owner(node)) || knot_dname_compare(qname, knot_node_owner(node)) == 0); @@ -2141,14 +2140,19 @@ static int ns_answer_from_zone(const knot_zone_contents_t *zone, uint16_t qtype = knot_packet_qtype(resp); search: - find_ret = knot_zone_contents_find_dname(zone, qname, &node, - &closest_encloser, &previous); -// node = knot_node_current(node); -// closest_encloser = knot_node_current(closest_encloser); -// previous = knot_node_current(previous); - previous = NULL; // TODO REVIEW LS + // Searching for a name directly is faster than when we need previous dname + node = knot_zone_contents_find_node(zone, qname); + if (node != NULL) { + // If node is found, closest_encloser is equal to node itself + closest_encloser = node; + find_ret = KNOT_ZONE_NAME_FOUND; + } else { + // We need previous and closest encloser, full search has to be done + find_ret = knot_zone_contents_find_dname(zone, qname, &node, + &closest_encloser, &previous); if (find_ret == KNOT_EINVAL) { - return NS_ERR_SERVFAIL; + return NS_ERR_SERVFAIL; + } } dbg_ns_exec_verb( diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h index 58ea212..6574539 100644 --- a/src/libknot/nameserver/name-server.h +++ b/src/libknot/nameserver/name-server.h @@ -159,7 +159,8 @@ static const size_t KNOT_NS_TSIG_DATA_MAX_SIZE = 100 * 64 * 1024; enum knot_ns_xfr_flag_t { XFR_FLAG_TCP = 1 << 0, /*!< XFR request is on TCP. */ XFR_FLAG_UDP = 1 << 1, /*!< XFR request is on UDP. */ - XFR_FLAG_AXFR_FINISHED = 1 << 2 /*!< Transfer is finished. */ + XFR_FLAG_AXFR_FINISHED = 1 << 2, /*!< Transfer is finished. */ + XFR_FLAG_CONNECTING = 1 << 3 /*!< In connecting phase. */ }; typedef enum knot_ns_transport { @@ -173,8 +174,8 @@ typedef enum knot_ns_transport { typedef enum knot_ns_xfr_type_t { /* DNS events. */ XFR_TYPE_AIN = 0, /*!< AXFR-IN request (start transfer). */ - XFR_TYPE_AOUT, /*!< AXFR-OUT request (incoming transfer). */ XFR_TYPE_IIN, /*!< IXFR-IN request (start transfer). */ + XFR_TYPE_AOUT, /*!< AXFR-OUT request (incoming transfer). */ XFR_TYPE_IOUT, /*!< IXFR-OUT request (incoming transfer). */ XFR_TYPE_SOA, /*!< Pending SOA request. */ XFR_TYPE_NOTIFY, /*!< Pending NOTIFY query. */ diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c index e22a629..c8c7fe7 100644 --- a/src/libknot/rrset-dump.c +++ b/src/libknot/rrset-dump.c @@ -549,9 +549,9 @@ static void wire_text_to_str(rrset_dump_params_t *p) // Loop over all characters. for (size_t i = 0; i < in_len; i++) { - char ch = (char)(p->in)[i]; + uint8_t ch = p->in[i]; - if (isprint((unsigned char)(ch)) != 0) { + if (isprint(ch) != 0) { // For special character print leading slash. if (ch == '\\' || ch == '"') { dump_string(p, "\\"); diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c index ff1a1d4..fbf4ab3 100644 --- a/src/libknot/zone/zone-contents.c +++ b/src/libknot/zone/zone-contents.c @@ -2515,6 +2515,12 @@ int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents) data.children = 0; data.contents = contents; + if (contents == NULL) { + log_zone_warning("Zone to be integrity-checked does " + "not exist. Skipping...\n"); + return 1; + } + int ret = knot_zone_contents_tree_apply_inorder( (knot_zone_contents_t *)contents, knot_zc_integrity_check_node, (void *)&data); diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 29733b7..bb381dc 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/Makefile.in b/src/tests/Makefile.in index df605b8..fefb224 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -50,10 +50,10 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -check_PROGRAMS = unittests$(EXEEXT) unittests_xfr$(EXEEXT) +check_PROGRAMS = unittests$(EXEEXT) TESTS = unittests$(EXEEXT) subdir = src/tests -DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ $(top_srcdir)/m4/ax_ext.m4 \ @@ -88,10 +88,6 @@ unittests_DEPENDENCIES = ../libknotd.la ../libknots.la @LIBOBJS@ AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent -am_unittests_xfr_OBJECTS = xfr_tests.$(OBJEXT) -unittests_xfr_OBJECTS = $(am_unittests_xfr_OBJECTS) -unittests_xfr_DEPENDENCIES = ../libknotd.la ../libknot.la \ - ../libknots.la @LIBOBJS@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -118,9 +114,8 @@ am__v_CCLD_0 = @echo " CCLD " $@; AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(unittests_SOURCES) $(nodist_unittests_SOURCES) \ - $(unittests_xfr_SOURCES) -DIST_SOURCES = $(unittests_SOURCES) $(unittests_xfr_SOURCES) +SOURCES = $(unittests_SOURCES) $(nodist_unittests_SOURCES) +DIST_SOURCES = $(unittests_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -198,6 +193,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RAGEL = @RAGEL@ RANLIB = @RANLIB@ +RELEASE_DATE = @RELEASE_DATE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -225,6 +221,7 @@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +config_dir = @config_dir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -321,12 +318,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@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am @@ -438,9 +430,6 @@ libknot/sign_tests.$(OBJEXT): libknot/$(am__dirstamp) \ unittests$(EXEEXT): $(unittests_OBJECTS) $(unittests_DEPENDENCIES) $(EXTRA_unittests_DEPENDENCIES) @rm -f unittests$(EXEEXT) $(AM_V_CCLD)$(LINK) $(unittests_OBJECTS) $(unittests_LDADD) $(LIBS) -unittests_xfr$(EXEEXT): $(unittests_xfr_OBJECTS) $(unittests_xfr_DEPENDENCIES) $(EXTRA_unittests_xfr_DEPENDENCIES) - @rm -f unittests_xfr$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(unittests_xfr_OBJECTS) $(unittests_xfr_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -469,7 +458,6 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unittests_main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfr_tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/acl_tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/base32hex_tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/base64_tests.Po@am__quote@ diff --git a/src/tests/README b/src/tests/README deleted file mode 100644 index 1d9748b..0000000 --- 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/common/fdset_tests.c b/src/tests/common/fdset_tests.c index d7b29fa..e8b9d73 100644 --- a/src/tests/common/fdset_tests.c +++ b/src/tests/common/fdset_tests.c @@ -98,22 +98,21 @@ static int fdset_tests_count(int argc, char *argv[]) static int fdset_tests_run(int argc, char *argv[]) { - diag("fdset: implements '%s'", fdset_method()); - /* 1. Create fdset. */ - fdset_t *set = fdset_new(); - ok(set != 0, "fdset: new"); + fdset_t set; + int ret = fdset_init(&set, 32); + ok(ret == 0, "fdset: init"); /* 2. Create pipe. */ int fds[2], tmpfds[2]; - int ret = pipe(fds); + ret = pipe(fds); ok(ret >= 0, "fdset: pipe() works"); ret = pipe(tmpfds); /* 3. Add fd to set. */ - ret = fdset_add(set, fds[0], OS_EV_READ); + ret = fdset_add(&set, fds[0], POLLIN, NULL); ok(ret == 0, "fdset: add to set works"); - fdset_add(set, tmpfds[0], OS_EV_READ); + fdset_add(&set, tmpfds[0], POLLIN, NULL); /* Schedule write. */ struct timeval ts, te; @@ -122,54 +121,44 @@ static int fdset_tests_run(int argc, char *argv[]) pthread_create(&t, 0, thr_action, &fds[1]); /* 4. Watch fdset. */ - ret = fdset_wait(set, OS_EV_FOREVER); + int nfds = poll(set.pfd, set.n, 2000); gettimeofday(&te, 0); size_t diff = timeval_diff(&ts, &te); - ok(ret > 0 && diff > 99 && diff < 10000, - "fdset: poll returned events in %zu ms", diff); + ok(nfds > 0 && diff > 99 && diff < 10000, + "fdset: poll returned %d events in %zu ms", nfds, diff); /* 5. Prepare event set. */ - fdset_it_t it; - ret = fdset_begin(set, &it); - ok(ret == 0 && it.fd == fds[0], "fdset: begin is valid, ret=%d", ret); + ok(set.pfd[0].revents & POLLIN, "fdset: pipe is active"); /* 6. Receive data. */ char buf = 0x00; - ret = read(it.fd, &buf, WRITE_PATTERN_LEN); - ok(ret >= 0 && buf == WRITE_PATTERN, "fdset: contains valid data, fd=%d", it.fd); - - /* 7. Iterate event set. */ - ret = fdset_next(set, &it); - ok(ret < 0, "fdset: boundary check works"); + ret = read(set.pfd[0].fd, &buf, WRITE_PATTERN_LEN); + ok(ret >= 0 && buf == WRITE_PATTERN, "fdset: contains valid data"); - /* 8. Remove from event set. */ - ret = fdset_remove(set, fds[0]); + /* 7-9. Remove from event set. */ + ret = fdset_remove(&set, 0); ok(ret == 0, "fdset: remove from fdset works"); close(fds[0]); close(fds[1]); - ret = fdset_remove(set, tmpfds[0]); + ret = fdset_remove(&set, 0); close(tmpfds[1]); close(tmpfds[1]); - - /* 9. Poll empty fdset. */ - ret = fdset_wait(set, OS_EV_FOREVER); - ok(ret <= 0, "fdset: polling empty fdset returns -1 (ret=%d)", ret); + ok(ret == 0, "fdset: remove from fdset works (2)"); + ret = fdset_remove(&set, 0); + ok(ret != 0, "fdset: removing nonexistent item"); /* 10. Crash test. */ lives_ok({ - fdset_destroy(0); - fdset_add(0, -1, 0); - fdset_remove(0, -1); - fdset_wait(0, OS_EV_NOWAIT); - fdset_begin(0, 0); - fdset_end(0, 0); - fdset_next(0, 0); - fdset_method(); + fdset_init(0, 0); + fdset_add(0, 1, 1, 0); + fdset_add(0, 0, 1, 0); + fdset_remove(0, 1); + fdset_remove(0, 0); }, "fdset: crash test successful"); /* 11. Destroy fdset. */ - ret = fdset_destroy(set); + ret = fdset_clear(&set); ok(ret == 0, "fdset: destroyed"); /* Cleanup. */ diff --git a/src/tests/xfr_tests.c b/src/tests/xfr_tests.c deleted file mode 100644 index fee09f2..0000000 --- a/src/tests/xfr_tests.c +++ /dev/null @@ -1,384 +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 - - // Setup event queue - evqueue_set(evqueue_new()); - - // 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. */ - for(;;) { - pthread_sigmask(SIG_UNBLOCK, &sa.sa_mask, NULL); - int ret = evqueue_poll(evqueue(), 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(evqueue(), &ev) == 0) { - dbg_server_verb("Event: " - "received new event.\n"); - if (ev.cb) { - ev.cb(&ev); - } - } - } - } - pthread_sigmask(SIG_UNBLOCK, &sa.sa_mask, NULL); - - 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); - - // Destroy event loop - evqueue_t *q = evqueue(); - evqueue_free(&q); - - // 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 29de11d..0000000 --- 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 diff --git a/src/utils/common/params.c b/src/utils/common/params.c index 56dc662..86b930d 100644 --- a/src/utils/common/params.c +++ b/src/utils/common/params.c @@ -168,7 +168,7 @@ int params_parse_type(const char *value, uint16_t *rtype, uint32_t *xfr_serial) char *end; // Convert string to serial. - unsigned long serial = strtoul(param_str, &end, 10); + unsigned long long serial = strtoull(param_str, &end, 10); // Check for bad serial string. if (end == param_str || *end != '\0' || @@ -217,7 +217,7 @@ int params_parse_wait(const char *value, int32_t *dst) } /* Convert string to number. */ - long num = strtol(value, &end, 10); + long long num = strtoll(value, &end, 10); /* Check for bad string (empty or incorrect). */ if (end == value || *end != '\0') { @@ -225,11 +225,11 @@ int params_parse_wait(const char *value, int32_t *dst) return KNOT_EINVAL; } else if (num < 1) { num = 1; - WARN("time %s is too short, using %ld instead\n", value, num); + WARN("time %s is too short, using %lld instead\n", value, num); /* Reduce maximal value. Poll takes signed int in milliseconds. */ } else if (num > INT32_MAX) { num = INT32_MAX / 1000; - WARN("time %s is too big, using %ld instead\n", value, num); + WARN("time %s is too big, using %lld instead\n", value, num); } *dst = num; @@ -247,7 +247,7 @@ int params_parse_num(const char *value, uint32_t *dst) } // Convert string to number. - unsigned long num = strtoul(value, &end, 10); + unsigned long long num = strtoull(value, &end, 10); // Check for bad string. if (end == value || *end != '\0') { @@ -257,7 +257,7 @@ int params_parse_num(const char *value, uint32_t *dst) if (num > UINT32_MAX) { num = UINT32_MAX; - WARN("number %s is too big, using %lu instead\n", value, num); + WARN("number %s is too big, using %llu instead\n", value, num); } *dst = num; @@ -275,7 +275,7 @@ int params_parse_bufsize(const char *value, int32_t *dst) } // Convert string to number. - unsigned long num = strtoul(value, &end, 10); + unsigned long long num = strtoull(value, &end, 10); // Check for bad string. if (end == value || *end != '\0') { @@ -285,7 +285,7 @@ int params_parse_bufsize(const char *value, int32_t *dst) if (num > UINT16_MAX) { num = UINT16_MAX; - WARN("size %s is too big, using %lu instead\n", value, num); + WARN("size %s is too big, using %llu instead\n", value, num); } *dst = num; diff --git a/src/utils/dig/dig_params.c b/src/utils/dig/dig_params.c index 54361c8..d3b3d71 100644 --- a/src/utils/dig/dig_params.c +++ b/src/utils/dig/dig_params.c @@ -512,7 +512,7 @@ static void dig_help(void) " +[no]cl Show DNS class.\n" " +[no]ttl Show TTL value.\n" " +time=T Set wait for reply interval in seconds.\n" - " +retries=N Set number of retries.\n" + " +retry=N Set number of retries.\n" " +bufsize=B Set EDNS buffer size.\n" " +[no]tcp Use TCP protocol.\n" " +[no]fail Stop if SERVFAIL.\n" @@ -855,8 +855,8 @@ static int parse_opt2(const char *value, dig_params_t *params) return KNOT_EINVAL; } } - else if (strncmp(value, "retries=", 8) == 0) { - if (params_parse_num(value + 8, &query->retries) + else if (strncmp(value, "retry=", 6) == 0) { + if (params_parse_num(value + 6, &query->retries) != KNOT_EOK) { return KNOT_EINVAL; } diff --git a/src/utils/host/host_params.c b/src/utils/host/host_params.c index 0b32893..66fe67a 100644 --- a/src/utils/host/host_params.c +++ b/src/utils/host/host_params.c @@ -179,7 +179,7 @@ static void host_help(void) " -d Allow debug messages.\n" " -h, --help Print help.\n" " -r Disable recursion.\n" - " -s Stop if servfail.\n" + " -s Stop if SERVFAIL.\n" " -T Use TCP procotol.\n" " -v Verbose output.\n" " -V, --version Print program version.\n" diff --git a/src/zscanner/test/cases/06-0_INCLUDE.in b/src/zscanner/test/cases/06-0_INCLUDE.in index 65ed38c..d8f4d27 100644 --- a/src/zscanner/test/cases/06-0_INCLUDE.in +++ b/src/zscanner/test/cases/06-0_INCLUDE.in @@ -19,10 +19,10 @@ $INCLUDE \./includes/include2 _a_.-b-c-./d/. ; Slashed character in file name, $INCLUDE ./includes/include2 \0320\ \\\"\.\@\*.tld. ; Origin with special chars 5. NS @ -$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/includes/include2 ; Absolute path without origin +$INCLUDE /home/ondrej/Projects/knot/src/zscanner/test/cases/includes/include2 ; Absolute path without origin 6. NS @ -$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/includes/include2 tld. ; Absolute path with origin +$INCLUDE /home/ondrej/Projects/knot/src/zscanner/test/cases/includes/include2 tld. ; Absolute path with origin 7. NS @ ; KO diff --git a/src/zscanner/test/cases/06-3_INCLUDE.in b/src/zscanner/test/cases/06-3_INCLUDE.in index 963e44d..3dc9ba8 100644 --- a/src/zscanner/test/cases/06-3_INCLUDE.in +++ b/src/zscanner/test/cases/06-3_INCLUDE.in @@ -2,4 +2,4 @@ $ORIGIN . $TTL 1 ; KO -$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/ ; Given file is a directory +$INCLUDE /home/ondrej/Projects/knot/src/zscanner/test/cases/ ; Given file is a directory diff --git a/src/zscanner/test/cases/06-4_INCLUDE.in b/src/zscanner/test/cases/06-4_INCLUDE.in index 438933a..f4e3c51 100644 --- a/src/zscanner/test/cases/06-4_INCLUDE.in +++ b/src/zscanner/test/cases/06-4_INCLUDE.in @@ -2,4 +2,4 @@ $ORIGIN . $TTL 1 ; KO -$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/zscanner_tests/file-doesnt-exist ; File doesn't exist +$INCLUDE /home/ondrej/Projects/knot/src/zscanner/test/cases/zscanner_tests/file-doesnt-exist ; File doesn't exist diff --git a/src/zscanner/test/run_tests.sh b/src/zscanner/test/run_tests.sh index 2bbdad8..ccac549 100644 --- a/src/zscanner/test/run_tests.sh +++ b/src/zscanner/test/run_tests.sh @@ -1,7 +1,7 @@ #!/bin/sh -TESTS_DIR="/home/ondrej/Projects/knot/build/../src/zscanner/test/cases" -OUTS_DIR="/home/ondrej/Projects/knot/build/src/zscanner/test/.out" +TESTS_DIR="/home/ondrej/Projects/knot/src/zscanner/test/cases" +OUTS_DIR="/home/ondrej/Projects/knot/src/zscanner/test/.out" TEST_BIN="./../zscanner-tool -m 2" # Delete temporary output directory at exit. |