summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--KNOWN_ISSUES1
-rw-r--r--Knot.files1
-rw-r--r--RELNOTES27
-rwxr-xr-xconfigure142
-rw-r--r--configure.ac9
-rw-r--r--samples/knot.full.conf10
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile.in13
-rw-r--r--src/common/crc.c155
-rw-r--r--src/common/crc.h91
-rw-r--r--src/common/log.c18
-rw-r--r--src/config.h.in3
-rw-r--r--src/knot/conf/cf-lex.l1
-rw-r--r--src/knot/conf/cf-parse.y4
-rw-r--r--src/knot/conf/conf.c5
-rw-r--r--src/knot/conf/conf.h2
-rw-r--r--src/knot/ctl/knotc_main.c124
-rw-r--r--src/knot/main.c47
-rw-r--r--src/knot/server/dthreads.c54
-rw-r--r--src/knot/server/dthreads.h33
-rw-r--r--src/knot/server/journal.c18
-rw-r--r--src/knot/server/journal.h2
-rw-r--r--src/knot/server/notify.c13
-rw-r--r--src/knot/server/server.c47
-rw-r--r--src/knot/server/server.h10
-rw-r--r--src/knot/server/tcp-handler.c43
-rw-r--r--src/knot/server/udp-handler.c78
-rw-r--r--src/knot/server/xfr-handler.c15
-rw-r--r--src/knot/server/zones.c571
-rw-r--r--src/knot/zone/zone-dump-text.c4
-rw-r--r--src/knot/zone/zone-dump-text.h4
-rw-r--r--src/knot/zone/zone-dump.c5
-rw-r--r--src/knot/zone/zone-dump.h2
-rw-r--r--src/knot/zone/zone-load.c34
-rw-r--r--src/libknot/dname.c13
-rw-r--r--src/libknot/nameserver/name-server.c82
-rw-r--r--src/libknot/nameserver/name-server.h11
-rw-r--r--src/libknot/updates/xfr-in.c203
-rw-r--r--src/libknot/util/descriptor.c7
-rw-r--r--src/libknot/util/descriptor.h1
-rw-r--r--src/libknot/zone/node.c218
-rw-r--r--src/libknot/zone/zone-contents.c67
-rw-r--r--src/libknot/zone/zone-contents.h25
-rw-r--r--src/zcompile/parser-descriptor.c7
-rw-r--r--src/zcompile/parser-descriptor.h1
-rw-r--r--src/zcompile/parser-util.c6
-rw-r--r--src/zcompile/zcompile.c30
-rw-r--r--src/zcompile/zcompile_main.c10
-rw-r--r--src/zcompile/zlexer.l5
-rw-r--r--src/zcompile/zparser.y29
50 files changed, 1366 insertions, 936 deletions
diff --git a/KNOWN_ISSUES b/KNOWN_ISSUES
index 1d87958..30ced5e 100644
--- a/KNOWN_ISSUES
+++ b/KNOWN_ISSUES
@@ -10,5 +10,4 @@ current version of Knot.
Known bugs
==========
-* IXFR may be slow when too much (10 000+) RRSets are transfered at once.
* Slow start with too many zones.
diff --git a/Knot.files b/Knot.files
index d283f32..71a588f 100644
--- a/Knot.files
+++ b/Knot.files
@@ -98,7 +98,6 @@ src/common/acl.c
src/common/acl.h
src/common/sockaddr.h
src/common/sockaddr.c
-src/common/crc.c
src/common/crc.h
src/common/ref.c
src/common/ref.h
diff --git a/RELNOTES b/RELNOTES
index e0297d6..76c74e2 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -1,4 +1,29 @@
-v1.0.3 - Apr 17, 2011
+v1.0.4 - May 16, 2012
+---------------------
+
+New features:
+ * Parallel loading of zones to the server.
+ * RFC3339-complaint format of log time.
+ * Support for TLSA (RR type 52).
+ * knotc checkzone (as a dry-run of zone compile).
+ * knotc refresh for forcing Knot to update all zones from master
+ servers.
+ * Reopening log files upon start (used to truncate them).
+
+Bugfixes:
+ * Copying OPCODE and RD bit from query to NOTIMPL responses.
+ * Corrected response to CNAME queries if the canonical name was also
+ an alias (was adding the whole CNAME chain to the response).
+ * Fixed crash when NS or MX points to an alias.
+ * Fixed problem with early closing of filedescriptors (lead to crash
+ when compiling and loading or bootstrapping and restarting the server
+ with a lot of zones).
+
+Other improvements:
+ * Significantly sped up IXFR-in and reduced its memory requirements.
+
+
+v1.0.3 - Apr 17, 2012
---------------------
Bugfixes:
diff --git a/configure b/configure
index 692c858..a6b20e9 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for knot 1.0.3.
+# Generated by GNU Autoconf 2.68 for knot 1.0.4.
#
# Report bugs to <knot-dns@labs.nic.cz>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='knot'
PACKAGE_TARNAME='knot'
-PACKAGE_VERSION='1.0.3'
-PACKAGE_STRING='knot 1.0.3'
+PACKAGE_VERSION='1.0.4'
+PACKAGE_STRING='knot 1.0.4'
PACKAGE_BUGREPORT='knot-dns@labs.nic.cz'
PACKAGE_URL=''
@@ -1303,7 +1303,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures knot 1.0.3 to adapt to many kinds of systems.
+\`configure' configures knot 1.0.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1373,7 +1373,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of knot 1.0.3:";;
+ short | recursive ) echo "Configuration of knot 1.0.4:";;
esac
cat <<\_ACEOF
@@ -1491,7 +1491,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-knot configure 1.0.3
+knot configure 1.0.4
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2041,7 +2041,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by knot $as_me 1.0.3, which was
+It was created by knot $as_me 1.0.4, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -2859,7 +2859,7 @@ fi
# Define the identity of the package.
PACKAGE='knot'
- VERSION='1.0.3'
+ VERSION='1.0.4'
cat >>confdefs.h <<_ACEOF
@@ -13237,6 +13237,70 @@ $as_echo "#define ENABLE_RECVMMSG 1" >>confdefs.h
fi
+# Check for link time optimizations support and predictive commoning
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts \"-flto\"" >&5
+$as_echo_n "checking whether C compiler accepts \"-flto\"... " >&6; }
+ax_save_FLAGS=$CFLAGS
+ CFLAGS=""-flto""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval `$as_echo "ax_cv_c_flags_"-flto"" | $as_tr_sh`=yes
+else
+ eval `$as_echo "ax_cv_c_flags_"-flto"" | $as_tr_sh`=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_save_FLAGS
+eval ax_check_compiler_flags=$`$as_echo "ax_cv_c_flags_"-flto"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
+$as_echo "$ax_check_compiler_flags" >&6; }
+if test "x$ax_check_compiler_flags" = xyes; then
+ CFLAGS="$CFLAGS -flto"
+else
+ :
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts \"-fpredictive-commoning\"" >&5
+$as_echo_n "checking whether C compiler accepts \"-fpredictive-commoning\"... " >&6; }
+ax_save_FLAGS=$CFLAGS
+ CFLAGS=""-fpredictive-commoning""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval `$as_echo "ax_cv_c_flags_"-fpredictive-commoning"" | $as_tr_sh`=yes
+else
+ eval `$as_echo "ax_cv_c_flags_"-fpredictive-commoning"" | $as_tr_sh`=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_save_FLAGS
+eval ax_check_compiler_flags=$`$as_echo "ax_cv_c_flags_"-fpredictive-commoning"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
+$as_echo "$ax_check_compiler_flags" >&6; }
+if test "x$ax_check_compiler_flags" = xyes; then
+ CFLAGS="$CFLAGS -fpredictive-commoning"
+else
+ :
+fi
+
+
# Checks for libraries.
# FIXME: Replace `main' with a function in `-lm':
# TODO: check if paths exist before appending
@@ -13696,6 +13760,62 @@ if test "$ac_res" != no; then :
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crc32" >&5
+$as_echo_n "checking for library containing crc32... " >&6; }
+if ${ac_cv_search_crc32+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char crc32 ();
+int
+main ()
+{
+return crc32 ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' z; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_crc32=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_crc32+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_crc32+:} false; then :
+
+else
+ ac_cv_search_crc32=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crc32" >&5
+$as_echo "$ac_cv_search_crc32" >&6; }
+ac_res=$ac_cv_search_crc32
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
#AC_SEARCH_LIBS([ldns_rr_list_pop_rrset], [ldns], [], [AC_MSG_ERROR([libldns not found])])
# Checks for header files.
@@ -14393,7 +14513,7 @@ $as_echo "#define HAVE_MMAP 1" >>confdefs.h
fi
rm -f conftest.mmap conftest.txt
-for ac_func in gethostbyname gettimeofday clock_gettime memalign memmove memset munmap regcomp pselect select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue setgroups sendmmsg madvise
+for ac_func in gethostbyname gettimeofday clock_gettime memalign memmove memset munmap regcomp pselect select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue setgroups sendmmsg madvise pthread_setaffinity_np
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -14950,7 +15070,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by knot $as_me 1.0.3, which was
+This file was extended by knot $as_me 1.0.4, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15016,7 +15136,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-knot config.status 1.0.3
+knot config.status 1.0.4
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index c2b498f..1f413cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
AC_PREREQ([2.65])
-AC_INIT([knot], [1.0.3], [knot-dns@labs.nic.cz])
+AC_INIT([knot], [1.0.4], [knot-dns@labs.nic.cz])
AM_INIT_AUTOMAKE([gnu -Wall -Werror])
AC_CONFIG_SRCDIR([src/knot/main.c])
AC_CONFIG_HEADERS([src/config.h])
@@ -122,6 +122,10 @@ AC_ARG_ENABLE([recvmmsg],
recvmmsg=true
])
+# Check for link time optimizations support and predictive commoning
+AX_CHECK_COMPILER_FLAGS("-flto", [CFLAGS="$CFLAGS -flto"], [])
+AX_CHECK_COMPILER_FLAGS("-fpredictive-commoning", [CFLAGS="$CFLAGS -fpredictive-commoning"], [])
+
# Checks for libraries.
# FIXME: Replace `main' with a function in `-lm':
# TODO: check if paths exist before appending
@@ -135,6 +139,7 @@ AC_SEARCH_LIBS([dlopen], [dl])
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_SEARCH_LIBS([OpenSSL_add_all_digests], [crypto],[], [AC_MSG_ERROR([libcrypto not found])])
AC_SEARCH_LIBS([capng_apply], [cap-ng])
+AC_SEARCH_LIBS([crc32], [z])
#AC_SEARCH_LIBS([ldns_rr_list_pop_rrset], [ldns], [], [AC_MSG_ERROR([libldns not found])])
# Checks for header files.
@@ -159,7 +164,7 @@ AC_DEFINE([DSFMT_MEXP], [521], [DSFMT parameters.])
# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_MMAP
-AC_CHECK_FUNCS([gethostbyname gettimeofday clock_gettime memalign memmove memset munmap regcomp pselect select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue setgroups sendmmsg madvise])
+AC_CHECK_FUNCS([gethostbyname gettimeofday clock_gettime memalign memmove memset munmap regcomp pselect select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue setgroups sendmmsg madvise pthread_setaffinity_np])
AC_CONFIG_FILES([Makefile
samples/Makefile
diff --git a/samples/knot.full.conf b/samples/knot.full.conf
index 6ed027e..d9d9de7 100644
--- a/samples/knot.full.conf
+++ b/samples/knot.full.conf
@@ -123,6 +123,11 @@ zones {
# Possible values: on|off
# Default value: off
semantic-checks off;
+
+ # Disable ANY type queries for authoritative answers (if 'on')
+ # Possible values: on|off
+ # Default value: off
+ disable-any off;
# NOTIFY response timeout
# Possible values: <1,...> (seconds)
@@ -157,6 +162,11 @@ zones {
# was started.
file "samples/example.com.zone";
+ # Disable ANY type queries for authoritative answers (if 'on')
+ # Possible values: on|off
+ # Default value: off
+ disable-any off;
+
# Enable zone semantic checks
# Possible values: on|off
# Default value: off
diff --git a/src/Makefile.am b/src/Makefile.am
index a1bb196..60c51c6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -247,7 +247,6 @@ libknots_la_SOURCES = \
common/sockaddr.h \
common/sockaddr.c \
common/crc.h \
- common/crc.c \
common/ref.h \
common/ref.c \
common/errors.h \
diff --git a/src/Makefile.in b/src/Makefile.in
index f35f211..c00450d 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -80,8 +80,8 @@ libknots_la_DEPENDENCIES = @LIBOBJS@
am_libknots_la_OBJECTS = slab.lo tap.lo mempattern.lo lists.lo \
base32.lo print.lo dynamic-array.lo skip-list.lo base32hex.lo \
general-tree.lo evqueue.lo evsched.lo acl.lo sockaddr.lo \
- crc.lo ref.lo errors.lo dSFMT.lo prng.lo fdset.lo \
- fdset_poll.lo fdset_kqueue.lo fdset_epoll.lo log.lo
+ ref.lo errors.lo dSFMT.lo prng.lo fdset.lo fdset_poll.lo \
+ fdset_kqueue.lo fdset_epoll.lo log.lo
libknots_la_OBJECTS = $(am_libknots_la_OBJECTS)
am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)" \
"$(DESTDIR)$(man8dir)"
@@ -570,7 +570,6 @@ libknots_la_SOURCES = \
common/sockaddr.h \
common/sockaddr.c \
common/crc.h \
- common/crc.c \
common/ref.h \
common/ref.c \
common/errors.h \
@@ -849,7 +848,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cuckoo-hash-table.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cuckoo_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dSFMT.Plo@am__quote@
@@ -1420,13 +1418,6 @@ sockaddr.lo: common/sockaddr.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sockaddr.lo `test -f 'common/sockaddr.c' || echo '$(srcdir)/'`common/sockaddr.c
-crc.lo: common/crc.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT crc.lo -MD -MP -MF $(DEPDIR)/crc.Tpo -c -o crc.lo `test -f 'common/crc.c' || echo '$(srcdir)/'`common/crc.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/crc.Tpo $(DEPDIR)/crc.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/crc.c' object='crc.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o crc.lo `test -f 'common/crc.c' || echo '$(srcdir)/'`common/crc.c
-
ref.lo: common/ref.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ref.lo -MD -MP -MF $(DEPDIR)/ref.Tpo -c -o ref.lo `test -f 'common/ref.c' || echo '$(srcdir)/'`common/ref.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ref.Tpo $(DEPDIR)/ref.Plo
diff --git a/src/common/crc.c b/src/common/crc.c
deleted file mode 100644
index 33bf903..0000000
--- a/src/common/crc.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- Copyright (c) 2006-2011, Thomas Pircher <tehpeh@gmx.net>
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
-
-/**
- * \file crc.c
- * Functions and types for CRC checks.
- *
- * Generated on Fri May 6 11:25:47 2011,
- * by pycrc v0.7.7, http://www.tty1.net/pycrc/
- * using the configuration:
- * Width = 32
- * Poly = 0x04c11db7
- * XorIn = 0xffffffff
- * ReflectIn = True
- * XorOut = 0xffffffff
- * ReflectOut = True
- * Algorithm = table-driven
- *****************************************************************************/
-#include "crc.h"
-#include <stdint.h>
-#include <stdlib.h>
-
-/**
- * Static table used for the table_driven implementation.
- *****************************************************************************/
-static const crc_t crc_table[256] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/**
- * Reflect all bits of a \a data word of \a data_len bytes.
- *
- * \param data The data word to be reflected.
- * \param data_len The width of \a data expressed in number of bits.
- * \return The reflected data.
- *****************************************************************************/
-crc_t crc_reflect(crc_t data, size_t data_len)
-{
- unsigned int i;
- crc_t ret;
-
- ret = data & 0x01;
- for (i = 1; i < data_len; i++) {
- data >>= 1;
- ret = (ret << 1) | (data & 0x01);
- }
- return ret;
-}
-
-
-/**
- * Update the crc value with new data.
- *
- * \param crc The current crc value.
- * \param data Pointer to a buffer of \a data_len bytes.
- * \param data_len Number of bytes in the \a data buffer.
- * \return The updated crc value.
- *****************************************************************************/
-crc_t crc_update(crc_t crc, const unsigned char *data, size_t data_len)
-{
- unsigned int tbl_idx;
-
- while (data_len--) {
- tbl_idx = (crc ^ *data) & 0xff;
- crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
-
- data++;
- }
- return crc & 0xffffffff;
-}
-
-
-
diff --git a/src/common/crc.h b/src/common/crc.h
index 41971a9..cf2e123 100644
--- a/src/common/crc.h
+++ b/src/common/crc.h
@@ -1,54 +1,34 @@
-/*
- Copyright (c) 2006-2011, Thomas Pircher <tehpeh@gmx.net>
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
+/* 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 crc.h
- * Functions and types for CRC checks.
*
- * Generated on Fri May 6 11:25:43 2011,
- * by pycrc v0.7.7, http://www.tty1.net/pycrc/
- * using the configuration:
- * Width = 32
- * Poly = 0x04c11db7
- * XorIn = 0xffffffff
- * ReflectIn = True
- * XorOut = 0xffffffff
- * ReflectOut = True
- * Algorithm = table-driven
- *****************************************************************************/
+ * \author UFO
+ *
+ * \brief Dummy interface to CRC function of libz library. Should be removed
+ *
+ * \addtogroup common_lib
+ * @{
+ */
+
#ifndef __CRC_H__
#define __CRC_H__
+#include <zlib.h>
#include <stdint.h>
-#include <stdlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/**
- * The definition of the used algorithm.
- *****************************************************************************/
-#define CRC_ALGO_TABLE_DRIVEN 1
/**
@@ -60,23 +40,13 @@ typedef uint32_t crc_t;
/**
- * Reflect all bits of a \a data word of \a data_len bytes.
- *
- * \param data The data word to be reflected.
- * \param data_len The width of \a data expressed in number of bits.
- * \return The reflected data.
- *****************************************************************************/
-crc_t crc_reflect(crc_t data, size_t data_len);
-
-
-/**
* Calculate the initial crc value.
*
* \return The initial crc value.
*****************************************************************************/
static inline crc_t crc_init(void)
{
- return 0xffffffff;
+ return adler32(0L, NULL, 0);
}
@@ -88,7 +58,10 @@ static inline crc_t crc_init(void)
* \param data_len Number of bytes in the \a data buffer.
* \return The updated crc value.
*****************************************************************************/
-crc_t crc_update(crc_t crc, const unsigned char *data, size_t data_len);
+static inline crc_t crc_update(crc_t crc, const unsigned char *data, size_t data_len)
+{
+ return adler32(crc, data, data_len);
+}
/**
@@ -99,12 +72,8 @@ crc_t crc_update(crc_t crc, const unsigned char *data, size_t data_len);
*****************************************************************************/
static inline crc_t crc_finalize(crc_t crc)
{
- return crc ^ 0xffffffff;
+ return crc;
}
-#ifdef __cplusplus
-} /* closing brace for extern "C" */
-#endif
-
#endif /* __CRC_H__ */
diff --git a/src/common/log.c b/src/common/log.c
index 6d77ccb..c70f739 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -14,11 +14,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define _BSD_SOURCE
#include <config.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
#include "common/log.h"
#include "common/lists.h"
@@ -140,7 +143,7 @@ int log_open_file(const char* filename)
}
// Open file
- LOG_FDS[LOG_FDS_OPEN] = fopen(filename, "w");
+ LOG_FDS[LOG_FDS_OPEN] = fopen(filename, "a");
if (!LOG_FDS[LOG_FDS_OPEN]) {
return KNOTD_EINVAL;
}
@@ -212,14 +215,15 @@ static int _log_msg(logsrc_t src, int level, const char *msg)
/* Prefix date and time. */
char tstr[128] = {0};
int tlen = 0;
- time_t t = time(NULL);
- struct tm *lt = localtime(&t);
- if (lt != NULL) {
+ struct tm lt;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ if (localtime_r(&tv.tv_sec, &lt) != NULL) {
tlen = strftime(tstr, sizeof(tstr) - 1,
- "%d-%m-%Y %H:%M:%S", lt);
+ "%Y-%m-%dT%H:%M:%S", &lt);
if (tlen > 0) {
- tstr[tlen] = ' ';
- tstr[tlen + 1] = '\0';
+ char pm = (lt.tm_gmtoff > 0)?'+':'-';
+ snprintf(tstr+tlen, 128-tlen-1, ".%.6lu%c%.2u:%.2u ", (unsigned long)tv.tv_usec, pm, (unsigned int)lt.tm_gmtoff/3600, (unsigned int)(lt.tm_gmtoff/60)%60);
}
}
diff --git a/src/config.h.in b/src/config.h.in
index 905e327..bd88e96 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -105,6 +105,9 @@
/* Define to 1 if you have the `pselect' function. */
#undef HAVE_PSELECT
+/* Define to 1 if you have the `pthread_setaffinity_np' function. */
+#undef HAVE_PTHREAD_SETAFFINITY_NP
+
/* Define to 1 if you have the `regcomp' function. */
#undef HAVE_REGCOMP
diff --git a/src/knot/conf/cf-lex.l b/src/knot/conf/cf-lex.l
index dfd0ac7..16b0343 100644
--- a/src/knot/conf/cf-lex.l
+++ b/src/knot/conf/cf-lex.l
@@ -77,6 +77,7 @@ remotes { lval.t = yytext; return REMOTES; }
zones { lval.t = yytext; return ZONES; }
file { lval.t = yytext; return FILENAME; }
+disable-any { lval.t = yytext; return DISABLE_ANY; }
semantic-checks { lval.t = yytext; return SEMANTIC_CHECKS; }
notify-retries { lval.t = yytext; return NOTIFY_RETRIES; }
notify-timeout { lval.t = yytext; return NOTIFY_TIMEOUT; }
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index 4981606..b415662 100644
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -171,6 +171,7 @@ static void conf_zone_start(void *scanner, char *name) {
this_zone->notify_retries = 0; // Default policy applies
this_zone->ixfr_fslimit = -1; // Default policy applies
this_zone->dbsync_timeout = -1; // Default policy applies
+ this_zone->disable_any = -1; // Default policy applies
// Append mising dot to ensure FQDN
size_t nlen = strlen(name);
@@ -255,6 +256,7 @@ static int conf_mask(void* scanner, int nval, int prefixlen) {
%token <tok> REMOTES
%token <tok> ZONES FILENAME
+%token <tok> DISABLE_ANY
%token <tok> SEMANTIC_CHECKS
%token <tok> NOTIFY_RETRIES
%token <tok> NOTIFY_TIMEOUT
@@ -642,6 +644,7 @@ zone:
| zone zone_acl_list
| zone FILENAME TEXT ';' { this_zone->file = $3.t; }
| zone SEMANTIC_CHECKS BOOL ';' { this_zone->enable_checks = $3.i; }
+ | zone DISABLE_ANY BOOL ';' { this_zone->disable_any = $3.i; }
| zone DBSYNC_TIMEOUT NUM ';' { this_zone->dbsync_timeout = $3.i; }
| zone DBSYNC_TIMEOUT INTERVAL ';' { this_zone->dbsync_timeout = $3.i; }
| zone IXFR_FSLIMIT SIZE ';' { new_config->ixfr_fslimit = $3.l; }
@@ -665,6 +668,7 @@ zone:
zones:
ZONES '{'
| zones zone '}'
+ | zones DISABLE_ANY BOOL ';' { new_config->disable_any = $3.i; }
| zones SEMANTIC_CHECKS BOOL ';' { new_config->zone_checks = $3.i; }
| zones IXFR_FSLIMIT SIZE ';' { new_config->ixfr_fslimit = $3.l; }
| zones IXFR_FSLIMIT NUM ';' { new_config->ixfr_fslimit = $3.i; }
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index 2cb4516..4bbf622 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -219,6 +219,11 @@ static int conf_process(conf_t *conf)
if (zone->enable_checks < 0) {
zone->enable_checks = conf->zone_checks;
}
+
+ // Default policy for disabling ANY type queries for AA
+ if (zone->disable_any < 0) {
+ zone->disable_any = conf->disable_any;
+ }
// Default policy for NOTIFY retries
if (zone->notify_retries <= 0) {
diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h
index 40cd1cc..7e1b61f 100644
--- a/src/knot/conf/conf.h
+++ b/src/knot/conf/conf.h
@@ -93,6 +93,7 @@ typedef struct conf_zone_t {
size_t ixfr_fslimit; /*!< File size limit for IXFR journal. */
int dbsync_timeout; /*!< Interval between syncing to zonefile.*/
int enable_checks; /*!< Semantic checks for parser.*/
+ int disable_any; /*!< Disable ANY type queries for AA.*/
int notify_retries; /*!< NOTIFY query retries. */
int notify_timeout; /*!< Timeout for NOTIFY response (s). */
struct {
@@ -191,6 +192,7 @@ typedef struct conf_t {
list zones; /*!< List of zones. */
int zones_count; /*!< Count of zones. */
int zone_checks; /*!< Semantic checks for parser.*/
+ int disable_any; /*!< Disable ANY type queries for AA.*/
int notify_retries; /*!< NOTIFY query retries. */
int notify_timeout; /*!< Timeout for NOTIFY response in seconds. */
int dbsync_timeout; /*!< Default interval between syncing to zonefile.*/
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index 436cc5e..97412dd 100644
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -54,7 +54,7 @@ static inline unsigned has_flag(unsigned flags, enum knotc_flag_t f) {
void help(int argc, char **argv)
{
printf("Usage: %sc [parameters] start|stop|restart|reload|running|"
- "compile\n", PACKAGE_NAME);
+ "compile [additional]\n", PACKAGE_NAME);
printf("Parameters:\n"
" -c [file], --config=[file] Select configuration file.\n"
" -j [num], --jobs=[num] Number of parallel tasks to run (only for 'compile').\n"
@@ -63,7 +63,7 @@ void help(int argc, char **argv)
" -V, --version Print %s server version.\n"
" -w, --wait Wait for the server to finish start/stop operations.\n"
" -i, --interactive Interactive mode (do not daemonize).\n"
- " -a, --auto Enable automatic recompilation (start or reload)."
+ " -a, --auto Enable automatic recompilation (start or reload).\n"
" -h, --help Print help and usage.\n",
PACKAGE_NAME);
printf("Actions:\n"
@@ -71,10 +71,13 @@ void help(int argc, char **argv)
" stop Stop %s server (no-op if not running).\n"
" restart Stops and then starts %s server.\n"
" reload Reload %s configuration and compiled zones.\n"
+ " refresh Refresh all slave zones.\n"
" running Check if server is running.\n"
" checkconf Check server configuration.\n"
"\n"
- " compile Compile zone file.\n",
+ " checkzone Check zones (accepts specific zones, f.e. "
+ "'knotc checkzone example1.com example2.com').\n"
+ " compile Compile zones (accepts specific zones, see above).\n",
PACKAGE_NAME, PACKAGE_NAME, PACKAGE_NAME, PACKAGE_NAME);
}
@@ -205,7 +208,7 @@ knotc_zctask_t *zctask_create(int count)
}
/*! \brief Wait for single task to finish. */
-int zctask_wait(knotc_zctask_t *tasks, int count)
+int zctask_wait(knotc_zctask_t *tasks, int count, int is_checkzone)
{
/* Wait for children to finish. */
int rc = 0;
@@ -229,16 +232,18 @@ int zctask_wait(knotc_zctask_t *tasks, int count)
/* Evaluate. */
if (!WIFEXITED(rc)) {
- log_server_error("Compilation of '%s' "
- "failed, process was killed.\n",
+ log_server_error("%s of '%s' failed, process was killed.\n",
+ is_checkzone ? "Checking" : "Compilation",
z->name);
return 1;
} else {
if (rc < 0 || WEXITSTATUS(rc) != 0) {
- log_server_error("Compilation of "
- "'%s' failed, knot-zcompile "
- "return code was '%d'\n",
- z->name, WEXITSTATUS(rc));
+ if (!is_checkzone) {
+ log_zone_error("Compilation of "
+ "'%s' failed, knot-zcompile "
+ "return code was '%d'\n",
+ z->name, WEXITSTATUS(rc));
+ }
return 1;
}
}
@@ -446,11 +451,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
log_server_warning("Server PID not found, "
"probably not running.\n");
- if (has_flag(flags, F_FORCE)) {
- log_server_info("Forcing server stop.\n");
- } else {
- return 1;
- }
+ return 1;
}
// Recompile zones if needed
@@ -461,8 +462,27 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
// Stop
if (kill(pid, SIGHUP) < 0) {
- pid_remove(pidfile);
rc = 1;
+ } else {
+ log_server_info("Server reload queued - OK.\n");
+ }
+ }
+ if (strcmp(action, "refresh") == 0) {
+
+ // Check PID
+ valid_cmd = 1;
+ if (pid <= 0 || !pid_running(pid)) {
+ log_server_warning("Server PID not found, "
+ "probably not running.\n");
+
+ return 1;
+ }
+
+ // Stop
+ if (kill(pid, SIGUSR2) < 0) {
+ rc = 1;
+ } else {
+ log_server_info("Zones refresh queued - OK.\n");
}
}
if (strcmp(action, "running") == 0) {
@@ -490,18 +510,22 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
rc = 0;
valid_cmd = 1;
}
- if (strcmp(action, "compile") == 0) {
+ if (strcmp(action, "compile") == 0 || strcmp(action, "checkzone") == 0){
// Print job count
- if (jobs > 1) {
+ if (jobs > 1 && argc == 0) {
log_server_warning("Will attempt to compile %d zones "
"in parallel, this increases memory "
- "consumption for large zones.\n", jobs);
+ "consumption for large zones.\n",
+ jobs);
}
+ // Zone checking
+ int is_checkzone = (strcmp(action, "checkzone") == 0);
+
// Check zone
valid_cmd = 1;
-
+
// Lock configuration
conf_read_lock();
@@ -513,57 +537,81 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
// Fetch zone
conf_zone_t *zone = (conf_zone_t*)n;
+
+ // Specific zone requested
+ int zone_match = 0;
+ for (unsigned i = 0; i < argc; ++i) {
+ size_t len = strlen(zone->name);
+ if (len > 1) {
+ len -= 1;
+ } // All (except root) without final dot
+ if (strncmp(zone->name, argv[i], len) == 0) {
+ zone_match = 1;
+ break;
+ }
+ }
+ if (!zone_match && argc > 0) {
+ continue;
+ }
// Check source files and mtime
int zone_status = check_zone(zone->db, zone->file);
- if (zone_status == KNOTD_EOK) {
+ if (zone_status == KNOTD_EOK && !is_checkzone) {
log_zone_info("Zone '%s' is up-to-date.\n",
- zone->name);
-
+ zone->name);
+
if (has_flag(flags, F_FORCE)) {
log_zone_info("Forcing zone "
- "recompilation.\n");
+ "recompilation.\n");
} else {
continue;
}
}
-
+
// Check for not existing source
if (zone_status == KNOTD_ENOENT) {
continue;
}
+
/* Evaluate space for new task. */
if (running == jobs) {
- rc |= zctask_wait(tasks, jobs);
+ rc |= zctask_wait(tasks, jobs, is_checkzone);
--running;
}
- const char *args[] = {
- ZONEPARSER_EXEC,
- zone->enable_checks ? "-s" : "",
- has_flag(flags, F_VERBOSE) ? "-v" : "",
- "-o",
- zone->db,
- zone->name,
- zone->file
- };
+ int ac = 0;
+ const char *args[7] = { NULL };
+ args[ac++] = ZONEPARSER_EXEC;
+ if (zone->enable_checks) {
+ args[ac++] = "-s";
+ }
+ if (has_flag(flags, F_VERBOSE)) {
+ args[ac++] = "-v";
+ }
+
+ if (!is_checkzone) {
+ args[ac++] = "-o";
+ args[ac++] = zone->db;
+ }
+ args[ac++] = zone->name;
+ args[ac++] = zone->file;
// Execute command
- if (has_flag(flags, F_VERBOSE)) {
+ if (has_flag(flags, F_VERBOSE) && !is_checkzone) {
log_zone_info("Compiling '%s' as '%s'...\n",
zone->name, zone->db);
}
fflush(stdout);
fflush(stderr);
- pid_t zcpid = start_cmd(args, 7);
+ pid_t zcpid = start_cmd(args, ac);
zctask_add(tasks, jobs, zcpid, zone);
++running;
}
/* Wait for all running tasks. */
while (running > 0) {
- rc |= zctask_wait(tasks, jobs);
+ rc |= zctask_wait(tasks, jobs, is_checkzone);
--running;
}
free(tasks);
diff --git a/src/knot/main.c b/src/knot/main.c
index e83551c..99ee1cf 100644
--- a/src/knot/main.c
+++ b/src/knot/main.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
+#include <limits.h>
#ifdef HAVE_CAP_NG_H
#include <cap-ng.h>
#endif /* HAVE_CAP_NG_H */
@@ -38,6 +39,7 @@
/* Signal flags. */
static volatile short sig_req_stop = 0;
static volatile short sig_req_reload = 0;
+static volatile short sig_req_refresh = 0;
static volatile short sig_stopping = 0;
// SIGINT signal handler
@@ -48,7 +50,13 @@ void interrupt_handle(int s)
sig_req_reload = 1;
return;
}
-
+
+ // Refresh
+ if (s == SIGUSR2) {
+ sig_req_refresh = 1;
+ return;
+ }
+
// Stop server
if (s == SIGINT || s == SIGTERM) {
if (sig_stopping == 0) {
@@ -165,24 +173,15 @@ int main(int argc, char **argv)
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);
+ char *rpath = realpath(config_fn, NULL);
+ if (rpath == NULL) {
+ log_server_error("Couldn't get absolute path for configuration file '%s' - "
+ "%s.\n", config_fn, strerror(errno));
+ return 1;
+ } else {
+ free(config_fn);
+ config_fn = rpath;
}
-
- // Assemble path to config file
- char *abs_cfg = strcdup(cwbuf, config_fn);
- free(config_fn);
- free(cwbuf);
- config_fn = abs_cfg;
}
/* POSIX 1003.1e capabilities. */
@@ -290,6 +289,7 @@ int main(int argc, char **argv)
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
+ sigaction(SIGUSR2, &sa, NULL);
sa.sa_flags = 0;
pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL);
@@ -326,6 +326,17 @@ int main(int argc, char **argv)
break;
}
}
+ if (sig_req_refresh) {
+ log_server_info("Refreshing slave zones...\n");
+ sig_req_reload = 0;
+ int cf_ret = server_refresh(server);
+ if (cf_ret != KNOTD_EOK) {
+ log_server_error("Couldn't refresh "
+ "slave zones - %s",
+ knotd_strerror(cf_ret));
+ }
+
+ }
/* Events. */
if (ret > 0) {
diff --git a/src/knot/server/dthreads.c b/src/knot/server/dthreads.c
index 4e2b490..e2b45f2 100644
--- a/src/knot/server/dthreads.c
+++ b/src/knot/server/dthreads.c
@@ -854,6 +854,28 @@ int dt_stop(dt_unit_t *unit)
// return KNOTD_EOK;
//}
+int dt_setaffinity(dthread_t *thread, void *mask, size_t len)
+{
+ if (thread == NULL || mask == NULL) {
+ return KNOTD_EINVAL;
+ }
+
+#ifdef HAVE_PTHREAD_SETAFFINITY_NP
+ if (len != sizeof(cpu_set_t)) {
+ return KNOTD_EINVAL;
+ }
+ pthread_t tid = pthread_self();
+ int ret = pthread_setaffinity_np(tid, len, (cpu_set_t*)mask);
+ if (ret < 0) {
+ return KNOTD_ERROR;
+ }
+#else
+ return KNOTD_ENOTSUP;
+#endif
+
+ return KNOTD_EOK;
+}
+
int dt_repurpose(dthread_t *thread, runnable_t runnable, void *data)
{
// Check
@@ -963,14 +985,22 @@ int dt_compact(dt_unit_t *unit)
return KNOTD_EOK;
}
-int dt_optimal_size()
+int dt_online_cpus()
{
+ int ret = -1;
#ifdef _SC_NPROCESSORS_ONLN
- int ret = (int) sysconf(_SC_NPROCESSORS_ONLN);
- if (ret >= 1) {
+ ret = (int) sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+ return ret;
+}
+
+int dt_optimal_size()
+{
+ int ret = dt_online_cpus();
+ if (ret > 0) {
return ret + CPU_ESTIMATE_MAGIC;
}
-#endif
+
dbg_dt("dthreads: failed to fetch the number of online CPUs.");
return DEFAULT_THR_COUNT;
}
@@ -993,6 +1023,22 @@ int dt_is_cancelled(dthread_t *thread)
return ret;
}
+unsigned dt_get_id(dthread_t *thread)
+{
+ if (thread == NULL || thread->unit == NULL) {
+ return 0;
+ }
+
+ dt_unit_t *unit = thread->unit;
+ for(unsigned tid = 0; tid < unit->size; ++tid) {
+ if (thread == unit->threads[tid]) {
+ return tid;
+ }
+ }
+
+ return 0;
+}
+
int dt_unit_lock(dt_unit_t *unit)
{
// Check input
diff --git a/src/knot/server/dthreads.h b/src/knot/server/dthreads.h
index 2347e1d..8ba457b 100644
--- a/src/knot/server/dthreads.h
+++ b/src/knot/server/dthreads.h
@@ -251,6 +251,17 @@ int dt_stop(dt_unit_t *unit);
//int dt_setprio(dthread_t *thread, int prio);
/*!
+ * \brief Set thread affinity to masked CPU's.
+ *
+ * \param thread Target thread instance.
+ * \param mask CPU mask (should be pointer to cpu_set_t).
+ *
+ * \retval KNOTD_EOK on success.
+ * \retval KNOTD_EINVAL on invalid parameters.
+ */
+int dt_setaffinity(dthread_t *thread, void *mask, size_t len);
+
+/*!
* \brief Set thread to execute another runnable.
*
* \param thread Target thread instance.
@@ -307,9 +318,17 @@ int dt_cancel(dthread_t *thread);
int dt_compact(dt_unit_t *unit);
/*!
+ * \brief Return number of online processors.
+ *
+ * \retval Number of online CPU's if success.
+ * \retval <0 on failure.
+ */
+int dt_online_cpus();
+
+/*!
* \brief Return optimal number of threads for instance.
*
- * It is estimated as NUM_CPUs + 1.
+ * It is estimated as NUM_CPUs + CONSTANT.
* Fallback is DEFAULT_THR_COUNT (\see common.h).
*
* \return Number of threads.
@@ -328,6 +347,18 @@ int dt_optimal_size();
*/
int dt_is_cancelled(dthread_t *thread);
+
+/*!
+ * \brief Return thread index in threading unit.
+ *
+ * \note Returns 0 when thread doesn't have a unit.
+ *
+ * \param thread Target thread instance.
+ *
+ * \return Thread index.
+ */
+unsigned dt_get_id(dthread_t *thread);
+
/*!
* \brief Lock unit to prevent parallel operations which could alter unit
* at the same time.
diff --git a/src/knot/server/journal.c b/src/knot/server/journal.c
index fc8ec5c..9203f79 100644
--- a/src/knot/server/journal.c
+++ b/src/knot/server/journal.c
@@ -62,6 +62,10 @@ static inline int journal_cmp_eq(uint64_t k1, uint64_t k2)
/*! \brief Recover metadata from journal. */
static int journal_recover(journal_t *j)
{
+ if (j == NULL) {
+ return KNOTD_EINVAL;
+ }
+
/* Attempt to recover queue. */
int qstate[2] = { -1, -1 };
unsigned c = 0, p = j->max_nodes - 1;
@@ -475,7 +479,8 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
"it will be flushed.\n", fn);
fcntl(fd, F_SETLK, &fl);
close(fd);
- return NULL;
+ journal_create(fn, JOURNAL_NCOUNT);
+ return journal_open(fn, fslimit, mode, bflags);
}
crc_t crc = 0;
if (!sfread(&crc, sizeof(crc_t), fd)) {
@@ -501,7 +506,8 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
"it will be flushed.\n", fn);
fcntl(fd, F_SETLK, &fl);
close(fd);
- return NULL;
+ journal_create(fn, JOURNAL_NCOUNT);
+ return journal_open(fn, fslimit, mode, bflags);
}
/* Check for lazy mode. */
@@ -653,7 +659,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
int journal_fetch(journal_t *journal, uint64_t id,
journal_cmp_t cf, journal_node_t** dst)
{
- if (journal == 0 || dst == 0) {
+ if (journal == NULL || dst == NULL) {
return KNOTD_EINVAL;
}
@@ -679,7 +685,7 @@ int journal_fetch(journal_t *journal, uint64_t id,
int journal_read(journal_t *journal, uint64_t id, journal_cmp_t cf, char *dst)
{
- if (journal == 0 || dst == 0) {
+ if (journal == NULL || dst == NULL) {
return KNOTD_EINVAL;
}
@@ -834,7 +840,7 @@ int journal_walk(journal_t *journal, journal_apply_t apply)
int journal_update(journal_t *journal, journal_node_t *n)
{
- if (!journal || !n) {
+ if (journal == NULL || n == NULL) {
return KNOTD_EINVAL;
}
@@ -941,7 +947,7 @@ int journal_trans_rollback(journal_t *journal)
int journal_close(journal_t *journal)
{
/* Check journal. */
- if (!journal) {
+ if (journal == NULL) {
return KNOTD_EINVAL;
}
diff --git a/src/knot/server/journal.h b/src/knot/server/journal.h
index d874996..322e25d 100644
--- a/src/knot/server/journal.h
+++ b/src/knot/server/journal.h
@@ -129,7 +129,7 @@ typedef int (*journal_apply_t)(journal_t *j, journal_node_t *n);
#define JOURNAL_NCOUNT 1024 /*!< Default node count. */
/* HEADER = magic, crc, max_entries, qhead, qtail */
#define JOURNAL_HSIZE (MAGIC_LENGTH + sizeof(crc_t) + sizeof(uint16_t) * 3)
-#define JOURNAL_MAGIC {'k', 'n', 'o', 't', '1', '0', '2'}
+#define JOURNAL_MAGIC {'k', 'n', 'o', 't', '1', '0', '4'}
/*!
* \brief Create new journal.
diff --git a/src/knot/server/notify.c b/src/knot/server/notify.c
index d12247b..aa0a52b 100644
--- a/src/knot/server/notify.c
+++ b/src/knot/server/notify.c
@@ -243,8 +243,9 @@ int notify_process_request(knot_nameserver_t *ns,
if (knot_packet_parse_rest(notify) != KNOT_EOK) {
dbg_notify("notify: failed to parse NOTIFY query\n");
knot_ns_error_response(ns, knot_packet_id(notify),
- KNOT_RCODE_FORMERR, buffer,
- size);
+ &notify->header.flags1,
+ KNOT_RCODE_FORMERR, buffer,
+ size);
return KNOTD_EOK;
}
}
@@ -255,8 +256,8 @@ int notify_process_request(knot_nameserver_t *ns,
if (ret != KNOTD_EOK) {
dbg_notify("notify: failed to create NOTIFY response\n");
knot_ns_error_response(ns, knot_packet_id(notify),
- KNOT_RCODE_SERVFAIL, buffer,
- size);
+ &notify->header.flags1,
+ KNOT_RCODE_SERVFAIL, buffer, size);
return KNOTD_EOK;
}
@@ -267,8 +268,8 @@ int notify_process_request(knot_nameserver_t *ns,
if (z == NULL) {
dbg_notify("notify: failed to find zone by name\n");
knot_ns_error_response(ns, knot_packet_id(notify),
- KNOT_RCODE_REFUSED, buffer,
- size);
+ &notify->header.flags1,
+ KNOT_RCODE_REFUSED, buffer, size);
return KNOTD_EOK;
}
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index ba7ccd7..5611a0c 100644
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -24,17 +24,20 @@
#include <assert.h>
#include <grp.h>
+
+#include "common/prng.h"
#include "knot/common.h"
#include "knot/other/error.h"
#include "knot/server/server.h"
#include "knot/server/udp-handler.h"
#include "knot/server/tcp-handler.h"
#include "knot/server/xfr-handler.h"
-#include "libknot/nameserver/name-server.h"
+#include "knot/server/zones.h"
+#include "knot/conf/conf.h"
#include "knot/stat/stat.h"
+#include "libknot/nameserver/name-server.h"
#include "libknot/zone/zonedb.h"
#include "libknot/dname.h"
-#include "knot/conf/conf.h"
/*! \brief Event scheduler loop. */
static int evsched_run(dthread_t *thread)
@@ -124,7 +127,7 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
/* Initialize interface. */
int ret = 0;
int sock = 0;
- char errbuf[128];
+ char errbuf[256] = {0};
int opt = 1024 * 1024;
int snd_opt = 1024 * 1024;
memset(new_if, 0, sizeof(iface_t));
@@ -153,7 +156,7 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
new_if->type[UDP_ID] = cfg_if->family;
/* Set socket options - voluntary. */
- char ebuf[512];
+ char ebuf[256] = {0};
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &snd_opt, sizeof(snd_opt)) < 0) {
strerror_r(errno, ebuf, sizeof(ebuf));
// log_server_warning("Failed to configure socket "
@@ -610,6 +613,42 @@ int server_wait(server_t *server)
return ret;
}
+int server_refresh(server_t *server)
+{
+ if (server == NULL || server->nameserver == NULL) {
+ return KNOTD_EINVAL;
+ }
+
+ /* Lock RCU and fetch zones. */
+ rcu_read_lock();
+ knot_nameserver_t *ns = server->nameserver;
+ evsched_t *sch = ((server_t *)knot_ns_get_data(ns))->sched;
+ const knot_zone_t **zones = knot_zonedb_zones(ns->zone_db);
+ if (zones == NULL) {
+ rcu_read_unlock();
+ return KNOTD_ENOMEM;
+ }
+
+ /* REFRESH zones. */
+ for (unsigned i = 0; i < knot_zonedb_zone_count(ns->zone_db); ++i) {
+ zonedata_t *zd = (zonedata_t *)zones[i]->data;
+ if (zd == NULL) {
+ continue;
+ }
+ /* Expire REFRESH timer. */
+ if (zd->xfr_in.timer) {
+ evsched_cancel(sch, zd->xfr_in.timer);
+ evsched_schedule(sch, zd->xfr_in.timer,
+ tls_rand() * 1000);
+ }
+ }
+
+ /* Unlock RCU. */
+ rcu_read_unlock();
+ free(zones);
+ return KNOTD_EOK;
+}
+
void server_stop(server_t *server)
{
dbg_server("server: stopping server\n");
diff --git a/src/knot/server/server.h b/src/knot/server/server.h
index b1358cd..79a4729 100644
--- a/src/knot/server/server.h
+++ b/src/knot/server/server.h
@@ -179,6 +179,16 @@ int server_start(server_t *server);
int server_wait(server_t *server);
/*!
+ * \brief Refresh served zones.
+ *
+ * \param server Server structure to be used for operation.
+ *
+ * \retval 0 On success (EOK).
+ * \retval <0 If an error occured (EINVAL).
+ */
+int server_refresh(server_t *server);
+
+/*!
* \brief Requests server to stop.
*
* \param server Server structure to be used for operation.
diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index 5f79096..977de0b 100644
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -132,6 +132,13 @@ static void tcp_sweep(fdset_t *set, int fd, void* data)
*
* \param w Associated I/O event.
* \param revents Returned events.
+ *
+ * \note We do not know if the packet makes sense or if it is
+ * a bunch of random bytes. There is no way to find out
+ * without parsing. However, it is irrelevant if we copy
+ * these random bytes to the response, so we may do it
+ * and ensure that in case of good packet the response
+ * is proper.
*/
static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen)
{
@@ -172,26 +179,31 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
}
/* Parse query. */
-// knot_response_t *resp = knot_response_new(qbuf_maxlen);
size_t resp_len = qbuf_maxlen; // 64K
knot_packet_type_t qtype = KNOT_QUERY_NORMAL;
knot_packet_t *packet =
knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
if (packet == NULL) {
- uint16_t pkt_id = knot_wire_get_id(qbuf);
- knot_ns_error_response(ns, pkt_id, KNOT_RCODE_SERVFAIL,
- qbuf, &resp_len);
- tcp_reply(fd, qbuf, resp_len);
+ int ret = knot_ns_error_response_from_query(ns, qbuf, n,
+ KNOT_RCODE_SERVFAIL,
+ qbuf, &resp_len);
+
+ if (ret == KNOT_EOK) {
+ tcp_reply(fd, qbuf, resp_len);
+ }
+
return KNOTD_EOK;
}
int parse_res = knot_ns_parse_packet(qbuf, n, packet, &qtype);
if (unlikely(parse_res != KNOT_EOK)) {
if (parse_res > 0) { /* Returned RCODE */
- uint16_t pkt_id = knot_wire_get_id(qbuf);
- knot_ns_error_response(ns, pkt_id, parse_res,
- qbuf, &resp_len);
- tcp_reply(fd, qbuf, resp_len);
+ int ret = knot_ns_error_response_from_query(ns, qbuf, n,
+ parse_res, qbuf, &resp_len);
+
+ if (ret == KNOT_EOK) {
+ tcp_reply(fd, qbuf, resp_len);
+ }
}
knot_packet_free(&packet);
return KNOTD_EOK;
@@ -224,6 +236,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
res = xfr_request_init(&xfr, xfrt, XFR_FLAG_TCP, packet);
if (res != KNOTD_EOK) {
knot_ns_error_response(ns, knot_packet_id(packet),
+ &packet->header.flags1,
KNOT_RCODE_SERVFAIL, qbuf,
&resp_len);
res = KNOTD_EOK;
@@ -240,8 +253,8 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
case KNOT_QUERY_UPDATE:
knot_ns_error_response(ns, knot_packet_id(packet),
- KNOT_RCODE_NOTIMPL, qbuf,
- &resp_len);
+ &packet->header.flags1,
+ KNOT_RCODE_NOTIMPL, qbuf, &resp_len);
res = KNOTD_EOK;
break;
@@ -256,16 +269,16 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
case KNOT_RESPONSE_AXFR: /*!< Processed in XFR handler. */
case KNOT_RESPONSE_IXFR: /*!< Processed in XFR handler. */
knot_ns_error_response(ns, knot_packet_id(packet),
- KNOT_RCODE_REFUSED, qbuf,
- &resp_len);
+ &packet->header.flags1,
+ KNOT_RCODE_REFUSED, qbuf, &resp_len);
res = KNOTD_EOK;
break;
/* Unknown opcodes. */
default:
knot_ns_error_response(ns, knot_packet_id(packet),
- KNOT_RCODE_FORMERR, qbuf,
- &resp_len);
+ &packet->header.flags1,
+ KNOT_RCODE_FORMERR, qbuf, &resp_len);
res = KNOTD_EOK;
break;
}
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index 80bc011..dcb5b1f 100644
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -47,6 +47,7 @@
#include "libknot/packet/packet.h"
#include "knot/server/zones.h"
#include "knot/server/notify.h"
+#include "libknot/util/error.h"
/* Check for sendmmsg syscall. */
#ifdef HAVE_SENDMMSG
@@ -83,9 +84,15 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
if (packet == NULL) {
dbg_net("udp: failed to create packet on fd=%d\n", fd);
- uint16_t pkt_id = knot_wire_get_id(qbuf);
- knot_ns_error_response(ns, pkt_id, KNOT_RCODE_SERVFAIL,
- qbuf, resp_len);
+
+ int ret = knot_ns_error_response_from_query(ns, qbuf, qbuflen,
+ KNOT_RCODE_SERVFAIL,
+ qbuf, resp_len);
+
+ if (ret != KNOT_EOK) {
+ return KNOTD_EMALF;
+ }
+
return KNOTD_EOK; /* Created error response. */
}
@@ -94,9 +101,15 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
if (unlikely(res != KNOTD_EOK)) {
dbg_net("udp: failed to parse packet on fd=%d\n", fd);
if (res > 0) { /* Returned RCODE */
- uint16_t pkt_id = knot_wire_get_id(qbuf);
- knot_ns_error_response(ns, pkt_id, res,
- qbuf, resp_len);
+ int ret = knot_ns_error_response_from_query(ns, qbuf,
+ qbuflen,
+ res, qbuf,
+ resp_len);
+
+ if (ret != KNOT_EOK) {
+ knot_packet_free(&packet);
+ return KNOTD_EMALF;
+ }
}
knot_packet_free(&packet);
@@ -111,20 +124,16 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
/* Response types. */
case KNOT_RESPONSE_NORMAL:
- res = zones_process_response(ns, addr, packet,
- qbuf, resp_len);
+ res = zones_process_response(ns, addr, packet, qbuf, resp_len);
break;
case KNOT_RESPONSE_NOTIFY:
- res = notify_process_response(ns, packet, addr,
- qbuf, resp_len);
+ res = notify_process_response(ns, packet, addr, qbuf, resp_len);
break;
/* Query types. */
case KNOT_QUERY_NORMAL:
res = zones_normal_query_answer(ns, packet, addr, qbuf,
resp_len, NS_TRANSPORT_UDP);
-// res = knot_ns_answer_normal(ns, packet, qbuf,
-// resp_len);
break;
case KNOT_QUERY_AXFR:
/* RFC1034, p.28 requires reliable transfer protocol.
@@ -132,8 +141,8 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
*/
/*! \note Draft exists for AXFR/UDP, but has not been standardized. */
knot_ns_error_response(ns, knot_packet_id(packet),
- KNOT_RCODE_FORMERR, qbuf,
- resp_len);
+ &packet->header.flags1,
+ KNOT_RCODE_FORMERR, qbuf, resp_len);
res = KNOTD_EOK;
break;
case KNOT_QUERY_IXFR:
@@ -146,8 +155,6 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
res = zones_normal_query_answer(ns, packet, addr,
qbuf, resp_len,
NS_TRANSPORT_UDP);
-// res = knot_ns_answer_normal(ns, packet, qbuf,
-// resp_len);
break;
case KNOT_QUERY_NOTIFY:
res = notify_process_request(ns, packet, addr,
@@ -157,8 +164,8 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
case KNOT_QUERY_UPDATE:
dbg_net("udp: UPDATE query on fd=%d not implemented\n", fd);
knot_ns_error_response(ns, knot_packet_id(packet),
- KNOT_RCODE_NOTIMPL, qbuf,
- resp_len);
+ &packet->header.flags1,
+ KNOT_RCODE_NOTIMPL, qbuf, resp_len);
res = KNOTD_EOK;
break;
@@ -166,6 +173,7 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
case KNOT_RESPONSE_AXFR: /*!< Processed in XFR handler. */
case KNOT_RESPONSE_IXFR: /*!< Processed in XFR handler. */
knot_ns_error_response(ns, knot_packet_id(packet),
+ &packet->header.flags1,
KNOT_RCODE_REFUSED, qbuf,
resp_len);
res = KNOTD_EOK;
@@ -174,8 +182,8 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
/* Unknown opcodes */
default:
knot_ns_error_response(ns, knot_packet_id(packet),
- KNOT_RCODE_FORMERR, qbuf,
- resp_len);
+ &packet->header.flags1,
+ KNOT_RCODE_FORMERR, qbuf, resp_len);
res = KNOTD_EOK;
break;
}
@@ -193,6 +201,21 @@ static inline int udp_master_recvfrom(dthread_t *thread, stat_t *thread_stat)
return KNOTD_EINVAL;
}
+ /* Set CPU affinity to improve load distribution on multicore systems.
+ * Partial overlapping mask to be nice to scheduler.
+ */
+#ifdef HAVE_PTHREAD_SETAFFINITY_NP
+ int cpcount = dt_online_cpus();
+ if (cpcount > 0) {
+ unsigned tid = dt_get_id(thread);
+ cpu_set_t cpus;
+ CPU_ZERO(&cpus);
+ CPU_SET(tid % cpcount, &cpus);
+ CPU_SET((tid + 1) % cpcount, &cpus);
+ dt_setaffinity(thread, &cpus, sizeof(cpu_set_t));
+ }
+#endif
+
knot_nameserver_t *ns = h->server->nameserver;
/* Initialize remote party address. */
@@ -380,6 +403,21 @@ static inline int udp_master_recvmmsg(dthread_t *thread, stat_t *thread_stat)
msgs[i].msg_hdr.msg_name = addrs[i].ptr;
msgs[i].msg_hdr.msg_namelen = addrs[i].len;
}
+
+ /* Set CPU affinity to improve load distribution on multicore systems.
+ * Partial overlapping mask to be nice to scheduler.
+ */
+#ifdef HAVE_PTHREAD_SETAFFINITY_NP
+ int cpcount = dt_online_cpus();
+ if (cpcount > 0) {
+ unsigned tid = dt_get_id(thread);
+ cpu_set_t cpus;
+ CPU_ZERO(&cpus);
+ CPU_SET(tid % cpcount, &cpus);
+ CPU_SET((tid + 1) % cpcount, &cpus);
+ dt_setaffinity(thread, &cpus, sizeof(cpu_set_t));
+ }
+#endif
/* Loop until all data is read. */
ssize_t n = 0;
diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index 2ba2417..f850642 100644
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -763,7 +763,14 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
}
/* Free data updated in this processing. */
- evqueue_write(nextw->q, data, sizeof(knot_ns_xfr_t));
+ ret = evqueue_write(nextw->q, data, sizeof(knot_ns_xfr_t));
+ if (ret != sizeof(knot_ns_xfr_t)) {
+ char ebuf[256] = {0};
+ strerror_r(errno, ebuf, sizeof(ebuf));
+ dbg_xfr("xfr: couldn't write request to evqueue: %s\n",
+ ebuf);
+ return KNOTD_ERROR;
+ }
return KNOTD_EOK;
} else {
zd->xfr_in.wrkr = w;
@@ -872,10 +879,10 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
/* Start transfer. */
ret = data->send(data->session, &data->addr, data->wire, bufsize);
if (ret != bufsize) {
- char buf[1024];
- strerror_r(errno, buf, sizeof(buf));
+ char ebuf[256] = {0};
+ strerror_r(errno, ebuf, sizeof(ebuf));
log_server_info("%s Failed to send query (%s).\n",
- data->msgpref, buf);
+ data->msgpref, ebuf);
pthread_mutex_unlock(&zd->xfr_in.lock);
close(data->session);
data->session = -1;
diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c
index 3de4a6a..6a710d4 100644
--- a/src/knot/server/zones.c
+++ b/src/knot/server/zones.c
@@ -167,19 +167,9 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
/* Initialize IXFR database. */
zd->ixfr_db = journal_open(cfg->ixfr_db, cfg->ixfr_fslimit,
JOURNAL_LAZY, JOURNAL_DIRTY);
- if (!zd->ixfr_db) {
- int ret = journal_create(cfg->ixfr_db, JOURNAL_NCOUNT);
- if (ret != KNOTD_EOK) {
- log_server_warning("Failed to create journal file "
- "'%s' (%s)\n", cfg->ixfr_db,
- knotd_strerror(ret));
- }
- zd->ixfr_db = journal_open(cfg->ixfr_db, cfg->ixfr_fslimit,
- JOURNAL_LAZY, JOURNAL_DIRTY);
- }
if (zd->ixfr_db == NULL) {
- char ebuf[128] = {0};
+ char ebuf[256] = {0};
strerror_r(errno, ebuf, sizeof(ebuf));
log_server_warning("Couldn't open journal file for zone '%s', "
"disabling IXFR/IN. (%s)\n", cfg->name, ebuf);
@@ -497,7 +487,7 @@ static int zones_refresh_ev(event_t *e)
/* Create query. */
int sock = -1;
- char strbuf[512] = "Generic error.";
+ char strbuf[256] = "Generic error.";
const char *errstr = strbuf;
sockaddr_t *master = &zd->xfr_in.master;
int ret = xfrin_create_soa_query(zone->name, &xfr_req, &buflen);
@@ -529,6 +519,7 @@ static int zones_refresh_ev(event_t *e)
if (sent == buflen) {
ret = KNOTD_EOK;
} else {
+ strbuf[0] = '\0';
strerror_r(errno, strbuf, sizeof(strbuf));
socket_close(sock);
sock = -1;
@@ -807,7 +798,7 @@ static int zones_set_acl(acl_t **acl, list* acl_list)
/*!
* \brief Load zone to zone database.
*
- * \param zonedb Zone database to load the zone into.
+ * \param dst Loaded zone will be returned in this parameter.
* \param zone_name Zone name (owner of the apex node).
* \param source Path to zone file source.
* \param filename Path to requested compiled zone file.
@@ -816,10 +807,14 @@ static int zones_set_acl(acl_t **acl, list* acl_list)
* \retval KNOTD_EINVAL
* \retval KNOTD_EZONEINVAL
*/
-static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
+static int zones_load_zone(knot_zone_t **dst, const char *zone_name,
const char *source, const char *filename)
{
- knot_zone_t *zone = NULL;
+ if (dst == NULL) {
+ return KNOTD_EINVAL;
+ }
+ *dst = NULL;
+
size_t zlen = strlen(zone_name);
char *zname = NULL;
if (zlen > 0) {
@@ -835,7 +830,7 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
/* Check if the compiled file still exists. */
struct stat st;
if (stat(source, &st) != 0) {
- char reason[1024];
+ char reason[256] = {0};
strerror_r(errno, reason, sizeof(reason));
log_server_warning("Failed to open zone file '%s' (%s).\n",
zname, reason);
@@ -893,18 +888,17 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
zname);
}
- zone = knot_zload_load(zl);
+ *dst = knot_zload_load(zl);
/* Check loaded name. */
- const knot_dname_t *dname = knot_zone_name(zone);
+ const knot_dname_t *dname = knot_zone_name(*dst);
knot_dname_t *dname_req = 0;
dname_req = knot_dname_new_from_str(zone_name, zlen, 0);
if (knot_dname_compare(dname, dname_req) != 0) {
log_server_warning("Origin of the zone db file is "
"different than '%s'\n",
zone_name);
- knot_zone_deep_free(&zone, 0);
- zone = 0;
+ knot_zone_deep_free(dst, 0);
}
knot_dname_free(&dname_req);
@@ -914,26 +908,21 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
// int errs = knot_zone_contents_integrity_check(zone->contents);
// fprintf(stderr, "INTEGRITY CHECK OF ZONE. ERRORS: %d\n", errs);
- if (zone) {
+ if (*dst != NULL) {
/* save the timestamp from the zone db file */
struct stat s;
if (stat(filename, &s) < 0) {
dbg_zones("zones: failed to stat() zone db, "
"something is seriously wrong\n");
- knot_zone_deep_free(&zone, 0);
- zone = 0;
+ knot_zone_deep_free(dst, 0);
} else {
- knot_zone_set_version(zone, s.st_mtime);
- if (knot_zonedb_add_zone(zonedb, zone) != 0){
- knot_zone_deep_free(&zone, 0);
- zone = 0;
- }
+ knot_zone_set_version(*dst, s.st_mtime);
}
}
knot_zload_close(zl);
- if (!zone) {
+ if (*dst == NULL) {
log_server_error("Failed to load "
"db '%s' for zone '%s'.\n",
filename, zname);
@@ -1146,6 +1135,9 @@ static int zones_load_changesets(const knot_zone_t *zone,
/* Retain journal for changeset loading. */
journal_t *j = journal_retain(zd->ixfr_db);
+ if (j == NULL) {
+ return KNOTD_EBUSY;
+ }
/* Read entries from starting serial until finished. */
uint32_t found_to = from;
@@ -1330,213 +1322,342 @@ static int zones_journal_apply(knot_zone_t *zone)
}
/*----------------------------------------------------------------------------*/
+
/*!
- * \brief Fill the new database with zones.
+ * \brief Insert new zone to the database.
*
* Zones that should be retained are just added from the old database to the
* new. New zones are loaded.
*
+ * \param z Zone configuration.
+ * \param dst Used for returning new/updated zone.
* \param ns Name server instance.
- * \param zone_conf Zone configuration.
* \param db_old Old zone database.
- * \param db_new New zone database.
*
- * \return Number of inserted zones.
+ * \retval KNOTD_EOK if successful.
+ * \retval KNOTD_EINVAL on invalid parameters.
+ * \retval KNOTD_ENOENT if zone has no contents.
+ * \retval KNOTD_ERROR on unspecified error.
*/
-static int zones_insert_zones(knot_nameserver_t *ns,
- const list *zone_conf,
- const knot_zonedb_t *db_old,
- knot_zonedb_t *db_new)
+static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
+ knot_nameserver_t *ns, const knot_zonedb_t *db_old)
{
- /*! \todo Change to zone contents. */
+ if (z == NULL || dst == NULL || ns == NULL || db_old == NULL) {
+ return KNOTD_EINVAL;
+ }
+
+ /* Convert the zone name into a domain name. */
+ /* Local allocation, will be discarded. */
+ knot_dname_t *dname = knot_dname_new_from_str(z->name, strlen(z->name),
+ NULL);
+ if (dname == NULL) {
+ log_server_error("Error creating domain name from zone"
+ " name\n");
+ return KNOTD_EINVAL;
+ }
- node *n = 0;
- int inserted = 0;
- /* for all zones in the configuration */
- WALK_LIST(n, *zone_conf) {
- conf_zone_t *z = (conf_zone_t *)n;
-
- /* Convert the zone name into a domain name. */
- /* Local allocation, will be discarded. */
- knot_dname_t *zone_name = knot_dname_new_from_str(z->name,
- strlen(z->name), NULL);
- if (zone_name == NULL) {
- log_server_error("Error creating domain name from zone"
- " name\n");
- return inserted;
- }
+ /* Try to find the zone in the current zone db. */
+ knot_zone_t *zone = knot_zonedb_find_zone(db_old, dname);
- dbg_zones_verb("zones: inserting zone %s into the new database.\n",
- z->name);
+ /* Attempt to bootstrap if db or source does not exist. */
+ int zone_changed = 0;
+ struct stat s = {};
+ int stat_ret = stat(z->file, &s);
+ if (zone != NULL && stat_ret == 0) {
+ /* if found, check timestamp of the file against the
+ * loaded zone
+ */
+ if (knot_zone_version(zone) < s.st_mtime) {
+ zone_changed = 1;
+ }
+ } else {
+ zone_changed = 1;
+ }
- /* try to find the zone in the current zone db */
- knot_zone_t *zone = knot_zonedb_find_zone(db_old,
- zone_name);
- int reload = 0;
+ /* Reload zone file. */
+ int ret = KNOTD_ERROR;
+ if (zone_changed) {
+ /* Zone file not exists and has master set. */
+ if (stat_ret < 0 && !EMPTY_LIST(z->acl.xfr_in)) {
- /* Attempt to bootstrap if db or source does not exist. */
- struct stat s = {};
- int stat_ret = stat(z->file, &s);
- if (zone != NULL && stat_ret == 0) {
- /* if found, check timestamp of the file against the
- * loaded zone
- */
- if (knot_zone_version(zone) < s.st_mtime) {
- /* the file is newer, reload! */
- reload = 1;
+ /* Create stub database. */
+ dbg_zones_verb("zones: loading stub zone '%s' "
+ "for bootstrap.\n",
+ z->name);
+ knot_dname_t *owner = knot_dname_deep_copy(dname);
+ zone = knot_zone_new_empty(owner);
+ if (zone != NULL) {
+ ret = KNOTD_EOK;
+ log_server_info("Will attempt to bootstrap zone"
+ " %s from AXFR master.\n",
+ z->name);
+ } else {
+ dbg_zones("zones: failed to create "
+ "stub zone '%s'.\n", z->name);
+ ret = KNOTD_ERROR;
}
} else {
- reload = 1;
- }
-
- /* Reload zone file. */
- int ret = KNOTD_ERROR;
- if (reload) {
- /* Zone file not exists and has master set. */
- if (stat_ret < 0 && !EMPTY_LIST(z->acl.xfr_in)) {
-
- /* Create stub database. */
- dbg_zones_verb("zones: loading stub zone '%s' "
- "for bootstrap.\n",
- z->name);
- knot_dname_t *owner = 0;
- owner = knot_dname_deep_copy(zone_name);
- knot_zone_t* sz = knot_zone_new_empty(owner);
- if (sz) {
- /* Add stub zone to db_new. */
- ret = knot_zonedb_add_zone(db_new, sz);
- if (ret != KNOT_EOK) {
- dbg_zones("zones: failed to add "
- "stub zone '%s'.\n",
- z->name);
- knot_zone_deep_free(&sz, 0);
- sz = 0;
- ret = KNOTD_ERROR;
- } else {
- log_server_info("Will attempt to "
- "bootstrap zone "
- "%s from AXFR "
- "master.\n",
- z->name);
- --inserted;
- }
-
- } else {
- dbg_zones("zones: failed to create "
- "stub zone '%s'.\n",
- z->name);
- ret = KNOTD_ERROR;
- }
-
- } else {
- dbg_zones_verb("zones: loading zone '%s' "
- "from '%s'\n",
- z->name,
- z->db);
- ret = zones_load_zone(db_new, z->name,
- z->file, z->db);
- if (ret == KNOTD_EOK) {
- log_server_info("Loaded zone '%s'\n",
- z->name);
- }
+ dbg_zones_verb("zones: loading zone '%s' from '%s'\n",
+ z->name, z->db);
+ ret = zones_load_zone(&zone, z->name, z->file, z->db);
+ if (ret == KNOTD_EOK) {
+ log_server_info("Loaded zone '%s'\n",
+ z->name);
}
+ }
- /* Find zone. */
- if (ret == KNOTD_EOK) {
- /* Find the new zone */
- zone = knot_zonedb_find_zone(db_new,
- zone_name);
- ++inserted;
-
- dbg_zones_verb("zones: inserted '%s' into "
- "database, initializing data\n",
- z->name);
+ /* Evaluate. */
+ if (ret == KNOTD_EOK && zone != NULL) {
+ dbg_zones_verb("zones: inserted '%s' into "
+ "database, initializing data\n",
+ z->name);
- /* Initialize zone-related data. */
- zonedata_init(z, zone);
+ /* Initialize zone-related data. */
+ zonedata_init(z, zone);
+ *dst = zone;
+ }
+ } else {
+ dbg_zones_verb("zones: found '%s' in old database, "
+ "copying to new.\n", z->name);
+ if (stat_ret == 0) {
+ log_server_info("Zone '%s' is up-to-date, no need "
+ "for reload.\n", z->name);
+ }
+ *dst = zone;
+ ret = KNOTD_EOK;
+ }
+
+ /* Update zone data. */
+ if (zone != NULL) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
+ assert(zd != NULL);
+
+ /* Update refs. */
+ zd->conf = z;
+
+ /* Update ACLs. */
+ dbg_zones("Updating zone ACLs.\n");
+ zones_set_acl(&zd->xfr_in.acl, &z->acl.xfr_in);
+ zones_set_acl(&zd->xfr_out, &z->acl.xfr_out);
+ zones_set_acl(&zd->notify_in, &z->acl.notify_in);
+ zones_set_acl(&zd->notify_out, &z->acl.notify_out);
+
+ /* Update server pointer. */
+ zd->server = (server_t *)knot_ns_get_data(ns);
+
+ /* Update master server address. */
+ memset(&zd->xfr_in.tsig_key, 0, sizeof(knot_key_t));
+ sockaddr_init(&zd->xfr_in.master, -1);
+ sockaddr_init(&zd->xfr_in.via, -1);
+ if (!EMPTY_LIST(z->acl.xfr_in)) {
+ conf_remote_t *r = HEAD(z->acl.xfr_in);
+ conf_iface_t *cfg_if = r->remote;
+ sockaddr_set(&zd->xfr_in.master,
+ cfg_if->family,
+ cfg_if->address,
+ cfg_if->port);
+ if (sockaddr_isvalid(&cfg_if->via)) {
+ sockaddr_copy(&zd->xfr_in.via,
+ &cfg_if->via);
}
- /* unused return value, if not loaded, just continue */
- } else {
- /* just insert the zone into the new zone db */
- dbg_zones_verb("zones: found '%s' in old database, "
- "copying to new.\n",
- z->name);
- /* Only if zone file exists. */
- if (stat_ret == 0) {
- log_server_info("Zone '%s' is up-to-date, no need "
- "for reload.\n", z->name);
- }
- int ret = knot_zonedb_add_zone(db_new, zone);
- if (ret != KNOT_EOK) {
- log_server_error("Error adding known zone '%s' to"
- " the new database - %s\n",
- z->name, knot_strerror(ret));
- } else {
- ++inserted;
+
+ if (cfg_if->key) {
+ memcpy(&zd->xfr_in.tsig_key,
+ cfg_if->key,
+ sizeof(knot_key_t));
}
+
+ dbg_zones("zones: using '%s@%d' as XFR master "
+ "for '%s'\n",
+ cfg_if->address,
+ cfg_if->port,
+ z->name);
}
- /* Update zone data. */
- if (zone) {
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
-
- /* Update refs. */
- zd->conf = z;
-
- /* Update ACLs. */
- dbg_zones("Updating zone ACLs.\n");
- zones_set_acl(&zd->xfr_in.acl, &z->acl.xfr_in);
- zones_set_acl(&zd->xfr_out, &z->acl.xfr_out);
- zones_set_acl(&zd->notify_in, &z->acl.notify_in);
- zones_set_acl(&zd->notify_out, &z->acl.notify_out);
-
- /* Update server pointer. */
- zd->server = (server_t *)knot_ns_get_data(ns);
-
- /* Update master server address. */
- memset(&zd->xfr_in.tsig_key, 0, sizeof(knot_key_t));
- sockaddr_init(&zd->xfr_in.master, -1);
- sockaddr_init(&zd->xfr_in.via, -1);
- if (!EMPTY_LIST(z->acl.xfr_in)) {
- conf_remote_t *r = HEAD(z->acl.xfr_in);
- conf_iface_t *cfg_if = r->remote;
- sockaddr_set(&zd->xfr_in.master,
- cfg_if->family,
- cfg_if->address,
- cfg_if->port);
- if (sockaddr_isvalid(&cfg_if->via)) {
- sockaddr_copy(&zd->xfr_in.via,
- &cfg_if->via);
- }
+ /* Apply changesets from journal. */
+ zones_journal_apply(zone);
- if (cfg_if->key) {
- memcpy(&zd->xfr_in.tsig_key,
- cfg_if->key,
- sizeof(knot_key_t));
- }
+ /* Update events scheduled for zone. */
+ evsched_t *sch = ((server_t *)knot_ns_get_data(ns))->sched;
+ zones_timers_update(zone, z, sch);
+
+ /* Schedule IXFR database syncing. */
+ /*! \note This has to remain separate as it must not be
+ * triggered by a zone update or SOA response.
+ */
+ /* Fetch zone data. */
+ int sync_tmr = z->dbsync_timeout * 1000; /* s -> ms. */
+ if (zd->ixfr_dbsync != NULL) {
+ evsched_cancel(sch, zd->ixfr_dbsync);
+ evsched_event_free(sch, zd->ixfr_dbsync);
+ zd->ixfr_dbsync = NULL;
+ }
+ if (zd->ixfr_db != NULL) {
+ zd->ixfr_dbsync = evsched_schedule_cb(
+ sch, zones_zonefile_sync_ev,
+ zone, sync_tmr);
+ dbg_zones("zone: journal sync of '%s' "
+ "set to %d\n", z->name, sync_tmr);
+ }
- dbg_zones("zones: using '%s@%d' as XFR master "
- "for '%s'\n",
- cfg_if->address,
- cfg_if->port,
- z->name);
+ /* Update ANY queries policy */
+ if (zd->conf->disable_any) {
+ knot_zone_contents_t *contents =
+ knot_zone_get_contents(zone);
+ if (contents) {
+ knot_zone_contents_disable_any(contents);
}
-
- /* Apply changesets from journal. */
- zones_journal_apply(zone);
-
- /* Update events scheduled for zone. */
- zones_timers_update(zone, z,
- ((server_t *)knot_ns_get_data(ns))->sched);
}
+ }
- /* CLEANUP */
+ /* CLEANUP */
// knot_zone_contents_dump(knot_zone_get_contents(zone), 1);
- /* Directly discard zone. */
- knot_dname_free(&zone_name);
+ /* Directly discard zone. */
+ knot_dname_free(&dname);
+ return ret;
+}
+
+/*! \brief Structure for multithreaded zone loading. */
+struct zonewalk_t {
+ knot_nameserver_t *ns;
+ const knot_zonedb_t *db_old;
+ knot_zonedb_t *db_new;
+ pthread_mutex_t lock;
+ int inserted;
+ unsigned qhead;
+ unsigned qtail;
+ conf_zone_t *q[];
+
+};
+
+/*! Thread entrypoint for loading zones. */
+static int zonewalker(dthread_t *thread)
+{
+ if (thread == NULL) {
+ return KNOTD_ERROR;
+ }
+
+ struct zonewalk_t *zw = (struct zonewalk_t *)thread->data;
+ if (zw == NULL) {
+ return KNOTD_ERROR;
}
+
+ unsigned i = 0;
+ int inserted = 0;
+ knot_zone_t **zones = NULL;
+ size_t allocd = 0;
+ for(;;) {
+ /* Fetch queue head. */
+ pthread_mutex_lock(&zw->lock);
+ i = zw->qhead++;
+ pthread_mutex_unlock(&zw->lock);
+ if (i >= zw->qtail) {
+ break;
+ }
+
+ if (mreserve((char **)&zones, sizeof(knot_zone_t*),
+ inserted + 1, 32, &allocd) < 0) {
+ dbg_zones("zones: failed to reserve space for "
+ "loading zones\n");
+ continue;
+ }
+
+ int ret = zones_insert_zone(zw->q[i], zones + inserted, zw->ns,
+ zw->db_old);
+ if (ret == KNOTD_EOK) {
+ ++inserted;
+ }
+ }
+
+ /* Collect results. */
+ pthread_mutex_lock(&zw->lock);
+ zw->inserted += inserted;
+ for (int i = 0; i < inserted; ++i) {
+ if (knot_zonedb_add_zone(zw->db_new, zones[i]) != KNOT_EOK) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(zones[i]);
+ log_server_error("Failed to insert zone '%s' "
+ "into database.\n", zd->conf->name);
+ knot_zone_deep_free(zones + i, 0);
+ }
+ }
+ pthread_mutex_unlock(&zw->lock);
+ free(zones);
+
+ return KNOTD_EOK;
+}
+
+/*!
+ * \brief Fill the new database with zones.
+ *
+ * Zones that should be retained are just added from the old database to the
+ * new. New zones are loaded.
+ *
+ * \param ns Name server instance.
+ * \param zone_conf Zone configuration.
+ * \param db_old Old zone database.
+ * \param db_new New zone database.
+ *
+ * \return Number of inserted zones.
+ */
+static int zones_insert_zones(knot_nameserver_t *ns,
+ const list *zone_conf,
+ const knot_zonedb_t *db_old,
+ knot_zonedb_t *db_new)
+{
+ int inserted = 0;
+ size_t zcount = 0;
+ conf_zone_t *z = NULL;
+ WALK_LIST(z, *zone_conf) {
+ ++zcount;
+ }
+
+ /* Initialize zonewalker. */
+ size_t zwlen = sizeof(struct zonewalk_t) + zcount * sizeof(conf_zone_t*);
+ struct zonewalk_t *zw = malloc(zwlen);
+ if (zw != NULL) {
+ memset(zw, 0, zwlen);
+ zw->ns = ns;
+ zw->db_old = db_old;
+ zw->db_new = db_new;
+ zw->inserted = 0;
+ if (pthread_mutex_init(&zw->lock, NULL) < 0) {
+ free(zw);
+ zw = NULL;
+ } else {
+ unsigned i = 0;
+ WALK_LIST(z, *zone_conf) {
+ zw->q[i++] = z;
+ }
+ zw->qhead = 0;
+ zw->qtail = zcount;
+ }
+ }
+
+ /* Initialize threads. */
+ dt_unit_t *unit = NULL;
+ if (zw != NULL) {
+ unit = dt_create_coherent(dt_optimal_size(), &zonewalker, zw);
+ }
+ /* Single-thread fallback. */
+ if (unit == NULL) {
+ log_server_error("Couldn't initialize zone loading - %s\n",
+ knotd_strerror(KNOTD_ENOMEM));
+ return 0;
+ }
+
+ /* Start loading. */
+ dt_start(unit);
+
+ /* Wait for finish. */
+ dt_join(unit);
+ dt_delete(&unit);
+
+ /* Collect counts. */
+ inserted = zw->inserted;
+ pthread_mutex_destroy(&zw->lock);
+ free(zw);
return inserted;
}
@@ -1838,6 +1959,9 @@ int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal)
if (!zone->data) {
return KNOTD_EINVAL;
}
+ if (journal == NULL) {
+ return KNOTD_EINVAL;
+ }
/* Fetch zone data. */
int ret = KNOTD_EOK;
@@ -1896,8 +2020,8 @@ int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal)
zd->conf->name, serial_to);
zd->zonefile_serial = serial_to;
} else {
- dbg_zones_verb("zones: '%s' zonefile is in sync "
- "with differences\n", zd->conf->name);
+ dbg_zones("zones: '%s' zonefile is in sync "
+ "with differences\n", zd->conf->name);
ret = KNOTD_ERANGE;
}
@@ -2029,15 +2153,15 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
dbg_zones_verb("Failed preparing response structure: %s.\n",
knot_strerror(rcode));
if (resp == NULL) {
- knot_ns_error_response(nameserver, knot_packet_id(query),
- rcode, resp_wire, rsize);
+ knot_ns_error_response(nameserver,
+ knot_packet_id(query),
+ &query->header.flags1,
+ rcode, resp_wire, rsize);
rcu_read_unlock();
return KNOT_EOK;
}
knot_ns_error_response_full(nameserver, resp, rcode, resp_wire,
rsize);
-// knot_ns_error_response(nameserver, knot_packet_id(query),
-// rcode, resp_wire, rsize);
} else {
/*
* Now we have zone. Verify TSIG if it is in the packet.
@@ -2416,7 +2540,16 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
return KNOTD_ERROR;
}
- if (zone_dump_text(zone, fd) != KNOTD_EOK) {
+ FILE *f = fdopen(fd, "w");
+ if (f == NULL) {
+ log_zone_warning("Failed to open file descriptor for text zone.\n");
+ close(fd);
+ unlink(new_fname);
+ free(new_fname);
+ return KNOTD_ERROR;
+ }
+
+ if (zone_dump_text(zone, f) != KNOTD_EOK) {
log_zone_warning("Failed to save the transferred zone to '%s'.\n",
new_fname);
close(fd);
@@ -2426,7 +2559,7 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
}
/* Swap temporary zonefile and new zonefile. */
- close(fd);
+ fclose(f);
int ret = rename(new_fname, fname);
if (ret < 0 && ret != EEXIST) {
log_zone_warning("Failed to replace old zone file '%s'' with a new"
@@ -3034,20 +3167,6 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
cfzone->name, refresh_tmr);
}
- /* Schedule IXFR database syncing. */
- /*! \todo Sync timer should not be reset after each xfr (issue #1348) */
- int sync_timeout = cfzone->dbsync_timeout * 1000; /* Convert to ms. */
- if (zd->ixfr_dbsync) {
- evsched_cancel(sch, zd->ixfr_dbsync);
- evsched_event_free(sch, zd->ixfr_dbsync);
- zd->ixfr_dbsync = 0;
- }
- if (zd->ixfr_db) {
- zd->ixfr_dbsync = evsched_schedule_cb(sch,
- zones_zonefile_sync_ev,
- zone, sync_timeout);
- }
-
/* Do not issue NOTIFY queries if stub. */
if (!knot_zone_contents(zone)) {
conf_read_unlock();
diff --git a/src/knot/zone/zone-dump-text.c b/src/knot/zone/zone-dump-text.c
index 2d0b9c0..bc606d3 100644
--- a/src/knot/zone/zone-dump-text.c
+++ b/src/knot/zone/zone-dump-text.c
@@ -1119,9 +1119,8 @@ void node_dump_text(knot_node_t *node, void *data)
free(rrsets);
}
-int zone_dump_text(knot_zone_contents_t *zone, int fd)
+int zone_dump_text(knot_zone_contents_t *zone, FILE *f)
{
- FILE *f = fdopen(fd, "w");
if (f == NULL) {
return KNOT_EBADARG;
}
@@ -1134,7 +1133,6 @@ int zone_dump_text(knot_zone_contents_t *zone, int fd)
param.origin = knot_node_owner(knot_zone_contents_apex(zone));
knot_zone_contents_tree_apply_inorder(zone, node_dump_text, &param);
knot_zone_contents_nsec3_apply_inorder(zone, node_dump_text, &param);
- fclose(f);
return KNOT_EOK;
}
diff --git a/src/knot/zone/zone-dump-text.h b/src/knot/zone/zone-dump-text.h
index 2a35643..9f9c8dd 100644
--- a/src/knot/zone/zone-dump-text.h
+++ b/src/knot/zone/zone-dump-text.h
@@ -34,12 +34,12 @@
* \brief Dumps given zone to text (BIND-like) file.
*
* \param zone Zone to be saved.
- * \param fd File descriptor to write to.
+ * \param File file to write to.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EBADARG if the specified file is not valid for writing.
*/
-int zone_dump_text(knot_zone_contents_t *zone, int fd);
+int zone_dump_text(knot_zone_contents_t *zone, FILE *f);
#endif // _KNOT_ZONE_DUMP_TEXT_H_
diff --git a/src/knot/zone/zone-dump.c b/src/knot/zone/zone-dump.c
index 31be9b0..aaf0165 100644
--- a/src/knot/zone/zone-dump.c
+++ b/src/knot/zone/zone-dump.c
@@ -62,7 +62,7 @@ static inline int write_to_file_crc(const void *src,
}
ssize_t rc = write(fd, src, size * n);
if (rc != size * n) {
- fprintf(stderr, "write: invalid write %zu (expected %zu)\n", rc,
+ fprintf(stderr, "write: invalid write %zd (expected %zu)\n", rc,
n);
}
@@ -1058,11 +1058,10 @@ int knot_zdump_binary(knot_zone_contents_t *zone, int fd,
/* Finish the dump. */
if (!write_to_file_crc(buffer, 1, written_bytes, fd, crc)) {
- dbg_zdump("zdump: Failed to finalize dump.\n");
+ fprintf(stderr, "Failed to finalize zone db!\n");
return KNOT_ERROR;
}
-
*crc = crc_finalize(*crc);
dbg_zdump("zdump: Zone %p dumped successfully.\n", zone);
diff --git a/src/knot/zone/zone-dump.h b/src/knot/zone/zone-dump.h
index 46e760e..fbebae9 100644
--- a/src/knot/zone/zone-dump.h
+++ b/src/knot/zone/zone-dump.h
@@ -38,7 +38,7 @@ enum {
};
/*! \brief Magic identifier: { "knot", maj_ver, min_ver, revision } */
-#define MAGIC_BYTES {'k', 'n', 'o', 't', '1', '0', '0'}
+#define MAGIC_BYTES {'k', 'n', 'o', 't', '1', '0', '4'}
/*!
* \brief Dumps given zone to binary file.
diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c
index b8c9beb..3a7134e 100644
--- a/src/knot/zone/zone-load.c
+++ b/src/knot/zone/zone-load.c
@@ -260,9 +260,15 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
knot_rdata_item_t *items =
malloc(sizeof(knot_rdata_item_t) * rdata_count);
+ if (items == NULL) {
+ ERR_ALLOC_FAILED;
+ free(items);
+ return NULL;
+ }
- if (desc->fixed_items) {
- assert(desc->length == rdata_count);
+ if (rdata_count > desc->length) {
+ dbg_zload("zload: load_rdata: Read wrong count of RDATA.\n");
+ return NULL;
}
uint16_t raw_data_length = 0;
@@ -347,8 +353,8 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
}
/*!< \todo this is not proper fix, see #1678 */
- items[i].raw_data = (uint16_t *)
- malloc(sizeof(uint8_t) * (raw_data_length + 2));
+ items[i].raw_data =
+ malloc(raw_data_length + 2);
if (items[i].raw_data == NULL) {
ERR_ALLOC_FAILED;
load_rdata_purge(rdata, items, i + 1, desc,
@@ -908,16 +914,7 @@ int knot_zload_open(zloader_t **dst, const char *filename)
/* Free some value and close the CRC file */
free(crc_path);
close(f_crc);
-
- /* Compare calculated and read CRCs. */
- if (crc_from_file != crc_calculated) {
- dbg_zload("knot_zload_open: CRC failed for "
- "file '%s'\n",
- filename);
- fclose(f);
- return KNOT_ECRC;
- }
-
+
/* Check magic sequence. */
static const uint8_t MAGIC[MAGIC_LENGTH] = MAGIC_BYTES;
if (!knot_check_magic(f, MAGIC, MAGIC_LENGTH)) {
@@ -929,6 +926,15 @@ int knot_zload_open(zloader_t **dst, const char *filename)
return KNOT_EMALF; // Illegal byte sequence (POSIX.1, C99)
}
+ /* Compare calculated and read CRCs. */
+ if (crc_from_file != crc_calculated) {
+ dbg_zload("knot_zload_open: CRC failed for "
+ "file '%s'\n",
+ filename);
+ fclose(f);
+ return KNOT_ECRC;
+ }
+
/* Read source file length. */
uint32_t sflen = 0;
if (!fread_wrapper(&sflen, 1, sizeof(uint32_t), f)) {
diff --git a/src/libknot/dname.c b/src/libknot/dname.c
index 7a6ea5a..80de030 100644
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -263,16 +263,21 @@ static int knot_dname_find_labels(knot_dname_t *dname, int alloc)
uint8_t labels[KNOT_MAX_DNAME_LABELS];
short label_count = 0;
- while (pos - name < size && *pos != '\0') {
+ while (pos - name < size && *pos != '\0' && label_count < KNOT_MAX_DNAME_LABELS ) {
labels[label_count++] = pos - name;
pos += *pos + 1;
}
// TODO: how to check if the domain name has right format?
- if (pos - name > size || *pos != '\0') {
+ if (label_count == KNOT_MAX_DNAME_LABELS) {
dbg_dname("Wrong wire format of domain name!\n");
- dbg_dname("Position: %d, character: %d, expected"
- " size: %d\n", pos - name, *pos, size);
+ dbg_dname("Too many labels: %s\n", name);
+ return -1;
+ }
+
+ if (pos - name > size || *pos != '\0' ) {
+ dbg_dname("Wrong wire format of domain name!\n");
+ dbg_dname("Position: %d, character: %d, expected size: %d\n", pos - name, *pos, size);
return -1;
}
diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c
index 213534c..d938683 100644
--- a/src/libknot/nameserver/name-server.c
+++ b/src/libknot/nameserver/name-server.c
@@ -1827,7 +1827,8 @@ have_node:
goto finalize;
}
- if (knot_node_rrset(node, KNOT_RRTYPE_CNAME) != NULL) {
+ if (knot_node_rrset(node, KNOT_RRTYPE_CNAME) != NULL
+ && qtype != KNOT_RRTYPE_CNAME) {
dbg_ns_exec(
char *name = knot_dname_to_str(node->owner);
dbg_ns("Node %s has CNAME record, resolving...\n",
@@ -2841,17 +2842,25 @@ int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
/*----------------------------------------------------------------------------*/
-void knot_ns_error_response(const knot_nameserver_t *nameserver, uint16_t query_id,
- uint8_t rcode, uint8_t *response_wire, size_t *rsize)
+void knot_ns_error_response(const knot_nameserver_t *nameserver,
+ uint16_t query_id, uint8_t *flags1_query,
+ uint8_t rcode, uint8_t *response_wire,
+ size_t *rsize)
{
- //dbg_ns("Error response: \n");
- //dbg_ns_hex((const char *)nameserver->err_response,
- // nameserver->err_resp_size);
-
memcpy(response_wire, nameserver->err_response,
nameserver->err_resp_size);
- // copy ID of the query
+
+ // copy only the ID of the query
knot_wire_set_id(response_wire, query_id);
+
+ if (flags1_query != NULL) {
+ if (knot_wire_flags_get_rd(*flags1_query) != 0) {
+ knot_wire_set_rd(response_wire);
+ }
+ knot_wire_set_opcode(response_wire,
+ knot_wire_flags_get_opcode(*flags1_query));
+ }
+
// set the RCODE
knot_wire_set_rcode(response_wire, rcode);
*rsize = nameserver->err_resp_size;
@@ -2859,6 +2868,33 @@ void knot_ns_error_response(const knot_nameserver_t *nameserver, uint16_t query_
/*----------------------------------------------------------------------------*/
+int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver,
+ const uint8_t *query, size_t size,
+ uint8_t rcode, uint8_t *response_wire,
+ size_t *rsize)
+{
+ if (size < 2) {
+ // ignore packet
+ return KNOT_EFEWDATA;
+ }
+
+ uint16_t pkt_id = knot_wire_get_id(query);
+
+ uint8_t *flags1_ptr = NULL;
+ uint8_t flags1;
+
+ if (size > KNOT_WIRE_OFFSET_FLAGS1) {
+ flags1 = knot_wire_get_flags1(query);
+ flags1_ptr = &flags1;
+ }
+ knot_ns_error_response(nameserver, pkt_id, flags1_ptr,
+ rcode, response_wire, rsize);
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
void knot_ns_error_response_full(knot_nameserver_t *nameserver,
knot_packet_t *response, uint8_t rcode,
uint8_t *response_wire, size_t *rsize)
@@ -2868,6 +2904,7 @@ void knot_ns_error_response_full(knot_nameserver_t *nameserver,
if (ns_error_response_to_wire(response, response_wire, rsize) != 0) {
knot_ns_error_response(nameserver, knot_packet_id(
knot_packet_query(response)),
+ &response->header.flags1,
KNOT_RCODE_SERVFAIL, response_wire,
rsize);
}
@@ -3039,9 +3076,10 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
dbg_ns("Failed to parse rest of the query: %s\n",
knot_strerror(ret));
knot_ns_error_response(nameserver, xfr->query->header.id,
- (ret == KNOT_EMALF) ? KNOT_RCODE_FORMERR
- : KNOT_RCODE_SERVFAIL,
- xfr->wire, &xfr->wire_size);
+ &xfr->query->header.flags1,
+ (ret == KNOT_EMALF) ? KNOT_RCODE_FORMERR
+ : KNOT_RCODE_SERVFAIL,
+ xfr->wire, &xfr->wire_size);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
return ret;
@@ -3057,8 +3095,9 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
dbg_ns("Failed to create packet structure.\n");
/*! \todo xfr->wire is not NULL, will fail on assert! */
knot_ns_error_response(nameserver, xfr->query->header.id,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ &xfr->query->header.flags1,
+ KNOT_RCODE_SERVFAIL, xfr->wire,
+ &xfr->wire_size);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
knot_packet_free(&response);
@@ -3087,8 +3126,9 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
dbg_ns("Failed to init response structure.\n");
/*! \todo xfr->wire is not NULL, will fail on assert! */
knot_ns_error_response(nameserver, xfr->query->header.id,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ &xfr->query->header.flags1,
+ KNOT_RCODE_SERVFAIL, xfr->wire,
+ &xfr->wire_size);
int res = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
knot_packet_free(&response);
@@ -3205,6 +3245,7 @@ int knot_ns_xfr_send_error(const knot_nameserver_t *nameserver,
if ((ret = ns_xfr_send_and_clear(xfr, 1)) != KNOT_EOK) {
size_t size = 0;
knot_ns_error_response(nameserver, xfr->query->header.id,
+ &xfr->query->header.flags1,
KNOT_RCODE_SERVFAIL, xfr->wire, &size);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire, size);
}
@@ -3229,8 +3270,9 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
dbg_ns("AXFR failed on stub zone\n");
/*! \todo replace with knot_ns_xfr_send_error() */
knot_ns_error_response(nameserver, xfr->query->header.id,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ &xfr->query->header.flags1,
+ KNOT_RCODE_SERVFAIL, xfr->wire,
+ &xfr->wire_size);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
rcu_read_unlock();
@@ -3263,8 +3305,9 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
/*! \todo xfr->wire is not NULL, will fail on assert! */
/*! \todo replace with knot_ns_xfr_send_error() */
knot_ns_error_response(nameserver, xfr->query->header.id,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ &xfr->query->header.flags1,
+ KNOT_RCODE_SERVFAIL, xfr->wire,
+ &xfr->wire_size);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
} else if (ret > 0) {
@@ -3576,6 +3619,7 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
MAX_UDP_PAYLOAD);
if (ret != KNOT_EOK) {
knot_ns_error_response(nameserver, knot_packet_id(query),
+ &query->header.flags1,
KNOT_RCODE_SERVFAIL, response_wire,
rsize);
return KNOT_EOK;
diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h
index d40a7d9..da19f49 100644
--- a/src/libknot/nameserver/name-server.h
+++ b/src/libknot/nameserver/name-server.h
@@ -231,8 +231,15 @@ int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
* \param response_wire Place for wire format of the response.
* \param rsize Size of the error response will be stored here.
*/
-void knot_ns_error_response(const knot_nameserver_t *nameserver, uint16_t query_id,
- uint8_t rcode, uint8_t *response_wire, size_t *rsize);
+void knot_ns_error_response(const knot_nameserver_t *nameserver,
+ uint16_t query_id, uint8_t *flags1_query,
+ uint8_t rcode, uint8_t *response_wire,
+ size_t *rsize);
+
+int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver,
+ const uint8_t *query, size_t size,
+ uint8_t rcode, uint8_t *response_wire,
+ size_t *rsize);
void knot_ns_error_response_full(knot_nameserver_t *nameserver,
knot_packet_t *response, uint8_t rcode,
diff --git a/src/libknot/updates/xfr-in.c b/src/libknot/updates/xfr-in.c
index 4874ccd..ea8178d 100644
--- a/src/libknot/updates/xfr-in.c
+++ b/src/libknot/updates/xfr-in.c
@@ -730,7 +730,7 @@ dbg_xfrin_exec(
return KNOT_ERROR; /*! \todo Other error code. */
} else if (ret == 1) {
assert(node != NULL);
-dbg_xfrin_exec(
+dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(node->owner);
dbg_xfrin("Found node for the record in "
"zone: %s. Merged.\n", name);
@@ -744,7 +744,7 @@ dbg_xfrin_exec(
// knot_rrset_deep_free(&rr, 1, 1, 1);
} else {
assert(node != NULL);
-dbg_xfrin_exec(
+dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(node->owner);
dbg_xfrin("Found node for the record in "
"zone: %s.\n", name);
@@ -1113,10 +1113,10 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
/*! \todo This may be implemented with much less IFs! */
while (ret == KNOT_EOK && rr != NULL) {
-dbg_xfrin_exec(
- dbg_xfrin("Next loop, state: %d\n", state);
+dbg_xfrin_exec_verb(
+ dbg_xfrin_verb("Next loop, state: %d\n", state);
char *name = knot_dname_to_str(knot_rrset_owner(rr));
- dbg_xfrin("Actual RR: %s, type %s.\n", name,
+ dbg_xfrin_verb("Actual RR: %s, type %s.\n", name,
knot_rrtype_to_string(knot_rrset_type(rr)));
free(name);
);
@@ -1228,9 +1228,9 @@ dbg_xfrin_exec(
}
// parse the next RR
- dbg_xfrin("Parsing next RR..\n");
+ dbg_xfrin_verb("Parsing next RR..\n");
ret = knot_packet_parse_next_rr_answer(packet, &rr);
- dbg_xfrin("Returned %d, %p.\n", ret, rr);
+ dbg_xfrin_verb("Returned %d, %p.\n", ret, rr);
}
/*! \note Check TSIG, we're at the end of packet. It may not be
@@ -1269,13 +1269,12 @@ cleanup:
static int xfrin_changes_check_rrsets(knot_rrset_t ***rrsets,
int *count, int *allocated, int to_add)
{
- /* Ensure at least requested size is allocated. */
- int new_count = (*count + to_add);
- assert(new_count >= 0);
- if (new_count <= *allocated) {
+ if (*count + to_add <= *allocated) {
return KNOT_EOK;
}
+ int new_count = (*allocated == 0) ? 2 : *allocated * 2;
+
/* Allocate new memory block. */
knot_rrset_t **rrsets_new = malloc(new_count * sizeof(knot_rrset_t *));
if (rrsets_new == NULL) {
@@ -1303,12 +1302,12 @@ static int xfrin_changes_check_nodes(knot_node_t ***nodes,
assert(count != NULL);
assert(allocated != 0);
- /* Ensure at least count and some reserve is allocated. */
- int new_count = *count + 2;
- if (new_count <= *allocated) {
+ if (*count + 2 <= *allocated) {
return KNOT_EOK;
}
+ int new_count = (*allocated == 0) ? 2 : *allocated * 2;
+
/* Allocate new memory block. */
const size_t node_len = sizeof(knot_node_t *);
knot_node_t **nodes_new = malloc(new_count * node_len);
@@ -1333,13 +1332,12 @@ static int xfrin_changes_check_nodes(knot_node_t ***nodes,
static int xfrin_changes_check_rdata(knot_rdata_t ***rdatas, uint **types,
int count, int *allocated, int to_add)
{
- /* Ensure at least requested size is allocated. */
- int new_count = (count + to_add);
- assert(new_count >= 0);
- if (new_count <= *allocated) {
+ if (count + to_add <= *allocated) {
return KNOT_EOK;
}
+ int new_count = (*allocated == 0) ? 2 : *allocated * 2;
+
/* Allocate new memory block. */
knot_rdata_t **rdatas_new = malloc(new_count * sizeof(knot_rdata_t *));
if (rdatas_new == NULL) {
@@ -1380,26 +1378,26 @@ static void xfrin_changes_add_rdata(knot_rdata_t **rdatas, uint *types,
return;
}
-dbg_xfrin_exec_detail(
- // try to find the first RDATA in the given list
- for (int i = 0; i < *count; ++i) {
- knot_rdata_t *r = rdatas[i];
- if (r == NULL) {
- continue;
- }
- while (r != NULL && r->next != rdatas[i]) {
- if (r == rdata) {
- dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
- knot_rdata_dump(rdata, type, 0);
- }
- r = r->next;
- }
- if (r == rdata) {
- dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
- knot_rdata_dump(rdata, type, 0);
- }
- }
-);
+//dbg_xfrin_exec_detail(
+// // try to find the first RDATA in the given list
+// for (int i = 0; i < *count; ++i) {
+// knot_rdata_t *r = rdatas[i];
+// if (r == NULL) {
+// continue;
+// }
+// while (r != NULL && r->next != rdatas[i]) {
+// if (r == rdata) {
+// dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
+// knot_rdata_dump(rdata, type, 0);
+// }
+// r = r->next;
+// }
+// if (r == rdata) {
+// dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
+// knot_rdata_dump(rdata, type, 0);
+// }
+// }
+//);
rdatas[*count] = rdata;
types[*count] = type;
@@ -1461,7 +1459,7 @@ static knot_rdata_t *xfrin_remove_rdata(knot_rrset_t *from,
static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
knot_changes_t *changes)
{
- dbg_xfrin("Copying old RRSet: %p\n", old);
+ dbg_xfrin_verb("Copying old RRSet: %p\n", old);
// create new RRSet by copying the old one
// int ret = knot_rrset_shallow_copy(old, copy);
int ret = knot_rrset_deep_copy(old, copy);
@@ -1573,7 +1571,7 @@ dbg_xfrin_exec_verb(
knot_node_rrset(node, type));
if (old == NULL) {
- dbg_xfrin("RRSet not found for RR to be removed.\n");
+ dbg_xfrin_verb("RRSet not found for RR to be removed.\n");
return 1;
}
@@ -1784,11 +1782,11 @@ static int xfrin_apply_remove_normal(knot_changes_t *changes,
} /*! \todo Does some other case even occur? */
if (*rrset == NULL) {
- dbg_xfrin("RRSet not found for RR to be removed.\n");
+ dbg_xfrin_verb("RRSet not found for RR to be removed.\n");
return 1;
}
-dbg_xfrin_exec(
+dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
dbg_xfrin("Updating RRSet with owner %s, type %s\n", name,
knot_rrtype_to_string(knot_rrset_type(*rrset)));
@@ -1961,7 +1959,7 @@ static int xfrin_apply_add_normal(knot_changes_t *changes,
int ret;
- dbg_xfrin("applying rrset:\n");
+ dbg_xfrin_verb("applying rrset:\n");
knot_rrset_dump(add, 0);
/*! \note Reusing RRSet from previous function caused it not to be
@@ -1981,7 +1979,7 @@ static int xfrin_apply_add_normal(knot_changes_t *changes,
*rrset = knot_node_remove_rrset(node, knot_rrset_type(add));
- dbg_xfrin("Removed RRSet: \n");
+ dbg_xfrin_verb("Removed RRSet: \n");
knot_rrset_dump(*rrset, 1);
if (*rrset == NULL) {
@@ -2017,7 +2015,7 @@ dbg_xfrin_exec_verb(
knot_rrset_t *old = *rrset;
-dbg_xfrin_exec(
+dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
dbg_xfrin("Found RRSet with owner %s, type %s\n", name,
knot_rrtype_to_string(knot_rrset_type(*rrset)));
@@ -2029,7 +2027,7 @@ dbg_xfrin_exec(
return ret;
}
- dbg_xfrin("Copied RRSet: %p\n", *rrset);
+ dbg_xfrin_verb("Copied RRSet: %p\n", *rrset);
// dbg_xfrin("After copy: Found RRSet with owner %s, type %s\n",
// knot_dname_to_str((*rrset)->owner),
@@ -2046,10 +2044,10 @@ dbg_xfrin_exec(
*
* TODO: add the 'add' rrset to list of old RRSets?
*/
- dbg_xfrin("Merging RRSets with owners: %s, %s types: %s, %s\n",
- (*rrset)->owner->name, add->owner->name,
- knot_rrtype_to_string((*rrset)->type),
- knot_rrtype_to_string(add->type));
+ dbg_xfrin_verb("Merging RRSets with owners: %s, %s types: %s, %s\n",
+ (*rrset)->owner->name, add->owner->name,
+ knot_rrtype_to_string((*rrset)->type),
+ knot_rrtype_to_string(add->type));
dbg_xfrin_detail("RDATA in RRSet1: %p, RDATA in RRSet2: %p\n",
(*rrset)->rdata, add->rdata);
@@ -2058,7 +2056,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to merge changeset RRSet to copy.\n");
return KNOT_ERROR;
}
- dbg_xfrin("Merge returned: %d\n", ret);
+ dbg_xfrin_verb("Merge returned: %d\n", ret);
knot_rrset_dump(*rrset, 1);
ret = knot_node_add_rrset(node, *rrset, 0);
@@ -2094,7 +2092,7 @@ static int xfrin_apply_add_rrsig(knot_changes_t *changes,
knot_rr_type_t type = knot_rdata_rrsig_type_covered(
knot_rrset_rdata(add));
-dbg_xfrin_exec(
+dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(add));
const char *typestr = knot_rrtype_to_string(type);
dbg_xfrin("Adding RRSIG: Owner %s, type covered %s.\n",
@@ -2128,7 +2126,7 @@ dbg_xfrin_exec(
}
if (*rrset == NULL) {
- dbg_xfrin("RRSet to be added not found in zone.\n");
+ dbg_xfrin_verb("RRSet to be added not found in zone.\n");
// create a new RRSet to add the RRSIGs into
*rrset = knot_rrset_new(knot_node_get_owner(node), type,
@@ -2138,7 +2136,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to create new RRSet for RRSIGs.\n");
return KNOT_ENOMEM;
}
- dbg_xfrin("Created new RRSet for RRSIG: %p.\n", *rrset);
+ dbg_xfrin_verb("Created new RRSet for RRSIG: %p.\n", *rrset);
// add the RRset to the list of new RRsets
ret = xfrin_changes_check_rrsets(
@@ -2165,7 +2163,7 @@ dbg_xfrin_exec(
changes->new_rrsets[changes->new_rrsets_count++] = *rrset;
}
-dbg_xfrin_exec(
+dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
dbg_xfrin("Found RRSet with owner %s, type %s\n", name,
knot_rrtype_to_string(knot_rrset_type(*rrset)));
@@ -2174,7 +2172,7 @@ dbg_xfrin_exec(
if (knot_rrset_rrsigs(*rrset) == NULL) {
- dbg_xfrin("Adding new RRSIGs to RRSet.\n");
+ dbg_xfrin_verb("Adding new RRSIGs to RRSet.\n");
ret = knot_zone_contents_add_rrsigs(contents, add, rrset, &node,
KNOT_RRSET_DUPL_SKIP, 1);
@@ -2205,7 +2203,7 @@ dbg_xfrin_exec(
knot_rrset_set_rrsigs(*rrset, rrsig);
// merge the changeset RRSet to the copy
- dbg_xfrin("Merging RRSIG to the one in the RRSet.\n");
+ dbg_xfrin_verb("Merging RRSIG to the one in the RRSet.\n");
ret = knot_rrset_merge((void **)&rrsig, (void **)&add);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to merge changeset RRSIG to copy: %s"
@@ -2415,6 +2413,8 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
{
assert(changes != NULL);
+ dbg_xfrin("Rolling back changeset application.\n");
+
if (*changes != NULL) {
// discard new RRSets
for (int i = 0; i < (*changes)->new_rrsets_count; ++i) {
@@ -2533,8 +2533,8 @@ dbg_xfrin_exec_detail(
knot_rrset_owner(chset->remove[i]));
}
if (node == NULL) {
- dbg_xfrin("Node not found for RR to be removed"
- "!\n");
+ dbg_xfrin_verb("Node not found for RR to be "
+ "removed!\n");
continue;
}
}
@@ -2559,7 +2559,7 @@ dbg_xfrin_exec_detail(
node, &rrset);
}
- dbg_xfrin("xfrin_apply_remove() ret = %d\n", ret);
+ dbg_xfrin_verb("xfrin_apply_remove() ret = %d\n", ret);
if (ret > 0) {
continue;
@@ -2624,7 +2624,7 @@ dbg_xfrin_exec_detail(
if (node == NULL) {
// create new node, connect it properly to the
// zone nodes
- dbg_xfrin("Node not found. Creating new.\n");
+ dbg_xfrin_verb("Node not found. Creating new.\n");
node = xfrin_add_new_node(contents,
chset->add[i],
is_nsec3);
@@ -2648,8 +2648,8 @@ dbg_xfrin_exec_detail(
assert(ret != KNOT_EOK);
- dbg_xfrin("xfrin_apply_..() returned %d, rrset: %p\n", ret,
- rrset);
+ dbg_xfrin_verb("xfrin_apply_..() returned %d, rrset: %p\n", ret,
+ rrset);
if (ret > 0) {
if (ret == 1) {
@@ -2922,8 +2922,10 @@ static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
{
int ret;
- dbg_xfrin("OLD NODES COUNT: %d\n", changes->old_nodes_count);
- dbg_xfrin("OLD NSEC3 NODES COUNT: %d\n", changes->old_nsec3_count);
+ dbg_xfrin("Removing empty nodes from zone.\n");
+
+ dbg_xfrin_verb("OLD NODES COUNT: %d\n", changes->old_nodes_count);
+ dbg_xfrin_verb("OLD NSEC3 NODES COUNT: %d\n", changes->old_nsec3_count);
// walk through the zone and select nodes to be removed
ret = knot_zone_contents_tree_apply_inorder_reverse(contents,
@@ -2937,8 +2939,8 @@ static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
(void *)changes);
assert(ret == KNOT_EOK);
- dbg_xfrin("OLD NODES COUNT: %d\n", changes->old_nodes_count);
- dbg_xfrin("OLD NSEC3 NODES COUNT: %d\n", changes->old_nsec3_count);
+ dbg_xfrin_verb("OLD NODES COUNT: %d\n", changes->old_nodes_count);
+ dbg_xfrin_verb("OLD NSEC3 NODES COUNT: %d\n", changes->old_nsec3_count);
// remove these nodes from both hash table and the tree
ck_hash_table_item_t *hash_item = NULL;
@@ -2997,73 +2999,6 @@ static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
-//static int xfrin_adjust_contents(knot_zone_contents_t *contents,
-// xfrin_changes_t *changes)
-//{
-// // first, load the NSEC3PARAM record, if there is one
-// const knot_node_t *apex = knot_zone_contents_apex(contents);
-// assert(apex != NULL);
-// const knot_rrset_t *rrset = knot_node_rrset(apex,
-// KNOT_RRTYPE_NSEC3PARAM);
-
-// if (rrset != NULL) {
-// knot_nsec3_params_from_wire(&contents->nsec3_params, rrset);
-// } else {
-// memset(&contents->nsec3_params, 0, sizeof(knot_nsec3_params_t));
-// }
-
-// // ^ OK
-
-// xfrin_adjust_data_t data;
-//// data.changes = changes;
-// data.contents = contents;
-// data.err = KNOT_EOK;
-
-// /*
-// * Select and delete empty nodes.
-// *
-// * TODO: do separately
-// */
-// int ret = xfrin_remove_empty_nodes(contents, changes);
-// if (ret != KNOT_EOK) {
-// dbg_xfrin("Failed to remove empty nodes: %s\n",
-// knot_strerror(ret));
-// return ret;
-// }
-
-// /*
-// * Walk through the nodes in the zone and do the following:
-// * 1) Check node flags (authoritative / non-authoritative / deleg. pt.).
-// * 2) For each node without NSEC3 node, try to find the NSEC3 node.
-// * 3) Insert all dnames to dname table.
-// *
-// * We must also set previous nodes, as this cannot be done during
-// * node insertion - in that time we do not know, if the node is
-// * authoritative or no.
-// */
-
-// knot_zone_contents_tree_apply_inorder(contents,
-// xfrin_adjust_node_in_tree,
-// (void *)&data);
-
-// if (data.err != KNOT_EOK) {
-// dbg_xfrin("Failed to adjust nodes after IXFR: %s\n",
-// knot_strerror(data.err));
-// return data.err;
-// }
-
-// /*
-// * In second walkthrough check CNAME loops, including wildcards.
-// */
-// knot_zone_contents_tree_apply_inorder(contents,
-// xfrin_check_loops_in_tree,
-// (void *)&data);
-
-// return data.err;
-//}
-
-/*----------------------------------------------------------------------------*/
-
static void xfrin_check_contents_copy_node(knot_node_t *node, void *data)
{
assert(node != NULL);
diff --git a/src/libknot/util/descriptor.c b/src/libknot/util/descriptor.c
index e6a0377..63e1747 100644
--- a/src/libknot/util/descriptor.c
+++ b/src/libknot/util/descriptor.c
@@ -373,6 +373,13 @@ static knot_rrtype_descriptor_t
{ KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE,
KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_HEX_LEN }, true },
/* 52 */
+ { KNOT_RRTYPE_TLSA, "TLSA", 4,
+ { KNOT_RDATA_WF_BYTE,
+ KNOT_RDATA_WF_BYTE,
+ KNOT_RDATA_WF_BYTE,
+ KNOT_RDATA_WF_BINARY },
+ { KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE,
+ KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_HEX }, true },
/* In NSD they have indices between 52 and 99 filled with
diff --git a/src/libknot/util/descriptor.h b/src/libknot/util/descriptor.h
index 10d3d20..b7e4a53 100644
--- a/src/libknot/util/descriptor.h
+++ b/src/libknot/util/descriptor.h
@@ -142,6 +142,7 @@ enum knot_rr_type {
* \brief 51 - NSEC3PARAM at zone apex nsec3 parameters
*/
KNOT_RRTYPE_NSEC3PARAM,
+ KNOT_RRTYPE_TLSA = 52,
/* TODO consider some better way of doing this, indices too high */
diff --git a/src/libknot/zone/node.c b/src/libknot/zone/node.c
index 27eb7f2..4ad2a27 100644
--- a/src/libknot/zone/node.c
+++ b/src/libknot/zone/node.c
@@ -215,6 +215,10 @@ knot_node_t *knot_node_new(knot_dname_t *owner, knot_node_t *parent,
int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
int merge)
{
+ if (node == NULL) {
+ return KNOT_EBADARG;
+ }
+
int ret = 0;
if ((ret = (gen_tree_add(node->rrset_tree, rrset,
@@ -236,7 +240,10 @@ int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
const knot_rrset_t *knot_node_rrset(const knot_node_t *node,
uint16_t type)
{
- assert(node != NULL);
+ if (node == NULL) {
+ return NULL;
+ }
+
assert(node->rrset_tree != NULL);
knot_rrset_t rrset;
rrset.type = type;
@@ -247,6 +254,10 @@ const knot_rrset_t *knot_node_rrset(const knot_node_t *node,
knot_rrset_t *knot_node_get_rrset(const knot_node_t *node, uint16_t type)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
knot_rrset_t rrset;
rrset.type = type;
return (knot_rrset_t *)gen_tree_find(node->rrset_tree, &rrset);
@@ -256,6 +267,10 @@ knot_rrset_t *knot_node_get_rrset(const knot_node_t *node, uint16_t type)
knot_rrset_t *knot_node_remove_rrset(knot_node_t *node, uint16_t type)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
knot_rrset_t dummy_rrset;
dummy_rrset.type = type;
knot_rrset_t *rrset =
@@ -271,6 +286,10 @@ knot_rrset_t *knot_node_remove_rrset(knot_node_t *node, uint16_t type)
void knot_node_remove_all_rrsets(knot_node_t *node)
{
+ if (node == NULL) {
+ return;
+ }
+
// remove RRSets but do not delete them
gen_tree_clear(node->rrset_tree);
node->rrset_count = 0;
@@ -281,6 +300,10 @@ void knot_node_remove_all_rrsets(knot_node_t *node)
short knot_node_rrset_count(const knot_node_t *node)
{
+ if (node == NULL) {
+ return KNOT_EBADARG;
+ }
+
return node->rrset_count;
}
@@ -308,8 +331,7 @@ static void save_rrset_to_array(void *node, void *data)
knot_rrset_t **knot_node_get_rrsets(const knot_node_t *node)
{
-// knot_node_dump(node, 1);
- if (node->rrset_count == 0) {
+ if (node == NULL || node->rrset_count == 0) {
return NULL;
}
knot_rrset_t **rrsets = (knot_rrset_t **)malloc(
@@ -331,6 +353,10 @@ knot_rrset_t **knot_node_get_rrsets(const knot_node_t *node)
const knot_rrset_t **knot_node_rrsets(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return (const knot_rrset_t **)knot_node_get_rrsets(node);
}
@@ -349,6 +375,10 @@ static void count_rrsets(void *node, void *data)
int knot_node_count_rrsets(const knot_node_t *node)
{
+ if (node == NULL) {
+ return KNOT_EBADARG;
+ }
+
int count = 0;
gen_tree_apply_inorder(node->rrset_tree, count_rrsets, (void *)&count);
@@ -359,6 +389,10 @@ int knot_node_count_rrsets(const knot_node_t *node)
const knot_node_t *knot_node_parent(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return knot_node_get_parent(node);
}
@@ -377,7 +411,7 @@ knot_node_t *knot_node_get_parent(const knot_node_t *node)
void knot_node_set_parent(knot_node_t *node, knot_node_t *parent)
{
- if (node->parent == parent) {
+ if (node == NULL || node->parent == parent) {
return;
}
@@ -398,6 +432,10 @@ void knot_node_set_parent(knot_node_t *node, knot_node_t *parent)
unsigned int knot_node_children(const knot_node_t *node)
{
+ if (node == NULL) {
+ return KNOT_EBADARG;
+ }
+
return node->children;
}
@@ -405,6 +443,10 @@ unsigned int knot_node_children(const knot_node_t *node)
const knot_node_t *knot_node_previous(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return knot_node_get_previous(node);
}
@@ -423,6 +465,10 @@ knot_node_t *knot_node_get_previous(const knot_node_t *node)
const knot_node_t *knot_node_next(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return node->next;
}
@@ -430,6 +476,10 @@ const knot_node_t *knot_node_next(const knot_node_t *node)
void knot_node_set_previous(knot_node_t *node, knot_node_t *prev)
{
+ if (node == NULL) {
+ return;
+ }
+
node->prev = prev;
}
@@ -448,6 +498,10 @@ knot_node_t *knot_node_get_nsec3_node(const knot_node_t *node)
const knot_node_t *knot_node_nsec3_node(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return knot_node_get_nsec3_node(node);
}
@@ -455,6 +509,10 @@ const knot_node_t *knot_node_nsec3_node(const knot_node_t *node)
void knot_node_set_nsec3_node(knot_node_t *node, knot_node_t *nsec3_node)
{
+ if (node == NULL) {
+ return;
+ }
+
node->nsec3_node = nsec3_node;
if (nsec3_node != NULL) {
nsec3_node->nsec3_referer = node;
@@ -465,6 +523,10 @@ void knot_node_set_nsec3_node(knot_node_t *node, knot_node_t *nsec3_node)
const knot_dname_t *knot_node_owner(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return node->owner;
}
@@ -503,6 +565,10 @@ knot_node_t *knot_node_get_wildcard_child(const knot_node_t *node)
void knot_node_set_wildcard_child(knot_node_t *node,
knot_node_t *wildcard_child)
{
+ if (node == NULL) {
+ return;
+ }
+
node->wildcard_child = wildcard_child;
// assert(wildcard_child->parent == node);
}
@@ -511,62 +577,21 @@ void knot_node_set_wildcard_child(knot_node_t *node,
const knot_node_t *knot_node_wildcard_child(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return knot_node_get_wildcard_child(node);
}
/*----------------------------------------------------------------------------*/
-//const knot_node_t *knot_node_current(const knot_node_t *node)
-//{
-// if (node == NULL || node->zone == NULL
-// || knot_zone_contents(node->zone) == NULL) {
-// return node;
-// }
-
-// int new_gen = knot_node_zone_gen_is_new(node);
-// int old_gen = knot_node_zone_gen_is_old(node);
-//// short ver = knot_node_zone_generation(node);
-
-// if (old_gen && knot_node_is_new(node)) {
-// return NULL;
-// } else if (new_gen && knot_node_is_old(node)) {
-// assert(node->new_node != NULL);
-// return node->new_node;
-// }
-// return node;
-//}
-
-/*----------------------------------------------------------------------------*/
-
-//knot_node_t *knot_node_get_current(knot_node_t *node)
-//{
-// if (node == NULL || node->zone == NULL
-// || knot_zone_contents(node->zone) == NULL) {
-// return node;
-// }
-
-// int new_gen = knot_node_zone_gen_is_new(node);
-// int old_gen = knot_node_zone_gen_is_old(node);
-//// short ver = knot_node_zone_generation(node);
-
-// if (old_gen && knot_node_is_new(node)) {
-// return NULL;
-// } else if (new_gen && knot_node_is_old(node)) {
-// assert(node->new_node != NULL);
-// return node->new_node;
-// }
-
-// assert((old_gen && knot_node_is_old(node))
-// || (new_gen && knot_node_is_new(node))
-// || (!old_gen && !new_gen));
-
-// return node;
-//}
-
-/*----------------------------------------------------------------------------*/
-
const knot_node_t *knot_node_new_node(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return node->new_node;
}
@@ -574,6 +599,10 @@ const knot_node_t *knot_node_new_node(const knot_node_t *node)
knot_node_t *knot_node_get_new_node(const knot_node_t *node)
{
+ if (node == NULL) {
+ return NULL;
+ }
+
return node->new_node;
}
@@ -582,6 +611,10 @@ knot_node_t *knot_node_get_new_node(const knot_node_t *node)
void knot_node_set_new_node(knot_node_t *node,
knot_node_t *new_node)
{
+ if (node == NULL) {
+ return;
+ }
+
node->new_node = new_node;
}
@@ -589,6 +622,10 @@ void knot_node_set_new_node(knot_node_t *node,
void knot_node_set_zone(knot_node_t *node, knot_zone_t *zone)
{
+ if (node == NULL) {
+ return;
+ }
+
node->zone = zone;
}
@@ -596,9 +633,6 @@ void knot_node_set_zone(knot_node_t *node, knot_zone_t *zone)
void knot_node_update_ref(knot_node_t **ref)
{
-// if (*ref != NULL && knot_node_is_old(*ref)) {
-// *ref = (*ref)->new_node;
-// }
if (*ref != NULL && (*ref)->new_node != NULL) {
*ref = (*ref)->new_node;
}
@@ -626,6 +660,10 @@ void knot_node_update_refs(knot_node_t *node)
void knot_node_set_deleg_point(knot_node_t *node)
{
+ if (node == NULL) {
+ return;
+ }
+
knot_node_flags_set_deleg(&node->flags);
}
@@ -633,6 +671,10 @@ void knot_node_set_deleg_point(knot_node_t *node)
int knot_node_is_deleg_point(const knot_node_t *node)
{
+ if (node == NULL) {
+ return KNOT_EBADARG;
+ }
+
return knot_node_flags_get_deleg(node->flags);
}
@@ -640,6 +682,10 @@ int knot_node_is_deleg_point(const knot_node_t *node)
void knot_node_set_non_auth(knot_node_t *node)
{
+ if (node == NULL) {
+ return;
+ }
+
knot_node_flags_set_nonauth(&node->flags);
}
@@ -647,6 +693,10 @@ void knot_node_set_non_auth(knot_node_t *node)
int knot_node_is_non_auth(const knot_node_t *node)
{
+ if (node == NULL) {
+ return KNOT_EBADARG;
+ }
+
return knot_node_flags_get_nonauth(node->flags);
}
@@ -654,51 +704,13 @@ int knot_node_is_non_auth(const knot_node_t *node)
int knot_node_is_auth(const knot_node_t *node)
{
+ if (node == NULL) {
+ return KNOT_EBADARG;
+ }
+
return (node->flags == 0);
}
-///*----------------------------------------------------------------------------*/
-
-//int knot_node_is_new(const knot_node_t *node)
-//{
-// return knot_node_flags_get_new(node->flags);
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//int knot_node_is_old(const knot_node_t *node)
-//{
-// return knot_node_flags_get_old(node->flags);
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//void knot_node_set_new(knot_node_t *node)
-//{
-// knot_node_flags_set_new(&node->flags);
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//void knot_node_set_old(knot_node_t *node)
-//{
-// knot_node_flags_set_old(&node->flags);
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//void knot_node_clear_new(knot_node_t *node)
-//{
-// knot_node_flags_clear_new(&node->flags);
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//void knot_node_clear_old(knot_node_t *node)
-//{
-// knot_node_flags_clear_old(&node->flags);
-//}
-
/*----------------------------------------------------------------------------*/
static void knot_node_free_rrsets_from_tree(void *item, void *data)
@@ -723,6 +735,10 @@ void knot_node_free_rrsets(knot_node_t *node, int free_rdata_dnames)
// free(rrsets);
+ if (node == NULL) {
+ return;
+ }
+
char *name = knot_dname_to_str(node->owner);
free(name);
@@ -805,6 +821,8 @@ void knot_node_free(knot_node_t **node, int fix_refs)
int knot_node_compare(knot_node_t *node1, knot_node_t *node2)
{
+ assert(node1 != NULL && node2 != NULL);
+
return knot_dname_compare(node1->owner, node2->owner);
}
@@ -812,6 +830,10 @@ int knot_node_compare(knot_node_t *node1, knot_node_t *node2)
int knot_node_shallow_copy(const knot_node_t *from, knot_node_t **to)
{
+ if (from == NULL || to == NULL) {
+ return KNOT_EBADARG;
+ }
+
// create new node
*to = knot_node_new(from->owner, NULL, from->flags);
if (*to == NULL) {
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c
index 3764acc..19268c4 100644
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -40,6 +40,15 @@ typedef struct {
/*----------------------------------------------------------------------------*/
+const uint8_t KNOT_ZONE_FLAGS_GEN_OLD = 0; /* xxxxxx00 */
+const uint8_t KNOT_ZONE_FLAGS_GEN_NEW = 1 << 0; /* xxxxxx01 */
+const uint8_t KNOT_ZONE_FLAGS_GEN_FIN = 1 << 2; /* xxxxxx10 */
+const uint8_t KNOT_ZONE_FLAGS_GEN_MASK = 3; /* 00000011 */
+const uint8_t KNOT_ZONE_FLAGS_ANY_MASK = 4; /* 00000100 */
+const uint8_t KNOT_ZONE_FLAGS_ANY = 4; /* 00000100 */
+
+/*----------------------------------------------------------------------------*/
+
static void knot_zone_tree_apply(knot_zone_tree_node_t *node,
void *data)
{
@@ -1134,58 +1143,72 @@ cleanup:
/*----------------------------------------------------------------------------*/
-//short knot_zone_contents_generation(const knot_zone_contents_t *zone)
-//{
-// return zone->generation;
-//}
-
-/*----------------------------------------------------------------------------*/
-
int knot_zone_contents_gen_is_old(const knot_zone_contents_t *contents)
{
- return (contents->generation == 0);
+ return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK)
+ == KNOT_ZONE_FLAGS_GEN_OLD);
}
/*----------------------------------------------------------------------------*/
int knot_zone_contents_gen_is_new(const knot_zone_contents_t *contents)
{
- return (contents->generation == 1);
+ return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK)
+ == KNOT_ZONE_FLAGS_GEN_NEW);
}
/*----------------------------------------------------------------------------*/
int knot_zone_contents_gen_is_finished(const knot_zone_contents_t *contents)
{
- return (contents->generation == -1);
+ return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK)
+ == KNOT_ZONE_FLAGS_GEN_FIN);
}
/*----------------------------------------------------------------------------*/
-//void knot_zone_contents_switch_generation(knot_zone_contents_t *zone)
-//{
-// zone->generation = 1 - zone->generation;
-//}
-
-/*----------------------------------------------------------------------------*/
-
void knot_zone_contents_set_gen_old(knot_zone_contents_t *contents)
{
- contents->generation = 0;
+ contents->flags &= ~KNOT_ZONE_FLAGS_GEN_MASK;
+ contents->flags |= KNOT_ZONE_FLAGS_GEN_OLD;
}
/*----------------------------------------------------------------------------*/
void knot_zone_contents_set_gen_new(knot_zone_contents_t *contents)
{
- contents->generation = 1;
+ contents->flags &= ~KNOT_ZONE_FLAGS_GEN_MASK;
+ contents->flags |= KNOT_ZONE_FLAGS_GEN_NEW;
}
/*----------------------------------------------------------------------------*/
void knot_zone_contents_set_gen_new_finished(knot_zone_contents_t *contents)
{
- contents->generation = -1;
+ contents->flags &= ~KNOT_ZONE_FLAGS_GEN_MASK;
+ contents->flags |= KNOT_ZONE_FLAGS_GEN_FIN;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int knot_zone_contents_any_disabled(const knot_zone_contents_t *contents)
+{
+ return ((contents->flags & KNOT_ZONE_FLAGS_ANY_MASK)
+ == KNOT_ZONE_FLAGS_ANY);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void knot_zone_contents_disable_any(knot_zone_contents_t *contents)
+{
+ contents->flags |= KNOT_ZONE_FLAGS_ANY;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void knot_zone_contents_enable_any(knot_zone_contents_t *contents)
+{
+ contents->flags &= ~KNOT_ZONE_FLAGS_ANY_MASK;
}
/*----------------------------------------------------------------------------*/
@@ -2619,7 +2642,7 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
}
contents->node_count = from->node_count;
- contents->generation = from->generation;
+ contents->flags = from->flags;
contents->zone = from->zone;
@@ -2716,7 +2739,7 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
}
contents->node_count = from->node_count;
- contents->generation = from->generation;
+ contents->flags = from->flags;
contents->zone = from->zone;
diff --git a/src/libknot/zone/zone-contents.h b/src/libknot/zone/zone-contents.h
index d31bbbb..3143ef9 100644
--- a/src/libknot/zone/zone-contents.h
+++ b/src/libknot/zone/zone-contents.h
@@ -60,15 +60,21 @@ typedef struct knot_zone_contents_t {
*/
uint node_count;
- /*! \brief Generation of the zone during update.
+ /*! \brief Various flags
*
+ * Two rightmost bits denote zone contents generation.
+ *
* Possible values:
- * - 0 - Original version of the zone. Old nodes should be used.
- * - 1 - New (updated) zone. New nodes should be used.
- * - -1 - New (updated) zone, but exactly the stored nodes should be
+ * - 00 - Original version of the zone. Old nodes should be used.
+ * - 01 - New (updated) zone. New nodes should be used.
+ * - 10 - New (updated) zone, but exactly the stored nodes should be
* used, no matter their generation.
+ *
+ * The third bit denotes whether ANY queries are enabled or disabled:
+ * - 1xx - ANY queries disabled
+ * - 0xx - ANY queries enabled
*/
- short generation;
+ uint8_t flags;
} knot_zone_contents_t;
/*----------------------------------------------------------------------------*/
@@ -78,11 +84,6 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
int use_domain_table,
struct knot_zone *zone);
-time_t knot_zone_contents_version(const knot_zone_contents_t *contents);
-
-void knot_zone_contents_set_version(knot_zone_contents_t *contents,
- time_t version);
-
//short knot_zone_contents_generation(const knot_zone_contents_t *contents);
int knot_zone_contents_gen_is_old(const knot_zone_contents_t *contents);
@@ -95,6 +96,10 @@ void knot_zone_contents_set_gen_old(knot_zone_contents_t *contents);
void knot_zone_contents_set_gen_new(knot_zone_contents_t *contents);
void knot_zone_contents_set_gen_new_finished(knot_zone_contents_t *contents);
+int knot_zone_contents_any_disabled(const knot_zone_contents_t *contents);
+void knot_zone_contents_disable_any(knot_zone_contents_t *contents);
+void knot_zone_contents_enable_any(knot_zone_contents_t *contents);
+
uint16_t knot_zone_contents_class(const knot_zone_contents_t *contents);
/*!
diff --git a/src/zcompile/parser-descriptor.c b/src/zcompile/parser-descriptor.c
index 152781c..b876877 100644
--- a/src/zcompile/parser-descriptor.c
+++ b/src/zcompile/parser-descriptor.c
@@ -315,7 +315,12 @@ static parser_rrtype_descriptor_t
PARSER_RDATA_WF_BYTE, /* flags */
PARSER_RDATA_WF_SHORT, /* iterations */
PARSER_RDATA_WF_BINARYWITHLENGTH /* salt */ }, true },
- /* 52 */
+ /* 52 TLSA */
+ { PARSER_RRTYPE_TLSA, T_TLSA, "TLSA", 3,
+ { PARSER_RDATA_WF_BYTE,
+ PARSER_RDATA_WF_BYTE,
+ PARSER_RDATA_WF_BYTE,
+ PARSER_RDATA_WF_BINARY}, true },
/* In NSD they have indices between 52 and 99 filled with
diff --git a/src/zcompile/parser-descriptor.h b/src/zcompile/parser-descriptor.h
index ba672f1..48c6f02 100644
--- a/src/zcompile/parser-descriptor.h
+++ b/src/zcompile/parser-descriptor.h
@@ -134,6 +134,7 @@ enum parser_rr_type {
* \brief 51 - NSEC3PARAM at zone apex nsec3 parameters
*/
PARSER_RRTYPE_NSEC3PARAM,
+ PARSER_RRTYPE_TLSA = 52,
/* TODO consider some better way of doing this, indices too high */
diff --git a/src/zcompile/parser-util.c b/src/zcompile/parser-util.c
index c225872..cfbc624 100644
--- a/src/zcompile/parser-util.c
+++ b/src/zcompile/parser-util.c
@@ -2291,9 +2291,9 @@ uint16_t * zparser_conv_apl_rdata(char *str)
zc_error_prev_line("invalid address '%s'", colon + 1);
return NULL;
} else if (rc == -1) {
- char ebuf[256];
- zc_error_prev_line("inet_pton failed: %s",
- strerror_r(errno, ebuf, sizeof(ebuf)));
+ char ebuf[256] = {0};
+ strerror_r(errno, ebuf, sizeof(ebuf));
+ zc_error_prev_line("inet_pton failed: %s", ebuf);
return NULL;
}
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
index 263d0d7..c4415d4 100644
--- a/src/zcompile/zcompile.c
+++ b/src/zcompile/zcompile.c
@@ -549,23 +549,19 @@ static int zone_open(const char *filename, uint32_t ttl, uint16_t rclass,
int zone_read(const char *name, const char *zonefile, const char *outfile,
int semantic_checks)
-{
- if (!outfile) {
- zc_error_prev_line("Missing output file for '%s'\n",
- zonefile);
- return KNOTDZCOMPILE_EINVAL;
- }
-
+{
dbg_zp("zp: zone_read: Reading zone: %s.\n", zonefile);
/* Check that we can write to outfile. */
- FILE *f = fopen(outfile, "wb");
- if (f == NULL) {
- fprintf(stderr, "Cannot write zone db to file '%s' (%s).\n",
- outfile, strerror(errno));
- return KNOTDZCOMPILE_EINVAL;
+ if (outfile != NULL) {
+ FILE *f = fopen(outfile, "wb");
+ if (f == NULL) {
+ fprintf(stderr, "Cannot write zone db to file '%s' (%s).\n",
+ outfile, strerror(errno));
+ return KNOTDZCOMPILE_EINVAL;
+ }
+ fclose(f);
}
- fclose(f);
knot_dname_t *dname =
knot_dname_new_from_str(name, strlen(name), NULL);
@@ -675,10 +671,10 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
dbg_zp("zp: zone_read: Zone adjusted.\n");
if (parser->errors != 0) {
- log_zone_error("Parser finished with %d error(s), "
- "not dumping the zone!\n",
- parser->errors);
- } else {
+ log_zone_error("Parser finished with %d error(s)%s\n",
+ parser->errors, outfile == NULL ?
+ "." : ", not dumping the zone!");
+ } else if (outfile != NULL) {
int fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG);
if (fd < 0) {
log_zone_error("Could not open destination file for db: %s.\n",
diff --git a/src/zcompile/zcompile_main.c b/src/zcompile/zcompile_main.c
index 4b631ce..c84515e 100644
--- a/src/zcompile/zcompile_main.c
+++ b/src/zcompile/zcompile_main.c
@@ -85,8 +85,10 @@ int main(int argc, char **argv)
// Initialize log (no syslog)
log_init();
log_levels_set(LOGT_SYSLOG, LOG_ANY, 0);
- log_zone_info("Parsing file '%s', origin '%s' ...\n",
- zonefile, origin);
+ if (outfile != NULL) {
+ log_zone_info("Parsing file '%s', origin '%s' ...\n",
+ zonefile, origin);
+ }
parser = zparser_create();
if (!parser) {
@@ -107,8 +109,10 @@ int main(int argc, char **argv)
// fprintf(stderr, "Finished with %u errors.\n");
// }
return 1;
- } else {
+ } else if (outfile != NULL) {
log_zone_info("Compilation of '%s' successful.\n", origin);
+ } else {
+ log_zone_info("Zone file for '%s' is OK.\n", origin);
}
//log_close();
diff --git a/src/zcompile/zlexer.l b/src/zcompile/zlexer.l
index c6c01fb..58e6439 100644
--- a/src/zcompile/zlexer.l
+++ b/src/zcompile/zlexer.l
@@ -243,9 +243,10 @@ ANY [^\"\n\\]|\\.
if (strlen(yytext) == 0) {
zc_error("missing file name in $INCLUDE directive");
} else if (!(input = fopen(yytext, "r"))) {
- char ebuf[256];
+ char ebuf[256] = {0};
+ strerror_r(errno, ebuf, sizeof(ebuf));
zc_error("cannot open include file '%s': %s",
- yytext, strerror_r(errno, ebuf, sizeof(ebuf)));
+ yytext, ebuf);
} else {
/* Initialize parser for include file. */
char *filename = strdup(yytext);
diff --git a/src/zcompile/zparser.y b/src/zcompile/zparser.y
index b353fbe..89af437 100644
--- a/src/zcompile/zparser.y
+++ b/src/zcompile/zparser.y
@@ -126,7 +126,7 @@ knot_dname_t *error_domain;
%token <type> T_GPOS T_EID T_NIMLOC T_ATMA T_NAPTR T_KX T_A6 T_DNAME T_SINK
%token <type> T_OPT T_APL T_UINFO T_UID T_GID T_UNSPEC T_TKEY T_TSIG T_IXFR
%token <type> T_AXFR T_MAILB T_MAILA T_DS T_DLV T_SSHFP T_RRSIG T_NSEC T_DNSKEY
-%token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM
+%token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA
/* other tokens */
%token DOLLAR_TTL DOLLAR_ORIGIN NL SP NO_MEM
@@ -566,14 +566,19 @@ str_seq: STR
{
zadd_rdata_txt_wireformat(zparser_conv_text($1.str, $1.len), 1);
- free($1.str);
+ if(strcmp($1.str, ".") && strcmp($1.str, "@")
+ && strcmp($1.str, "\\#")) { // Lexer freed that
+ free($1.str);
+ }
}
| str_seq sp STR
{
zadd_rdata_txt_wireformat(zparser_conv_text($3.str, $3.len), 0);
-// zc_warning("multiple TXT entries are currently not supported!");
- free($3.str);
+ if(strcmp($3.str, ".") && strcmp($3.str, "@")
+ && strcmp($3.str, "\\#")) { // Lexer freed that
+ free($3.str);
+ }
}
;
@@ -913,6 +918,8 @@ type_and_rdata:
| T_NSEC3 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_NSEC3PARAM sp rdata_nsec3_param
| T_NSEC3PARAM sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
+ | T_TLSA sp rdata_tlsa
+ | T_TLSA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_DNSKEY sp rdata_dnskey
| T_DNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_UTYPE sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
@@ -1424,6 +1431,20 @@ rdata_nsec3_param: STR sp STR sp STR sp STR trail
free($7.str);
}
;
+
+rdata_tlsa: STR sp STR sp STR sp str_sp_seq trail
+ {
+ zadd_rdata_wireformat(zparser_conv_byte($1.str));
+ zadd_rdata_wireformat(zparser_conv_byte($3.str));
+ zadd_rdata_wireformat(zparser_conv_byte($5.str));
+ zadd_rdata_wireformat(zparser_conv_hex($7.str, $7.len));
+
+ free($1.str);
+ free($3.str);
+ free($5.str);
+ free($7.str);
+ }
+ ;
rdata_dnskey: STR sp STR sp STR sp str_sp_seq trail
{