summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-02-15 21:02:28 +0100
committerOndřej Surý <ondrej@sury.org>2012-02-15 21:02:28 +0100
commita3a4fcd0e5a4bbc54fc6f6c555b3656798f3a5aa (patch)
treeadbb86088686bdeef3fae9f984f7942d1f922505
parentf855fa7608da509ea1539f861ab7eb54305443c4 (diff)
downloadknot-a3a4fcd0e5a4bbc54fc6f6c555b3656798f3a5aa.tar.gz
Imported Upstream version 1.0~rc1upstream/1.0_rc1
-rw-r--r--README54
-rw-r--r--RELNOTES23
-rwxr-xr-xconfigure138
-rw-r--r--configure.ac10
-rw-r--r--samples/example.com.zone6
-rw-r--r--samples/example.com.zone.nsec3635
-rw-r--r--samples/example.com.zone.signed2133
-rw-r--r--samples/example.com.zone.signed.nsec3690
-rw-r--r--samples/knot.full.conf13
-rw-r--r--scripts/urcu-tls-compat.patch1495
-rw-r--r--src/common/acl.h2
-rw-r--r--src/common/evqueue.c78
-rw-r--r--src/common/evsched.c21
-rw-r--r--src/common/fdset.c127
-rw-r--r--src/common/fdset.h73
-rw-r--r--src/common/fdset_epoll.c16
-rw-r--r--src/common/fdset_epoll.h5
-rw-r--r--src/common/fdset_kqueue.c31
-rw-r--r--src/common/fdset_kqueue.h5
-rw-r--r--src/common/fdset_poll.c14
-rw-r--r--src/common/fdset_poll.h5
-rw-r--r--src/common/prng.c9
-rw-r--r--src/common/slab/slab.c4
-rw-r--r--src/common/slab/slab.h3
-rw-r--r--src/config.h.in21
-rwxr-xr-xsrc/knot.init70
-rw-r--r--src/knot.service13
-rw-r--r--src/knot.spec70
-rw-r--r--src/knot.sysconfig4
-rw-r--r--src/knot/conf/cf-lex.l43
-rw-r--r--src/knot/conf/cf-parse.y67
-rw-r--r--src/knot/conf/conf.c27
-rw-r--r--src/knot/conf/conf.h7
-rw-r--r--src/knot/ctl/knotc_main.c118
-rw-r--r--src/knot/main.c69
-rw-r--r--src/knot/other/debug.h4
-rw-r--r--src/knot/other/log.c1
-rw-r--r--src/knot/server/dthreads.c19
-rw-r--r--src/knot/server/journal.c4
-rw-r--r--src/knot/server/journal.h2
-rw-r--r--src/knot/server/notify.h1
-rw-r--r--src/knot/server/server.c79
-rw-r--r--src/knot/server/server.h2
-rw-r--r--src/knot/server/socket.c4
-rw-r--r--src/knot/server/socket.h2
-rw-r--r--src/knot/server/tcp-handler.c232
-rw-r--r--src/knot/server/tcp-handler.h7
-rw-r--r--src/knot/server/udp-handler.c82
-rw-r--r--src/knot/server/xfr-handler.c532
-rw-r--r--src/knot/server/xfr-handler.h14
-rw-r--r--src/knot/server/zones.c186
-rw-r--r--src/knot/server/zones.h4
-rw-r--r--src/knot/stat/stat.h2
-rw-r--r--src/knot/zone/semantic-check.c373
-rw-r--r--src/knot/zone/semantic-check.h91
-rw-r--r--src/knot/zone/zone-dump-text.c5
-rw-r--r--src/knot/zone/zone-dump.c134
-rw-r--r--src/knot/zone/zone-dump.h13
-rw-r--r--src/knot/zone/zone-load.c19
-rw-r--r--src/libknot/dname.c70
-rw-r--r--src/libknot/dname.h6
-rw-r--r--src/libknot/edns.c50
-rw-r--r--src/libknot/edns.h5
-rw-r--r--src/libknot/hash/cuckoo-hash-table.c189
-rw-r--r--src/libknot/hash/cuckoo-hash-table.h2
-rw-r--r--src/libknot/nameserver/name-server.c206
-rw-r--r--src/libknot/nameserver/name-server.h11
-rw-r--r--src/libknot/packet/packet.c6
-rw-r--r--src/libknot/packet/packet.h1
-rw-r--r--src/libknot/packet/query.c1
-rw-r--r--src/libknot/packet/response.c95
-rw-r--r--src/libknot/packet/response.h3
-rw-r--r--src/libknot/rdata.c53
-rw-r--r--src/libknot/rdata.h2
-rw-r--r--src/libknot/rrset.c20
-rw-r--r--src/libknot/tsig-op.c6
-rw-r--r--src/libknot/updates/xfr-in.c1766
-rw-r--r--src/libknot/updates/xfr-in.h3
-rw-r--r--src/libknot/util/debug.c4
-rw-r--r--src/libknot/util/debug.h4
-rw-r--r--src/libknot/util/error.h3
-rw-r--r--src/libknot/util/libknot_error.c1
-rw-r--r--src/libknot/util/utils.h36
-rw-r--r--src/libknot/zone/dname-table.c17
-rw-r--r--src/libknot/zone/dname-table.h8
-rw-r--r--src/libknot/zone/node.c539
-rw-r--r--src/libknot/zone/node.h37
-rw-r--r--src/libknot/zone/zone-contents.c1406
-rw-r--r--src/libknot/zone/zone-contents.h20
-rw-r--r--src/libknot/zone/zone-tree.c106
-rw-r--r--src/libknot/zone/zone-tree.h11
-rw-r--r--src/libknot/zone/zonedb.c20
-rw-r--r--src/tests/common/acl_tests.c1
-rw-r--r--src/tests/common/fdset_tests.c6
-rw-r--r--src/tests/libknot/libknot/dname_tests.c10
-rw-r--r--src/tests/libknot/libknot/node_tests.c20
-rw-r--r--src/tests/libknot/libknot/response_tests.c24
-rw-r--r--src/tests/libknot/libknot/tsig_tests.c9
-rw-r--r--src/tests/libknot/libknot/zone_tests.c12
-rw-r--r--src/tests/libknot/libknot/zone_tree_tests.c34
-rw-r--r--src/tests/libknot/realdata/libknot/node_tests_realdata.c4
-rw-r--r--src/tests/libknot/realdata/libknot/response_tests_realdata.c6
-rw-r--r--src/tests/libknot/realdata/libknot/zone_tests_realdata.c2
-rw-r--r--src/tests/xfr_tests.c56
-rw-r--r--src/zcompile/zcompile.c5
105 files changed, 9157 insertions, 3650 deletions
diff --git a/README b/README
index 1d04c6b..69163ac 100644
--- a/README
+++ b/README
@@ -1,3 +1,16 @@
+Dependencies
+============
+Knot DNS has several dependencies:
+* libtool
+* autoconf > 2.65
+* flex >= 2.5.31
+* bison >= 2.3
+* libssl >= 0.9.8
+* liburcu >= 0.5.4 (available as packages or as a sources from http://lttng.org/urcu)
+
+Optional packages:
+* libcap-ng >= 0.6.4 for POSIX 1003.1e capabilites(7)
+
Installation
============
@@ -10,25 +23,23 @@ Ubuntu Server (AMD64, I386) 10.04 LTS
Ubuntu Desktop (AMD64, I386) 10.04 LTS
----------------------------------------------
-$ # make the system up-to-date
-$
+# Make the system up-to-date
$ sudo apt-get update
$ sudo apt-get upgrade
-$
-$ # ensure all prerequisites are installed
-$
-$ sudo apt-get install git-core autoconf libtool flex bison libssl-dev
-$
-$ # the required version of liburcu is not available in the default package
-$ # sources.
-$
+
+# Ensure all prerequisites are installed
+$ sudo apt-get install git-core autoconf libtool flex bison libssl-dev liburcu-dev
+
+# Install optional packages (POSIX 1003.1e capabilities)
+$ sudo apt-get install libcap-ng-dev
+
+# If the liburcu-dev package is not present, install directly
$ wget http://bd.archive.ubuntu.com/ubuntu/pool/universe/libu/liburcu/liburcu0_0.5.4-1_amd64.deb
$ wget http://bd.archive.ubuntu.com/ubuntu/pool/universe/libu/liburcu/liburcu-dev_0.5.4-1_amd64.deb
$ sudo dpkg -i liburcu0_0.5.4-1_amd64.deb
$ sudo dpkg -i liburcu-dev_0.5.4-1_amd64.deb
-$
-$ # go for the real thing
-$
+
+# Go for the real thing
$ git clone git://git.nic.cz/knot
$ cd knot
$ autoreconf -if
@@ -38,7 +49,6 @@ $ sudo make install
$ sudo ldconfig
Alternative packages for I386:
-
$ # the required version of liburcu is not available in the default package
$ # sources.
$
@@ -65,6 +75,22 @@ $ autoreconf -if
$ ./configure
$ make && sudo make install
+Installation on OpenBSD/NetBSD
+==============================
+Also works for OS X, if you don't want to install gcc from ports.
+Prerequisites:
+- liburcu needs patch for absent compiler TLS capability
+ - patch is located in "scripts/urcu-tls-compat.patch"
+- patch compatible with liburcu-0.6.7
+
+$ mkdir liburcu && cd liburcu
+$ wget "http://lttng.org/files/urcu/userspace-rcu-0.6.7.tar.bz2"
+$ patch -p1 < ../scripts/urcu-tls-compat.patch
+$ autoconf && ./configure && make && sudo make install
+$ # or follow installation instructions in INSTALL
+
+Knot DNS installation is the same as in previous section (Installation on BSD).
+
Installation on OS X
====================
diff --git a/RELNOTES b/RELNOTES
index 958306d..aeeaf51 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -1,3 +1,26 @@
+v1.0-rc1 - Feb 14, 2012
+-----------------------
+
+New features:
+ * NSID support (RFC5001).
+ * Root zone support.
+ * Automatic zone compiling on server start.
+ * Setting user to run Knot under in config file.
+ * Dropping privileges after binding to port 53.
+ + Support for Linux capabilities(7).
+ * Setting source address of outgoing transfers in config file.
+ * Custom PID file.
+ * CNAME loop detection.
+ * Timeout on TCP connections.
+ * Basic defense against DoS attacks.
+
+Bugfixes:
+ * Fixed IXFR processing.
+ * Patched URCU so that it compiles on architectures without TLS in compiler (NetBSD, OpenBSD).
+ * Fixed response to DS query at parent zone.
+ * A lot of other bugfixes.
+
+
v0.9.1 - Jan 20, 2012
---------------------
diff --git a/configure b/configure
index 8c56d3e..0becd5b 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 0.9.1.
+# Generated by GNU Autoconf 2.68 for knot 1.0-rc1.
#
# 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='0.9.1'
-PACKAGE_STRING='knot 0.9.1'
+PACKAGE_VERSION='1.0-rc1'
+PACKAGE_STRING='knot 1.0-rc1'
PACKAGE_BUGREPORT='knot-dns@labs.nic.cz'
PACKAGE_URL=''
@@ -1302,7 +1302,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 0.9.1 to adapt to many kinds of systems.
+\`configure' configures knot 1.0-rc1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1372,7 +1372,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of knot 0.9.1:";;
+ short | recursive ) echo "Configuration of knot 1.0-rc1:";;
esac
cat <<\_ACEOF
@@ -1488,7 +1488,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-knot configure 0.9.1
+knot configure 1.0-rc1
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2038,7 +2038,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 0.9.1, which was
+It was created by knot $as_me 1.0-rc1, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -2856,7 +2856,7 @@ fi
# Define the identity of the package.
PACKAGE='knot'
- VERSION='0.9.1'
+ VERSION='1.0-rc1'
cat >>confdefs.h <<_ACEOF
@@ -11938,6 +11938,7 @@ CC="$lt_save_CC"
+
# Checks for programs.
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -13425,7 +13426,62 @@ if test "$ac_res" != no; then :
fi
-#AC_SEARCH_LIBS([clock_gettime], [rt], [], [AC_MSG_ERROR([librt not found])])
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
+$as_echo_n "checking for library containing clock_gettime... " >&6; }
+if ${ac_cv_search_clock_gettime+:} 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 clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; 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_clock_gettime=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_clock_gettime+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_clock_gettime+:} false; then :
+
+else
+ ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
+$as_echo "$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing OpenSSL_add_all_digests" >&5
$as_echo_n "checking for library containing OpenSSL_add_all_digests... " >&6; }
if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
@@ -13484,6 +13540,62 @@ else
as_fn_error $? "libcrypto not found" "$LINENO" 5
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing capng_apply" >&5
+$as_echo_n "checking for library containing capng_apply... " >&6; }
+if ${ac_cv_search_capng_apply+:} 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 capng_apply ();
+int
+main ()
+{
+return capng_apply ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' cap-ng; 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_capng_apply=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_capng_apply+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_capng_apply+:} false; then :
+
+else
+ ac_cv_search_capng_apply=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_capng_apply" >&5
+$as_echo "$ac_cv_search_capng_apply" >&6; }
+ac_res=$ac_cv_search_capng_apply
+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.
@@ -13513,7 +13625,7 @@ fi
done
-for ac_header in arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h syslog.h unistd.h urcu.h ev.h
+for ac_header in arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in_systm.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h cap-ng.h syslog.h unistd.h urcu.h ev.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -14181,7 +14293,7 @@ $as_echo "#define HAVE_MMAP 1" >>confdefs.h
fi
rm -f conftest.mmap conftest.txt
-for ac_func in gethostbyname gettimeofday memmove memset munmap regcomp select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue
+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
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"
@@ -14738,7 +14850,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 0.9.1, which was
+This file was extended by knot $as_me 1.0-rc1, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14804,7 +14916,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 0.9.1
+knot config.status 1.0-rc1
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 70545a5..e1fb61d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
AC_PREREQ([2.65])
-AC_INIT([knot], [0.9.1], [knot-dns@labs.nic.cz])
+AC_INIT([knot], [1.0-rc1], [knot-dns@labs.nic.cz])
AM_INIT_AUTOMAKE([gnu -Wall -Werror])
AC_CONFIG_SRCDIR([src/knot/main.c])
AC_CONFIG_HEADERS([src/config.h])
@@ -13,6 +13,7 @@ AX_EXT
AM_MAINTAINER_MODE([enable])
# Initialize libtool
+AC_PROG_LIBTOOL
LT_INIT
# Checks for programs.
@@ -110,13 +111,14 @@ AC_SEARCH_LIBS([pow], [m])
AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR([pthreads not found])])
AC_SEARCH_LIBS([rcu_set_pointer_sym], [urcu], [], [AC_MSG_ERROR([liburcu not found])])
AC_SEARCH_LIBS([dlopen], [dl])
-#AC_SEARCH_LIBS([clock_gettime], [rt], [], [AC_MSG_ERROR([librt not found])])
+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([ldns_rr_list_pop_rrset], [ldns], [], [AC_MSG_ERROR([libldns not found])])
# Checks for header files.
AC_HEADER_RESOLV
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h syslog.h unistd.h urcu.h ev.h])
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in_systm.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h cap-ng.h syslog.h unistd.h urcu.h ev.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
@@ -136,7 +138,7 @@ AC_DEFINE([DSFMT_MEXP], [521], [DSFMT parameters.])
# Checks for library functions.
AC_FUNC_FORK
AC_FUNC_MMAP
-AC_CHECK_FUNCS([gethostbyname gettimeofday memmove memset munmap regcomp select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue])
+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])
AC_CONFIG_FILES([Makefile
samples/Makefile
diff --git a/samples/example.com.zone b/samples/example.com.zone
index a1e3aef..c6a0aef 100644
--- a/samples/example.com.zone
+++ b/samples/example.com.zone
@@ -2,15 +2,15 @@ $TTL 1h ; The default expiration time of a resource record with
$ORIGIN example.com.
@ IN SOA ns.example.com. username.example.com. (
2007120713 ; serial number of this zone file
- 10 ; slave refresh (1 day)
- 30 ; slave retry time in case of a problem (1 day)
+ 10 ; slave refresh (10 seconds)
+ 30 ; slave retry time in case of a problem (30 seconds)
4w ; slave expiration time (4 weeks)
1h ; minimum caching time in case of failed lookups (1 hour)
)
NS ns ; ns.example.com is the nameserver for example.com
NS ns.somewhere.com. ; ns.somewhere.com is a backup nameserver for example.com
MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com
- MX 20 mail2.example.com. ; Similar to above line, but using "@" to say "use $ORIGIN"
+@ MX 20 mail2.example.com. ; Similar to above line, but using "@" to say "use $ORIGIN"
MX 50 mail3 ; Similar to above line, but using a host within this domain
A 10.0.0.1 ; ip address for "example.com"
ns A 10.0.0.2 ; ip address for "ns.example.com". Since there is no "." after ns, $ORIGIN is attached
diff --git a/samples/example.com.zone.nsec3 b/samples/example.com.zone.nsec3
deleted file mode 100644
index f5bf984..0000000
--- a/samples/example.com.zone.nsec3
+++ /dev/null
@@ -1,635 +0,0 @@
-; File written on Tue Mar 1 10:45:24 2011
-; dnssec_signzone version 9.7.1-P2
-example.com. 3600 IN SOA ns.example.com. username.example.com. (
- 2007120712 ; serial
- 86400 ; refresh (1 day)
- 86400 ; retry (1 day)
- 2419200 ; expire (4 weeks)
- 3600 ; minimum (1 hour)
- )
- 3600 RRSIG SOA 8 2 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 6G4Hpl8WFCTVZN292HX+NaS1K8+oLaXK+2gr
- tIp53Y1MI/A8qAD2HZ+bECnbedU+mP5PIJ8I
- 4Q6STbZE3HpiaTMP8D87sJwgD6tUexHhBNgf
- CPZQBdF2Gw/hP+yqeY89ZcoeJVimy6h56X+V
- 7KM+JqRQ6KlGo8vLJTn/lo3pOq8= )
- 3600 NS c.a.example.com.
- 3600 NS ns.example.com.
- 3600 NS ns.somewhere.com.
- 3600 NS ns2.example.com.
- 3600 RRSIG NS 8 2 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 3VqU2AvI720W9frpY+jz5U6a25115tUmkC57
- tr/fvZS2CEAYhWVEpSSFWKRApb70JmQeYgvt
- pvdmOriyChzq4y6phVJxChYrFeTqVYS0AvE1
- ldZ1k5xL6I0hIL6UXgMoz6nRZQ6T1qh/7G2o
- Ge9Taqu0KroITTLGfn4HlyMViq4= )
- 3600 A 10.0.0.1
- 3600 RRSIG A 8 2 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 5tOtdUUMjX0T7QWL/YgYga+HuJOLOh8O3to8
- 3fWUvS5hmrR5/hWV1TRXSHCS0HKIaPBJCn24
- DCHM91uTPNASrpdyWlIAXTJBDqm62C0tXOKD
- zn/50P0cgqHJXa7f69FQc5V+oA/OGcOb2xpV
- e/ig/L8xLcRTGFoYScNMObq9tlg= )
- 3600 MX 10 mail.example.com.
- 3600 MX 20 mail2.example.com.
- 3600 MX 50 mail3.example.com.
- 3600 RRSIG MX 8 2 3600 20110331084524 (
- 20110301084524 28635 example.com.
- yX8xQLpUeZCX3Q4Aq0PTsjEO+5HUrXTWSH1k
- LQ6qozQqWW/SAvnYGkjL/MILnqtTFl07DyrY
- 1y++Ifh2vW5wR11lrIUiftpa0QmSUIj4eJlJ
- fc78wZa3D1g6ni1VDsRClEk3Gx3sfmf2ryjN
- QVa3s++ZszKolUR4WjGGJuwmbFI= )
- 3600 DNSKEY 256 3 8 (
- AwEAAdtkxsfkpMv9P3oa4FGDr+zbs5T28hC2
- G7zRsgHHSP1r3AS9JW8I3yCXI/DWJu5M0Iv3
- UuOc5Q/lNoxmiMKipIP0UZZ97sRyVIK4RWfB
- quVV0GKQ08exwUvUwkej9Uu5Ub0YcWkQXAg5
- xVNpWZ5WxlVhcDVwXG/geikMJPyk6j2N
- ) ; key id = 25581
- 3600 DNSKEY 256 3 8 (
- AwEAAesA9XFmAudDuFARUUn4fcYdwbPfSRYU
- DVC792SMtnEl6dZBLujInZbbQiqW+OyVlo6v
- kyjyQBDuS6aebN4sxO7UYz4vHxxJVuP/+H0n
- /+UAyz11XYT8Rbsmpgzu3PMq5mB13jCjzZ9y
- 3JBJjp5Lrk/jRjFcZapDpX/yXu0UsuuV
- ) ; key id = 28635
- 3600 DNSKEY 257 3 8 (
- AwEAAddbawR+0U7Bz/2lbX1iwMGmAoYOHmb8
- sQF5Jp8gI1tEtpsDD42fW4EM1i1tx7Cyca/9
- u9MSFB14BapX+dxMMj1xJJg0RNTiswjw4DC+
- 7idLwmQHDUMhZLJBqdGkSDcgfsXm9xNEdRrs
- u10wxWpmqMUFxyGStSdGneqdchSRDgr6fihu
- NExHeXp884kXUPuAXSYu02xtYOLLAAhqLeEL
- tQAoyi901FwmmYhyu4eYK2aWqy+ld7JCZZbQ
- j4/9zdecIGETI+NbvQVoO5lSGt6GY7cKaf8m
- 17L++dj2R2rTER/R3gwnjAGQ1GL/djhqbgMi
- vhrxqAQ9R9Ko+6kaeqA6a60=
- ) ; key id = 6190
- 3600 RRSIG DNSKEY 8 2 3600 20110331084524 (
- 20110301084524 6190 example.com.
- qRB0bNPGgy4p2kGBNKbjK/03dowH3zx4fLyP
- 6wv4VmJinbqe2hxqLNLGTdA1toT/82iaLJEA
- Nh0GKnYRVW1rmX/YsvArYH5Z8ikrZbTYSu7Z
- TVTJHHXOGIbddpx3BaEPeNJyJHf7UF5yDKkv
- wM8KhkMw7zRWnuLw5dWYTqmegMVHkNekIHrH
- kW389rY7gbNsZexusmsKURhl3/LhRJlZd/hP
- IlAUIhEV0DZ2xmFEkCOa7QRD/PMUwuiEykxd
- 0ffGm1aCzBUUWdVP7tbYbsePa9f380473m6U
- xDSgNmU5/NjFRYw79/QopE68OU+7F+xTX+6S
- U6bBtAvTPoG+RIBUAQ== )
- 3600 RRSIG DNSKEY 8 2 3600 20110331084524 (
- 20110301084524 28635 example.com.
- MD75IQDQQtrDQTUHJV/F2cYfd49e6YkSWT7O
- BuJUnTvyuYyxpqJg7Rj1H552078yrUQiNSCC
- fqo9yoW6QrpxXgAsPW8wd4vT/bXRayvqZTRJ
- 6ht4FMvOe1dI0cMEOEGfOnve1r4faaHBYPIo
- P5sJQIkoYpQ/0FOnOLz1dIiFZpI= )
- 0 NSEC3PARAM 1 0 100 8B3F579FA62A6CE6
- 0 RRSIG NSEC3PARAM 8 2 0 20110331084524 (
- 20110301084524 28635 example.com.
- Go3s7HQ1n+WLlECouJi/2P0h0F7buRYP7zSE
- UcjBgBDczSucB8ZdfSI+Z9gZpJrOL+hpnhU5
- UB0xVUldoWzO3KK/Zu0YEoBNf/z1eSA8Lrt0
- kWtxDlppfYk9rMRJIBEkY4nNKJz/IlPppZ8j
- TY361bbHGhoHmjJeozrdMGc6/Ls= )
-_foobar._tcp.example.com. 3600 IN SRV 0 1 9 old-slow-box.example.com.
- 3600 IN SRV 0 3 9 new-fast-box.example.com.
- 3600 IN SRV 1 0 9 server.example.com.
- 3600 IN SRV 1 0 9 sysadmins-box.example.com.
- 3600 RRSIG SRV 8 4 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 45kpyR6Avac84Ycv/EpLT3ScICeNpLFgQq7P
- peNgEpboXrJTc7uYUtoxswq19m9czMNQNcoZ
- nFKw3unQGrsfr/B38Vz6uOc9ILF/4WQbC002
- F+VGlgGvPVc9RficEYg3Wwzly7m27d4hPwk4
- pnQQaVenubmXgVHKQ+kl1c8Bqu4= )
-*._udp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- zxu5UR7j0cgvdw8q1L8eD2AvsvhkhbSvuFQH
- C8a0pYCmM0OoDEiLoHj5F9Mk7LI4Mc7sESfr
- roKEOQC4y6xwsuQxCjuG+V2s4xnxLbSrZwee
- JqaI3e8X/gVfd3VoKycY3MqDC1432Qc8VSZC
- Lz9mb68ulNEK1VrEbbA3/jTGGOM= )
-a.example.com. 3600 IN A 10.0.0.4
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- x30rkJBwLV+aiDao0J1N/FbiUWROwBqkl6lK
- V3z4zHfkcEgORa7o2kNkHANPCUJj7bQSSlPD
- I99dyszDxYW4bgnlNlYw9h3D+6+sK9ehREDa
- IMvV1Xuup+oo6LccJhZTlEFrGFU4oUF9VXj+
- g4TDzCyCGMHnVj3SFc/+5xUXGsg= )
-c.example.com. 3600 IN CNAME c.a.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 1sHLDUiGyabatbzRknYdhwu4CQXH+bb6+9x0
- yW/173FMudGOGowiPdfMkUFOP0Igqb/4FqVj
- bg+jDdu4zFCszLQ5MC4Q6mrLL0nfUJ4JL2J9
- kScZN12/t9+P0dnLb5YYXKV8E0GtlKd4ZVr5
- 9fRJvve/OsV29Xj02vX1+sXNjoE= )
-d.example.com. 3600 IN CNAME non-existing.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- Or6i4+ez4nkhodwJC8OWJaj9TyvxJ1i6HC3u
- /xjwF/kStCkTaX/Cg8d36KhVGev6z6LyT++s
- SKiQ0wdPzhgfv2d386W7XUSCje7/OCRUUZwp
- taQvzJsfKCBy2hYz00Anai2qk1pldKEYI3aN
- P3qnSItISO9zbOcKtV2ug6B304Y= )
-e.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- sbrGVq24p55ke3GGXkr/7IPu3fNO67SUABQW
- 67VKrfL1AF5qWN7UdcEb5FZQ5302s28/mePb
- c4Ubn2bpQrmHdMZm1W370J0fDQ/PBT9lKnQS
- tZpAx6xPMRmLG+qvrOtGFDeuCVDqmRlK13wJ
- ryCGvI2eJcfrOU7Kx98ZLgDTzbQ= )
-*._tcp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- k9YqgNDYkvF4tqiPjw0FCsL675BQ6V0mztXc
- +Vfcd/bSbpD3HiMDbkmBeW68TH7g2rkqTzS2
- yjXGdVsxo7jDWdfPiGDdAUueYbPzxEF1eY3q
- v7oquG86sfTrbosYFPfihLXZrnGhVDIlHmgi
- L428BtZbXTINKm9XwjFwv+pZ66s= )
-g.example.com. 3600 IN CNAME www.bogus25.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- gwENYoTmnyn38R4sIb1wJ/uKXPNQnKOu2gfa
- sWW91lrkcwQYF59XZIDme+XST4fiscDJfjPH
- 9xHXs86j771L/2shVZkfh161qXMv2xWVKP14
- tXXfjcQyz/YZ4S6S6MWkUl1w5ujqJCq4PLv0
- +BucVmtjQkcxG9yR0P8F5hMZBsA= )
-*.j.k.example.com. 3600 IN A 10.0.0.22
- 3600 RRSIG A 8 4 3600 20110331084524 (
- 20110301084524 28635 example.com.
- MI/Q/zFqnUrlIQmPjy4Kpq8lQ38PAi15cidP
- C1ZutJUXV7aiYpJJcpmkDNRA96L+/cApfW06
- /ahv+IYrxI3qWd8agOxDXTR/bclrxWJs8Zdq
- aQeM+uvhtVCua6tRcdJf1UCHwEFpqoEg6xcs
- 3vR13IuPLlJrfe/AMrw1FvROfBg= )
-f.example.com. 3600 IN CNAME e.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- cvQbg2jKGDrL6dyOXSY++SaEzo31OKDPRXWe
- l4pVWsJdK9YmjQ0zXdAVtqiYFdKsfS4ep5FG
- VPFF3xuHF0cPzzozwQ3cyn6BRq6EVDohn5Ct
- oyqSQ9jWuwDNdLxG6yCFK+R6bdlc5fxE3Jkn
- qQ8hK6z7XHpHL7ZySVufRtGhMrA= )
-h.i.j.k.example.com. 3600 IN A 10.0.0.21
- 3600 RRSIG A 8 6 3600 20110331084524 (
- 20110301084524 28635 example.com.
- m+FuNt4WmfnICukl82DSunja8nfoy68u+oBU
- MX3nzp5AjwbqWyZTvQRaZpDa0Rsa90oHbCuv
- hOYiK4tVdZjk0yd0Fx6XX/zFqD29BEI/oLu4
- u8CPLvSC9vWB8bFScOjeoCUM+hmnoLVuZ/rq
- XFHz/CQmYX+mpU3u7pKSpFyQDAw= )
-mail.example.com. 3600 IN A 10.0.0.3
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- HPK9q98C16xCURI5wxP3lxUGdJr1X1TeRZ2L
- tnf2s5Izmt28Y3SIbVI83prKO/m4PrpfeV7T
- Ji3ErMMUe7k6Q096YaGStBHL5GWeymJCAzC8
- pJPnyzExDRZeGeknEg4bn0+WJHJz+hlVzYQx
- LRaqA4O021aZf9U/sdDZhGBR0Hw= )
-*.a.example.com. 3600 IN A 10.0.0.5
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- fXOfzPtCYPPyxtw5ivLn7Kq3JlK+LR8BbYLp
- Z6f/Nir3R00GURfsUM6NVbPnMOpnPE513yz7
- 1sAAO/rsOFXPZUSJF4G4zMA6O4OirjGh68bX
- Ei/yrdllyPiTgtHI693MpsDvAFNIaO+pkgS6
- zt+Mk1MEau+78saWxyZVbBWCqT4= )
-*.n.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- s/gyETQ20pNXEbhwRhTIPTMOQYMW8KhhHaSN
- uOYX57dabeGuYgfXFRfNIB+Y1m3kTlxmacMS
- dNIep2b4SF59/T7Ww06/I4P/qQiOosdyeBSY
- X4mQeMrUh8kqxh9C4cQh5yPiiz4w/0Ui+SLP
- J/7Z0AKgYKh7t+pVQfiDAKGQJXo= )
-ns.example.com. 3600 IN A 10.0.0.2
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- aPAigU/glISbY2VM8F8JpfElQ+xab12ZO7el
- 5Cl3t1qiU/3iirBmaKTj7g6IhBduPx+iBgOy
- 5v32FyrfHi2El6nJZxEgi52/Z/4Ohvju3jVA
- hUJLGoREc20FUXOiICCftEauQp7uPM1RAQ17
- Q0pykRRQ50bn+jApSRLL696e+EY= )
-f.g.example.com. 3600 IN A 10.0.0.20
- 3600 RRSIG A 8 4 3600 20110331084524 (
- 20110301084524 28635 example.com.
- EfjVvHQ/IEPdP10B+dEDfyHpCRNpmf0dV7Pb
- Ia/gRDuoRg6FUbL04oycNQSMjafInBpinmx/
- WSDMenEf5HUtP3fyzZ9Fywg2QDZqm6/TJXBk
- 8q+uOxPKfMlcn9Skg1k8XJGbJkAovmyCS+DA
- LC2Ewp7yVUwEliZBkKzUblWE5ig= )
-ns2.example.com. 3600 IN A 10.0.0.6
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- hgX7gI1GpJeuQtTnVDCHS4esc1wRQk6zAP/8
- st6cILlYbOQkwfRVpB88Y4LDCYuWLkplKBjp
- cOhL/gU+zvR8QQQHmdksUlYSK0SFEdvcpvIm
- uD4KosW3wJSAPS8M3bxI2yA/CPdY6SalClbY
- jM/OpPfynAqS1UdNo8vNu4pBYks= )
-o.example.com. 3600 IN CNAME a.e.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- RMRnQd17zWB6vxGUl6L+zKWchPD9XyNMaK6W
- v0MfpY5E9hqSMvNp5BKf+1Fsk5aWs9aWga/a
- AVFUTObelpdG4IE4oyGSUB3wCN9ZTxJ9rKqd
- NVG48X2+iAb2k3tGcUQaYH20gBIezPwi2AWc
- k+CHI2FTi10evykIeVJo+Paro7I= )
-old-slow-box.example.com. 3600 IN A 172.30.79.11
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- LfF5v3pRRomTjLMLqCyEqK9J9m7dbBs1V0zS
- bEu9T+MPOdW4swoObFBPv/FLqr50Y6OGlovK
- J0lSGo+plLw6gPMW9bzJNGeIP19TgcEmF626
- 7+hRibwn6fZvoK4qBQSDQKmNBoST1u+ZhWa6
- xpdY5bdosyQ0oM1Q6eHZsEGELvs= )
-*.l.example.com. 3600 IN CNAME c.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- l+p7hZxP1VakVXtcDE2dN+DCK9tAdZpT8i0i
- IoUdRUgeTv2DcViVsK2tNjv0HIZcffhEatwi
- pM7IAvqkbS22PduU+dxb3OMzcj6n/dQBcxoW
- vfk56RpQcDrqPJVYn7AqVH6KXFg6oRrIYzw1
- O9uTLaHt+futcIEDvRVMTODe9os= )
-sub.example.com. 3600 IN NS ns.sub.example.com.
-ns.sub.example.com. 3600 IN A 10.1.0.1
-sub2.example.com. 3600 IN NS ns.sub2.example.com.
-*.sub2.example.com. 3600 IN A 10.2.0.1
-sub3.example.com. 3600 IN NS ns.sub2.example.com.
-sub4.example.com. 3600 IN NS ns.example.com.
-server.example.com. 3600 IN A 172.30.79.10
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- zWLeUhLq/2lU0KwPFxzJaFIiOSqwA4xQ+mwh
- UYSa27N1t58m3L+XeOwj/zSE69sWl8Lbm3pV
- B+4FNVVPkGzBhocJRf/7a0xc0IlQSI1hgZ3p
- meFlPC/kMTmxK1p9un/dF5r35FsnnAN8ECnR
- 2imbaQLIrjhHshK9bBIVCwK92Ws= )
-sysadmins-box.example.com. 3600 IN A 172.30.79.12
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- WUp7V4gH7JMyvtKURuvrNmW7rVMI1aSMZU9U
- xukVAmQDaQTYXsD5XC3j7X+9gAhQJWA/JNga
- pXT7wzBJpqVrJHqAfRYZFMQ9WI0rJzKJnFPI
- WOlVerQMEwUpyJsX/GlJglldK5kKM0bbPjW8
- s6Vqmq3rfyjGY94HNS9jX+uqCwk= )
-new-fast-box.example.com. 3600 IN A 172.30.79.13
- 3600 RRSIG A 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- qK9x7sS736Go3vdVfYhtuEnFLOhl6djWpXVC
- l4+kvvPpkAJTkfHmTcAsWbChSolB8X4UPt/P
- KTnImnF4uhc2qLOhvToKqx9tVExEIWDBKA7F
- JPPBYG0c6n/50j2bVmzrkhyzaLLuhsbbfm5o
- eZDwwO+vuoMBvj8Z/mt0Di9rh/w= )
-www.example.com. 3600 IN CNAME ns.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- LPrX8sh5xYUfW+wKpQRg50qkf67maJRcN6tH
- R+H3OwL4u9JhdK6RpdRvs4nAF8HmrUZZYtxo
- 80+RMbFhynqPYWlnXd/ZH6taQN2qJYdVLdnd
- dhyLajAkxJqpOWVLezr2KOPj6YzJzu15ngXD
- nHnkSKsTlziq3ifLd5oJLy9UJAk= )
-0J3ID6U2GQUPOADI9B867SGMROP8U4Q0.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 18DGVBOD0NE6AJ2OV3MV9QGNBTJ39V2U SRV RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- BStj/PbAk78rRKdCf4eCvtGKYGco/i7fg54U
- mlIGY/ToQwsB4f9NuDpuajdt+30QnL6w1m5u
- /Hku6cZAV7PEr5S286TWtIHu1GSUfjQ2ObKC
- sF9PYoQrARTNYceY8ZKPNwTk1DgfBNM1WcdW
- 5zJLbQ/DfP/O1c9ZiaR5jokbRnE= )
-18DGVBOD0NE6AJ2OV3MV9QGNBTJ39V2U.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 28CVPDQCRQARAVE71745J8C1C9RR9U6A NS
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- LeQC7vW1322QqG/X08ZQ3hokSMIDB0rmGxk/
- JsmrNt6o1hmpwfz9ET1GM6LDf+SLd12SdnYa
- vRZxVVeUv7KloxZI77aaZabqKYWCX+LmkoJk
- LAinY3wQ6vZD3vSP/BxUZL4Ojs0GNpWqGNzs
- ZOkU9EOOE/mwQFlU6GamBJoy2nU= )
-sub5.example.com. 3600 IN CNAME sub3.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- qIPaS9aKJASzy2ncqcnlyLW4npkwBW12Udvc
- zGyjk/bO8Q58eKm3uBfJ3LtQVCznkBhAksXK
- AXGnN1TRtaxeVBWZNqlRtHV2hgmXQsTWxoVz
- Qc8Qz2LvnzfgRTjt0H1n/5aDQ3FeZ25XuwLB
- W5fFHwvOmQDd3lvZhOJVfSvEKNM= )
-28CVPDQCRQARAVE71745J8C1C9RR9U6A.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 2BMOOQEUMB3KGE328CJ7B2Q65OPJM8DJ CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- i2K6FAon2wyZnGTH35mMmjWth+czEC1cdoyL
- hk6Xd3iGrN5tjPAqkMtuKDuG2boGjDP02npj
- Ytv59m5IK5vSNgeOekR6TRNWdJ/S3XM9VSlv
- 9R07P9WjJVjO4viGtAfvbKVNOYyLPe6+e/Na
- lIjYv87EAAlV3Hot7Pzff1duRSM= )
-2BMOOQEUMB3KGE328CJ7B2Q65OPJM8DJ.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 2CIJJH4RBMAISUSA1TH02A2RAN03THDQ CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- HWSQYMuhCxYWm6DVKRwnik/PYwQmdZhOHMmb
- P+Map173RzL0kzCqGzpokaDmZBs8zZohgvMs
- UYbQss8jnXJuAcyRF0dSc0IVVeJLUAaipJpi
- kmzyIy/+ANxsaSeRgKvkGecFT8dnl5xNQ6F3
- vbBwGNQ34VQHNx6S4a3Qa/vBwS8= )
-wwwtest.example.com. 3600 IN CNAME www.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 2kfR8e8X0LNbTyPg9fe7vlOknc63ksjBRECm
- pCKNFqSMXJ9gd4gbB2DKHTQLarAQx1KOy3lA
- OezcuJS3WKxF/ucZDqkOaiN/YGJqC5GZ1jcW
- zcCahY8FAM/eJfjbZpdn8YowVQy9f/1m+agl
- vsHMD00nflPUyFiRmoik1DAWoVU= )
-2CIJJH4RBMAISUSA1TH02A2RAN03THDQ.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 2E74KFMC0MPQFVMLM1UD7O7HCEUV01TQ A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- f6Gj3qbdYjC27HqDBLv3Ip5Gf/j/GJNVko3G
- XIVrebHqTPUssOy81/CRElLstM1l1WzX/KTz
- 9Pzu5e1qmlYk4Ym20mMAyihWON3/IJk2GI8x
- TDR4tJ3DBWk37l1S4eMhjv43OSms98GlKfZl
- soYKgv6hwPyX7si1FEL9gWTJjio= )
-2FIB35726VOBGISOGPQLFO6O5IRN3M0G.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 3JL9UEM86R2IO5RMPACMSD92NTVGRPNG SRV RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- xmeQ5RA8LUt1UDtfFhKdTCq6ean35+UdK0fP
- OIb7XeWcp63YVS28l0uoud3+HjsB8VSF/FXi
- PpJnN/kG6Xk/+sdTDGuObtqlAI1W6/dXgDcP
- VdbGNo4uPcJsdkQdCgrQs0oxZCwpW2Q69LWH
- yKLTVO6avq/V9DiNOPjTSG7Ix8c= )
-3JL9UEM86R2IO5RMPACMSD92NTVGRPNG.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 4F4ISAF7SLHE2FVS6IH2N1HHOCVUTMTN A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- JbwLpP6KcZ4UbuR7vmjRozuL2uoyp6U1HP9L
- tRu6CH5CJwMa0crXBM6cCg7zm4PkSxyQBMSV
- lt+T3lThVSx6HzxGoDAblj5SiPF/SA79zZW6
- g9qFAlLQ4doeC0CesjeOPu9bL37wtWJIZY5P
- 3LhYhNN67PYAwGFl+s+3kVrLiTE= )
-p.example.com. 3600 IN CNAME a.sub.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- eXmvtean3kAh6cJGtMWPfzVlOC6cjaF4IgIC
- UnJruUTcL61mR57nQKxBD6Fc6/BQoVMOvP2n
- Q19akZQoDvgt/p/Koo3vUozrCzLvkj1n4oSd
- R0fSl7PCBl8Rf1TMuvw+7XvQeIfLq2c8INL1
- PONXmm/lkgqbYw2BJxzx5tKffcE= )
-6A3ESFQICSC9TLOHO0P20QB3T0H8DHNT.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 6T8FEOHJ6MH3O1N4B0H6AES9842FDUSS A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- kUhsVZbbmfkCczTv/wMzX8sbPn+5VbR1r+xE
- x8YvzZ42zof62wIvS2JcwXCR2GvSi9LVKBQE
- 3y1g548Y8n9moXC13MP4F84h+5U/VAhyaPpw
- e2TJpBnMLCDjvMUXP3XQKQzkdiV3UaLFn0aP
- khwT6nh+TTPYeREjcSLuyhWs8Hk= )
-74EBGC37NAC14CAFDT47M48A5JSFFSL2.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 75DLOF6I4571LIKU0GLDE5T49QMEN8IG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- MtZCtVby4Hprx3spzSglrUqmPvvreRDrKXhc
- 0xaWh27f81oGsnek+jDYvaw9JIdDcOAQbonT
- 2nVy6s6Jmrjt+7pWSGPkuFGPgybBrH1l0Rh3
- QmODDmVDueyTMSdEpfe+Nw7+zlq7BI1qXe3T
- fBoESwb73RXgOQ4VztK0/XXk1wQ= )
-75DLOF6I4571LIKU0GLDE5T49QMEN8IG.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 7GD2384TAD22TQJ5ULAC03C93FO12QF0 A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- zukfY1bN+D7H/q3QKmPz+rRRxofgC1ECjbxL
- ZdG0NBT/w2QL3wRLe5CDmy4hNsU0Iq3xxeel
- 7B4f/CMkY+F7WXBbFwsi0cLf0gfN+VOMcFR9
- 700/L99AUw8ofRkH7sWNj0sfHB/CHSC38980
- u+n453MvcT31Svt6GwBVtt75ZOc= )
-7GD2384TAD22TQJ5ULAC03C93FO12QF0.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 7NS0GBBS9N6L1E3OM48637F6HOKCOLQB
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 4nqxLigxKw86DpZ0KAo/k0507oWoind1FOCV
- GDJvF+YejkSuvJFpAtfVSUrw690XZ7+zyuoV
- 05e7BH07rcJV9TeSTgWe86nIGegDr+yzZBEZ
- 3eGsbCwHxrR9ROieVBxNpWnfkVrA6MFqHZj1
- trAY6ajLrb/+kQEBaBdPC668tJE= )
-6T8FEOHJ6MH3O1N4B0H6AES9842FDUSS.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 74EBGC37NAC14CAFDT47M48A5JSFFSL2 DNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- i0z9WCo2snvGjQJvl2ZOkzg0PwCBuCPlDZ2U
- NTbw3k/P4N90yVYu7IuJVEOuwPNaKHzBnz1u
- 2vzYxM/fJHkWi4FljRFGGHC2ViBKJS+li5FK
- KVUXwqZCHWlEc5tZ6lrpFTv5Q7h0zC6M3gSt
- kBl8r8CZY75Yls/xGk7NZDd40R0= )
-7NS0GBBS9N6L1E3OM48637F6HOKCOLQB.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 80I3RRJLHHEFK8HQHD2A8O6VBHGKBSJ7
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- VXcnf/ptpsoJgahBd0QYFkxBqyBE7ZOPNFJO
- jT/fh6syVGIuV/FVSPY5c24RTs0pU59FPW1e
- Ce1bDLWR30pyZfXBrwLmvjwn6XA+RhYtlBu2
- vE31i9zr8pSnZ3GU553zE/30J3ggO+WLQy6f
- sLMmPynGnACOMz8hwvAuqATLswA= )
-9LF5T2M8139TAUL9LBR53N1RLU9BLIFG.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 9T92PKASBK46QUITTDHH5T7U73HFLO9A
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- vJJLcMmUHJIKxBS1a33EljJpocAmudNOZJ1k
- KKpoHIfhN2U4b2GbaAQRbPIttDW14dmwuqZg
- pi//Vm5krSx1PrVWoaCwvyn/9Fey3PcY4zWX
- Rj5m/zgMrqnK8mVdnCVTcSVwlgpcJrpiYxxA
- 5/Lj2MsiY9vf2Gk9kcYqyg09iqg= )
-4F4ISAF7SLHE2FVS6IH2N1HHOCVUTMTN.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 6A3ESFQICSC9TLOHO0P20QB3T0H8DHNT CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- QO6x9M8tKx9nEwTGTLOmWJm2ReQWdDJq/s8x
- CyLc8W1v38iqMgP/X0e+un2MicXkG9Xx6bn/
- KBCMVx16q9MFfpdyQaxvc3w0ZvRliAupP9iH
- pFS5igBe/BAnUS7O6jjAaY03frbz+JaAmNUU
- qbyEm+nfWWDWmPpVgU9qMTh4Iz8= )
-9T92PKASBK46QUITTDHH5T7U73HFLO9A.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 B939IPLCHDGHKH64CLV0F799P2QFKODM DNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- b08XgQYnvasffMbun6yS0gohnuJL2TklNPf8
- AA+2g036YcXQeLTHHMgzgxrpUTKVAnBP8G4U
- gWD+xRwsys2q4Ws14oG9SAos+YEcus8AGs+7
- AFtHyOyBmRwOgP90Iu4W27bpIYf8D0mTC/vL
- JDFkAVYzcL5DW7Rx+pr2F8bqY3I= )
-C8BNH0HKUBJF5F9Q6TV3BLVDP2H05C7D.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 DB9UE21NARLOFV0U06U8CMVKP4GNC10K NS
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- bxfqIBTAIogKzXbyqPnlv+MFIyoYlIT6knm7
- F6BZp9Q0VXNgVM6dEU0THhIzPvaMszn55Tg/
- lEohKrDuFWgbEbWpA9CQEm3LFLVg9QYuYl4j
- 3Glym7TdGl3PDGagEpmHvLHx4gKbnqZWtN6J
- uudu2UAlp8EUP4BWwsCsbnzLk2g= )
-80I3RRJLHHEFK8HQHD2A8O6VBHGKBSJ7.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 9LF5T2M8139TAUL9LBR53N1RLU9BLIFG CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- A2sU+74sIE4X4Ai2pzJPngzssUG9q6FTrBA2
- ZcvOZtkzS1hY9OafSHoyKonqlRC9A+tX8Ny0
- by2M66eX4NvlinGyBJWdC5Ekj1b5cMy6Pcig
- zcMAGsj91MZOqA8gwKiJ8xRGF/LUf1YdlQAb
- qD2MLj83BSzg2m5lXl9EVMLmQwg= )
-DB9UE21NARLOFV0U06U8CMVKP4GNC10K.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 DE3D7U7081COUA3PSVT8MLFDGNGNMUTN A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- VPzYwah96Z+CrgO1cgRHzAe6DCDbn0wxGvfS
- X7suIoXVhz71+PCksxmBzXCjEX8hkta8bfgy
- KEweSDw/PAGeBq/gktmx4XravfhSrvcdxfyC
- jaJQDfKvf//iJKujR4sP1crWnTNKXNLNO4io
- AKiecOcs5L7FFLf/mG/tkRrZD4g= )
-2E74KFMC0MPQFVMLM1UD7O7HCEUV01TQ.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 2FIB35726VOBGISOGPQLFO6O5IRN3M0G A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- k4LLw681oD7qIr/GUupQFuOlbUJe0XkH5YHB
- hG19hIy4BXPGYI0UEaxLnPcLsvhLgb+sdWTG
- JL1JrRcCMRne0zNMY28sAzO1npbtN9pd9oK5
- ZYe5OK6wXpIvziGdJ/2eUVEmV+NrSJREgPbO
- krsX8SxFss/S5i3C+UoWHQd9LoU= )
-EE6P9GRHC60PKN1E34GP2GFODTK9ABNL.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 ER30P5E30F7PBIBO9JHDUD2ATC20OKNQ NS
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- N1IBfELSSlFUJwA9WBo0CtNHwvsWrDnVTUGv
- Cdfz3mp4H1CIUtKx36zX4CJeVXtwc+zWgKki
- WZvpc00L+uvP6tIyMwGeshjd4etY5DqbnIuH
- mCbIxGpVqgjhcAahCogG0kHBnNWkHYD37SZ7
- 9J/uwMoNHUGqpEKiy9PeIHfX3zw= )
-GDU5SE9F3JUO6HF8AONHIVJI53NAE301.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 GJPHM3J2JR55KMCICU1NPT84KMP1C4UU CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- 1M5Lz9VF7zkSQWN+uUUHAvCIzj54/eRvqkkV
- XLjviMkQ3G90qrS7Ro3FN35fbVdgn1sets/r
- R87yO3TpgNwWjcBejT0KQXr3VI8me/Jr/yID
- HlXpfkJZi7YfOs7Us7pKwlzXz6Ox90qtC0ce
- 8WXbjdjrmdpiLAsdZxo1miQXTZA= )
-ER30P5E30F7PBIBO9JHDUD2ATC20OKNQ.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 GDU5SE9F3JUO6HF8AONHIVJI53NAE301 NS
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- TKkytnNfTi8pvoqjXO6V7CY20Zr9oosNb1/z
- 3X7s5UBDZh5KR1aSDjFxt1FrY6+SJkTGHfC/
- 3pNerSIecbMJ5Y2crLJReXFt8zafrL6SLI/a
- 2QwFVuqVWzacwN+0rSxCqcz1tUPcztv0KSv4
- 87yK39umtsKCQ76PaucVtj6DNYk= )
-GJPHM3J2JR55KMCICU1NPT84KMP1C4UU.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 HOJ16G88JKIIDO9ML2CJFV5SNJ8BFVEI A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- QYhzXTmXhrSEsN6ue8c0NgSTaLXVyauv8cTW
- WA/Wa9MDa3+OzaI/X5VnDZOumbnAbX4p1EC3
- yHDrXC+QnQrgr6/Gj9rqCaNzyXKtmBYIGUvV
- DZ4ZRayXeYc/18GgWrCx1gBTUsjsqy1ON/1K
- i8R/aZhwzcUvWbqr1FlaTLSvk78= )
-HOJ16G88JKIIDO9ML2CJFV5SNJ8BFVEI.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 J2A0018O0QCSI08D608LDVJOLPTB3G96 CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- bnvyEDA/snJUVw5jBhdMZ0ajEE4kcfiXVSM/
- P/cKiCEMgR+xhDrz4sUSWitQHz75QXLybgSj
- cjU1XrjGP53kWGb3YEtWaM+JaqV/1yZEdCDH
- ny+zyxcI0foYPu/4r9uqTWB9VLIRHCQol7kJ
- XHu88kXYdu44hdiqQf5E0+VSdfQ= )
-J2A0018O0QCSI08D608LDVJOLPTB3G96.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 K3MJD76QQQ6H0RKERHB88S6LHEHOMJRV
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- jIknVULnzmGn8B3LoTKcuU6ELNYyRLagrI37
- XrnvlLjxWcqNk8W5aiNcVMhfEjlu6F2zLGLU
- 4K4KLV1efxNfJpcp5Ki0lNS+i3HB0rkg8dP2
- j+UCsQ9wHbwzZNSbDli3/kQzEwnHvuuy9f5t
- WCEXC1dwVt0QDrVu9yNVgXuW5SI= )
-N9INKG4137UMU0NL0U8V5FOTD66UJQIN.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 OBT94VQ2BVN9NBPVL65OCARNBQ92R9NS A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- P0xnjLy1AbyOUDyM1lbApfQxQILKU9m3lVIR
- 6a419fA3jkFcBoB3A5ReXWFUW+lYuVGAL7cX
- na/QB4J+skak7oEUz03Hoctc3eCR/ud7vobY
- QULzq+cHzFsDUFC3b8ie0NWMZH8GNRGeHS0T
- FtlHk4mQofYwQkF9Dbzdwn327iE= )
-OBT94VQ2BVN9NBPVL65OCARNBQ92R9NS.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 ONKAPQRU8HJED18U7QPRPJA8GGKP5RCQ CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- uhM8yr7khK1/Ii3buLO+oHUY38t23CcSApyP
- RUefb87LREQVtcNh26Oymd741/NfhvZmhop7
- Uvx0CxSICmjdV+u8Pm7/fbFK1Ha5m0/UvrUo
- 0M4QNEGS8Jbs+xsshr8RbaBCpUStTCxz5og0
- E4lFekJEXuqT7wa/0TVBRyzWIQc= )
-DE3D7U7081COUA3PSVT8MLFDGNGNMUTN.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 EE6P9GRHC60PKN1E34GP2GFODTK9ABNL CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- onPGqq1wHK4TnzDM0stR93s5SsCWFMQh0l0u
- 3lVmvEh8T93G7OpfSEhRoQ9td9o5NxHSR6V0
- 4xxgDxvnjgMMbvDvgyeHLtnmRaaJhC6xL6jy
- 0UQYb0Dz5S5aGocR6tvgDu8vmDgEmTx7zMV7
- 8vdwz2epzT40MX0hGAw9YhYdQGk= )
-B939IPLCHDGHKH64CLV0F799P2QFKODM.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 C8BNH0HKUBJF5F9Q6TV3BLVDP2H05C7D A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- nUn1EpD0cHWC8C9RnfBt4wBepa+DGQFU3nKU
- 2+75RSeL1ltptxuuUmhmiBindtODFY10rdtP
- TecPL4dsG5CXIZzx1zO0OMJalYFyN3MAnZXS
- ENv/K7bWTal6OqVjxsYfrCqCcEmYW+8+0b+1
- vUhfqqaIAdCgVGYrzXMDoQ80m0A= )
-ONKAPQRU8HJED18U7QPRPJA8GGKP5RCQ.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 PO4K5TL8FC932CHVR1339QMSVCG8TFE5 SRV RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- d+sbaGrwmTVOfTajPdsD9NHEUpLXjjJ94Rpp
- 9HIvdJozkwPOP4nUt2lc3lZiJ1OhK/GbMkHZ
- wFlkPKmGeBPoa6FARpYuFj1DtDZhWCd+mTH/
- VMSzGiX8InCQGoTTiufT1G4aSP21oY+UtduF
- KHJYikaPULyWgWjbqOpoO0OxFtM= )
-Q373J0K0LKK0NE6QLDMCDUMUS4D7N9DF.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 Q89JNCJ55KEMLN012BN386RRG5V35MGG CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- ESQkjbD7LTon4QDSN6tZwU4ZaPopzvIXfJ5d
- 3UorybWbBVrctR0AR4mvjuaY8jPuxjcn3awh
- B/RwtlQ2oWrquPfFdinx60v6hmbhFJRSzIM7
- ob6tJObd6Be775r8M9N/aEi0ghtL7qv4BO0F
- 3aoN1TKFHrFB58uyjmtNUBYtE2A= )
-Q89JNCJ55KEMLN012BN386RRG5V35MGG.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 S6102U94KPK3HL2EEB1KU341JC2EMML8
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- s9GsCDhpCzdFG/lnYS1EXxD1yqW1Rs8NFsZi
- ht7zt0qu+AlxFXZ5Y9rC3joPYzoVgMH6f0h5
- WItWvGHQ8gBQgjel7ZAKVSAdinYcyvXyh/g5
- XQ2xwbDHi/Gx736y3SNW3Ivr3vRRNQ/ORJgt
- SQ0ECCQbhRryNCz25SlDDAxbs6w= )
-PO4K5TL8FC932CHVR1339QMSVCG8TFE5.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 Q373J0K0LKK0NE6QLDMCDUMUS4D7N9DF A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- cz7WE3bqo5gy7MGC+CCp5rQq2OmWp1T0fb4z
- SA3kxsMIEh8CDG9B3ETauKSvBokyLHT+WVC1
- z96F1BiIM+ZDey0IYRDc3EGYhNBgdNGGan7N
- GvyGpzTlwhBZAZNvn0Ledn9W6dI8DLBWEIbl
- LFaBFwOGseR2VUp2u7yla73QTP0= )
-SEF41HBES71QEAB5G8DV253ODMLDJS10.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 VCVTKD7HV5II9DCBRH6O7O0FL9NV6O88 A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- SWIZLy2XlDbDRqN7UPOrWMxnc5MHzfw12I8A
- VKGdUlXhOVcVEwVVAk4A3bXihVMP5gG5Z6WU
- sLYFe5TOBmz66OjRmGNVODQNHpacdHeDvjQo
- f3KcbWbl8CGH+uLxjGGkTpZ8MhJ8vm9w9cBq
- urAsJbO1zFHDJi8zi9dQknmfJcQ= )
-VEK49TJCDQQ7AFSAH0A8MMF4EPP0LVFE.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 0J3ID6U2GQUPOADI9B867SGMROP8U4Q0
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- bSvFoFDIForjpYjxvmq7au1hq0oyL5mSC5zl
- V/4WXGT9lAYk7wOZUA/8jsp0BGha9deH0G64
- fTAfxt0OOuwibgqjXOEL9ioJ+xjk0ut1YQqc
- lLenWNE7986fNLKihLk6CTIzXDRORqOp1cS/
- 1ZmeKTA5zT8oM7FUwGmxPYLjozc= )
-S6102U94KPK3HL2EEB1KU341JC2EMML8.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 SEF41HBES71QEAB5G8DV253ODMLDJS10 CNAME RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- LMpezs03lkHxNunfHXUIqt5nOhUVclymGgvM
- JCqFIDuUyhi6pcOPm4lxK5uPjxl4H5rdBRQ8
- k0H3Ms3a4u0/wCFVgoZxsmxRBKuuYg8Hy2DY
- 1wA8xshYi//tMqpSfaPn1qWOQ4H3Lmk1QQ9d
- 7oS5xbj8LbxgRy2nHIMq2Tu/PLA= )
-VCVTKD7HV5II9DCBRH6O7O0FL9NV6O88.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 VEK49TJCDQQ7AFSAH0A8MMF4EPP0LVFE A NS SOA MX RRSIG DNSKEY NSEC3PARAM
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- KtSNurYbgzIR4o419h/wdNPJmiCe/N6V8Qpn
- lL5L/ZE5JqnAq2MKdybxHpSwojGR2pTGehMc
- GV5NEWqyK2TPN8f9stwJ0bH6N1/ab5iXe6Kt
- F8zHjWXMDt/dwtKspsTt1crkXaI4qduta4Rp
- IKoL0b5PqVr3vA4hvwAwqgYe/Zk= )
-K3MJD76QQQ6H0RKERHB88S6LHEHOMJRV.example.com. 3600 IN NSEC3 1 0 100 8B3F579FA62A6CE6 N9INKG4137UMU0NL0U8V5FOTD66UJQIN A RRSIG
- 3600 RRSIG NSEC3 8 3 3600 20110331084524 (
- 20110301084524 28635 example.com.
- zyqm5HgDE1CUqpY2D/UcceQ7GmJZvyZn2uWd
- 9S9/As+NIp/Pf90E6bnhpPu5Hn6H34xubnKk
- G7qH3IE8JcohHw4zRIv1kW4u0CLikBbNq+1d
- rDkWz/FDjsV5QR+nxLlaGwkO12wgDQYSZwNw
- ja5DoRdcCKz2T1jKcQ+NNr0j0Cg= )
diff --git a/samples/example.com.zone.signed b/samples/example.com.zone.signed
index 851cc13..d57b39b 100644
--- a/samples/example.com.zone.signed
+++ b/samples/example.com.zone.signed
@@ -1,5 +1,5 @@
-; File written on Thu Feb 17 11:19:57 2011
-; dnssec_signzone version 9.7.1-P2
+; File written on Fri Feb 10 13:40:36 2012
+; dnssec_signzone version 9.7.3
example.com. 3600 IN SOA ns.example.com. username.example.com. (
2007120711 ; serial
86400 ; refresh (1 day)
@@ -7,50 +7,119 @@ example.com. 3600 IN SOA ns.example.com. username.example.com. (
2419200 ; expire (4 weeks)
3600 ; minimum (1 hour)
)
- 3600 RRSIG SOA 8 2 3600 20110319091957 (
- 20110217091957 20058 example.com.
- T8PgPaLsdbkEfZvPHPvYV08y73yoEGqQuLOl
- db4jvv48AUqt/Q/6dLMcWz6lpFDCEyf/9aCl
- XVBhS+PAo3ex8lXye8MIyGvh5/yGFUveDHRM
- TvigNYz3iJnJj6aK8nkSM29DUe92pkx2m76O
- sT97uSoh+8FX8Vz4qRRBD6NwVIQ= )
+ 3600 RRSIG SOA 7 2 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ qeUEedzQrkf6Cjz94WT1EGT3WjqM8h3Sk7x0
+ 6Yh9KILdnT5pb+Vr7cbqtd2OWl2Pje6qxNnH
+ w2ZIZN8f7DADz55BhYlT0Fvo8UBc6MaLDp3k
+ /8d18oNMEyRSd5/pJkjoJaJNAkHRQ/Mov6rT
+ 9fSUgAnJK7muHZanbgLN+WMIGlM= )
+ 3600 RRSIG SOA 7 2 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ hFSbRH5nZGOZMGhTsKDoAweBLwyoO1OweuMi
+ CWg/ABcOl/RkLsSvoPgDl8SITMi6r2l6Sc7B
+ TOktcW9BGfHY6XOOx/fGZK8lICGStsGGSs5q
+ owbDFFDaBffVbMjJueOMx8vF5FFKQ2A2L/2F
+ TQTduwav0Q2GJlMsmj3SGcCmUeo= )
+ 3600 RRSIG SOA 7 2 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ JJrtIed56dztpBx9xesWIAX1kRDtxJsUkzrh
+ a2BB2LhkjZDyhdQSX8kBhBzp6du9w3DDL5au
+ sG8mhAX14FOPdtGS/CRY3MmLZrTU2R75N7u0
+ aRt3PSH5tYCj7Vhvyk+7XQyXVjh3OzPhTxju
+ oJVX2W6dfe8yTXDHwbRKnPmfEq4= )
3600 NS c.a.example.com.
3600 NS ns.example.com.
3600 NS ns.somewhere.com.
3600 NS ns2.example.com.
- 3600 RRSIG NS 8 2 3600 20110319091957 (
- 20110217091957 20058 example.com.
- U8RogXPsS5rAUPbG0d8Wcvdk2NJ5ccvK4pda
- jEfvIXXgZIib3T+gR+PwDuK4sMV2rQxsmcrr
- qz3Vc15SQhyt+DAXVsrTojT8iu0NJXEZSr/H
- ntPu2/BfVcHbq2wTu01QW1g9/ub0yUltbkcv
- Mt8ZGiIyF5AoChy04SmZVlmuHSI= )
+ 3600 RRSIG NS 7 2 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ NddhSfnU9UdLkyD64EtrEuNiIuAupw8elpyf
+ 2jouZOcbhW/ZKQUvbIMhU3a3I28LqG3fxlcr
+ uTR2C163Qei1r3rvq9+dUEDzb5J15orGCpP1
+ bSeca64RQ0ptda3tMJHiDuq1i6evocFFBnAH
+ YChMxdfMet4mRZD866ge+E7W08w= )
+ 3600 RRSIG NS 7 2 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ Q/7tyQTriPFc6SQYKv7nDylu8CiaPlOq973I
+ N5YGUCVflEnoRbL8f55bMUhllQqa/4RX8sS1
+ ZzM8vuXlwfeP/7qtGgLt5kElUYjS2bUDRJJM
+ g83HlX/9dfwGKdXIU6GUsJ6jvW5mZO9ahTLI
+ oAqw8vVyb3+nwJAheW/6BaiOMJk= )
+ 3600 RRSIG NS 7 2 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ iA72EF8VQy04OUVZs4xf/GG8qKGOGTwgzQXZ
+ he7CnZHNjZ6wTUA1D8FoH71ZiLOiTJds9Im+
+ HoxaynVnTSogxs5i0/HDdxtDonv5o81kf+aJ
+ XgRtsoE69Nl+54/xKePizzH7hgetcHca4lNe
+ uDMh186bBjzRobYICghSMuCrVZU= )
3600 A 10.0.0.1
- 3600 RRSIG A 8 2 3600 20110319091957 (
- 20110217091957 20058 example.com.
- RXbKPkFlSJLiKoliNUC+tlPKru2UZfdksz63
- Jdla5qf+prYU5HZlvMLD/Fs3dSmK7vx5S6gh
- 4pzWAtI0NZ7NoHSsxk/aztoASeal0On55yCt
- 9lXRQ+Avzl7Z41fyFTTdu3GF+tOfAoPuTegL
- qDLokpWQTRfABy8zFIQvVvLWAHY= )
+ 3600 RRSIG A 7 2 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ F9Xe34UUok3PMJd/gfI+zwKZA574ndjaRLXc
+ iI++XwiuvIF65D6qiXsTKj/a3xwzNewo7HW0
+ u465laJZkVeJwoB1lvWLXEo+6Ay/6hYM9UrZ
+ rqsZvKLENRwZnbCijgq3r27FZG28KV7KO7gR
+ KgneNutPNOk/acfQ86XhlPHmGgw= )
+ 3600 RRSIG A 7 2 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ F5LZdgZKg4+uJ06pf5FTcLuH3h65NGtxXcKH
+ /KazE+YiXBxYJLdEZvOtxqDtaoDtjTRer2O/
+ lMO0MiLyY5CBDMB30U5GvfM8GfK+LTPa96k4
+ fF7fFAOj1HlgoxQHgU2wvqG2V/2Pht6MRnSw
+ Wnd20BNvh2Qn/RbXf612bcMT5Xg= )
+ 3600 RRSIG A 7 2 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ ud19/QunaJLw5n0JFlbsBoKO/biKmOFG+EE1
+ 5fP3cSP78ecZTDjyReuOxQRphxXal+msogRr
+ xVs655a1Auwe8e4SwLkVoBZXaPdwB05H7Uv5
+ 6bfTx5CghzU2PhOqh/b6WSp2nE+98x9qmfXi
+ zyv5ZWWmxtUzBq75DJ8AEicvH/E= )
3600 MX 10 mail.example.com.
3600 MX 20 mail2.example.com.
3600 MX 50 mail3.example.com.
- 3600 RRSIG MX 8 2 3600 20110319091957 (
- 20110217091957 20058 example.com.
- Skb7nbpNawsKpBZBC/4vVXUxioxbrPggr+Pv
- EZzxrVcZN4PNL1vLQxWLKaZf9p0VWjFUh6Y7
- pyup5y8kL/y5PBM75jTIx+L95FlnB+Cef24c
- z4f5eqGTteWxqBhp25ZNGNxs5lI6wWJkIObU
- 2PHjtoZyXEGcYYQHtC5LQVQndbI= )
- 3600 NSEC *._tcp.example.com. A NS SOA MX RRSIG NSEC DNSKEY
- 3600 RRSIG NSEC 8 2 3600 20110319091957 (
- 20110217091957 20058 example.com.
- cM0Oa8GL61RYfdbLp3P6dH0gU2Yp1hsPvpkw
- IBCcJ+0MNbZRxCTBnMBxt6VyBBAu9PPsTkgN
- 1TdFmu1kD0fBP2bYAHrVg7xul7n9xoCKhWhx
- x5Kj3bQCKlWL1AfhdH0fkXGyY4D8ufe4yItK
- svm1y0TsIHnXO8aUrh+DOxyp4rE= )
+ 3600 RRSIG MX 7 2 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ g4iyNVNDBUD7SpiJIfm/BMlLvYj7Y/1cm6vs
+ 15zX82fUwxKPMEzVicrTwyvQPBs1G1KOxyGx
+ e0jMIIs/WDD9ZzG+xYBrct/pnGZFm/ztgKE0
+ vcc9dW6On1qUcH4+VcOvauN2IpJELM3oyJil
+ 0QDO1xYwEzfcEsBmPnRDXPr+PzU= )
+ 3600 RRSIG MX 7 2 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ qsyCaJyTlST5swZgPFDWu4L7p7iNsg4ZUBH8
+ /VxM+0WWkbKEg9uUoQouiA+3R89n64uzNFAp
+ tZS43DZ7G/P0JflxmSZT9Yiqb9uLYlRlx8JX
+ mvz6RXRkiJIBOwkDyZ2NBzrHRR/O5babTOzW
+ pg4le1zbH/QlhhiCdOtTbJoPxpU= )
+ 3600 RRSIG MX 7 2 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ lGiTwXcAu50SDtxLHCcKHjkNdK22mFjJzFmU
+ aPa7Rx+ZtGioKBNkRH6sfLmGmckAeotCu79u
+ ZZzuSksQd0fj4TwmjuHyw1SRoAuWmpR3BeKk
+ 0s3anU/wl0F686JJA9VPUB/VmZpVJJnIyUki
+ 6eX9rC25SSPENZz6r7LyNlB7JRk= )
+ 3600 DNSKEY 256 3 7 (
+ AwEAAar2/5Ofpjw0RYuiet7Vzmqp2eCchCkP
+ 0qfud2TF19PtGPu1tXkHd+NL+ZhnM+EDgYUh
+ H7V9mkBV6pv0Scjv3dre/vjrIl/doNvlrbjH
+ y1k3Jb8SfnwsCldzwZ3KHROre3XL8uMiuShK
+ TtwjHaCoOYNA0h1mIMsHd5o54NzGn5Q5
+ ) ; key id = 13760
+ 3600 DNSKEY 256 3 7 (
+ AwEAAbvwMH12OejpiaI8weXipEquyNyzOffu
+ Dv/GGDJ4UiJqZSPb0YWzuG6LcL4BB+X4npDQ
+ SZQGOb26uiQnML2H3ZWsbKu+7qh2YDonSRKi
+ yqLnlv/oFbbz26HNVWjl+rGaIRcmw7IxTJcI
+ kk5DXClzeuYs7NQzxN7asDdFkE++qVCX
+ ) ; key id = 58574
+ 3600 DNSKEY 256 3 7 (
+ AwEAAdq9WVhtJHuVPUvhkH8BFw6JVCQC9r8K
+ ti/sRDFtJPbX9wKtONBjbzD7lw/6myXZC0Qm
+ BK3rRYG3EkpH1lbfqnXxe7A9qiniOsr2QqEO
+ hN8iQY92tib3TaIBQH38P7irejPbMFbeHYB3
+ O3iZkYnnr/TpnyD3Oob/CNX2Dg6Jb8/7
+ ) ; key id = 59507
3600 DNSKEY 256 3 8 (
AwEAAbns20HerHdgnwqTXVG1a3764I7hVAzp
ahf9AF2dq+f+/aC8CWwow9BxU2uUSxDGj33c
@@ -65,6 +134,42 @@ example.com. 3600 IN SOA ns.example.com. username.example.com. (
xTV9Qky/ZRwO7Le/LbhsYgzw6eSE8d1xOUrb
3w9PL8Zn5/059TE4yjmO8W73AZakgMtL
) ; key id = 20058
+ 3600 DNSKEY 257 3 7 (
+ AwEAAbteFDeDikHmJRer5eXnEPdkbSOyrg4I
+ qOYl9eTUEyFxxGBuNBwpQ69iDLsBeznnTJSe
+ 6vbywUwBzEkm3g3APYSkQthXjYm7c4D+XK3h
+ GIEhX0GpCQfHVfhcxgB2NidLQTNm7SiZSSYM
+ m29MM6wfJaSRtq5uclRZcEwDQXfAFP24QT4g
+ oi4bsyoeh+3n/AuAi7KXy4e8sAGJqdJTjuCZ
+ DWCUpz6yBeLQBPihn0/6VnIjlioMTuaIeHEV
+ qhDp2OaLrFScy7A7n5fzCNRUsdZYdv3JsgN5
+ p/bTx3Uep9nlSXmpAFzESHSVnSElCF47t2ww
+ 4Og1SxsPhUcHiBMw1ftMYdM=
+ ) ; key id = 12624
+ 3600 DNSKEY 257 3 7 (
+ AwEAAb+dffUyUGEOYSUc6GFnm1m7Mq57YEpz
+ knSMY+US+7RWnzw5pPoGI8vEqVdFJ/q4pzVH
+ lgNAnVFxaWRE94c29RCjdX9RF8FY4g1/nEQ8
+ 5ZlAgSK/HKBrS+mOumjkx6hVHH7ZPVt2RM4D
+ /6qTqEQJ/9S5UB/k2CPL2tGJg5t5AeljiiTt
+ gNVsVR2BAKnQw1cGuUoKsdEtPNg02uB1b4uC
+ DDfLb8pJcJPWneW8a5iPJaL/MsDf41BxUxXe
+ /f2T3Zq00p/UL6iiJBifQs0oFuz+zOfkBAwV
+ hc8ABzb+gdeMqYhfTROXSLPL1F8iG/6Yxhou
+ s1KPPGhr/wHxEckGXNX+cpk=
+ ) ; key id = 58515
+ 3600 DNSKEY 257 3 7 (
+ AwEAAeUpOTLiCuENRlyGBJLs14RUY2vyBDrY
+ tjd4y6SzbnSpAMxFcv8Lk+ehhOIYnk6fcF41
+ nGpr9+UsFadfQ6gUQj/7Zw3Tb3vGXzT16X/C
+ cVOwC1f5qzgNdVeHJtpV3xv5+4Mjh0LCsJlT
+ tF2qsMwOBqELm78+RK+11NlmYA2zI/lsvSci
+ f1CIYX769oWR7ZX6E4jpgvEsSpqGpI+RgZa+
+ E4yrwxnPRsRXE9WCLvykIhmftg77/8G8olYD
+ +/3S7iHecIqKaJ2mgZWpub8rryJOFfzXT8+T
+ ZCTo8fJ3qoyEscT3OyBzPqV64rluexzHdXaw
+ u+nNPps38uYchpCOS2wxWwk=
+ ) ; key id = 47859
3600 DNSKEY 257 3 8 (
AwEAAdA0zDQsBM+2/OI8I1lAmAvdf8cB5jiS
wyyrjRjpWHlMQYiNXNTigb7fZdTx1SfX05Vf
@@ -77,495 +182,1505 @@ example.com. 3600 IN SOA ns.example.com. username.example.com. (
WNsrCmbQE3zpwZsa7pCC8LW7YQowTtbjOIhZ
DsatvWPhGGUaCemoTt2ceH0=
) ; key id = 49540
- 3600 RRSIG DNSKEY 8 2 3600 20110319091957 (
- 20110217091957 20058 example.com.
- RW5kvcZuCmlM8DEb8teYpTRv8BCT87cvrlv2
- eJHlnIT03wjUVJx5pLr9gYrL1fjua4zGPLc6
- 8MjssdVoiHbYt7pZ9JVnGgrfTSMW5emkyu3+
- FazMDmCpMhy8GN6QyUADS9c12JkanNR+ugwW
- i2IuR6VSZbBEbgK7wizdmu3yt58= )
- 3600 RRSIG DNSKEY 8 2 3600 20110319091957 (
- 20110217091957 49540 example.com.
- AFg593dFrLP8EWKnKVQCpt+/rufL8mCTe/Ks
- NozsesatF/B0LXkztK41wEFczeciTJOMlqcp
- tbuaTUyiC0Lnz8yzAt1PRRxxZrjr8CVbwHDn
- SodKElpfRA9MEFHEvphD7s8gnzCEVCQEw2zo
- 8IbDapCNAADx8pDE976/ixKWca1XNbXGUUwv
- LSKZ/pbNd4FCd8DqG3B7vcmVv8k5bGcJXdlU
- v8OlI2rJXr9yVs4Tb/LgncLcDHOHg4TCKE5e
- ssQ3qnAwC+PtJGMl+UF2Ar5Ue2JZXijkcgxx
- fYYqB3yFaoxfn7neRE5CdALY+kMwv9ySkXWz
- 1+D0NCjZGKIdnZCAcg== )
-*._tcp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- SZqwbOWOrGh0PB0st0OwVICwishDYIwM/VE1
- 3yp3/WboQFWESfrpv9QOfPD19yet97Zi17C/
- vQ7YifNWm/pKHOfvlgAMd5Y+Vku0Y7W85M5j
- SsqjfDoiS6jPWKtHswVq8MRHIpRrCyLY7ZTM
- fGp2A9SRGTa/vFyCgbvu76ampbs= )
- 3600 NSEC _foobar._tcp.example.com. SRV RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- B7lFuz7YrWCvuTs5wb0dA7a+FaKhzQnOYSAr
- 4myC1mVFpRtTsk50n/NkUBTSDBoHjfDdlYU9
- DRBBct0PZTmRRv5EX0Eiw1BVs4mDa7WlYfFq
- Xkc9nhY2jjOFbt8HTLsOdAahXV7VxQBHn8/w
- ewrh0BvaM2Z/r4OHUqc2DVsgr2U= )
-a.example.com. 3600 IN A 10.0.0.4
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- KMwO1EvPdjDW7LJaKY85TPtUogFWA4IWQPvw
- SKNX2aADOanzu/gnY2tVOhDq7mWJ9tQXlMtx
- TwsAzcp+1PdEKCUjEBC53YQI/L1s3opKBl4S
- HTLgGCKw5KhcALeWKGVJp4bbuuDFzmkpP3dw
- DX41E74bR1qFeVofwcjuvQw45hw= )
- 3600 NSEC *.a.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- p09gsGkMo8QSE1ujTblgmpKqaOk6X5RXsIsi
- 8oiOgpNiMfBIMAYNd4T8OqyAEoygvkqw4h/U
- GuRSlSI1vFUzcsua+lVd9/WfbQ0gjWw9zzGL
- rfku6PS+skQZPfZhkTh+a7TnUwoHb3K1sY5l
- tM8Cph4mXhHJbiqxdAiQqjlSj7k= )
-*._udp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- IG3bi+NqZUHgSG0qyASuEc56z9HVV1/TMCUM
- dMTBMfsMzG3LqI3qonhRGPelb9ELDlowKnXC
- joMXetqLNPpsFsc6tO97yxmkDfAskAFpWmUu
- UQ5lG5crlwJ+6PiVANXtrNNZnsMp/jiDFOoV
- b7FrF48gfkt/8E6Mzq1nYKFn67I= )
- 3600 NSEC a.example.com. SRV RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- mQxN2DLH/YEO2bHnvKaHqhfJYkx3HHgqD8JM
- fRbcRX/YDNY0oy0b7VNfN1J+4FYdCZ8r60eb
- 39dFigjiSEXNXmi3SJ6X6irqv4ZOXwoxtjtk
- CzQV5GsKXnERFcQ5SsCwSbFNik2R3gb3kYuW
- qqvYpqPSVA+ScJ4cdNXODvL9zag= )
+ 3600 RRSIG DNSKEY 7 2 3600 20120311114036 (
+ 20120210114036 12624 example.com.
+ PFHuIix2X5Cecl4x9dit0Q3gJ/+6XmvAb71W
+ z2+BOXI3pQTObtR0nXJTrpEeWeyTNcaejVu2
+ DsiqUkrNfmmEptu1SwtNO/obKST0ewwmfZC0
+ fT/MT5FlRcdXNMXYbzTtykqfebCaQFEvDqtu
+ xMnKVlMn6Gl1GhJWL/FOCbx+h4M8j/7XeYMc
+ LeA5AUFxGJ9u7o2heWk218Q8wDas4ohsmkE8
+ h6EAo1A6qzWvtYZBJ40iUibC01w2oSfqqN46
+ /GdzHB1+SDomrctfwSOaVFuF2mSC1X+iy7GG
+ tX2Mq/kl5wEGrz9vgms6s9Y75oozIq0JOkWN
+ XYD9Nx5c0SsehA15sQ== )
+ 3600 RRSIG DNSKEY 7 2 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ ULc5iLBsBLh3hvOGEF9wXbhoPWVOsMdeXx79
+ 0UPi/Ro/c92so7WiF8hZpXNKkuISOZsp/7C5
+ kpO2Ds3qwHukLmcb60mdm2ORja5rG2vq9L6V
+ 8L9zOki6+uqCiBQr0yTmxKH2snI74O5xA2NW
+ 8e4Lqhm+8kqlarFOXdac+yPNdmY= )
+ 0 NSEC3PARAM 1 0 10 AD3302FF
+ 0 RRSIG NSEC3PARAM 7 2 0 20120311113926 (
+ 20120210113926 13760 example.com.
+ G/XZq9xvzAe34fFEBEbE/rsRvD9datHP4EJ+
+ V6z0a0gfFlkY9dbkIe6Qtbd6vR3cXPqKTgEW
+ yOYf2qNs/ZW3lfskq4JNTsCgtw/ZnY5XwiNi
+ Blt32YKmtu6VpReXK1cdFkQ08nFeugW4S6aG
+ jFfzXAe3YAYa+Bwz/4Ku/E533fE= )
+ 0 RRSIG NSEC3PARAM 7 2 0 20120311114013 (
+ 20120210114013 59507 example.com.
+ sM4Zu2O4BVU7XRF9wPm2kpLgwdZJ3lkuJsbS
+ aVX0ZZsee1DgBwJc9E/LiCmP0yn9XhL2Iro7
+ O/yKwD2dcg21kO97mnrFxBh4FwCBtgPU6W1R
+ TEt3QFhqG+qmhsESgPTntnpUncMWy+wo9pma
+ Q8Q01AOO41RjOcC4uee76V81Ajg= )
+ 0 RRSIG NSEC3PARAM 7 2 0 20120311114036 (
+ 20120210114036 58574 example.com.
+ KhqJ0xarqvbLOikDJgjg+mJ512KRlqxAtYRD
+ xS5HJ4xtbpaVSdJW88ROFZClAfETXHLFdZwV
+ yByF/d+cSSXM9BdmZRgr0fXjPVvVIzP0PvNW
+ kQar8vufIEAigxSX8gDXM9WTYonE1vfRc/Dx
+ RqmK8Mu5dFAGDA31A/ELVOvlKRk= )
_foobar._tcp.example.com. 3600 IN SRV 0 1 9 old-slow-box.example.com.
3600 IN SRV 0 3 9 new-fast-box.example.com.
3600 IN SRV 1 0 9 server.example.com.
3600 IN SRV 1 0 9 sysadmins-box.example.com.
- 3600 RRSIG SRV 8 4 3600 20110319091957 (
- 20110217091957 20058 example.com.
- jIA+72DXdYMsWQ45Sv2MBg0rI3rv/7oEqoA0
- rJ9X4la9o/ozwca7CJE8HKP6l43gzns1pfZ7
- +QsYW5BJOOB8ov+cCEVBW9XY37naNa8fKUsK
- Mpzo35gaQ1zi9+FnseAwZ0WAicl4+766p4iJ
- MzDEZA9VXvSMq36i/v8c+VMxFP4= )
- 3600 NSEC *._udp.example.com. SRV RRSIG NSEC
- 3600 RRSIG NSEC 8 4 3600 20110319091957 (
- 20110217091957 20058 example.com.
- npUQV7MbigckrB6D4jshTkGpOvZY4XTulYP1
- EUjN7Ttr8i56UEon3zzVY2ZUK4McyNrkzWqg
- KPoFNG8xwf4bI2+WxdJeYo45PPZsy6bDTbMu
- lYc68hQ35r3ok32SPG4GMuV53iuSJBCNrM9o
- Rat/FL4Qoqzy+sVk1+tnz2ShzqI= )
+ 3600 RRSIG SRV 7 4 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ lsx9zG/XlVYf+5KwWAQIrO9dyjfrRg9jNXTL
+ Hr9k9cSwAo08lgiLBL+O9oSIYBoCE6ACR7bv
+ o3IMb8uhQmx5TOcmBZLC/9lV/E074aQfC2gc
+ AoQsc3djYzRnoLqFZutHF8vtTQGTtaTh6o3U
+ 4YwOrsJNE0/mey7QZh34CJgsbc4= )
+ 3600 RRSIG SRV 7 4 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ 1MZAWcrEJFkQn9y7urePqFVEP9Pw5bJdESjA
+ w19FeHRlqQpSxcxM9KPoTFDopFSRbcCMnVf+
+ qNzeSjyM7m4n+B9F0L/ga/vlfO6JIc+klcV1
+ 4nf775cBZNFhP3yiMhvQdFnu8KGdxPG+MKWj
+ 2eNPnYzjixr89NMTdAYULyCRhBc= )
+ 3600 RRSIG SRV 7 4 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ chZW5V4d2FPj/vPI7+ImeIxVFZ1xrK3D9/Gm
+ r3ssEGhtVwd7MvUDuZyNsTjQCjwahoB0PcPh
+ IZanWyFf0nFRNQ0LdMxpCqgzT1zkzdo4/lf6
+ PJi0OxKvB+yiSg7VAihABUJ2dFdVIuUx28Ep
+ q7y+0mnJG1KErKbUNk35V1ZlJsg= )
+*._tcp.example.com. 3600 IN SRV 0 0 0 .
+ 3600 RRSIG SRV 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ K/uSiRdsTASX/dlfEFWCsfPMimzdFWU/L5UL
+ c6ZZdiz5v22vhVMMlKuNEIqOnBvkjh/nGJRb
+ ZVW/yfPeclrdgBBw7qxGJE8B6z3qoAyyjuEW
+ 2Eoh5eWxuPWTyc0DWsRxyY6WAgK7vKUcdeCd
+ PSLFF28pOBkqsmpnCgi3xC/PvW8= )
+ 3600 RRSIG SRV 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ lUIdAHJ8vHyuGJk15SWXGvbcoWRUY/Wvxj9D
+ QglTe/VeBVrQtQe4kPiM9NyfKxW26QABrvb9
+ pU8PJPN9KLLeGoZvLvkEwbyGIdq5jI7gp9mt
+ WXQUSegexHlAcL9BxzrO7sXBoomyWkzesLqs
+ f7P2qiR1Mnta59tctQ8crfy88a0= )
+ 3600 RRSIG SRV 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ aiCp2Z/Skts3Wsn82oPP1OfBO60VmtC9ydDK
+ TwwrL5t0jipNIST8CUgrc33fZE4xrKLze3QG
+ G2UjpNZUk75/vbGMaSqPdwpOg+1ZXC+eM+BI
+ Rhhg8PE8yqfbHXOaCgbHzEDH2c8aZeeuAHXE
+ xbjuRntIOCJL/aZwciu2U8pi0Pw= )
+*._udp.example.com. 3600 IN SRV 0 0 0 .
+ 3600 RRSIG SRV 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ XnZgnLEz7E5rAboyJWVu6/t1rDvVfDGk7Zs5
+ 5zpv+Ue1PDzpAnATldNqzyg3su4knjZf9uEu
+ wPeQ85YzGV+++YhmkfLCVtyjQl9+od3S2IOL
+ KOc6plEA/wxeKtQZooYOA2BSOcY9n+pn4CMc
+ +N1N0K5HKVD25wFIa5JqmeGvVq8= )
+ 3600 RRSIG SRV 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ qLv8BCXSeS37ZEyfkQ+Dk/LLhdatK4yLLWwR
+ 06Xq+yBxa2Abax1zhnvwpJeW+3gR9X90Y/pr
+ dgc4QIcO/EiKMUI83+993lcmEvwMHcKHddNZ
+ LDujo/hgO8Qy+yUu7rs1x59dFa+jua1fwjZr
+ XlQ7OCerB3sxpkqoNFTDANc0TpU= )
+ 3600 RRSIG SRV 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ OhyGUYdZTY1tDWHF0UKqHlXPQh92JS0krNBy
+ uD5F6HdeZP/nGW1hIiMx7y7dvCnWb8rRdHyC
+ yVH3ilGtiS9kAnFI4OTCfzYYopKcC13H0mzN
+ /MoSxpzvXer9UDtIM0GQcJFGJnvY4sMwTMa6
+ ggRagi0EqBuimuJCaxPBXCAAOUw= )
+a.example.com. 3600 IN A 10.0.0.4
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ ib2NUsqQbTKZd7Rxe+UGX3GbEzlNB+IogQg4
+ Dh0fyvi8hZlMT/3JSzVyTMggjvvD5yNiXQJO
+ 7QepRRTS3s8a/4w67g3GtI55umVgk9P7amrn
+ dkgVbhbUfNvtj1UHpE8bSntWjEJdwUczH+Hd
+ Rps+WWdtcQer9oHijs6T7sFweiI= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ HuovqaRWsK22AL4UamGL3IGxuV7Su6X6pYms
+ oFWGYwp1EIh7zLtyFbE+K87HQ2Uuoj/edcqe
+ gxmyAzPvZjv8M9J5N4DgLs2wHNK/aqjCcQwK
+ v9QoymZVwZPOeAkIHO6FW6+ez1V1uL2g0Dyd
+ 4sRRctkZw9k2dW5G6ZAi9cnf7Eo= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ MTtOXhChyvgyFVMr9DoM+Q6CEXmcXSjBR4PO
+ wIUQ/vjp//8B11WJGrJoOFJo4dzuWp7LO1eP
+ zGyrzCIj46ALhj1R+Vt/YJLuFEWwsj+RnYTW
+ RTtEdgD7/sN2R21HC+UOGe3tgAWMWBxIHaC6
+ elzE2yderm0aTs1o8UduCJEWNf8= )
*.a.example.com. 3600 IN A 10.0.0.5
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- iHMA40EdVEV0HIxDKbxcOe74roa7X3Vi+lpr
- XGJWx0gbVVhMsGdXi8YycbWAyHvwxImiU/VT
- ZcDiDExzH89XZbzmEtP5vjAOBaf9rQu7cFzC
- mAekgEEccVYSt6QLJTxcdk97CDRNkbU1kd02
- J09lSSyQL8ATADXIlWFUfMC8Fx4= )
- 3600 NSEC c.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- NKYN+2bmtp/2Bfic6vBqWAC/ouTz4qEUgdw9
- a153VST6W3UpROG/xiKV/STmURt8oYIzHy42
- UDRp8DmuVRMgeP7CCCYDmFq1+hSHv7iia79k
- bvrSqdEbfaAjBkHMPlJyd3VjqKz0L+Q7sOKP
- pWKItsBruF9UTJMP0Y4WLCvsD1Y= )
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ ig0iVfSdt1gbjMe6NtCLNZS+GAqeAV72cPNy
+ KRAtd9sorH2A/sfLRHET0FRjHqgFkoN3tMlD
+ g7Fl8N8rd4f6pofemt9VrhNqO4v4cIS+F60q
+ QYn0WAvBPpnBR9HRSOfkMve+Offa2E2Z0kai
+ EZ/FtyueZAa2pZwcdEMK0FHyxcU= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ TrA7KYJuGNJzBHDdVwkgpDGWyN0gG82nU0k8
+ qTgBKTNDoMXqR0z6dgaghLzbCN3N5iRDWeHN
+ /gXB4bfyy0Tpr7JxTSHaHqFyxztAcSZBv4xr
+ Qv0ij9pTJJge44+H2cHikcE/yptVQsr5iTNW
+ 2u0R3k+1GrmmuuDZtE7JkUu8puQ= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ Cpm2UdGKo6fwa7+DIj03t2qdjM497Va2dHLF
+ +MWgfWOnubJdZ8lO3Omr01MRAwxqtDZztkKE
+ xIdps9n3dhNrAoVTPKO8ITnO5ku44fhrQ0Jd
+ Quimk88sMgZlYaL4xs1uKFX5U7WeIdYO0CkW
+ ycnD1UA20BvJejStxofTkqYF4yY= )
d.example.com. 3600 IN CNAME non-existing.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- KFfbRqMSwZOtr3plXJ2E9uKvEZjop9wpmq57
- EXq4Pus6pBhdPXXgwDo9/tDsTj6woScdlWyk
- BsDYRIVfcu+jBbyTdFYSg2Em2A3XwtTxHD+s
- wL3cRc7uKHs/FsWDVldxvrKy/ljX/kdmkiHN
- xiRCWZsPa6kxB3/KtDRjYO6pkCM= )
- 3600 NSEC e.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- HbB+j61LK2AzrGmeLtVFRI4Ee+9dkh01xY44
- AHWKIEqqxRA95yOxWYDwVXXC4F1cO/UN0nAs
- pTZekW8qb3vGrBUytno3mYZST+RHN8KcrWwL
- n0nXsidEekA+ZGxRw7eltu8ECYX71C56bqp/
- DIilbcD1+bIyGxFHlYN77l+nVUw= )
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ BHiNhy1zE1ziC5xkpamNHfTYGFqpLprApsxZ
+ PSwnguEVR8GeCyCsD9IA0/1/uqPVrDlLlZtd
+ znztcUuG7iJCxN+mUtILjx9SsDeeHzOIDAz0
+ sJbV/383B6SkbbhTWgLobg2HvCyieJCqY1M6
+ yQ0zePBZi7YMc3E7qBriGF1crWg= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ J81+CQdrbye+lOEAuACsTdUhC5POtpQ2iHxe
+ HswN3pVr+9E2NZHeOExPdikWH/HrS7IwfeYE
+ eo8TuiZnygvxljK6pEASEL8cXrYahSVgjIPh
+ W+68MjxtkJIaFalWisgiffRgIbpo+HlhB4wK
+ OFYKHlocZLzPr24VX89DfYnVgH0= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ PShNWIZ4zS/VYTOsIEMSLmDgufGD3wJp2QyS
+ 2JXxj/rv0o644QlBcR9rz0CMhJBri4pochIa
+ 2Hb1i+WCFCFCEHuvU6DS5R42M2T2OQ96xjbk
+ bvYN6+h6Qle/N/Y0N20wZPFsQQvPXbL/xNSH
+ VaYxS1j66Jw+Wx7CCNEXl2UBU30= )
e.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- SKLwv2FArbnNXXjaRxHsw3YcqYBxPNL/EETi
- 6rKHVHHOgLN/IwQ6wLtmXZfRSV3Avw0pYmgt
- 6hVda0mnJ8M4BPRal3z2cf9+PVX/f9kJWUNM
- h1A/ibKKIwrhcdh4Z9s7QXGioE6WiEViG3zP
- pfkajBllmOrE0pEH0YX1rWValCE= )
- 3600 NSEC f.example.com. DNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- swVPAYAboz3U8Y2Jcil1R6jUIAHggZlrs8I8
- ky7EAQTFYDRhLBC4UeGO+6DpkHAKCGepd2E7
- yojy/wttp4VhBxcaDGidc94z59Km/wuxF9Yk
- cCYv7Ip6qLpk8L4CJOJvkFAGWTpkOYkA1qDR
- tQ1IMSOsc6s1xaY9pd4vxmZkS4o= )
+ 3600 RRSIG DNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ dFPAkQVZNn4La6rZgfRZW5Xf5XqMol5bBHHJ
+ tslLotEN4OGHGKfqY0AmNJ6BbaWm/pug0Ne4
+ sflPqt9YX1le04WMkQg577OI3yjXKpb7leht
+ YFiLzAg7hdskQ+xlq74wBWrn6WoO2yZhP/fw
+ 0Ik8hdc5ktbvzr+/GOu01hNH1vQ= )
+ 3600 RRSIG DNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ xKtV9LuyzQYmhPETm3gbG83EBTx+SbtQPMMG
+ byisttKCVIzNOGrDibcn74EiL4K+pVxxv2/d
+ 1Bs+wPdjH/9OWddsdflwwhbSzB/hhptH0sYz
+ VfLewN4+XXeMNZO7ofvoI6TKPNkti1bxiJlK
+ 7tXprVyQRbqrT23WeHy1zHJ6Mlo= )
+ 3600 RRSIG DNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ F92JDZa+GomHTzEno6YB1oYcnvFPvfRybfhk
+ 9CHJ5MY+elSYVVG27veVYqgEGCshqTwYzP46
+ S0jJF/H3muFXa5A3at+8BNEoKj5PEZFNMe+8
+ 8YVSIjOpLdecPCZFqrjQCqwNUInzrpzHuk2w
+ BOWgLfAfBTq/thRG6admkJ2ROnA= )
c.example.com. 3600 IN CNAME c.a.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- hlO9jq8fIGbacLj9oYvwwyz65+z6ttWGg0Dh
- wel26v08PEEJ19wVcZsXwiZi5ey9xaNG0OfC
- z0xeH4XCOYaFGtKjSAqpT1FLGmcFOqhbGP2+
- 4pxICNlMonG+w/p7YePr5jyDILbTbUmp62Hc
- ZoV+MVNvjFpDbxgHvCpFoGZguqs= )
- 3600 NSEC d.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- yTCDrpHhmnrwD8HxGPwPAXCmCik9aFyfESjW
- 7bqrVgo8/pH57JJxGw1FVdoP46+ba1E0XRmo
- zBdKKjum19SJBV5rzTFsJ58TDxsIeXWgwZgB
- +RKY/peVIEfhuBHfLhdPocWB7rrk0dCDsLmN
- FbmhtNkmXs9CKLYv/ucsXnEEyYU= )
-g.example.com. 3600 IN CNAME www.bogus25.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- PCl2njNFV8UQjnI5C5QUOE4IPETqM3orSN/e
- B0WhX8QRvYRqJgayP07tjgaslUIzpAWo4t/J
- +R1bjfkj4w0Kxk+eABUgyHBq4Cd1EO82L88L
- DVvrDAXxg7Uw1dkeeN8y5ZuJ0tK71AE7XJ7u
- YdTpbi7cfwcJuhRY45NbZDVtLd8= )
- 3600 NSEC f.g.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- zVhwl4EzpNuLNvPr5y5m8hIZyjhMzHSMNPQz
- gMqljABxOeeNw3r5y9NZzm+6vczJVuJstrzr
- n99bHnis0CX9QHZ9JMyZM2+qDLqvFccjAqTF
- TwZBRhYODrI6u61DiRPCum8J2sIiEwIOVW8a
- cDosel0Kz5cckjLJmyvew+vI2Hg= )
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ MCvKWbCBNUANSmRvzR+/p/qtJ7MDwBoHeCcq
+ zIRwrJIeLozb8+tjwk65pR4M936Me+CNLzaI
+ ToNZQecxnZfK5qp68KSKtJxsJ5gCI/VXy7S0
+ mNodC1ER2Pp1/RTpRWzhp3syQ7VduK3iDIT1
+ xh782chcZl2JOMyIHvlqxRNXSH8= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ MO2QcNGMPeDtMMIK0oChbxdCkUqcgtTFPmnH
+ 8pjXnHm04T1n7ABIIXU+NQikyjDw6WMclPJv
+ E6wmPmutp/ofVwvc5sqhePCM5wxfU70zZWGh
+ eAf3uT2O91qA3whptN6n8ATxWU6YKUzsc8lH
+ wcNQCBHZApKHhe4BX041hjxcXYk= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ euNFkmfD0fvlwJyRZVRrjDiqNGjWDKYPEBhn
+ GebVKZXQuoyVzabzhTFggK5IPAkv78VwBYDK
+ DYJ611l2jkspYw7F7BwatMwlo/coCksSmG1Q
+ jrPmQ3dqDTZwbf7w1hQEaAIh2hQuacQh/H/m
+ W1kufmhNcVShIzrmyUw1VpFvAa4= )
f.example.com. 3600 IN CNAME e.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- QLcICtoOCD6eqtqDlawijBoRkruFxtOY2lv5
- nrkQoZa0zarM4Y8Zs05PPjMnFYd1kVgDgzNq
- 4RU3jd0bMM6vdFBDfg/HV1OK98nvA9upuFOy
- Mn4Ll98aSkZ9rBW2nHMK0gxClGZBRSU0983v
- +vcSrrwK/Xr5MLYzJPCyMzmZjt0= )
- 3600 NSEC g.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- zWPwHGblevq/icAJ2PEB/Vrexdk78ZqkQ4fb
- sfKxqHXoXlXvXSTgMd+8jD83rpCwS9ju3W1c
- XF0qcrw7kWVDsjuZB4ynustAWXFa61+S93Tz
- clXNNb0zRFFt/pfhMi/6MG8VL3lPZ3seRUAH
- sNqUj9cD8J3ViCJ6S2tD0EaWdqI= )
-*.j.k.example.com. 3600 IN A 10.0.0.22
- 3600 RRSIG A 8 4 3600 20110319091957 (
- 20110217091957 20058 example.com.
- AhY44yY5dbyJvWFfEjxhksL0Jr2hGy7LAwFS
- nM1+xeU40Z4+xB+6NEiwu+aa52ylbHkGyp7W
- seQ0+8DG9biYIFm4QiEud/jQQIDEqYk/oVVX
- +aJmTYsJbZFVmffWK5oG+/ncP/xfLcnPQ7Zp
- GAvKgnnxSr0B+FNsFGwFrAJpyy8= )
- 3600 NSEC h.i.j.k.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 4 3600 20110319091957 (
- 20110217091957 20058 example.com.
- aS+Z3vh9yrxVIk5w2t5SfuSjY52ylTaKCFoq
- QP5WiZ+Ce9K9E5kenfU3ugmKxU2Ocwl7491G
- 7mYW9ZxfBRnqoA4WZtszDL5g/qGNS0UQm2q7
- 1tVkBQlMt5vXQO7e0mK0upZ2Y+6mllgvv5/x
- EfICd8LbiJuD8PqrixsiTZRGzXk= )
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ AUq/kYNePn4R4w5YddqK07RaFSvCLDVdRPPv
+ fU5ICNb/A6pdmuhk1OHi3iG2LSMdNhmSoa90
+ PazNVOakW5UPpoIdNuvpNudnG+X5792X1B+b
+ 3ZcvPMkqlHKc14/Nh6U0njghlbBD1jFwHiqQ
+ xB4pjcv+mHBuGi7kIAmIa4L4oZY= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ s+KE8eUyftH6PawCzIHLrd9gZo1psXlnU1Hj
+ s5xERhyBCexFnYnIhd6MLmNfV89nMgjpRaDt
+ wrBML9tOqCjURBqBdNrN8hKPtNHP85zxTdrj
+ dshRFhhh91RFohJsGd3e1uFZ0e3eonOSGCmm
+ JzRtM8B/dKzd80ebnFkSjz3yV6Q= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ YHCSKb3hW5OSuqKTPlravCFlwFymQqRZg9z3
+ SD4Hqjny69Lv2NEL9eU+DXzT5sUZn9ipueSY
+ 0/+WGYJUSotgrINgzVDvIlhYuBPvRAQJE+Fa
+ PT8HwO6BI/nw57+zUtnxpnphB9E6OvKNSa81
+ qEvtb/q9AQANp4b/YhmGf0kwOmY= )
f.g.example.com. 3600 IN A 10.0.0.20
- 3600 RRSIG A 8 4 3600 20110319091957 (
- 20110217091957 20058 example.com.
- EEOBQ2O31vmGHuj86oLBL5AmFAV7nVVxPjxI
- +Xvru2Evbm2HJdZalcB8YwrFEdFGMpoxLpXo
- FKevq2mGL0CfwifSfN6Z+lU6/m3JZQ5ugzXz
- c6PFm/KDtCJtWkNIYtHGC4flj2rpMNlJ4ERm
- /U/lfDy0PwPQ0QvYXZE8imXQsjw= )
- 3600 NSEC *.j.k.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 4 3600 20110319091957 (
- 20110217091957 20058 example.com.
- knCwO1mKW8GKZr+jq0zT2FwlPwoK58GgvyGt
- wvJmotKlu0pyYvVXeibowOxacDRx1SZA/Zue
- nkA3dF83GWygxg36WjH3lyN+yaIFkuXtKYFH
- nb/F6tIT6C26gnBJfMBKxm5mh6DqncIMFIad
- p7ohHb/HKjj0CbGP55T6NV6OJdY= )
-*.l.example.com. 3600 IN CNAME c.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- bj2qkiCFVKzkmLafxnS70+gzkTErQgsJK1sl
- SAxObFbBfG9eLGktw64k5XNSX1gK8cswj4Q0
- d/XkITXMf//rVgyRSXFkIRdalhW9VlkqNHll
- muF5PQF3bqz1ec3aVYJoQJurnjKj9YIyCzNm
- Y5gjwqB69xzc08hUM57WwS5PrYc= )
- 3600 NSEC mail.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- W5qj7ZHUIii8CR3sHkLc6ivln+AFK4SmxpjD
- tgYUCWaUd8Y/ahldOzgCjzFY+I+hrUCifd1G
- YLr0WtlNe/LgF9JhbiuIFg+SViBnLJzJAPR/
- yTr9qENKWQABvhmd5CfCsUAW/r8q5d+q4/9d
- P7DfCX7FosksTkOuO5qSWFHiPAg= )
+ 3600 RRSIG A 7 4 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ AieEyxCXhj81os9lt1WfH72+/cm8Ff2IKe+O
+ f9oGk8bNi1EqYGIw8oGjwBMovrfmgxFM7vw8
+ yU2TF5yKjjjIIo4iMkxQWPi5z/COxERXrNDJ
+ VuIgYQB7OgoXdkENHNTVXxm5R97r5n2vBKJR
+ pvfIixoPPmmoWEvGQNd4DykX320= )
+ 3600 RRSIG A 7 4 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ mO/ICPyqa/8kY+9jxVVSwdezxeaUpdmQQIrv
+ Ppvm9Q5dyFguHVMeoRewUoYz129ZXZMUXkEm
+ ZghIE0uaotgkSA0/YjVIMIGAPP5fl5oITKbm
+ GOUE4cZq3w2k0QtZ1ASnv8FWqMd2ZTRS0BdZ
+ NMRFZ/0RM9OJ2mm+vUq08vmc3wc= )
+ 3600 RRSIG A 7 4 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ F3Z83j1JjMr6B6gOcDaSw3I7HEgUBi1aSpQi
+ 0Es2CWc7WlJ5KXB/kvBas3F9qiyC1/Lje86v
+ x9LU+Nk63RHRRFvFCGynrZTFGgvR33ZT2v4x
+ adAExnwOij0e9W4PX3hmjwuh/Fa99lmJKV2T
+ Shw37xX35ahEjIqvJZ1IsgMAy+k= )
+g.example.com. 3600 IN CNAME www.bogus25.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ Rr1o+aiADRswGkANUQcAx+GFYHlWPC9pVx+y
+ jv9JlvfhpO+F6B5SdBIh+BDw57l6TOBD5AqF
+ ZH3hqfepTHL45sQ76+g4h0cwwQ2Mv83+SopC
+ HkWZoTBqOm4o7dETajZctlWrWzYy15H9YWo6
+ VJz6PNjUFBQN9x7qitTc28xynG4= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ Q4Ti66ZAJXoiFlHi6TUEH+RXb7YR7BnS6RAa
+ 4A/7pEia5f6TclezkKLqT40+CaoIVRKm/TSl
+ hglITjs2lezvg4QKPqSqEk40Wg+lIL96+nYJ
+ SnwB88oSJxeECBcFW9qnqbr8Hbo2/4RGXDlG
+ cyfz698QmuenSgFzGYgARPB/dU8= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ eJ6BkMvJbhwfkjn6mtToSW9CFeRHOhA4ffUK
+ zh5iNL5BwZVs1JsTp7Pp9g2BnA/yv3Qt3cPp
+ Y44NjN4+CxQvQ3iSpkwJSG98b8QO7TioMC1x
+ xSpYimqjIO8duuPCJUdfN/tMrbX1Hu0sZXyg
+ RGrNjyK/zdq1GFkq/zKZL5JNGv0= )
h.i.j.k.example.com. 3600 IN A 10.0.0.21
- 3600 RRSIG A 8 6 3600 20110319091957 (
- 20110217091957 20058 example.com.
- IfqXe0py5ug/bM3n+L8vIjgyEF+DPCkWZ1xj
- LmHAYjBHW8fBnByoYNwSBayXJDzpVPrlGiGB
- u7FC78yTqNeeGKgH72D7JgNybpEELpHY72+A
- uYKOgizlOQn+172h5pmQcSNZjfRPVtK5wR3t
- /ZOsz44siyNR3+TQEuDTnZnS59A= )
- 3600 NSEC *.l.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 6 3600 20110319091957 (
- 20110217091957 20058 example.com.
- nTUAjiYPw6Gj+V+uz7gW27lYidi7Jgu1rTRY
- 7GGZZHZRaFtoeM7ymSxZmlOdKrJxsjIhpXOC
- ltU9dR0PJo1OnXKCQPrLjK3nIkNfGVcJU5Xj
- MfNcdW6T1ursO2uZ7lrTOgBhSTxNNqiXln1d
- HLwy1lHgTqNGg8QvdsbT1ixR3uE= )
-*.n.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- gcuk3osH5dCvM2GgfVEogCuSNIQgQFAc+hY1
- igrm4uTT9Q+xrwRTKVqyaIZs/TovhKUS3npB
- 4noVLbGJIlguztNvIgaB9wnam61NaFnBZRdW
- 1guOnkExhSe/dTBupdEKVAw0WOrAOLlt06Fu
- TFAAOBNo6384KB3aZ1RrKUu4Cqs= )
- 3600 NSEC new-fast-box.example.com. DNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- wMenqM3A9lWwZSHJz+7t0hBfTsB1JGK9qV9F
- kGtJRNl0SuZA28bFRL0J5vSKj9tuB8EjCRdW
- 2l885yaKKGSTF3aFzDnF2YW9mV6BadNGwdkC
- +mYguk/tkPNW2TMdrYJC7StXKh8dOQIpT6/K
- oc+ShVBYtQJocRy89hk9M4Ex9EA= )
+ 3600 RRSIG A 7 6 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ aX1wWf9oiP1B3jM1zbQsg2rrVf0HR3MIugsE
+ k3CXZ848XmdLFy6tU2/ZochGwfKnS8XN9G7Z
+ LT+oN/eTYc3F2Mfg5TBkPF990KDwnHGtMYiQ
+ pg80IaPEZBmaY+U8orjUFM6Gg0U2DJOfKBLQ
+ fJH2jpZgqiQYyzV1ho+s1aIOJEI= )
+ 3600 RRSIG A 7 6 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ riGA8p/s7c4pX7ftA1jK+6+c43VTgWYhWq21
+ sC2azv8XVQEoXvhRz/X4Qk56YlihPX+oGn5m
+ LlBCa7Zan+JDpJ67wfBnVlNZCbqxyE1eZOZ3
+ H6o3mRT2OhTEmdyogI/sXsjOn/XXd0B6O0r2
+ /VsSmnpsRX+v5HEzBJ9PeIz+GVo= )
+ 3600 RRSIG A 7 6 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ W0GiAkNUBtaQFmPFD6Vk8MRkPwuRfQ6DMw60
+ 3ZWkL/acliVdPjEJkqo3RnXaJpxs+sa80KUv
+ vO6MUNonsRyBx1LtxNkR74MF+DjDBpN1WqND
+ 2RbsGMNfFvOvQYdTq5C2hXIbz51KNdykm/Xc
+ QcENLRQxkZYW0uwM7SWeg0EB4is= )
mail.example.com. 3600 IN A 10.0.0.3
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- ah9IQBB/moRnqRL9mug+9cEE6Pz1YbJMQkUg
- yzTeh/09bh3POMn9eZqo5bBx6vlDsFgUbw6e
- IclZY4rV4mUeIWz2kEW/ZHc2tADDYVHRTQAy
- 4sy3g+tF3d8OxMQZ0v6J2MTN9DlpVCaxbjPp
- sd0xjJ2uBmn81DKbaZ8UKA5ND1E= )
- 3600 NSEC *.n.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- oJMJsjzzNWihix6CeVihqCI/ByqU0qm+hDWX
- mvgss0U8VXQ1o6oUJ2kXB9agzhRtzo+Z/5jU
- 6zFYajcnzuwD62jmLbz5NAzcyZX+ejyHtt+d
- /wlkYGrumY1B4qB0YGRji66Wo68BK11VZ+a4
- hjsW6qRyHsQeKus3BfdQ2DRHU2s= )
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ TJUSJxyBdrie+gGZ6r3Lay1eeowmYvz3UcII
+ nTpoFq9jHodDL99EXZ+sCu2pf/OMx5Ema3DU
+ MSznJobBsrTGzZyUcCfYbbSdGZbcBGs9izBn
+ KU8HJQYIWGx0WCpuvrLINsv6+1GoaWdemVZg
+ A4FMaGR7FaXif/dI9aJ+tqwp+8E= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ KgyWfvPIJ024fWUzf3z0RCodgiWRN2QKBAwN
+ Mm1XevQn7gp4JQ7mR+FJttvi87Xp+2OJsEIo
+ ueMZR1QD6aDK+sgbsM7Tajhq3Z556FE4rSab
+ 8WJf39LRBry9tgH9FslDuNlIWk/We1H2o6cm
+ eg5iXj0U7X/91lhKgoNdP1ddMsQ= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ pvOxt+RdNf3ua9pN1BVXxLoRHTy/kccP2xQr
+ kxMa+3wvrmc7vML+/gD980xhZZ0rBas8kGV8
+ ze9M2u+cX78/utyxVJYtv7NG+LNOBXIu/7is
+ Q5SKaegZ3asLF6LbV6IbruQ0QDSy41Oqxhpz
+ 9ePzKj/Q9Csp2DWBfwwzxuiPokE= )
+*.j.k.example.com. 3600 IN A 10.0.0.22
+ 3600 RRSIG A 7 4 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ dLQwDNg/9Gcxo/rpskAs8dt8fEOEdy7fFx1W
+ VUu1ZqEPjq00YLW9YHNy/h8ej+TSRUp/HONu
+ 4nX/MflexL5lWuqpszE823Yn9heOymH2HWu8
+ q53vzETP9T/ZCvpnn7pJ06MRLQEch3Z7NSuJ
+ Ny642jlGMFkiP/2ES1dOZu9qLMA= )
+ 3600 RRSIG A 7 4 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ XxFMfqTLkVu/+yk4jN1TLdiBb1GQ9Ixk7k5t
+ X7d/80ACVp4JuaP21JlyDoFHqb+Zi08ZV4ZC
+ zr4H8ljlBBaD90u40fX5UY7t8cdqCmDX55/Z
+ 37Z4YRr/K+qM8p70K4J693o7fvbhmz5OriFt
+ 5QJRTXs5eMqfL9g/0oYQbmrAfBQ= )
+ 3600 RRSIG A 7 4 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ oUjQJX27CxtHnHu2DwGtrLYB/hB9SenofrDt
+ unJLWuyNuwwj7zWm9LEp42stvHRriTf36kk9
+ kz7zHr2WnS5z3+tskZhWQuDx/OBidCfpwzvB
+ 4Y0qEckGdPyT2gk3iNLhxme5A7vmtEUfiibP
+ HWQYtUZPzbXK+4PEAeshF/7x68I= )
+*.l.example.com. 3600 IN CNAME c.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ FE/DRNChjWQr5UQUnr5uyv78LqVC2Eu4z5x+
+ 9eJbUBarGeu+zpMauBfS/Unni8kZ/1LcD4/5
+ z74CyTZIDG1ZaZJ81Osl5eVxCjGbyQNzzX6Q
+ v3Bpk2panHieIzKJdAFoPjgyteQQUD0JmPyI
+ h1VVuE1mPG0Q0DXV+ED3PJbk5ys= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ q3dxD/z/bMhBmv0Ui0nA6ii+1yndPxrnrYP4
+ DDZymcbO5DX5+ZZjOAtUbFLHS+u0ZBkE9zTI
+ fYVVzsqRF8DBU+AhHezsYIJexExrBImJW4v8
+ +ShIm85213nnyU1ZfLfwKpfJXTQ1gPWj6qAl
+ 0UZyPvCq7riyXYHTMzXk2IdzuxQ= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ XqLkSp6x+UINFdBNqFYfqg5qAA/yj12icenM
+ M8VLrf7eSaD9ADssVDSZQ8Zh8TEdTJtl+V1Q
+ KI67+UatPVymvrkCCCZeV5Pj4+iEqHJatpCw
+ x75+xRyVXkWCFTeKXdyTMU+6nBMoE+oSIN8Z
+ D6O+nmGX3aEUU5uyrTwg+lve0gM= )
ns.example.com. 3600 IN A 10.0.0.2
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- Lx5lSuiEjsbXrLW6PVIkoojgWfRTxIxdbVDv
- 8lC5bUziKm41NQ0AVduIY/c08fBshJ83ylM1
- GqsZKwfqSszMIlHu3u5pONkMsYs7lxxYBdES
- NZqEsTsaEmgnMlv6BM5cvstiJKVX7+z43y9j
- XohTZ3G9UOv3B0uObMzabqweSfw= )
- 3600 NSEC ns2.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- rqlsD5SHTL9sXqlqBU/ZcAxn9pkKFZoRjAiB
- kgdU8vExku+wGRbBB+c0toFbmPjJv1E4z9ae
- fN3dfxCmIg049UspJUP0AqWOrtbQqqN2d3dl
- ycJRw5Cpf7qOpp41EGJ/ujPzeIq6t0nW/m2P
- JGkE9arlL8J802tFJKWn2aUc78Y= )
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ O3VYWRVnAspmT89PkbAOtzLoVaCt0Nx2k46f
+ qHRf/iBgICBY0w1ugRbLWB3Zf9AFrJnk0/X+
+ 7iWq80FwRcsSStXSIxB+mRGFxRTB41sHxhNS
+ gRUgbB0VDE+UfMXOEHqjOzKw2L5s4HPKyo11
+ sUmLO9prjHS+/TlWn9QV1OhV8nI= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ rutrFJR2YwhpCtNiz3nkaqwYAfqJklrwT5AI
+ 95T9nUZoT5IAcfhT2E2imm9ovvJ3LHX8eSxi
+ ffLcnhfPs+iXPTK4HUnooKvGD4QOEgN0MCBd
+ S+5dI4tZqX6Oa09JpnyFxHQjT2bHtviNa0oY
+ kdDjeFhl5pfrdTfBy0IeSU7UzqA= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ JLBOPoGSb+/QFg08RPs8Rl3q3vSxMC0sZcMS
+ XRL+OhWOKdg0fHMu8zOJ0AlaFnmQAGETKEGC
+ cUw/wC3HjBE8KNgnDzMP9cwgYxgMauh2+7Tp
+ 6WUe6Z2qdYb5OIfuWjb00aHUK5a1cx/kb+pc
+ zigJlsSVN34EcaQHdvenBXqbwds= )
+*.n.example.com. 3600 IN DNAME bogus25.com.
+ 3600 RRSIG DNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ YpRP8uc0g55raFFpFkY17ZARRML0vuNJJlsn
+ EXUD1s48+is2eoMhZQNXWchmcGrcPOcdGP3X
+ 2/L+laJDLcAYcSQrEJQtcXyjLz5nqaRKm28x
+ 0bsDFlM1dbI5bOP6JSPS/cCHRy1PbfZlI9GR
+ 04kl6sCzAzcFaJKtwK2qLhIsYSo= )
+ 3600 RRSIG DNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ xTzl2eq7QImosoIU4nzEp5KkBWMAeuhSJrmi
+ dj9/jIuXRLBuOe1eVtC0639/SOJWWAMSGD5p
+ 6oKj8lAYhwU04h2JglH5LubpPeV6TVbteZRp
+ 7+Va+7NioEdyxncWoVW7Xsn7lOGQ78++dmYJ
+ yS3x4SbEw0W+jgW0vowJxEohsEc= )
+ 3600 RRSIG DNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ tILOJHeCI6hgEYTKzEyMYjc60FFxHfn85Nhs
+ QiMex8bzGcbuIwdEt5vcC1pO5nDJjcmtyDZ/
+ EOJILY0eaYuZDHwNODG2TEpQo9PNKe/ufzZ4
+ lZR+Z9UnjuZaxAls62FsDatO30MwucabcehV
+ dAiO1jxlg1EiwrhUh6S1ub+hYZE= )
o.example.com. 3600 IN CNAME a.e.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- fjrWtwXBv82jZ6BWeYlfxLqxOvaZNONWqiIF
- 6p3NM4Nwv7O1BvI+Jr9MzxAkk3CkTynGIFQc
- 2wFDrAlT6XnBjJmvNiGf45utlhkifEYOR2Vw
- qR1O3o3x4XMc+gVrmhdMaYAabZnD6YYPEybM
- 6dLzSDMg5K6GjLJglmimT0wfTcI= )
- 3600 NSEC old-slow-box.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- RwVHMNAd0Qdcu85znEzuhPF47UmoEZ0uBo0M
- jd8ySEH07eV0lg9JOpzvdo3gUD6zyYs3xC1S
- CO/RcTGIhEAfvkhV1N4/S5eQzUn3Cc5iaXUG
- WQNpYuE2JKaLr3m3iGmxO2JqkE8YqTyK2WEf
- rAL2SunFcKua1KHX959yNFGtou0= )
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ StHh2y6i8Wy6z6vL1Hi5ANcCCHHYBceKRFyG
+ lvpCrYV3JUIhPIVfes4cRMW4umhq/BrD0+Hp
+ gUroc/B8RKrnklo28rPu9ooj1X16d4JhrDmZ
+ 1Lb9jeWuKrdNbL2rvsG1MmsdjwjWl6MDbmoc
+ MK9k860eEqGzbFDQq/N86j51VQE= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ ph1n8IxZ37Uh/adaYXeUf8eoSv3sQ8fWxHBi
+ Px69Aqh2KSjWbmmxXjlDeqYOJLhURYGPzoe+
+ cVxIqMehVIX7GqKEO5O7ax6kYuXfBW2CluYs
+ LOC+6MmCvEMe8hdinGiH08N1G/P/8zTdPPjL
+ ckWdkMrEqaqrTcpfO2JuyS61wm8= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ mt/kg83oCi2ONU25Vmb9wztOMTp0ql0bJ5TW
+ X1vXheYNcss8Aah4iXkt+ubxTLkFEfqt3W1e
+ +ZOWm0+WwGQMFcwUBH8l3Rqf8UdhDRi1Kru+
+ mI3kuHCffygLVtUilS5GfsGgamItgz6QiE0p
+ y/eLr3oIoTok4+Nrme0t/UKKMoI= )
new-fast-box.example.com. 3600 IN A 172.30.79.13
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- aeEl9FNzWG3QAPjDjCTZNMpO108nKfRqB8oW
- Sw/e6Hynq4XKQuBBKNCvRBujuyrPMSuJdV1Z
- xc1MGKMbSD1ZGyROhW+F1pTyRho1f3V4gmyI
- 318iZuKxy+IbOVimYxXggM2xgkBgROOVI7r8
- slU5+SqZ3c/DfJn3cVHuevAI+wo= )
- 3600 NSEC ns.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- KF7gy4yC2SLwJvhCr/wBiNDWO68ypNu6EyBo
- SyFnP3BsoZxsZvz3PYnG+slYAfMYqxfZAnEX
- p8qMUQeWuZEzZLqmDw4/yrRupzjLDFE581vp
- LVjUxYANKjOvYPbn+bPsuLKG2BuCcpyjLeEb
- 4GrR1PBI6tRPfIyeUo1AUjXzlW8= )
-ns2.example.com. 3600 IN A 10.0.0.6
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- EjnIln97zP0GlFiF8J9HUuGBohcqvaAnCZUf
- u9RuM4YhAijthrv+1vYJj9IKLE7JGXesVXcW
- 6iLsddK05EA9UWcKhyOWrSIz2NmBBo0lj8uK
- 7K/0zAvJ4uiSU+/CiGJBmzXxAQzC/gH4mU8k
- vdpB7AufVUaKGDkB8203wk7LeiU= )
- 3600 NSEC o.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- cOxEjb/Aje8DI82rY7qNowoJ2VIiPOZIhlfr
- MJMNDEiXBfbw+x53ewEj+YpnwwAAFWPrATtj
- C/pEyxGCqwxEYkUCCTaM6YjhAKR0yPVJVkjY
- GM1frct0/uOUuowalGf1SppZsxBKqv5cGq8o
- x8GlBRNWt02ElyO2Wyy9k2TjKR4= )
-old-slow-box.example.com. 3600 IN A 172.30.79.11
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- ON91+7dJR8dAN2SUBZclVbrhRX8BOU5HLRYx
- J8Iy4kiaPMNdLEHqXF2tK5FqSLKkZV9S6k1p
- 5Hl1TUGYxVFq1+OxXpYzgk+Wy6QCW/sxWNky
- ZpZ2X0ZzicI733kJ2YTZS8F7GaU053tCwOmY
- wmLMKa6qd+FNh/xGLpUFrG6xRmo= )
- 3600 NSEC p.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- LFwXMS6XtokUOkda4DcVgSTNpuO2dhzUMbiu
- LhfiYQ+nXn3Qwx0gORJZNdcMmUn3/j8dV/MN
- Mfdil66OwG12ZNfi6LvLlj8DdMsBie/vHDLR
- oUJUXdeQe5sM1rU+QoHfPCBXMWv5Bp6ZV8Wo
- Bw1ASybab+P0JXWzlnKkfzgBUsg= )
-ns.sub.example.com. 3600 IN A 10.1.0.1
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ eujmHzNAKlZqXN9jSh0C9d5LTACh3WezXKgP
+ B/IGo3d2VOxIjiHPLgRIgmyTQOyo+iMIgqai
+ lgws/TxTeNe+olyDo4ijmXe3JEHRvt3k3Klv
+ soj7moubP2nBDUOL+RPGum1pKfepsYzvyp/o
+ v8ngIrMiYinBETP4su9UyXce7uU= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ CKfoEKHS6pzYQZnB+NvTVA5ejrX7sj1GYihJ
+ xCIZ4ATPkuJGPGmGHDO5DnUC485rIxYh5KdX
+ KtUZYOO1MmUBG+mDBZg2s3ITdIyhO4eCuEWz
+ 8SEimWMwfkZg3+dydfNLOC54Wqb13EMIpgFv
+ 6qc/7Qr3uNMx4LAUMD+fur754o4= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ jnisCwvrzRKVkP5HGETwkHeKN6SLRLWwvCiV
+ r/I8L+l1+6E/emB0J2ufm9J6TmE2M2AcSeCN
+ 72/feKcmaKiCk2JfkV/lG8/dR/2NKx1LoIlM
+ /PVL1xz9Dw2j7WV2uhnj0GRhBAkW79aq6Xj8
+ cY2aLX7pg0qWKkZ7E+sPX6OWfpM= )
+server.example.com. 3600 IN A 172.30.79.10
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ YLVX509yH2zq3++9qh5Oy9uZWL5+C9dIn8RW
+ W+lEfoFtwQLpj/y3oIM7mm4xsM0V9o7+z6YJ
+ MxPVV/ZFmBRdGKDQF9krH+nR6q89lCc13t01
+ tN9spDH73S41jnMQw27Y19rYKIVu61MXOfGR
+ 7KEv5WHOVkkER98bHb+bCK5yBD4= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ UVSj/Uujr7B/Jts7Hh1yLOkQsjlyEzSGQyb7
+ yWzRyN3U7dOpmuU8yKZ0vbPscsBS8yEgvtqT
+ WeWfqiJ0/SI6WAY7IveLhzj724w2Ks8JRxUm
+ mH4thHGLN3tbXA4iXWge1WV3TAMuTXZ+nbrN
+ PaIx1PlE0/ZehIAFDrw0e1ffHqA= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ A5Y4Wly9iZUxYf3z1Nx+ehOHpSkHm7DbkP8v
+ mJIUK7g3FMcXEDFqcdbJ99o3ZoAAfpXZ+7ej
+ KfTTiPRrVoKalf/lHVrJsnoF+6LOfOxKkv4U
+ Vs6ETZssT/7HjHlZ/AbT3oi94zexh/8pweut
+ H3pGgxFN+inHP19L88y3JYX0RhQ= )
sub.example.com. 3600 IN NS ns.sub.example.com.
- 3600 NSEC sub2.example.com. NS RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- HjalhqyrN25GoPU0znzhzh58b7nM8N4mLKsE
- bB+edEZOkM15enAhMeKzYWtUau9DTWwUC3Ip
- DeLUT5XKEm91Ln0UnK7GKWfSPfVyTrpNOpKi
- EnCUpk9yVC3OKkYt5jCTlP5HjuLRh7IJLpfd
- RPtrJqJJSNmHt2vFoSdMw54Z1Xk= )
-*.sub2.example.com. 3600 IN A 10.2.0.1
+ns.sub.example.com. 3600 IN A 10.1.0.1
sub2.example.com. 3600 IN NS ns.sub2.example.com.
- 3600 NSEC sub3.example.com. NS RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- NdI/fYvlY5BQsIU98z37XRUtoYL+3d6NJBMn
- erxI0rDgqceMFVI52Hl2POzqanYoqK9QEyWS
- 9rnt6pKzCG3vZv7XcdyqFkP/sIoMNcevZw5/
- JJ172wyrfYRepkbQ20CL9KUGOyQaPJQs61wR
- 1L/78YmA8QD+zduli61hwDRjN4Y= )
-p.example.com. 3600 IN CNAME a.sub.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- DQQ5JhXp1OUOTm6+Rtsb3idf0iO9PvuASLwU
- 9tzKExU9piaTE7FQN95fq48Kv40iH3W7513p
- JKbojGbZui2OR4l4V0gqDzP4MU0fhMi+kmt8
- oKhEY7FlOx09Ei9jS0wWYBnPAxIm5N1NSTbP
- g5tQ7MWYtBNtyyrN9mSdicAaCvw= )
- 3600 NSEC server.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- LcvgnVSYj2bojkEPkHopvuwg097SLoVYVzDe
- N9M4GbHYkPILrdevgmmNIhDw7FS5XJI4zVo9
- xvE+bUMK056uT+DmPSCJh36q9gt2bteSxbqb
- yus9zWldGoUoQzwuvtWcjHwPtSnquL/16xUJ
- 3FPwtqNGKw4Vx6zw5PXdY+jRTcs= )
+*.sub2.example.com. 3600 IN A 10.2.0.1
sub3.example.com. 3600 IN NS ns.sub2.example.com.
- 3600 NSEC sub4.example.com. NS RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- QKnEmC9rfdkdEkLLKxcnm0EkAyW1QI56AuTG
- +Mf2CoD+JHgf9dFKm9EOinM+pHcrlT6/XmUW
- H2IKnWcoqs2B9Vrh9CeC9qXCnFxaNxgMG9hu
- zg4H6LCW0pSKOoq8/KPCrtGGJTn6k8ck+qhP
- hoz2O63tHuIpAtO6jcFL0B5jk7k= )
sub4.example.com. 3600 IN NS ns.example.com.
- 3600 NSEC sub5.example.com. NS RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- pFTM518iEalVbWIisYeXX0mfel5D3EeKL2tV
- e547nz5STOOKeqhaFpwiEkBnvBvbUJLDpNJH
- bTpR98BDLnLPhSuhdQy1uBhONl6vaI6o0+P1
- 2cDaDQWat7Qc0bt2FOjWfhwzEJznqUvHFW1E
- 3umsEPEXcHR4fmdPNnpvCnuCYv8= )
-server.example.com. 3600 IN A 172.30.79.10
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- ptyuguf9rHSyP8q4a+ob+kNl4ns3ZNzOT2NZ
- +9lZsqpbbe6D15/6AVZyEz7NjLsLbSTbmUxI
- MKacxVRUbJS1vQ7pztP/Lms4W+LsmnXafH0d
- Pyj1OpArqckA/zeX05RXizUfqmsWq5thTZZ8
- VMsCFImGqpi+p3wr6FFc6NkuvEE= )
- 3600 NSEC sub.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- Tv46nHdkqO+SBiFf3RtDnIbyom2qGJ8w+ftJ
- EYNfIdIghrR45az4sE5Ax2OzbIDzDycJhu8i
- dSaLEgWASatClQZvzysdqoVmM2ajD+MgKTpv
- Djr5BRpLSQc/qfEINM5lus1Gy1UNruhYc7XV
- ah4fr1LXSrPGoo3bPk5r9Sy2VKI= )
+ns2.example.com. 3600 IN A 10.0.0.6
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ RtHrh3MAsZtWfaIkPvMZZnZZzN2W1umMTkEY
+ 55HH2pnPPE2VATR/lm4xf0la0FeB1jLWLUQ9
+ 4TLuy1GARwrlqswvQNHRy1nwcUdHD6OEaKS3
+ qsoLanpQtik5nJUwM5dx0hMrrdGPRYgyApBA
+ iSbOJI3VNUKr81kPz0zGaiWdTTk= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ n0bkcmtuzcTAk2gSSq+4GGY85YpHBQwXJi2d
+ Iw6GaWoXyXVDfy1+AzFfOD6V5EPv7v5x9xY7
+ RmMiTvl6YF+4w2DHj38Ti3JB8agfzeQf/q7E
+ AX1RigpCgroCcGHbonW5497MbNmnG7CLthLI
+ wEyDwYOLlD7Kbwcgjf9tUxzsXfU= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ Fu11GG7pPC5WN8oNvrRE17Roy9b281A0/WqY
+ XyXSr3CU3GLIV7wg4w4Miig437ShK47GpHLt
+ mGBTNZAaRFQmWIC/jNfuJa/VynDytMjyu+Oa
+ cDpKVaMdO5CFVHyCC25LPorVGZOn8cll19DQ
+ hRbqAld7APpG7mdTdrO/sP/eqqo= )
+p.example.com. 3600 IN CNAME a.sub.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ etVmE9Klo4wb9DW6QLgm3sJckAGpSDjIp10k
+ 7ITKrsiK6c0bMV0rznp2tlWEa5tQkmgTbpeI
+ MxNCd8XHa9/OSHlV6LdQPYtzVujWPftOwfiA
+ FMdhzEnDh4dl6s7kuryzVjQfNCN9NbhwjaaM
+ muyrjUNGFjB2rcimQU76AKJzgDM= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ ztWlq1uFc4gkNpkPRyNGo3FsK3weYU8J0gBU
+ CQpHyE1RrGcD6upk3lh6r+TEiTHlNtAPYfK+
+ RoAqVt9hPgTq6bErrsY53Ux9kVRwEIqQ6vIC
+ S6OEsEJjQkdJZ9X+4LMRxzWNNozbpe9YnBLI
+ COh0bm9vCY9Wryxkrlt9FzWrSEk= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ jOkv1c+V1vaBTcIOQdHlubwMjR2sFYzbDaSM
+ IBRsmuD3WtAmhNDO0yZLVjqkfNYTnA80at6B
+ P3n28xhJUIyxp9k7l2TSCBgHDK9NAeIj2PTe
+ KMLKsj8ZKg9W3lCa1XnMqbi/sqgKBMWt7GDs
+ e6g5LbPj8JVp3tdH0dv6KqRT7rg= )
+www.example.com. 3600 IN CNAME ns.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ CXfi5IjLMEJi/3V2PFsXZDVw4VH4QqrJhpcW
+ Y4do17PP9VjKpoqQBOR8VZz+WIVU6Y7ljaoj
+ kzvktCi+h3ZTa6/xWicAItN3H2/ZQpNJoQOQ
+ hE7O5BGE+/PAvd2LlQnEcN26flcKiutyZ51j
+ AuJ4LPsbmOFkm+zYYnITDbEOcwQ= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ B/G4dvFwNMaKID9C71Ic5DKEUpvSJOBJYqiF
+ whpHMweLnDNTvQwVpxyZMG9tRWzPyDoy3MWs
+ 0+KYqgBqoou51h9/W/SCTMFypmAwVD7Ln7f5
+ 4vqXcP6fzKO14uk6HO0XtMvN67vNQ6MKxSCm
+ 1xrB8rworij3GlZzZAfIaJqpYms= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ Hfb+gJ4MSnrR0ng1EMiS1G+huX/WnI+0k3zC
+ Akkuqfg93Svnkzl7IiYCd5q4+S8MbZJHuqdk
+ jO/juQxdQMTu+pr03u0vJI3swgn5bAnYwEGq
+ /4aWbfbADJ3qZmeNSgqMlUgOzLY0kZRd+hhy
+ h178rruFMiRXZtcYZ82zzAw6Nwo= )
+old-slow-box.example.com. 3600 IN A 172.30.79.11
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ JMMCGey2OfFJRAoBZIq6+4fTF5iu1KGONFnm
+ 9tW/KAzAxAfhJYtrpUOX5mqXPiJJPBzq2/0V
+ BzhuxRaAZ8zQ7xv0HjchGRonkBkD+arCQTlD
+ Z4XBg83SfZ11yBvDjNpdoqhuqmUKKpxAGb7K
+ raoS89RnzG584+MOFiSBjK0BhRg= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ MfXNI2pFznN5m3gFUKZIGRGTwzW0+neZnHpB
+ 3org3XKj7PdEnESBiLHsqPpTTAv0GPMbdDcR
+ y4P2/TCXQajeq0bltIJ23k4yemesEKnENLB3
+ VDFrcH+U0j4Zaj9PMWhaPsPMqIgDRml3Eflw
+ 2mqp30YOHQJKstmT9ney/gUagNQ= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ S+F0ghsUivJDNdZTuEpuz23HTpifoI6PQCjQ
+ xc8rU8yDh1f5mIBttEF1eL6Kl8TLJiHEnp6Y
+ qV1eZ8MzIruokK4sZjbqGT91Qadg3CQziC6M
+ SGBg1dzGnubD4EkqDhUgiReKHKphGOMh6hGA
+ z9ZLmq284c3MhE8HCQVm/Gzbao8= )
sub5.example.com. 3600 IN CNAME sub3.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- AP1MAgDTW5UYOQGZe1kW9qJGNComeMgBtQtK
- PzsIU9y2TyrcSbU4wB8JRFJ1hMZk5wlkUe5M
- yhvKe55wvknSlWOR1AU0vks0kSzhoPxHPxEM
- NpMBV/Dv7NCGivh7LMxr0ra7EENNr4Ojv1Bl
- bUAj8VMuLir8xqv5z3LzWTEVQ/g= )
- 3600 NSEC sysadmins-box.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- u+ulC7UqLA754CiYgKQHXquGhHHHoF3SifcC
- lVHj9OTLXomfJMDJX5UG5K3yODlokaYVWOZS
- MDus3B0LdAVv0+rEEPNxVBZ+t6P5/4JufESK
- JFvxL3pSIU1bIlUZ4VDzgg5h6rBnA/oFavCc
- a8xgf6FDwRNWVxdWcSfH/dStCSk= )
-wwwtest.example.com. 3600 IN CNAME www.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- GNh/COVeSULHxFcEBE66wv56YHNAWsPuSF7C
- Cl2rc0JXlOCDhUqKy7ZKFTbXMZi++upiHpwI
- BBbYLb7mhpLr/zEaOJH8QdiHsE7+hkY7oe2e
- Gz1rvDyjx4XSugVXHr97RhZI7UA4opECDrIv
- 5p3nqGLutSWju/grR6+keppEfFk= )
- 3600 NSEC example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- sRklHhLmH7i22GH8W3j5N6qMrG0rEmUb2+d9
- QJVcnQCgwyeiO38DMN2Vvy8jqVgXN+C5uRHV
- XcvUhJjyJ7x7zaxVKvncwlRBQkGj5hNmVCoJ
- 4gpVzD3aerZ8fwwMUf+ETqBtbkBajsfayEXq
- kpITfSd4Pi5IyVbIr420IconoPc= )
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ LwmV0GyJSmiA04UvzBtEXTqxNGQoJuw1WNkC
+ TUHcw+RMTp3dEa94cA3HvN4J9mFAONI7Py3s
+ t7ebHB7mgQ0ksYbAE+kzr5FeUFR+g3Di/h5S
+ ZtlwfpIMNSczM0OgZP77PPqkY1LPHTRDIXa2
+ 3UZ7FgU6n5k7XA/36SrYALdlN1U= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ UsLiqhIFddPFAIITmc0n6fJz5YAFKXYjuGAN
+ wNam8W+dTtmdj48FOInJecWRX1byEFIdBp6S
+ 5QjRB/vLMjPhIVpGD0WZYj5QxCZZ1gwTXy+P
+ /nN5bkvNbkMPoplSBUNKMmtxOJbbA7ZgOiiK
+ ZLqLSeQIYbSZ89hyxpIZmXRsOiI= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ p6wqmfuG7A8F5zYvYatnq59OlRnD5XS9qrVF
+ ygaih/fN84cOP8O5wXJr7fmuhVWejorseI6r
+ 3m5pHum6UekHf+2xSziyFs3cIJfFKmJQ5uh2
+ JR7sEiIe+hwgSGWVx/RyirW16ol+fWYhYE9e
+ IzzqeswPEe6dBZMUk4OqIT5GTsY= )
sysadmins-box.example.com. 3600 IN A 172.30.79.12
- 3600 RRSIG A 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- ztrXayS9OAxxKPP2U6DxtU3VNQ+aauZXNB+l
- lxhXm2j/dFo6j6eR1hnRfGx6UeauQAdeKQA3
- OKeNaar6KbH9rw/iwnZbErWQurdUNVYvxEHD
- fRRBa1b6d/zkwPcbdT+pSIZVoRzt9LrWQuEd
- 2Gk5cBl6RP2oKxulDeP5XWXpQN8= )
- 3600 NSEC www.example.com. A RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- D03U27J/Yoan06O1qYHavUBHZZapO/f0GR5j
- OfNHxpEvsiQmekeJNtYD/pm3aQhXjn8GDh57
- yrN6TBmo4tleL9M0w5BTT4Bm7yHdg69T+DgW
- cVvgqv2Vgq/zbIYJuBd21doDh2LrkHcMbTas
- FSYHA6OV8p6DzkbkXL9oykq/LCo= )
-www.example.com. 3600 IN CNAME ns.example.com.
- 3600 RRSIG CNAME 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- ElzpT92LMJmKZq37lHmE6tOFDjh3RBdW3wRF
- M63YsLhlP0OFNsbFefBA9H6qQdlV/OlP9QYD
- FRn6hWPkuoelvDjyNdVFPc6CZrns4+eU34Yg
- aGPZoKVszovHu22Lr4soJnDFwRAJ/DXcHMCJ
- EHMSQpTYIg7AuDaBg9j+LqCVKZs= )
- 3600 NSEC wwwtest.example.com. CNAME RRSIG NSEC
- 3600 RRSIG NSEC 8 3 3600 20110319091957 (
- 20110217091957 20058 example.com.
- ycFBDZT3AHzyCklFxMheOfRyehNZNZsXHJei
- h6Fi9AChB05oLVsM1MZqVQj0LPfZC7bJENtJ
- XNwNz/wOJIjX4OUSGQQvEBLa+bzMvBg9i3L1
- YduNOH1xHGYbYKvxUd5b84XsIu1VQdffWDoK
- hkFCBPGlL+A8/5qPva1FFdk3s6Q= )
+ 3600 RRSIG A 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ ItoQw3SlGTWVcpQKf2W0n8hCQzAGBvhMTYhM
+ p5Vq3Ks9Sf8iiBi525i4s2jjo/bh5kM7Xloq
+ zWcq6JTJCyfMRNVmflVqnaiespLlYMiT4GXX
+ FJP/ez1r7IysSRT1C8PivlByxChC5aLFl3YS
+ x5uyFEIlPPcPuiCvcyoiA57nk38= )
+ 3600 RRSIG A 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ rOAEIcQSCNINZl8ZapXg/GH71TeivQ2tec4/
+ Bf8XzyDAtCJoETdRJ/2vA/Gh9mc0/f78x5Er
+ uY9gnqr7l+z7veBZHbqn2NAQxEXd5xjg/QcZ
+ MLUNpytyCb1XltUwAoh8ZmC1xWdTcM01fU+8
+ 2EAQT3cWEEULps0yfSaeb9onx3E= )
+ 3600 RRSIG A 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ ChMtph8oxYQNNllIadTWvtwq7HBt8msgZ5tm
+ t+Wi/RriVxGOA51KKMAj3QSHo8bG98bvQoqP
+ 2o2naWkDrKxUkw/iApwNwnfWYQWTGVx6e7pk
+ FVZtv2z2NFXjoVPHQZ/gkdYBx1EqumJdnzAP
+ C5dmH1WnQC9ixns647lcvJUExDw= )
+0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ msfUzi1BkrU6AubIJlsPXUNyH8frCK6xT5BQ
+ thUm0ftrYIkm7mt6wWw1SsoeWNZYMXGmv9Eg
+ 0tayicAHodB0cAI7AUMR6p09hUC/2Lq5sC2Q
+ xjxpTwEsyhE50CmUW6L4Ro01IKKaKLKFYYo8
+ 23upUqDBGBLaXvZxmWn00HYd4m4= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ D8hb2ltU3bDzA4qIkxOGMHnntavQZ2QXsmoT
+ k9rhzdRdnpjnNKkywKaP4++hJnECwhaqDZmn
+ blkLpWKC71MhChw9JyB+3Fm1Rc6DHKfSNrO0
+ oOREh2GWNcdnzuLilM3KLR0ByEdXRpRf8bt9
+ wpt3pDqU4j5gSbYCtlG1McPX+DM= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ aLq8mvv55dUsGek/v/zxmWvZfHHYKaPvwJZ5
+ zKP4s/kDNj9EJ2R59/kMx5pjCDacodDwAjJu
+ C41TqInL2B31FggghHNFCrX7tnQBnr5fkbHo
+ sPPDYEfc4hKVXosfwaCTKmtLkk2pFGEVSqgc
+ HKFBcOT277dHShmPNpzjSe1W1UU= )
+1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ qAioq4Gv8IaKHCGcrWLqa9+aISIZYW8ivD7s
+ lvZJ9TgfD8wvh8s1Rq1xcUeufxpM21PLqm9d
+ ZQkoalelTlGix5CJi53TYKy4lBuR7OL9Y5Mv
+ hnGcGlBNP+0yv5f7CYx37H2hGBxzVLBslU9s
+ 82eclo2SveXTxIHZ19Gs7rXQ354= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ Wcpxl+9CEHpE1jWrkhPt/mMuUTHVMMjVlS3j
+ Ni6e5ubILs6Ff2+DFBUQiCDo71Q8JJ+ABmq1
+ kl6XHtFDceOg0GWbzvsRqVhsGI5fM0TF9XZz
+ zySY9drMrba/ImpC5qUFUGCwCS0sSK8fzWhy
+ 3w6i1xO5+jJfHmBD7w/eFBhX3UQ= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ X1QSQnz9t1pebXLpbqu9/+SRrw1LX9Ser/X3
+ oI/z3I2pDuUwsH/MaJkzUHQd+z19xFnJPw25
+ 1RpuwbC5U/7s6em1tyqJ+O1Op+1PQV3hZbz9
+ CrrCYw5tJ2Lw1P5dHb/vV4y3176/XzBjNMuk
+ ktyP9HEUbxP+fXohM5KILAKlBlk= )
+3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 572T84KRFBMQUC5O8I2V5BNLNHA8CBQN SRV RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ P/VgOsq/A9doxdcX59USly5uimiWExYdSQzj
+ IQgibgt5GP0Jn7tkAWNfCHCX16xS2/eFTBiX
+ 7faMXf7xdG75yCuH6SHyospG4Sck/S4BymhF
+ ilBv3xfEj/upwjBOX4rO53OpUu/eSVDc4UeR
+ UMJ4oIZ+MxEd3vveb2zi9TZUVOk= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ nRVgUIw6/jJS8FV3OUd7JGBgTAbeQQshwSIt
+ MRqLl8bHewPGHUTYDjNpvVkPhQAzdqeN1Imo
+ eG5TSCcSKDS1/i9PTyCVtcEKFWRRGoqJ4pXf
+ TZDyPuB4tqcu2tfkmZtGOeDnrmV6a4DulKRW
+ 4JDz5X065H5ZI8OOK8IoFqtME6w= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ IjycBX276kZZ/qW/ix4icZ9VNiD3p5noUp1q
+ 4ff05DVPq6alRP84zGqbLZ3w5vMe/drNiDtu
+ 55xk4F/9kgvk6YM62lk9OzJGPOLJUvWwz9i8
+ trp3lOCuEx7FzPKTnpi5YGvHt852vrAacczD
+ dZDcRJWuaLEGmj8CocwvOhNrVkA= )
+wwwtest.example.com. 3600 IN CNAME www.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ T/WgP1/hiPDfDym10VMEQ6nGdD9Tbf9G48ZC
+ Wz//5BEJPZ/dUQ/RGY6T5oKPUO9UEv3v9tcr
+ 6N1vROBkgu7/hnbi/yGkDR0eZC6XZGR6zBJ+
+ X09QDYNDddvWCSO015QQ976IF3Z+p6woAP6a
+ HnT73bx67YGI3snBdayTq6TYhDs= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ hzNM/Vf21K93xVBJjEVluisjz8uscyidcoXd
+ EeFWTcMe1y4JIm9/HUv4qCjAcwQa2WKxQy+x
+ C/N3IgIHNbw4qoHrOEqkBi9YE+cMnDb4fvuN
+ hwxLVp+TObsv0pdD2TUsb7igX/YBTinSAeWE
+ fd6Krlc4MfHHcL9e19SroL83JNo= )
+ 3600 RRSIG CNAME 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ fHA/W3JKDua3rz25CZdY9MRD/IR+DIK/qs5Q
+ QjPIdvxqLGsuuF7Kxze29Hckkm4ph5P+nRZ/
+ 1D5cB58DSVutrEAhegF4UMZpfJjj0vCHoYT9
+ +a7c3y2JJFTzlYmLeNSiDfNgEs/W7aCEf6Mw
+ KEquRC0ZaJqezda2Fmceoz7y4BY= )
+6K06BSDDT661B33QPG6F6EB14TIAJ42D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9CGLSFKECUFG8QODUCMQPMVH0JP35440 A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ FnLE422keDCUcjy4rWNTF+KHGGbdiI+FITwc
+ ecyC3+meN0HFb+OhlI/Nrr8IwdUIqQTVIOTR
+ a3/oZZDtne0XbR6bXw1/AKl+aRXLBsFWVyAK
+ ESLIWQvxaVwWG5fcB9MO1wOsjWpRxG544Ev0
+ 5EDnA2qcdtDW8x+kSdylKgyDcoE= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ sxzypr5kURXb4lYRjOwhNW+ryDpFxd/bggBL
+ 7pEW36NILvCO+1PHdr644gCVMYbqXslsWlQE
+ JCBXeU3VTaDtWrtyl67AxKq+ZtguZVb7hCeO
+ AVCUnGW2A/99N179vOO/1PVPNkIqT0LmZ7MC
+ ugGWTJeOsuPqfDtK++SL8+LtqDA= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ lGQ31blQWd74cSH+4djKZc+bzpz5QH5ESFvU
+ HIuW5NGBUS0qnrIi8lLWyjAarvR8DsiVsyfN
+ jWRlIfviI++o/cq03nWjWNqMqL88l8ka3EYV
+ 6m2yyRJHlJkpcZ8UxwXoksrcJ+9LXmCAl448
+ HpGct8DIFtIojJKhDkTkXRWQg7U= )
+572T84KRFBMQUC5O8I2V5BNLNHA8CBQN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 58KH92475K4K07K5NV8KAHO2UOHLGA5N A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ ZFhKIc1AZKczgkkSDC1KotilNcZZI8MG0E9s
+ DIFiEMpZopagIvo/Mt33m0Qc1zs2c8zH6sAH
+ BBHvFO2GpxQRdQDJ06BZ29QqUJqo4ekA9v8g
+ i3mPFB0UQMYIxXjEQ/u2tucgA1RbRD2Zhr4G
+ bUB7vXOF6z5C53CE7j2dQ0CcKEs= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ A52sfF+O7caf0soRM9e8v1LMTlguJzqFfGcj
+ pq5LfXHMnM/dpVGivmiTypCYhF4th+jtXzCS
+ DyYid6ycFsCHEI2UX/GH46zY9/PV3Qg5YpMH
+ bB5U3Fkm+hJZbOhElIE9VzwdDUUQg0h3lr36
+ uTDrFId9s/eOdvkmg3kIOplsZNQ= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ Vz5KSak6VR2xAasrITcxaYG2cixKpF2e2zhE
+ 4fOKeKs8cA1iJGQPCw1+TCafKdvhcXrGmToI
+ w0Gx9JHq9+JDcSjAsmTwvPwGn0QybHGP/OXz
+ 8MkExF6d9Tt/YX9PQ8kwYgrf2kOewAo5C5la
+ RVoIqvgqSWuBx9Nh1tzUhdb3/Gg= )
+58KH92475K4K07K5NV8KAHO2UOHLGA5N.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 600RRJ34OTBFOQCRPSG5J4F19RM76IOE A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ Xabi8Xuq+lzefpWqbWWQfTKRyIlr9uAPKpUt
+ Ot4mR+80gUrth6Kk+EU03KJU7hlTeRWISvf8
+ CLrmS+QCg22NjeIK4Zf9V1X5oeLR7qTli4Y7
+ XzTyRQ/bZ6sl4azfAfwL7Ipkvj7T5VQ/wYmg
+ SLYH25fdL9dMELM/mgp0h0di4g0= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ kc0m5pUs/yHxe16FVmR2jrLw2hCPtOyumRsX
+ MmjO0V+hSlToKJ3YgsDADN96qC5siTG09yQY
+ XLrQ9aSifIgtw9igbGXj3BabINA7zGY5hnH2
+ byKDackMIliitU0LXM1PMzN8nf9EW01CTezy
+ Ck+MK3AwF93Qq+KxJ+212hDy8cg= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ b2zUsnj7rDfmr43Qwa2XSV+2Z7elsmFHyJ4Z
+ 6LJUKESn/01La7Qdtl8sF489gHpZR+8unp6O
+ QfHO5Agyp/OFt026FhfCbV9DOYgm3lgSFH8C
+ EVOsBN+v03ufrIIWiVX2bMQTJNrXBU4wZZnR
+ ZqWD6xnzTIAzxudmRahS1Cp203w= )
+600RRJ34OTBFOQCRPSG5J4F19RM76IOE.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 6K06BSDDT661B33QPG6F6EB14TIAJ42D SRV RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ L86fCGixazBOgs5RmRerniPJNXjeE5O/LzHE
+ 7e6B3mfMqehojAMudK0ZHy8zTsBQ5af0a77C
+ x62bEbbHi56fDpKfck5r+bFrnJeburjCdJ1T
+ arke2yK5SJJvSAhhsPGwgYluKu2doxXfSGZJ
+ IqLRmX+tghnSBFPwvwckXJRtUGM= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ 1gkarvb7+atyK0MX+o25E0OS9guVXLkoptMv
+ 6axx9r1GTKTmXubDc+m4FzsUyCtPj766yU/G
+ w4SorsdRhRWBoL/50GL3W0Svjywv20WX8mNK
+ TcDVIvWy4ovcUq/UmZhJDF4k66n4NsrGl0m+
+ 1H/NoOMfxsvQeLTSxUUusYVRdwM= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ O/1ebTLAAO89Jwq3iesQziZ5CaFeLUOUMoxL
+ WrHF7zGEkOmRqTp0nhUwL+1mr7aWxkgugF2j
+ 5BEHAtq25Kq2QxGl99voqlGG8x50koS7bpVX
+ g5wdVq+l0TA3NVcd1VKu7ZRUExBIF4zYxtvc
+ 0nHHfHLxzo0WoHfa6WQSEv0FuCg= )
+AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ ICDZ/5MqmxF+9zgSIQFOX1BNjzhpAbl44LMQ
+ heaVXzkTfXs/x+JYuUIbhtYIlK9xw9CvR29z
+ D08IK2rdqdGMhf7YsmxXGkA5EwGSuDbvEo0D
+ FyU/T6rcadaZM8WjPSJX6WxzFryDOcpNvezx
+ HQmJlM1ElTwduh1K6AWp4NunWVs= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ KiCqHwkebsPsgcfR+8TF7p1HW7xW8yApXKQp
+ dAxuMVge7UrIpKCM9ZxjV/O2lsppN++gphdV
+ 8jarDyqNfGz+QLeZqJG1BHEsvHzLvL1KxxsB
+ j2J/mVdp3PgceLC856psxsc3cnXX3pO34I/y
+ Dy6+5cOxEXSHLqMYUoDyQ/KuCq8= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ T8914GSwUmxdWI9h2rK3vq94xx1ehRX973Io
+ LZKiO4HnSNQFohAg16LcuoOEHqdfIxoLOuRi
+ IddfITRjfGnJNhUZnQmRpVDlmiogxsC/uYJc
+ mq3kUibdBZTluN6OLw9RA3mkXhYsN/xrkuIv
+ xUrllJ6K83/3WHIBxfFb7KulZ1E= )
+BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ GPJRQ4SXLTbIgyZpqNndW+K8K504KtHZ2Hb1
+ VuEri1H4FhnCJKzRTtw10yEV4V+VS6XWsWIn
+ S/Xs12hsL0Gx7rnFYMtH7tFrxTt34u6pNulB
+ JAKpYFkrsTaaxLUOMHL6GGKXUaUq5XmYCOvC
+ rK2wBs+0qSEKKFwhBfUfaGefyEQ= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ tmdL9xAC78cwTimpNO/TpSafGcGyT+nIu979
+ /bKF658ognw5ZHBZ2XIvAO+nVo49qacKDweA
+ m5F6Huo7ANEbF/7DS9m1aSu6EzJze6v4ynKV
+ yHyqytEQWM/2zaunvPaOR1jQPqwCUyd4E1mA
+ RxYUxvCzhkRCn1nLa64fPtvZgs0= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ TUPU8dQqli/nfKyZw2agkdM+ZfiLjUL5L4eg
+ N07XR/V47M2ERuHts7kxo10JK0k3/6EK8Oj5
+ SEAkqrNxAkpOGy0S8AXX6pjo0fzfrdveVeKr
+ Sg9YFbMm9qLcsaiPTM3G/UTuLjfyoRtL2FQB
+ i+xAX1B4LWuZJFoA7vE3UaPXY/s= )
+9CGLSFKECUFG8QODUCMQPMVH0JP35440.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ gmFVIEEb3J1pRZnOYUgn/wlBeQ61YfZ5P8Dj
+ HJlN+SgUOAKLwmA7y6JDIdhG3jTOC8qlC+74
+ Yzy4czwapCMtp8U5W25Hoj32sCiS+CMNzZD4
+ 3hVBdm7NQI1PaAZzqL4nAdzZHhUoei2wflb4
+ AiZTVHNyJ6wOXqj3xxAPMKgZIoU= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ ozGyuT+NVqxRINgvFl6u67dl2rMyXEDWEWv+
+ CFGbuMfgfx+fAkcRj/g0r1RxeJ+SG0SY3IzU
+ TSUtTMTavkToBq1oR8uMhZhmeeGD8VsYdbP0
+ 7b+E9XaUuvQ8nyhfxuV9fO0dtK6Vamjof1mG
+ fP2IGH5vvBZwZFkcWf44lys7s7w= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ RU3+Zw8pEKULu2rnCK8bwn78TB24uWynOa9g
+ UbOOqGqLRwtENxVk0KlLLYicN/IOS+2MHou1
+ tzRCrIxa7QoxTKxhJeSbv75m7K3njQT5GlQ1
+ A28P+CbCU93pPzvvOwwfGMwVOcEAkbsnFJLs
+ 2VANXPRhlDMz0sxxtjUjfj5on1Q= )
+9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V.example.com. 3600 IN NSEC3 1 0 10 AD3302FF AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ OFyGfq+fIlz7QWr3/oPOBzDexpQiSxXlxFH8
+ teLqjyVT+wyAQ0m38KcGJzpBkmG516MbCFLS
+ TNiMcdVFqVsXOs8Y/1dGB590C2cfb9lKF6JR
+ n0ARolZ1sToaXYjAMtxZhqTWNa51NwkV115C
+ CkDKUQNqxX8fuCnEweN1el+xIKk= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ YzaeqS7VcDuSSeq63+GFgQnqCzrn6Zw5NIyM
+ m6qRAJozcYAb92BxHsKYv4as8uj9qV8A4J8j
+ w3koisCsueEhgmtDkOU7bBf+CmDVjNEwE2YR
+ WWME52NqHQ/tkaz1wcBrMYlkgv7SmdoikQjr
+ 1HG1mkPe9SCFF3r7N97rhNlrNnc= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ sCJs4XcYOWK5JRscEFfHXnV15HwkzujcCG6E
+ m8GPYBK+SUNEFcmaMc/12afHVZA689tfIH6k
+ BdyCBQBcnbS/L7q0SEF978sGdL8gcwWzVlzQ
+ scpXokXgY8l2WX3mv9ar+18fJwVkfcCXM8cU
+ uBAhCk32+GaG5tbsw98n5wbLcZE= )
+D2S5TIC04S7ORKP09MAEOFV1GN1IQORK.example.com. 3600 IN NSEC3 1 0 10 AD3302FF DV0IMRDKSGUBTBMM94HHURG2QOPJS33D CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ JZW2lYvpmO8BrYK4z9CEGdO/gbOCt8DRZERP
+ h+bqs2qUkP/SBawWQmshPI9gi+XtIh/+w4fH
+ 3IccRojiByz3m1TptDwkR5ay1Us4oRns1S5F
+ U/AYkBvZXwvoYZQkY0QHRwPAvE77jjJRt2BY
+ ffpHEMo31Zv2MB6y1H+UkcYRZ34= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ m2c/CE62AzrReXZ+PI+y4k1JkgydR95TxKQS
+ McC1MFhldTfSBcjh6c2bMco4P6Cx7iixw+ja
+ CaOfHkTqo2NvU7wtBzOZluVguqdmW3SR6l2Z
+ WMG0IIvhc446ybgH0WI9X+4CjFMwa7FMxB1j
+ 1um+Aq1DQNsCpHchLN4e2Kn+ry4= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ pLamZh+7VkIwYqVhZ94/AzVgzgjFqNyq3tSg
+ 2Ncxm3UYxpMPGRlZYrfldUXpD4vfUJgUEmK8
+ 6I1UosgxqeeDk9ZWSBqfD5Wh9/ngCqAQgPRw
+ oTP3WTaxEb6N7ub8pCozHHJiVn8aZInW9Nbm
+ kZQ3xvoOin9mRe7ovFysaKM4ecw= )
+BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV.example.com. 3600 IN NSEC3 1 0 10 AD3302FF CITG8IDONU692P92JJHS57P0ADNMB59S A NS SOA MX RRSIG DNSKEY NSEC3PARAM
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ BnP6ytht0Oic613DxIN3F4JFZu4QB7elZtiQ
+ VXQQ7hpNw6P/jx2KJ+FU+ksqIYAl+cadZzBW
+ GxRgLAKP5r8m00GKfn1WfVrHkBtwne6s9FAt
+ u7B1cKN7Y9J6Tvj19W8uPEAkxy++g5BUrBLF
+ kX5GObd5kuCGBqB4SgwYsN7+GSs= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ yi5W3IGmzvS3Eu4w4ONnywCpL2UhDzr3/9u7
+ Vf2ascqFbmDAaZv6nD6lc4M5l9Crd9BuoApL
+ QVqhLFMbb+OVr2RIQibYf2yElkG6uotMM1vx
+ s1osq4qzwYOReEes1p3cqP4CDv5jrD0QJFky
+ 1abOXlRUj0xRCHhmQSQdqEL5qy8= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ dd4PChhqHEJ+28qWmXrAvm9oirdHD3UkMlbi
+ Q6way4XdItktmp836y505XETzKfjaS4QQDEl
+ Amf76VTH9tDCCPaEoAx2FAp3mEwR8/X51+/q
+ UqyI6Zs4dxQ6R+jZpa6XV2gE3dp+dtgWjy6T
+ cPFKgBMCViayDO30S9lWpkvWgEs= )
+DV0IMRDKSGUBTBMM94HHURG2QOPJS33D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI SRV RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ gEi3yTE7HRiArjBVOT9i2RdNfiYo5H+52Oi2
+ ic7xMQ6ZGoJYn76NQOwU/IIK6ss+9NRC+M/B
+ 6U3gEvFJeb9pYd1Pt5U3KrlZflbS4XVWBPWM
+ rMYgxmXSI+9Pv7mhzdVxqY0C2ABjtFies6je
+ zYFDQCM0KZ2CSzl+1MbLwgAeXKM= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ O8H2yYOYWWp10jANk1KEjxrBUdV1PyqdjWfl
+ MJk5LfP6Z5YkCSZapRQ+B4er8RQDslucao8N
+ lRd48+M+0dtLjBO7U01T95g+lwW+gCQz0vhN
+ 4HDoZuEYpewsj2NGdsVRQ+XlQEDK3ULRgdGz
+ upbpaoSo5ZiKU56emBvf+Ii/mG8= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ OfTv4bNbctSlcHF/yzFzqfPbubU8v8CUqOG7
+ e11r5PlFEJbjYmpM0c+OOgIqDYhk3uUSY8vK
+ sKkMf17EnVPGSxHKYu3DRR3SmX+Jrgv9PbGx
+ P1QOc8NvIEO4tm9I/AJ7DdZD/JzsCrV+HnwG
+ CHjQG0uSUmtcyo8VO0YuaBj7QOk= )
+CITG8IDONU692P92JJHS57P0ADNMB59S.example.com. 3600 IN NSEC3 1 0 10 AD3302FF D2S5TIC04S7ORKP09MAEOFV1GN1IQORK A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ laygNP/hV2kb+vMhexrqbecVRLImwX5+soSq
+ CDo0PQBFV0ohHgJBpYElV9tbril3iicjwLOs
+ YEco448dUSovQjdb210Za3PAdNVw46PCXj6H
+ iPH4sFcLmSSSMZ47Mm8Jh8J4+ERjmwize3/d
+ 3UvVj4WILaEiqDjCw1yBoIB6tdE= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ Bf2RUMaj/YvIaZBEtpEIR84I2t6sWwQJY5fp
+ 4bju8q0fmCr8K69ycMtFDNrmzcwK+HLmDHjm
+ SurPdU6/p5F1H7e03Rw7UhSJHDhhF8kZvY8p
+ Uc6geNfrWBw0N53AGVTI6JocCVb1ptEtXyOy
+ Jl8+aSVqh+k3G13u0lyxeNqDAzA= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ oBGvU4Co5tEM4KdWrP96N1P/ZDHDt8yI0HTm
+ z8bmaBcaSy1IS92xVT6orNyl6m7rWn0EC4UV
+ TZVHslzk2pQCkNZnuBIUkrlShcv7clHAInLk
+ wVFVk4yiCd2833NRc5WcanNrCKyeg5sC2U2N
+ 6WBYspJUQGfqvBgoNSkE4JW37Xw= )
+EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I.example.com. 3600 IN NSEC3 1 0 10 AD3302FF G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8 CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ IGhCvWz93eZHWlqsMNNbTb4NjEad3g8TL15Q
+ yAJ1J/1Dw2fxGV5gJ0dCov6r10BH+WM8JDjH
+ VQAV7ncI2UXiZKJk3+zTDkL7Wg9nmESUMmgS
+ wXwEgObKsQ2iJGdJCEiItTaiWqUCi3EnhGA2
+ 0qngKtz8C/foDNT3eLVbeCseyos= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ zRd9YpFH3JFNlImV7Yu+hpzdwZ/sR6UQ6wiW
+ FWf5N7ZGLva7fTjdhg3wdq5XDNba7wPc5dlG
+ Zq+F7hkAE2xC/VplomblmhDh+40b4QCDGQtO
+ im6BoWF6iE66C0AgbiLs8EfNcnuWNsEDW0qm
+ MIORJAiSfvihWD/jbQxwFCb8+gE= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ IMOZIwFNLDAGeHDKLMCdChQeICgHE5PF95/E
+ okpS42Yu8YrMJPvE3bx92igVCMBkctD5jPXu
+ ZEHE19ZPRDFwE6akGF2I5ffFcENuOILHtOwG
+ eO+aFLKDoIRd64QMeSPyyOphg44Oc/mL74BW
+ gFwtNK3fke+69QQmoA/gf0+BxZY= )
+EAO0AESHP4M49Q5F332G7SOK1JH53NT4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ X/QUrNWKc2lEWDRDrhOzACOmcxNYbKv3yuuX
+ iV5Cl7mRJwqELi38+Cp6r3Hux5utyQD/8As7
+ CIfuB30FE+gkFnwQJQ6SnN/0cTmfA+DXQr0K
+ KmP9VgAjcdjqNg0Ii+6PouhMLV0lb1qR7eok
+ cdhShP3OTn3HL7V8TBI+WG4i/i4= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ 0+IhHYExtbNG79aZuYhlTMkPA0XE5cUq2Ept
+ G6AwlriXydcKw64MJtw0FfRBljjeLsCV6vsS
+ ArrNSTRBnptpy5ChXK82Z93IV+NOzXGrhFU9
+ t5vBmk+JJvKeUV/tRl/CC8S9m6JXeVGidUm/
+ y0WLQ3RNjtCzKPoLlPghh19VgBY= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ CngXdsTmCn9HvyyeMrblrHxWyh9Y8D3/n9Q1
+ JhVzB7jwf2itfRUEqnHGd8FGAR/hhV5XboYP
+ p+3uUmykoTF2yp0JjikZwLHgq7R1Fm9Ctcy1
+ yehmNpa1Sp/UH4x8BmJ2wa40rq7SZyWKkhL6
+ F1Y93Dfqyd9EkHfzbXE8vy6a5zE= )
+E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EAO0AESHP4M49Q5F332G7SOK1JH53NT4 NS
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ KsOrVaAXuBLHZKbWufX6ToCwS7PPjrEdrAoo
+ Vw5DBfCKKYRRJfEurtljqmoYoZTxXUKvnDyt
+ j1HX3K3PMWUCeSruJ6dnT2WgxFDOC/pMatX3
+ flSHbVObEwIDQ0Eiz/ynydDFUVycy1bjDg44
+ tfXqPQuzGvOHL2peey/41/wr+Yg= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ 0512KQdUDl9nLYut0pZ4b823mOo+fPe1TstY
+ 36ruxDUg42vrh3gffP0rTmV5405H9eM9T38j
+ BvGiRtcKC4P/IKLZKz0Q2OrPKaRoPFw5KaPh
+ BVWzrit1vs7+IWGso8Ka9i0eGLOT4HgqM1x/
+ GB0StyEIepOwjbdqHCsHO7FbsMI= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ DB6n09AUERJMJIOWSa9jLXKmgd5q8jqJ4fZJ
+ m3FqEUZIhtBziboYDgvzICIowowCjX3o4HnE
+ i9LGuUgvWwQDbda95TmAVqSrJJCNc24hpUoM
+ zcX9fWPjCJPHWxZ2ChOjvN+3cp6eSM8lUAoJ
+ ahasAbf5BUO6pE1gyNo9b+TsSDo= )
+G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GC9S3VD2NHESSRL256KS0805PL0KAI2T DNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ k+wgT3opBCjyZBY5oJduYiTjnjiNwikz3Ybv
+ Y+i4td/QakMa7bfzKVg8RqFlwj+8l4x8hGhQ
+ kAEgkyFB9i08F4x7ZXYwODSfqFSebvzmKyl8
+ eqJIHSOU/V6F6lUyaBo/9RPVZycjsUzHU1Ci
+ +dHXkad7d2+TMi3Tr6aplQYsqlo= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ K8gxRNkW3QTJscsf1pMBv0qNcBqi4pb+ARcn
+ ASCH1ykdMR9Pvhpx+9G+u9qo1QjE8EzfkLmH
+ Skz3YxMm6Az8zZxXbsWWlscz8aeXp4B6isk+
+ HcP0EQFjFcbLc2LZRfJxTABi7MOwEgyeLIcy
+ 2SjANfi6PxWOp3cHHBn24z06CpY= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ W22o4fdbyQ50Z/Jndnd8ffhYSpzbgw+vHsRF
+ 1sJLXUwYn4GraEm1XnbZyatFGVcFVxe9Q3PQ
+ UMsw7XlHkbGMEm1oyfGCkT3PsPLB2m/jknhr
+ hGi3KAG6+UonCXkK0WGaHRbJHUOdYz0Qzdzd
+ VKV45Zgdx9cKbHvgsaR7hEUYO60= )
+IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC.example.com. 3600 IN NSEC3 1 0 10 AD3302FF J7A75JJN87L9PTVO6HBKH8IPI78IPUO4 A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ FMXWpl6oQPZphacag5FOYqBCUY8Y+zwHjGzM
+ zq8GQZrnhV9Pq4/ENE2Slxl6GBoxP7hqz7fC
+ k69+s7H9hlP1gp0IyzLSWqqTs2UI6VZaA9SJ
+ OBTeRBoGbzDT8uRgCmLuQIp6iVQjgp/xzgAP
+ o+O6Ra4Je6bTTp0LvnRLLWRD+cU= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ FLzncovwrynHUcZAelmmRyTyNf1LVfJFa+Bz
+ CtwTM6s9a/rpkBRPocWF9925KL8ovp/fav/v
+ hHibW1qub6BBVnnluChdUOuFYAuWStqh64+u
+ XuKWJjD6i8Orn3chwmYZJt5sIuEdBRYyxOIy
+ 3IJjfHra3AAbFy0B4f0j8ccKXZE= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ aepONihWE12b97aLYduH1C+IOhn8Ef31gXvt
+ zZ45L0pVsLaAsUoEa3e1x1HsBj0xBK3aYvVu
+ K8gmwqB83pJZ4BPtsi6jsTH86fdHuCQlYTFT
+ EtGPrC0NyzDu45YeUkwDoh9DsS+JtaNz/n1d
+ p1KMYWLGc03LVlKybDZ3z7exw5o= )
+GC9S3VD2NHESSRL256KS0805PL0KAI2T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF H01743IKEGI4JJOMSNCP0VG5S6IPGPIF A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ mbK8uuWhXaxyjYT05jkLfHVgkhG7olI1yfPw
+ pWB5WIFgZnaJiman9+WmM4LV24wmCP0ftdmz
+ pO6gSKQU57J6kks5hguFfkMbPL9uvLwUDSLe
+ mnPKaxAtp+cA4/Zvfo305CvcQFvjmj547S1W
+ RO6NUTlA3/GlfH8Ip8czkcMZfvU= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ zP72CxHDH5bnIlPZNTLSp+rl3SgUW//pWdwt
+ vcH8Jvfm28ACA7uWxT0n5QcDt1cSC+mIvj5G
+ Mdop5eBQsFS6nm4i8vsAlxgLKKpF+Bq+UZ7d
+ Ivpvr6Rycg2wlaBptnPqqhQ0rBDZR0PfK7CC
+ GJctdwwWCF9tN9QnINTwS6CTq7Y= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ QEKHEQJDM9QgRzbe0D9jjttXE4XgIO8Ykpv/
+ UByZYirJRPYrVYTKSPSEUAV52qxBTu+A8P0o
+ 6ZULZaUy3fyh+d61E1xA2+lYfa9/k4mYD/4e
+ jaFEKni//39awT94AlBTzFxJ0j3KpHGJ5XWB
+ murC5SrnLxKZZkbIwulz9G+uJ5w= )
+J7A75JJN87L9PTVO6HBKH8IPI78IPUO4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF KI1L4Q2S3IFEG634FE6DN6E3FGEGV956 A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ aEl0050jrFVhHPlyE/xn0CO4kk0Zq7P/9gts
+ iWn4+s8qaHQYrEqfdyKtQge8YCT5eBvpZOS/
+ qKE3Fp2DFZAbp/OfAJRoGEwgWICB9KpjCf6W
+ FVQHT+Z78xv8PJHvN/uEvL+hq3gaHSYBd2rf
+ mZ6y/baxU3bT+zy+LDlDW2MpQ4M= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ djuhZzKM27N7b6ZsGNvcLYX8QpkNyWcFaBdb
+ fyxJa5Yhn77RfgQJaehHWHX+by5fw4DdpJcq
+ +rTSM5AyhiXVeA8pa/VVrKcH/Im1n798TNYt
+ ut8wJTE88P3gvZyxAWNdXhPxCwe+O73uoNVV
+ nqdIqikvqeuQUopYaY8zrWfNh0s= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ Z7snzL1A+r8TsTzY76d2JPCFSKk6KYhfkTXV
+ tC/qEYHzAZsn4lzk9cLKcEiUMc8UJNo9KO6M
+ vTVef5TE9jZWXy1OhbAtgjCzFfaHpHiMG7oI
+ LsfzMDCiwLNhFSlDE1oybZrng15/0TzeMQ+D
+ M6gHODGA8r++0faiFgw3oTfIi9s= )
+H01743IKEGI4JJOMSNCP0VG5S6IPGPIF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ oRhWX0gctcbRADsspHmDpVzEkEGoe/7Q3D9T
+ L81bwvQpDKfe0Xa/ksLfHdElnj44GzK6CiDg
+ 6b05S4yKuKUjd5bbx3wyA8Wl/hMphhdDn679
+ zCmi/+CFHYMTTXZEk/BTa5GrMF1Ra+6axytU
+ AXzHYRSF8u21f/8mx1M8Scn3n9E= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ RMVgjtaxet7goMfOdZlovbwoobRwOjABu1Zd
+ HhAsygqytWXgrvb4GSBa4OgjU6wnZdP4uFpt
+ LeWINpZpaEdLsrw+Ee4hsm+ws886QDEvUZOH
+ lvIaRro7gJe/cXHydjFpXNDvVN4r8PwV9ZP5
+ PL8eshnUrhaDKYWygR/A7Ahe3Hk= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ VVHm6YcQyfozsGT/Im3xLGvRTy8tBpvhXtRP
+ 9qsI8U1QRURciaMa7NH3D8umdxpWAMjTv7A7
+ mxr8PPMjCTZlVMIdacWlSMTW7YfYmMjnbeX/
+ tRVK2RGKOgXmDP8sY+TuQrVq3w7UQbTmpWzE
+ Id2tmEhSb4FCAUe1hAw+jmQs/bc= )
+LMQIHH5MDDR9PTGEHOHA5ND49685RR01.example.com. 3600 IN NSEC3 1 0 10 AD3302FF MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ TTRWTk11fEIZt67lQ2esQ73vETMljLS7T9EJ
+ R9IdbaZwtCfyALht+LIw3UKAzuvEahO9m9c7
+ yJA+2WalAv+2KXu3L3iqcVKF4CPRR+7Z+Nxw
+ +D09T5h+mEzPec73tTpTSG20hK65jpRd8QZn
+ t0qsAgYGKGBpYG1pYiesuWbH01g= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ XY2wBbFHrXJ5B+Kd3o4AevusyoEUvK3ZUlG8
+ L7WYDcuopoGIMv2BuaIbjYON2PjTc3DH9iRx
+ gMoiKxhpm+fH0dCvH4NVrxh+j1xqgGSjteNq
+ zUOyxXSmhmNOoDBiONzxWqKzveVF8mHRCEPr
+ EGx+LKO4gApI9HnE1xzqOxsNjNg= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ hmqTo+lS7OX5KUG8mQGbYz1bUE4xleqVYOq1
+ mJRjHAwWcLX7u7/oHDDCPlqmBWTEyLB8RwBU
+ p+QPPnJPuN0AQhUF8SWivdDQ4H5uzoOd3xIv
+ +IraKdp/S3qR1DDo8rCb9KFuLIhTd0EDkk9i
+ iF/ov3pQAEpEDeXgLeXMw73COqU= )
+KI1L4Q2S3IFEG634FE6DN6E3FGEGV956.example.com. 3600 IN NSEC3 1 0 10 AD3302FF LMQIHH5MDDR9PTGEHOHA5ND49685RR01 DNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ X4P4YY1MsXI7TQsjxNvVSxbPuHBOnAanBu7n
+ 59EYn88vehSsSfk5KnFurXxLrVF9w2friu4v
+ QMA97HwAezAq/JmDWRctDSAZTNO9zuLkeKfb
+ Ux5jAmZWN8c25FQc3DqbbN4Flp7e56aTMzCA
+ PzXj9E5E/T6Fn5nqWVt9QPrFTpw= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ qGLIB3Cbnq987NgFVE3mTjWQVDrrWgDVDKCT
+ umklyY/pwr6zooXROYhu0hazTs1iLqKvYfgS
+ khfNyU+ulLjsbDQ1lnzMd4z8n97mgG2QzhwY
+ apx3e5LUcpx3oTvXPC9H+jA0anMG1/VwPnwU
+ qehhhR8WZRyCnzVO8Eje1/9bonE= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ N85zcB7Q4vImuCyq2MSxd2E+iwOzHCuuJ7f/
+ LUid0XIfBtG4vRFN3yfj1JDmxPvuYuYhsrOF
+ CAgCKWFmqtKDuRU7QZOH0RBGn3XeDzNBmFgj
+ Ep62rh/ppPpnRZ2KmGn3wA8R1wZ0At/NtHfU
+ X5VyBUZkhMg8/+DjmC+rTNsRfQY= )
+MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OIKQOJ12077E6HOP6HHST9DHAMGPED5T
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ ngYCZ4ptY2sAOs3nNWekbB90cbhxXuQ8Kpdj
+ 9oUlzVnYyqD/fZ82l+wXiOAbIH+lKxdN2Q2D
+ NjJYaimQpv4UoOL5zTfcxTfVoAmJ8S5v7Eln
+ Bk0KZyGuSvU+pfXkLZM+9P82XmdI3maa9MZh
+ IhnDZi2xXuXIYsqXk1n3/wucf4k= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ YBVuPeXL+OY96fwlXYPYrc+KRXubunNndwpM
+ UE9SkaL/RhurQ0xpXjPBpeThcJo0gKGZa2dl
+ f55acakc5VL4i5MQJx0uGP1XFiqJkx2TVund
+ sljAffBm7Mgkonumg0CcM4qmx7LT9SrH3J/w
+ tvhqbjvF9Czqb13usaqiurU/2Lw= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ Obo0lj3v+eAEe8Xk4aSow3GYTMnK5IAtKBMo
+ Cc/5nlij7T3pIPt+q6EbWcFpRHDBHEJp/nm4
+ Ic2WjTbmlHf2o/3w7TC/TcV2qIxeZ8wj2cmZ
+ +TrfxRSON7ybKqrBfAP2ZBlLcg2Ik0fbX0qe
+ H2L2UCR40CE40YpnCvuOdoiGZ+4= )
+OIKQOJ12077E6HOP6HHST9DHAMGPED5T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OTMDSI120AJGM768VIKPLND04FDSUQSJ CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ GvZZoTVd15j1afy/UoqeYgXsqoO7+P0agD+h
+ Jc/osBG+9u0FtrFvcgmWPVWVfYSiGgtcai41
+ D9sJf3bikuLMdn4HYkZGehVuEM2Z7PXFRVVk
+ NklUUxxXquDo4GyHOAP/44/l73u1sCF3urof
+ VrrkQ0CS+OmEko/vwl1URkl28p0= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ HWdQqAItWDdlnydvAw9wZFrcSnzgrPRBlMIC
+ SkRHWe03X0VQWksprbk6lAJH/DIcQ3g9TSKV
+ W/v+ye6AmhRMKGmebMTabvTxeBqQ7YIQETso
+ SBUR+a//TleRx2wAS0XI0RQOyAflCjZ4J/Us
+ E4Ma9Y64AYNo9RUX+wg//d8RBzo= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ pIRWEqeSijTmMo2pM993IPbzynp/hg5Dtwqt
+ 0RzOslJ0k7KP7EX5ImvlB8igRjnmNkWJ+7jT
+ oAdQXmwxN7NZgs+R/e+/312YYm6WYWzoM8Zu
+ tq/PFwPggDeWRlE5dv/i880SvB6V8X+GfPd5
+ Kv6fxWPuVo7HuphHEfV40thmYyA= )
+OTMDSI120AJGM768VIKPLND04FDSUQSJ.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ jZfAumkz7cHAi7LCOwA5WfvxSbgYbnwvKpoJ
+ 5pEwKN7fjIgT6EGrrQ5PgQNqPnzGGS61cc82
+ zMj2ExiYJR84Brc/l43dCkq+IikN3sf/EmNU
+ cwmF+qYSsbwUWV7uEXd+d8deYAhxO559Rrra
+ +11OeNNlPsaBjaS3cRIJRM8S+Zc= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ HRl88fXi1YI/C6e9cQZLWBDm20OSqTqyjuLC
+ 1zdvUES0bo+KnTnvwfrQohJbldezjNyJTihl
+ KZYKTdxxoZpBY76YQIn2fjIz95o1r4VuBkQX
+ /QEXTlSStnSDe/N1xhqvigglQb6CmVOHSJXQ
+ bB17NNReYLDhph23URS68YxYJcs= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ aF3kJqcbs2+3CeHCxGhYy0PNHb5reqKrI1SS
+ FpJWjE7z3bPq/shRoDaJhTZzryS9Z79ZsNlA
+ m8CJeu3gEdZPIa0iaeBtR0Vk+1LQhRhfmaJk
+ y4fELM/Vpm3C+6A8mHCNL4K+kK1wxdIRzL1M
+ 7MvZXmlLERS3pU1XrznboQGN150= )
+P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7 CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ HFoa13mfo+lRQcY6Y/9iM9k05dj0UxOgmVlk
+ o2p8eLh8gVZBcEX3vZYEVx6e5RRqdfxANC01
+ EivLSMDAY/y3Lj7ZSoUX6TztjKiQ+SRdkEa7
+ 5RPgvRBbOdfZm/R7gsOnUOXKgFne1wCPzI6+
+ mEQ7JgTzZUazy5ggC6F3DPkDf6I= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ 2Crtwc7SjuABVPbfojQhXFzhV+dbHIfoxmHP
+ puFDUHszttyhGBSgZ3zwJ/J9+TXqq4M/jP4B
+ 2m4bx9eoCXQtUdkxAmPCiJkbkvyYTsE77lWI
+ t7z18GH6BriPYUot/6EeYlToocyZnEoeDPDT
+ +f9nRM4qL8Jlw8KnXXG38gSvkg4= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ DZe6ordphHAB6ReqwVAp7V0c1XYd1l3UZdkN
+ uXNg3JM7iYmoh1MJu9a0Dj6FSu5OyWjoTu6Y
+ kNx2m0XXFRvfXiEH7xk7ke6Pf/eQ+xIjynJO
+ uhZL4W4D0ZnBpIaXh2jVilexNJms21GyiUZ4
+ Q3rODRmym/KG6wsC5SlQSm26k9M= )
+P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ a7ZImTzIoztA8Smg0vvQAZ3vC14Y/nb/60/4
+ eHKKjBK1VH/nDzuVvnpsCEBLJWm1nLuvHqDg
+ 6C63qxZbnclOwssnfow8aIV5rbiKBk1HHoge
+ tzxJQYe7a2hotY7OTA5s+ncJdyUuS8w7VUIP
+ JIrF+tE015qUTaunILXfLydQgO8= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ 2X+O3SnOGNuLp5HXNpiuUHCspLQUCagtU5uQ
+ 1qxuLLrsx053wNIJ9vC/BNXssgdZggxYpXqp
+ 1nzpzk5dK4nIwmOYGhJO86/FNZu4zgt47yQb
+ HEfXI30hanTyuG16kNVGycpbPMyzqKEAJN1+
+ 0Jv30Wd/CFjnBTto6Tbq7fEkBbM= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ bQ+F/eJYMogZ3b1SbvotL2/Aoh+UI5/McQIF
+ G9BB+1bQs6tqLszPx7P8PjvxJDxt8Q493M4l
+ INvgZDQQIaFNqMMEh0Eus17OAx1EqLhDK69C
+ klX1sXbZGhQqNbBWvTeaF74T0tFRVLMgtIFx
+ /Np2gCA42NGQskIsBGN4r3N0tqg= )
+PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PSMSPPC19D8OAICCQ64C7MQ387MTVGC1 NS
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ krM4mSHU0B3KtQQVoFCBpdAecqSj/7Oo4cyd
+ YQNuF1CvChDTHFGs5BjpMzKxrBlrNH7wXk6C
+ Z3kREpgK+uNRU/G3XPhYqG42lO/WHHIRiWBT
+ iEcUXhpLYLto8ro0UWopUPRRItotcjXFhSNJ
+ BzWcWphP5+fa23odDEPCO8ZRyR0= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ KPEs6aIATlvmzk+gl45yXM0VDYMI3fE2uHAR
+ GSLPehUZDXT4IYdERA1eQuiAfMkadomjWoQ2
+ D4VvfBf3Ho7ilGmsms590NvE+W1UZTF51CjD
+ fyQW2+34UdgsNmNm1dIKv1sq6llQSHSL8kzF
+ Aum9ohDU3CS4jsbj8/4LTZ5+R0I= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ K41ckswo80M0l8+Cz3SVDqrFBbXfToKS8Gzx
+ pr1HycM3GblmriCBdIgxOAX/AuZZrDitxkzK
+ D1hNeKqAmW+76zPw0vxocX/tdnjYgHodi+FA
+ dVzOaMlbAT2gAOUp8BeQOgaE+k4ysTqYt2M3
+ RxOB0zDtwXum5/e4ZYYWNmjBBcU= )
+PSMSPPC19D8OAICCQ64C7MQ387MTVGC1.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RQK67K3ON1JGJ60JNO4883D1JVIOIG2D
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ VsNIjTrZUt/0Kyw+WYP0P1F2Xq0BgyZxiUBT
+ jwFp5etUAx/fx6thM2L1mLadUpb9m4R+JxXB
+ b3/fn9H3E+oqvlzr2p/LGcqASohdiqmCADdb
+ dzcqqYaKbqjUDsNsJuhGz2iWSccjOTepg4kn
+ gFdp5em/jmqYr5X5xZuv/ZsPWRE= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ Ouj1pNttVU3EPD7qDicNu5W3CyECZjojxusF
+ cibOFBQwLkK4a7RnsTbB3EFuW06pMpo0JJ13
+ 2FIvwOusess7AgKC2ATyAgTY3lO+Ja7GgK8y
+ Q20oxMw/wiADKJqVNoROUPVacdSkU+CkBC8o
+ CvNXyPrro0g5LOzSgleeHCNSV4g= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ DY0n5eh2Y4XcNTCWQmDez4EtkbIcRLLXSDai
+ iPEnk+JITGaaghxMhnvdSAyl7OtQbWielh5i
+ L/toRRJfWA0RcmWvzzNpNZm7EP/+I86KTdCw
+ fUPt9hU0XTzyP32FYcw+NosauxrMD7prhE0H
+ lyXzYwT2m4cnsSqvrAIfZYrlFB4= )
+RQK67K3ON1JGJ60JNO4883D1JVIOIG2D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ bWfMW3+ct/fNIr14DZxhQSdC2xqTFfSTFzch
+ k2+zrsoXFL4JyD8VC5dUmuvE0JHMLRBQs2SD
+ T+H0L63SV4PZzyijo4lLSmz0PzdAEaCagktl
+ pwD5as8jXb3+uUx1qlrpVht2QuwHjRm9AMTi
+ YZmX6wYEyUTTC69L5BC4VvEkVvg= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ zyN8D+2X2PEvIo16h6sok8m3M3MCVqiT6P0O
+ sqSKVKoQ4+xzxpIYPOUPfRH3RWZ4D03II1n7
+ 2gtMCc1kk8Y81D8I5L0r67WmAAj6QNtL7jpd
+ jghl4uyHcp3yKy8GDaKreugWgqZ6ew05vXVf
+ AbeSJSXFX4+j8TfF3z4M5xnWpwQ= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ Mdfdwoh4OlXhe61DmYTzQouDjcvfMLmAQihD
+ bLy2ZDMsPm6cv3GykhvrVPMVn0P19kcD9hqd
+ LIKPQlVcrpP+H+WCgDI4Dz7UjHtmxUM2s6KQ
+ +GzgkD4ttn07cjY0xSrT8lhpPbDiwK4V+RT4
+ pme25SYDQFbcGog6IgQycgrWGeA= )
+RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G NS
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ JRrCvpMfhrk2JClELV805D/pt2a2YhBRROOt
+ 6dUZ18ZVQtXPOzvI5TEOuhFEFaBTPC2PrDfX
+ YBcM1pf7mwD5gTnFhrD7vXwsR9FUDw3sUx63
+ H5Lkp/zZSqt16eBUmwYcuSHceJ3qRrvmgfi2
+ GYP2c6kft5O7DHXFoXKcUBVsuMQ= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ hwNx2shB/t2gB/uc18S8Aaw3SXjkJq7txozP
+ az1JyD14ha9CpzhWMEv0qzENQAFezTapBA2t
+ T1FVUaSb3BaUC64w60N3bjmOQk5hycQ59YdU
+ Nuo46i9o3tWgr/1Vk1ZTMBw9nmXMY09AzLYa
+ qUxrgVo7IDp7HoE8UFl6IR+QqrI= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ JdX++j+SKyIpuad/KA89T1aVWR5927xQLK8M
+ 9WRe/JJEaoJoi7UKboTlAQ21AuGvGwu6wB8l
+ T66ZA49z5LVU4aq/TLI6u7OzIEdldmypbtjB
+ +xTvlLApJ1Z+CouMLzswIjdrOzBU8Zl2i21P
+ Gm2Je720L0Sgg3WCqL9rQAEErvY= )
+S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS NS
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ Tu+XjkIiVrDubGLnKLgIwiP0V1dQvKXVQySM
+ A/qOj0L4Eh38P90bjoVsD0Y5Xt9TEhbyShgX
+ bTJ1K4qhLX5iMejg8XHkgxPM1SckGy8xgDNq
+ /udOmIzHSjh6Ac9xHZv6ADvahqAQLNiuso2z
+ 8P99fqfqQVIrdBD9c2BEKs0Hdao= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ JWLrARNVKUnnwK2DX9Y0BBaDWMuVlNs5EN6c
+ EAnPmwVF4lXcD5WNkWSEmj8c5c3R9VQJAx6H
+ PhpWuw2olxwPV91CPeHOO7Mw8y5wCXcA4Zoo
+ sXbw/WfpjLYAPdZ4JSF26t4NEjQ7Zn7UNZXT
+ TCBJjHxdFTEGmc6852z1n47lDwg= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ cLPQugaP1G96bBA/u90h07bXtzgK+rnNmdOM
+ /g517Rb+0GwPrJFPNXKN5okoL3iJabyNk5DI
+ BxlkXL3rdXy6KnTBJA4yIFaoR3YAl0QtpuJi
+ vcpCizL6aEiQKwq8yTgIIY8CFt1DL74Oy4XS
+ s0lUYlhApluMNBGzE1LP6OIKuMc= )
+SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF UB8IU759M5EE63CQBISIRM9C0V2RU1RT CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ GacQYyh2UTMay2+CD8d9tADE4LWcflUwUc07
+ 6tWksDvwyj/Rp9gR6p074kvghPhRS2h5F3Ik
+ HCxzNY61If8aCaOlB6lrv3YMfiuJoITFisqo
+ vQCNEtIriEENdFOfGEMZonw8WMKP9fnw9Zbq
+ LiE9/zcKCcxN89FVxSz2PlX0vEo= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ p+xzV4l5PxxSyvwiu5IykFbYxKnXgSRtHgYz
+ 2+bCOMBGyv7Snt/VTkZNulTqBNxEXWDZRnfP
+ oo+2ingu/gyInx0cWLcVxVvHGdPntjUb0gbS
+ Y+dlOh8NvjhkdEpahZHMMQDPPdkFS2EcOUiV
+ T8WlOKz61Qj8C+a4dwpW8hdJNn0= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ GHtvMmQUXC33TVgtFdqaiK5jVJCL1WX0LSW+
+ WBmiAejPji/26k2uD9Bc2jysowrHD0eUOPYa
+ yhwcsn+SUBWN1QoTcJvyyx/vtXiM5xgqsoyo
+ bgZxtO33SkqoLUEG61NvKJKz9vXuJtpjZAXF
+ bFX2l4czAEXwmdLW+IlhtMwAbvg= )
+URIDB302IVQCE7DQSKELLE9LEFOHV0LT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ bJWx87h9mPriMU0pNbZoM4ejR0P57hiZ4GTU
+ CGvFlO4TZZ/4i/iPYDN8J46rA7diCaEaOhIg
+ m9SeRvUrIiUw3WdI+7sWNI6atXlaNM+LY9un
+ OGueiKtabYt029SlZegkWdCqNyC70vACtBbe
+ 06d5J1HO15wTrtCFNP3N4MGAuME= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ qu6bqA2HCxnxvtQ5ECzMh3gm42tZsWGzC+66
+ s8t97N+HXM3vv6qLQ8xjDwF633vtMY7Uuieg
+ 4XONpJoU3UxyFJ//900TuQ8WPHzzwSm3ORYM
+ 8BiKOn/eg9dtIxpYTelleOSzmen3979NAelQ
+ yjmyx+nNzvvrj8ZEBmB7OfB8oAw= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ WyR0ilIZAADX3HLXYuyvlhK9yRAbPFv3vtOs
+ DIlg8Dj2F5hgXUv9V6AbuK5nEz19S4og3E72
+ JN/Z6QINx9MhZkCnzYFOHlS6GS+zqayPk6kp
+ 3BGzDZ/jYJ0KsUGrTIE9ritV4lfs9Ns5jSS0
+ 0Hg89y8AK8KoMpvnTuzTXt/iIQ0= )
+UB8IU759M5EE63CQBISIRM9C0V2RU1RT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF URIDB302IVQCE7DQSKELLE9LEFOHV0LT A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ BKqTnlAxyPcDJbWH7r2o2GS0wipIPD2fj40A
+ MWIF8hOtF/NwN5WAbdVjoyVGI31G6CTDGdD6
+ TPllaiCCFi7yEKm3/vBZfoX5uZhy96ln4G/0
+ SbRdD6Ooy351L6HPlfwJLmb5a7CBBkBmTYQs
+ ig1o3XoicFPRQG3clgX9v1UQrIc= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ qWWyZ2Rh83GyNUcw6ftZSDCGrYvsB7E4dHat
+ 3+reQZrNjmAY5GaIvUq+v1/Bp0EpRlbx64C+
+ H1MrNDv3ZQ7L4O/Mc9YnOpWpEDs1g88ONmVK
+ lsZ2vBeT5PdEVsM8VwxRaTLHzZ+2ddn9/zQW
+ fjb7woheUAr4U5ga4h4XAcHh6qk= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ E6d/cFSl+89rhmjn5OXRaN4OcHmdtAgqaDQQ
+ gOk9EwrQq54XKgzYa6zT0VBzznQZlbsOW87X
+ jp3C/RBdWR7VOV77btuko3jWYYSVvA7UDseG
+ pr7TNEZSck0bJuih5Z/axsGioLNiUKW95XwB
+ 63n4EGBC8iIoekIDVi4b78OCK1E= )
+V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7 CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
+ 20120210113926 13760 example.com.
+ PUxRemQkIzsdDafT73oeBF6U8M8iFHdL2ACJ
+ h/Kw8TtZfZpulj2XxxeU83BqAICpZdkeqbZi
+ YGJuqIN3AattGV73O7nv5rjIhlhgDl0UgOFu
+ 5cIC1My6qYuqMEosQHAkokq40ZhIcWEFOy7P
+ S/Fd2r+ERPkLNDUGFyIbQzYEpyA= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
+ 20120210114013 59507 example.com.
+ lNMX0meB0th1kePzZAWX3NYUAEGNJbCJmeUA
+ DsQmct5CmPObBaUjUQF1Y+XFLlme8BQJVUnj
+ GfthFJJhPmrW4AvDNMMRbXo0wo4hIWn6tlJF
+ xkTDcFB1BRz0w3Dz8cuXTxH2gpUbtbOq5FcG
+ 5ZmYDo9akGuBdw9okfRuZ7S8xm4= )
+ 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
+ 20120210114036 58574 example.com.
+ YI/o1LESLnn3xIcJIBJ5ibKs2ajwjml70lMS
+ 53nM+EMe6lKZdCmdB9BRR26PzhKNngWLakI1
+ 1XarAJD4gM6hJf6DMqSWbrOpfVpuePFTiVH7
+ zkJfa12Qcjx4CFviV0cCdnQRVAsv2X7ajLcZ
+ 6QszvmkzIwR+HdsY9WeFBZ9yZ7I= )
diff --git a/samples/example.com.zone.signed.nsec3 b/samples/example.com.zone.signed.nsec3
new file mode 100644
index 0000000..88a28fc
--- /dev/null
+++ b/samples/example.com.zone.signed.nsec3
@@ -0,0 +1,690 @@
+; File written on Fri Feb 10 13:41:08 2012
+; dnssec_signzone version 9.7.3
+example.com. 3600 IN SOA ns.example.com. username.example.com. (
+ 2007120713 ; serial
+ 10 ; refresh (10 seconds)
+ 30 ; retry (30 seconds)
+ 2419200 ; expire (4 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ 3600 RRSIG SOA 7 2 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Ez84tPNF+mHlVMRW2qXS4yLcaKHtlqAm7bmn
+ DR3jI17pwqUyJ+aFlZcuWLbGf8ipWfEFN/zh
+ +sn3lAafUlbuPseAgqOnaWt1OEMxPK/Fj4d+
+ DodZfmCXru7Fm/baTXFB4GH94PeC5H5mqCPI
+ oD3m0/c7OLDIF2t66xs6XHb0YB4= )
+ 3600 NS c.a.example.com.
+ 3600 NS ns.example.com.
+ 3600 NS ns.somewhere.com.
+ 3600 NS ns2.example.com.
+ 3600 RRSIG NS 7 2 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ BauFYgGnXIOYPg8vx45JwlTJg/ZGrefAC/cH
+ uOpCgezjutVKsYAwKjTdUu2/YnliLPl7qTHV
+ wMEandEUUBhtMmaMcEqssw1fjp6hDTnPzjKh
+ WTaZMObi8oJzwTg9rrtlaqh9ruWlLvwmX90y
+ /WlIDQBob+YcrkhtmtRSadojRAA= )
+ 3600 A 10.0.0.1
+ 3600 RRSIG A 7 2 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ uOArtqyKZB7f5iYvzRkyp4B1doREoJ4Mnh+P
+ dSmpRn4kklovuAB74kNJCy/eb9Jajtg1Gvf1
+ ryNFdyRjsL5KYG0D3O9CljV1/9RAGpocp5HI
+ BWOgjOXPT+qpKkaV8+XP5c3uXsgsc8x0Xbd0
+ EUqH4MF8mCh32m/TWqR0xhW2bvw= )
+ 3600 MX 10 mail.example.com.
+ 3600 MX 20 mail2.example.com.
+ 3600 MX 50 mail3.example.com.
+ 3600 RRSIG MX 7 2 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ B8uDHsHFw8ArmcuLU8oh7LppxtvDSGQE7hgA
+ VTwiOuGIv46xKoxTcZUpZhGMrqvFiXmgYS2j
+ Qq4DWCYjpDtXnfruZV0pXmcJY4AB1Blp5g5i
+ XK//ZIcX/gyHs2JA4KhQWtg3KfQmJcUJkO6q
+ YduW9eMycJ61lZUVCb1jwQE98+w= )
+ 3600 DNSKEY 256 3 7 (
+ AwEAAcKiv8JVo/nwOl7snGkyU8TXRXfRYuKx
+ QpA42gttcSGG00PhRTCWrhlC1amY0fmgabvO
+ YVdkM2aK+NRTz0KLitWbvkfM7BAn4QUUR262
+ lxCeDXFX19pOPdV9G5hD/4X7EkilsusiAGwx
+ ni0lJkLVhmrEtvLSm4r0smcr/Te7o8nT
+ ) ; key id = 60914
+ 3600 DNSKEY 257 3 7 (
+ AwEAAdjJ0gueZiGl8beGI/a/D2B3svXKQbg9
+ uh2J/Amfc/IgrjjzCWiBoajADo2D1A4MyTWS
+ BtOGk31LCyOumJFTNr4/vMHSMGS7dXX7wCMo
+ sJjBgMBDnv33uiE0D6RFgw3X3Xg9ftoucRrs
+ lG9MMZpKcFc6v3ajLckgGj0vHFmf/g3mHwXr
+ 7htSg1cRVzhVnC098bHRqLQgcckzOxDQZgUs
+ UVQEmNEPGXyURPjqVoMaWZPSWB34XJrd8q1S
+ qshANW/Cz550xhXEp3de4y2bBrRIgJdrcQnA
+ GqVb/hxn51i6bj0R5qRtcIY+OWydV8DCEOmA
+ I0E+ioifx6nEgw1iHEdFU70=
+ ) ; key id = 41955
+ 3600 RRSIG DNSKEY 7 2 3600 20120311114108 (
+ 20120210114108 41955 example.com.
+ rcZlhmkMpb+ZUt6xdOZq7RI/7p3zqLEJzMwu
+ 5Nce2Yo7fQHjQGWI18+HA2US8TKZKwR2L/MU
+ MJ8cMx7ElaoEmFnebjq1cnMcLt4EHkKNMSM1
+ LcJAGowmC9q270R7vwAzpyCCToT2YDN+WO69
+ 0G2lRSGjaGJR2RY8o2+zQYNU1jm3R8NiXlen
+ VKywg9jlrkdQ1Z6MnYQKuywTZjDb/mhjbMqF
+ ANKf5zgDdvZI9y3tb4EKkGHL8sE0xKDTf+tT
+ GdSiLXQi5FTD6eaCclDB7qd0WGPf3bkTAq8H
+ FofDcE+CRi+9DGReKiAFR3w5Ujq3LXkQ5swi
+ xyHTyYUlWvfGg+hZsg== )
+ 3600 RRSIG DNSKEY 7 2 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ PtLvtaPNUKfcRbrQKM53Qo60zimxVlNP8uPV
+ 257uSmxbDnmkOa38O6xXISdgq24SW6mRPqW+
+ YZvXu0C7w4aZkbCgfYBmFeplAXE6iBVXd4Q+
+ s6aOiqaukTn0o918nrCOCbEC/bXlPRcpRZJg
+ 65jQuQdRWdqK83yRzy1J/bSN/fA= )
+ 0 NSEC3PARAM 1 0 10 AD3302FF
+ 0 RRSIG NSEC3PARAM 7 2 0 20120311114108 (
+ 20120210114108 60914 example.com.
+ WuKOUKwmvXyM/sIVaz1AlzgazTkoCNKgS2jE
+ hxhzqKNHbNMMzvd5rH4lwg1z1NMDBcwvfhpd
+ 8qpt+Q2NklIEUC8Db0DoKdD9HT+zt6k/erhQ
+ JJXuSfoypnPhrwk4rs7n1U4X/xXbmOctTp2r
+ SFY7FAbXNtjQwE7WB0wMkpfoJTg= )
+_foobar._tcp.example.com. 3600 IN SRV 0 1 9 old-slow-box.example.com.
+ 3600 IN SRV 0 3 9 new-fast-box.example.com.
+ 3600 IN SRV 1 0 9 server.example.com.
+ 3600 IN SRV 1 0 9 sysadmins-box.example.com.
+ 3600 RRSIG SRV 7 4 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Kava/zmrJ9xXbNDSuq8qPwTrp8H8VkPWuKLz
+ pmY8Test9DbhbX17OVwOrRvb5npkiD5pjTMV
+ gPzUc7g3UpRzORTlf4LW2j2P5UWB3IfCBKJX
+ zJXhW+ScR+jRX8T7ZQTE1Xg8Qc2lvPsycZiJ
+ i+BL+1uIsyrXK2/T0oAeLhF4O30= )
+*._tcp.example.com. 3600 IN SRV 0 0 0 .
+ 3600 RRSIG SRV 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ jCxrJOjdRJNyCqPsuPlFYo1cYXn3xACjWcUQ
+ a+SY2h91wgtwOwy3hzPvx5G9UbynqtvbAplW
+ d1q/pJwyfeXf4k3BemKJiPVYl/S6CiWk5Otf
+ FSdiTsKsYgKiyG8cUNcXOLteRbYt0s9Y51nU
+ zhEfhBdRFXG8vy4sle1XA6wkqSE= )
+a.example.com. 3600 IN A 10.0.0.4
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ YzA/6SJLjNJmYZ1BYjS3hgiebRQLlcjvn8IV
+ jU4c2FCGW+H43IIejzaIwlvuWUaXv6hpYYBL
+ cBudB3Zw7t4IfgT4XMkbEVcCfv+Gu3TLXn8a
+ qAblKbMxRHbWaqPi0KYHMptYqm3xmChqRqHs
+ h11uOi2YbA2cD9SqXhMwupIH4g8= )
+c.example.com. 3600 IN CNAME c.a.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ qaA91r8RUIfGg7QXqviyFKQEb0P3lU552mX2
+ 0tzo2PbdEWbnQBLNtACmhiG+nk57RYkFAPaY
+ TaexFiDwPXYViG0OGUiZUXJtVxXCg+vgW+34
+ ZRH2eEhTOPbrBKc/bHJ1Mo/1O2oOYLPF23PT
+ 03IF9ywBmwXnhJBwqzHJPitJ0LA= )
+*.a.example.com. 3600 IN A 10.0.0.5
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ JTXlbeNQRnhkGUrBRb9kY9NNzPRIV8oymIha
+ ZGWwQFB4WjjSHSnrNB9bu7pXrYL5V4fwy4og
+ IJexjAqteTlDfiBsVCTs4m6V/5XMWBGA1tet
+ 7FT0bwPYnYrV5ij79KYogYVXbIje3g26yAT2
+ TtHxp0VqpkUOHLIsPP/dJwOIi8Y= )
+*._udp.example.com. 3600 IN SRV 0 0 0 .
+ 3600 RRSIG SRV 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ GXRBT3HhPySbPhlnRIi3y+de7Ptesf4JDhNA
+ wTUoOkanLhnsE27u51OoineUchRI8AEKtejs
+ J1J8Q/iaFTn+nIEk1yVBZTz12NENRgJwX3Vd
+ XWQHWnANx7/3u3bXuHICv3q4NPJXO20j3a43
+ 26hlFkZt2YviMJq9l4FIeVbXqfQ= )
+f.example.com. 3600 IN CNAME e.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ aLrdCDbjTkJ21rRaCn0O95ch85kIVQtcpLWq
+ pNwZdEkFG6nanUsgqFwAewl4n/PYxsHhqFlP
+ bNO/rL5v3Aq7CyyLZ3NM9ZSt3wermKBpseyp
+ jaBIrcekZeq7qUJXEJi/ZlffnBGGFjJtAXpL
+ ZyP6I00MYcV1FP9VYkPYi7wzFig= )
+e.example.com. 3600 IN DNAME bogus25.com.
+ 3600 RRSIG DNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Bh6S2as2/EjwihXV5FM8hC9urhLMcXCyhXwX
+ l+/cRM/8Rd0hKZEcoMVN5U8f163hZQgueRA8
+ J2n8kPSQ3tdEURCkaYdvgU332pJgBpaibWYu
+ KrkvyPhK/4YkMYkAj245ioHOln8G0wkf6oTW
+ 8dpM5JsAvSAckJ2tK0fBIreM07M= )
+f.g.example.com. 3600 IN A 10.0.0.20
+ 3600 RRSIG A 7 4 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ TwU34N2AwNYPmwOy4J9LlaOgGmX5Sozmk/Re
+ pjrkEmRTtCbxmYNJli6LobKFyAxwrF1tan5o
+ z8x/kX4zOR3iBr6dR2fqJkC3VmW9fYLPYshY
+ SHKsbD9U6903QpxYFGhmI+a5A6/0HY+pZyO6
+ 4JFmQATfvRin31c2SHkPckqgatU= )
+d.example.com. 3600 IN CNAME non-existing.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ dLQ+FGitt6BvKZY1/TCEpH7soI+V31wPb2lJ
+ AX/MevBQsfVIk9BZW5eeqEcf6YqvHi4pBo++
+ 1pD0NDnuDJ3UAwLH674CQnJEUKZNFCyM0z/A
+ rZNl3HIszRNf6tJG0flMtQczmWlMOejmuvqL
+ vcYPTl/0ON6vuDeB0HA8G5NQgmI= )
+h.i.j.k.example.com. 3600 IN A 10.0.0.21
+ 3600 RRSIG A 7 6 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ qvwrNdbdE3tyfN4OUZqNmtdMLLavwbwGc+06
+ un4SM2DL3G2CWfxun3nHnJOwdgatWnlmMMEL
+ kllvuQhtNURgkP3WOwBhXJDzWCvaLT4E/Gvo
+ Ni23Znh8jO5Ef8RndKQY/cnIJOdh5JcTOl54
+ z64rLoW71qfxhVAAZy0f08LHKis= )
+*.j.k.example.com. 3600 IN A 10.0.0.22
+ 3600 RRSIG A 7 4 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ sw2Hlu7zcahxgTCNiMBGdK/svV0FH1sy8a/h
+ ixywRiCYgtrRyDWjgxFMNP1wpw2I6d9QiiDr
+ uha/I10eA8Ku4J78YY1HpWz3Lus2UqLeXKrf
+ q7I5xa8Pu+SJYIomZ086yp63ZH5z/dVOcMhh
+ rKrUiISXfFL9mvACTLTzOWwo5Pk= )
+g.example.com. 3600 IN CNAME www.bogus25.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Yc1t4U4yV0PZkfxAth2PtdqDOZKXJuYmOWuN
+ ni6g0REAaCNmuvCbHj+4YkOWKAq9NOEL5oqI
+ ALNA+XUeauaTYdibdVWoFbuL3q/oKqMFHvnU
+ eaTcM1xi+tCzo2lHvqxkc4Rcn7DjpZjFfR1H
+ H4YH4msXP9VPdoMMljFUvLsKwQI= )
+mail.example.com. 3600 IN A 10.0.0.3
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ MiSjUJWxYuMkwoQ2XGzdciruLO2jlKWCzyAK
+ BduPRMuIpx+l6cbhFdas59jKfcQGxQ7q/7h/
+ JcZS99LijXSRABW/AQDQzHIJkHh3lnhRdxg6
+ 7tkJExh1aLHsClLElteICS4cD0Ep7ESfPgkx
+ 6a9V/RB/DBGXJufxfKrTgaMJTuw= )
+new-fast-box.example.com. 3600 IN A 172.30.79.13
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ IbRvf4mFyUSm7gzpiDcmaAjasrJKWgJ2aohc
+ h9IowzJLiEn2+m3kII1qwC1NgMYuBzqyx5M8
+ nf+DYX/Vv4+uc6wVHRQjB+m8YS/7XB5hO8Mk
+ 4Wi9D5zk2Pzm/nJqmaVv0z4b6GS8w46Q/V7W
+ DG13RKprePL7oN+5fX0wWi/hGZA= )
+ns.example.com. 3600 IN A 10.0.0.2
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ HB4CX3PPLe8XMSUkABN5huUyYJ61q+hk8R6x
+ 1OMBMK1g2c6L9OcLY36Jxi1fyk1UDbk7wbIV
+ PGObOU98gF3Rz6hYrRLO1R1yDSA0YpkDL9Q2
+ fu8qGwoFdKjqE6JJiaYcH86bbEX/xaTPIwr2
+ kWnMZSF1F/inw3NWxekU532xycg= )
+o.example.com. 3600 IN CNAME a.e.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ ti7Cw/aVjpeDKuRmEJrQwLOIYZCpt7YWFVn8
+ XvChoxuv8OjEdhjtjZm6s5YWT7m6+NWpadZ4
+ 2YxjWkbi1JfmPVB8NdR+cLse2cFdr6StTeFn
+ 3TZei5zLsjje7XHJ78Ezsm91nJsT7YANBCwV
+ bp6exprqVvWSZIjmwzndP/6ldKQ= )
+*.l.example.com. 3600 IN CNAME c.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ N8JgT0V4xI4q2HsOZ996VWSc+RvT9dIlH7zf
+ dpvVB9GVYcMo+CC/vz53rLM/WCPkjcYVZxqH
+ xyRlAktjY7mMGFy/3ATlgBW/5fUjvCAPe3n+
+ WQf/lTO2p75SPgnz4yHzXRWFBgatTk4zxp5/
+ 34GoV+sE0rrVgOPKm5IkBp8lN08= )
+old-slow-box.example.com. 3600 IN A 172.30.79.11
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ mRqdT1LUhXB1+jzeRmtlysRlZvQ/wVa3RYez
+ 0ED3YAUpbhWPulW3SLiYWdQNSCs2kL1gbix0
+ 6z1gIrNUdwA9ndR9vIO4Ji1jeZIqfPtGLL2/
+ FI7PhcbjGGUuR/X60G0RxKvboNIDV42zZ34z
+ pMJU0U5kx+ibGUKdoTI/ZUIIaMU= )
+*.n.example.com. 3600 IN DNAME bogus25.com.
+ 3600 RRSIG DNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ LYfL+QODtn6ImPCadS9DYp3hDWFyooI0Sdug
+ kG4ENfOrFco31LlGs98CRsWM2cuIdAbh3a0M
+ FOtuRFl0dgvw8SOR7QV5x4S/pI4Xj9OIL4T8
+ xsw23Y6gVJ7oPOha7RBHRZFwniJgRyGsZc6L
+ 6ZTQzkOY4iGc2QEmV7kVwo0Fwdo= )
+r.example.com. 3600 IN CNAME a.l.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ NLSNK8cAEnGcIBX+oJm9VVVYxzUml/rQjNxH
+ pu9L+WROH0z4mgXiC9qaN6jiNHSY68aPxfph
+ xdnhfuaPQziKYezh5roXS036IBYdU/GzXyQE
+ KDmxBmM8Yevtp9xJs2/BrS5ny+bmoAf/2suv
+ kDfKD80tF16036x8JJFMPeyIKtI= )
+ns2.example.com. 3600 IN A 10.0.0.6
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ fijL4QoqM0u9E7eOA+Tjf3RIFGxCNGQp9Sp5
+ YTiEcv4vHSNI+4Y6tp93C9C9yeUp8YQ7VW9d
+ zagyF/jHKfODDpn6Sm2tcWzCxX2KZTuXGSNz
+ i7o16HJj4jRyg+uqdXIrp7ArPjudCc3mzd1K
+ LxTv7Zb3KVwWYyt4r1YbARFvvOs= )
+*.s.example.com. 3600 IN CNAME s.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ vfGi8BkLoPlB2ZAORnwG3ZlmhtOtrs/0z3wb
+ pY29MTNGNVBHJROXg1L7ANHTBglkbzrKExHz
+ +M9c9YmFgtOKqDne00R79KWpC9XB/zsdQPhV
+ TRGR2Fc00KY74ZrQZ0by2/xW34MqDPpgbmur
+ b+EeKV7UnnwZ9y84HIC3U12wQGk= )
+s.example.com. 3600 IN A 10.1.1.1
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ kpS37lgrK97OEG606nym1tYyovXp97xkG0y6
+ rteGws46zMYYrsW9L819ibzRO1DUAjOd4zkO
+ BI7hu9CI+Mgrk12wb4vKS/ERIDZkiZ5AadJE
+ nodcYYZBNwRMwE+frFgPxORS8rUtmtrkdqXR
+ Vjhs3llHqtJbJr1ve/nZvfgX/I8= )
+sub2.example.com. 3600 IN NS ns.sub2.example.com.
+*.sub2.example.com. 3600 IN A 10.2.0.1
+sub3.example.com. 3600 IN NS ns.sub2.example.com.
+sub4.example.com. 3600 IN NS ns.example.com.
+p.example.com. 3600 IN CNAME a.sub.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Cyvn5zf20vG8RHpIZ+oIvPV8nZnG9kROIIpC
+ pCXPx8RG0CY0+IhOpUdgGwvcfMkPSE4aMYw1
+ 7Dgbykszd0MrCt0Lel9iCF6sroeZNLCuriUl
+ 8hiYli602XJCamDB/9INSzvGtfRtiN4QGuRV
+ mbeuXLHP8ecv0Ib9GOt32dMTuwk= )
+ns.sub.example.com. 3600 IN A 10.1.0.1
+ 3600 RRSIG A 7 4 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ YuQAVe8hfw48Ily9RdN8maHLcIUDWKuDgcdd
+ W/5T/yBsf1ezILAh2zugDtc86A1HRxjH6jro
+ xqBlSkJ4bWSwA4OtaU6krsMODlV19gCXUNvW
+ SV/2TkCp0F0qSj88A6ZelUhbnMHTKw22z0K9
+ UdkdLB1ohRSw2I9xtSCek0DwLDA= )
+sysadmins-box.example.com. 3600 IN A 172.30.79.12
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ n+Pe+pQjCO8NJZq06uemhm/QuMRtbsuRYnrE
+ 85aJ65IGKfFdwn1bFYcW58Gc2HS/+nWE1gIy
+ DtvVxz/FZ5PK6acW8aQeji/sPBMvb7XfgXRl
+ 458lhlw1hkuxXRguqkKIDk1qL7GCBPHegNUV
+ 8xzGJLaxjQ0hMGVLPrPIH1udGwo= )
+www.example.com. 3600 IN CNAME ns.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ NnCpNpsZIV0U2qOsuuj7819OEubIY9XsoH6k
+ IY8fFCds7SRckoeGS+bM+LGRbQWJj4RRx4Xs
+ geWZB5xF/UXu5OCRSQSx3B2V+u7drfeqya/+
+ kpQaECsIxGljej92QHn5ABgJgY6eaWDI+cDO
+ KhhUkCoSrsvU7aYQLNmSacf+fPM= )
+0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ hdoNfv4A1PpOTW8EuR5fcwzvYoLT1Q7znxkJ
+ +0vEJ6z6nhdCCwUua0IsE0J79vQfy2Nmyofc
+ Q2OpLjz2tnvalX9dPX40SYPPV0NTAARs1Lms
+ tCueg1uRT8MMrkIRChSAW5aGHL1ObZNVqFuD
+ ulvfm+W7/3sHEBXuuAJW1QYaJU0= )
+server.example.com. 3600 IN A 172.30.79.10
+ 3600 RRSIG A 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ uEav81+vz3eDo/TkNMaKMf3IpMIsuVg7NV+3
+ oN7akjotlRzGkeWT1LHM/tZz2XGG+Tlw3LI7
+ +L3h6N0QQMlJJ4d6atOL4CShNWyYC27JNZ7t
+ WJLxZNLfZJaRBgmOqWP60g8ZicCerFasxR1o
+ +JDf5nNL6FH1KStC0ZuJfMLQVbk= )
+sub5.example.com. 3600 IN CNAME sub3.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Z2PhwJKkA3pgLFRgZCNytK+f6gNX/5sfo/Y6
+ 7SYp0VJHbWndhMwX4sxSRjY2F23QKrzo0PdK
+ cAHYrzBb8lVSaxdLqDKKGazhLE7sMwNZzTBe
+ f3rokNWjz+y+1GP0/WFcVW5WLh2REaR7yR62
+ 3QemcT3e2uB5FV/IIIUPCR85zwU= )
+1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ to+Oi5Ls4ea8RiwCikG5CMLG3poJ6EOCn51p
+ Fe6c6hY532DNi64z2jBWithM9YxIfAwt3j3Y
+ e3gIftTZvsMzP23Cdh11PUnThMX0180E8Vnc
+ waYAgLB2rG9HBc+0zrgYjA6s7xOCEEoYbVLW
+ mjPFLlpE9iVVtGuPf823SBilzro= )
+wwwtest.example.com. 3600 IN CNAME www.example.com.
+ 3600 RRSIG CNAME 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ khglR0/LGoeaAsSYFAf+YXmUAVOzFeE/eY2M
+ HuI8HliMuHl1jlo27I88OahsCY7c36+3z3j1
+ lIh3G5gpKbPB60KZ/5nWqR0os1ASm863L4Jk
+ L+Q5vfxiMeO6yZ2ywUjm7bUEPH6DXo9IoiXC
+ I6AedcGz25t1nzutks/gad6dNUg= )
+3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 572T84KRFBMQUC5O8I2V5BNLNHA8CBQN SRV RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ leFMlSPZk2RQXikgAkH49rf51b1Bdz0PXGrD
+ FrIQ3BhVy6AWN36MkD0DppqDk5838a9J2Qo3
+ 8MCR85WM061J3lGm8DhwR0az22+Ot2erzO0s
+ PL/21G1iaOF1OP3b5EN2jfoZdZ9F1T96dSjW
+ 5iA4PbB97IqgzAnFlrOBrWsBJf4= )
+572T84KRFBMQUC5O8I2V5BNLNHA8CBQN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 58KH92475K4K07K5NV8KAHO2UOHLGA5N A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Pr8qo3SOSxkKhW0VW+0Fk4Y/p/NMF/Ys1Rt5
+ 2Ux60M/5jbIY6yIAZBeJvBAeWG0a0lO6G/+t
+ XL81AV6dX2XVJsgYxEhyBzIiz2Y4gJT2QS1L
+ VEW4b26+7MH5JL7dKaKNJx8AUNS6X7xb9RJY
+ wzstiifxrHTYNBwoCZPlCmYrFJ8= )
+58KH92475K4K07K5NV8KAHO2UOHLGA5N.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 600RRJ34OTBFOQCRPSG5J4F19RM76IOE A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ TJLCuX3rB9xIBaffuYRAzR1CFkJ6ReAp9AXu
+ j4QFsmoo7IfU8stwYscWB/NQUUDR3zA6rych
+ KetLhIwHG96GPiI4ERiQ2y1O0cND9j47rnkC
+ 2tAy7o9Ou8InmUJuKT6rV0NrVEiXmSaNMxuh
+ eLhcIcRmFulkAaCv7yfja91fsSU= )
+9CGLSFKECUFG8QODUCMQPMVH0JP35440.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ KuqCuiNXU84Zv+R7/tFeoc4+n0jybD2v3jFQ
+ r7UyHwYkbgJjT4EjCkIywm56DnrZZ0J8Klz5
+ dF4/fWaa/uha+q8j9zbNwYFnzUOmX08rAhAA
+ CTGyoq6Gq7vBLxh7IyaCTi6phDdGajAywODG
+ B08oWuYgyl+BaV6HUMXxjoC8v0E= )
+9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V.example.com. 3600 IN NSEC3 1 0 10 AD3302FF AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ nt2Hz0NSjX67Wv9HrpzglnFtDwHB3SE1LiNm
+ xZeTx0hKk/4b8DGTB69/YglwCiVzd0h001A5
+ 9N0KLQH/cFfV1N6GWcyH382t1e31UtYzVWbm
+ o4SXfj+xex9Zgnr6DpuefOCzMNSkrB8hVBR7
+ jIVafVPz8H2a+EEnFrf3NII8HTY= )
+6K06BSDDT661B33QPG6F6EB14TIAJ42D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9CGLSFKECUFG8QODUCMQPMVH0JP35440 A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ lo+UMe/OHfBIQYxkbggwETXfy7FShVTIk51E
+ NBHD3TzNvUdjimVammEbkmbMI79Ic3wdnKrj
+ sk0IbF5DU4owVTF0Ze2EMikNpWndTIw4F03I
+ IbRd6cI38RtKGzxTUd3N+H0Dv+x1HK06TZsp
+ ildUHnYomQ3OMzdIuLOO70GGse0= )
+600RRJ34OTBFOQCRPSG5J4F19RM76IOE.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 6K06BSDDT661B33QPG6F6EB14TIAJ42D SRV RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Gx41Q8P2L1LIMqEJ++6DDIwWOIarnKH9+APX
+ a0ydl7+BMEa3uYtpEMRN822szoWNro96N1km
+ ih6lQesDaVFqkksrnJ+2dnyuCqQFV2FxnLJu
+ D6w3KxzXs8HDh4jDUBo2Je7grdNXdiHT5FqY
+ xCYcHtvbXqPDUBUVoka0YQYq2DY= )
+AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ pAm1NJoUtgrh1nZZOa+BOLe+sqxBYDRmy43+
+ Qsn9/xK+5nFP4uMewpJ399W+lYRXTVHj551W
+ SFSaPQViD30s3f/GRhux2Thkc9qUYO4XfQhl
+ cFM6ZBo6mjMc7coEeE2i/SA31tYvx1aL402a
+ HqdzfPGLGtVvrv1ebZngBva6Wdg= )
+CITG8IDONU692P92JJHS57P0ADNMB59S.example.com. 3600 IN NSEC3 1 0 10 AD3302FF D2S5TIC04S7ORKP09MAEOFV1GN1IQORK A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ FK+huH4wLnBWZ7dtydX3lYj1pB9rP6WS+Nqq
+ 3+3y3HlrrVM3dfJ/CdN8VjhrE6J7UWNl0hrG
+ nmZix1zLXZUWLusY/hPE6cyKh+yGmjtZit/0
+ qJfxPMr9GQLY6pa64kFejhX74Dr5Tch0rvIS
+ cCdqrgS1hppQkVC+NuJfXDiWSfc= )
+BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ FhTgIqqS6DUxaSLZd7RO7uWMi7rJjRfzkcj2
+ D0SP4iBPwBmntadfMSbJ7LQhqmF/RSlZJ9e3
+ ijiAzMcLQspiFeV/WJAivlNLLG9wESYcSoNH
+ GiEhtVbQDmhsCTeywoLWL2Ttf2En4l3SonKr
+ EceztaBYd4VSZb9eQ6mRWdF+nwA= )
+BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV.example.com. 3600 IN NSEC3 1 0 10 AD3302FF CITG8IDONU692P92JJHS57P0ADNMB59S A NS SOA MX RRSIG DNSKEY NSEC3PARAM
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ k7y2B2ZDxLVV/dGu52n2kaHU42UiLExA2RWe
+ pC8DuqezyFotFMwAxRT7jozgzLAYuWV6hnR4
+ 4eZQ2IIoqKUTXpnNh7p+xidNACwEGY1ZD4Fb
+ SjVbhKKRc9HQzVcBoKsS91OmJnH3Wxl/Zr1v
+ fkyAORJESGw0TMVHKYiE38HKuZo= )
+E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EAO0AESHP4M49Q5F332G7SOK1JH53NT4 NS
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ eeYNlR+7RF/WnR2Xfpi5BrwYmJsMKVtVGXBe
+ 3NzeQrZcqdDwnXwhwmpYZSYoBnQ46XrniGdx
+ BTIRHEqkj55uQxQ+xRCK+P/B7Q2VZWsiSsq5
+ UAJSnCuErfJze6tRe3xTw7Jk27HBQD//nG8o
+ ZH9xoMdkzC9H9y8QiMJabDAG6Pk= )
+DV0IMRDKSGUBTBMM94HHURG2QOPJS33D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI SRV RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ rEfdvZaXj4lmZJWz+o4ZOotWHlYbjFhoXUCk
+ JsRilkouAzzZkq6XDgTWW+n6KAHfB2t9mjex
+ UH7JK6/AQrSF9SolAzPZorVMVPFnoT1gQnQM
+ sklwqGHkwhHO+ZFumXGPjsKKDwsxfGSnchyh
+ 5X+jNJbtkEG45Pz0vcAgJVL7zDU= )
+D2S5TIC04S7ORKP09MAEOFV1GN1IQORK.example.com. 3600 IN NSEC3 1 0 10 AD3302FF DSSTL51IUQBKDPULIFJHGJP40C3NK2EA CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ SfsbWl8rpuCStr+LeCdKGL/2PDVI4XmqWbo/
+ WvEMXcidKxw3S+MIPctFRMBQfMxaiidpjdF6
+ MxTPJkQIIkuHxz0m0KCHxjkzQCGq4E9aSINJ
+ 58XBq9Lvq2891pymq18FogRpYaDnZUQDoezk
+ qaDLBJIQ7+j+wmD+gRxrIp9Co/I= )
+DSSTL51IUQBKDPULIFJHGJP40C3NK2EA.example.com. 3600 IN NSEC3 1 0 10 AD3302FF DV0IMRDKSGUBTBMM94HHURG2QOPJS33D CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Ip7RkE1QMBk6TVbD7BckwtJpEM/bZR7CdCh2
+ mYwDCH/VvE/4SHxu8ZaKZUxxe5jo4fdgbUml
+ tlwraOROKEY1pO3eD/x1xu5GI1NcB31Cq3Oh
+ 9anWbEglye9wYr2AqqWZ6/Dvf+P1gTYbEK9+
+ V9Fj1xm9vnHubnEwsCOfKDdXZ/I= )
+G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GC9S3VD2NHESSRL256KS0805PL0KAI2T DNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ cfmuSLlgtjXs7nlbqAXXSXa6A/yR6txfYWxS
+ MLx4KkI2La949SiV4GlcqypKlZ5EL32xdqk3
+ 8qDMhBBpzxSSmrsQRi4XiAG8f0/lGEBVSy+D
+ 0PlXeZHuCOfND8DtxsIttkxHOEop7vj7GuTA
+ 1V7I6TKxdFDPYaOtp/iz8wrCIOQ= )
+GC9S3VD2NHESSRL256KS0805PL0KAI2T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GGR966KJ5J300229Q7154AMB4EVVLLMG A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ uMUt9rYgxn4+VutPJ2B2in3lt8QmiV+cUwE5
+ TryjJsqFyWeKbhZpmh5fVbQLLZAjMAuQfQtY
+ CJb1gMeO7CIxlk4uLcjZSsMdDcKtwstU41T+
+ 9b4rHh42mgQBo7LrRXP8NUtXOZyvqge3AHmV
+ FKSJdhvmQdtLKgJUXRWPJQk2kIA= )
+EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I.example.com. 3600 IN NSEC3 1 0 10 AD3302FF G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8 CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ B937ph6NFfdD4bBEBEK4NVup+k7C4+vDKZVF
+ Wy9tzJAEqjoFTWqxrrfs1pmpxsvB4LzawVXm
+ XIxjqBuve6tNOk/LWjjrMigtx0gdJ8m3fCiU
+ Uk7t7xiDy5AgS8vkzYiQSr4EXb00v3dcSlUQ
+ nqjabZhgTx58KhbqF3O4c/oViY8= )
+EAO0AESHP4M49Q5F332G7SOK1JH53NT4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ rN/OU0sPJ9P28hEhDUlvMvPnQSBbyRwnMN3h
+ YipF2VX2r7Ij3qdD0k3PKx/Emzsbl+ImbGNm
+ mfhDQ0O72m6sT664Q8yO32Pve8i/fxQIVKTF
+ HalkrM2xonf7Bg+wzI4CnQHmWD8hcq4L7Mj1
+ bFI0H+PRWz75h0BB4hJYIs6sCuQ= )
+GGR966KJ5J300229Q7154AMB4EVVLLMG.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GJRT9TI4T3VSP9D26OC04EQ88SOFVRON A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ Bg8bWWuR/Gw8xKCrFjEHQRBhbBPKu0AL2DGT
+ QChgHqSaAj7hcaMHLStaCH7NRy/EQL07ryU1
+ Xh7EPFZn191xKJPrwFq2bIsgpYYoQ5Knwt1w
+ P3EdQEV6jANOx0k9IHsXC+9oGbMipe0iGYV1
+ 4XG295g5Kk47sfEcl9leOgH9xNQ= )
+H01743IKEGI4JJOMSNCP0VG5S6IPGPIF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ SS6rDyoEGhD/SkKu87gA4GNlKoAxyXnfVZ7K
+ iEdXMSrSdAu1dkHWCNqHvGuws9VDjwdZ2VKM
+ R0H09jMFs9Uur2u2A8RYv9RTwk3i2VKY9TPW
+ V5cp35ukOK2zQWWM8hSxIjIudiMhSdp/dluU
+ hGGMxb/Vl6TWMBff961lBqmQe0k= )
+IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC.example.com. 3600 IN NSEC3 1 0 10 AD3302FF J7A75JJN87L9PTVO6HBKH8IPI78IPUO4 A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ BsmFOWVyvp6T+lYJq9iI7N72LFces0lgUzgE
+ mi5hgj5j+/ak7Jbh5HMA9clnA4x2gVIbl4tB
+ n64PqfOoDeotG3KUS40aJMLtD5kLQ2lS8Jje
+ nj5ZGTvkkyDq03nzuCbO4WTVGs3Lv8nuKhPL
+ 0JchxWeMS4yya/7ZDAexOcaas5k= )
+GJRT9TI4T3VSP9D26OC04EQ88SOFVRON.example.com. 3600 IN NSEC3 1 0 10 AD3302FF H01743IKEGI4JJOMSNCP0VG5S6IPGPIF CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ atmcjXLJAop3xdnjTYTLDu1ooa/VrFPISBAl
+ 3yvMJmOBEtxO9I+wQUkSv59nDC59my/Pfye0
+ +tEo8iUanThfoNFZehA7HAl+scL7eiizyzpV
+ iemaGcqA8blGZmvGegBfgnHClw/s+J0lyxPO
+ +R6C1Ht53+5RL5havJgeiyDhrF0= )
+J7A75JJN87L9PTVO6HBKH8IPI78IPUO4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF KI1L4Q2S3IFEG634FE6DN6E3FGEGV956 A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ nejtB8Eb1URet62fXj1vdJ3FNJ+yIBFF5Kiw
+ 0trO8jpxEXZbop3Ls55eMRBO4uyxnXAQzOqd
+ iawmpOXkuhJkUC5dHg//l4bu7NnD1Delyfv0
+ t7VXAFjH8sV82HNsk/g8ngn4gekexXZU3QTJ
+ GcpAIGxpza48oI9qYf1jU7SOGuE= )
+KI1L4Q2S3IFEG634FE6DN6E3FGEGV956.example.com. 3600 IN NSEC3 1 0 10 AD3302FF LMQIHH5MDDR9PTGEHOHA5ND49685RR01 DNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ eoSPJ3B1MdvFBppmzqQ6+VY3ojgFuJdAqLIZ
+ Rac7CTMKqOILvQVEwwV9rU+vX3WpkiJ+RaiZ
+ +TUICV13KE3PJW6sEar7VenLHJyBLb9L2gRO
+ CaVf8IZy/PKwS1zdrasidKW2URRFhJdVcnuu
+ kdwRXfEmZYA4qEafclF+PDj49v0= )
+OIKQOJ12077E6HOP6HHST9DHAMGPED5T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OTMDSI120AJGM768VIKPLND04FDSUQSJ CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ H8h+djCAspCVBuSd5QyWe1Z3rIQcRJSCYtky
+ XRqfUN4gkcrMFEduIM5Ic5AJD25AxM2CnTBL
+ yVOGlcEJdpMivzZwJF+5mavO3hJ36LFEZkay
+ hmqUx39zqNC60a6bHDK9QTkvouQ5EuM26nMf
+ 9o6HytksqjvsYxkBJCJfR7oiTok= )
+MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OIKQOJ12077E6HOP6HHST9DHAMGPED5T
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ ZLiscKNOltWTqqwxDvjZmwTqhqAfjiDA68le
+ vmvY4mYzoPEHASd19gEhddNvR+KK/JVGYvEr
+ hB2jpgOSZCs1wsW90UpL0boenluMPppLFDUD
+ xLUD2jvzA9a6lBjl55jzUr6mLyyr2hHIPmk0
+ CmrSFITGT6qEzEWq/CLA6TvtBsY= )
+LMQIHH5MDDR9PTGEHOHA5ND49685RR01.example.com. 3600 IN NSEC3 1 0 10 AD3302FF MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ da0fy8qWaZtO26BoIvbr56jBrrucndmMJ/0h
+ /Y5BE2ib8X65KVjkNVt5Mg5YKpTvaeOZN6CQ
+ Dls5bxnUkqmu0kgaUjIB/rhiMhpPqkKF7dSP
+ SI85zqJXIgCInMsgfTiBp5uZwrBKtse89LwH
+ y6BC682kK/uX7ikjG4+BapL6ivQ= )
+OTMDSI120AJGM768VIKPLND04FDSUQSJ.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ jWagz+ntj/MtfWB6xUJlkfihEkwrj84g1CbX
+ F6yKKVk4WToETt2ApHMHd8tn4wbHYLfojavI
+ TbsIVBfWxyMFsCshMoBASML7T8I9X3jjEYKS
+ W877XhA2yxuFcMaTjh3jDm7wfLHIvEgqhanr
+ 6JO2qGWTKSlNWK+bYg4y89YJOOA= )
+PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PO8BSJPMDN4514A8JA8QNK1C79EJIF7E NS
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ qA/sA5sV/eRmtgb+HBzbENLI2jy7xEkiDd4H
+ d/REG2hCp3rlIlo1FK2y7q1sZDr3sZ0/5vrQ
+ jxOHpZx+akeHi7hT3R1KhQLFb/+veEOBXNVG
+ HMtB3+Uc7Ttq1bGdVQIDhrVpNVhKS44nEG6O
+ UwOKgK7aT2q2mnUA3c6foWI0sM8= )
+P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ VoYUgMVgFe4QXN5ggAzleOYWGKatee//AXnv
+ CeFRHn4lKcGKWGRxbaMaHHGkTX+UjN2DnGcD
+ nCU/LQo15nKk8m8EYoUYywaHYiZ+aJ5eoagB
+ hka9G8YRM4goHxyKr4asFtfjHcfGdW82y3kv
+ BJYH/MN82GAhMfsdCA9z9zp88zo= )
+PO8BSJPMDN4514A8JA8QNK1C79EJIF7E.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PSMSPPC19D8OAICCQ64C7MQ387MTVGC1 A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ QtJhRcGQl3Fi9tGK6xD0Dr5s740QqsOhvaJN
+ ofLjQVTa4zDEoC6txlgTO4czRl7KPFWa8T48
+ W+jCqEysIamuUMmUOypCj7Airg4lDdS2VBUJ
+ BC2npTHBKnx+J1h8p58p0KDhozYoMNtYUUFF
+ gBp99sWEsORnDxyiW+KFFTTW0xU= )
+P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7 CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ sBdCg4Y3vGxry/Z1zV/Xg6bdpYjKiTXTSDm8
+ 9D1WZ8WAW5vbSJHxTnXq4IxwAJr2fpI4fUiT
+ cAS0uFqd+Ft8XpSQjaNPGuwzS08DCLn++Hrm
+ lbCngUeApxrgCfxo+cf4ibRPfef3UPcUxDOD
+ meqoGFw51+5DpB1Ygf5+yEPhAX0= )
+PSMSPPC19D8OAICCQ64C7MQ387MTVGC1.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RQK67K3ON1JGJ60JNO4883D1JVIOIG2D
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ DMO3YD4aOFqjkxmw+SDajMoQ+3TylCrk6yyr
+ ZQiV7yrfP5SIwY40EKCVG+6d0jSNQd7LrbJz
+ uyXiGpGEpKRTmAJZYSrpiPyfbbfw1XrOW9BX
+ 7qVZCvK8iZrkaNT6yQ4W/Q4gwSIyRpUqE1j1
+ 2SgEv934CIWBew/cjGfVzdIMHCo= )
+RQK67K3ON1JGJ60JNO4883D1JVIOIG2D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ fVTi0gRo2WwgEu51Fx1iH5Ke8eh8m8l94luf
+ yx5K6gCqywv9Sbk7YhyKmW5/94r0VwyNqgPS
+ 5DF6+RXBlM/t+35g+K04eBortmy89dbzFSZD
+ YPqfk2Q7v98jMnB0OzLoqGg5LqxTBPHftKm4
+ O0tsGJ7AC8bto6+iBEOEjX3ky54= )
+SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF UB8IU759M5EE63CQBISIRM9C0V2RU1RT CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ ASL7wTfcNyORVN8g+BjK3CSP5NXsWoqF9imO
+ E93NzOn4EvgOI1K7jDZ+urgCaaaw3rqt/yUS
+ 4/nU7wHUDjuNsvP9B+lWm93l8I1n9nhkOy5D
+ J17XjWE+8AqBidwX7O5clx+yAMSCnL7X4Rp5
+ luSPK6oZeRX2A5wSHbrvHeQkI78= )
+UB8IU759M5EE63CQBISIRM9C0V2RU1RT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF URIDB302IVQCE7DQSKELLE9LEFOHV0LT A RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ uZPu1mukjnAj+p7IKGe5tQV4yMBEytV4ab5W
+ nWNZeChWwQfooNwaOK+ZBkFvWs/bxyKtwL7b
+ 24xAbU+4+TzD5Ier9xNYDNfLXUkJ9hKuBrvg
+ RDYN8W/rRN++aL4xR0o/jOwzVnkww/VtIkvK
+ 7FPE0F2YpEw16H/ZIWnL6htRb5w= )
+RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ sIaGgFypdpWWLFqcWGI0PzitwaIZI6irA8uw
+ Y/E4etgI+l5aKbHPeum0+qzktYWc/wFxte44
+ 0T3dRujlVbMOhDAhE3QJFjZWEZo8ZZH7ARxC
+ bn5pTkzmKjWqKjKhol2U0Y7ve74oJpi5H5o5
+ D7nqiEmr1Ou8xkqbK281PGSti+s= )
+S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS NS
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ bDbE5EuKlVnpyavKronRh+FiK5wB0Ecw+ubc
+ HiVRrQfJvnayxRVOiE0OvUrK0n0FyQwuXk6w
+ /EysxVkcDK8wwX3SsXW71qEE1qG6GmFHUUOJ
+ gksxkjkVTMug0Xnmm+UGO9va5VhekMJLiNzF
+ Nl+vhTphDLLTgql8pyoA44PDARM= )
+URIDB302IVQCE7DQSKELLE9LEFOHV0LT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ JuCoPMHnJZXXo+/2ACPorEF6zHtGylp4ybXe
+ eN2VC5jmj7NMj+8EFkHa2hRoy2yL4hA5+dOo
+ PDzaQtHJ9wO2gYgU9qz2eGNRfFM655ig4Uq+
+ yfpQjUq5hAyuxTehlhH51jElOo1B9rC+qpbY
+ eQIfqyK318Xp7JswLblUn8IHzUE= )
+V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7 CNAME RRSIG
+ 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
+ 20120210114108 60914 example.com.
+ q5cTrHk3CXT3nACoB0sexMUuit+ze5mj+PX3
+ Xvv9XPMm30q9CGdVYQG9N5f4TiYiQJU6Lf99
+ Pt7t+zWhB/YVfFrcCB3k5zWA/QfmwQYLrEyK
+ QiTxMEGvRU5QhbXwdiltAjQIpiO/fqa9wwr3
+ l9/TaVniVaOM0XXV2A8xzNUHuYM= )
diff --git a/samples/knot.full.conf b/samples/knot.full.conf
index 04fbe09..91d5674 100644
--- a/samples/knot.full.conf
+++ b/samples/knot.full.conf
@@ -20,14 +20,27 @@ system {
# Version of the server (see RFC 4892). Not used yet.
version "0.1";
+ # Server identifier
+ # Use string format "text"
+ # Or hexstring 0x01ab00
+ nsid "myserver0";
+
# Working directory of the server
# Used to store compiled zones and PID file
storage "/tmp/knot-sample";
+ # Custom pidfile path
+ # default: pidfile is created in 'storage'.
+ pidfile "/tmp/knot.pid";
+
# Number of workers per interface
# This option is used to force number of threads used per interface
# Default: unset (auto-estimates optimal value from the number of online CPUs)
workers 1;
+
+ # User for running server
+ # May also specify user.group (f.e. knot.users)
+ user: root;
}
# Section 'keys' contains list of TSIG keys
diff --git a/scripts/urcu-tls-compat.patch b/scripts/urcu-tls-compat.patch
new file mode 100644
index 0000000..cd5ff25
--- /dev/null
+++ b/scripts/urcu-tls-compat.patch
@@ -0,0 +1,1495 @@
+From 998d005870782ed52ba0fe66a99589dc8b7eb20e Mon Sep 17 00:00:00 2001
+From: Marek Vavrusa <marek@vavrusa.com>
+Date: Mon, 30 Jan 2012 16:40:12 +0100
+Subject: [PATCH] Compatibility for compilers without TLS support.
+
+If TLS is detected on configure, it is used as before.
+If not, it is emulated using pthread_setspecific()/pthread_getspecific()
+and set of macros.
+
+For usage info, see urcu/tls-compat.h
+---
+ .gitignore | 1 -
+ configure.ac | 3 +
+ m4/ax_tls.m4 | 76 ++++++++++++++++++++++++++++++++
+ tests/test_mutex.c | 8 +++-
+ tests/test_perthreadlock.c | 8 +++-
+ tests/test_rwlock.c | 8 +++-
+ tests/test_urcu.c | 8 +++-
+ tests/test_urcu_assign.c | 8 +++-
+ tests/test_urcu_bp.c | 8 +++-
+ tests/test_urcu_defer.c | 8 +++-
+ tests/test_urcu_gc.c | 8 +++-
+ tests/test_urcu_lfq.c | 14 ++++--
+ tests/test_urcu_lfs.c | 14 ++++--
+ tests/test_urcu_qsbr.c | 8 +++-
+ tests/test_urcu_qsbr_gc.c | 8 +++-
+ tests/test_urcu_wfq.c | 14 ++++--
+ tests/test_urcu_wfs.c | 14 ++++--
+ urcu-bp.c | 10 +++--
+ urcu-call-rcu-impl.h | 26 +++++++++++-
+ urcu-defer-impl.h | 49 +++++++++++---------
+ urcu-qsbr.c | 18 ++++---
+ urcu.c | 22 +++++----
+ urcu/map/urcu-bp.h | 2 +
+ urcu/map/urcu-qsbr.h | 2 +
+ urcu/map/urcu.h | 4 ++
+ urcu/static/urcu-bp.h | 18 +++++---
+ urcu/static/urcu-qsbr.h | 22 ++++++----
+ urcu/static/urcu.h | 21 ++++++---
+ urcu/tls-compat.h | 104 ++++++++++++++++++++++++++++++++++++++++++++
+ 29 files changed, 408 insertions(+), 106 deletions(-)
+ create mode 100644 m4/ax_tls.m4
+ create mode 100644 urcu/tls-compat.h
+
+diff --git a/.gitignore b/.gitignore
+index 6eeb2a1..7af5609 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -71,7 +71,6 @@ tests/*.log
+ .libs/
+ Makefile.in
+ Makefile
+-*.m4
+ *.la
+ *.bz2
+ *.o
+diff --git a/configure.ac b/configure.ac
+index 5a90008..1953a8a 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -14,6 +14,9 @@ AC_CANONICAL_HOST
+ AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip])
+ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
++AC_CONFIG_MACRO_DIR([m4])
++m4_include([m4/ax_tls.m4])
++
+ AC_CONFIG_SRCDIR([urcu.h])
+ AM_PROG_MKDIR_P
+
+diff --git a/m4/ax_tls.m4 b/m4/ax_tls.m4
+new file mode 100644
+index 0000000..033e3b1
+--- /dev/null
++++ b/m4/ax_tls.m4
+@@ -0,0 +1,76 @@
++# ===========================================================================
++# http://www.gnu.org/software/autoconf-archive/ax_tls.html
++# ===========================================================================
++#
++# SYNOPSIS
++#
++# AX_TLS([action-if-found], [action-if-not-found])
++#
++# DESCRIPTION
++#
++# Provides a test for the compiler support of thread local storage (TLS)
++# extensions. Defines TLS if it is found. Currently knows about GCC/ICC
++# and MSVC. I think SunPro uses the same as GCC, and Borland apparently
++# supports either.
++#
++# LICENSE
++#
++# Copyright (c) 2008 Alan Woodland <ajw05@aber.ac.uk>
++# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
++#
++# 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/>.
++#
++# As a special exception, the respective Autoconf Macro's copyright owner
++# gives unlimited permission to copy, distribute and modify the configure
++# scripts that are the output of Autoconf when processing the Macro. You
++# need not follow the terms of the GNU General Public License when using
++# or distributing such scripts, even though portions of the text of the
++# Macro appear in them. The GNU General Public License (GPL) does govern
++# all other use of the material that constitutes the Autoconf Macro.
++#
++# This special exception to the GPL applies to versions of the Autoconf
++# Macro released by the Autoconf Archive. When you make and distribute a
++# modified version of the Autoconf Macro, you may extend this special
++# exception to the GPL to apply to your modified version as well.
++
++#serial 10
++
++AC_DEFUN([AX_TLS], [
++ AC_MSG_CHECKING(for thread local storage (TLS) class)
++ AC_CACHE_VAL(ac_cv_tls, [
++ ax_tls_keywords="__thread __declspec(thread) none"
++ for ax_tls_keyword in $ax_tls_keywords; do
++ AS_CASE([$ax_tls_keyword],
++ [none], [ac_cv_tls=none ; break],
++ [AC_TRY_COMPILE(
++ [#include <stdlib.h>
++ static void
++ foo(void) {
++ static ] $ax_tls_keyword [ int bar;
++ exit(1);
++ }],
++ [],
++ [ac_cv_tls=$ax_tls_keyword ; break],
++ ac_cv_tls=none
++ )])
++ done
++ ])
++ AC_MSG_RESULT($ac_cv_tls)
++
++ AS_IF([test "$ac_cv_tls" != "none"],
++ AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here])
++ m4_ifnblank([$1], [$1]),
++ m4_ifnblank([$2], [$2])
++ )
++])
+diff --git a/tests/test_mutex.c b/tests/test_mutex.c
+index 3f84bbf..bb73f1c 100644
+--- a/tests/test_mutex.c
++++ b/tests/test_mutex.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -155,8 +157,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static
+ unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
+diff --git a/tests/test_perthreadlock.c b/tests/test_perthreadlock.c
+index fa9c89a..14362cf 100644
+--- a/tests/test_perthreadlock.c
++++ b/tests/test_perthreadlock.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -159,8 +161,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static
+ unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
+diff --git a/tests/test_rwlock.c b/tests/test_rwlock.c
+index 34d8c07..087ff58 100644
+--- a/tests/test_rwlock.c
++++ b/tests/test_rwlock.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -156,8 +158,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static unsigned int nr_readers;
+ static unsigned int nr_writers;
+diff --git a/tests/test_urcu.c b/tests/test_urcu.c
+index 870f133..cf8e12e 100644
+--- a/tests/test_urcu.c
++++ b/tests/test_urcu.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -154,8 +156,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static unsigned int nr_readers;
+ static unsigned int nr_writers;
+diff --git a/tests/test_urcu_assign.c b/tests/test_urcu_assign.c
+index 42d70c2..55eab0c 100644
+--- a/tests/test_urcu_assign.c
++++ b/tests/test_urcu_assign.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -154,8 +156,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static unsigned int nr_readers;
+ static unsigned int nr_writers;
+diff --git a/tests/test_urcu_bp.c b/tests/test_urcu_bp.c
+index 857913f..08170b6 100644
+--- a/tests/test_urcu_bp.c
++++ b/tests/test_urcu_bp.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -154,8 +156,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static unsigned int nr_readers;
+ static unsigned int nr_writers;
+diff --git a/tests/test_urcu_defer.c b/tests/test_urcu_defer.c
+index 1575e9c..c5aeeb4 100644
+--- a/tests/test_urcu_defer.c
++++ b/tests/test_urcu_defer.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program (with automatic reclamation)
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -155,8 +157,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static
+ unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
+diff --git a/tests/test_urcu_gc.c b/tests/test_urcu_gc.c
+index 21c5d56..31d3e65 100644
+--- a/tests/test_urcu_gc.c
++++ b/tests/test_urcu_gc.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program (with baatch reclamation)
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -163,8 +165,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static
+ unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
+diff --git a/tests/test_urcu_lfq.c b/tests/test_urcu_lfq.c
+index 11e7eb3..83db5d1 100644
+--- a/tests/test_urcu_lfq.c
++++ b/tests/test_urcu_lfq.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -38,6 +39,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -148,11 +150,15 @@ static int test_duration_enqueue(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_dequeues;
+-static unsigned long long __thread nr_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
++#define nr_dequeues (*_nr_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
++#define nr_enqueues (*_nr_enqueues())
+
+-static unsigned long long __thread nr_successful_dequeues;
+-static unsigned long long __thread nr_successful_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
++#define nr_successful_dequeues (*_nr_successful_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
++#define nr_successful_enqueues (*_nr_successful_enqueues())
+
+ static unsigned int nr_enqueuers;
+ static unsigned int nr_dequeuers;
+diff --git a/tests/test_urcu_lfs.c b/tests/test_urcu_lfs.c
+index 883fd0c..79a1ceb 100644
+--- a/tests/test_urcu_lfs.c
++++ b/tests/test_urcu_lfs.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -38,6 +39,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -148,11 +150,15 @@ static int test_duration_enqueue(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_dequeues;
+-static unsigned long long __thread nr_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
++#define nr_dequeues (*_nr_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
++#define nr_enqueues (*_nr_enqueues())
+
+-static unsigned long long __thread nr_successful_dequeues;
+-static unsigned long long __thread nr_successful_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
++#define nr_successful_dequeues (*_nr_successful_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
++#define nr_successful_enqueues (*_nr_successful_enqueues())
+
+ static unsigned int nr_enqueuers;
+ static unsigned int nr_dequeuers;
+diff --git a/tests/test_urcu_qsbr.c b/tests/test_urcu_qsbr.c
+index b986fd8..eaa4a67 100644
+--- a/tests/test_urcu_qsbr.c
++++ b/tests/test_urcu_qsbr.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -153,8 +155,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static unsigned int nr_readers;
+ static unsigned int nr_writers;
+diff --git a/tests/test_urcu_qsbr_gc.c b/tests/test_urcu_qsbr_gc.c
+index 9deb0aa..e65503a 100644
+--- a/tests/test_urcu_qsbr_gc.c
++++ b/tests/test_urcu_qsbr_gc.c
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - test program (with baatch reclamation)
+ *
+ * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -35,6 +36,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -159,8 +161,10 @@ static int test_duration_read(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_writes;
+-static unsigned long long __thread nr_reads;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
++#define nr_writes (*_nr_writes())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
++#define nr_reads (*_nr_reads())
+
+ static unsigned int nr_readers;
+ static unsigned int nr_writers;
+diff --git a/tests/test_urcu_wfq.c b/tests/test_urcu_wfq.c
+index 83ec635..32156dc 100644
+--- a/tests/test_urcu_wfq.c
++++ b/tests/test_urcu_wfq.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -38,6 +39,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -147,11 +149,15 @@ static int test_duration_enqueue(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_dequeues;
+-static unsigned long long __thread nr_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
++#define nr_dequeues (*_nr_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
++#define nr_enqueues (*_nr_enqueues())
+
+-static unsigned long long __thread nr_successful_dequeues;
+-static unsigned long long __thread nr_successful_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
++#define nr_successful_dequeues (*_nr_successful_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
++#define nr_successful_enqueues (*_nr_successful_enqueues())
+
+ static unsigned int nr_enqueuers;
+ static unsigned int nr_dequeuers;
+diff --git a/tests/test_urcu_wfs.c b/tests/test_urcu_wfs.c
+index 7746a1d..1e78211 100644
+--- a/tests/test_urcu_wfs.c
++++ b/tests/test_urcu_wfs.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * 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
+@@ -38,6 +39,7 @@
+ #include <errno.h>
+
+ #include <urcu/arch.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __linux__
+ #include <syscall.h>
+@@ -147,11 +149,15 @@ static int test_duration_enqueue(void)
+ return !test_stop;
+ }
+
+-static unsigned long long __thread nr_dequeues;
+-static unsigned long long __thread nr_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
++#define nr_dequeues (*_nr_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
++#define nr_enqueues (*_nr_enqueues())
+
+-static unsigned long long __thread nr_successful_dequeues;
+-static unsigned long long __thread nr_successful_enqueues;
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
++#define nr_successful_dequeues (*_nr_successful_dequeues())
++TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
++#define nr_successful_enqueues (*_nr_successful_enqueues())
+
+ static unsigned int nr_enqueuers;
+ static unsigned int nr_dequeuers;
+diff --git a/urcu-bp.c b/urcu-bp.c
+index f3249b4..1b38097 100644
+--- a/urcu-bp.c
++++ b/urcu-bp.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -35,6 +36,7 @@
+ #include <poll.h>
+ #include <unistd.h>
+ #include <sys/mman.h>
++#include <config.h>
+
+ #include "urcu/wfqueue.h"
+ #include "urcu/map/urcu-bp.h"
+@@ -94,7 +96,7 @@ static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
+
+ #ifdef DEBUG_YIELD
+ unsigned int yield_active;
+-unsigned int __thread rand_yield;
++TLS_DEFINE(unsigned int, get_rand_yield, _rand_yield);
+ #endif
+
+ /*
+@@ -109,7 +111,7 @@ long rcu_gp_ctr = RCU_GP_COUNT;
+ * Pointer to registry elements. Written to only by each individual reader. Read
+ * by both the reader and the writers.
+ */
+-struct rcu_reader __thread *rcu_reader;
++TLS_DEFINE(struct rcu_reader*, rcu_reader, _rcu_reader);
+
+ static CDS_LIST_HEAD(registry);
+
+@@ -322,7 +324,7 @@ static void add_thread(void)
+ rcu_reader_reg->tid = pthread_self();
+ assert(rcu_reader_reg->ctr == 0);
+ cds_list_add(&rcu_reader_reg->node, &registry);
+- rcu_reader = rcu_reader_reg;
++ *rcu_reader() = rcu_reader_reg;
+ }
+
+ /* Called with signals off and mutex locked */
+@@ -363,7 +365,7 @@ void rcu_bp_register(void)
+ /*
+ * Check if a signal concurrently registered our thread since
+ * the check in rcu_read_lock(). */
+- if (rcu_reader)
++ if (*rcu_reader())
+ goto end;
+
+ mutex_lock(&rcu_gp_lock);
+diff --git a/urcu-call-rcu-impl.h b/urcu-call-rcu-impl.h
+index 36e3cf4..27cb1ac 100644
+--- a/urcu-call-rcu-impl.h
++++ b/urcu-call-rcu-impl.h
+@@ -4,6 +4,7 @@
+ * Userspace RCU library - batch memory reclamation with kernel API
+ *
+ * Copyright (c) 2010 Paul E. McKenney <paulmck@linux.vnet.ibm.com>
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -61,8 +62,31 @@ struct call_rcu_data {
+ CDS_LIST_HEAD(call_rcu_data_list);
+
+ /* Link a thread using call_rcu() to its call_rcu thread. */
+-
++#ifdef TLS
+ static __thread struct call_rcu_data *thread_call_rcu_data;
++#else
++static pthread_key_t tls_tcrd_key;
++static pthread_once_t tls_tcrd_once = PTHREAD_ONCE_INIT;
++static void tls_tcrd_deinit() {
++ void *p = pthread_getspecific(tls_tcrd_key);
++ free(p);
++}
++static void tls_tcrd_init() {
++ (void)pthread_key_create(&tls_tcrd_key, tls_tcrd_deinit);
++ atexit(tls_tcrd_deinit);
++}
++static struct call_rcu_data **tls_thread_call_rcu_data() {
++ (void)pthread_once(&tls_tcrd_once, tls_tcrd_init);
++ struct call_rcu_data **r = pthread_getspecific(tls_tcrd_key);
++ if (r == NULL) {
++ r = malloc(sizeof(struct call_rcu_data *));
++ *r = NULL;
++ (void)pthread_setspecific(tls_tcrd_key, r);
++ }
++ return r;
++}
++#define thread_call_rcu_data (*tls_thread_call_rcu_data())
++#endif
+
+ /* Guard call_rcu thread creation. */
+
+diff --git a/urcu-defer-impl.h b/urcu-defer-impl.h
+index 4d1ca5e..21c337d 100644
+--- a/urcu-defer-impl.h
++++ b/urcu-defer-impl.h
+@@ -11,6 +11,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -40,6 +41,7 @@
+ #include <sys/time.h>
+ #include <unistd.h>
+ #include <stdint.h>
++#include <config.h>
+
+ #include "urcu/futex.h"
+
+@@ -48,6 +50,7 @@
+ #include <urcu/uatomic.h>
+ #include <urcu/list.h>
+ #include <urcu/system.h>
++#include <urcu/tls-compat.h>
+
+ /*
+ * Number of entries in the per-thread defer queue. Must be power of 2.
+@@ -130,7 +133,9 @@ static int32_t defer_thread_stop;
+ * Written to only by each individual deferer. Read by both the deferer and
+ * the reclamation tread.
+ */
+-static struct defer_queue __thread defer_queue;
++TLS_DEFINE_SIMPLE(struct defer_queue, get_defer_queue, defer_queue);
++#define _defer_queue (*get_defer_queue())
++
+ static CDS_LIST_HEAD(registry_defer);
+ static pthread_t tid_defer;
+
+@@ -245,12 +250,12 @@ static void _rcu_defer_barrier_thread(void)
+ {
+ unsigned long head, num_items;
+
+- head = defer_queue.head;
+- num_items = head - defer_queue.tail;
++ head = _defer_queue.head;
++ num_items = head - _defer_queue.tail;
+ if (caa_unlikely(!num_items))
+ return;
+ synchronize_rcu();
+- rcu_defer_barrier_queue(&defer_queue, head);
++ rcu_defer_barrier_queue(&_defer_queue, head);
+ }
+
+ void rcu_defer_barrier_thread(void)
+@@ -311,8 +316,8 @@ void _defer_rcu(void (*fct)(void *p), void *p)
+ * Head is only modified by ourself. Tail can be modified by reclamation
+ * thread.
+ */
+- head = defer_queue.head;
+- tail = CMM_LOAD_SHARED(defer_queue.tail);
++ head = _defer_queue.head;
++ tail = CMM_LOAD_SHARED(_defer_queue.tail);
+
+ /*
+ * If queue is full, or reached threshold. Empty queue ourself.
+@@ -321,7 +326,7 @@ void _defer_rcu(void (*fct)(void *p), void *p)
+ if (caa_unlikely(head - tail >= DEFER_QUEUE_SIZE - 2)) {
+ assert(head - tail <= DEFER_QUEUE_SIZE);
+ rcu_defer_barrier_thread();
+- assert(head - CMM_LOAD_SHARED(defer_queue.tail) == 0);
++ assert(head - CMM_LOAD_SHARED(_defer_queue.tail) == 0);
+ }
+
+ /*
+@@ -340,25 +345,25 @@ void _defer_rcu(void (*fct)(void *p), void *p)
+ * Decode: see the comments before 'struct defer_queue'
+ * or the code in rcu_defer_barrier_queue().
+ */
+- if (caa_unlikely(defer_queue.last_fct_in != fct
++ if (caa_unlikely(_defer_queue.last_fct_in != fct
+ || DQ_IS_FCT_BIT(p)
+ || p == DQ_FCT_MARK)) {
+- defer_queue.last_fct_in = fct;
++ _defer_queue.last_fct_in = fct;
+ if (caa_unlikely(DQ_IS_FCT_BIT(fct) || fct == DQ_FCT_MARK)) {
+- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK],
++ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK],
+ DQ_FCT_MARK);
+- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK],
++ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK],
+ fct);
+ } else {
+ DQ_SET_FCT_BIT(fct);
+- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK],
++ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK],
+ fct);
+ }
+ }
+- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK], p);
++ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK], p);
+ cmm_smp_wmb(); /* Publish new pointer before head */
+ /* Write q[] before head. */
+- CMM_STORE_SHARED(defer_queue.head, head);
++ CMM_STORE_SHARED(_defer_queue.head, head);
+ cmm_smp_mb(); /* Write queue head before read futex */
+ /*
+ * Wake-up any waiting defer thread.
+@@ -422,16 +427,16 @@ int rcu_defer_register_thread(void)
+ {
+ int was_empty;
+
+- assert(defer_queue.last_head == 0);
+- assert(defer_queue.q == NULL);
+- defer_queue.q = malloc(sizeof(void *) * DEFER_QUEUE_SIZE);
+- if (!defer_queue.q)
++ assert(_defer_queue.last_head == 0);
++ assert(_defer_queue.q == NULL);
++ _defer_queue.q = malloc(sizeof(void *) * DEFER_QUEUE_SIZE);
++ if (!_defer_queue.q)
+ return -ENOMEM;
+
+ mutex_lock_defer(&defer_thread_mutex);
+ mutex_lock_defer(&rcu_defer_mutex);
+ was_empty = cds_list_empty(&registry_defer);
+- cds_list_add(&defer_queue.list, &registry_defer);
++ cds_list_add(&_defer_queue.list, &registry_defer);
+ mutex_unlock(&rcu_defer_mutex);
+
+ if (was_empty)
+@@ -446,10 +451,10 @@ void rcu_defer_unregister_thread(void)
+
+ mutex_lock_defer(&defer_thread_mutex);
+ mutex_lock_defer(&rcu_defer_mutex);
+- cds_list_del(&defer_queue.list);
++ cds_list_del(&_defer_queue.list);
+ _rcu_defer_barrier_thread();
+- free(defer_queue.q);
+- defer_queue.q = NULL;
++ free(_defer_queue.q);
++ _defer_queue.q = NULL;
+ is_empty = cds_list_empty(&registry_defer);
+ mutex_unlock(&rcu_defer_mutex);
+
+diff --git a/urcu-qsbr.c b/urcu-qsbr.c
+index 5530295..6eeb90c 100644
+--- a/urcu-qsbr.c
++++ b/urcu-qsbr.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -34,6 +35,7 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <poll.h>
++#include <config.h>
+
+ #include "urcu/wfqueue.h"
+ #include "urcu/map/urcu-qsbr.h"
+@@ -66,11 +68,11 @@ unsigned long rcu_gp_ctr = RCU_GP_ONLINE;
+ * Written to only by each individual reader. Read by both the reader and the
+ * writers.
+ */
+-struct rcu_reader __thread rcu_reader;
++TLS_DEFINE(struct rcu_reader, rcu_reader, _rcu_reader);
+
+ #ifdef DEBUG_YIELD
+ unsigned int yield_active;
+-unsigned int __thread rand_yield;
++TLS_DEFINE(unsigned int, get_rand_yield, _rand_yield);
+ #endif
+
+ static CDS_LIST_HEAD(registry);
+@@ -206,7 +208,7 @@ void synchronize_rcu(void)
+ {
+ unsigned long was_online;
+
+- was_online = rcu_reader.ctr;
++ was_online = rcu_reader()->ctr;
+
+ /* All threads should read qparity before accessing data structure
+ * where new ptr points to. In the "then" case, rcu_thread_offline
+@@ -269,7 +271,7 @@ void synchronize_rcu(void)
+ {
+ unsigned long was_online;
+
+- was_online = rcu_reader.ctr;
++ was_online = rcu_reader()->ctr;
+
+ /*
+ * Mark the writer thread offline to make sure we don't wait for
+@@ -326,11 +328,11 @@ void rcu_thread_online(void)
+
+ void rcu_register_thread(void)
+ {
+- rcu_reader.tid = pthread_self();
+- assert(rcu_reader.ctr == 0);
++ rcu_reader()->tid = pthread_self();
++ assert(rcu_reader()->ctr == 0);
+
+ mutex_lock(&rcu_gp_lock);
+- cds_list_add(&rcu_reader.node, &registry);
++ cds_list_add(&rcu_reader()->node, &registry);
+ mutex_unlock(&rcu_gp_lock);
+ _rcu_thread_online();
+ }
+@@ -343,7 +345,7 @@ void rcu_unregister_thread(void)
+ */
+ _rcu_thread_offline();
+ mutex_lock(&rcu_gp_lock);
+- cds_list_del(&rcu_reader.node);
++ cds_list_del(&rcu_reader()->node);
+ mutex_unlock(&rcu_gp_lock);
+ }
+
+diff --git a/urcu.c b/urcu.c
+index ba013d9..69a8311 100644
+--- a/urcu.c
++++ b/urcu.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -35,6 +36,7 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <poll.h>
++#include <config.h>
+
+ #include "urcu/wfqueue.h"
+ #include "urcu/map/urcu.h"
+@@ -94,11 +96,11 @@ unsigned long rcu_gp_ctr = RCU_GP_COUNT;
+ * Written to only by each individual reader. Read by both the reader and the
+ * writers.
+ */
+-struct rcu_reader __thread rcu_reader;
++TLS_DEFINE(struct rcu_reader, rcu_reader, _rcu_reader);
+
+ #ifdef DEBUG_YIELD
+ unsigned int yield_active;
+-unsigned int __thread rand_yield;
++TLS_DEFINE(unsigned int, get_rand_yield, _rand_yield);
+ #endif
+
+ static CDS_LIST_HEAD(registry);
+@@ -120,9 +122,9 @@ static void mutex_lock(pthread_mutex_t *mutex)
+ perror("Error in pthread mutex lock");
+ exit(-1);
+ }
+- if (CMM_LOAD_SHARED(rcu_reader.need_mb)) {
++ if (CMM_LOAD_SHARED(rcu_reader()->need_mb)) {
+ cmm_smp_mb();
+- _CMM_STORE_SHARED(rcu_reader.need_mb, 0);
++ _CMM_STORE_SHARED(rcu_reader()->need_mb, 0);
+ cmm_smp_mb();
+ }
+ poll(NULL,0,10);
+@@ -368,20 +370,20 @@ void rcu_read_unlock(void)
+
+ void rcu_register_thread(void)
+ {
+- rcu_reader.tid = pthread_self();
+- assert(rcu_reader.need_mb == 0);
+- assert(!(rcu_reader.ctr & RCU_GP_CTR_NEST_MASK));
++ rcu_reader()->tid = pthread_self();
++ assert(rcu_reader()->need_mb == 0);
++ assert(!(rcu_reader()->ctr & RCU_GP_CTR_NEST_MASK));
+
+ mutex_lock(&rcu_gp_lock);
+ rcu_init(); /* In case gcc does not support constructor attribute */
+- cds_list_add(&rcu_reader.node, &registry);
++ cds_list_add(&rcu_reader()->node, &registry);
+ mutex_unlock(&rcu_gp_lock);
+ }
+
+ void rcu_unregister_thread(void)
+ {
+ mutex_lock(&rcu_gp_lock);
+- cds_list_del(&rcu_reader.node);
++ cds_list_del(&rcu_reader()->node);
+ mutex_unlock(&rcu_gp_lock);
+ }
+
+@@ -405,7 +407,7 @@ static void sigrcu_handler(int signo, siginfo_t *siginfo, void *context)
+ * executed on.
+ */
+ cmm_smp_mb();
+- _CMM_STORE_SHARED(rcu_reader.need_mb, 0);
++ _CMM_STORE_SHARED(rcu_reader()->need_mb, 0);
+ cmm_smp_mb();
+ }
+
+diff --git a/urcu/map/urcu-bp.h b/urcu/map/urcu-bp.h
+index 4abe8dc..f269135 100644
+--- a/urcu/map/urcu-bp.h
++++ b/urcu/map/urcu-bp.h
+@@ -9,6 +9,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+@@ -44,6 +45,7 @@
+ #define rcu_exit rcu_exit_bp
+ #define synchronize_rcu synchronize_rcu_bp
+ #define rcu_reader rcu_reader_bp
++#define _rcu_reader _rcu_reader_bp
+ #define rcu_gp_ctr rcu_gp_ctr_bp
+
+ #define get_cpu_call_rcu_data get_cpu_call_rcu_data_bp
+diff --git a/urcu/map/urcu-qsbr.h b/urcu/map/urcu-qsbr.h
+index 0d88d83..f947791 100644
+--- a/urcu/map/urcu-qsbr.h
++++ b/urcu/map/urcu-qsbr.h
+@@ -9,6 +9,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+@@ -47,6 +48,7 @@
+ #define rcu_exit rcu_exit_qsbr
+ #define synchronize_rcu synchronize_rcu_qsbr
+ #define rcu_reader rcu_reader_qsbr
++#define _rcu_reader _rcu_reader_qsbr
+ #define rcu_gp_ctr rcu_gp_ctr_qsbr
+
+ #define get_cpu_call_rcu_data get_cpu_call_rcu_data_qsbr
+diff --git a/urcu/map/urcu.h b/urcu/map/urcu.h
+index 3f436a7..a6d5c37 100644
+--- a/urcu/map/urcu.h
++++ b/urcu/map/urcu.h
+@@ -9,6 +9,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+@@ -75,6 +76,7 @@
+ #define rcu_exit rcu_exit_memb
+ #define synchronize_rcu synchronize_rcu_memb
+ #define rcu_reader rcu_reader_memb
++#define _rcu_reader _rcu_reader_memb
+ #define rcu_gp_ctr rcu_gp_ctr_memb
+
+ #define get_cpu_call_rcu_data get_cpu_call_rcu_data_memb
+@@ -107,6 +109,7 @@
+ #define rcu_exit rcu_exit_sig
+ #define synchronize_rcu synchronize_rcu_sig
+ #define rcu_reader rcu_reader_sig
++#define _rcu_reader _rcu_reader_sig
+ #define rcu_gp_ctr rcu_gp_ctr_sig
+
+ #define get_cpu_call_rcu_data get_cpu_call_rcu_data_sig
+@@ -139,6 +142,7 @@
+ #define rcu_exit rcu_exit_mb
+ #define synchronize_rcu synchronize_rcu_mb
+ #define rcu_reader rcu_reader_mb
++#define _rcu_reader _rcu_reader_mb
+ #define rcu_gp_ctr rcu_gp_ctr_mb
+
+ #define get_cpu_call_rcu_data get_cpu_call_rcu_data_mb
+diff --git a/urcu/static/urcu-bp.h b/urcu/static/urcu-bp.h
+index 8d22163..42e4b6e 100644
+--- a/urcu/static/urcu-bp.h
++++ b/urcu/static/urcu-bp.h
+@@ -11,6 +11,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -38,6 +39,7 @@
+ #include <urcu/system.h>
+ #include <urcu/uatomic.h>
+ #include <urcu/list.h>
++#include <urcu/tls-compat.h>
+
+ /*
+ * This code section can only be included in LGPL 2.1 compatible source code.
+@@ -74,7 +76,9 @@ extern "C" {
+ #define MAX_SLEEP 50
+
+ extern unsigned int yield_active;
+-extern unsigned int __thread rand_yield;
++TLS_DECLARE(unsigned int, get_rand_yield, _rand_yield);
++// Safe if rand_yield is not redefined
++#define rand_yield (*get_rand_yield())
+
+ static inline void debug_yield_read(void)
+ {
+@@ -144,7 +148,7 @@ struct rcu_reader {
+ * Adds a pointer dereference on the read-side, but won't require to unregister
+ * the reader thread.
+ */
+-extern struct rcu_reader __thread *rcu_reader;
++TLS_DECLARE(struct rcu_reader*, rcu_reader, _rcu_reader);
+
+ static inline int rcu_old_gp_ongoing(long *value)
+ {
+@@ -166,24 +170,24 @@ static inline void _rcu_read_lock(void)
+ long tmp;
+
+ /* Check if registered */
+- if (caa_unlikely(!rcu_reader))
++ if (caa_unlikely(!*rcu_reader()))
+ rcu_bp_register();
+
+ cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
+- tmp = rcu_reader->ctr;
++ tmp = (*rcu_reader())->ctr;
+ /*
+ * rcu_gp_ctr is
+ * RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
+ */
+ if (caa_likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
+- _CMM_STORE_SHARED(rcu_reader->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
++ _CMM_STORE_SHARED((*rcu_reader())->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
+ /*
+ * Set active readers count for outermost nesting level before
+ * accessing the pointer.
+ */
+ cmm_smp_mb();
+ } else {
+- _CMM_STORE_SHARED(rcu_reader->ctr, tmp + RCU_GP_COUNT);
++ _CMM_STORE_SHARED((*rcu_reader())->ctr, tmp + RCU_GP_COUNT);
+ }
+ }
+
+@@ -193,7 +197,7 @@ static inline void _rcu_read_unlock(void)
+ * Finish using rcu before decrementing the pointer.
+ */
+ cmm_smp_mb();
+- _CMM_STORE_SHARED(rcu_reader->ctr, rcu_reader->ctr - RCU_GP_COUNT);
++ _CMM_STORE_SHARED((*rcu_reader())->ctr, (*rcu_reader())->ctr - RCU_GP_COUNT);
+ cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
+ }
+
+diff --git a/urcu/static/urcu-qsbr.h b/urcu/static/urcu-qsbr.h
+index 68bfc31..fac39a1 100644
+--- a/urcu/static/urcu-qsbr.h
++++ b/urcu/static/urcu-qsbr.h
+@@ -11,6 +11,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -42,6 +43,7 @@
+ #include <urcu/uatomic.h>
+ #include <urcu/list.h>
+ #include <urcu/futex.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+@@ -74,7 +76,9 @@ extern "C" {
+ #define MAX_SLEEP 50
+
+ extern unsigned int yield_active;
+-extern unsigned int __thread rand_yield;
++TLS_DECLARE(unsigned int, get_rand_yield, _rand_yield);
++// Safe if rand_yield is not redefined
++#define rand_yield (*get_rand_yield())
+
+ static inline void debug_yield_read(void)
+ {
+@@ -128,7 +132,7 @@ struct rcu_reader {
+ pthread_t tid;
+ };
+
+-extern struct rcu_reader __thread rcu_reader;
++TLS_DECLARE(struct rcu_reader, rcu_reader, _rcu_reader);
+
+ extern int32_t gp_futex;
+
+@@ -137,8 +141,8 @@ extern int32_t gp_futex;
+ */
+ static inline void wake_up_gp(void)
+ {
+- if (caa_unlikely(_CMM_LOAD_SHARED(rcu_reader.waiting))) {
+- _CMM_STORE_SHARED(rcu_reader.waiting, 0);
++ if (caa_unlikely(_CMM_LOAD_SHARED(rcu_reader()->waiting))) {
++ _CMM_STORE_SHARED(rcu_reader()->waiting, 0);
+ cmm_smp_mb();
+ if (uatomic_read(&gp_futex) != -1)
+ return;
+@@ -158,7 +162,7 @@ static inline int rcu_gp_ongoing(unsigned long *ctr)
+
+ static inline void _rcu_read_lock(void)
+ {
+- rcu_assert(rcu_reader.ctr);
++ rcu_assert(rcu_reader()->ctr);
+ }
+
+ static inline void _rcu_read_unlock(void)
+@@ -168,7 +172,7 @@ static inline void _rcu_read_unlock(void)
+ static inline void _rcu_quiescent_state(void)
+ {
+ cmm_smp_mb();
+- _CMM_STORE_SHARED(rcu_reader.ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
++ _CMM_STORE_SHARED(rcu_reader()->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
+ cmm_smp_mb(); /* write rcu_reader.ctr before read futex */
+ wake_up_gp();
+ cmm_smp_mb();
+@@ -177,8 +181,8 @@ static inline void _rcu_quiescent_state(void)
+ static inline void _rcu_thread_offline(void)
+ {
+ cmm_smp_mb();
+- CMM_STORE_SHARED(rcu_reader.ctr, 0);
+- cmm_smp_mb(); /* write rcu_reader.ctr before read futex */
++ CMM_STORE_SHARED(rcu_reader()->ctr, 0);
++ cmm_smp_mb(); /* write _rcu_reader.ctr before read futex */
+ wake_up_gp();
+ cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
+ }
+@@ -186,7 +190,7 @@ static inline void _rcu_thread_offline(void)
+ static inline void _rcu_thread_online(void)
+ {
+ cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
+- _CMM_STORE_SHARED(rcu_reader.ctr, CMM_LOAD_SHARED(rcu_gp_ctr));
++ _CMM_STORE_SHARED(rcu_reader()->ctr, CMM_LOAD_SHARED(rcu_gp_ctr));
+ cmm_smp_mb();
+ }
+
+diff --git a/urcu/static/urcu.h b/urcu/static/urcu.h
+index 7ae0185..302404b 100644
+--- a/urcu/static/urcu.h
++++ b/urcu/static/urcu.h
+@@ -11,6 +11,7 @@
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
++ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -33,6 +34,7 @@
+ #include <pthread.h>
+ #include <unistd.h>
+ #include <stdint.h>
++#include <config.h>
+
+ #include <urcu/compiler.h>
+ #include <urcu/arch.h>
+@@ -40,6 +42,7 @@
+ #include <urcu/uatomic.h>
+ #include <urcu/list.h>
+ #include <urcu/futex.h>
++#include <urcu/tls-compat.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+@@ -121,7 +124,9 @@ extern "C" {
+ #endif
+
+ extern unsigned int yield_active;
+-extern unsigned int __thread rand_yield;
++TLS_DECLARE(unsigned int, get_rand_yield, _rand_yield);
++// Safe shortcut if rand_yield is not redefined
++#define rand_yield (*get_rand_yield())
+
+ static inline void debug_yield_read(void)
+ {
+@@ -222,7 +227,7 @@ struct rcu_reader {
+ pthread_t tid;
+ };
+
+-extern struct rcu_reader __thread rcu_reader;
++TLS_DECLARE(struct rcu_reader, rcu_reader, _rcu_reader);
+
+ extern int32_t gp_futex;
+
+@@ -256,20 +261,20 @@ static inline void _rcu_read_lock(void)
+ unsigned long tmp;
+
+ cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
+- tmp = rcu_reader.ctr;
++ tmp = rcu_reader()->ctr;
+ /*
+ * rcu_gp_ctr is
+ * RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
+ */
+ if (caa_likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
+- _CMM_STORE_SHARED(rcu_reader.ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
++ _CMM_STORE_SHARED(rcu_reader()->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
+ /*
+ * Set active readers count for outermost nesting level before
+ * accessing the pointer. See smp_mb_master().
+ */
+ smp_mb_slave(RCU_MB_GROUP);
+ } else {
+- _CMM_STORE_SHARED(rcu_reader.ctr, tmp + RCU_GP_COUNT);
++ _CMM_STORE_SHARED(rcu_reader()->ctr, tmp + RCU_GP_COUNT);
+ }
+ }
+
+@@ -277,19 +282,19 @@ static inline void _rcu_read_unlock(void)
+ {
+ unsigned long tmp;
+
+- tmp = rcu_reader.ctr;
++ tmp = rcu_reader()->ctr;
+ /*
+ * Finish using rcu before decrementing the pointer.
+ * See smp_mb_master().
+ */
+ if (caa_likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) {
+ smp_mb_slave(RCU_MB_GROUP);
+- _CMM_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT);
++ _CMM_STORE_SHARED(rcu_reader()->ctr, rcu_reader()->ctr - RCU_GP_COUNT);
+ /* write rcu_reader.ctr before read futex */
+ smp_mb_slave(RCU_MB_GROUP);
+ wake_up_gp();
+ } else {
+- _CMM_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT);
++ _CMM_STORE_SHARED(rcu_reader()->ctr, rcu_reader()->ctr - RCU_GP_COUNT);
+ }
+ cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
+ }
+diff --git a/urcu/tls-compat.h b/urcu/tls-compat.h
+new file mode 100644
+index 0000000..d47e803
+--- /dev/null
++++ b/urcu/tls-compat.h
+@@ -0,0 +1,104 @@
++/* 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/>.
++ */
++#ifndef _TLS_COMPAT_H
++#define _TLS_COMPAT_H
++#include <config.h>
++
++/* Conditional includes. */
++#ifndef TLS
++#include <pthread.h>
++#endif
++
++/*!
++ * \brief TLS variable declaration (requires TLS_DEFINITION in .c file)
++ * \param T declared type.
++ * \param name output function name.
++ * \param vname internal variable name.
++ *
++ * Output: function "T* name()".
++ *
++ * Example:
++ * TLS_DECLARE(int, a, _a);
++ * TLS_DEFINE(int, a, _a);
++ * *(a()) = 1
++ */
++#ifdef TLS
++ #define TLS_DECLARE(T, name, vname) \
++ extern TLS T vname; \
++ static inline T *name() { \
++ return &vname;\
++ }
++#else
++ #define TLS_DECLARE(T, name, vname) \
++ T *name()
++#endif
++
++/*!
++ * \brief TLS variable definition.
++ * \param T declared type.
++ * \param name output function name.
++ * \param vname internal variable name.
++ *
++ * Output: function "T* name()" or TLS variable "vname".
++ * Requires TLS_DECLARE for exported API.
++ */
++#ifdef TLS
++#define TLS_DEFINE(T, name, vname) \
++TLS T vname
++#else
++#define TLS_DEFINE(T, name, vname) \
++static pthread_key_t tls_ ## name ## _key; \
++static pthread_once_t tls_ ## name ## _once = PTHREAD_ONCE_INIT; \
++static void tls_ ## name ## _deinit() { \
++ free((void*)pthread_getspecific(tls_ ## name ## _key)); \
++} \
++static void tls_ ## name ## _init() { \
++ (void)pthread_key_create(&tls_ ## name ## _key, tls_ ## name ## _deinit); \
++ atexit(tls_ ## name ## _deinit); \
++} \
++T *name() { \
++ (void)pthread_once(&tls_ ## name ## _once, tls_ ## name ## _init); \
++ void *p = pthread_getspecific(tls_ ## name ## _key); \
++ if (p == NULL) { \
++ p = malloc(sizeof(T)); \
++ memset(p, 0, sizeof(T)); \
++ (void)pthread_setspecific(tls_ ## name ## _key, p); \
++ } \
++ return p; \
++}
++#endif
++
++/*!
++ * \brief TLS variable declaration+definition.
++ * \param T declared type.
++ * \param name output function name.
++ * \param vname internal variable name.
++ *
++ * Output: function "T* name()" or TLS variable "vname".
++ * Requires TLS_DECLARE for exported API.
++ */
++#ifndef TLS
++#define TLS_DEFINE_SIMPLE(T, name, vname) \
++TLS_DEFINE(T, name, vname)
++#else
++#define TLS_DEFINE_SIMPLE(T, name, vname) \
++TLS_DEFINE(T, name, vname); \
++static inline T *name() { \
++ return &vname;\
++}
++#endif
++
++#endif // _TLS_COMPAT_H
+--
+1.7.7.1
+
diff --git a/src/common/acl.h b/src/common/acl.h
index 1b7e97f..7303de8 100644
--- a/src/common/acl.h
+++ b/src/common/acl.h
@@ -75,7 +75,7 @@ void acl_delete(acl_t **acl);
/*!
* \brief Create new ACL rule.
*
- * \todo Support address subnets.
+ * \todo Support address subnets (issue #1366).
*
* \param acl Pointer to ACL instance.
* \param addr IP address.
diff --git a/src/common/evqueue.c b/src/common/evqueue.c
index ca3027f..7614111 100644
--- a/src/common/evqueue.c
+++ b/src/common/evqueue.c
@@ -17,6 +17,84 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <config.h>
+
+/* OpenBSD compatibility. */
+#ifndef HAVE_PSELECT
+/*
+ * Like select(2) but set the signals to block while waiting in
+ * select. This version is not entirely race condition safe. Only
+ * operating system support can make it so.
+ *
+ * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <unistd.h>
+#include <signal.h>
+
+static int
+pselect (int n,
+ fd_set *readfds,
+ fd_set *writefds,
+ fd_set *exceptfds,
+ const struct timespec *timeout,
+ const sigset_t *sigmask)
+{
+ int result;
+ sigset_t saved_sigmask;
+ struct timeval saved_timeout;
+
+ if (sigmask && sigprocmask(SIG_SETMASK, sigmask, &saved_sigmask) == -1)
+ return -1;
+
+ if (timeout) {
+ saved_timeout.tv_sec = timeout->tv_sec;
+ saved_timeout.tv_usec = timeout->tv_nsec / 1000;
+ result = select(n, readfds, writefds, exceptfds, &saved_timeout);
+ } else {
+ result = select(n, readfds, writefds, exceptfds, NULL);
+ }
+
+ if (sigmask && sigprocmask(SIG_SETMASK, &saved_sigmask, NULL) == -1)
+ return -1;
+
+ return result;
+}
+
+#endif
#include "common/evqueue.h"
diff --git a/src/common/evsched.c b/src/common/evsched.c
index c4a6786..067977f 100644
--- a/src/common/evsched.c
+++ b/src/common/evsched.c
@@ -17,9 +17,15 @@
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
+#include <config.h>
#include "common/evsched.h"
+/*! \todo Fix properly (issue #1581). */
+#ifndef HAVE_PSELECT
+#define OPENBSD_SLAB_BROKEN
+#endif
+
/*!
* \brief Set event timer to T (now) + dt miliseconds.
*/
@@ -60,7 +66,9 @@ evsched_t *evsched_new()
pthread_mutex_init(&s->mx, 0);
pthread_cond_init(&s->notify, 0);
pthread_mutex_init(&s->cache.lock, 0);
+#ifndef OPENBSD_SLAB_BROKEN
slab_cache_init(&s->cache.alloc, sizeof(event_t));
+#endif
init_list(&s->calendar);
return s;
}
@@ -83,8 +91,10 @@ void evsched_delete(evsched_t **s)
evsched_event_free((*s), (event_t*)n);
}
+#ifndef OPENBSD_SLAB_BROKEN
/* Free allocator. */
slab_cache_destroy(&(*s)->cache.alloc);
+#endif
pthread_mutex_destroy(&(*s)->cache.lock);
/* Free scheduler. */
@@ -99,9 +109,16 @@ event_t *evsched_event_new(evsched_t *s, int type)
}
/* Allocate. */
+#ifndef OPENBSD_SLAB_BROKEN
pthread_mutex_lock(&s->cache.lock);
event_t *e = slab_cache_alloc(&s->cache.alloc);
pthread_mutex_unlock(&s->cache.lock);
+#else
+ event_t *e = malloc(sizeof(event_t));
+#endif
+ if (e == NULL) {
+ return NULL;
+ }
/* Initialize. */
memset(e, 0, sizeof(event_t));
@@ -115,9 +132,13 @@ void evsched_event_free(evsched_t *s, event_t *ev)
return;
}
+#ifndef OPENBSD_SLAB_BROKEN
pthread_mutex_lock(&s->cache.lock);
slab_free(ev);
pthread_mutex_unlock(&s->cache.lock);
+#else
+ free(ev);
+#endif
}
event_t* evsched_next(evsched_t *s)
diff --git a/src/common/fdset.c b/src/common/fdset.c
index 8c070ad..a281473 100644
--- a/src/common/fdset.c
+++ b/src/common/fdset.c
@@ -21,8 +21,22 @@
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
-#include "common/fdset.h"
+#include <time.h>
+#include <stdlib.h>
#include <config.h>
+#include "common/fdset.h"
+
+/* Workarounds for clock_gettime() not available on some platforms. */
+#ifdef HAVE_CLOCK_GETTIME
+#define time_now(x) clock_gettime(CLOCK_MONOTONIC, (x))
+typedef struct timespec timev_t;
+#elif HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#define time_now(x) gettimeofday((x), NULL)
+typedef struct timeval timev_t;
+#else
+#error Neither clock_gettime() nor gettimeofday() found. At least one is required.
+#endif
struct fdset_backend_t _fdset_backend = {
};
@@ -78,3 +92,114 @@ void __attribute__ ((constructor)) fdset_init()
fprintf(stderr, "fdset: fatal error - no valid fdset backend found\n");
return;
}
+
+/*!
+ * \brief Compare file descriptors.
+ *
+ * \param a File descriptor.
+ * \param b File descriptor.
+ *
+ * \retval -1 if a < b
+ * \retval 0 if a == b
+ * \retval 1 if a > b
+ */
+static int fdset_compare(void *a, void *b)
+{
+ if ((size_t)a < (size_t)b) return -1;
+ if ((size_t)a > (size_t)b) return 1;
+ return 0;
+}
+
+fdset_t *fdset_new() {
+ fdset_t* set = _fdset_backend.fdset_new();
+ fdset_base_t *base = (fdset_base_t*)set;
+ if (base != NULL) {
+ /* Create atimes list. */
+ base->atimes = skip_create_list(fdset_compare);
+ if (base->atimes == NULL) {
+ fdset_destroy(set);
+ set = NULL;
+ }
+ }
+ return set;
+}
+
+int fdset_destroy(fdset_t* fdset) {
+ fdset_base_t *base = (fdset_base_t*)fdset;
+ if (base != NULL && base->atimes != NULL) {
+ skip_destroy_list(&base->atimes, NULL, free);
+ }
+ return _fdset_backend.fdset_destroy(fdset);
+}
+
+int fdset_remove(fdset_t *fdset, int fd) {
+ fdset_base_t *base = (fdset_base_t*)fdset;
+ if (base != NULL && base->atimes != NULL) {
+ skip_remove(base->atimes, (void*)((size_t)fd), NULL, free);
+ }
+ return _fdset_backend.fdset_remove(fdset, fd);
+}
+
+int fdset_set_watchdog(fdset_t* fdset, int fd, int interval)
+{
+ fdset_base_t *base = (fdset_base_t*)fdset;
+ if (base == NULL || base->atimes == NULL) {
+ return -1;
+ }
+
+ /* Lift watchdog if interval is negative. */
+ if (interval < 0) {
+ skip_remove(base->atimes, (void*)((size_t)fd), NULL, free);
+ return 0;
+ }
+
+ /* Find if exists. */
+ timev_t *ts = NULL;
+ ts = (timev_t*)skip_find(base->atimes, (void*)((size_t)fd));
+ if (ts == NULL) {
+ ts = malloc(sizeof(timev_t));
+ if (ts == NULL) {
+ return -1;
+ }
+ skip_insert(base->atimes, (void*)((size_t)fd), (void*)ts, NULL);
+ }
+
+ /* Update clock. */
+ if (time_now(ts) < 0) {
+ return -1;
+ }
+
+ ts->tv_sec += interval; /* Only seconds precision. */
+ return 0;
+}
+
+int fdset_sweep(fdset_t* fdset, void(*cb)(fdset_t*, int))
+{
+ fdset_base_t *base = (fdset_base_t*)fdset;
+ if (base == NULL || base->atimes == NULL) {
+ return -1;
+ }
+
+ /* Get time threshold. */
+ timev_t now;
+ if (time_now(&now) < 0) {
+ return -1;
+ }
+
+ /* Inspect all nodes. */
+ int sweeped = 0;
+ const skip_node_t *n = skip_first(base->atimes);
+ while (n != NULL) {
+ const skip_node_t* pnext = skip_next(n);
+
+ /* Evaluate */
+ timev_t *ts = (timev_t*)n->value;
+ if (ts->tv_sec <= now.tv_sec) {
+ cb(fdset, (int)(((ssize_t)n->key)));
+ ++sweeped;
+ }
+ n = pnext;
+ }
+
+ return sweeped;
+}
diff --git a/src/common/fdset.h b/src/common/fdset.h
index 10196bf..a40cb4a 100644
--- a/src/common/fdset.h
+++ b/src/common/fdset.h
@@ -21,8 +21,7 @@
* \brief Wrapper for native I/O multiplexing.
*
* Selects best implementation according to config.
- * - select()
- * - poll() \todo
+ * - poll()
* - epoll()
* - kqueue()
*
@@ -34,8 +33,28 @@
#define _KNOTD_FDSET_H_
#include <stddef.h>
+#include "skip-list.h"
-/*! \brief Opaque pointer to implementation-specific fdset data. */
+/*! \brief Waiting for completion constants. */
+enum fdset_wait_t {
+ OS_EV_FOREVER = -1, /*!< Wait forever. */
+ OS_EV_NOWAIT = 0 /*!< Return immediately. */
+};
+
+/*! \brief Base for implementation-specific fdsets. */
+typedef struct fdset_base_t {
+ skip_list_t *atimes;
+} fdset_base_t;
+
+/*!
+ * \brief Opaque pointer to implementation-specific fdset data.
+ * \warning Implementation MUST have fdset_base_t member on the first place.
+ * Example:
+ * struct fdset_t {
+ * fdset_base_t base;
+ * ...other members...
+ * }
+ */
typedef struct fdset_t fdset_t;
/*! \brief Unified event types. */
@@ -63,7 +82,7 @@ struct fdset_backend_t
int (*fdset_destroy)(fdset_t*);
int (*fdset_add)(fdset_t*, int, int);
int (*fdset_remove)(fdset_t*, int);
- int (*fdset_wait)(fdset_t*);
+ int (*fdset_wait)(fdset_t*, int);
int (*fdset_begin)(fdset_t*, fdset_it_t*);
int (*fdset_end)(fdset_t*, fdset_it_t*);
int (*fdset_next)(fdset_t*, fdset_it_t*);
@@ -84,9 +103,7 @@ extern struct fdset_backend_t _fdset_backend;
* \retval Pointer to initialized FDSET structure if successful.
* \retval NULL on error.
*/
-static inline fdset_t *fdset_new() {
- return _fdset_backend.fdset_new();
-}
+fdset_t *fdset_new();
/*!
* \brief Destroy FDSET.
@@ -94,9 +111,7 @@ static inline fdset_t *fdset_new() {
* \retval 0 if successful.
* \retval -1 on error.
*/
-static inline int fdset_destroy(fdset_t * fdset) {
- return _fdset_backend.fdset_destroy(fdset);
-}
+int fdset_destroy(fdset_t* fdset);
/*!
* \brief Add file descriptor to watched set.
@@ -122,22 +137,19 @@ static inline int fdset_add(fdset_t *fdset, int fd, int events) {
* \retval 0 if successful.
* \retval -1 on errors.
*/
-static inline int fdset_remove(fdset_t *fdset, int fd) {
- return _fdset_backend.fdset_remove(fdset, fd);
-}
+int fdset_remove(fdset_t *fdset, int fd);
/*!
* \brief Poll set for new events.
*
* \param fdset Target set.
+ * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds).
*
* \retval Number of events if successful.
* \retval -1 on errors.
- *
- * \todo Timeout.
*/
-static inline int fdset_wait(fdset_t *fdset) {
- return _fdset_backend.fdset_wait(fdset);
+static inline int fdset_wait(fdset_t *fdset, int timeout) {
+ return _fdset_backend.fdset_wait(fdset, timeout);
}
/*!
@@ -191,6 +203,33 @@ static inline const char* fdset_method() {
return _fdset_backend.fdset_method();
}
+/*!
+ * \brief Set file descriptor watchdog interval.
+ *
+ * Descriptors without activity in given interval
+ * can be disposed with fdset_sweep().
+ *
+ * \param fdset Target set.
+ * \param fd File descriptor.
+ * \param interval Allowed interval without activity (seconds).
+ * <0 removes watchdog interval.
+ *
+ * \retval 0 if successful.
+ * \retval -1 on errors.
+ */
+int fdset_set_watchdog(fdset_t* fdset, int fd, int interval);
+
+/*!
+ * \brief Sweep file descriptors with exceeding inactivity period.
+ *
+ * \param fdset Target set.
+ * \param cb Callback for sweeped descriptors.
+ *
+ * \retval number of sweeped descriptors.
+ * \retval -1 on errors.
+ */
+int fdset_sweep(fdset_t* fdset, void(*cb)(fdset_t* set, int fd));
+
#endif /* _KNOTD_FDSET_H_ */
/*! @} */
diff --git a/src/common/fdset_epoll.c b/src/common/fdset_epoll.c
index cb2e3e1..dbd803f 100644
--- a/src/common/fdset_epoll.c
+++ b/src/common/fdset_epoll.c
@@ -24,11 +24,13 @@
#include <unistd.h>
#include "fdset_epoll.h"
+#include "skip-list.h"
#define OS_FDS_CHUNKSIZE 8 /*!< Number of pollfd structs in a chunk. */
#define OS_FDS_KEEPCHUNKS 32 /*!< Will attempt to free memory when reached. */
struct fdset_t {
+ fdset_base_t _base;
int epfd;
struct epoll_event *events;
size_t nfds;
@@ -40,7 +42,7 @@ fdset_t *fdset_epoll_new()
{
fdset_t *set = malloc(sizeof(fdset_t));
if (!set) {
- return 0;
+ return NULL;
}
/* Blank memory. */
@@ -95,7 +97,7 @@ int fdset_epoll_add(fdset_t *fdset, int fd, int events)
/* Add to epoll set. */
struct epoll_event ev;
memset(&ev, 0, sizeof(struct epoll_event));
- ev.events = EPOLLIN; /*! \todo MAP events. */
+ ev.events = EPOLLIN;
ev.data.fd = fd;
if (epoll_ctl(fdset->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
return -1;
@@ -121,11 +123,11 @@ int fdset_epoll_remove(fdset_t *fdset, int fd)
/* Overwrite current item. */
--fdset->nfds;
- /*! \todo Return memory if overallocated (nfds is far lower than reserved). */
+ /*! \todo Return memory if unused (issue #1582). */
return 0;
}
-int fdset_epoll_wait(fdset_t *fdset)
+int fdset_epoll_wait(fdset_t *fdset, int timeout)
{
if (!fdset || fdset->nfds < 1 || !fdset->events) {
return -1;
@@ -133,7 +135,7 @@ int fdset_epoll_wait(fdset_t *fdset)
/* Poll new events. */
fdset->polled = 0;
- int nfds = epoll_wait(fdset->epfd, fdset->events, fdset->nfds, -1);
+ int nfds = epoll_wait(fdset->epfd, fdset->events, fdset->nfds, timeout);
/* Check. */
if (nfds < 0) {
@@ -173,7 +175,7 @@ int fdset_epoll_end(fdset_t *fdset, fdset_it_t *it)
size_t nid = fdset->polled - 1;
it->fd = fdset->events[nid].data.fd;
it->pos = nid;
- it->events = 0; /*! \todo Map events. */
+ it->events = 0;
return -1;
}
@@ -191,7 +193,7 @@ int fdset_epoll_next(fdset_t *fdset, fdset_it_t *it)
/* Select next. */
size_t nid = it->pos++;
it->fd = fdset->events[nid].data.fd;
- it->events = 0; /*! \todo Map events. */
+ it->events = 0;
return 0;
}
diff --git a/src/common/fdset_epoll.h b/src/common/fdset_epoll.h
index 551394d..58f25f8 100644
--- a/src/common/fdset_epoll.h
+++ b/src/common/fdset_epoll.h
@@ -74,13 +74,12 @@ int fdset_epoll_remove(fdset_t *fdset, int fd);
* \brief Poll set for new events.
*
* \param fdset Target set.
+ * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds).
*
* \retval Number of events if successful.
* \retval -1 on errors.
- *
- * \todo Timeout.
*/
-int fdset_epoll_wait(fdset_t *fdset);
+int fdset_epoll_wait(fdset_t *fdset, int timeout);
/*!
* \brief Set event iterator to the beginning of last polled events.
diff --git a/src/common/fdset_kqueue.c b/src/common/fdset_kqueue.c
index c7199ae..bbb35fc 100644
--- a/src/common/fdset_kqueue.c
+++ b/src/common/fdset_kqueue.c
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <sys/event.h>
#include <sys/time.h>
+#include <time.h>
#include "fdset_kqueue.h"
@@ -31,6 +32,7 @@
#define OS_FDS_KEEPCHUNKS 32 /*!< Will attempt to free memory when reached. */
struct fdset_t {
+ fdset_base_t _base;
int kq;
struct kevent *events;
struct kevent *revents;
@@ -75,7 +77,7 @@ int fdset_kqueue_destroy(fdset_t * fdset)
return 0;
}
-int fdset_kqueue_realloc(void **old, size_t oldsize, size_t nsize)
+int fdset_kqueue_realloc(struct kevent **old, size_t oldsize, size_t nsize)
{
void *nmem = malloc(nsize);
if (!nmem) {
@@ -101,10 +103,10 @@ int fdset_kqueue_add(fdset_t *fdset, int fd, int events)
/* Realloc needed. */
if (fdset->nfds == fdset->reserved) {
- const size_t chunk = OS_FDS_CHUNKSIZE;
- const size_t nsize = (fdset->reserved + chunk) *
+ size_t chunk = OS_FDS_CHUNKSIZE;
+ size_t nsize = (fdset->reserved + chunk) *
sizeof(struct kevent);
- const size_t oldsize = fdset->nfds * sizeof(struct kevent);
+ size_t oldsize = fdset->nfds * sizeof(struct kevent);
if (fdset_kqueue_realloc(&fdset->events, oldsize, nsize) < 0) {
return -1;
@@ -117,7 +119,7 @@ int fdset_kqueue_add(fdset_t *fdset, int fd, int events)
}
/* Add to kqueue set. */
- int evfilt = EVFILT_READ; /*! \todo Map events. */
+ int evfilt = EVFILT_READ;
EV_SET(&fdset->events[fdset->nfds], fd, evfilt,
EV_ADD|EV_ENABLE, 0, 0, 0);
@@ -155,20 +157,33 @@ int fdset_kqueue_remove(fdset_t *fdset, int fd)
/* Overwrite current item. */
--fdset->nfds;
- /*! \todo Return memory if overallocated (nfds is far lower than reserved). */
+ /*! \todo Return memory if unused (issue #1582). */
return 0;
}
-int fdset_kqueue_wait(fdset_t *fdset)
+int fdset_kqueue_wait(fdset_t *fdset, int timeout)
{
if (!fdset || fdset->nfds < 1 || !fdset->events) {
return -1;
}
+ /* Set timeout. */
+ struct timespec tmval;
+ struct timespec *tm = NULL;
+ if (timeout == 0) {
+ tmval.tv_sec = tmval.tv_nsec = 0;
+ tm = &tmval;
+ } else if (timeout > 0) {
+ tmval.tv_sec = timeout / 1000; /* ms -> s */
+ timeout -= tmval.tv_sec * 1000; /* Cut off */
+ tmval.tv_nsec = timeout * 1000000L; /* ms -> ns */
+ tm = &tmval;
+ }
+
/* Poll new events. */
fdset->polled = 0;
int nfds = kevent(fdset->kq, fdset->events, fdset->nfds,
- fdset->revents, fdset->nfds, 0);
+ fdset->revents, fdset->nfds, tm);
/* Check. */
if (nfds < 0) {
diff --git a/src/common/fdset_kqueue.h b/src/common/fdset_kqueue.h
index f64482f..4b650a7 100644
--- a/src/common/fdset_kqueue.h
+++ b/src/common/fdset_kqueue.h
@@ -74,13 +74,12 @@ int fdset_kqueue_remove(fdset_t *fdset, int fd);
* \brief Poll set for new events.
*
* \param fdset Target set.
+ * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds).
*
* \retval Number of events if successful.
* \retval -1 on errors.
- *
- * \todo Timeout.
*/
-int fdset_kqueue_wait(fdset_t *fdset);
+int fdset_kqueue_wait(fdset_t *fdset, int timeout);
/*!
* \brief Set event iterator to the beginning of last polled events.
diff --git a/src/common/fdset_poll.c b/src/common/fdset_poll.c
index 8682eaf..02ed8d4 100644
--- a/src/common/fdset_poll.c
+++ b/src/common/fdset_poll.c
@@ -29,6 +29,7 @@
#define OS_FDS_KEEPCHUNKS 32 /*!< Will attempt to free memory when reached. */
struct fdset_t {
+ fdset_base_t _base;
struct pollfd *fds;
nfds_t nfds;
size_t reserved;
@@ -54,8 +55,6 @@ int fdset_poll_destroy(fdset_t * fdset)
return -1;
}
- /*! \todo No teardown required I guess. */
-
/* OK if NULL. */
free(fdset->fds);
free(fdset);
@@ -88,7 +87,7 @@ int fdset_poll_add(fdset_t *fdset, int fd, int events)
/* Append. */
int nid = fdset->nfds++;
fdset->fds[nid].fd = fd;
- fdset->fds[nid].events = POLLIN; /*! \todo Map events to POLL events. */
+ fdset->fds[nid].events = POLLIN;
return 0;
}
@@ -119,12 +118,11 @@ int fdset_poll_remove(fdset_t *fdset, int fd)
memmove(fdset->fds + pos, fdset->fds + (pos + 1), remaining);
--fdset->nfds;
- /*! \todo Return memory if overallocated (nfds is far lower than reserved). */
- /*! \todo Maybe >64 free chunks is excess? */
+ /*! \todo Return memory if unused (issue #1582). */
return 0;
}
-int fdset_poll_wait(fdset_t *fdset)
+int fdset_poll_wait(fdset_t *fdset, int timeout)
{
if (!fdset || fdset->nfds < 1 || !fdset->fds) {
return -1;
@@ -135,7 +133,7 @@ int fdset_poll_wait(fdset_t *fdset)
fdset->begin = 0;
/* Poll for events. */
- int ret = poll(fdset->fds, fdset->nfds, -1);
+ int ret = poll(fdset->fds, fdset->nfds, timeout);
if (ret < 0) {
return -1;
}
@@ -197,7 +195,7 @@ int fdset_poll_next(fdset_t *fdset, fdset_it_t *it)
struct pollfd* pfd = fdset->fds + it->pos;
if (pfd->events & pfd->revents) {
it->fd = pfd->fd;
- it->events = pfd->revents; /*! \todo MAP events. */
+ it->events = pfd->revents;
++it->pos; /* Next will start after current. */
return 0;
}
diff --git a/src/common/fdset_poll.h b/src/common/fdset_poll.h
index d72b5bb..68e9e69 100644
--- a/src/common/fdset_poll.h
+++ b/src/common/fdset_poll.h
@@ -74,13 +74,12 @@ int fdset_poll_remove(fdset_t *fdset, int fd);
* \brief Poll set for new events.
*
* \param fdset Target set.
+ * \param timeout Timeout (OS_EV_FOREVER, OS_EV_NOWAIT or value in miliseconds).
*
* \retval Number of events if successful.
* \retval -1 on errors.
- *
- * \todo Timeout.
*/
-int fdset_poll_wait(fdset_t *fdset);
+int fdset_poll_wait(fdset_t *fdset, int timeout);
/*!
* \brief Set event iterator to the beginning of last polled events.
diff --git a/src/common/prng.c b/src/common/prng.c
index ca87b0d..250a506 100644
--- a/src/common/prng.c
+++ b/src/common/prng.c
@@ -20,6 +20,10 @@
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
+#include <config.h>
+#ifdef HAVE_MEMALIGN
+#include <malloc.h>
+#endif
#include "prng.h"
#include "dSFMT.h"
@@ -79,7 +83,11 @@ double tls_rand()
}
/* Initialize PRNG state. */
+#ifdef HAVE_MEMALIGN
+ s = memalign(16, sizeof(dsfmt_t));
+#else
s = malloc(sizeof(dsfmt_t));
+#endif
if (s == NULL) {
fprintf(stderr, "error: PRNG: not enough memory\n");
return .0;
@@ -87,6 +95,7 @@ double tls_rand()
dsfmt_init_gen_rand(s, seed);
(void)pthread_setspecific(tls_prng_key, s);
}
+
}
return dsfmt_genrand_close_open(s);
diff --git a/src/common/slab/slab.c b/src/common/slab/slab.c
index ccdf7ca..df30998 100644
--- a/src/common/slab/slab.c
+++ b/src/common/slab/slab.c
@@ -117,7 +117,6 @@ static unsigned SLAB_LOGSIZE = 0; /*!< \brief Binary logarithm of slab size. */
* from a slab with just a few slab items by caching N slabs before returning
* them to the system.
*
- * \todo With wider use, locking or RCU will be necessary.
*/
#ifdef MEM_SLAB_DEPOT
static slab_depot_t _depot_g; /*! \brief Global slab depot. */
@@ -339,7 +338,7 @@ slab_t* slab_create(slab_cache_t* cache)
slab_t* slab = slab_depot_alloc(cache->bufsize);
- if (unlikely(slab < 0)) {
+ if (unlikely(slab == 0)) {
dbg_mem("%s: failed to allocate aligned memory block\n",
__func__);
return 0;
@@ -677,7 +676,6 @@ void* slab_alloc_alloc(slab_alloc_t* alloc, size_t size)
#ifdef MEM_POISON
// Memory barrier
- /*! \todo Broken, need to store the barrier byte size. */
//int* pb = (int*)((char*)mem + size - sizeof(int));
//mprotect(pb, sizeof(int), PROT_NONE);
#endif
diff --git a/src/common/slab/slab.h b/src/common/slab/slab.h
index d64188e..4ea7e31 100644
--- a/src/common/slab/slab.h
+++ b/src/common/slab/slab.h
@@ -74,7 +74,7 @@
*
* \todo Allocate slab headers elsewhere and use just first sizeof(void*) bytes
* in each slab as a pointer to slab header. This could improve the
- * performance.
+ * performance (issue #1583).
*
* \note Slab allocation is not thread safe for performance reasons.
*
@@ -336,7 +336,6 @@ void* slab_alloc_alloc(slab_alloc_t* alloc, size_t size);
* \retval Pointer to newly allocated memory.
* \retval NULL on error.
*
- * \todo Realloc could be probably implement more effectively.
*/
void *slab_alloc_realloc(slab_alloc_t* alloc, void *ptr, size_t size);
diff --git a/src/config.h.in b/src/config.h.in
index 8fe63ce..4761e6b 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -21,6 +21,12 @@
/* Define to 1 if you have the <arpa/nameser.h> header file. */
#undef HAVE_ARPA_NAMESER_H
+/* Define to 1 if you have the <cap-ng.h> header file. */
+#undef HAVE_CAP_NG_H
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
@@ -60,6 +66,9 @@
/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
+/* Define to 1 if you have the `memalign' function. */
+#undef HAVE_MEMALIGN
+
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
@@ -84,9 +93,15 @@
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#undef HAVE_NETINET_IN_SYSTM_H
+
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
+/* Define to 1 if you have the `pselect' function. */
+#undef HAVE_PSELECT
+
/* Define to 1 if you have the `regcomp' function. */
#undef HAVE_REGCOMP
@@ -96,6 +111,12 @@
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
+/* Define to 1 if you have the `sendmmsg' function. */
+#undef HAVE_SENDMMSG
+
+/* Define to 1 if you have the `setgroups' function. */
+#undef HAVE_SETGROUPS
+
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
diff --git a/src/knot.init b/src/knot.init
deleted file mode 100755
index 97194cd..0000000
--- a/src/knot.init
+++ /dev/null
@@ -1,70 +0,0 @@
-#! /bin/sh
-#
-# bird Starts the KNOT DNS daemon
-#
-# Author: Ondrej Feela Filip, <feela@network.cz>
-#
-# chkconfig: - 32 75
-# description: Authoritative DNS server
-#
-# processname: knotd
-# config: /etc/knot/knot.conf
-
-exec="/usr/sbin/knotd"
-prog="knot"
-config="/etc/knot/knot.conf"
-lockfile=/var/lock/subsys/$prog
-
-
-# Source function library.
-. /etc/rc.d/init.d/functions
-
-[ -f /etc/sysconfig/network ] || exit 0
-
-. /etc/sysconfig/network
-
-RETVAL=0
-[ "$EUID" != "0" ] && exit 4
-
-# See how we were called.
-case "$1" in
- start)
- [ "$NETWORKING" = "no" ] && exit 1
- [ -x $exec ] || exit 5
- if [ ! -f $config ]; then
- echo $"Configuration file $config missing" 1>&2
- exit 6
- fi
- echo -n "Starting KNOT DNS daemon: "
- daemon $exec -d
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch $lockfile
- ;;
- stop)
- echo -n "Stopping KNOT DNS daemon: "
- killproc knotd
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f $lockfile
-
- ;;
- status)
- status knotd
- RETVAL=$?
- ;;
- restart)
- $0 stop
- $0 start
- RETVAL=$?
- ;;
- reload)
- knotc reload
- RETVAL=$?
- ;;
- *)
- echo "Usage: knot.init {start|stop|status|restart|reload}"
- exit 1
-esac
-
-exit $RETVAL
diff --git a/src/knot.service b/src/knot.service
new file mode 100644
index 0000000..36864d0
--- /dev/null
+++ b/src/knot.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Knot DNS daemon
+After=syslog.target network.target auditd.service
+
+[Service]
+EnvironmentFile=/etc/sysconfig/knot
+ExecReload=/usr/sbin/knotc reload
+ExecStart=/usr/sbin/knotd $KNOTARGS
+Restart=on-abort
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/src/knot.spec b/src/knot.spec
index a3c430b..5856aab 100644
--- a/src/knot.spec
+++ b/src/knot.spec
@@ -1,27 +1,28 @@
Summary: KNOT DNS daemon
Name: knot
-Version: 0.8
+Version: 0.9.1
Release: 1
License: GPL
Group: Networking/Daemons
-Source: http://public.nic.cz/files/knot-dns/knot-0.8.tar.gz
-Source1: knot.init
-Buildroot: /var/tmp/knot-root
+Source: http://public.nic.cz/files/knot-dns/knot-%{version}.tar.gz
+Source1: %{name}.sysconfig
+Source2: %{name}.service
+Patch: %{name}.diff
+Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-build
Url: http://www.knot-dns.cz
-#Prereq: /sbin/chkconfig
-BuildRequires: flex userspace-rcu-devel openssl-devel
+BuildRequires: flex userspace-rcu-devel openssl-devel bison
%description
KNOT DNS is a high-performance authoritative DNS server implementation.
%prep
%setup -n %{name}-%{version}
-#%patch -p1
+%patch -p1
%build
./configure --prefix=%{_prefix} --sysconfdir=%{_sysconfdir}/%{name} --localstatedir=%{_var}/lib --libexecdir=%{_libexecdir}/%{name}
-make -C samples knot.sample.conf
+make -C samples %{name}.sample.conf
make
@@ -29,27 +30,62 @@ make
rm -rf %{buildroot}/*
make install prefix=%{buildroot}/%{_prefix} sysconfdir=%{buildroot}/%{_sysconfdir}/%{name} localstatedir=%{buildroot}/%{_var}/lib mandir=%{buildroot}/%{_mandir} libexecdir=%{buildroot}/%{_libexecdir}/%{name}
-install -d %{buildroot}/%{_sysconfdir}/init.d
-install $RPM_SOURCE_DIR/%{name}.init %{buildroot}/%{_sysconfdir}/init.d/%{name}
+install -d %{buildroot}/%{_sysconfdir}/sysconfig
+install $RPM_SOURCE_DIR/%{name}.sysconfig %{buildroot}/%{_sysconfdir}/sysconfig/%{name}
install -d %{buildroot}/%{_var}/lib/%{name}
+install -d %{buildroot}/lib/systemd/system/
+install $RPM_SOURCE_DIR/%{name}.service %{buildroot}/lib/systemd/system/%{name}.service
%post
-/sbin/ldconfig
-/sbin/chkconfig --add %{name}
-
+# run after an installation
+if [ $1 -eq 1 ] ; then
+ # Initial installation
+ /bin/systemctl daemon-reload >/dev/null 2>&1 || :
+fi
+
%preun
-if [ $1 = 0 ] ; then
- /sbin/chkconfig --del %{name}
-fi
+# run before a package is removed
+if [ $1 -eq 0 ]; then
+ /bin/systemctl --no-reload disable %{name}.service >/dev/null 2>&1 || :
+ /bin/systemctl stop %{name}.service > /dev/null 2>&1 || :
+fi
+
+%postun
+# run after a package is removed
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+if [ $1 -ge 1 ]; then
+ /bin/systemctl try-restart %{name}.service >/dev/null 2>&1 || :
+fi
+
+%triggerun -- knot < 0.9
+# Save the current service runlevel info
+# User must manually run systemd-sysv-convert --apply %{name}
+# to migrate them to systemd targets
+/usr/bin/systemd-sysv-convert --save %{name}
+
+/sbin/chkconfig --del %{name} >/dev/null 2>&1 || :
+/bin/systemctl try-restart %{name}.service >/dev/null 2>&1 || :
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+
+
%files
%defattr(-,root,root,-)
%config %attr(644,root,root) %{_sysconfdir}/%{name}/*
%{_sbindir}/*
%{_libexecdir}/%{name}/*
-%attr(755,root,root) %{_sysconfdir}/init.d/%{name}
%dir %{_var}/lib/%{name}/
%doc %{_mandir}/man8/*
+%attr(0644,root,root) /lib/systemd/system/%{name}.service
+%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
+
+
%changelog
+* Mon Jan 16 2012 - feela@network.cz
+- Support for systemd.
+- Specfile cleanup
+
+* Thu Nov 3 2011 - feela@network.cz
+- Initial version
diff --git a/src/knot.sysconfig b/src/knot.sysconfig
new file mode 100644
index 0000000..99daeba
--- /dev/null
+++ b/src/knot.sysconfig
@@ -0,0 +1,4 @@
+# Settings for the KNOT DNS daemon.
+# KNOTARGS= : any extra command-line startup arguments for knot dns
+KNOTARGS=
+
diff --git a/src/knot/conf/cf-lex.l b/src/knot/conf/cf-lex.l
index 97ac8f8..6683edc 100644
--- a/src/knot/conf/cf-lex.l
+++ b/src/knot/conf/cf-lex.l
@@ -27,6 +27,20 @@ void switch_input(const char *str, void *scanner)
yy_scan_string(str, scanner);
}
+/* Convert hex to binary. */
+static inline char xd(char d) {
+ if (d >= '0' && d <= '9') return d - '0';
+ if (d >= 'a' && d <= 'f') return d - 'a' + 10;
+ if (d >= 'A' && d <= 'F') return d - 'A' + 10;
+ return 0;
+}
+int hex2bin(const char* src, char *dst, size_t len) {
+ for (unsigned i = 0; i < len; ++i) {
+ dst[i] = (xd(src[i<<1])<<4) + xd(src[(i<<1)+1]);
+ }
+ return 0;
+}
+
//#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
#define YY_NO_UNPUT
@@ -56,6 +70,7 @@ BLANK [ \t\n]
system { lval.t = yytext; return SYSTEM; }
identity { lval.t = yytext; return IDENTITY; }
version { lval.t = yytext; return VERSION; }
+nsid { lval.t = yytext; return NSID; }
storage { lval.t = yytext; return STORAGE; }
key { lval.t = yytext; return KEY; }
keys { lval.t = yytext; return KEYS; }
@@ -73,10 +88,13 @@ xfr-out { lval.t = yytext; return XFR_OUT; }
notify-in { lval.t = yytext; return NOTIFY_IN; }
notify-out { lval.t = yytext; return NOTIFY_OUT; }
workers { lval.t = yytext; return WORKERS; }
+user { lval.t = yytext; return USER; }
+pidfile { lval.t = yytext; return PIDFILE; }
interfaces { lval.t = yytext; return INTERFACES; }
address { lval.t = yytext; return ADDRESS; }
port { lval.t = yytext; return PORT; }
+via { lval.t = yytext; return VIA; }
log { lval.t = yytext; return LOG; }
@@ -191,6 +209,31 @@ on|off {
#endif
}
+[0][x]{HEXA}+ {
+ lval.t = NULL;
+ lval.l = 0;
+ yytext = yytext + 2; /* Cut off 0x */
+ size_t dlen = strlen(yytext);
+ if (dlen % 2 == 1) {
+ cf_error(yyscanner, "Invalid hex-string length.");
+ } else {
+ dlen = dlen / 2;
+ lval.t = malloc((dlen) * sizeof(char));
+ if (lval.t == NULL) {
+ cf_error(yyscanner, "Out of memory when allocating hex-string.\n");
+ } else {
+ memset(lval.t, 0, dlen);
+ if (hex2bin(yytext, lval.t, dlen) < 0) {
+ cf_error(yyscanner, "Failed to convert hex-string to binary.\n");
+ } else {
+ lval.l = dlen;
+ }
+ }
+ }
+
+ return HEXSTR;
+}
+
gss-tsig { lval.alg = KNOT_TSIG_ALG_GSS_TSIG; return TSIG_ALGO_NAME; }
hmac-md5 { lval.alg = KNOT_TSIG_ALG_HMAC_MD5; return TSIG_ALGO_NAME; }
hmac-sha1 { lval.alg = KNOT_TSIG_ALG_HMAC_SHA1; return TSIG_ALGO_NAME; }
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index 9939540..9d68d90 100644
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -10,6 +10,8 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
#include "libknot/dname.h"
#include "knot/conf/conf.h"
#include "libknotd_la-cf-parse.h" /* Automake generated header. */
@@ -30,7 +32,6 @@ static void conf_start_iface(char* ifname)
this_iface = malloc(sizeof(conf_iface_t));
memset(this_iface, 0, sizeof(conf_iface_t));
this_iface->name = ifname;
- this_iface->address = 0; // No default address (mandatory)
this_iface->port = CONFIG_DEFAULT_PORT;
add_tail(&new_config->ifaces, &this_iface->n);
++new_config->ifaces_count;
@@ -41,12 +42,30 @@ static void conf_start_remote(char *remote)
this_remote = malloc(sizeof(conf_iface_t));
memset(this_remote, 0, sizeof(conf_iface_t));
this_remote->name = remote;
- this_remote->address = 0; // No default address (mandatory)
- this_remote->port = 0; // Port wildcard
add_tail(&new_config->remotes, &this_remote->n);
++new_config->remotes_count;
}
+static void conf_remote_set_via(void *scanner, char *item) {
+ /* Find existing node in remotes. */
+ node* r = 0; conf_iface_t* found = 0;
+ WALK_LIST (r, new_config->ifaces) {
+ if (strcmp(((conf_iface_t*)r)->name, item) == 0) {
+ found = (conf_iface_t*)r;
+ break;
+ }
+ }
+
+ /* Check */
+ if (!found) {
+ char buf[512];
+ snprintf(buf, sizeof(buf), "remote '%s' is not defined", item);
+ cf_error(scanner, buf);
+ } else {
+ this_remote->via = found;
+ }
+}
+
static void conf_acl_item(void *scanner, char *item)
{
/* Find existing node in remotes. */
@@ -148,14 +167,17 @@ static int conf_key_add(void *scanner, knot_key_t **key, char *item)
%token END INVALID_TOKEN
%token <tok> TEXT
+%token <tok> HEXSTR
%token <tok> NUM
%token <tok> INTERVAL
%token <tok> SIZE
%token <tok> BOOL
-%token <tok> SYSTEM IDENTITY VERSION STORAGE KEY KEYS
+%token <tok> SYSTEM IDENTITY VERSION NSID STORAGE KEY KEYS
%token <tok> TSIG_ALGO_NAME
%token <tok> WORKERS
+%token <tok> USER
+%token <tok> PIDFILE
%token <tok> REMOTES
@@ -173,6 +195,7 @@ static int conf_key_add(void *scanner, knot_key_t **key, char *item)
%token <tok> INTERFACES ADDRESS PORT
%token <tok> IPA
%token <tok> IPA6
+%token <tok> VIA
%token <tok> LOG
%token <tok> LOG_DEST
@@ -264,7 +287,10 @@ system:
SYSTEM '{'
| system VERSION TEXT ';' { new_config->version = $3.t; }
| system IDENTITY TEXT ';' { new_config->identity = $3.t; }
+ | system NSID HEXSTR ';' { new_config->nsid = $3.t; new_config->nsid_len = $3.l; }
+ | system NSID TEXT ';' { new_config->nsid = $3.t; new_config->nsid_len = strlen(new_config->nsid); }
| system STORAGE TEXT ';' { new_config->storage = $3.t; }
+ | system PIDFILE TEXT ';' { new_config->pidfile = $3.t; }
| system KEY TSIG_ALGO_NAME TEXT ';' {
fprintf(stderr, "warning: Config option 'system.key' is deprecated "
"and has no effect.\n");
@@ -277,6 +303,30 @@ system:
new_config->workers = $3.i;
}
}
+ | system USER TEXT ';' {
+ char buf[512];
+ new_config->uid = new_config->gid = -1; // Invalidate
+ char* dpos = strchr($3.t, '.'); // Find uid.gid format
+ if (dpos != NULL) {
+ struct group *grp = getgrnam(dpos + 1); // Skip dot
+ if (grp != NULL) {
+ new_config->gid = grp->gr_gid;
+ } else {
+ snprintf(buf, sizeof(buf), "invalid group name '%s'", dpos + 1);
+ cf_error(scanner, buf);
+ }
+ *dpos = '\0'; // Cut off
+ }
+ struct passwd* pwd = getpwnam($3.t);
+ if (pwd != NULL) {
+ new_config->uid = pwd->pw_uid;
+ } else {
+ snprintf(buf, sizeof(buf), "invalid user name '%s'", $3.t);
+ cf_error(scanner, buf);
+ }
+
+ free($3.t);
+ }
;
keys:
@@ -291,7 +341,6 @@ keys:
char *fqdn = $2.t;
size_t fqdnl = strlen(fqdn);
if (fqdn[fqdnl - 1] != '.') {
- /*! \todo Oddly, it requires memory aligned to 4B */
fqdnl = ((fqdnl + 2)/4+1)*4; /* '.', '\0' */
char* tmpdn = malloc(fqdnl);
if (!tmpdn) {
@@ -398,6 +447,14 @@ remote:
}
free($3.t);
}
+ | remote VIA TEXT ';' {
+ if (this_remote->key != 0) {
+ cf_error(scanner, "only one 'via' definition is allowed in remote section\n");
+ } else {
+ conf_remote_set_via(scanner, $3.t);
+ }
+ free($3.t);
+ }
;
remotes:
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index 636901b..a382bba 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -166,7 +166,7 @@ static void zone_free(conf_zone_t *zone)
*
* This function is called automatically after config update.
*
- * \todo Selective hooks.
+ * \todo Selective hooks (issue #1583).
*/
static void conf_update_hooks(conf_t *conf)
{
@@ -201,10 +201,19 @@ static int conf_process(conf_t *conf)
struct stat st;
if (stat(conf->storage, &st) != 0) {
rmkdir(conf->storage, S_IRWXU);
+ if (conf->uid >= 0) {
+ if (chown(conf->storage, conf->uid, conf->gid) < 0) {
+ log_server_warning("Could not change ownership"
+ " of '%s' to uid=%d.\n",
+ conf->storage, conf->uid);
+ }
+ }
}
// Create PID file
- conf->pidfile = strcdup(conf->storage, "/" PID_FILE);
+ if (conf->pidfile == NULL) {
+ conf->pidfile = strcdup(conf->storage, "/" PID_FILE);
+ }
// Postprocess zones
int ret = KNOTD_EOK;
@@ -445,6 +454,8 @@ conf_t *conf_new(const char* path)
c->notify_timeout = CONFIG_NOTIFY_TIMEOUT;
c->dbsync_timeout = CONFIG_DBSYNC_TIMEOUT;
c->ixfr_fslimit = -1;
+ c->uid = -1;
+ c->gid = -1;
return c;
}
@@ -513,7 +524,7 @@ void conf_truncate(conf_t *conf, int unload_hooks)
// Unload hooks
if (unload_hooks) {
WALK_LIST_DELSAFE(n, nxt, conf->hooks) {
- //! \todo call hook unload.
+ /*! \todo Call hook unload (issue #1583) */
free((conf_hook_t*)n);
}
conf->hooks_count = 0;
@@ -573,6 +584,10 @@ void conf_truncate(conf_t *conf, int unload_hooks)
free(conf->pidfile);
conf->pidfile = 0;
}
+ if (conf->nsid) {
+ free(conf->nsid);
+ conf->nsid = 0;
+ }
}
void conf_free(conf_t *conf)
@@ -624,11 +639,9 @@ int conf_open(const char* path)
}
/* Check if exists. */
- FILE *fp = fopen(path, "r");
- if (fp == 0) {
+ struct stat st;
+ if (stat(path, &st) != 0) {
return KNOTD_ENOENT;
- } else {
- fclose(fp);
}
/* Create new config. */
diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h
index ef35e41..b5c1afa 100644
--- a/src/knot/conf/conf.h
+++ b/src/knot/conf/conf.h
@@ -59,6 +59,7 @@ typedef struct conf_iface_t {
int port; /*!< Port number for this interface */
int family; /*!< Address family. */
knot_key_t *key; /*!< TSIG key (only valid for remotes). */
+ struct conf_iface_t *via; /*!< Used for remotes to specify qry endpoint.*/
} conf_iface_t;
/*!
@@ -79,8 +80,6 @@ typedef struct conf_remote_t {
* location on the disk. It also allows to have multiple DNS servers
* as a source for the zone transfer and multiple DNS servers to allow
* zone transfers. Same logic applies for the NOTIFY.
- *
- * \todo Missing XFR type (AXFR/IXFR/IXFR-ONLY) for each server.
*/
typedef struct conf_zone_t {
node n;
@@ -154,7 +153,11 @@ typedef struct conf_t {
char *version; /*!< Version for CH TXT version.{bind|server} */
char *storage; /*!< Persistent storage path for databases and such. */
char *pidfile; /*!< PID file path. */
+ char *nsid; /*!< Server's NSID. */
+ size_t nsid_len;/*!< Server's NSID length. */
int workers; /*!< Number of workers per interface. */
+ int uid; /*!< Specified user id. */
+ int gid; /*!< Specified group id. */
/*
* Log
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index f472303..f111f25 100644
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -36,6 +36,20 @@ enum knotc_constants_t {
WAITPID_TIMEOUT = 10 /*!< \brief Timeout for waiting for process. */
};
+/*! \brief Controller flags. */
+enum knotc_flag_t {
+ F_NULL = 0 << 0,
+ F_FORCE = 1 << 0,
+ F_VERBOSE = 1 << 1,
+ F_WAIT = 1 << 2,
+ F_INTERACTIVE = 1 << 3,
+ F_AUTO = 1 << 4
+};
+
+static inline unsigned has_flag(unsigned flags, enum knotc_flag_t f) {
+ return flags & f;
+}
+
/*! \brief Print help. */
void help(int argc, char **argv)
{
@@ -49,6 +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)."
" -h, --help Print help and usage.\n",
PACKAGE_NAME);
printf("Actions:\n"
@@ -243,16 +258,15 @@ int zctask_add(knotc_zctask_t *tasks, int count, pid_t pid, conf_zone_t *zone)
* \param force True if forced operation is required.
* \param wait Wait for the operation to finish.
* \param interactive Interactive mode.
+ * \param automatic Automatic compilation.
* \param jobs Number of parallel tasks to run.
* \param pidfile Specified PID file for action.
*
* \retval 0 on success.
* \retval error return code for main on error.
- *
- * \todo Make enumerated flags instead of many parameters...
*/
-int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
- int force, int wait, int interactive, int jobs, const char *pidfile)
+int execute(const char *action, char **argv, int argc, pid_t pid,
+ unsigned flags, unsigned jobs, const char *pidfile)
{
int valid_cmd = 0;
int rc = 0;
@@ -270,7 +284,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
fprintf(stderr, "control: Server PID found, "
"already running.\n");
- if (!force) {
+ if (!has_flag(flags, F_FORCE)) {
return 1;
} else {
fprintf(stderr, "control: forcing "
@@ -281,6 +295,12 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
}
}
+ // Recompile zones if needed
+ if (has_flag(flags, F_AUTO)) {
+ rc = execute("compile", argv, argc, -1, flags,
+ jobs, pidfile);
+ }
+
// Lock configuration
conf_read_lock();
@@ -288,10 +308,10 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
const char *cfg = conf()->filename;
const char *args[] = {
PROJECT_EXEC,
- interactive ? "" : "-d",
+ has_flag(flags, F_INTERACTIVE) ? "" : "-d",
cfg ? "-c" : "",
cfg ? cfg : "",
- verbose ? "-v" : "",
+ has_flag(flags, F_VERBOSE) ? "-v" : "",
argc > 0 ? argv[0] : ""
};
@@ -299,7 +319,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
conf_read_unlock();
// Execute command
- if (interactive) {
+ if (has_flag(flags, F_INTERACTIVE)) {
printf("control: Running in interactive mode.\n");
fflush(stderr);
fflush(stdout);
@@ -312,8 +332,8 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
fflush(stdout);
// Wait for finish
- if (wait && !interactive) {
- if (verbose) {
+ if (has_flag(flags, F_WAIT) && !has_flag(flags, F_INTERACTIVE)) {
+ if (has_flag(flags, F_VERBOSE)) {
fprintf(stdout, "control: waiting for server "
"to load.\n");
}
@@ -338,7 +358,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
fprintf(stderr, "Server PID not found, "
"probably not running.\n");
- if (!force) {
+ if (!has_flag(flags, F_FORCE)) {
rc = 1;
} else {
fprintf(stderr, "control: forcing "
@@ -355,8 +375,8 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
}
// Wait for finish
- if (rc == 0 && wait) {
- if (verbose) {
+ if (rc == 0 && has_flag(flags, F_WAIT)) {
+ if (has_flag(flags, F_VERBOSE)) {
fprintf(stdout, "control: waiting for server "
"to stop.\n");
}
@@ -372,8 +392,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
}
if (strcmp(action, "restart") == 0) {
valid_cmd = 1;
- execute("stop", argv, argc, pid, verbose, force, wait,
- interactive, jobs, pidfile);
+ execute("stop", argv, argc, pid, flags, jobs, pidfile);
int i = 0;
while((pid = pid_read(pidfile)) > 0) {
@@ -394,8 +413,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
}
printf("Restarting server.\n");
- rc = execute("start", argv, argc, -1, verbose, force, wait,
- interactive, jobs, pidfile);
+ rc = execute("start", argv, argc, -1, flags, jobs, pidfile);
}
if (strcmp(action, "reload") == 0) {
@@ -405,7 +423,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
fprintf(stderr, "Server PID not found, "
"probably not running.\n");
- if (force) {
+ if (has_flag(flags, F_FORCE)) {
fprintf(stderr, "control: forcing "
"server stop.\n");
} else {
@@ -413,6 +431,12 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
}
}
+ // Recompile zones if needed
+ if (has_flag(flags, F_AUTO)) {
+ rc = execute("compile", argv, argc, -1, flags,
+ jobs, pidfile);
+ }
+
// Stop
if (kill(pid, SIGHUP) < 0) {
pid_remove(pidfile);
@@ -470,7 +494,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
printf("Zone '%s' is up-to-date.\n",
zone->name);
- if (force) {
+ if (has_flag(flags, F_FORCE)) {
fprintf(stderr, "control: forcing "
"zone recompilation.\n");
} else {
@@ -492,7 +516,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
const char *args[] = {
ZONEPARSER_EXEC,
zone->enable_checks ? "-s" : "",
- verbose ? "-v" : "",
+ has_flag(flags, F_VERBOSE) ? "-v" : "",
"-o",
zone->db,
zone->name,
@@ -500,7 +524,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
};
// Execute command
- if (verbose) {
+ if (has_flag(flags, F_VERBOSE)) {
printf("Compiling '%s' as '%s'...\n",
zone->name, zone->db);
}
@@ -527,7 +551,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid, int verbose,
}
// Log
- if (verbose) {
+ if (has_flag(flags, F_VERBOSE)) {
printf("'%s' finished (return code %d)\n", action, rc);
}
return rc;
@@ -537,11 +561,8 @@ int main(int argc, char **argv)
{
// Parse command line arguments
int c = 0, li = 0;
- int force = 0;
- int verbose = 0;
- int wait = 0;
- int interactive = 0;
- int jobs = 1;
+ unsigned jobs = 1;
+ unsigned flags = F_NULL;
const char* config_fn = 0;
/* Long options. */
@@ -551,30 +572,23 @@ int main(int argc, char **argv)
{"config", required_argument, 0, 'c'},
{"verbose", no_argument, 0, 'v'},
{"interactive", no_argument, 0, 'i'},
+ {"auto", no_argument, 0, 'a'},
{"jobs", required_argument, 0, 'c'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
- while ((c = getopt_long(argc, argv, "wfc:vij:Vh", opts, &li)) != -1) {
- switch (c)
- {
- case 'w':
- wait = 1;
- break;
- case 'f':
- force = 1;
- break;
+ while ((c = getopt_long(argc, argv, "wfc:viaj:Vh", opts, &li)) != -1) {
+ switch (c) {
+ case 'w': flags |= F_WAIT; break;
+ case 'f': flags |= F_FORCE; break;
+ case 'v': flags |= F_VERBOSE; break;
+ case 'i': flags |= F_INTERACTIVE; break;
+ case 'a': flags |= F_AUTO; break;
case 'c':
config_fn = optarg;
break;
- case 'v':
- verbose = 1;
- break;
- case 'i':
- interactive = 1;
- break;
case 'j':
jobs = atoi(optarg);
if (jobs < 1) {
@@ -616,9 +630,15 @@ int main(int argc, char **argv)
}
// Open configuration
- if (conf_open(config_fn) != 0) {
- fprintf(stderr, "Failed to parse configuration '%s'.\n",
- config_fn);
+ int conf_ret = conf_open(config_fn);
+ if (conf_ret != KNOTD_EOK) {
+ if (conf_ret == KNOTD_ENOENT) {
+ fprintf(stderr, "Couldn't open configuration file "
+ "'%s'.\n", config_fn);
+ } else {
+ fprintf(stderr, "Failed to parse configuration '%s'.\n",
+ config_fn);
+ }
free(default_fn);
return 1;
}
@@ -627,9 +647,9 @@ int main(int argc, char **argv)
free(default_fn);
// Verbose mode
- if (verbose) {
- int mask = LOG_MASK(LOG_INFO)|LOG_MASK(LOG_DEBUG);
- log_levels_add(LOGT_STDOUT, LOG_ANY, mask);
+ if (has_flag(flags, F_VERBOSE)) {
+ log_levels_add(LOGT_STDOUT, LOG_ANY,
+ LOG_MASK(LOG_INFO)|LOG_MASK(LOG_DEBUG));
}
// Fetch PID
@@ -648,7 +668,7 @@ int main(int argc, char **argv)
// Execute action
int rc = execute(action, argv + optind + 1, argc - optind - 1,
- pid, verbose, force, wait, interactive, jobs, pidfile);
+ pid, flags, jobs, pidfile);
// Finish
free(pidfile);
diff --git a/src/knot/main.c b/src/knot/main.c
index d4e10b9..d4c6bca 100644
--- a/src/knot/main.c
+++ b/src/knot/main.c
@@ -19,15 +19,18 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
-#include "common.h"
+#ifdef HAVE_CAP_NG_H
+#include <cap-ng.h>
+#endif /* HAVE_CAP_NG_H */
+#include "common.h"
+#include "common/evqueue.h"
#include "knot/common.h"
#include "knot/other/error.h"
#include "knot/server/server.h"
#include "knot/ctl/process.h"
#include "knot/conf/conf.h"
#include "knot/conf/logconf.h"
-#include "common/evqueue.h"
#include "knot/server/zones.h"
/*----------------------------------------------------------------------------*/
@@ -127,6 +130,7 @@ int main(int argc, char **argv)
sigemptyset(&emptyset.sa_mask);
emptyset.sa_flags = 0;
sigaction(SIGALRM, &emptyset, NULL); // Interrupt
+ sigaction(SIGPIPE, &emptyset, NULL); // Mask
// Setup event queue
evqueue_set(evqueue_new());
@@ -149,8 +153,8 @@ int main(int argc, char **argv)
// Initialize configuration
conf_read_lock();
conf_add_hook(conf(), CONF_LOG, log_conf_hook, 0);
- conf_add_hook(conf(), CONF_LOG, zones_ns_conf_hook, server->nameserver);
- conf_add_hook(conf(), CONF_LOG, server_conf_hook, server);
+ conf_add_hook(conf(), CONF_ALL, server_conf_hook, server);
+ conf_add_hook(conf(), CONF_ALL, zones_ns_conf_hook, server->nameserver);
conf_read_unlock();
// Find implicit configuration file
@@ -181,13 +185,55 @@ int main(int argc, char **argv)
free(cwbuf);
config_fn = abs_cfg;
}
+
+ /* POSIX 1003.1e capabilities. */
+#ifdef HAVE_CAP_NG_H
+
+ /* Drop all capabilities. */
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+ capng_clear(CAPNG_SELECT_BOTH);
+
+
+ /* Retain ability to set capabilities and FS access. */
+ capng_type_t tp = CAPNG_EFFECTIVE|CAPNG_PERMITTED;
+ capng_update(CAPNG_ADD, tp, CAP_SETPCAP);
+ capng_update(CAPNG_ADD, tp, CAP_DAC_OVERRIDE);
+ capng_update(CAPNG_ADD, tp, CAP_CHOWN); /* Storage ownership. */
+
+ /* Allow binding to privileged ports.
+ * (Not inheritable)
+ */
+ capng_update(CAPNG_ADD, tp, CAP_NET_BIND_SERVICE);
+
+ /* Allow setuid/setgid. */
+ capng_update(CAPNG_ADD, tp, CAP_SETUID);
+ capng_update(CAPNG_ADD, tp, CAP_SETGID);
+
+ /* Allow priorities changing. */
+ capng_update(CAPNG_ADD, tp, CAP_SYS_NICE);
+
+ /* Apply */
+ if (capng_apply(CAPNG_SELECT_BOTH) < 0) {
+ log_server_error("Couldn't set process capabilities - "
+ "%s.\n", strerror(errno));
+ }
+ } else {
+ log_server_info("User uid=%d is not allowed to set "
+ "capabilities, skipping.\n", getuid());
+ }
+#endif /* HAVE_CAP_NG_H */
// Open configuration
- log_server_info("Parsing configuration '%s' ...\n", config_fn);
- if (conf_open(config_fn) != KNOTD_EOK) {
-
- log_server_error("Failed to parse configuration file '%s'.\n",
- config_fn);
+ log_server_info("Reading configuration '%s' ...\n", config_fn);
+ int conf_ret = conf_open(config_fn);
+ if (conf_ret != KNOTD_EOK) {
+ if (conf_ret == KNOTD_ENOENT) {
+ log_server_error("Couldn't open configuration file "
+ "'%s'.\n", config_fn);
+ } else {
+ log_server_error("Failed to parse configuration '%s'.\n",
+ config_fn);
+ }
server_destroy(&server);
free(config_fn);
return 1;
@@ -241,6 +287,7 @@ int main(int argc, char **argv)
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
sa.sa_flags = 0;
pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL);
@@ -251,10 +298,6 @@ int main(int argc, char **argv)
pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL);
/* Interrupts. */
- /*! \todo More robust way to exit evloop.
- * Event loop should exit with a special
- * event.
- */
if (sig_req_stop) {
sig_req_stop = 0;
server_stop(server);
diff --git a/src/knot/other/debug.h b/src/knot/other/debug.h
index 8b01c85..93b52fe 100644
--- a/src/knot/other/debug.h
+++ b/src/knot/other/debug.h
@@ -32,12 +32,12 @@
#include "knot/other/log.h"
#include "common/print.h"
-/*! \todo Set these during configure as well. */
+/*! \todo Set these during configure as well (issue #1585). */
//#define KNOTD_SERVER_DEBUG
//#define KNOTD_THREADS_DEBUG
//#define KNOTD_JOURNAL_DEBUG
//#define KNOTD_NET_DEBUG
-#define KNOTD_ZONES_DEBUG
+//#define KNOTD_ZONES_DEBUG
//#define KNOTD_XFR_DEBUG
//#define KNOTD_NOTIFY_DEBUG
//#define KNOTD_ZDUMP_DEBUG
diff --git a/src/knot/other/log.c b/src/knot/other/log.c
index 00bcea3..488763d 100644
--- a/src/knot/other/log.c
+++ b/src/knot/other/log.c
@@ -96,7 +96,6 @@ int log_init()
log_levels_set(LOGT_STDERR, LOG_ANY, emask);
log_levels_set(LOGT_STDOUT, LOG_ANY, imask);
- /// \todo May change to LOG_DAEMON.
setlogmask(LOG_UPTO(LOG_DEBUG));
openlog(PACKAGE_NAME, LOG_PID, LOG_DAEMON);
return ret;
diff --git a/src/knot/server/dthreads.c b/src/knot/server/dthreads.c
index 9d1e69d..be6fc24 100644
--- a/src/knot/server/dthreads.c
+++ b/src/knot/server/dthreads.c
@@ -21,6 +21,9 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
+#ifdef HAVE_CAP_NG_H
+#include <cap-ng.h>
+#endif /* HAVE_CAP_NG_H */
#include "knot/common.h"
#include "knot/server/dthreads.h"
@@ -120,9 +123,20 @@ static void *thread_ep(void *data)
sigaddset(&ignset, SIGINT);
sigaddset(&ignset, SIGTERM);
sigaddset(&ignset, SIGHUP);
- pthread_sigmask(SIG_BLOCK, &ignset, 0); /*! \todo Review under BSD. */
+ sigaddset(&ignset, SIGPIPE);
+ pthread_sigmask(SIG_BLOCK, &ignset, 0); /*! \todo Review under BSD (issue #1441). */
dbg_dt("dthreads: [%p] entered ep\n", thread);
+
+ /* Drop capabilities except FS access. */
+#ifdef HAVE_CAP_NG_H
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+ capng_type_t tp = CAPNG_EFFECTIVE|CAPNG_PERMITTED;
+ capng_clear(CAPNG_SELECT_BOTH);
+ capng_update(CAPNG_ADD, tp, CAP_DAC_OVERRIDE);
+ capng_apply(CAPNG_SELECT_BOTH);
+ }
+#endif /* HAVE_CAP_NG_H */
// Run loop
for (;;) {
@@ -176,7 +190,6 @@ static void *thread_ep(void *data)
// Wait for notification from unit
dbg_dt("dthreads: [%p] going idle\n", thread);
- /*! \todo Check return value. */
pthread_cond_wait(&unit->_notify, &unit->_notify_mx);
pthread_mutex_unlock(&unit->_notify_mx);
dbg_dt("dthreads: [%p] resumed from idle\n", thread);
@@ -961,7 +974,7 @@ int dt_optimal_size()
}
/*!
- * \todo Use memory barriers or asynchronous read-only access, locking
+ * \note Use memory barriers or asynchronous read-only access, locking
* poses a thread performance decrease by 1.31%.
*/
diff --git a/src/knot/server/journal.c b/src/knot/server/journal.c
index 438332a..cd3e342 100644
--- a/src/knot/server/journal.c
+++ b/src/knot/server/journal.c
@@ -221,7 +221,7 @@ int journal_create(const char *fn, uint16_t max_nodes)
journal_t* journal_open(const char *fn, size_t fslimit, uint16_t bflags)
{
- /*! \todo Memory mapping may be faster than stdio? */
+ /*! \todo Memory mapping may be faster than stdio? (issue #964) */
/* File lock. */
struct flock fl;
@@ -590,7 +590,7 @@ int journal_write(journal_t *journal, uint64_t id, const char *src, size_t size)
return KNOTD_ERROR;
}
- /*! \todo Delayed write-back? */
+ /*! \todo Delayed write-back? (issue #964) */
dbg_journal_verb("journal: write of finished, nqueue=<%u, %u>\n",
journal->qhead, journal->qtail);
diff --git a/src/knot/server/journal.h b/src/knot/server/journal.h
index 321b591..564f0fe 100644
--- a/src/knot/server/journal.h
+++ b/src/knot/server/journal.h
@@ -77,7 +77,7 @@ typedef struct journal_node_t
* Each journal has a fixed number of nodes.
*
* \todo Organize nodes in an advanced structure, like
- * btree or hash table to improve lookup time.
+ * btree or hash table to improve lookup time (issue #964).
*/
typedef struct journal_t
{
diff --git a/src/knot/server/notify.h b/src/knot/server/notify.h
index c1bebb8..a9ba807 100644
--- a/src/knot/server/notify.h
+++ b/src/knot/server/notify.h
@@ -47,6 +47,7 @@ typedef struct notify_ev_t {
int retries; /*!< Number of retries. */
int msgid; /*!< ID of pending NOTIFY. */
sockaddr_t addr; /*!< Slave server address. */
+ sockaddr_t saddr; /*!< Transit interface address. */
struct event_t *timer; /*!< Event timer. */
knot_zone_t *zone; /*!< Associated zone. */
} notify_ev_t;
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index 6b61d61..5e7b6e0 100644
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <openssl/evp.h>
#include <assert.h>
+#include <grp.h>
#include "knot/common.h"
#include "knot/other/error.h"
@@ -152,12 +153,15 @@ 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];
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &snd_opt, sizeof(snd_opt)) < 0) {
- // log_server_warning("Failed to configure socket "
- // "write buffers.\n");
+ strerror_r(errno, ebuf, sizeof(ebuf));
+ log_server_warning("Failed to configure socket "
+ "write buffers: %s.\n", ebuf);
}
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
- // log_server_warning("Failed to configure socket read buffers.\n");
+ strerror_r(errno, ebuf, sizeof(ebuf));
+ log_server_warning("Failed to configure socket read buffers: %s.\n", ebuf);
}
/* Create TCP socket. */
@@ -207,7 +211,9 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
*/
static int server_bind_sockets(server_t *server)
{
- /*! \todo This requires locking to disable parallel updates. */
+ /*! \todo This requires locking to disable parallel updates (issue #278).
+ * However, this is only used when RCU is read-locked, so count with that.
+ */
/* Lock configuration. */
conf_read_lock();
@@ -455,7 +461,9 @@ iohandler_t *server_create_handler(server_t *server, int fd, dt_unit_t *unit)
}
}
- /*! \todo This requires either RCU compatible ptr swap or locking. */
+ /*! \todo This requires locking to disable parallel updates (issue #278).
+ * However, this is only used when RCU is read-locked, so count with that.
+ */
/* Lock RCU. */
rcu_read_lock();
@@ -479,7 +487,9 @@ int server_remove_handler(server_t *server, iohandler_t *h)
/* Lock RCU. */
rcu_read_lock();
- /*! \todo This requires either RCU compatible ptr swap or locking. */
+ /*! \todo This requires locking to disable parallel updates (issue #278).
+ * However, this is only used when RCU is read-locked, so count with that.
+ */
// Remove node
rem_node((node*)h);
@@ -687,24 +697,61 @@ int server_conf_hook(const struct conf_t *conf, void *data)
if ((ret = server_bind_sockets(server)) < 0) {
log_server_error("Failed to bind configured "
"interfaces.\n");
- return KNOTD_ERROR;
+ } else {
+ /* Update handlers. */
+ if ((ret = server_bind_handlers(server)) < 0) {
+ log_server_error("Failed to create handlers for "
+ "configured interfaces.\n");
+ }
+ }
+
+ /* Lock configuration. */
+ conf_read_lock();
+ int priv_failed = 0;
+
+#ifdef HAVE_SETGROUPS
+ /* Drop supplementary groups. */
+ if (conf->gid > -1 || conf->uid > -1) {
+ ret = setgroups(0, NULL);
+
+ /* Collect results. */
+ if (ret < 0) {
+ log_server_error("Failed to set supplementary groups "
+ "for uid=%d %s\n",
+ getuid(), strerror(errno));
+ priv_failed = 1;
+ }
+ }
+#endif
+
+ /* Watch uid/gid. */
+ if (conf->gid > -1 && conf->gid != getgid()) {
+ log_server_info("Changing group id to %d.\n", conf->gid);
+ if (setregid(conf->gid, conf->gid) < 0) {
+ log_server_error("Failed to change gid to %d.\n",
+ conf->gid);
+ priv_failed = 1;
+ }
+ }
+ if (conf->uid > -1 && conf->uid != getuid()) {
+ log_server_info("Changing user id to %d.\n", conf->uid);
+ if (setreuid(conf->uid, conf->uid) < 0) {
+ log_server_error("Failed to change uid to %d.\n",
+ conf->uid);
+ priv_failed = 1;
+ }
}
- /* Update handlers. */
- if ((ret = server_bind_handlers(server)) < 0) {
- log_server_error("Failed to create handlers for "
- "configured interfaces.\n");
- return ret;
+ if (priv_failed) {
+ ret = KNOTD_EACCES;
}
/* Exit if the server is not running. */
- if (!(server->state & ServerRunning)) {
+ if (ret != KNOTD_EOK || !(server->state & ServerRunning)) {
+ conf_read_unlock();
return KNOTD_ENOTRUNNING;
}
- /* Lock configuration. */
- conf_read_lock();
-
/* Start new handlers. */
iohandler_t *h = 0;
WALK_LIST(h, server->handlers) {
diff --git a/src/knot/server/server.h b/src/knot/server/server.h
index 480219b..b1358cd 100644
--- a/src/knot/server/server.h
+++ b/src/knot/server/server.h
@@ -165,8 +165,6 @@ int server_remove_handler(server_t *server, iohandler_t *ref);
* \retval KNOTD_EOK on success.
* \retval KNOTD_EINVAL on invalid parameters.
*
- * \todo When a module for configuration is added, the filename parameter will
- * be removed.
*/
int server_start(server_t *server);
diff --git a/src/knot/server/socket.c b/src/knot/server/socket.c
index 67f4a5f..4deb862 100644
--- a/src/knot/server/socket.c
+++ b/src/knot/server/socket.c
@@ -22,7 +22,11 @@
#include <errno.h>
#include <stdio.h>
#include <netdb.h>
+#include <time.h>
#include <sys/socket.h>
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
diff --git a/src/knot/server/socket.h b/src/knot/server/socket.h
index dff5216..2185f03 100644
--- a/src/knot/server/socket.h
+++ b/src/knot/server/socket.h
@@ -39,7 +39,7 @@
/*! \brief Socket-related constants. */
typedef enum {
- SOCKET_MTU_SZ = 8192, /*!< \todo Determine UDP MTU size. */
+ SOCKET_MTU_SZ = 65535, /*!< Maximum MTU size. */
} socket_const_t;
/*!
diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index 71452e9..0af85a9 100644
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -24,6 +24,9 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#ifdef HAVE_CAP_NG_H
+#include <cap-ng.h>
+#endif /* HAVE_CAP_NG_H */
#include "common/sockaddr.h"
#include "common/skip-list.h"
@@ -35,8 +38,21 @@
#include "knot/server/zones.h"
#include "libknot/nameserver/name-server.h"
#include "knot/other/error.h"
+#include "libknot/util/error.h"
#include "libknot/util/wire.h"
+/* Workarounds for clock_gettime() not available on some platforms. */
+#ifdef HAVE_CLOCK_GETTIME
+#define time_now(x) clock_gettime(CLOCK_MONOTONIC, (x))
+typedef struct timespec timev_t;
+#elif HAVE_GETTIMEOFDAY
+#define time_now(x) gettimeofday((x), NULL)
+typedef struct timeval timev_t;
+#else
+#error Neither clock_gettime() nor gettimeofday() found. At least one is required.
+#endif
+
+
/* Defines */
#define TCP_BUFFER_SIZE 65535 /*! Do not change, as it is used for maximum DNS/TCP packet size. */
@@ -63,7 +79,60 @@ static inline int tcp_throttle() {
static int xfr_send_cb(int session, sockaddr_t *addr, uint8_t *msg, size_t msglen)
{
UNUSED(addr);
- return tcp_send(session, msg, msglen);
+ int ret = tcp_send(session, msg, msglen);
+ if (ret < 0) {
+ return KNOT_ECONN;
+ }
+
+ return ret;
+}
+
+/*! \brief Send reply. */
+static int tcp_reply(int fd, uint8_t *qbuf, size_t resp_len)
+{
+ dbg_net("tcp: got answer of size %zd.\n",
+ resp_len);
+
+ int res = 0;
+ if (resp_len > 0) {
+ res = tcp_send(fd, qbuf, resp_len);
+ }
+
+ /* Check result. */
+ if (res < 0 || (size_t)res != resp_len) {
+ dbg_net("tcp: %s: failed: %d - %d.\n",
+ "socket_send()",
+ res, errno);
+ }
+
+ return res;
+}
+
+/*! \brief Sweep TCP connection. */
+static void tcp_sweep(fdset_t *set, int fd) {
+ char r_addr[SOCKADDR_STRLEN] = { '\0' };
+ int r_port = 0;
+ struct sockaddr_storage addr;
+ socklen_t len = sizeof(addr);
+ getpeername(fd, (struct sockaddr*)&addr, &len);
+
+ /* Translate */
+ if (addr.ss_family == AF_INET) {
+ struct sockaddr_in *s = (struct sockaddr_in *)&addr;
+ r_port = ntohs(s->sin_port);
+ inet_ntop(AF_INET, &s->sin_addr, r_addr, sizeof(r_addr));
+ } else {
+#ifndef DISABLE_IPV6
+ struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
+ r_port = ntohs(s->sin6_port);
+ inet_ntop(AF_INET6, &s->sin6_addr, r_addr, sizeof(r_addr));
+#endif
+ }
+
+ log_server_notice("Connection with %s:%d was terminated due to "
+ "inactivity.\n", r_addr, r_port);
+ fdset_remove(set, fd);
+ close(fd);
}
/*!
@@ -74,18 +143,17 @@ static int xfr_send_cb(int session, sockaddr_t *addr, uint8_t *msg, size_t msgle
* \param w Associated I/O event.
* \param revents Returned events.
*/
-static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen)
+static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen)
{
if (fd < 0 || !w || !w->ioh) {
dbg_net("tcp: tcp_handle(%p, %d) - invalid parameters\n", w, fd);
- return;
+ return KNOTD_EINVAL;
}
dbg_net("tcp: handling TCP event on fd=%d in thread %p.\n",
fd, (void*)pthread_self());
knot_nameserver_t *ns = w->ioh->server->nameserver;
- xfrhandler_t *xfr_h = w->ioh->server->xfr_h;
/* Check address type. */
sockaddr_t addr;
@@ -93,7 +161,7 @@ static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxle
log_server_error("Socket type %d is not supported, "
"IPv6 support is probably disabled.\n",
w->ioh->type);
- return;
+ return KNOTD_ECONNREFUSED;
}
/* Receive data. */
@@ -102,7 +170,15 @@ static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxle
dbg_net("tcp: client on fd=%d disconnected\n", fd);
fdset_remove(w->fdset, fd);
close(fd);
- return;
+ if (n == KNOTD_EAGAIN) {
+ char r_addr[SOCKADDR_STRLEN];
+ sockaddr_tostr(&addr, r_addr, sizeof(r_addr));
+ int r_port = sockaddr_portnum(&addr);
+ log_server_warning("Couldn't receive query from %s:%d "
+ "within the time limit %ds.\n",
+ r_addr, r_port, TCP_ACTIVITY_WD);
+ }
+ return KNOTD_ECONNREFUSED;
}
/* Parse query. */
@@ -117,26 +193,25 @@ static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxle
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);
- return;
+ qbuf, &resp_len);
+ tcp_reply(fd, qbuf, resp_len);
+ return KNOTD_EOK;
}
int res = knot_ns_parse_packet(qbuf, n, packet, &qtype);
- if (unlikely(res != KNOTD_EOK)) {
-
- /* Send error response on dnslib RCODE. */
- if (res > 0) {
+ if (unlikely(res != KNOT_EOK)) {
+ 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);
+ qbuf, &resp_len);
+ tcp_reply(fd, qbuf, resp_len);
}
-
-// knot_response_free(&resp);
knot_packet_free(&packet);
- return;
+ return KNOTD_EOK;
}
/* Handle query. */
+ int xfrt = -1;
knot_ns_xfr_t xfr;
res = KNOTD_ERROR;
switch(qtype) {
@@ -146,23 +221,16 @@ static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxle
//res = knot_ns_answer_normal(ns, packet, qbuf, &resp_len);
res = zones_normal_query_answer(ns, packet, &addr, qbuf, &resp_len);
break;
+ case KNOT_QUERY_AXFR:
case KNOT_QUERY_IXFR:
- res = xfr_request_init(&xfr, XFR_TYPE_IOUT, XFR_FLAG_TCP, packet);
- if (res != KNOTD_EOK) {
- knot_ns_error_response(ns, knot_packet_id(packet),
- KNOT_RCODE_SERVFAIL, qbuf,
- &resp_len);
- res = KNOTD_EOK;
- break;
+ if (qtype == KNOT_QUERY_IXFR) {
+ xfrt = XFR_TYPE_IOUT;
+ } else {
+ xfrt = XFR_TYPE_AOUT;
}
- xfr.send = xfr_send_cb;
- xfr.session = fd;
- memcpy(&xfr.addr, &addr, sizeof(sockaddr_t));
- xfr_request(xfr_h, &xfr);
- dbg_net("tcp: enqueued IXFR query on fd=%d\n", fd);
- return;
- case KNOT_QUERY_AXFR:
- res = xfr_request_init(&xfr, XFR_TYPE_AOUT, XFR_FLAG_TCP, packet);
+
+ /* Prepare context. */
+ res = xfr_request_init(&xfr, xfrt, XFR_FLAG_TCP, packet);
if (res != KNOTD_EOK) {
knot_ns_error_response(ns, knot_packet_id(packet),
KNOT_RCODE_SERVFAIL, qbuf,
@@ -172,12 +240,13 @@ static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxle
}
xfr.send = xfr_send_cb;
xfr.session = fd;
+ xfr.wire = qbuf;
+ xfr.wire_size = qbuf_maxlen;
memcpy(&xfr.addr, &addr, sizeof(sockaddr_t));
- xfr_request(xfr_h, &xfr);
- dbg_net("tcp: enqueued AXFR query on fd=%d\n", fd);
- return;
- /*! \todo Implement query notify/update. */
+ /* Answer. */
+ return xfr_answer(ns, &xfr);
+
case KNOT_QUERY_UPDATE:
knot_ns_error_response(ns, knot_packet_id(packet),
KNOT_RCODE_NOTIMPL, qbuf,
@@ -185,8 +254,12 @@ static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxle
res = KNOTD_EOK;
break;
+ case KNOT_QUERY_NOTIFY:
+ res = notify_process_request(ns, packet, &addr,
+ qbuf, &resp_len);
+ break;
+
/* Unhandled opcodes. */
- case KNOT_QUERY_NOTIFY: /*!< Only in UDP. */
case KNOT_RESPONSE_NOTIFY: /*!< Only in UDP. */
case KNOT_RESPONSE_NORMAL: /*!< TCP handler doesn't send queries. */
case KNOT_RESPONSE_AXFR: /*!< Processed in XFR handler. */
@@ -210,25 +283,13 @@ static void tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxle
/* Send answer. */
if (res == KNOTD_EOK) {
-
- dbg_net("tcp: got answer of size %zd.\n",
- resp_len);
-
- assert(resp_len > 0);
- res = tcp_send(fd, qbuf, resp_len);
-
- /* Check result. */
- if (res != (int)resp_len) {
- dbg_net("tcp: %s: failed: %d - %d.\n",
- "socket_send()",
- res, errno);
- }
+ tcp_reply(fd, qbuf, resp_len);
} else {
dbg_net("tcp: failed to respond to query type=%d on fd=%d - %s\n",
qtype, fd, knotd_strerror(res));;
}
- return;
+ return KNOTD_EOK;
}
static int tcp_accept(int fd)
@@ -239,6 +300,7 @@ static int tcp_accept(int fd)
/* Evaluate connection. */
if (incoming < 0) {
int en = errno;
+ /*! \todo Better solution so it doesn't block current connections (issue #1542). */
if (en != EINTR) {
log_server_error("Cannot accept connection "
"(%d).\n", errno);
@@ -256,6 +318,13 @@ static int tcp_accept(int fd)
}
} else {
dbg_net("tcp: accepted connection fd=%d\n", incoming);
+ /* Set recv() timeout. */
+#ifdef SO_RCVTIMEO
+ struct timeval tv;
+ tv.tv_sec = TCP_ACTIVITY_WD;
+ tv.tv_usec = 0;
+ setsockopt(incoming, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+#endif
}
return incoming;
@@ -347,7 +416,11 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr)
unsigned short pktsize = 0;
int n = recv(fd, &pktsize, sizeof(unsigned short), MSG_WAITALL);
if (n < 0) {
- return KNOTD_ERROR;
+ if (errno == EAGAIN) {
+ return KNOTD_EAGAIN;
+ } else {
+ return KNOTD_ERROR;
+ }
}
pktsize = ntohs(pktsize);
@@ -364,16 +437,22 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr)
if (len < pktsize) {
return KNOTD_ENOMEM;
}
-
- /* Receive payload. */
- n = recv(fd, buf, pktsize, MSG_WAITALL);
-
+
/* Get peer name. */
if (addr) {
socklen_t alen = addr->len;
getpeername(fd, addr->ptr, &alen);
}
+ /* Receive payload. */
+ n = recv(fd, buf, pktsize, MSG_WAITALL);
+ if (n < 0) {
+ if (errno == EAGAIN) {
+ return KNOTD_EAGAIN;
+ } else {
+ return KNOTD_ERROR;
+ }
+ }
dbg_net("tcp: received packet size=%d on fd=%d\n",
n, fd);
@@ -438,6 +517,19 @@ int tcp_loop_worker(dthread_t *thread)
dbg_net("tcp: failed to allocate buffers for TCP worker\n");
return KNOTD_EINVAL;
}
+
+ /* Drop all capabilities on workers. */
+#ifdef HAVE_CAP_NG_H
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+ capng_clear(CAPNG_SELECT_BOTH);
+ capng_apply(CAPNG_SELECT_BOTH);
+ }
+#endif /* HAVE_CAP_NG_H */
+
+ /* Next sweep time. */
+ timev_t next_sweep;
+ time_now(&next_sweep);
+ next_sweep.tv_sec += TCP_SWEEP_INTERVAL;
/* Accept clients. */
dbg_net_verb("tcp: worker %p started\n", w);
@@ -449,8 +541,8 @@ int tcp_loop_worker(dthread_t *thread)
}
/* Wait for events. */
- int nfds = fdset_wait(w->fdset);
- if (nfds <= 0) {
+ int nfds = fdset_wait(w->fdset, (TCP_SWEEP_INTERVAL * 1000)/2);
+ if (nfds < 0) {
continue;
}
@@ -459,7 +551,7 @@ int tcp_loop_worker(dthread_t *thread)
w, nfds);
fdset_it_t it;
fdset_begin(w->fdset, &it);
- while(1) {
+ while(nfds > 0) {
/* Handle incoming clients. */
if (it.fd == w->pipe[0]) {
@@ -472,9 +564,22 @@ int tcp_loop_worker(dthread_t *thread)
"client %d\n",
w, client);
fdset_add(w->fdset, client, OS_EV_READ);
+ fdset_set_watchdog(w->fdset, client,
+ TCP_HANDSHAKE_WD);
+ dbg_net("tcp: watchdog for fd=%d set to %ds\n",
+ client, TCP_HANDSHAKE_WD);
} else {
/* Handle other events. */
- tcp_handle(w, it.fd, qbuf, TCP_BUFFER_SIZE);
+ int ret = tcp_handle(w, it.fd, qbuf,
+ TCP_BUFFER_SIZE);
+ if (ret == KNOTD_EOK) {
+ fdset_set_watchdog(w->fdset, it.fd,
+ TCP_ACTIVITY_WD);
+ dbg_net("tcp: watchdog for fd=%d "
+ "set to %ds\n",
+ it.fd, TCP_ACTIVITY_WD);
+ }
+
}
/* Check if next exists. */
@@ -483,6 +588,15 @@ int tcp_loop_worker(dthread_t *thread)
}
}
+ /* Sweep inactive. */
+ timev_t now;
+ if (time_now(&now) == 0) {
+ if (now.tv_sec >= next_sweep.tv_sec) {
+ fdset_sweep(w->fdset, &tcp_sweep);
+ memcpy(&next_sweep, &now, sizeof(next_sweep));
+ next_sweep.tv_sec += TCP_SWEEP_INTERVAL;
+ }
+ }
}
/* Stop whole unit. */
diff --git a/src/knot/server/tcp-handler.h b/src/knot/server/tcp-handler.h
index f5fd17a..ab6baab 100644
--- a/src/knot/server/tcp-handler.h
+++ b/src/knot/server/tcp-handler.h
@@ -24,8 +24,6 @@
* the worker threads ("buckets"). Each threads processes it's own
* set of sockets, and eliminates mutual exclusion problem by doing so.
*
- * \todo Improve documentation of TCP pool API and use proper error codes.
- *
* \addtogroup server
* @{
*/
@@ -39,6 +37,11 @@
#include "knot/server/server.h"
#include "knot/server/dthreads.h"
+/* Constants */
+#define TCP_HANDSHAKE_WD 10 /* [secs] for connection to make a request.*/
+#define TCP_ACTIVITY_WD 60 /* [secs] of allowed inactivity between requests */
+#define TCP_SWEEP_INTERVAL 2 /* [secs] granularity of connection sweeping */
+
/*!
* \brief Send TCP message.
*
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index b202669..60b0843 100644
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -31,6 +31,9 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
+#ifdef HAVE_CAP_NG_H
+#include <cap-ng.h>
+#endif /* HAVE_CAP_NG_H */
#include "common/sockaddr.h"
#include "knot/common.h"
@@ -46,8 +49,12 @@
#include "knot/server/notify.h"
/* Check for sendmmsg syscall. */
-#ifdef SYS_sendmmsg
-#define ENABLE_SENDMMSG 1
+#ifdef HAVE_SENDMMSG
+ #define ENABLE_SENDMMSG 1
+#else
+ #ifdef SYS_sendmmsg
+ #define ENABLE_SENDMMSG 1
+ #endif
#endif
/*! \brief Pointer to selected UDP master implementation. */
@@ -62,7 +69,12 @@ static int (*_udp_master)(dthread_t *, stat_t *) = 0;
int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
sockaddr_t* addr, knot_nameserver_t *ns)
{
- dbg_net("udp: fd=%d received %zd bytes.\n", fd, qbuflen);
+#ifdef DEBUG_ENABLE_BRIEF
+ char strfrom[SOCKADDR_STRLEN];
+ sockaddr_tostr(addr, strfrom, sizeof(strfrom));
+ dbg_net("udp: fd=%d received %zd bytes from %s:%d.\n", fd, qbuflen,
+ strfrom, sockaddr_portnum(addr));
+#endif
knot_packet_type_t qtype = KNOT_QUERY_NORMAL;
*resp_len = SOCKET_MTU_SZ;
@@ -81,11 +93,10 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
int res = knot_ns_parse_packet(qbuf, qbuflen, packet, &qtype);
if (unlikely(res != KNOTD_EOK)) {
dbg_net("udp: failed to parse packet on fd=%d\n", fd);
- /* Send error response on dnslib RCODE. */
- if (res > 0) {
+ 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);
+ qbuf, resp_len);
}
knot_packet_free(&packet);
@@ -119,29 +130,12 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
/* RFC1034, p.28 requires reliable transfer protocol.
* Bind responds with FORMERR.
*/
- /*! \todo Draft exists for AXFR/UDP, but has not been standardized. */
+ /*! \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);
res = KNOTD_EOK;
break;
-
-// /* Process AXFR over UDP. */
-// res = xfr_request_init(&xfr, XFR_TYPE_AOUT, XFR_FLAG_UDP, packet);
-// if (res != KNOTD_EOK) {
-// knot_ns_error_response(ns, knot_packet_id(packet),
-// KNOT_RCODE_SERVFAIL, qbuf,
-// resp_len);
-// res = KNOTD_EOK;
-// break;
-// }
-// xfr.send = xfr_send_udp;
-// xfr.session = dup(fd);
-// memcpy(&xfr.addr, addr, sizeof(sockaddr_t));
-// xfr_request(srv->xfr_h, &xfr);
-// dbg_net("udp: enqueued AXFR query on fd=%d\n", xfr.session);
-// *resp_len = 0;
-// return KNOTD_EOK;
case KNOT_QUERY_IXFR:
/* According to RFC1035, respond with SOA.
* Draft proposes trying to fit response into one packet,
@@ -154,28 +148,11 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
// res = knot_ns_answer_normal(ns, packet, qbuf,
// resp_len);
break;
-// /* Process IXFR over UDP. */
-// res = xfr_request_init(&xfr, XFR_TYPE_IOUT, XFR_FLAG_UDP, packet);
-// if (res != KNOTD_EOK) {
-// knot_ns_error_response(ns, knot_packet_id(packet),
-// KNOT_RCODE_SERVFAIL, qbuf,
-// resp_len);
-// res = KNOTD_EOK;
-// break;
-// }
-// xfr.send = xfr_send_udp;
-// xfr.session = dup(fd);
-// memcpy(&xfr.addr, addr, sizeof(sockaddr_t));
-// xfr_request(srv->xfr_h, &xfr);
-// dbg_net("udp: enqueued IXFR query on fd=%d\n", xfr.session);
-// *resp_len = 0;
-// return KNOTD_EOK;
case KNOT_QUERY_NOTIFY:
res = notify_process_request(ns, packet, addr,
qbuf, resp_len);
break;
- /*! \todo Implement query notify/update. */
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),
@@ -227,23 +204,13 @@ static inline int udp_master_recvfrom(dthread_t *thread, stat_t *thread_stat)
int sock = dup(h->fd);
uint8_t qbuf[SOCKET_MTU_SZ];
- struct msghdr msg;
- memset(&msg, 0, sizeof(struct msghdr));
- struct iovec iov;
- memset(&iov, 0, sizeof(struct iovec));
- iov.iov_base = qbuf;
- iov.iov_len = SOCKET_MTU_SZ;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_name = addr.ptr;
- msg.msg_namelen = addr.len;
/* Loop until all data is read. */
ssize_t n = 0;
while (n >= 0) {
/* Receive packet. */
- n = recvmsg(sock, &msg, 0);
+ n = recvfrom(sock, qbuf, SOCKET_MTU_SZ, 0, addr.ptr, &addr.len);
/* Cancellation point. */
if (dt_is_cancelled(thread)) {
@@ -331,11 +298,13 @@ int udp_sendto(int sock, sockaddr_t * addrs, struct mmsghdr *msgs, size_t count)
#ifdef ENABLE_SENDMMSG
/*! \brief sendmmsg() syscall interface. */
+#ifndef HAVE_SENDMMSG
static inline int sendmmsg(int fd, struct mmsghdr *mmsg, unsigned vlen,
unsigned flags)
{
return syscall(SYS_sendmmsg, fd, mmsg, vlen, flags, NULL);
}
+#endif
/*!
* \brief Send multiple packets.
@@ -509,6 +478,15 @@ int udp_master(dthread_t *thread)
stat_t *thread_stat = 0;
STAT_INIT(thread_stat); //XXX new stat instance every time.
stat_set_protocol(thread_stat, stat_UDP);
+
+ /* Drop all capabilities on workers. */
+#ifdef HAVE_CAP_NG_H
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+ capng_clear(CAPNG_SELECT_BOTH);
+ capng_apply(CAPNG_SELECT_BOTH);
+ }
+#endif /* HAVE_CAP_NG_H */
+
/* Execute proper handler. */
dbg_net_verb("udp: thread started (worker %p).\n", thread);
diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index bc55434..fe7c0ab 100644
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -60,6 +60,14 @@ static int xfr_udp_timeout(event_t *e)
if (!data) {
return KNOTD_EINVAL;
}
+
+ /* Remove reference to this event. */
+ if (data->zone != NULL) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(data->zone);
+ if (zd != NULL && zd->soa_pending == e) {
+ zd->soa_pending = NULL;
+ }
+ }
sockaddr_update(&data->addr);
char r_addr[SOCKADDR_STRLEN];
@@ -100,24 +108,17 @@ static int xfr_udp_timeout(event_t *e)
*/
static int xfr_process_udp_query(xfrworker_t *w, int fd, knot_ns_xfr_t *data)
{
- /* Prepare msg header. */
- struct msghdr msg;
- memset(&msg, 0, sizeof(struct msghdr));
- struct iovec iov;
- memset(&iov, 0, sizeof(struct iovec));
- iov.iov_base = data->wire;
- iov.iov_len = data->wire_size;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_name = data->addr.ptr;
- msg.msg_namelen = data->addr.len;
-
/* Receive msg. */
- ssize_t n = recvmsg(data->session, &msg, 0);
+ ssize_t n = recvfrom(data->session, data->wire, data->wire_size, 0, data->addr.ptr, &data->addr.len);
size_t resp_len = data->wire_size;
if (n > 0) {
udp_handle(fd, data->wire, n, &resp_len, &data->addr, w->ns);
}
+
+ if(data->type == XFR_TYPE_SOA && data->zone) {
+ zonedata_t * zd = (zonedata_t*)knot_zone_data(data->zone);
+ zd->soa_pending = NULL;
+ }
/* Disable timeout. */
evsched_t *sched =
@@ -144,7 +145,7 @@ static int xfr_process_udp_query(xfrworker_t *w, int fd, knot_ns_xfr_t *data)
return KNOTD_EOK;
}
-/*! \todo Document me. */
+/*! \todo Document me (issue #1586) */
static void xfr_free_task(knot_ns_xfr_t *task)
{
if (!task) {
@@ -179,12 +180,11 @@ static void xfr_free_task(knot_ns_xfr_t *task)
skip_remove(h->tasks, (void*)((size_t)task->session), 0, 0);
pthread_mutex_unlock(&h->tasks_mx);
- /*! \todo Free data. */
close(task->session);
free(task);
}
-/*! \todo Document me. */
+/*! \todo Document me (issue #1586) */
static knot_ns_xfr_t *xfr_register_task(xfrworker_t *w, knot_ns_xfr_t *req)
{
knot_ns_xfr_t *t = malloc(sizeof(knot_ns_xfr_t));
@@ -223,13 +223,18 @@ static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
switch(data->type) {
case XFR_TYPE_AIN:
if (data->data) {
- xfrin_constructed_zone_t *constr_zone =
+ if (data->flags & XFR_FLAG_AXFR_FINISHED) {
+ knot_zone_contents_deep_free(
+ (knot_zone_contents_t **)&data->data, 0);
+ } else {
+ xfrin_constructed_zone_t *constr_zone =
(xfrin_constructed_zone_t *)data->data;
- knot_zone_contents_deep_free(
- &(constr_zone->contents), 0);
- xfrin_free_orphan_rrsigs(&(constr_zone->rrsigs));
- free(data->data);
- data->data = 0;
+ knot_zone_contents_deep_free(
+ &(constr_zone->contents), 0);
+ xfrin_free_orphan_rrsigs(&(constr_zone->rrsigs));
+ free(data->data);
+ data->data = 0;
+ }
}
break;
case XFR_TYPE_IIN:
@@ -306,12 +311,12 @@ static int xfr_xfrin_finalize(xfrworker_t *w, knot_ns_xfr_t *data)
} else {
/* Update zone. */
ret = zones_apply_changesets(data);
- if (ret != KNOTD_EOK) {
+ if (ret != KNOT_EOK) {
log_zone_error("IXFR failed to "
"apply changesets to "
"zone '%s/IN' - %s\n",
zorigin,
- knotd_strerror(ret));
+ knot_strerror(ret));
}
}
/* Free changesets, but not the data. */
@@ -400,10 +405,6 @@ static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode)
log_server_info("Unsupported digest algorithm "
"requested, treating as "
"bad key.\n");
- /*! \todo [TSIG] It is unclear from RFC if I
- * should treat is as a bad key
- * or some other error.
- */
*rcode = KNOT_RCODE_NOTAUTH;
xfr->tsig_key = NULL;
xfr->tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
@@ -419,7 +420,7 @@ static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode)
if (key && kname && knot_dname_compare(key->name, kname) == 0) {
dbg_xfr("xfr: found claimed TSIG key for comparison\n");
} else {
- /*! \todo These ifs are redundant. */
+ /*! \todo These ifs are redundant (issue #1586) */
*rcode = KNOT_RCODE_NOTAUTH;
/* TSIG is mandatory if configured for interface. */
if (key && !kname) {
@@ -517,9 +518,23 @@ static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode)
*/
int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf, size_t buflen)
{
+ /* Fetch associated zone. */
+ const char *zname = "<unknown>";
+ knot_zone_t *zone = (knot_zone_t *)data->zone;
+ if (zone) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
+ if (zd) {
+ zname = zd->conf->name;
+ }
+ }
+
/* Update xfer state. */
data->wire = buf;
data->wire_size = buflen;
+
+ char r_addr[SOCKADDR_STRLEN];
+ sockaddr_tostr(&data->addr, r_addr, sizeof(r_addr));
+ int r_port = sockaddr_portnum(&data->addr);
/* Handle SOA/NOTIFY responses. */
if (data->type == XFR_TYPE_NOTIFY || data->type == XFR_TYPE_SOA) {
@@ -551,7 +566,9 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* AXFR-style IXFR. */
if (ret == KNOT_ENOIXFR) {
- log_server_notice("IXFR/IN - Fallback to AXFR/IN.\n");
+ log_server_notice("IXFR of '%s/IN' with %s:%d - "
+ "Fallback to AXFR/IN.\n",
+ zname, r_addr, r_port);
assert(data->type == XFR_TYPE_IIN);
data->type = XFR_TYPE_AIN;
ret = knot_ns_process_axfrin(w->ns, data);
@@ -567,10 +584,10 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
}
/* IXFR refused, try again with AXFR. */
- knot_zone_t *zone = (knot_zone_t *)data->zone;
if (zone && data->type == XFR_TYPE_IIN && ret == KNOT_EXFRREFUSED) {
- log_server_notice("IXFR/IN failed, attempting to use "
- "AXFR/IN instead.\n");
+ log_server_notice("IXFR of '%s/IN' with %s:%d failed, attempting "
+ "to use AXFR/IN instead.\n",
+ zname, r_addr, r_port);
size_t bufsize = buflen;
data->wire_size = buflen; /* Reset maximum bufsize */
ret = xfrin_create_axfr_query(zone->name, data,
@@ -589,13 +606,17 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* Handle errors. */
if (ret == KNOT_ENOXFR) {
- log_server_warning("%cXFR/IN request finished - %s\n",
+ log_server_warning("%cXFR request of '%s/IN' with %s:%d "
+ "finished - %s\n",
data->type == XFR_TYPE_AIN ? 'A' : 'I',
+ zname, r_addr, r_port,
knot_strerror(ret));
} else if (ret < 0) {
- log_server_error("%cXFR/IN request failed - %s\n",
- data->type == XFR_TYPE_AIN ? 'A' : 'I',
- knot_strerror(ret));
+ log_server_error("%cXFR/IN request of '%s/IN' with %s:%d "
+ "failed - %s\n",
+ data->type == XFR_TYPE_AIN ? 'A' : 'I',
+ zname, r_addr, r_port,
+ knot_strerror(ret));
}
@@ -605,7 +626,6 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
knot_zone_t *zone = (knot_zone_t *)data->zone;
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- const char *zorigin = zd->conf->name;
/* Only for successful xfers. */
if (ret > 0) {
@@ -613,14 +633,14 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* AXFR bootstrap timeout. */
rcu_read_lock();
- if (ret != KNOTD_EOK && data->type == XFR_TYPE_AIN) {
+ if (ret != KNOTD_EOK && !knot_zone_contents(zone)) {
/* Schedule request (60 - 90s random delay). */
int tmr_s = AXFR_BOOTSTRAP_RETRY;
tmr_s += (30.0 * 1000) * (tls_rand());
zd->xfr_in.bootstrap_retry = tmr_s;
log_zone_info("Another attempt to AXFR bootstrap "
"zone '%s' in %d seconds.\n",
- zorigin, tmr_s/1000);
+ zname, tmr_s/1000);
}
rcu_read_unlock();
@@ -652,7 +672,7 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
return result;
}
-/*! \todo Document me.
+/*! \todo Document me (issue #1586)
*/
static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
{
@@ -693,7 +713,14 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
/* Connect to remote. */
if (data->session <= 0) {
int fd = socket_create(data->addr.family, SOCK_STREAM);
- if (fd < 0) {
+ if (fd >= 0) {
+ /* Bind to specific address - if set. */
+ sockaddr_update(&data->saddr);
+ if (data->saddr.len > 0) {
+ /* Presume port is already preset. */
+ ret = bind(fd, data->saddr.ptr, data->saddr.len);
+ }
+ } else {
pthread_mutex_unlock(&zd->xfr_in.lock);
log_server_warning("Failed to create socket "
"(type=%s, family=%s).\n",
@@ -702,6 +729,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
"AF_INET" : "AF_INET6");
return KNOTD_ERROR;
}
+
ret = connect(fd, data->addr.ptr, data->addr.len);
if (ret < 0) {
pthread_mutex_unlock(&zd->xfr_in.lock);
@@ -722,7 +750,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
"another attempt in %d seconds."
"\n", tmr_s / 1000);
}
- return KNOTD_ERROR;
+ return KNOTD_ECONNREFUSED;
}
/* Store new socket descriptor. */
@@ -740,7 +768,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
rcu_read_unlock();
log_server_warning("Failed start IXFR on zone with no "
"contents\n");
- return KNOTD_ERROR;
+ return KNOTD_EINVAL;
}
/* Prepare TSIG key if set. */
@@ -791,6 +819,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
ret = data->send(data->session, &data->addr, data->wire, bufsize);
if (ret != bufsize) {
+ pthread_mutex_unlock(&zd->xfr_in.lock);
log_server_notice("Failed to send %cXFR query.",
data->type == XFR_TYPE_AIN ? 'A' : 'I');
xfr_free_task(task);
@@ -819,6 +848,67 @@ static int xfr_fd_compare(void *k1, void *k2)
return 0;
}
+static inline char xfr_strtype(knot_ns_xfr_t *xfr) {
+ if (xfr->type == XFR_TYPE_IOUT) {
+ return 'I';
+ } else {
+ return 'A';
+ }
+}
+
+static int xfr_answer_axfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
+{
+ int ret = knot_ns_answer_axfr(ns, xfr);
+ dbg_xfr("xfr: ns_answer_axfr() = %d.\n", ret);
+ return ret;
+}
+
+static int xfr_answer_ixfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
+{
+ /* Check serial differeces. */
+ int ret = KNOT_EOK;
+ uint32_t serial_from = 0;
+ uint32_t serial_to = 0;
+ dbg_xfr_verb("Loading serials for IXFR.\n");
+ ret = ns_ixfr_load_serials(xfr, &serial_from, &serial_to);
+ dbg_xfr_detail("Loaded serials: from: %u, to: %u\n",
+ serial_from, serial_to);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ /* Load changesets from journal. */
+ dbg_xfr_verb("Loading changesets from journal.\n");
+ int chsload = zones_xfr_load_changesets(xfr, serial_from, serial_to);
+ if (chsload != KNOTD_EOK) {
+ /* History cannot be reconstructed, fallback to AXFR. */
+ if (chsload == KNOTD_ERANGE || chsload == KNOTD_ENOENT) {
+ log_server_info("IXFR transfer of zone '%s/OUT'"
+ " - failed to load data from journal: "
+ " Incomplete history. "
+ "Fallback to AXFR.\n",
+ xfr->zname);
+ xfr->type = XFR_TYPE_AOUT;
+ return xfr_answer_axfr(ns, xfr);
+ } else if (chsload == KNOTD_EMALF) {
+ xfr->rcode = KNOT_RCODE_FORMERR;
+ } else {
+ xfr->rcode = KNOT_RCODE_SERVFAIL;
+ }
+
+ /* Mark all as generic error. */
+ ret = KNOT_ERROR;
+ }
+
+ /* Finally, answer. */
+ if (chsload == KNOTD_EOK) {
+ ret = knot_ns_answer_ixfr(ns, xfr);
+ dbg_xfr("xfr: ns_answer_ixfr() = %d.\n", ret);
+ }
+
+ return ret;
+}
+
/*
* Public APIs.
*/
@@ -1014,12 +1104,113 @@ int xfr_request(xfrhandler_t *handler, knot_ns_xfr_t *req)
return KNOTD_EOK;
}
+int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
+{
+ if (ns == NULL || xfr == NULL) {
+ return KNOTD_EINVAL;
+ }
+
+ int ret = knot_ns_init_xfr(ns, xfr);
+ int xfr_failed = (ret != KNOT_EOK);
+ const char * errstr = knot_strerror(ret);
+
+ /* Check requested zone. */
+ if (!xfr_failed) {
+ ret = zones_xfr_check_zone(xfr, &xfr->rcode);
+ xfr_failed = (ret != KNOTD_EOK);
+ errstr = knotd_strerror(ret);
+ }
+
+ /* Check TSIG. */
+ if (!xfr_failed && xfr->tsig_key != NULL) {
+ ret = xfr_check_tsig(xfr, &xfr->rcode);
+ xfr_failed = (ret != KNOT_EOK);
+ errstr = knot_strerror(ret);
+ }
+
+ /* Prepare place for TSIG data */
+ xfr->tsig_data = malloc(KNOT_NS_TSIG_DATA_MAX_SIZE);
+ if (xfr->tsig_data) {
+ dbg_xfr("xfr: TSIG data allocated: %zu.\n",
+ KNOT_NS_TSIG_DATA_MAX_SIZE);
+ xfr->tsig_data_size = 0;
+ } else {
+ dbg_xfr("xfr: failed to allocate TSIG data "
+ "buffer (%zu kB)\n",
+ KNOT_NS_TSIG_DATA_MAX_SIZE / 1024);
+ }
+
+ // use the QNAME as the zone name to get names also for
+ // zones that are not in the server
+ const knot_dname_t *qname = knot_packet_qname(xfr->query);
+ if (qname != NULL) {
+ xfr->zname = knot_dname_to_str(qname);
+ } else {
+ xfr->zname = strdup("(unknown)");
+ }
+
+ /* Finally, answer AXFR/IXFR. */
+ int io_error = 0;
+ if (!xfr_failed) {
+ switch(xfr->type) {
+ case XFR_TYPE_AOUT:
+ ret = xfr_answer_axfr(ns, xfr);
+ break;
+ case XFR_TYPE_IOUT:
+ ret = xfr_answer_ixfr(ns, xfr);
+ break;
+ default: ret = KNOTD_ENOTSUP; break;
+ }
+
+ xfr_failed = (ret != KNOT_EOK);
+ errstr = knot_strerror(ret);
+ io_error = (ret == KNOT_ECONN);
+ }
+
+ /* Remote address identification. */
+ char r_addr[SOCKADDR_STRLEN];
+ sockaddr_tostr(&xfr->addr, r_addr, sizeof(r_addr));
+ int r_port = sockaddr_portnum(&xfr->addr);
+
+ /* Check results. */
+ if (xfr_failed) {
+ if (!io_error) {
+ knot_ns_xfr_send_error(ns, xfr, xfr->rcode);
+ }
+ log_server_notice("%cXFR transfer of zone '%s/OUT' "
+ "%s:%d failed: %s\n",
+ xfr_strtype(xfr) , xfr->zname,
+ r_addr, r_port,
+ errstr);
+ ret = KNOTD_ERROR;
+ } else {
+ log_server_info("%cXFR transfer of zone '%s/OUT' "
+ "to %s:%d successful.\n",
+ xfr_strtype(xfr), xfr->zname,
+ r_addr, r_port);
+ ret = KNOTD_EOK;
+ }
+
+ /* Free allocated data. */
+ free(xfr->tsig_data);
+ xfr->tsig_data = NULL;
+
+ /* Cleanup. */
+ free(xfr->digest);
+ free(xfr->query->wireformat); /* Free wireformat. */
+ knot_packet_free(&xfr->query); /* Free query. */
+ knot_packet_free(&xfr->response); /* Free response. */
+ knot_free_changesets((knot_changesets_t **)(&xfr->data));
+ free(xfr->zname);
+ return ret;
+}
+
static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
{
/* Read single request. */
knot_ns_xfr_t xfr = {};
int ret = evqueue_read(w->q, &xfr, sizeof(knot_ns_xfr_t));
- if (ret != sizeof(knot_ns_xfr_t)) {
+ if (ret != sizeof(knot_ns_xfr_t)) {
dbg_xfr_verb("xfr: evqueue_read() returned %d.\n", ret);
return KNOTD_ENOTRUNNING;
}
@@ -1035,247 +1226,23 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
conf_read_lock();
/* Handle request. */
+ zonedata_t *zd = NULL;
+ if(xfr.zone != NULL) {
+ zd = (zonedata_t *)knot_zone_data(xfr.zone);
+ }
knot_ns_xfr_t *task = 0;
evsched_t *sch = 0;
const char *req_type = "";
- knot_rcode_t rcode = 0;
- char *zname = "(unknown)";
- uint32_t serial_from = 0;
- uint32_t serial_to = 0;
-
- /* XFR request state tracking. */
- int init_failed = 0;
- const char *errstr = "";
- const knot_dname_t *qname = NULL;
-
- dbg_xfr_verb("Query ptr: %p\n", xfr.query);
-
dbg_xfr_verb("xfr: processing request type '%d'\n", xfr.type);
+ dbg_xfr_verb("xfr: query ptr: %p\n", xfr.query);
switch(xfr.type) {
- case XFR_TYPE_AOUT:
- req_type = "AXFR/OUT";
- ret = knot_ns_init_xfr(w->ns, &xfr);
- init_failed = (ret != KNOT_EOK);
- errstr = knot_strerror(ret);
-
- // use the QNAME as the zone name to get names also for
- // zones that are not in the server
- qname = knot_packet_qname(xfr.query);
- if (qname != NULL) {
- zname = knot_dname_to_str(qname);
- }
-
- /* Check requested zone. */
- if (!init_failed) {
- ret = zones_xfr_check_zone(&xfr, &rcode);
- init_failed = (ret != KNOTD_EOK);
- errstr = knotd_strerror(ret);
- }
-
- /* Check TSIG. */
- if (!init_failed && xfr.tsig_key != NULL) {
- ret = xfr_check_tsig(&xfr, &rcode);
- init_failed = (ret != KNOT_EOK);
- errstr = knot_strerror(ret);
- }
-
- /* Evaluate progress and answer if passed. */
- if (init_failed) {
- knot_ns_xfr_send_error(w->ns, &xfr, rcode);
- socket_close(xfr.session);
- log_server_notice("AXFR transfer of zone '%s/OUT' "
- "%s:%d failed: %s\n",
- zname,
- r_addr, r_port,
- errstr);
- } else {
- /* Prepare place for TSIG data */
- xfr.tsig_data = malloc(KNOT_NS_TSIG_DATA_MAX_SIZE);
- if (xfr.tsig_data) {
- dbg_xfr("xfr: TSIG data allocated: %zu.\n",
- KNOT_NS_TSIG_DATA_MAX_SIZE);
- xfr.tsig_data_size = 0;
- } else {
- dbg_xfr("xfr: failed to allocate TSIG data "
- "buffer (%zu kB)\n",
- KNOT_NS_TSIG_DATA_MAX_SIZE / 1024);
- }
-
- ret = knot_ns_answer_axfr(w->ns, &xfr);
- dbg_xfr("xfr: ns_answer_axfr() = %d.\n", ret);
- if (ret != KNOTD_EOK) {
- socket_close(xfr.session);
- } else {
- log_server_info("AXFR transfer of zone '%s/OUT' "
- "to %s:%d successful.\n",
- zname,
- r_addr, r_port);
- }
-
- /* Free allocated data. */
- free(xfr.tsig_data);
- xfr.tsig_data = NULL;
- }
-
- if (xfr.digest) {
- free(xfr.digest);
- xfr.digest_max_size = 0;
- xfr.digest = 0;
- }
- free(xfr.query->wireformat);
- xfr.query->wireformat = 0;
- knot_packet_free(&xfr.query); /* Free query. */
- xfr.query = NULL;
- knot_packet_free(&xfr.response); /* Free response. */
- xfr.response = NULL;
-
- if (qname != NULL) {
- free(zname);
- }
-
- break;
- case XFR_TYPE_IOUT:
- req_type = "IXFR/OUT";
- ret = knot_ns_init_xfr(w->ns, &xfr);
- init_failed = (ret != KNOT_EOK);
- errstr = knot_strerror(ret);
-
- qname = knot_packet_qname(xfr.query);
- if (qname != NULL) {
- zname = knot_dname_to_str(qname);
- }
-
- /* Check requested zone. */
- if (!init_failed) {
- ret = zones_xfr_check_zone(&xfr, &rcode);
- init_failed = (ret != KNOTD_EOK);
- errstr = knotd_strerror(ret);
- }
-
- /* Check TSIG. */
- if (!init_failed && xfr.tsig_key != NULL) {
- ret = xfr_check_tsig(&xfr, &rcode);
- init_failed = (ret != KNOT_EOK);
- errstr = knot_strerror(ret);
- }
-
- // Check serial differeces
- if (!init_failed) {
- dbg_xfr_verb("Loading serials for IXFR.\n");
- ret = ns_ixfr_load_serials(&xfr, &serial_from,
- &serial_to);
- dbg_xfr_detail("Loaded serials: from: %u, to: %u\n",
- serial_from, serial_to);
- init_failed = (ret != KNOT_EOK);
- errstr = knot_strerror(ret);
- }
-
- /* Load changesets from journal. */
- if (!init_failed) {
- dbg_xfr_verb("Loading changesets from journal.\n");
- ret = zones_xfr_load_changesets(&xfr, serial_from,
- serial_to);
- if (ret != KNOTD_EOK) {
- /* History cannot be reconstructed, fallback to AXFR. */
- if (ret == KNOTD_ERANGE || ret == KNOTD_ENOENT) {
- log_server_info("IXFR transfer of zone '%s/OUT'"
- " - failed to load data from journal: %s."
- " Fallback to AXFR.\n",
- knotd_strerror(ret), zname);
- xfr.type = XFR_TYPE_AOUT;
- xfr_request(w->master, &xfr);
- conf_read_unlock();
- return KNOTD_EOK;
- } else if (ret == KNOTD_EMALF) {
- rcode = KNOT_RCODE_FORMERR;
- } else {
- rcode = KNOT_RCODE_SERVFAIL;
- }
- init_failed = (ret != KNOTD_EOK);
- errstr = knotd_strerror(ret);
- }
- }
-
- /* Evaluate progress and answer if passed. */
- if (init_failed) {
- knot_ns_xfr_send_error(w->ns, &xfr, rcode);
- log_server_notice("IXFR transfer of zone '%s/OUT' "
- "%s:%d failed: %s\n",
- zname,
- r_addr, r_port,
- errstr);
- ret = KNOTD_ERROR;
- } else {
- /* Prepare place for TSIG data */
- xfr.tsig_data = malloc(KNOT_NS_TSIG_DATA_MAX_SIZE);
- if (xfr.tsig_data) {
- dbg_xfr("xfr: TSIG data allocated: %zu.\n",
- KNOT_NS_TSIG_DATA_MAX_SIZE);
- xfr.tsig_data_size = 0;
- } else {
- dbg_xfr("xfr: failed to allocate TSIG data "
- "buffer (%zu kB)\n",
- KNOT_NS_TSIG_DATA_MAX_SIZE / 1024);
- }
-
- ret = knot_ns_answer_ixfr(w->ns, &xfr);
- dbg_xfr("xfr: ns_answer_ixfr() = %d.\n", ret);
- if (ret != KNOT_EOK) {
- errstr = knot_strerror(ret);
- log_server_notice("IXFR transfer of zone '%s/OUT' "
- "%s:%d failed: %s\n",
- zname,
- r_addr, r_port,
- errstr);
- socket_close(xfr.session);
- } else {
- log_server_info("IXFR transfer of zone '%s/OUT' "
- "to %s:%d successful.\n",
- zname,
- r_addr, r_port);
- }
-
- /* Free allocated data. */
- free(xfr.tsig_data);
- xfr.tsig_data = NULL;
- }
-
- /* Cleanup. */
- if (xfr.digest) {
- free(xfr.digest);
- xfr.digest = NULL;
- xfr.digest_max_size = 0;
- }
- free(xfr.query->wireformat); /* Free wireformat. */
- xfr.query->wireformat = NULL;
- knot_packet_free(&xfr.query); /* Free query. */
- xfr.query = NULL;
- knot_packet_free(&xfr.response); /* Free response. */
- xfr.response = NULL;
-
- if (xfr.data != NULL) { /* Free changesets. */
- knot_free_changesets((knot_changesets_t **)
- (&xfr.data));
- }
-
- if (zname) {
- free(zname);
- }
-
- break;
case XFR_TYPE_AIN:
- req_type = "AXFR/IN";
- ret = xfr_client_start(w, &xfr);
-
- /* Report. */
- if (ret != KNOTD_EOK && ret != KNOTD_EACCES) {
- log_server_error("%s request from %s:%d failed: %s\n",
- req_type, r_addr, r_port,
- knotd_strerror(ret));
- }
- break;
case XFR_TYPE_IIN:
- req_type = "IXFR/IN";
+ if (xfr.type == XFR_TYPE_IIN) {
+ req_type = "IXFR/IN";
+ } else {
+ req_type = "AXFR/IN";
+ }
ret = xfr_client_start(w, &xfr);
/* Report. */
@@ -1302,13 +1269,18 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
sch = ((server_t *)knot_ns_get_data(w->ns))->sched;
task->data = evsched_schedule_cb(sch, xfr_udp_timeout,
task, SOA_QRY_TIMEOUT);
+ if (zd && xfr.type == XFR_TYPE_SOA) {
+ zd->soa_pending = (event_t*)task->data;
+ }
ret = KNOTD_EOK;
break;
/* Socket close event. */
case XFR_TYPE_CLOSE:
xfr_free_task((knot_ns_xfr_t *)xfr.data);
ret = KNOTD_EOK;
+ break;
default:
+ log_server_error("Unknown XFR request type (%d).\n", xfr.type);
break;
}
@@ -1347,7 +1319,7 @@ int xfr_worker(dthread_t *thread)
}
/* Poll fdset. */
- int nfds = fdset_wait(w->fdset);
+ int nfds = fdset_wait(w->fdset, OS_EV_FOREVER);
if (nfds <= 0) {
continue;
}
diff --git a/src/knot/server/xfr-handler.h b/src/knot/server/xfr-handler.h
index 3587d93..02eb189 100644
--- a/src/knot/server/xfr-handler.h
+++ b/src/knot/server/xfr-handler.h
@@ -31,7 +31,7 @@
#include "libknot/nameserver/name-server.h"
#include "common/evqueue.h"
#include "common/fdset.h"
-#include "common/skip-list.h" /*!< \todo Consider another data struct. */
+#include "common/skip-list.h"
struct xfrhandler_t;
@@ -146,6 +146,18 @@ int xfr_request_init(knot_ns_xfr_t *r, int type, int flags, knot_packet_t *pkt);
int xfr_request(xfrhandler_t *handler, knot_ns_xfr_t *req);
/*!
+ * \brief Answer XFR query.
+ *
+ * \param ns Nameserver instance.
+ * \param req XFR request.
+ *
+ * \retval KNOTD_EOK on success.
+ * \retval KNOTD_EINVAL on NULL handler or request.
+ * \retval KNOTD_ERROR on error.
+ */
+int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *req);
+
+/*!
* \brief XFR master runnable.
*
* Processes incoming AXFR/IXFR requests asynchonously.
diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c
index 8616ebd..a196462 100644
--- a/src/knot/server/zones.c
+++ b/src/knot/server/zones.c
@@ -46,7 +46,6 @@ static const size_t XFRIN_CHANGESET_BINARY_STEP = 100;
/*!
* \brief Wrapper for TCP send.
- * \todo Implement generic fd pool properly with callbacks.
*/
#include "knot/server/tcp-handler.h"
static int zones_send_cb(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
@@ -59,6 +58,10 @@ static int zones_send_cb(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
/*! \brief Zone data destructor function. */
static int zonedata_destroy(knot_zone_t *zone)
{
+ if (zone == NULL) {
+ return KNOTD_EINVAL;
+ }
+
dbg_zones_verb("zones: zonedata_destroy(%p) called\n", zone);
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
@@ -122,10 +125,14 @@ static int zonedata_destroy(knot_zone_t *zone)
/*! \brief Zone data constructor function. */
static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
{
+ if (cfg == NULL || zone == NULL) {
+ return KNOTD_EINVAL;
+ }
zonedata_t *zd = malloc(sizeof(zonedata_t));
if (!zd) {
return KNOTD_ENOMEM;
}
+ memset(zd, 0, sizeof(zonedata_t));
/* Link to config. */
zd->conf = cfg;
@@ -362,6 +369,7 @@ static int zones_refresh_ev(event_t *e)
knot_ns_xfr_t xfr_req;
memset(&xfr_req, 0, sizeof(knot_ns_xfr_t));
memcpy(&xfr_req.addr, &zd->xfr_in.master, sizeof(sockaddr_t));
+ memcpy(&xfr_req.saddr, &zd->xfr_in.via, sizeof(sockaddr_t));
xfr_req.data = (void *)zone;
xfr_req.send = zones_send_cb;
@@ -410,15 +418,17 @@ static int zones_refresh_ev(event_t *e)
} else {
pthread_mutex_unlock(&zd->xfr_in.lock);
}
-
- /* Create query. */
- /*! \todo API for retrieval of name. */
+
+ /* Invalidate pending SOA query. */
+ event_t *soa_pending = zd->soa_pending;
+ zd->soa_pending = NULL;
/*! \todo [TSIG] CHANGE!!! only for compatibility now. */
knot_ns_xfr_t xfr_req;
memset(&xfr_req, 0, sizeof(knot_ns_xfr_t));
xfr_req.wire = qbuf;
-
+
+ /* Create query. */
int ret = xfrin_create_soa_query(zone->name, &xfr_req, &buflen);
if (ret == KNOT_EOK) {
@@ -426,6 +436,15 @@ static int zones_refresh_ev(event_t *e)
/* Create socket on random port. */
int sock = socket_create(master->family, SOCK_DGRAM);
+
+ /* Check requested source. */
+ sockaddr_t *via = &zd->xfr_in.via;
+ if (via->len > 0) {
+ if (bind(sock, via->ptr, via->len) < 0) {
+ socket_close(sock);
+ sock = -1;
+ }
+ }
/* Send query. */
ret = KNOTD_ERROR;
@@ -456,12 +475,18 @@ static int zones_refresh_ev(event_t *e)
req.type = XFR_TYPE_SOA;
req.zone = zone;
memcpy(&req.addr, master, sizeof(sockaddr_t));
+ memcpy(&req.saddr, &zd->xfr_in.via, sizeof(sockaddr_t));
sockaddr_update(&req.addr);
- xfr_request(zd->server->xfr_h, &req);
+ ret = xfr_request(zd->server->xfr_h, &req);
}
} else {
ret = KNOTD_ERROR;
}
+
+ if (ret != KNOTD_EOK) {
+ log_server_warning("Failed to issue SOA query for zone '%s'.\n",
+ zd->conf->name);
+ }
/* Schedule EXPIRE timer on first attempt. */
if (!zd->xfr_in.expire) {
@@ -481,7 +506,13 @@ static int zones_refresh_ev(event_t *e)
/* Unlock RCU. */
rcu_read_unlock();
-
+
+ /* Close invalidated SOA query. */
+ evsched_event_finished(e->parent);
+ if (soa_pending != NULL) {
+ /* Execute */
+ evsched_schedule(e->parent, soa_pending, 0);
+ }
return ret;
}
@@ -495,7 +526,7 @@ static int zones_notify_send(event_t *e)
notify_ev_t *ev = (notify_ev_t *)e->data;
knot_zone_t *zone = ev->zone;
if (!zone) {
- log_zone_error("notify: NOTIFY invalid event received\n");
+ log_zone_error("NOTIFY invalid event received\n");
evsched_event_free(e->parent, e);
free(ev);
return KNOTD_EINVAL;
@@ -544,6 +575,14 @@ static int zones_notify_send(event_t *e)
/* Create socket on random port. */
int sock = socket_create(ev->addr.family, SOCK_DGRAM);
+
+ /* Check requested source. */
+ if (ev->saddr.len > 0) {
+ if (bind(sock, ev->saddr.ptr, ev->saddr.len) < 0) {
+ socket_close(sock);
+ sock = -1;
+ }
+ }
/* Send query. */
ret = -1;
@@ -558,9 +597,9 @@ static int zones_notify_send(event_t *e)
sockaddr_tostr(&ev->addr, r_addr, sizeof(r_addr));
int r_port = sockaddr_portnum(&ev->addr);
ev->msgid = knot_wire_get_id(qbuf);
- log_server_info("Issued NOTIFY query to %s:%d, expecting "
- "response ID=%d\n",
- r_addr, r_port,
+ log_server_info("Issued '%s' NOTIFY query to %s:%d, "
+ "expecting response ID=%d\n",
+ zd->conf->name, r_addr, r_port,
ev->msgid);
}
@@ -698,6 +737,17 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
const char *source, const char *filename)
{
knot_zone_t *zone = NULL;
+ size_t zlen = strlen(zone_name);
+ char *zname = NULL;
+ if (zlen > 0) {
+ if ((zname = strdup(zone_name)) == NULL) {
+ return KNOTD_ENOMEM;
+ }
+ } else {
+ return KNOTD_EINVAL;
+ }
+
+ zname[zlen - 1] = '\0'; /* Trim last dot */
/* Check path */
if (filename) {
@@ -709,24 +759,29 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
/* OK */
break;
case KNOT_EFEWDATA:
- log_server_error("Compiled zone db '%s' not exists.\n",
- filename);
+ log_server_error("Couldn't find compiled zone. "
+ "Please recompile '%s'.\n", zname);
+ free(zname);
return KNOTD_EZONEINVAL;
case KNOT_ECRC:
- log_server_error("Compiled zone db CRC mismatches, "
- "db is corrupted or .crc file is "
- "deleted.\n");
+ log_server_error("Compiled zone db CRC mismatch, "
+ "db is corrupted or .crc file is "
+ "deleted. Please recompile '%s'.\n",
+ zname);
+ free(zname);
return KNOTD_EZONEINVAL;
case KNOT_EMALF:
- log_server_error("Compiled db '%s' is too old, "
- " please recompile.\n",
- filename);
+ log_server_error("Compiled db '%s' is too old. "
+ "Please recompile '%s'.\n",
+ filename, zname);
+ free(zname);
return KNOTD_EZONEINVAL;
case KNOT_ERROR:
case KNOT_ENOMEM:
default:
- log_server_error("Failed to read zone db file '%s'.\n",
- filename);
+ log_server_error("Failed to load compiled zone file "
+ "'%s'.\n", filename);
+ free(zname);
return KNOTD_EZONEINVAL;
}
@@ -735,7 +790,7 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
if (src_changed || knot_zload_needs_update(zl)) {
log_server_warning("Database for zone '%s' is not "
"up-to-date. Please recompile.\n",
- zone_name);
+ zname);
}
zone = knot_zload_load(zl);
@@ -743,8 +798,7 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
/* Check loaded name. */
const knot_dname_t *dname = knot_zone_name(zone);
knot_dname_t *dname_req = 0;
- dname_req = knot_dname_new_from_str(zone_name,
- strlen(zone_name), 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",
@@ -756,7 +810,9 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
knot_dname_free(&dname_req);
/* CLEANUP */
- //knot_zone_contents_dump(zone->contents, 1);
+// knot_zone_contents_dump(zone->contents, 1);
+// int errs = knot_zone_contents_integrity_check(zone->contents);
+// fprintf(stderr, "INTEGRITY CHECK OF ZONE. ERRORS: %d\n", errs);
if (zone) {
/* save the timestamp from the zone db file */
@@ -780,16 +836,20 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name,
if (!zone) {
log_server_error("Failed to load "
"db '%s' for zone '%s'.\n",
- filename, zone_name);
+ filename, zname);
+ free(zname);
return KNOTD_EZONEINVAL;
}
} else {
/* db is null. */
+ log_server_error("No file name for zone '%s'.\n", zname);
+ free(zname);
return KNOTD_EINVAL;
}
/* CLEANUP */
// knot_zone_dump(zone, 1);
+ free(zname);
return KNOTD_EOK;
}
@@ -1113,7 +1173,7 @@ static int zones_journal_apply(knot_zone_t *zone)
log_server_info("Applying '%zu' changesets from journal "
"to zone '%s'.\n",
chsets->count, zd->conf->name);
- int apply_ret = xfrin_apply_changesets_to_zone(zone, chsets);
+ int apply_ret = xfrin_apply_changesets(zone, chsets);
if (apply_ret != KNOT_EOK) {
log_server_error("Failed to apply changesets to "
"'%s' - %s\n",
@@ -1237,15 +1297,10 @@ static int zones_insert_zones(knot_nameserver_t *ns,
z->name,
z->db);
ret = zones_load_zone(db_new, z->name,
- z->file, z->db);
+ z->file, z->db);
if (ret == KNOTD_EOK) {
log_server_info("Loaded zone '%s'\n",
z->name);
- } else {
- log_server_error("Failed to load zone "
- "'%s' - %s\n",
- z->name,
- knotd_strerror(ret));
}
}
@@ -1302,6 +1357,7 @@ static int zones_insert_zones(knot_nameserver_t *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;
@@ -1309,6 +1365,12 @@ static int zones_insert_zones(knot_nameserver_t *ns,
cfg_if->family,
cfg_if->address,
cfg_if->port);
+ if (cfg_if->via) {
+ sockaddr_set(&zd->xfr_in.via,
+ cfg_if->via->family,
+ cfg_if->via->address,
+ 0);
+ }
if (cfg_if->key) {
memcpy(&zd->xfr_in.tsig_key,
@@ -1510,7 +1572,7 @@ static int zones_check_tsig_query(const knot_zone_t *zone,
assert(rcode != NULL);
assert(tsig_key_zone != NULL);
- knot_rrset_t *tsig = NULL;
+ const knot_rrset_t *tsig = NULL;
if (knot_packet_additional_rrset_count(query) > 0) {
/*! \todo warning */
@@ -1811,17 +1873,24 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
rcode = KNOT_RCODE_REFUSED;
}
- assert(resp != NULL);
-
if (rcode != KNOT_RCODE_NOERROR) {
dbg_zones_verb("Failed preparing response structure: %s.\n",
knot_strerror(rcode));
- knot_ns_error_response(nameserver, knot_packet_id(query),
- rcode, resp_wire, rsize);
+ if (resp == NULL) {
+ knot_ns_error_response(nameserver, knot_packet_id(query),
+ 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.
*/
+ assert(resp != NULL);
assert(rcode == KNOT_RCODE_NOERROR);
uint16_t tsig_rcode = 0;
knot_key_t *tsig_key_zone = NULL;
@@ -1996,6 +2065,9 @@ int zones_process_response(knot_nameserver_t *nameserver,
response_wire == NULL) {
return KNOTD_EINVAL;
}
+
+ /* Declare no response. */
+ *rsize = 0;
/* Handle SOA query response, cancel EXPIRE timer
* and start AXFR transfer if needed.
@@ -2008,9 +2080,6 @@ int zones_process_response(knot_nameserver_t *nameserver,
return KNOTD_ERROR;
}
- /* No response. */
- *rsize = 0;
-
/* Find matching zone and ID. */
const knot_dname_t *zone_name = knot_packet_qname(packet);
/*! \todo Change the access to the zone db. */
@@ -2041,6 +2110,7 @@ int zones_process_response(knot_nameserver_t *nameserver,
dbg_zones_verb("xfrin_transfer_needed() returned %d\n", ret);
if (ret < 0) {
/* RETRY/EXPIRE timers running, do not interfere. */
+ rcu_read_unlock();
return KNOTD_ERROR;
}
@@ -2074,7 +2144,8 @@ int zones_process_response(knot_nameserver_t *nameserver,
/* Prepare XFR client transfer. */
knot_ns_xfr_t xfr_req;
memset(&xfr_req, 0, sizeof(knot_ns_xfr_t));
- memcpy(&xfr_req.addr, from, sizeof(sockaddr_t));
+ memcpy(&xfr_req.addr, &zd->xfr_in.master, sizeof(sockaddr_t));
+ memcpy(&xfr_req.saddr, &zd->xfr_in.via, sizeof(sockaddr_t));
xfr_req.zone = (void *)zone;
xfr_req.send = zones_send_cb;
@@ -2094,7 +2165,6 @@ int zones_process_response(knot_nameserver_t *nameserver,
nameserver))->xfr_h, &xfr_req);
}
-
return KNOTD_EOK;
}
@@ -2194,6 +2264,7 @@ static int zones_dump_xfr_zone_text(knot_zone_contents_t *zone,
* until the zone_dump_text is called. Needs to be opened in
* this function for writing.
* Use open() for exclusive open and fcntl() for locking.
+ * (issue #1587)
*/
char *new_zonefile = zones_find_free_filename(zonefile);
@@ -2213,13 +2284,13 @@ static int zones_dump_xfr_zone_text(knot_zone_contents_t *zone,
return KNOTD_ERROR;
}
- /*! \todo this would also need locking as well. */
+ /*! \todo this would also need locking as well (issue #1587) */
remove(zonefile); /* Don't care, as the rename will trigger the error. */
if (rename(new_zonefile, zonefile) != 0) {
log_zone_warning("Failed to replace old zone file '%s'' with a new"
" zone file '%s'.\n", zonefile, new_zonefile);
/*! \todo with proper locking, this shouldn't happen,
- * revise it later on.
+ * revise it later on (issue #1587)
*/
zone_dump_text(zone, zonefile);
free(new_zonefile);
@@ -2243,6 +2314,7 @@ static int ns_dump_xfr_zone_binary(knot_zone_contents_t *zone,
* until the zone_dump_text is called. Needs to be opened in
* this function for writing.
* Use open() for exclusive open and fcntl() for locking.
+ * (issue #1587)
*/
char *new_zonedb = zones_find_free_filename(zonedb);
@@ -2253,7 +2325,7 @@ static int ns_dump_xfr_zone_binary(knot_zone_contents_t *zone,
return KNOTD_ERROR; /*! \todo New error code? */
}
- /*! \todo this would also need locking as well. */
+ /*! \todo this would also need locking as well (issue #1587) */
int rc = knot_zdump_dump_and_swap(zone, new_zonedb, zonedb, zonefile);
free(new_zonedb);
@@ -2306,6 +2378,9 @@ int zones_ns_conf_hook(const struct conf_t *conf, void *data)
{
knot_nameserver_t *ns = (knot_nameserver_t *)data;
dbg_zones_verb("zones: reconfiguring name server.\n");
+
+ /* Set NSID. */
+ knot_ns_set_nsid(ns, conf->nsid, conf->nsid_len);
knot_zonedb_t *old_db = 0;
@@ -2477,8 +2552,6 @@ int zones_store_changesets(knot_ns_xfr_t *xfr)
knot_zone_t *zone = xfr->zone;
knot_changesets_t *src = (knot_changesets_t *)xfr->data;
- /*! \todo Convert to binary format. */
-
int ret = zones_changesets_to_binary(src);
if (ret != KNOTD_EOK) {
return ret;
@@ -2606,11 +2679,11 @@ int zones_xfr_load_changesets(knot_ns_xfr_t *xfr, uint32_t serial_from,
int zones_apply_changesets(knot_ns_xfr_t *xfr)
{
if (xfr == NULL || xfr->zone == NULL || xfr->data == NULL) {
- return KNOTD_EINVAL;
+ return KNOT_EBADARG;
}
- return xfrin_apply_changesets_to_zone(xfr->zone,
- (knot_changesets_t *)xfr->data);
+ return xfrin_apply_changesets(xfr->zone,
+ (knot_changesets_t *)xfr->data);
}
/*----------------------------------------------------------------------------*/
@@ -2665,7 +2738,7 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
}
/* Schedule IXFR database syncing. */
- /*! \todo Sync timer should not be reset after each xfr. */
+ /*! \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);
@@ -2702,9 +2775,15 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
}
/* Parse server address. */
+ sockaddr_init(&ev->saddr, -1);
int ret = sockaddr_set(&ev->addr, cfg_if->family,
cfg_if->address,
cfg_if->port);
+ conf_iface_t *via = cfg_if->via;
+ if (ret > 0 && via != NULL) {
+ ret = sockaddr_set(&ev->saddr, via->family,
+ via->address, 0);
+ }
if (ret < 1) {
free(ev);
dbg_zones("notify: NOTIFY slave %s has invalid "
@@ -2726,7 +2805,8 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
add_tail(&zd->notify_pending, &ev->n);
pthread_mutex_unlock(&zd->lock);
- log_server_info("Scheduled NOTIFY query after %d s to %s:%d\n",
+ log_server_info("Scheduled '%s' NOTIFY query "
+ "after %d s to %s:%d\n", zd->conf->name,
tmr_s, cfg_if->address, cfg_if->port);
}
diff --git a/src/knot/server/zones.h b/src/knot/server/zones.h
index 9fcab7d..53c5290 100644
--- a/src/knot/server/zones.h
+++ b/src/knot/server/zones.h
@@ -69,6 +69,7 @@ typedef struct zonedata_t
struct {
acl_t *acl; /*!< ACL for xfr-in.*/
sockaddr_t master; /*!< Master server for xfr-in.*/
+ sockaddr_t via; /*!< Master server transit interface.*/
knot_key_t tsig_key; /*!< Master TSIG key. */
struct event_t *timer; /*!< Timer for REFRESH/RETRY. */
struct event_t *expire; /*!< Timer for REFRESH. */
@@ -80,6 +81,9 @@ typedef struct zonedata_t
/*! \brief List of pending NOTIFY events. */
list notify_pending;
+
+ /*! \brief List of pending SOA queries. */
+ struct event_t* soa_pending;
/*! \brief Zone IXFR history. */
journal_t *ixfr_db;
diff --git a/src/knot/stat/stat.h b/src/knot/stat/stat.h
index a82f130..0cf1454 100644
--- a/src/knot/stat/stat.h
+++ b/src/knot/stat/stat.h
@@ -71,7 +71,7 @@ typedef struct stat_stat stat_t;
#ifdef STAT_COMPILE
stat_t *stat_new();
#else
-inline stat_t *stat_new()
+static inline inline stat_t *stat_new()
{
return NULL;
}
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index 3ca38a2..f511f35 100644
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -3,6 +3,7 @@
#include <arpa/inet.h>
#include "knot/common.h"
+#include "knot/zone/zone-dump.h"
#include "knot/other/error.h"
#include "libknot/libknot.h"
#include "common/base32hex.h"
@@ -10,6 +11,90 @@
#include "semantic-check.h"
+static char *error_messages[(-ZC_ERR_ALLOC) + 1] = {
+ [-ZC_ERR_ALLOC] = "Memory allocation error!\n",
+
+ [-ZC_ERR_MISSING_SOA] = "SOA record missing in zone!\n",
+
+ [-ZC_ERR_RRSIG_RDATA_TYPE_COVERED] =
+ "RRSIG: Type covered rdata field is wrong!\n",
+ [-ZC_ERR_RRSIG_RDATA_TTL] =
+ "RRSIG: TTL rdata field is wrong!\n",
+ [-ZC_ERR_RRSIG_RDATA_LABELS] =
+ "RRSIG: Labels rdata field is wrong!\n",
+ [-ZC_ERR_RRSIG_RDATA_DNSKEY_OWNER] =
+ "RRSIG: Signer name is different than in DNSKEY!\n",
+ [-ZC_ERR_RRSIG_RDATA_SIGNED_WRONG] =
+ "RRSIG: Key error!\n",
+ [-ZC_ERR_RRSIG_NO_RRSIG] =
+ "RRSIG: No RRSIG!\n",
+ [-ZC_ERR_RRSIG_SIGNED] =
+ "RRSIG: Signed RRSIG!\n",
+ [-ZC_ERR_RRSIG_OWNER] =
+ "RRSIG: Owner name rdata field is wrong!\n",
+ [-ZC_ERR_RRSIG_CLASS] =
+ "RRSIG: Class is wrong!\n",
+ [-ZC_ERR_RRSIG_TTL] =
+ "RRSIG: TTL is wrong!\n",
+ [-ZC_ERR_RRSIG_NOT_ALL] =
+ "RRSIG: Not all RRs are signed!\n",
+
+ [-ZC_ERR_NO_NSEC] =
+ "NSEC: Missing NSEC record\n",
+ [-ZC_ERR_NSEC_RDATA_BITMAP] =
+ "NSEC: Wrong NSEC bitmap!\n",
+ [-ZC_ERR_NSEC_RDATA_MULTIPLE] =
+ "NSEC: Multiple NSEC records!\n",
+ [-ZC_ERR_NSEC_RDATA_CHAIN] =
+ "NSEC: NSEC chain is not coherent!\n",
+ [-ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC] =
+ "NSEC: NSEC chain is not cyclic!\n",
+
+ [-ZC_ERR_NSEC3_UNSECURED_DELEGATION] =
+ "NSEC3: Zone contains unsecured delegation!\n",
+ [-ZC_ERR_NSEC3_NOT_FOUND] =
+ "NSEC3: Could not find previous NSEC3 record in the zone!\n",
+ [-ZC_ERR_NSEC3_UNSECURED_DELEGATION_OPT] =
+ "NSEC3: Unsecured delegation is not part "
+ "of the Opt-Out span!\n",
+ [-ZC_ERR_NSEC3_RDATA_TTL] =
+ "NSEC3: Original TTL rdata field is wrong!\n",
+ [-ZC_ERR_NSEC3_RDATA_CHAIN] =
+ "NSEC3: NSEC3 chain is not coherent!\n",
+ [-ZC_ERR_NSEC3_RDATA_BITMAP] =
+ "NSEC3: NSEC3 bitmap error!\n",
+
+ [-ZC_ERR_CNAME_CYCLE] =
+ "CNAME: CNAME cycle!\n",
+ [-ZC_ERR_DNAME_CYCLE] =
+ "CNAME: DNAME cycle!\n",
+ [-ZC_ERR_CNAME_EXTRA_RECORDS] =
+ "CNAME: Node with CNAME record has other records!\n",
+ [-ZC_ERR_DNAME_CHILDREN] =
+ "DNAME: Node with DNAME record has children!\n",
+ [-ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC] =
+ "CNAME: Node with CNAME record has other "
+ "records than RRSIG and NSEC/NSEC3!\n",
+ [-ZC_ERR_CNAME_MULTIPLE] = "CNAME: Multiple CNAME records!\n",
+ [-ZC_ERR_DNAME_MULTIPLE] = "DNAME: Multiple DNAME records!\n",
+ [-ZC_ERR_CNAME_WILDCARD_SELF] = "CNAME wildcard "
+ "pointing to itself!\n",
+ [-ZC_ERR_DNAME_WILDCARD_SELF] = "DNAME wildcard "
+ "pointing to itself!\n",
+
+ /* ^
+ | Important errors (to be logged on first occurence and counted) */
+
+
+ /* Below are errors of lesser importance, to be counted unless
+ specified otherwise */
+
+ [-ZC_ERR_GLUE_NODE] =
+ "GLUE: Node with Glue record missing!\n",
+ [-ZC_ERR_GLUE_RECORD] =
+ "GLUE: Record with Glue address missing\n",
+};
+
static const uint MAX_CNAME_CYCLE_DEPTH = 15;
err_handler_t *handler_new(char log_cname, char log_glue,
@@ -21,7 +106,8 @@ err_handler_t *handler_new(char log_cname, char log_glue,
/* It should be initialized, but to be safe */
memset(handler->errors, 0, sizeof(uint) * (-ZC_ERR_ALLOC + 1));
-
+
+ handler->error_count = 0;
handler->options.log_cname = log_cname;
handler->options.log_glue = log_glue;
handler->options.log_rrsigs = log_rrsigs;
@@ -42,9 +128,15 @@ err_handler_t *handler_new(char log_cname, char log_glue,
*/
static void log_error_from_node(err_handler_t *handler,
const knot_node_t *node,
- uint error)
+ int error)
{
+ if (error > (int)ZC_ERR_GLUE_RECORD) {
+ fprintf(stderr, "Unknown error.\n");
+ return;
+ }
+
if (node != NULL) {
+ handler->error_count++;
char *name =
knot_dname_to_str(knot_node_owner(node));
fprintf(stderr, "Semantic warning in node: %s: ", name);
@@ -59,7 +151,7 @@ static void log_error_from_node(err_handler_t *handler,
int err_handler_handle_error(err_handler_t *handler,
const knot_node_t *node,
- uint error)
+ int error)
{
assert(handler && node);
if ((error != 0) &&
@@ -67,9 +159,10 @@ int err_handler_handle_error(err_handler_t *handler,
return ZC_ERR_UNKNOWN;
}
- if (error == ZC_ERR_ALLOC) {
- ERR_ALLOC_FAILED;
- return ZC_ERR_ALLOC;
+ /*!< \todo this is so wrong! This should not even return anything. */
+ if (error == ZC_ERR_ALLOC || error == KNOT_ERROR
+ || error == KNOT_EBADARG) {
+ return KNOT_EBADARG;
}
/* missing SOA can only occur once, so there
@@ -145,8 +238,14 @@ void err_handler_log_all(err_handler_t *handler)
* \retval ZC_ERR_CNAME_CYCLE when cycle is present.
*/
static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
- const knot_rrset_t *rrset)
+ const knot_rrset_t *rrset,
+ char *fatal_error)
{
+ if (rrset->type != KNOT_RRTYPE_CNAME &&
+ rrset->type != KNOT_RRTYPE_DNAME) {
+ return KNOT_EBADARG;
+ }
+
const knot_rrset_t *next_rrset = rrset;
assert(rrset);
const knot_rdata_t *tmp_rdata = knot_rrset_rdata(next_rrset);
@@ -158,19 +257,151 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
const knot_dname_t *next_dname =
knot_rdata_cname_name(tmp_rdata);
+ /* (cname_name == dname_target) */
assert(next_dname);
-
+
+ /* Check wildcard pointing to itself. */
+ if (knot_dname_is_wildcard(knot_rrset_owner(rrset))) {
+ /* We need to chop the wildcard. */
+
+ knot_dname_t *chopped_wc =
+ knot_dname_left_chop(knot_rrset_owner(rrset));
+ if (!chopped_wc) {
+ /* Definitely not a cycle. */
+ return KNOT_EOK;
+ }
+
+ /*
+ * And check that no sub-dname up to zone apex is present
+ * in its rdata.
+ */
+
+ knot_dname_t *next_dname_copy =
+ knot_dname_deep_copy(next_dname);
+ if (!next_dname_copy) {
+ knot_dname_free(&chopped_wc);
+ return KNOT_ERROR;
+ }
+
+ const knot_dname_t *zone_origin =
+ knot_node_owner(knot_zone_contents_apex(zone));
+ if (!zone_origin) {
+ knot_dname_free(&chopped_wc);
+ knot_dname_free(&next_dname_copy);
+ return KNOT_ERROR;
+ }
+
+ char error_found = 0;
+ char cut_offs = 1;
+
+ while (knot_dname_compare(next_dname_copy,
+ zone_origin) != 0 &&
+ !error_found) {
+ /* Compare chopped owner with current next dname. */
+ error_found =
+ knot_dname_compare(next_dname_copy,
+ chopped_wc) == 0;
+ if (error_found && cut_offs == 1) {
+ /* WC without * == link. */
+ knot_dname_free(&next_dname_copy);
+ knot_dname_free(&chopped_wc);
+ return KNOT_EOK;
+ }
+
+ knot_dname_t *tmp_chopped =
+ knot_dname_left_chop(next_dname_copy);
+ knot_dname_free(&next_dname_copy);
+ if (!tmp_chopped) {
+ knot_dname_free(&chopped_wc);
+ knot_dname_free(&next_dname_copy);
+ return KNOT_ERROR;
+ }
+
+ cut_offs++;
+
+ next_dname_copy = tmp_chopped;
+ }
+
+ if (error_found) {
+ knot_dname_free(&next_dname_copy);
+ knot_dname_free(&chopped_wc);
+ assert(cut_offs > 1);
+ *fatal_error = 1;
+ return ZC_ERR_CNAME_WILDCARD_SELF;
+ }
+
+ knot_dname_free(&next_dname_copy);
+ knot_dname_free(&chopped_wc);
+
+ /*
+ * Test for transitive wildcard loops.
+ * Basically the same as below, only we look for wildcards and
+ * strip them in the same fashion as above.
+ */
+
+ }
+
while (i < MAX_CNAME_CYCLE_DEPTH && next_dname != NULL) {
next_node = knot_zone_contents_get_node(zone, next_dname);
if (next_node == NULL) {
next_node =
- knot_zone_contents_get_nsec3_node(zone, next_dname);
+ knot_zone_contents_get_nsec3_node(zone,
+ next_dname);
+ }
+
+/*!< \todo this might replace some of the code above. */
+// /* Still NULL, try wildcards. */
+// if (next_node == NULL && knot_dname_is_wildcard(next_dname)) {
+// /* We can only use the wildcard so many times. */
+
+// /* Create chopped copy of wc. */
+// knot_dname_t *chopped_wc =
+// knot_dname_left_chop(next_dname);
+// if (chopped_wc == NULL) {
+// /* If name with this wc is in the zone,
+// we have a problem (eg. cycle continues). */
+// next_node =
+// knot_zone_contents_get_node(zone,
+// chopped_wc);
+// /* (No need to consider NSEC3 nodes.) */
+// knot_dname_free(&chopped_wc);
+// }
+// }
+
+ /* Just a guess. */
+ knot_dname_t *chopped_next =
+ knot_dname_left_chop(next_dname);
+ if (chopped_next == NULL) {
+ /*!< \todo check. */
+ return KNOT_ERROR;
+ }
+ while (next_node == NULL && chopped_next != NULL) {
+ /* Cat '*' .*/
+ knot_dname_t *wc =
+ knot_dname_new_from_str("*", strlen("*"),
+ NULL);
+ if (wc == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ if (knot_dname_cat(wc, chopped_next) == NULL) {
+ return KNOT_ERROR;
+ }
+
+ next_node =
+ knot_zone_contents_get_node(zone, wc);
+ knot_dname_free(&wc);
+ knot_dname_t *tmp = chopped_next;
+ chopped_next = knot_dname_left_chop(chopped_next);
+ knot_dname_free(&tmp);
}
+
+ knot_dname_free(&chopped_next);
if (next_node != NULL) {
next_rrset = knot_node_rrset(next_node,
- KNOT_RRTYPE_CNAME);
+ rrset->type);
if (next_rrset != NULL) {
next_dname =
knot_rdata_cname_name(next_rrset->rdata);
@@ -186,6 +417,7 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
/* even if the length is 0, i will be 1 */
if (i >= MAX_CNAME_CYCLE_DEPTH) {
+ *fatal_error = 1;
return ZC_ERR_CNAME_CYCLE;
}
@@ -626,7 +858,7 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
err_handler_t *handler)
{
assert(handler);
- const knot_node_t *nsec3_node = knot_node_nsec3_node(node, 0);
+ const knot_node_t *nsec3_node = knot_node_nsec3_node(node);
if (nsec3_node == NULL) {
/* I know it's probably not what RFCs say, but it will have to
@@ -643,7 +875,7 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
if (knot_zone_contents_find_nsec3_for_name(zone,
knot_node_owner(node),
&nsec3_node,
- &nsec3_previous, 0) != 0) {
+ &nsec3_previous) != 0) {
err_handler_handle_error(handler, node,
ZC_ERR_NSEC3_NOT_FOUND);
}
@@ -713,17 +945,17 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
}
/* This is why we allocate maximum length of decoded string + 1 */
- memmove(next_dname_decoded + 1, next_dname_decoded, real_size);
- next_dname_decoded[0] = real_size;
-
+// memmove(next_dname_decoded + 1, next_dname_decoded, real_size);
+// next_dname_decoded[0] = real_size;
+
/* Local allocation, will be discarded. */
knot_dname_t *next_dname =
- knot_dname_new_from_wire(next_dname_decoded,
- real_size + 1, NULL);
+ knot_dname_new_from_str((char *)next_dname_decoded,
+ real_size, NULL);
CHECK_ALLOC_LOG(next_dname, KNOT_ENOMEM);
free(next_dname_decoded);
-
+
if (knot_dname_cat(next_dname,
knot_node_owner(knot_zone_contents_apex(zone))) == NULL) {
fprintf(stderr, "Could not concatenate dnames!\n");
@@ -764,7 +996,6 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
type) == NULL) {
err_handler_handle_error(handler, node,
ZC_ERR_NSEC3_RDATA_BITMAP);
- break;
/* char *name =
knot_dname_to_str(
log_zone_error("Node %s does "
@@ -796,21 +1027,25 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
static int semantic_checks_plain(knot_zone_contents_t *zone,
knot_node_t *node,
char do_checks,
- err_handler_t *handler)
+ err_handler_t *handler,
+ int only_mandatory,
+ char *fatal_error)
{
assert(handler);
const knot_rrset_t *cname_rrset =
knot_node_rrset(node, KNOT_RRTYPE_CNAME);
if (cname_rrset != NULL) {
- if (check_cname_cycles_in_zone(zone, cname_rrset) !=
- KNOT_EOK) {
+ int ret = check_cname_cycles_in_zone(zone, cname_rrset,
+ fatal_error);
+ if (ret != KNOT_EOK) {
err_handler_handle_error(handler, node,
- ZC_ERR_CNAME_CYCLE);
+ ret);
}
/* No DNSSEC and yet there is more than one rrset in node */
if (do_checks == 1 &&
knot_node_rrset_count(node) != 1) {
+ *fatal_error = 1;
err_handler_handle_error(handler, node,
ZC_ERR_CNAME_EXTRA_RECORDS);
} else if (knot_node_rrset_count(node) != 1) {
@@ -818,6 +1053,7 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
if (!(knot_node_rrset(node, KNOT_RRTYPE_RRSIG) ||
knot_node_rrset(node, KNOT_RRTYPE_NSEC)) ||
knot_node_rrset_count(node) > 3) {
+ *fatal_error = 1;
err_handler_handle_error(handler, node,
ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC);
}
@@ -825,6 +1061,7 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
if (knot_rrset_rdata(cname_rrset)->next !=
knot_rrset_rdata(cname_rrset)) {
+ *fatal_error = 1;
err_handler_handle_error(handler, node,
ZC_ERR_CNAME_MULTIPLE);
}
@@ -833,23 +1070,35 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
const knot_rrset_t *dname_rrset =
knot_node_rrset(node, KNOT_RRTYPE_DNAME);
if (dname_rrset != NULL) {
- if (check_cname_cycles_in_zone(zone, dname_rrset) !=
- KNOT_EOK) {
+ int ret = check_cname_cycles_in_zone(zone, dname_rrset,
+ fatal_error);
+ if (ret == ZC_ERR_CNAME_CYCLE) {
+ *fatal_error = 1;
err_handler_handle_error(handler, node,
ZC_ERR_DNAME_CYCLE);
+ } else if (ret == ZC_ERR_CNAME_WILDCARD_SELF) {
+ *fatal_error = 1;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_DNAME_WILDCARD_SELF);
}
if (knot_node_rrset(node, KNOT_RRTYPE_CNAME)) {
+ *fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_DNAME_EXTRA_RECORDS);
+ ZC_ERR_CNAME_EXTRA_RECORDS);
}
-
- if (knot_rrset_rdata(dname_rrset)->next !=
- knot_rrset_rdata(dname_rrset)) {
+
+ if (node->children != 0) {
+ *fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_DNAME_MULTIPLE);
+ ZC_ERR_DNAME_CHILDREN);
}
}
+
+ if (only_mandatory) {
+ return KNOT_EOK;
+ }
+
/* check for glue records at zone cuts */
if (knot_node_is_deleg_point(node)) {
@@ -1086,23 +1335,27 @@ static void do_checks_in_tree(knot_node_t *node, void *data)
assert(zone);
-
-/* for (int i = 0; i < count; ++i) {
- assert(rrsets[i] != NULL);
- knot_zone_save_enclosers_rrset(rrsets[i],
- zone,
- (skip_list_t *)args->arg2);
- } */
-
knot_node_t *first_node = (knot_node_t *)args->arg4;
knot_node_t **last_node = (knot_node_t **)args->arg5;
err_handler_t *handler = (err_handler_t *)args->arg6;
-
+
char do_checks = *((char *)(args->arg3));
if (do_checks) {
- semantic_checks_plain(zone, node, do_checks, handler);
+ semantic_checks_plain(zone, node, do_checks, handler, 0,
+ (char *)args->arg7);
+ } else {
+ assert(handler);
+ /* All CNAME/DNAME checks are mandatory. */
+ handler->options.log_cname = 1;
+ int check_level = 1 + (zone_is_secure(zone) ? 1 : 0);
+ semantic_checks_plain(zone, node, check_level, handler, 1,
+ (char *)args->arg7);
+
+ free(rrsets);
+ assert(do_checks == 0);
+ return;
}
if (do_checks > 1) {
@@ -1113,24 +1366,31 @@ static void do_checks_in_tree(knot_node_t *node, void *data)
free(rrsets);
}
-void zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
+int zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
err_handler_t *handler,
knot_node_t **last_node)
{
- if (!do_checks) {
- return;
+ if (!handler) {
+ return KNOT_EBADARG;
}
-
arg_t arguments;
arguments.arg1 = zone;
arguments.arg3 = &do_checks;
arguments.arg4 = NULL;
arguments.arg5 = last_node;
arguments.arg6 = handler;
+ char fatal_error = 0;
+ arguments.arg7 = (void *)&fatal_error;
knot_zone_contents_tree_apply_inorder(zone,
do_checks_in_tree,
(void *)&arguments);
+
+ if (fatal_error) {
+ return KNOT_ERROR;
+ }
+
+ return KNOT_EOK;
}
void log_cyclic_errors_in_zone(err_handler_t *handler,
@@ -1167,14 +1427,10 @@ void log_cyclic_errors_in_zone(err_handler_t *handler,
return;
}
- /* This is why allocate maximum length of decoded string + 1 */
- memmove(next_dname_decoded + 1, next_dname_decoded, real_size);
- next_dname_decoded[0] = real_size;
-
/* Local allocation, will be discarded. */
knot_dname_t *next_dname =
- knot_dname_new_from_wire(next_dname_decoded,
- real_size + 1, NULL);
+ knot_dname_new_from_str((char *)next_dname_decoded,
+ real_size, NULL);
if (next_dname == NULL) {
fprintf(stderr, "Could not allocate dname!\n");
err_handler_handle_error(handler, last_nsec3_node,
@@ -1196,15 +1452,18 @@ void log_cyclic_errors_in_zone(err_handler_t *handler,
/* Check it points somewhere first. */
if (knot_zone_contents_find_nsec3_node(zone, next_dname) == NULL) {
+ assert(knot_zone_contents_find_node(zone,
+ next_dname) ==
+ NULL);
err_handler_handle_error(handler, last_nsec3_node,
ZC_ERR_NSEC3_RDATA_CHAIN);
- }
-
- /* Compare with the actual first NSEC3 node. */
- if (knot_dname_compare(first_nsec3_node->owner,
- next_dname) != 0) {
- err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
+ } else {
+ /* Compare with the actual first NSEC3 node. */
+ if (knot_dname_compare(first_nsec3_node->owner,
+ next_dname) != 0) {
+ err_handler_handle_error(handler, last_nsec3_node,
+ ZC_ERR_NSEC3_RDATA_CHAIN);
+ }
}
/* Directly discard. */
diff --git a/src/knot/zone/semantic-check.h b/src/knot/zone/semantic-check.h
index 88d828a..08396c8 100644
--- a/src/knot/zone/semantic-check.h
+++ b/src/knot/zone/semantic-check.h
@@ -32,7 +32,7 @@
* so that code does not have to change if new errors are added.
*/
enum zonechecks_errors {
- ZC_ERR_ALLOC = -40,
+ ZC_ERR_ALLOC = -50,
ZC_ERR_UNKNOWN,
ZC_ERR_MISSING_SOA,
@@ -73,10 +73,12 @@ enum zonechecks_errors {
ZC_ERR_CNAME_CYCLE,
ZC_ERR_DNAME_CYCLE,
ZC_ERR_CNAME_EXTRA_RECORDS,
- ZC_ERR_DNAME_EXTRA_RECORDS,
+ ZC_ERR_DNAME_CHILDREN,
ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC,
ZC_ERR_CNAME_MULTIPLE,
ZC_ERR_DNAME_MULTIPLE,
+ ZC_ERR_CNAME_WILDCARD_SELF,
+ ZC_ERR_DNAME_WILDCARD_SELF,
ZC_ERR_CNAME_GENERAL_ERROR,
@@ -86,86 +88,6 @@ enum zonechecks_errors {
ZC_ERR_GLUE_GENERAL_ERROR,
};
-static char *error_messages[(-ZC_ERR_ALLOC) + 1] = {
- [-ZC_ERR_ALLOC] = "Memory allocation error!\n",
-
- [-ZC_ERR_MISSING_SOA] = "SOA record missing in zone!\n",
-
- [-ZC_ERR_RRSIG_RDATA_TYPE_COVERED] =
- "RRSIG: Type covered rdata field is wrong!\n",
- [-ZC_ERR_RRSIG_RDATA_TTL] =
- "RRSIG: TTL rdata field is wrong!\n",
- [-ZC_ERR_RRSIG_RDATA_LABELS] =
- "RRSIG: Labels rdata field is wrong!\n",
- [-ZC_ERR_RRSIG_RDATA_DNSKEY_OWNER] =
- "RRSIG: Signer name is different than in DNSKEY!\n",
- [-ZC_ERR_RRSIG_RDATA_SIGNED_WRONG] =
- "RRSIG: Key error!\n",
- [-ZC_ERR_RRSIG_NO_RRSIG] =
- "RRSIG: No RRSIG!\n",
- [-ZC_ERR_RRSIG_SIGNED] =
- "RRSIG: Signed RRSIG!\n",
- [-ZC_ERR_RRSIG_OWNER] =
- "RRSIG: Owner name rdata field is wrong!\n",
- [-ZC_ERR_RRSIG_CLASS] =
- "RRSIG: Class is wrong!\n",
- [-ZC_ERR_RRSIG_TTL] =
- "RRSIG: TTL is wrong!\n",
- [-ZC_ERR_RRSIG_NOT_ALL] =
- "RRSIG: Not all RRs are signed!\n",
-
- [-ZC_ERR_NO_NSEC] =
- "NSEC: Missing NSEC record\n",
- [-ZC_ERR_NSEC_RDATA_BITMAP] =
- "NSEC: Wrong NSEC bitmap!\n",
- [-ZC_ERR_NSEC_RDATA_MULTIPLE] =
- "NSEC: Multiple NSEC records!\n",
- [-ZC_ERR_NSEC_RDATA_CHAIN] =
- "NSEC: NSEC chain is not coherent!\n",
- [-ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC] =
- "NSEC: NSEC chain is not cyclic!\n",
-
- [-ZC_ERR_NSEC3_UNSECURED_DELEGATION] =
- "NSEC3: Zone contains unsecured delegation!\n",
- [-ZC_ERR_NSEC3_NOT_FOUND] =
- "NSEC3: Could not find previous NSEC3 record in the zone!\n",
- [-ZC_ERR_NSEC3_UNSECURED_DELEGATION_OPT] =
- "NSEC3: Unsecured delegation is not part "
- "of the Opt-Out span!\n",
- [-ZC_ERR_NSEC3_RDATA_TTL] =
- "NSEC3: Original TTL rdata field is wrong!\n",
- [-ZC_ERR_NSEC3_RDATA_CHAIN] =
- "NSEC3: NSEC3 chain is not coherent!\n",
- [-ZC_ERR_NSEC3_RDATA_BITMAP] =
- "NSEC3: NSEC3 bitmap error!\n",
-
- [-ZC_ERR_CNAME_CYCLE] =
- "CNAME: CNAME cycle!\n",
- [-ZC_ERR_DNAME_CYCLE] =
- "CNAME: DNAME cycle!\n",
- [-ZC_ERR_CNAME_EXTRA_RECORDS] =
- "CNAME: Node with CNAME record has other records!\n",
- [-ZC_ERR_DNAME_EXTRA_RECORDS] =
- "DNAME: Node with DNAME record has other records!\n",
- [-ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC] =
- "CNAME: Node with CNAME record has other "
- "records than RRSIG and NSEC/NSEC3!\n",
- [-ZC_ERR_CNAME_MULTIPLE] = "CNAME: Multiple CNAME records!\n",
- [-ZC_ERR_DNAME_MULTIPLE] = "DNAME: Multiple DNAME records!\n",
-
- /* ^
- | Important errors (to be logged on first occurence and counted) */
-
-
- /* Below are errors of lesser importance, to be counted unless
- specified otherwise */
-
- [-ZC_ERR_GLUE_NODE] =
- "GLUE: Node with Glue record missing!\n",
- [-ZC_ERR_GLUE_RECORD] =
- "GLUE: Record with Glue address missing\n",
-};
-
/*!
* \brief Arguments to be used with tree traversal functions. Uses void pointers
* to be more versatile.
@@ -201,6 +123,7 @@ struct err_handler {
/* Consider moving error messages here */
struct handler_options options; /*!< Handler options. */
uint errors[(-ZC_ERR_ALLOC) + 1]; /*!< Array with error messages */
+ uint error_count; /*!< Total error count */
};
typedef struct err_handler err_handler_t;
@@ -234,7 +157,7 @@ err_handler_t *handler_new(char log_cname, char log_glue,
*/
int err_handler_handle_error(err_handler_t *handler,
const knot_node_t *node,
- uint error);
+ int error);
/*!
* \brief Checks if last node in NSEC/NSEC3 chain points to first node in the
@@ -269,7 +192,7 @@ void err_handler_log_all(err_handler_t *handler);
* \param handler Semantic error handler.
* \param last_node Last checked node, which is part of NSEC(3) chain.
*/
-void zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
+int zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
err_handler_t *handler,
knot_node_t **last_node);
diff --git a/src/knot/zone/zone-dump-text.c b/src/knot/zone/zone-dump-text.c
index 8ce0441..dcb9add 100644
--- a/src/knot/zone/zone-dump-text.c
+++ b/src/knot/zone/zone-dump-text.c
@@ -316,6 +316,11 @@ char *rdata_binary_dname_to_string(knot_rdata_item_t item)
if (item.raw_data == NULL) {
return NULL;
}
+
+ if (item.raw_data[0] == 0) {
+ return NULL;
+ }
+
/* Create new dname frow raw data - probably the easiest way. */
knot_dname_t *dname = knot_dname_new_from_wire((uint8_t *)(item.raw_data + 1),
item.raw_data[0], NULL);
diff --git a/src/knot/zone/zone-dump.c b/src/knot/zone/zone-dump.c
index de4a5a1..0be1ac7 100644
--- a/src/knot/zone/zone-dump.c
+++ b/src/knot/zone/zone-dump.c
@@ -406,9 +406,9 @@ static void knot_node_dump_binary(knot_node_t *node, void *data,
fwrite_wrapper(&owner_id, sizeof(owner_id), 1, f, stream, stream_size,
crc);
- if (knot_node_parent(node, 0) != NULL) {
+ if (knot_node_parent(node) != NULL) {
uint32_t parent_id = knot_dname_id(
- knot_node_owner(knot_node_parent(node, 0)));
+ knot_node_owner(knot_node_parent(node)));
fwrite_wrapper(&parent_id, sizeof(parent_id), 1, f,
stream, stream_size, crc);
} else {
@@ -422,13 +422,13 @@ static void knot_node_dump_binary(knot_node_t *node, void *data,
dbg_zdump("Written flags: %u\n", node->flags);
- if (knot_node_nsec3_node(node, 0) != NULL) {
+ if (knot_node_nsec3_node(node) != NULL) {
uint32_t nsec3_id =
- knot_node_owner(knot_node_nsec3_node(node, 0))->id;
+ knot_node_owner(knot_node_nsec3_node(node))->id;
fwrite_wrapper(&nsec3_id, sizeof(nsec3_id), 1, f,
stream, stream_size, crc);
dbg_zdump("Written nsec3 node id: %u\n",
- knot_node_owner(knot_node_nsec3_node(node, 0))->id);
+ knot_node_owner(knot_node_nsec3_node(node))->id);
} else {
uint32_t nsec3_id = 0;
fwrite_wrapper(&nsec3_id, sizeof(nsec3_id), 1, f,
@@ -472,16 +472,7 @@ static void knot_node_dump_binary(knot_node_t *node, void *data,
dbg_zdump("Function ends with: %ld\n\n", ftell(f));
}
-/*!
- * \brief Checks if zone uses DNSSEC and/or NSEC3
- *
- * \param zone Zone to be checked.
- *
- * \retval 0 if zone is not secured.
- * \retval 2 if zone uses NSEC3
- * \retval 1 if zone uses NSEC
- */
-static int zone_is_secure(knot_zone_contents_t *zone)
+int zone_is_secure(knot_zone_contents_t *zone)
{
if (knot_node_rrset(knot_zone_contents_apex(zone),
KNOT_RRTYPE_DNSKEY) == NULL) {
@@ -562,6 +553,21 @@ static void dump_node_to_file(knot_node_t *node, void *data)
knot_node_dump_binary(node, data, NULL, NULL, (crc_t *)arg->arg7);
}
+static char *knot_zdump_crc_file(const char* filename)
+{
+ char *crc_path =
+ malloc(sizeof(char) * (strlen(filename) +
+ strlen(".crc") + 1));
+ CHECK_ALLOC_LOG(crc_path, NULL);
+ memset(crc_path, 0,
+ sizeof(char) * (strlen(filename) +
+ strlen(".crc") + 1));
+ memcpy(crc_path, filename,
+ sizeof(char) * strlen(filename));
+ crc_path = strcat(crc_path, ".crc");
+ return crc_path;
+}
+
int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
int do_checks, const char *sfilename)
{
@@ -572,6 +578,9 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open(new_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (fd == -1) {
+ close(fd);
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
return KNOT_EBADARG;
}
@@ -606,31 +615,37 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
if (do_checks && zone_is_secure(zone)) {
do_checks += zone_is_secure(zone);
}
-
- err_handler_t *handler = NULL;
-
- if (do_checks) {
- handler = handler_new(1, 0, 1, 1, 1);
- if (handler == NULL) {
- /* disable checks and we can continue */
- do_checks = 0;
- } else { /* Do check for SOA right now */
- if (knot_node_rrset(knot_zone_contents_apex(zone),
- KNOT_RRTYPE_SOA) == NULL) {
- err_handler_handle_error(handler,
- knot_zone_contents_apex(zone),
- ZC_ERR_MISSING_SOA);
- }
+
+ err_handler_t *handler = handler_new(1, 1, 1, 1, 1);
+ if (handler == NULL) {
+ return KNOT_ENOMEM;
+ } else { /* Do check for SOA right now */
+ if (knot_node_rrset(knot_zone_contents_apex(zone),
+ KNOT_RRTYPE_SOA) == NULL) {
+ err_handler_handle_error(handler,
+ knot_zone_contents_apex(zone),
+ ZC_ERR_MISSING_SOA);
}
-
- knot_node_t *last_node = NULL;
-
- zone_do_sem_checks(zone, do_checks, handler, &last_node);
- log_cyclic_errors_in_zone(handler, zone, last_node,
- first_nsec3_node, last_nsec3_node,
- do_checks);
- err_handler_log_all(handler);
- free(handler);
+ }
+
+ knot_node_t *last_node = NULL;
+ int ret = zone_do_sem_checks(zone,
+ do_checks, handler, &last_node);
+ log_cyclic_errors_in_zone(handler, zone, last_node,
+ first_nsec3_node, last_nsec3_node,
+ do_checks);
+ err_handler_log_all(handler);
+ free(handler);
+
+ if (ret != KNOT_EOK) {
+ fprintf(stderr, "Zone will not be dumped because of "
+ "fatal semantic errors.\n");
+ fclose(f);
+ close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
+ return KNOT_ERROR;
}
crc_t crc = crc_init();
@@ -671,6 +686,11 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
/* Write dname table. */
if (knot_dump_dname_table(zone->dname_table, f, &crc)
!= KNOT_EOK) {
+ fclose(f);
+ close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
return KNOT_ERROR;
}
@@ -693,6 +713,10 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
malloc(sizeof(char) * (strlen(filename) + strlen(".crc") + 1));
if (unlikely(!crc_path)) {
close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
+ free(crc_path);
return KNOT_ENOMEM;
}
memset(crc_path, 0,
@@ -705,6 +729,9 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
dbg_zload("knot_zload_open: failed to open '%s'\n",
crc_path);
close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
free(crc_path);
return ENOENT;
}
@@ -720,6 +747,10 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
fprintf(stderr, "%s\n", strerror(errno));
fprintf(stderr, "Could not open destination file! Use '%s' "
"file instead.\n", new_path);
+ close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
return KNOT_ERROR;
}
@@ -728,6 +759,9 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
fprintf(stderr, "Could not lock destination file for write! "
"Use '%s' file instead.\n", new_path);
close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
return KNOT_ERROR;
}
@@ -736,12 +770,19 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
fprintf(stderr, "Could not move to originally given file! "
"Use '%s' file instead.\n", new_path);
close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
return KNOT_ERROR;
}
/* Release the lock. */
if (fcntl(fd, F_SETLK, knot_file_lock(F_UNLCK, SEEK_SET)) == -1) {
fprintf(stderr, "Could not unlock destination file!\n");
+ close(fd);
+ /* If remove fails, there is nothing we can do. */
+ remove(new_path);
+ remove(knot_zdump_crc_file(filename));
return KNOT_ERROR;
}
@@ -767,21 +808,6 @@ int knot_zdump_rrset_serialize(const knot_rrset_t *rrset, uint8_t **stream,
return KNOT_EOK;
}
-static char *knot_zdump_crc_file(const char* filename)
-{
- char *crc_path =
- malloc(sizeof(char) * (strlen(filename) +
- strlen(".crc") + 1));
- CHECK_ALLOC_LOG(crc_path, NULL);
- memset(crc_path, 0,
- sizeof(char) * (strlen(filename) +
- strlen(".crc") + 1));
- memcpy(crc_path, filename,
- sizeof(char) * strlen(filename));
- crc_path = strcat(crc_path, ".crc");
- return crc_path;
-}
-
int knot_zdump_dump_and_swap(knot_zone_contents_t *zone,
const char *temp_zonedb,
const char *destination_zonedb,
diff --git a/src/knot/zone/zone-dump.h b/src/knot/zone/zone-dump.h
index daf6c18..97f1318 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', '0', '8', '0'}
+#define MAGIC_BYTES {'k', 'n', 'o', 't', '1', 'r', 'c'}
/*!
* \brief Dumps given zone to binary file.
@@ -84,6 +84,17 @@ int knot_zdump_rrset_serialize(const knot_rrset_t *rrset, uint8_t **stream,
int knot_zdump_rrset_serialize(const knot_rrset_t *rrset, uint8_t **stream,
size_t *size);
+/*!
+ * \brief Checks if zone uses DNSSEC and/or NSEC3
+ *
+ * \param zone Zone to be checked.
+ *
+ * \retval 0 if zone is not secured.
+ * \retval 2 if zone uses NSEC3
+ * \retval 1 if zone uses NSEC
+ */
+int zone_is_secure(knot_zone_contents_t *zone);
+
int knot_zdump_dump_and_swap(knot_zone_contents_t *zone,
const char *temp_zonedb,
const char *destination_zonedb,
diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c
index 9ab0e8d..5710fe9 100644
--- a/src/knot/zone/zone-load.c
+++ b/src/knot/zone/zone-load.c
@@ -310,7 +310,7 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
} else if (use_ids && !in_the_zone) { /* destroy the node */
if (id_array[dname_id]->node != NULL) {
knot_node_free(&id_array[dname_id]->
- node, 0, 0);
+ node, 0);
}
/* Also sets node to NULL! */
}
@@ -571,7 +571,7 @@ static knot_node_t *knot_load_node(FILE *f, knot_dname_t **id_array)
if (parent_id != 0) {
knot_node_set_parent(node, id_array[parent_id]->node);
- assert(knot_node_parent(node, 0) != NULL);
+ assert(knot_node_parent(node) != NULL);
} else {
knot_node_set_parent(node, NULL);
}
@@ -580,7 +580,7 @@ static knot_node_t *knot_load_node(FILE *f, knot_dname_t **id_array)
for (int i = 0; i < rrset_count; i++) {
if ((tmp_rrset = knot_load_rrset(f, id_array, 1)) == NULL) {
- knot_node_free(&node, 1, 0);
+ knot_node_free(&node, 0);
//TODO what else to free?
fprintf(stderr, "zone: Could not load rrset.\n");
return NULL;
@@ -611,7 +611,6 @@ static void find_and_set_wildcard_child(knot_zone_contents_t *zone,
knot_node_t *node, int nsec3)
{
knot_dname_t *chopped = knot_dname_left_chop(node->owner);
- assert(chopped);
knot_node_t *wildcard_parent;
if (!nsec3) {
wildcard_parent =
@@ -1065,8 +1064,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
}
}
- assert(knot_node_previous(knot_zone_contents_apex(contents), 0)
- == NULL);
+ assert(knot_node_previous(knot_zone_contents_apex(contents)) == NULL);
knot_node_set_previous(knot_zone_contents_get_apex(contents),
last_node);
@@ -1120,7 +1118,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
}
if (nsec3_node_count) {
- assert(knot_node_previous(nsec3_first, 0) == NULL);
+ assert(knot_node_previous(nsec3_first) == NULL);
knot_node_set_previous(nsec3_first, last_node);
/* CLEANUP */
// nsec3_first->prev = last_node;
@@ -1134,6 +1132,13 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
free(id_array);
dbg_zload("zone loaded, returning: %p\n", zone);
+
+// knot_zone_contents_integrity_check(zone->contents);
+
+ //knot_dname_table_dump(zone->contents->dname_table);
+
+ //knot_zone_contents_dump(zone->contents);
+
return zone;
}
diff --git a/src/libknot/dname.c b/src/libknot/dname.c
index 869b342..e4b7d5f 100644
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -408,8 +408,8 @@ knot_dname_t *knot_dname_new_from_str(const char *name, uint size,
dbg_dname("\n");
if (dname->size <= 0) {
- fprintf(stderr, "Could not parse domain name "
- "from string: '%.*s'\n", size, name);
+ dbg_dname("Could not parse domain name "
+ "from string: '%.*s'\n", size, name);
}
assert(dname->name != NULL);
@@ -491,6 +491,10 @@ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire,
int pointer_used = 0;
while (p < size && wire[p] != 0) {
+ /* Check maximum number of labels (may overflow). */
+ if (l == KNOT_MAX_DNAME_LABELS) {
+ return NULL;
+ }
labels[l] = i;
dbg_dname("Next label (%d.) position: %zu\n", l, i);
@@ -508,7 +512,15 @@ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire,
} else {
// label; first byte is label length
uint8_t length = *(wire + p);
-// printf("Label, length: %u.\n", length);
+ /* Check label length (maximum 63 bytes allowed). */
+ if (length > 63) {
+ return NULL;
+ }
+ /* Check if there's enough space. */
+ if (i + length + 2 > KNOT_MAX_DNAME_LENGTH) {
+ return NULL;
+ }
+ //printf("Label %d (max %d), length: %u.\n", l, KNOT_MAX_DNAME_LABELS, length);
memcpy(name + i, wire + p, length + 1);
p += length + 1;
i += length + 1;
@@ -693,27 +705,20 @@ uint8_t knot_dname_size_part(const knot_dname_t *dname, int labels)
/*----------------------------------------------------------------------------*/
-const struct knot_node *knot_dname_node(const knot_dname_t *dname,
- int check_version)
+const struct knot_node *knot_dname_node(const knot_dname_t *dname)
{
- if (check_version) {
- return knot_node_current(dname->node);
- } else {
- return dname->node;
- }
+ return knot_dname_get_node(dname);
}
/*----------------------------------------------------------------------------*/
-struct knot_node *knot_dname_get_node(knot_dname_t *dname,
- int check_version)
+struct knot_node *knot_dname_get_node(const knot_dname_t *dname)
{
- if (check_version) {
- return knot_node_get_current(dname->node);
- } else {
- return dname->node;
+ if (dname == NULL) {
+ return NULL;
}
+ return dname->node;
}
/*----------------------------------------------------------------------------*/
@@ -741,10 +746,42 @@ int knot_dname_is_fqdn(const knot_dname_t *dname)
knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname)
{
+ if (dname == NULL ||
+ /* Root domain. */
+ ((knot_dname_label_count(dname) == 0) &&
+ (knot_dname_is_fqdn(dname)))) {
+ return NULL;
+ }
+
knot_dname_t *parent = knot_dname_new();
if (parent == NULL) {
return NULL;
}
+
+ // last label, the result should be root domain
+ if (dname->label_count == 1) {
+ dbg_dname_verb("Chopping last label.\n");
+ parent->label_count = 0;
+
+ parent->name = (uint8_t *)malloc(1);
+ if (parent->name == NULL) {
+ ERR_ALLOC_FAILED;
+ knot_dname_free(&parent);
+ return NULL;
+ }
+
+ *parent->name = 0;
+
+ parent->size = 1;
+
+ return parent;
+ }
+
+// if (dname->label_count <= 1) {
+// /* Nothing to chop. */
+// return NULL;
+// }
+
parent->size = dname->size - dname->name[0] - 1;
parent->name = (uint8_t *)malloc(parent->size);
@@ -763,6 +800,7 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname)
}
memcpy(parent->name, &dname->name[dname->name[0] + 1], parent->size);
+
short first_label_length = dname->labels[1];
diff --git a/src/libknot/dname.h b/src/libknot/dname.h
index 9efcffe..bb5e2db 100644
--- a/src/libknot/dname.h
+++ b/src/libknot/dname.h
@@ -215,11 +215,9 @@ uint8_t knot_dname_size_part(const knot_dname_t *dname, int labels);
*
* \return Zone node the domain name belongs to or NULL if none.
*/
-const struct knot_node *knot_dname_node(const knot_dname_t *dname,
- int check_version);
+const struct knot_node *knot_dname_node(const knot_dname_t *dname);
-struct knot_node *knot_dname_get_node(knot_dname_t *dname,
- int check_version);
+struct knot_node *knot_dname_get_node(const knot_dname_t *dname);
void knot_dname_set_node(knot_dname_t *dname, struct knot_node *node);
diff --git a/src/libknot/edns.c b/src/libknot/edns.c
index 05ebd7b..435e27c 100644
--- a/src/libknot/edns.c
+++ b/src/libknot/edns.c
@@ -32,9 +32,6 @@ enum knot_edns_consts {
KNOT_EDNS_OPTION_STEP = 1
};
-/*! \brief Minimum size of EDNS OPT RR in wire format. */
-static const short KNOT_EDNS_MIN_SIZE = 11;
-
/*----------------------------------------------------------------------------*/
knot_opt_rr_t *knot_edns_new()
@@ -42,6 +39,7 @@ knot_opt_rr_t *knot_edns_new()
knot_opt_rr_t *opt_rr = (knot_opt_rr_t *)malloc(
sizeof(knot_opt_rr_t));
CHECK_ALLOC_LOG(opt_rr, NULL);
+ memset(opt_rr, 0, sizeof(knot_opt_rr_t));
opt_rr->size = KNOT_EDNS_MIN_SIZE;
opt_rr->option_count = 0;
opt_rr->options_max = 0;
@@ -174,15 +172,16 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
// i.e. preceded by their length
if (rdata != NULL) {
assert(knot_rdata_item_count(rdata) == 1);
+ uint16_t size = knot_rdata_item(rdata, 0)->raw_data[0];
const uint8_t *raw = (const uint8_t *)
knot_rdata_item(rdata, 0)->raw_data;
- uint16_t size = knot_wire_read_u16(raw);
int pos = 2;
assert(size > 0);
while (pos - 2 < size) {
// ensure there is enough data to parse the OPTION CODE
// and OPTION LENGTH
if (size - pos + 2 < 4) {
+ dbg_edns("Not enough data to parse.\n");
return KNOT_EMALF;
}
uint16_t opt_code = knot_wire_read_u16(raw + pos);
@@ -191,16 +190,23 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
// there should be enough data for parsing the OPTION
// data
if (size - pos - 2 < opt_size) {
+ dbg_edns("Not enough data to parse options: "
+ "size - pos - 2=%d, opt_size=%d\n",
+ size - pos - 2, opt_size);
return KNOT_EMALF;
}
rc = knot_edns_add_option(opt_rr, opt_code, opt_size,
raw + pos + 4);
if (rc != KNOT_EOK) {
+ dbg_edns("Could not add option.\n");
return rc;
}
pos += 4 + opt_size;
}
}
+
+
+ dbg_edns("EDNS created.\n");
return KNOT_EOK;
}
@@ -302,8 +308,11 @@ int knot_edns_add_option(knot_opt_rr_t *opt_rr, uint16_t code,
sizeof(knot_opt_option_t));
CHECK_ALLOC_LOG(options_new, KNOT_ENOMEM);
memcpy(options_new, opt_rr->options, opt_rr->option_count);
+
+ knot_opt_option_t *old_options = opt_rr->options;
opt_rr->options = options_new;
opt_rr->options_max += KNOT_EDNS_OPTION_STEP;
+ free(old_options);
}
dbg_edns("Adding option.\n");
@@ -359,6 +368,11 @@ short knot_edns_to_wire(const knot_opt_rr_t *opt_rr, uint8_t *wire,
}
uint8_t *pos = wire;
+
+ dbg_edns_detail("Putting OPT RR to the wire format. Size: %zu, "
+ "position: %zu\n",
+ opt_rr->size, (size_t)(pos - wire));
+
*(pos++) = 0;
knot_wire_write_u16(pos, KNOT_RRTYPE_OPT);
pos += 2;
@@ -369,12 +383,17 @@ short knot_edns_to_wire(const knot_opt_rr_t *opt_rr, uint8_t *wire,
knot_wire_write_u16(pos, opt_rr->flags);
pos += 2;
+ dbg_edns_detail("Leaving space for RDLENGTH at pos %zu\n",
+ (size_t)(pos - wire));
+
uint8_t *rdlen = pos;
uint16_t len = 0;
pos += 2;
// OPTIONs
for (int i = 0; i < opt_rr->option_count; ++i) {
+ dbg_edns_detail("Inserting option #%d at pos %zu\n",
+ i, (size_t)(pos - wire));
knot_wire_write_u16(pos, opt_rr->options[i].code);
pos += 2;
knot_wire_write_u16(pos, opt_rr->options[i].length);
@@ -384,6 +403,8 @@ short knot_edns_to_wire(const knot_opt_rr_t *opt_rr, uint8_t *wire,
len += 4 + opt_rr->options[i].length;
}
+ dbg_edns_detail("Final pos %zu\n", (size_t)(pos - wire));
+
knot_wire_write_u16(rdlen, len);
return opt_rr->size;
@@ -402,15 +423,30 @@ short knot_edns_size(knot_opt_rr_t *opt_rr)
/*----------------------------------------------------------------------------*/
+void knot_edns_free_options(knot_opt_rr_t *opt_rr)
+{
+ if (opt_rr->option_count > 0) {
+ /* Free the option data, if any. */
+ for (int i = 0; i < opt_rr->option_count; i++) {
+ struct knot_opt_option option = opt_rr->options[i];
+ if (option.data != NULL) {
+ free(option.data);
+ }
+ }
+ free(opt_rr->options);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
void knot_edns_free(knot_opt_rr_t **opt_rr)
{
if (opt_rr == NULL || *opt_rr == NULL) {
return;
}
- if ((*opt_rr)->option_count > 0) {
- free((*opt_rr)->options);
- }
+ knot_edns_free_options(*opt_rr);
+
free(*opt_rr);
*opt_rr = NULL;
}
diff --git a/src/libknot/edns.h b/src/libknot/edns.h
index 010d155..022ac36 100644
--- a/src/libknot/edns.h
+++ b/src/libknot/edns.h
@@ -81,6 +81,9 @@ enum knot_edns_option_codes {
EDNS_OPTION_NSID = (uint16_t)3 /*!< NSID option code. */
};
+/*! \brief Minimum size of EDNS OPT RR in wire format. */
+static const short KNOT_EDNS_MIN_SIZE = 11;
+
/*----------------------------------------------------------------------------*/
/*!
* \brief Creates new empty OPT RR structure for holding EDNS parameters.
@@ -261,6 +264,8 @@ short knot_edns_to_wire(const knot_opt_rr_t *opt_rr, uint8_t *wire,
*/
short knot_edns_size(knot_opt_rr_t *opt_rr);
+void knot_edns_free_options(knot_opt_rr_t *opt_rr);
+
/*!
* \brief Properly destroys the OPT RR structure.
*
diff --git a/src/libknot/hash/cuckoo-hash-table.c b/src/libknot/hash/cuckoo-hash-table.c
index c5d1c4f..6688a40 100644
--- a/src/libknot/hash/cuckoo-hash-table.c
+++ b/src/libknot/hash/cuckoo-hash-table.c
@@ -379,6 +379,8 @@ static uint ck_check_used_twice(da_array_t *used, uint32_t hash)
static inline uint ck_items_match(const ck_hash_table_item_t *item,
const char *key, size_t length)
{
+ assert(item != NULL);
+
return (length == item->key_length
&& (strncmp(item->key, key, length) == 0));
}
@@ -414,7 +416,13 @@ static ck_hash_table_item_t **ck_find_in_stash(const ck_hash_table_t *table,
"with searched item (key %.*s (size %u)).\n",
(int)item->item->key_length, item->item->key,
item->item->key_length, (int)length, key, length);
- if (ck_items_match(item->item, key, length)) {
+ /*! \todo Can the item be NULL?
+ * Sometimes it crashed on assert in ck_items_match(),
+ * But I'm not sure if this may happen or if the
+ * semantics of the stash are that all items must be
+ * non-NULL.
+ */
+ if (item->item && ck_items_match(item->item, key, length)) {
return &item->item;
}
item = item->next;
@@ -1137,7 +1145,7 @@ int ck_shallow_copy(const ck_hash_table_t *from, ck_hash_table_t **to)
// copy the ck_hash_table_item_t within them.
ck_stash_item_t *si = from->stash;
ck_stash_item_t **pos = &(*to)->stash;
- dbg_ck_verb(stderr, "Copying hash table stash.\n");
+ dbg_ck_verb("Copying hash table stash.\n");
while (si != NULL) {
ck_stash_item_t *si_new = (ck_stash_item_t *)
malloc(sizeof(ck_stash_item_t));
@@ -1202,7 +1210,182 @@ int ck_shallow_copy(const ck_hash_table_t *from, ck_hash_table_t **to)
/*----------------------------------------------------------------------------*/
-int ck_apply(ck_hash_table_t *table,
+static int ck_copy_items(ck_hash_table_item_t **from,
+ ck_hash_table_item_t **to, uint32_t count)
+{
+ assert(from != NULL);
+ assert(to != NULL);
+
+ for (int i = 0; i < count; ++i) {
+ if (from[i] != NULL) {
+ to[i] = (ck_hash_table_item_t *)
+ malloc(sizeof(ck_hash_table_item_t));
+
+ if (to[i] == NULL) {
+ return -2;
+ }
+
+ memcpy(to[i], from[i], sizeof(ck_hash_table_item_t));
+ } else {
+ to[i] = NULL;
+ }
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void ck_deep_copy_cleanup(ck_hash_table_t *table, int table_count)
+{
+ // free tables with their items
+ for (int t = 0; t < table_count; ++t) {
+ for (int i = 0; i < hashsize(table->table_size_exp); ++i) {
+ free(table->tables[t][i]);
+ }
+ free(table->tables[t]);
+ }
+
+ // free stash items with hash table items in them
+ ck_stash_item_t *si = table->stash;
+ ck_stash_item_t *to_free;
+ while (si != NULL) {
+ to_free = si;
+ si = si->next;
+ free(to_free->item);
+ free(to_free);
+ }
+
+ free(table);
+}
+
+/*----------------------------------------------------------------------------*/
+
+int ck_deep_copy(ck_hash_table_t *from, ck_hash_table_t **to)
+{
+ if (from == NULL || to == NULL) {
+ return -1;
+ }
+
+ dbg_ck("Allocating new table...\n");
+ *to = (ck_hash_table_t *)malloc(sizeof(ck_hash_table_t));
+
+ if (*to == NULL) {
+ ERR_ALLOC_FAILED;
+ return -2;
+ }
+ memset(*to, 0, sizeof(ck_hash_table_t));
+
+ // copy table count and table size exponent
+ (*to)->table_size_exp = from->table_size_exp;
+ (*to)->table_count = from->table_count;
+ assert((*to)->table_size_exp <= 32);
+
+ dbg_ck("Creating hash table for %u items.\n", from->table_count);
+ dbg_ck("Exponent: %u, number of tables: %u\n ",
+ (*to)->table_size_exp, (*to)->table_count);
+ dbg_ck("Table size: %u items, each %zu bytes, total %zu bytes\n",
+ hashsize((*to)->table_size_exp),
+ sizeof(ck_hash_table_item_t *),
+ hashsize((*to)->table_size_exp)
+ * sizeof(ck_hash_table_item_t *));
+
+ // create tables
+ for (uint t = 0; t < (*to)->table_count; ++t) {
+ dbg_ck("Creating table %u...\n", t);
+ (*to)->tables[t] = (ck_hash_table_item_t **)malloc(
+ hashsize((*to)->table_size_exp)
+ * sizeof(ck_hash_table_item_t *));
+ if ((*to)->tables[t] == NULL) {
+ ERR_ALLOC_FAILED;
+ for (uint i = 0; i < t; ++i) {
+ free((*to)->tables[i]);
+ }
+ free(*to);
+ return -2;
+ }
+
+ // copy the table with all hash table items
+ dbg_ck("Copying table %u...\n", t);
+ int ret = ck_copy_items(from->tables[t], (*to)->tables[t],
+ hashsize((*to)->table_size_exp));
+ if (ret != 0) {
+ dbg_ck("Failed!\n");
+ // free all tables created until now
+ ck_deep_copy_cleanup(*to, t);
+ return ret;
+ }
+ }
+
+ // copy the stash - we must explicitly copy each stash item,
+ // together with the hash table item stored in it
+ ck_stash_item_t *si = from->stash;
+ ck_stash_item_t **pos = &(*to)->stash;
+ dbg_ck_verb("Copying hash table stash.\n");
+ while (si != NULL) {
+ ck_stash_item_t *si_new = (ck_stash_item_t *)
+ malloc(sizeof(ck_stash_item_t));
+ if (si_new == NULL) {
+ ERR_ALLOC_FAILED;
+ ck_deep_copy_cleanup(*to, (*to)->table_count);
+ return -2;
+ }
+
+ dbg_ck("Copying stash item: %p with item %p, ", si, si->item);
+ dbg_ck("key: %.*s\n", (int)si->item->key_length, si->item->key);
+
+ si_new->item = (ck_hash_table_item_t *)
+ malloc(sizeof(ck_hash_table_item_t));
+
+ if (si_new->item == NULL) {
+ ERR_ALLOC_FAILED;
+ ck_deep_copy_cleanup(*to, (*to)->table_count);
+ return -2;
+ }
+
+ memcpy(si_new->item, si->item, sizeof(ck_hash_table_item_t));
+
+ *pos = si_new;
+ pos = &si_new->next;
+ si = si->next;
+
+
+ dbg_ck("Old stash item: %p with item %p, ", si,
+ ((si == NULL) ? NULL : si->item));
+ if (si != NULL) {
+ dbg_ck("key: %.*s\n", (int)si->item->key_length, si->item->key);
+ } else {
+ dbg_ck("\n");
+ }
+ dbg_ck("New stash item: %p with item %p, ", si_new,
+ si_new->item);
+ dbg_ck("key: %.*s\n", (int)si_new->item->key_length,
+ si_new->item->key);
+ }
+
+ *pos = NULL;
+
+ // there should be no item being hashed right now
+ /*! \todo This operation should not be done while inserting / rehashing.
+ */
+ assert(from->hashed == NULL);
+ (*to)->hashed = NULL;
+
+ // initialize rehash/insert mutex
+ pthread_mutex_init(&(*to)->mtx_table, NULL);
+
+ // copy the generation
+ (*to)->generation = from->generation;
+
+ // copy the hash functions
+ memcpy(&(*to)->hash_system, &from->hash_system, sizeof(us_system_t));
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int ck_apply(ck_hash_table_t *table,
void (*function)(ck_hash_table_item_t *item, void *data),
void *data)
{
diff --git a/src/libknot/hash/cuckoo-hash-table.h b/src/libknot/hash/cuckoo-hash-table.h
index dd78294..eaa6a89 100644
--- a/src/libknot/hash/cuckoo-hash-table.h
+++ b/src/libknot/hash/cuckoo-hash-table.h
@@ -309,6 +309,8 @@ ck_hash_table_item_t *ck_remove_item(ck_hash_table_t *table, const char *key,
*/
int ck_shallow_copy(const ck_hash_table_t *from, ck_hash_table_t **to);
+int ck_deep_copy(ck_hash_table_t *from, ck_hash_table_t **to);
+
int ck_apply(ck_hash_table_t *table,
void (*function)(ck_hash_table_item_t *item, void *data),
void *data);
diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c
index a4e4ae7..547a629 100644
--- a/src/libknot/nameserver/name-server.c
+++ b/src/libknot/nameserver/name-server.c
@@ -98,6 +98,11 @@ static const knot_zone_t *ns_get_zone_for_qname(knot_zonedb_t *zdb,
zone = knot_zonedb_find_zone_for_name(zdb, name);
/* Directly discard. */
knot_dname_free(&name);
+ /* If zone does not exist, search for its parent zone,
+ this will later result to NODATA answer. */
+ if (zone == NULL) {
+ zone = knot_zonedb_find_zone_for_name(zdb, qname);
+ }
} else {
zone = knot_zonedb_find_zone_for_name(zdb, qname);
}
@@ -148,7 +153,7 @@ static knot_rrset_t *ns_synth_from_wildcard(
// but there is no way to distinguish it when deleting
// temporary RRSets
knot_rdata_t *rdata_copy = knot_rdata_deep_copy(rdata,
- knot_rrset_type(synth_rrset));
+ knot_rrset_type(synth_rrset), 0);
if (rdata_copy == NULL) {
knot_rrset_deep_free(&synth_rrset, 1, 1, 0);
return NULL;
@@ -312,7 +317,7 @@ dbg_ns_exec(
knot_rrset_rdata(cname_rrset));
dbg_ns("CNAME name from RDATA: %p\n", cname);
// change the node to the node of that name
- *node = knot_dname_node(cname, 1);
+ *node = knot_dname_node(cname);
dbg_ns("This name's node: %p\n", *node);
// // it is not an old node and if yes, skip it
// if (knot_node_is_old(*node)) {
@@ -470,24 +475,22 @@ static void ns_put_additional_for_rrset(knot_packet_t *resp,
while (rdata != NULL) {
dbg_ns("Getting name from RDATA, type %s..\n",
knot_rrtype_to_string(knot_rrset_type(rrset)));
- dname = knot_rdata_get_name(rdata,
- knot_rrset_type(rrset));
+ dname = knot_rdata_get_name(rdata, knot_rrset_type(rrset));
assert(dname != NULL);
- node = knot_dname_node(dname, 1);
-// // check if the node is not old and if yes, take the new one
-// if (knot_node_is_old(node)) {
-// node = knot_node_new_node(node);
-// }
+ node = knot_dname_node(dname);
- dbg_ns_detail("Node saved in RDATA dname: %p\n", node);
+// dbg_ns_detail("Node saved in RDATA dname: %p\n", node);
+// char *name = knot_dname_to_str(dname);
+// dbg_ns_detail("Owner of the node: %p, dname: %p (%s)\n",
+// node->owner, dname, name);
+// free(name);
+// knot_node_dump((knot_node_t *)node, (void *)1);
if (node != NULL && node->owner != dname) {
// the stored node should be the closest encloser
assert(knot_dname_is_subdomain(dname, node->owner));
// try the wildcard child, if any
- node = knot_node_wildcard_child(node, 1);
-// // this should not be old node!!
-// assert(!knot_node_is_old(node));
+ node = knot_node_wildcard_child(node);
}
knot_rrset_t *rrset_add;
@@ -731,10 +734,10 @@ static int ns_put_covering_nsec3(const knot_zone_contents_t *zone,
const knot_node_t *prev, *node;
/*! \todo Check version. */
int match = knot_zone_contents_find_nsec3_for_name(zone, name,
- &node, &prev, 1);
+ &node, &prev);
assert(match >= 0);
- node = knot_node_current(node);
- prev = knot_node_current(prev);
+// node = knot_node_current(node);
+// prev = knot_node_current(prev);
if (match == KNOT_ZONE_NAME_FOUND){
// run-time collision => SERVFAIL
@@ -811,10 +814,10 @@ dbg_ns_exec(
*/
const knot_node_t *nsec3_node = NULL;
const knot_dname_t *next_closer = NULL;
- while ((nsec3_node = knot_node_nsec3_node((*closest_encloser), 1))
+ while ((nsec3_node = knot_node_nsec3_node((*closest_encloser)))
== NULL) {
next_closer = knot_node_owner((*closest_encloser));
- *closest_encloser = knot_node_parent(*closest_encloser, 1);
+ *closest_encloser = knot_node_parent(*closest_encloser);
if (*closest_encloser == NULL) {
// there are no NSEC3s to add
return KNOT_EOK;
@@ -957,7 +960,7 @@ static void ns_put_nsec_nsec3_nodata(const knot_node_t *node,
return;
}
- knot_node_t *nsec3_node = knot_node_get_nsec3_node(node, 1);
+ knot_node_t *nsec3_node = knot_node_get_nsec3_node(node);
knot_rrset_t *rrset = NULL;
if ((rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NSEC)) != NULL
|| (nsec3_node != NULL && (rrset =
@@ -1001,13 +1004,11 @@ static int ns_put_nsec_nxdomain(const knot_dname_t *qname,
if (previous == NULL) {
/*! \todo Check version. */
previous = knot_zone_contents_find_previous(zone, qname);
+ assert(previous != NULL);
while (!knot_node_is_auth(previous)) {
- previous = knot_node_previous(previous, 1);
+ previous = knot_node_previous(previous);
}
-
- previous = knot_node_current(previous);
- assert(previous != NULL);
}
char *name = knot_dname_to_str(previous->owner);
@@ -1044,16 +1045,22 @@ static int ns_put_nsec_nxdomain(const knot_dname_t *qname,
while (knot_dname_compare(knot_node_owner(prev_new),
wildcard) > 0) {
- dbg_ns("Previous node: %s\n",
- knot_dname_to_str(knot_node_owner(prev_new)));
+dbg_ns_exec(
+ char *name = knot_dname_to_str(knot_node_owner(prev_new));
+ dbg_ns("Previous node: %s\n", name);
+ free(name);
+);
assert(prev_new != knot_zone_contents_apex(zone));
- prev_new = knot_node_previous(prev_new, 1);
+ prev_new = knot_node_previous(prev_new);
}
assert(knot_dname_compare(knot_node_owner(prev_new),
wildcard) < 0);
- dbg_ns("Previous node: %s\n",
- knot_dname_to_str(knot_node_owner(prev_new)));
+dbg_ns_exec(
+ char *name = knot_dname_to_str(knot_node_owner(prev_new));
+ dbg_ns("Previous node: %s\n", name);
+ free(name);
+);
/* Directly discard dname. */
knot_dname_free(&wildcard);
@@ -1226,13 +1233,11 @@ static void ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
// check if we have previous; if not, find one using the tree
if (previous == NULL) {
previous = knot_zone_contents_find_previous(zone, qname);
+ assert(previous != NULL);
while (!knot_node_is_auth(previous)) {
- previous = knot_node_previous(previous, 1);
+ previous = knot_node_previous(previous);
}
-
- previous = knot_node_current(previous);
- assert(previous != NULL);
}
knot_rrset_t *rrset =
@@ -1280,7 +1285,7 @@ static int ns_put_nsec_nsec3_wildcard_nodata(const knot_node_t *node,
const knot_node_t *nsec3_node;
if (ret == KNOT_EOK
- && (nsec3_node = knot_node_nsec3_node(node, 1))
+ && (nsec3_node = knot_node_nsec3_node(node))
!= NULL) {
ns_put_nsec3_from_node(nsec3_node, resp);
}
@@ -1350,21 +1355,59 @@ static int ns_put_nsec_nsec3_wildcard_answer(const knot_node_t *node,
static inline int ns_referral(const knot_node_t *node,
const knot_zone_contents_t *zone,
const knot_dname_t *qname,
- knot_packet_t *resp)
+ knot_packet_t *resp,
+ uint16_t qtype)
{
dbg_ns("Referral response.\n");
while (!knot_node_is_deleg_point(node)) {
- assert(knot_node_parent(node, 1) != NULL);
- node = knot_node_parent(node, 1);
+ assert(knot_node_parent(node) != NULL);
+ node = knot_node_parent(node);
}
+ // Special handling of DS queries
+ if (qtype == KNOT_RRTYPE_DS) {
+ knot_rrset_t *ds_rrset = knot_node_get_rrset(node,
+ KNOT_RRTYPE_DS);
+ int ret = KNOT_EOK;
+
+ if (ds_rrset) {
+ knot_response_add_rrset_answer(resp, ds_rrset, 1, 0,
+ 0, 1);
+ if (DNSSEC_ENABLED
+ && knot_query_dnssec_requested(
+ knot_packet_query(resp))) {
+ ns_add_rrsigs(ds_rrset, resp, node->owner,
+ knot_response_add_rrset_authority,
+ 1);
+ }
+ } else {
+ // normal NODATA response
+ /*! \todo Handle in some generic way. */
+
+ dbg_ns("Adding NSEC/NSEC3 for NODATA.\n");
+ ns_put_nsec_nsec3_nodata(node, resp);
+
+ // wildcard delegations not supported!
+// if (knot_dname_is_wildcard(node->owner)) {
+// dbg_ns("Putting NSEC/NSEC3 for wildcard"
+// " NODATA\n");
+// ret = ns_put_nsec_nsec3_wildcard_nodata(node,
+// closest_encloser, previous, zone, qname,
+// resp);
+// }
+ ns_put_authority_soa(zone, resp);
+ }
+
+ return ret;
+ }
+
knot_rrset_t *rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NS);
assert(rrset != NULL);
// TODO: wildcards??
//ns_check_wildcard(name, resp, &rrset);
-
+
knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
ns_add_rrsigs(rrset, resp, node->owner,
knot_response_add_rrset_authority, 1);
@@ -1387,7 +1430,7 @@ static inline int ns_referral(const knot_node_t *node,
// if NSEC3 enabled, search for NSEC3
if (knot_zone_contents_nsec3_enabled(zone)) {
const knot_node_t *nsec3_node =
- knot_node_nsec3_node(node, 1);
+ knot_node_nsec3_node(node);
dbg_ns("There is no DS, putting NSEC3s...\n");
if (nsec3_node != NULL) {
dbg_ns("Putting NSEC3s from the node.\n");
@@ -1406,7 +1449,7 @@ static inline int ns_referral(const knot_node_t *node,
/*! \todo Check return value? */
knot_response_add_rrset_authority(
resp, nsec, 1, 1, 0, 1);
- if ((nsec = knot_rrset_rrsigs(nsec)) != NULL) {
+ if ((nsec = knot_rrset_get_rrsigs(nsec)) != NULL) {
knot_response_add_rrset_authority(
resp, nsec, 1, 1, 0, 1);
}
@@ -1465,7 +1508,7 @@ static int ns_answer_from_node(const knot_node_t *node,
//assert(knot_node_rrset_count(closest_encloser) > 0);
dbg_ns("Adding NSEC/NSEC3 for NXDOMAIN.\n");
ret = ns_put_nsec_nsec3_nxdomain(zone,
- knot_node_previous(node, 1), closest_encloser,
+ knot_node_previous(node), closest_encloser,
qname, resp);
} else {
dbg_ns("Adding NSEC/NSEC3 for NODATA.\n");
@@ -1725,7 +1768,7 @@ have_node:
if (knot_node_is_deleg_point(closest_encloser)
|| knot_node_is_non_auth(closest_encloser)) {
- ret = ns_referral(closest_encloser, zone, qname, resp);
+ ret = ns_referral(closest_encloser, zone, qname, resp, qtype);
goto finalize;
}
@@ -1741,7 +1784,7 @@ have_node:
}
// else check for a wildcard child
const knot_node_t *wildcard_node =
- knot_node_wildcard_child(closest_encloser, 1);
+ knot_node_wildcard_child(closest_encloser);
if (wildcard_node == NULL) {
dbg_ns("No wildcard node. (cname: %d)\n",
@@ -1769,7 +1812,7 @@ have_node:
// now we have the node for answering
if (knot_node_is_deleg_point(node) || knot_node_is_non_auth(node)) {
- ret = ns_referral(node, zone, qname, resp);
+ ret = ns_referral(node, zone, qname, resp, qtype);
goto finalize;
}
@@ -1974,7 +2017,15 @@ static int ns_error_response_to_wire(knot_packet_t *resp, uint8_t *wire,
/*! \todo Why is this copied?? Why we cannot use resp->wireformat?? */
memcpy(wire, rwire, rsize);
- *wire_size = rsize;
+ if (resp->opt_rr.version != EDNS_NOT_SUPPORTED) {
+ short edns_size = knot_edns_to_wire(&resp->opt_rr, wire + rsize,
+ *wire_size - rsize);
+ if (edns_size > 0) {
+ *wire_size = rsize + edns_size;
+ }
+ } else {
+ *wire_size = rsize;
+ }
return KNOT_EOK;
}
@@ -2465,7 +2516,9 @@ static int ns_ixfr(knot_ns_xfr_t *xfr)
dbg_ns("IXFR query does not contain authority record.\n");
knot_response_set_rcode(xfr->response, KNOT_RCODE_FORMERR);
/*! \todo Probably rename the function. */
- ns_xfr_send_and_clear(xfr, 1);
+ if (ns_xfr_send_and_clear(xfr, 1) == KNOT_ECONN) {
+ return KNOT_ECONN;
+ }
//socket_close(xfr->session);
return KNOT_EMALF;
}
@@ -2481,7 +2534,9 @@ static int ns_ixfr(knot_ns_xfr_t *xfr)
dbg_ns("IXFR query is malformed.\n");
knot_response_set_rcode(xfr->response, KNOT_RCODE_FORMERR);
/*! \todo Probably rename the function. */
- ns_xfr_send_and_clear(xfr, 1);
+ if (ns_xfr_send_and_clear(xfr, 1) == KNOT_ECONN) {
+ return KNOT_ECONN;
+ }
//socket_close(xfr->session); /*! \todo Remove for UDP. */
return KNOT_EMALF;
}
@@ -2635,6 +2690,30 @@ knot_nameserver_t *knot_ns_create()
/*----------------------------------------------------------------------------*/
+void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid, size_t len)
+{
+ if (nameserver == NULL) {
+ dbg_ns("NS: set_nsid: nameserver=NULL.\n");
+ return;
+ }
+
+ if (nsid == NULL) {
+ /* This is fine. */
+ return;
+ }
+
+ int ret = knot_edns_add_option(nameserver->opt_rr, EDNS_OPTION_NSID,
+ len, (const uint8_t *)nsid);
+ if (ret != KNOT_EOK) {
+ dbg_ns("NS: set_nsid: could not add EDNS option.\n");
+ return;
+ }
+
+ dbg_ns("NS: set_nsid: added successfully.\n");
+}
+
+/*----------------------------------------------------------------------------*/
+
int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
knot_packet_t *packet, knot_packet_type_t *type)
{
@@ -2820,7 +2899,8 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
// set the OPT RR to the response
if (knot_query_edns_supported(query)) {
- ret = knot_response_add_opt(*resp, nameserver->opt_rr, 1);
+ ret = knot_response_add_opt(*resp, nameserver->opt_rr, 1,
+ knot_query_nsid_requested(query));
if (ret != KNOT_EOK) {
dbg_ns("Failed to set OPT RR to the response"
": %s\n", knot_strerror(ret));
@@ -3097,7 +3177,7 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
xfr->wire_size);
rcu_read_unlock();
knot_packet_free(&xfr->response);
- return KNOT_EOK;
+ return ret;
}
/*!
@@ -3119,7 +3199,7 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
* and when it does not. E.g. if there was problem in sending
* packet, it will probably fail when sending the SERVFAIL also.
*/
- if (ret < 0) {
+ if (ret < 0 && ret != KNOT_ECONN) {
dbg_ns("AXFR failed, sending SERVFAIL.\n");
// now only one type of error (SERVFAIL), later maybe more
/*! \todo xfr->wire is not NULL, will fail on assert! */
@@ -3137,7 +3217,7 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
knot_packet_free(&xfr->response);
- return KNOT_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -3226,24 +3306,44 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
knot_zone_contents_t *zone = constr_zone->contents;
assert(zone != NULL);
- dbg_ns("ns_process_axfrin: adjusting zone.\n");
- knot_zone_contents_adjust(zone, 0);
-
/* Create and fill hash table */
dbg_ns("ns_process_axfrin: filling hash table.\n");
int rc = knot_zone_contents_create_and_fill_hash_table(zone);
if (rc != KNOT_EOK) {
return KNOT_ERROR; // TODO: change error code
}
+
+ dbg_ns("ns_process_axfrin: adjusting zone.\n");
+ rc = knot_zone_contents_adjust(zone);
+ if (rc != KNOT_EOK) {
+ return rc;
+ }
+
+ dbg_ns("ns_process_axfrin: checking loops.\n");
+ rc = knot_zone_contents_check_loops(zone);
+ if (rc != KNOT_EOK) {
+ return rc;
+ }
// save the zone contents to the xfr->data
xfr->data = zone;
+ xfr->flags |= XFR_FLAG_AXFR_FINISHED;
+
+ assert(zone->nsec3_nodes != NULL);
// free the structure used for processing XFR
assert(constr_zone->rrsigs == NULL);
free(constr_zone);
//knot_zone_contents_dump(zone, 0);
+
+ // check zone integrity
+#ifdef KNOT_XFRIN_DEBUG
+#ifdef DEBUG_ENABLE_BRIEF
+ int errs = knot_zone_contents_integrity_check(zone);
+ dbg_ns("Zone integrity check: %d errors.\n", errs);
+#endif
+#endif
}
/*!
diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h
index 928d79c..3bf9552 100644
--- a/src/libknot/nameserver/name-server.h
+++ b/src/libknot/nameserver/name-server.h
@@ -81,9 +81,10 @@ typedef int (*xfr_callback_t)(int session, sockaddr_t *addr,
typedef struct knot_ns_xfr {
int type;
int flags;
- sockaddr_t addr;
+ sockaddr_t addr, saddr;
knot_packet_t *query;
knot_packet_t *response;
+ knot_rcode_t rcode;
xfr_callback_t send;
int session;
@@ -100,6 +101,7 @@ typedef struct knot_ns_xfr {
size_t wire_size;
void *data;
knot_zone_t *zone;
+ char* zname;
void *owner;
/*! \note [TSIG] TSIG fields */
@@ -148,7 +150,8 @@ static const size_t KNOT_NS_TSIG_DATA_MAX_SIZE = 100 * 64 * 1024;
*/
enum knot_ns_xfr_flag_t {
XFR_FLAG_TCP = 1 << 0, /*!< XFR request is on TCP. */
- XFR_FLAG_UDP = 1 << 1 /*!< XFR request is on UDP. */
+ XFR_FLAG_UDP = 1 << 1, /*!< XFR request is on UDP. */
+ XFR_FLAG_AXFR_FINISHED = 1 << 2
};
/*!
@@ -175,6 +178,10 @@ typedef enum knot_ns_xfr_type_t {
*/
knot_nameserver_t *knot_ns_create();
+/*! \todo Document me. */
+void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid,
+ size_t nsid_length);
+
/*!
* \brief Parses the given query into the response structure and recognizes
* type of the query.
diff --git a/src/libknot/packet/packet.c b/src/libknot/packet/packet.c
index 59c1a0d..6fc97b8 100644
--- a/src/libknot/packet/packet.c
+++ b/src/libknot/packet/packet.c
@@ -110,6 +110,7 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
dbg_packet("Compression offsets: %p\n", pkt->compression.offsets);
pkt->compression.max = DEFAULT_DOMAINS_IN_RESPONSE;
+ pkt->compression.default_count = DEFAULT_DOMAINS_IN_RESPONSE;
pkt->tmp_rrsets = (const knot_rrset_t **)pos;
pos += DEFAULT_TMP_RRSETS * sizeof(const knot_rrset_t *);
@@ -633,7 +634,7 @@ static void knot_packet_free_allocated_space(knot_packet_t *pkt)
free(pkt->additional);
}
- if (pkt->compression.max > DEFAULT_DOMAINS_IN_RESPONSE) {
+ if (pkt->compression.max > pkt->compression.default_count) {
free(pkt->compression.dnames);
free(pkt->compression.offsets);
}
@@ -1470,6 +1471,9 @@ void knot_packet_free(knot_packet_t **packet)
free((*packet)->wireformat);
}
+ // free EDNS options
+ knot_edns_free_options(&(*packet)->opt_rr);
+
dbg_packet("Freeing packet structure\n");
free(*packet);
*packet = NULL;
diff --git a/src/libknot/packet/packet.h b/src/libknot/packet/packet.h
index 81b1812..8f76ae2 100644
--- a/src/libknot/packet/packet.h
+++ b/src/libknot/packet/packet.h
@@ -48,6 +48,7 @@ struct knot_compressed_dnames {
size_t *offsets; /*!< Offsets of domain names in the packet. */
short count; /*!< Count of items in the previous arrays. */
short max; /*!< Capacity of the structure (allocated). */
+ short default_count;
};
typedef struct knot_compressed_dnames knot_compressed_dnames_t;
diff --git a/src/libknot/packet/query.c b/src/libknot/packet/query.c
index 63e902a..b76059b 100644
--- a/src/libknot/packet/query.c
+++ b/src/libknot/packet/query.c
@@ -207,6 +207,7 @@ int knot_query_add_rrset_authority(knot_packet_t *query,
assert(endp - startp > query->opt_rr.size + query->tsig_size);
// reserve space for OPT RR
+ /*! \todo Why here??? */
endp -= query->opt_rr.size;
/*! \note [TSIG] reserve space for TSIG RR */
endp -= query->tsig_size;
diff --git a/src/libknot/packet/response.c b/src/libknot/packet/response.c
index ed16e2f..c9f2ba7 100644
--- a/src/libknot/packet/response.c
+++ b/src/libknot/packet/response.c
@@ -23,6 +23,7 @@
#include "util/error.h"
#include "util/debug.h"
#include "packet/packet.h"
+#include "edns.h"
/*----------------------------------------------------------------------------*/
/*!
@@ -75,7 +76,7 @@ static const size_t KNOT_RESPONSE_MAX_PTR = 16383;
*/
static int knot_response_realloc_compr(knot_compressed_dnames_t *table)
{
- int free_old = table->max != DEFAULT_DOMAINS_IN_RESPONSE;
+ int free_old = table->max != table->default_count;
size_t *old_offsets = table->offsets;
const knot_dname_t **old_dnames = table->dnames;
@@ -233,10 +234,10 @@ dbg_response_exec(
// If case-sensitive search is in place, we should not save the
// node's parent's positions.
- to_save = !compr_cs && (knot_dname_node(to_save, 1) != NULL
- && knot_node_parent(knot_dname_node(to_save, 1), 1)
+ to_save = !compr_cs && (knot_dname_node(to_save) != NULL
+ && knot_node_parent(knot_dname_node(to_save))
!= NULL) ? knot_node_owner(knot_node_parent(
- knot_dname_node(to_save, 1), 1))
+ knot_dname_node(to_save)))
: NULL;
dbg_response("i: %d\n", i);
@@ -391,31 +392,31 @@ dbg_response_exec(
}
#else
// if case-sensitive comparation, we cannot just take the parent
- if (compr_cs || knot_dname_node(to_find, 1) == NULL
- || knot_node_owner(knot_dname_node(to_find, 1)) != to_find
- || knot_node_parent(knot_dname_node(to_find, 1), 1)
+ if (compr_cs || knot_dname_node(to_find) == NULL
+ || knot_node_owner(knot_dname_node(to_find)) != to_find
+ || knot_node_parent(knot_dname_node(to_find))
== NULL) {
dbg_response("compr_cs: %d\n", compr_cs);
dbg_response("knot_dname_node(to_find, 1) == %p"
- "\n", knot_dname_node(to_find, 1));
+ "\n", knot_dname_node(to_find));
- if (knot_dname_node(to_find, 1) != NULL) {
+ if (knot_dname_node(to_find) != NULL) {
dbg_response("knot_node_owner(knot_dname_node("
"to_find, 1)) = %p, to_find = %p\n",
- knot_node_owner(knot_dname_node(to_find, 1)),
+ knot_node_owner(knot_dname_node(to_find)),
to_find);
dbg_response("knot_node_parent(knot_dname_node("
"to_find, 1), 1) = %p\n",
- knot_node_parent(knot_dname_node(to_find, 1), 1));
+ knot_node_parent(knot_dname_node(to_find)));
}
break;
} else {
- assert(knot_dname_node(to_find, 1) !=
- knot_node_parent(knot_dname_node(to_find, 1), 1));
+ assert(knot_dname_node(to_find) !=
+ knot_node_parent(knot_dname_node(to_find)));
assert(to_find != knot_node_owner(
- knot_node_parent(knot_dname_node(to_find, 1), 1)));
+ knot_node_parent(knot_dname_node(to_find))));
to_find = knot_node_owner(
- knot_node_parent(knot_dname_node(to_find, 1), 1));
+ knot_node_parent(knot_dname_node(to_find)));
dbg_response("New to_find: %p\n", to_find);
}
#endif
@@ -456,7 +457,7 @@ dbg_response_exec(
assert(compr->wire_pos >= 0);
if (knot_response_store_dname_pos(compr->table, dname, not_matched,
- compr->wire_pos, offset, compr_cs)
+ compr->wire_pos, offset, compr_cs)
!= 0) {
dbg_response("Compression info could not be stored."
"\n");
@@ -952,25 +953,79 @@ void knot_response_clear(knot_packet_t *resp, int clear_question)
/*----------------------------------------------------------------------------*/
int knot_response_add_opt(knot_packet_t *resp,
- const knot_opt_rr_t *opt_rr,
- int override_max_size)
+ const knot_opt_rr_t *opt_rr,
+ int override_max_size,
+ int add_nsid)
{
if (resp == NULL || opt_rr == NULL) {
return KNOT_EBADARG;
}
// copy the OPT RR
+
+ /*! \todo Change the way OPT RR is handled in response.
+ * Pointer to nameserver->opt_rr should be enough.
+ */
+
resp->opt_rr.version = opt_rr->version;
resp->opt_rr.ext_rcode = opt_rr->ext_rcode;
resp->opt_rr.payload = opt_rr->payload;
- resp->opt_rr.size = opt_rr->size;
+
+ /*
+ * Add options only if NSID is requested.
+ *
+ * This is a bit hack and should be resolved in other way before some
+ * other options are supported.
+ */
+
+ if (add_nsid) {
+ resp->opt_rr.option_count = opt_rr->option_count;
+ assert(resp->opt_rr.options == NULL);
+ resp->opt_rr.options = (knot_opt_option_t *)malloc(
+ resp->opt_rr.option_count * sizeof(knot_opt_option_t));
+ CHECK_ALLOC_LOG(resp->opt_rr.options, KNOT_ENOMEM);
+
+ memcpy(resp->opt_rr.options, opt_rr->options,
+ resp->opt_rr.option_count * sizeof(knot_opt_option_t));
+
+ // copy all data
+ for (int i = 0; i < opt_rr->option_count; i++) {
+ resp->opt_rr.options[i].data = (uint8_t *)malloc(
+ resp->opt_rr.options[i].length);
+ CHECK_ALLOC_LOG(resp->opt_rr.options[i].data, KNOT_ENOMEM);
+
+ memcpy(resp->opt_rr.options[i].data,
+ opt_rr->options[i].data,
+ resp->opt_rr.options[i].length);
+
+// struct knot_opt_option option;
+// option = opt_rr->options[i];
+
+// /* Do not add NSID unless specified. */
+// if ((option.code != EDNS_OPTION_NSID) || (add_nsid)) {
+// int ret =
+// knot_edns_add_option(&resp->opt_rr,
+// option.code,
+// option.length,
+// option.data);
+// if (ret != KNOT_EOK) {
+// dbg_response("Could not "
+// "copy option to EDNS!\n");
+// }
+// }
+ }
+ resp->opt_rr.size = opt_rr->size;
+ } else {
+ resp->opt_rr.size = KNOT_EDNS_MIN_SIZE;
+ }
// if max size is set, it means there is some reason to be that way,
// so we can't just set it to higher value
if (override_max_size && resp->max_size > 0
&& resp->max_size < opt_rr->payload) {
- return KNOT_EPAYLOAD;
+// return KNOT_EPAYLOAD;
+ return KNOT_EOK;
}
// set max size (less is OK)
diff --git a/src/libknot/packet/response.h b/src/libknot/packet/response.h
index d76c10c..d522f82 100644
--- a/src/libknot/packet/response.h
+++ b/src/libknot/packet/response.h
@@ -96,7 +96,8 @@ void knot_response_clear(knot_packet_t *resp, int clear_question);
*/
int knot_response_add_opt(knot_packet_t *resp,
const knot_opt_rr_t *opt_rr,
- int override_max_size);
+ int override_max_size,
+ int add_nsid);
/*!
* \brief Adds a RRSet to the Answer section of the response.
diff --git a/src/libknot/rdata.c b/src/libknot/rdata.c
index 27fa6ec..51a1a70 100644
--- a/src/libknot/rdata.c
+++ b/src/libknot/rdata.c
@@ -268,20 +268,38 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
break;
case 3:
pos2 = *pos;
- fprintf(stderr, "reading dname from pos: %zu\n", pos2);
- dname =
- knot_dname_parse_from_wire(
+ //fprintf(stderr, "reading dname from pos: %zu\n", pos2);
+ dname = knot_dname_parse_from_wire(
wire, &pos2, total_size, NULL);
if (dname == NULL) {
return KNOT_ERROR;
}
- items[i].dname = dname;
+
+ items[i].raw_data = (uint16_t *)malloc(
+ knot_dname_size(dname) + 2);
+ if (items[i].raw_data == NULL) {
+ /*! \todo This will leak. */
+ free(items);
+ return KNOT_ENOMEM;
+ }
+
+ items[i].raw_data[0] = knot_dname_size(dname);
+ memcpy((uint8_t *)(items[i].raw_data + 1),
+ knot_dname_name(dname),
+ knot_dname_size(dname));
+
+// items[i].dname = dname;
//*pos += dname->size;
parsed += pos2 - *pos;
- fprintf(stderr, "read %zu bytes.\n", parsed);
+ //fprintf(stderr, "read %zu bytes.\n", parsed);
*pos = pos2;
- dname = 0;
+ knot_dname_free(&dname);
+
+ // continue with next item
+ ++i;
+ continue;
+
break;
default:
assert(0);
@@ -295,6 +313,7 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
if (item_size != 0) {
if (parsed + item_size > rdlength) {
+ /*! \todo This will leak a lot. */
free(items);
return KNOT_EFEWDATA;
}
@@ -302,15 +321,16 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
items[i].raw_data = (uint16_t *)malloc(item_size + 2);
if (items[i].raw_data == NULL) {
free(items);
+ /*! \todo This will also leak a lot. */
return KNOT_ENOMEM;
}
memcpy(items[i].raw_data, &item_size, 2);
memcpy(items[i].raw_data + 1, wire + *pos, item_size);
*pos += item_size;
parsed += item_size;
- } else if (item_type == KNOT_RDATA_WF_BINARY
- || item_type == KNOT_RDATA_WF_IPSECGATEWAY) {
- fprintf(stderr, "item_size was 0, creating empty rdata item.\n");
+ } else if (item_type == KNOT_RDATA_WF_BINARY/*
+ || item_type == KNOT_RDATA_WF_IPSECGATEWAY*/) {
+// fprintf(stderr, "item_size was 0, creating empty rdata item.\n");
// in this case we are at the end of the RDATA
// and should create an empty RDATA item
items[i].raw_data = (uint16_t *)malloc(2);
@@ -322,8 +342,8 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
} else if (item_type != KNOT_RDATA_WF_COMPRESSED_DNAME
&& item_type != KNOT_RDATA_WF_UNCOMPRESSED_DNAME
&& item_type != KNOT_RDATA_WF_LITERAL_DNAME) {
- fprintf(stderr, "RDATA item not set (i: %d), type: %u"
- " RDATA item type: %d\n", i, desc->type ,item_type);
+// fprintf(stderr, "RDATA item not set (i: %d), type: %u"
+// " RDATA item type: %d\n", i, desc->type ,item_type);
assert(0);
}
@@ -634,7 +654,7 @@ void knot_rdata_deep_free(knot_rdata_t **rdata, uint type,
/*----------------------------------------------------------------------------*/
knot_rdata_t *knot_rdata_deep_copy(const knot_rdata_t *rdata,
- uint16_t type)
+ uint16_t type, int copy_dnames)
{
knot_rdata_t *copy = knot_rdata_new();
CHECK_ALLOC_LOG(copy, NULL);
@@ -658,8 +678,13 @@ knot_rdata_t *knot_rdata_deep_copy(const knot_rdata_t *rdata,
if (d->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME
|| d->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
|| d->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME) {
- copy->items[i].dname =
- knot_dname_deep_copy(rdata->items[i].dname);
+ if (copy_dnames) {
+ copy->items[i].dname =
+ knot_dname_deep_copy(rdata->items[i].dname);
+ } else {
+ copy->items[i].dname = rdata->items[i].dname;
+ knot_dname_retain(rdata->items[i].dname);
+ }
} else {
copy->items[i].raw_data = (uint16_t *)malloc(
rdata->items[i].raw_data[0] + 2);
diff --git a/src/libknot/rdata.h b/src/libknot/rdata.h
index 6d9907d..bb45f50 100644
--- a/src/libknot/rdata.h
+++ b/src/libknot/rdata.h
@@ -229,7 +229,7 @@ int knot_rdata_item_set_raw_data(knot_rdata_t *rdata, unsigned int pos,
* \return Copy of \a rdata.
*/
knot_rdata_t *knot_rdata_deep_copy(const knot_rdata_t *rdata,
- uint16_t type);
+ uint16_t type, int copy_dnames);
/*!
* \brief Destroys the RDATA structure without deleting RDATA items.
diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index 44282fd..d968378 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -55,6 +55,8 @@ static void knot_rrset_disconnect_rdata(knot_rrset_t *rrset,
rrset->rdata = rdata->next;
}
}
+
+ rdata->next = NULL;
}
/*----------------------------------------------------------------------------*/
@@ -128,7 +130,7 @@ knot_rdata_t *knot_rrset_remove_rdata(knot_rrset_t *rrset,
}
while (rr != NULL) {
- /*! \todo maybe the dnames should be compared case-insensitive*/
+ /*! \todo dnames are compared case-insensitive. is it OK?*/
if (knot_rdata_compare(rr, rdata, desc->wireformat) == 0) {
knot_rrset_disconnect_rdata(rrset, prev, rr);
return rr;
@@ -457,8 +459,7 @@ static int knot_rrset_rr_to_wire(const knot_rrset_t *rrset,
// save whole domain name
memcpy(*pos, knot_dname_name(dname),
knot_dname_size(dname));
- dbg_rrset_detail(stderr,
- "Uncompressed dname size: %d\n",
+ dbg_rrset_detail("Uncompressed dname size: %d\n",
knot_dname_size(dname));
*pos += knot_dname_size(dname);
rdlength += knot_dname_size(dname);
@@ -579,7 +580,9 @@ int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to)
*to = (knot_rrset_t *)calloc(1, sizeof(knot_rrset_t));
CHECK_ALLOC_LOG(*to, KNOT_ENOMEM);
- (*to)->owner = knot_dname_deep_copy(from->owner);
+ //(*to)->owner = knot_dname_deep_copy(from->owner);
+ (*to)->owner = from->owner;
+ knot_dname_retain((*to)->owner);
(*to)->rclass = from->rclass;
(*to)->ttl = from->ttl;
(*to)->type = from->type;
@@ -597,7 +600,7 @@ int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to)
/*! \note Order of RDATA will be reversed. */
while (rdata != NULL) {
ret = knot_rrset_add_rdata(*to, knot_rdata_deep_copy(rdata,
- knot_rrset_type(from)));
+ knot_rrset_type(from), 1));
if (ret != KNOT_EOK) {
knot_rrset_deep_free(to, 1, 1, 1);
return ret;
@@ -654,6 +657,12 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
return;
}
+// char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
+// char *type = knot_rrtype_to_string(knot_rrset_type(*rrset));
+// fprintf(stderr, "Deleting RRSet (%p) %s, type %s, rdata: %p\n",
+// *rrset, name, type, (*rrset)->rdata);
+// free(name);
+
if (free_rdata) {
knot_rdata_t *tmp_rdata;
knot_rdata_t *next_rdata;
@@ -668,6 +677,7 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
tmp_rdata = next_rdata;
}
+// printf("test: %p\n", tmp_rdata->next->next);
assert(tmp_rdata == NULL
|| tmp_rdata->next == (*rrset)->rdata);
diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c
index edc68d8..bdaf083 100644
--- a/src/libknot/tsig-op.c
+++ b/src/libknot/tsig-op.c
@@ -540,11 +540,11 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
tsig_rdata_set_time_signed(tmp_tsig, request_time_signed);
/* Store current time into Other data. */
- uint8_t time_signed[3];
+ uint8_t time_signed[6];
time_t curr_time = time(NULL);
- /*! \todo bleeding eyes. */
- knot_wire_write_u48(time_signed, (uint64_t)curr_time);
+ uint64_t time64 = curr_time;
+ knot_wire_write_u48(time_signed, time64);
tsig_rdata_set_other_data(tmp_tsig, 6, time_signed);
} else {
diff --git a/src/libknot/updates/xfr-in.c b/src/libknot/updates/xfr-in.c
index 4a7e9ba..c1ea13d 100644
--- a/src/libknot/updates/xfr-in.c
+++ b/src/libknot/updates/xfr-in.c
@@ -248,23 +248,33 @@ int xfrin_create_ixfr_query(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
-static int xfrin_add_orphan_rrsig(xfrin_orphan_rrsig_t *rrsigs,
+static int xfrin_add_orphan_rrsig(xfrin_orphan_rrsig_t **rrsigs,
knot_rrset_t *rr)
{
// try to find similar RRSIGs (check owner and type covered) in the list
assert(knot_rrset_type(rr) == KNOT_RRTYPE_RRSIG);
+ if (*rrsigs == NULL) {
+ /* First item, nothing to iterate. */
+ *rrsigs = malloc(sizeof(xfrin_orphan_rrsig_t));
+ CHECK_ALLOC_LOG(*rrsigs, KNOT_ENOMEM);
+ (*rrsigs)->rrsig = rr;
+ (*rrsigs)->next = NULL;
+ return KNOT_EOK;
+ }
+
int ret = 0;
- xfrin_orphan_rrsig_t **last = &rrsigs;
- while (*last != NULL) {
+ xfrin_orphan_rrsig_t *last = *rrsigs;
+ assert(last);
+ while (last != NULL) {
// check if the RRSIG is not similar to the one we want to add
- assert((*last)->rrsig != NULL);
- if (knot_rrset_compare((*last)->rrsig, rr,
+ assert(last->rrsig != NULL);
+ if (knot_rrset_compare(last->rrsig, rr,
KNOT_RRSET_COMPARE_HEADER) == 1
&& knot_rdata_rrsig_type_covered(knot_rrset_rdata(
- (*last)->rrsig))
+ last->rrsig))
== knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr))) {
- ret = knot_rrset_merge((void **)&(*last)->rrsig,
+ ret = knot_rrset_merge((void **)&last->rrsig,
(void **)&rr);
if (ret != KNOT_EOK) {
return ret;
@@ -272,16 +282,19 @@ static int xfrin_add_orphan_rrsig(xfrin_orphan_rrsig_t *rrsigs,
return 1;
}
}
- last = &((*last)->next);
+ last = last->next;
}
+
+ assert(last == NULL);
+ assert(&last != rrsigs);
- assert(*last == NULL);
- // we did not find the right RRSIGs, add to the end
- *last = (xfrin_orphan_rrsig_t *)malloc(sizeof(xfrin_orphan_rrsig_t));
- CHECK_ALLOC_LOG(*last, KNOT_ENOMEM);
+ // the RRSIG is not in the list, add to the front
+ xfrin_orphan_rrsig_t *new_item = malloc(sizeof(xfrin_orphan_rrsig_t));
+ CHECK_ALLOC_LOG(new_item, KNOT_ENOMEM);
+ new_item->rrsig = rr;
+ new_item->next = *rrsigs;
- (*last)->rrsig = rr;
- (*last)->next = NULL;
+ *rrsigs = new_item;
return KNOT_EOK;
}
@@ -506,7 +519,7 @@ int xfrin_process_axfr_packet(/*const uint8_t *pkt, size_t size,
dbg_xfrin("No zone created, but the first RR in "
"Answer is not a SOA RR.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
knot_rrset_deep_free(&rr, 1, 1, 1);
/*! \todo Cleanup. */
return KNOT_EMALF;
@@ -528,7 +541,7 @@ dbg_xfrin_exec(
);
/*! \todo Cleanup. */
knot_packet_free(&packet);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_EMALF;
}
@@ -549,7 +562,7 @@ dbg_xfrin_exec(
if (*constr == NULL) {
dbg_xfrin("Failed to create new constr. zone.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ENOMEM;
}
@@ -561,7 +574,7 @@ dbg_xfrin_exec(
if ((*constr)->contents== NULL) {
dbg_xfrin("Failed to create new zone.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
knot_rrset_deep_free(&rr, 1, 1, 1);
/*! \todo Cleanup. */
return KNOT_ENOMEM;
@@ -580,7 +593,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to add RRSet to zone node: %s.\n",
knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
knot_rrset_deep_free(&rr, 1, 1, 1);
/*! \todo Cleanup. */
return KNOT_ERROR;
@@ -687,8 +700,14 @@ dbg_xfrin_exec(
if (ret == KNOT_ENONODE || ret == KNOT_ENORRSET) {
dbg_xfrin("No node or RRSet for RRSIGs\n");
dbg_xfrin("Saving for later insertion.\n");
- ret = xfrin_add_orphan_rrsig((*constr)->rrsigs,
+
+ if (ret == KNOT_ENORRSET) {
+ in_zone = 1;
+ }
+
+ ret = xfrin_add_orphan_rrsig(&(*constr)->rrsigs,
rr);
+
if (ret > 0) {
dbg_xfrin("Merged RRSIGs.\n");
knot_rrset_free(&rr);
@@ -696,7 +715,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to save orphan"
" RRSIGs.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 1, 0); // ???
+ knot_node_free(&node, 0); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return ret;
}
@@ -704,7 +723,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to add RRSIGs (%s).\n",
knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 1, 0); // ???
+ knot_node_free(&node, 0); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ERROR; /*! \todo Other error code. */
} else if (ret == 1) {
@@ -712,7 +731,7 @@ dbg_xfrin_exec(
dbg_xfrin_exec(
char *name = knot_dname_to_str(node->owner);
dbg_xfrin("Found node for the record in "
- "zone: %s.\n", name);
+ "zone: %s. Merged.\n", name);
free(name);
);
in_zone = 1;
@@ -744,7 +763,7 @@ dbg_xfrin_exec(
// not allowed here
dbg_xfrin(" in Answer section.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 1, 0); // ???
+ knot_node_free(&node, 0); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_EMALF;
}
@@ -787,7 +806,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to add RRSet to node (%s"
")\n", knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 1, 0); // ???
+ knot_node_free(&node, 0); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ERROR;
} else if (ret > 0) {
@@ -803,7 +822,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to add node to zone (%s)"
".\n", knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 1, 0); // ???
+ knot_node_free(&node, 0); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ERROR;
}
@@ -839,7 +858,7 @@ dbg_xfrin_exec(
dbg_xfrin("Could not parse next RR: %s.\n",
knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
knot_rrset_deep_free(&rr, 1, 1, 1);
/*! \todo Cleanup. */
return KNOT_EMALF;
@@ -856,7 +875,7 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to add last node into zone (%s)"
".\n", knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 1, 0);
+ knot_node_free(&node, 0);
return KNOT_ERROR; /*! \todo Other error */
}
}
@@ -1009,6 +1028,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
return XFRIN_RES_SOA_ONLY;
} else if (knot_rrset_type(rr) != KNOT_RRTYPE_SOA) {
knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_packet_free(&packet);
dbg_xfrin("Fallback to AXFR.\n");
ret = XFRIN_RES_FALLBACK;
return ret;
@@ -1260,39 +1280,27 @@ typedef struct {
int new_rrsets_allocated;
/*!
- * Deleted (without contents) after successful update.
+ * Deleted after failed update.
*/
+ knot_rdata_t **new_rdata;
+ uint *new_rdata_types;
+ int new_rdata_count;
+ int new_rdata_allocated;
+
+// /*!
+// * Deleted (without contents) after successful update.
+// */
knot_node_t **old_nodes;
int old_nodes_count;
int old_nodes_allocated;
- /*!
- * Deleted (without contents) after failed update.
- */
- knot_node_t **new_nodes;
- int new_nodes_count;
- int new_nodes_allocated;
-
- ck_hash_table_item_t **old_hash_items;
- int old_hash_items_count;
- int old_hash_items_allocated;
+ knot_node_t **old_nsec3;
+ int old_nsec3_count;
+ int old_nsec3_allocated;
} xfrin_changes_t;
/*----------------------------------------------------------------------------*/
-static void xfrin_changes_free(xfrin_changes_t **changes)
-{
- free((*changes)->old_nodes);
- free((*changes)->old_rrsets);
- free((*changes)->old_rdata);
- free((*changes)->old_rdata_types);
- free((*changes)->new_rrsets);
- free((*changes)->new_nodes);
- free((*changes)->old_hash_items);
-}
-
-/*----------------------------------------------------------------------------*/
-
static int xfrin_changes_check_rrsets(knot_rrset_t ***rrsets,
int *count, int *allocated, int to_add)
{
@@ -1397,51 +1405,20 @@ static int xfrin_changes_check_rdata(knot_rdata_t ***rdatas, uint **types,
/*----------------------------------------------------------------------------*/
-static int xfrin_changes_check_hash_items(ck_hash_table_item_t ***items,
- int *count, int *allocated)
-{
- /* Prevent infinite loop in case of allocated = 0. */
- int new_count = 0;
- if (*allocated == 0) {
- new_count = *count + 1;
- } else {
- if (*count == *allocated) {
- new_count = *allocated * 2;
- }
- }
-
- const size_t item_len = sizeof(ck_hash_table_item_t *);
- ck_hash_table_item_t **items_new = malloc(new_count * item_len);
- if (items_new == NULL) {
- return KNOT_ENOMEM;
- }
-
- memset(items_new, 0, new_count * item_len);
- memcpy(items_new, *items, (*count) * item_len);
- free(*items);
- *items = items_new;
- *allocated = new_count;
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
static void xfrin_zone_contents_free(knot_zone_contents_t **contents)
{
/*! \todo This should be all in some API!! */
if ((*contents)->table != NULL) {
-// ck_destroy_table(&(*contents)->table, NULL, 0);
- ck_table_free(&(*contents)->table);
+ ck_destroy_table(&(*contents)->table, NULL, 0);
+// ck_table_free(&(*contents)->table);
}
- // free the zone tree, but only the structure
- // (nodes are already destroyed)
+ // free the zone tree with nodes
dbg_zone("Destroying zone tree.\n");
- knot_zone_tree_free(&(*contents)->nodes);
+ knot_zone_tree_deep_free(&(*contents)->nodes);
dbg_zone("Destroying NSEC3 zone tree.\n");
- knot_zone_tree_free(&(*contents)->nsec3_nodes);
+ knot_zone_tree_deep_free(&(*contents)->nsec3_nodes);
knot_nsec3_params_free(&(*contents)->nsec3_params);
@@ -1453,39 +1430,6 @@ static void xfrin_zone_contents_free(knot_zone_contents_t **contents)
/*----------------------------------------------------------------------------*/
-static void xfrin_rollback_update(knot_zone_contents_t *contents,
- xfrin_changes_t *changes)
-{
- /*
- * This function is called only when no references were actually set to
- * the new nodes, just the new nodes reference other.
- * We thus do not need to fix any references, just from the old nodes
- * to the new ones.
- */
-
- // discard new nodes, but do not remove RRSets from them
- for (int i = 0; i < changes->new_nodes_count; ++i) {
- knot_node_free(&changes->new_nodes[i], 0, 0);
- }
-
- // set references from old nodes to new nodes to NULL and remove the
- // old flag
- for (int i = 0; i < changes->old_nodes_count; ++i) {
- knot_node_set_new_node(changes->old_nodes[i], NULL);
- knot_node_clear_old(changes->old_nodes[i]);
- }
-
- // discard new RRSets
- for (int i = 0; i < changes->new_rrsets_count; ++i) {
- knot_rrset_deep_free(&changes->new_rrsets[i], 0, 1, 0);
- }
-
- // destroy the shallow copy of zone
- xfrin_zone_contents_free(&contents);
-}
-
-/*----------------------------------------------------------------------------*/
-
static knot_rdata_t *xfrin_remove_rdata(knot_rrset_t *from,
const knot_rrset_t *what)
{
@@ -1495,6 +1439,8 @@ static knot_rdata_t *xfrin_remove_rdata(knot_rrset_t *from,
const knot_rdata_t *rdata = knot_rrset_rdata(what);
while (rdata != NULL) {
+ // rdata - the RDATA to be removed
+ // old_actual - removed RDATA
old_actual = knot_rrset_remove_rdata(from, rdata);
if (old_actual != NULL) {
old_actual->next = old;
@@ -1503,105 +1449,97 @@ static knot_rdata_t *xfrin_remove_rdata(knot_rrset_t *from,
rdata = knot_rrset_rdata_next(what, rdata);
}
+ // returning chain of removed RDATA (terminated with NULL)
return old;
}
/*----------------------------------------------------------------------------*/
-static int xfrin_get_node_copy(knot_node_t **node, xfrin_changes_t *changes)
-{
- knot_node_t *new_node =
- knot_node_get_new_node(*node);
- if (new_node == NULL) {
- dbg_xfrin("Creating copy of node.\n");
- int ret = knot_node_shallow_copy(*node, &new_node);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to create node copy.\n");
- return KNOT_ENOMEM;
- }
-
- dbg_xfrin_detail("Created copy of old node %p to new node %p\n",
- *node, new_node);
-
- assert(changes);
-
-// changes->new_nodes_allocated = 0;
-
- // save the copy of the node
- ret = xfrin_changes_check_nodes(
- &changes->new_nodes,
- &changes->new_nodes_count,
- &changes->new_nodes_allocated);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add new node to list.\n");
- knot_node_free(&new_node, 0, 0);
- return ret;
- }
-
-// changes->old_nodes_allocated = 0;
-
- // save the old node to list of old nodes
- ret = xfrin_changes_check_nodes(
- &changes->old_nodes,
- &changes->old_nodes_count,
- &changes->old_nodes_allocated);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add old node to list.\n");
- knot_node_free(&new_node, 0, 0);
- return ret;
- }
-
- assert(changes->new_nodes);
- assert(changes->old_nodes);
-
- changes->new_nodes[changes->new_nodes_count++] = new_node;
- changes->old_nodes[changes->old_nodes_count++] = *node;
-
- // mark the old node as old
- knot_node_set_old(*node);
-
- knot_node_set_new(new_node);
- knot_node_set_new_node(*node, new_node);
- }
-
- *node = new_node;
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
xfrin_changes_t *changes)
{
// create new RRSet by copying the old one
- int ret = knot_rrset_shallow_copy(old, copy);
+// int ret = knot_rrset_shallow_copy(old, copy);
+ int ret = knot_rrset_deep_copy(old, copy);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to create RRSet copy.\n");
return KNOT_ENOMEM;
}
// add the RRSet to the list of new RRSets
+ // create place also for RRSIGs
ret = xfrin_changes_check_rrsets(&changes->new_rrsets,
&changes->new_rrsets_count,
- &changes->new_rrsets_allocated, 1);
+ &changes->new_rrsets_allocated, 2);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RRSet to list.\n");
- knot_rrset_free(copy);
+ knot_rrset_deep_free(copy, 1, 1, 1);
+ return ret;
+ }
+
+ // add the copied RDATA to the list of new RDATA
+ ret = xfrin_changes_check_rdata(&changes->new_rdata,
+ &changes->new_rdata_types,
+ changes->new_rdata_count,
+ &changes->new_rdata_allocated, 2);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to add new RRSet to list.\n");
+ knot_rrset_deep_free(copy, 1, 1, 1);
return ret;
}
changes->new_rrsets[changes->new_rrsets_count++] = *copy;
+ changes->new_rdata[changes->new_rdata_count] =
+ knot_rrset_get_rdata(*copy);
+ changes->new_rdata_types[changes->new_rdata_count] =
+ knot_rrset_type(*copy);
+ ++changes->new_rdata_count;
+
+ if ((*copy)->rrsigs != NULL) {
+ assert(old->rrsigs != NULL);
+ changes->new_rrsets[changes->new_rrsets_count++] =
+ (*copy)->rrsigs;
+ changes->new_rdata[changes->new_rdata_count] =
+ knot_rrset_get_rdata((*copy)->rrsigs);
+ changes->new_rdata_types[changes->new_rdata_count] =
+ KNOT_RRTYPE_RRSIG;
+ ++changes->new_rdata_count;
+ }
// add the old RRSet to the list of old RRSets
ret = xfrin_changes_check_rrsets(&changes->old_rrsets,
&changes->old_rrsets_count,
- &changes->old_rrsets_allocated, 1);
+ &changes->old_rrsets_allocated, 2);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to add old RRSet to list.\n");
+ return ret;
+ }
+
+ // and old RDATA to the list of old RDATA
+ ret = xfrin_changes_check_rdata(&changes->old_rdata,
+ &changes->old_rdata_types,
+ changes->old_rdata_count,
+ &changes->old_rdata_allocated, 2);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add old RRSet to list.\n");
return ret;
}
changes->old_rrsets[changes->old_rrsets_count++] = old;
+ changes->old_rdata[changes->old_rdata_count] = old->rdata;
+ changes->old_rdata_types[changes->old_rdata_count] =
+ knot_rrset_type(old);
+ ++changes->old_rdata_count;
+
+ if ((*copy)->rrsigs != NULL) {
+ assert(old->rrsigs != NULL);
+ changes->old_rrsets[changes->old_rrsets_count++] = old->rrsigs;
+ changes->old_rdata[changes->old_rdata_count] =
+ old->rrsigs->rdata;
+ changes->old_rdata_types[changes->old_rdata_count] =
+ KNOT_RRTYPE_RRSIG;
+ ++changes->old_rdata_count;
+ }
return KNOT_EOK;
}
@@ -1623,8 +1561,7 @@ static int xfrin_copy_rrset(knot_node_t *node, knot_rr_type_t type,
return ret;
}
- dbg_xfrin_detail("Copied old rrset %p to new %p.\n",
- old, *rrset);
+ dbg_xfrin_detail("Copied old rrset %p to new %p.\n", old, *rrset);
// replace the RRSet in the node copy by the new one
ret = knot_node_add_rrset(node, *rrset, 0);
@@ -1655,6 +1592,8 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
int ret;
+ int copied = 0;
+
if (!*rrset
|| knot_dname_compare(knot_rrset_owner(*rrset),
knot_node_owner(node)) != 0
@@ -1670,6 +1609,7 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
dbg_xfrin("Failed to copy rrset from changeset.\n");
return ret;
}
+ copied = 1;
} else {
// we should have the right RRSIG RRSet in *rrset
assert(knot_rrset_type(*rrset)
@@ -1677,6 +1617,7 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
knot_rrset_rdata(remove)));
// this RRSet should be the already copied RRSet so we may
// update it right away
+ /*! \todo Does this case even occur? */
}
// get the old rrsigs
@@ -1686,11 +1627,14 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
}
// copy the RRSIGs
- /*! \todo This may be done unnecessarily more times. */
- knot_rrset_t *rrsigs;
- ret = xfrin_copy_old_rrset(old, &rrsigs, changes);
- if (ret != KNOT_EOK) {
- return ret;
+ knot_rrset_t *rrsigs = NULL;
+ if (!copied) {
+ ret = xfrin_copy_old_rrset(old, &rrsigs, changes);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+ } else {
+ rrsigs = old;
}
// set the RRSIGs to the new RRSet copy
@@ -1698,8 +1642,6 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
dbg_xfrin("Failed to set rrsigs.\n");
return KNOT_ERROR;
}
-
-
// now in '*rrset' we have a copy of the RRSet which holds the RRSIGs
// and in 'rrsigs' we have the copy of the RRSIGs
@@ -1710,6 +1652,20 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
knot_strerror(ret));
return 1;
}
+
+ // connect the RDATA to the list of old RDATA
+ ret = xfrin_changes_check_rdata(&changes->old_rdata,
+ &changes->old_rdata_types,
+ changes->old_rdata_count,
+ &changes->old_rdata_allocated, 1);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ changes->old_rdata[changes->old_rdata_count] = rdata;
+ changes->old_rdata_types[changes->old_rdata_count] =
+ knot_rrset_type(remove);
+ ++changes->old_rdata_count;
// if the RRSet is empty, remove from node and add to old RRSets
// check if there is no RRSIGs; if there are, leave the RRSet
@@ -1718,6 +1674,7 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
// remove the RRSIGs from the RRSet
knot_rrset_set_rrsigs(*rrset, NULL);
+ // add RRSet to the list of old RRSets
ret = xfrin_changes_check_rrsets(&changes->old_rrsets,
&changes->old_rrsets_count,
&changes->old_rrsets_allocated,
@@ -1731,6 +1688,8 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
}
changes->old_rrsets[changes->old_rrsets_count++] = rrsigs;
+
+ // saving old RDATA is not necessary as there is none
// now check if the RRSet is not totally empty
if (knot_rrset_rdata(*rrset) == NULL) {
@@ -1758,20 +1717,6 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
}
}
- // connect the RDATA to the list of old RDATA
- ret = xfrin_changes_check_rdata(&changes->old_rdata,
- &changes->old_rdata_types,
- changes->old_rdata_count,
- &changes->old_rdata_allocated, 1);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- changes->old_rdata[changes->old_rdata_count] = rdata;
- changes->old_rdata_types[changes->old_rdata_count] =
- knot_rrset_type(remove);
- ++changes->old_rdata_count;
-
return KNOT_EOK;
}
@@ -1797,8 +1742,7 @@ static int xfrin_apply_remove_normal(xfrin_changes_t *changes,
if (!*rrset
|| knot_dname_compare(knot_rrset_owner(*rrset),
knot_node_owner(node)) != 0
- || knot_rrset_type(*rrset)
- != knot_rrset_type(remove)) {
+ || knot_rrset_type(*rrset) != knot_rrset_type(remove)) {
/*!
* \todo This may happen also with already
* copied RRSet. In that case it would be
@@ -1812,7 +1756,7 @@ static int xfrin_apply_remove_normal(xfrin_changes_t *changes,
if (ret != KNOT_EOK) {
return ret;
}
- }
+ } /*! \todo Does some other case even occur? */
if (*rrset == NULL) {
dbg_xfrin("RRSet not found for RR to be removed.\n");
@@ -1830,8 +1774,8 @@ dbg_xfrin_exec(
// sets)
knot_rdata_t *rdata = xfrin_remove_rdata(*rrset, remove);
if (rdata == NULL) {
- dbg_xfrin("Failed to remove RDATA from RRSet: %s.\n",
- knot_strerror(ret));
+ dbg_xfrin("Failed to remove RDATA from RRSet\n");
+ // In this case, the RDATA was not found in the RRSet
return 1;
}
@@ -1846,6 +1790,20 @@ dbg_xfrin_exec_detail(
} while (r != NULL && r != rdata);
}
);
+
+ // connect the RDATA to the list of old RDATA
+ ret = xfrin_changes_check_rdata(&changes->old_rdata,
+ &changes->old_rdata_types,
+ changes->old_rdata_count,
+ &changes->old_rdata_allocated, 1);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ changes->old_rdata[changes->old_rdata_count] = rdata;
+ changes->old_rdata_types[changes->old_rdata_count] =
+ knot_rrset_type(remove);
+ ++changes->old_rdata_count;
// if the RRSet is empty, remove from node and add to old RRSets
// check if there is no RRSIGs; if there are, leave the RRSet
@@ -1875,20 +1833,6 @@ dbg_xfrin_exec_detail(
changes->old_rrsets[changes->old_rrsets_count++] = *rrset;
}
- // connect the RDATA to the list of old RDATA
- ret = xfrin_changes_check_rdata(&changes->old_rdata,
- &changes->old_rdata_types,
- changes->old_rdata_count,
- &changes->old_rdata_allocated, 1);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- changes->old_rdata[changes->old_rdata_count] = rdata;
- changes->old_rdata_types[changes->old_rdata_count] =
- knot_rrset_type(remove);
- ++changes->old_rdata_count;
-
return KNOT_EOK;
}
@@ -1897,7 +1841,6 @@ dbg_xfrin_exec_detail(
static int xfrin_apply_remove_all_rrsets(xfrin_changes_t *changes,
knot_node_t *node, uint16_t type)
{
- /*! \todo Implement. */
int ret;
if (type == KNOT_RRTYPE_ANY) {
@@ -1915,7 +1858,8 @@ static int xfrin_apply_remove_all_rrsets(xfrin_changes_t *changes,
knot_rrset_t **place = changes->old_rrsets
+ changes->old_rrsets_count;
/*! \todo Test this!!! */
- memcpy(place, rrsets, knot_node_rrset_count(node) * sizeof(knot_rrset_t *));
+ memcpy(place, rrsets, knot_node_rrset_count(node)
+ * sizeof(knot_rrset_t *));
// remove all RRSets from the node
knot_node_remove_all_rrsets(node);
@@ -1938,83 +1882,11 @@ static int xfrin_apply_remove_all_rrsets(xfrin_changes_t *changes,
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_remove(knot_zone_contents_t *contents,
- knot_changeset_t *chset,
- xfrin_changes_t *changes)
-{
- /*
- * Iterate over removed RRSets, copy appropriate nodes and remove
- * the rrsets from them. By default, the RRSet should be copied so that
- * RDATA may be removed from it.
- */
- int ret = 0;
- knot_node_t *node = NULL;
- knot_rrset_t *rrset = NULL;
-
- for (int i = 0; i < chset->remove_count; ++i) {
- // check if the old node is not the one we should use
- if (!node || knot_rrset_owner(chset->remove[i])
- != knot_node_owner(node)) {
- node = knot_zone_contents_get_node(contents,
- knot_rrset_owner(chset->remove[i]));
- if (node == NULL) {
- dbg_xfrin("Node not found for RR to be removed"
- "!\n");
- continue;
- }
- }
-
- // create a copy of the node if not already created
- if (!knot_node_is_new(node)) {
- ret = xfrin_get_node_copy(&node, changes);
- if (ret != KNOT_EOK) {
- return ret;
- }
- }
-
- assert(node != NULL);
- assert(knot_node_is_new(node));
-
- // first check if all RRSets should be removed
- if (knot_rrset_class(chset->remove[i]) == KNOT_CLASS_ANY) {
- ret = xfrin_apply_remove_all_rrsets(
- changes, node,
- knot_rrset_type(chset->remove[i]));
- } else if (knot_rrset_type(chset->remove[i])
- == KNOT_RRTYPE_RRSIG) {
- // this should work also for UPDATE
- ret = xfrin_apply_remove_rrsigs(changes,
- chset->remove[i],
- node, &rrset);
- } else {
- // this should work also for UPDATE
- ret = xfrin_apply_remove_normal(changes,
- chset->remove[i],
- node, &rrset);
- }
-
- dbg_xfrin("xfrin_apply_remove() ret = %d\n", ret);
-
- if (ret > 0) {
- continue;
- } else if (ret != KNOT_EOK) {
- return ret;
- }
- }
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
static knot_node_t *xfrin_add_new_node(knot_zone_contents_t *contents,
- knot_rrset_t *rrset)
+ knot_rrset_t *rrset, int is_nsec3)
{
- /*! \todo Why is the function disabled? */
- //return NULL;
-
knot_node_t *node = knot_node_new(knot_rrset_get_owner(rrset),
- NULL, KNOT_NODE_FLAGS_NEW);
+ NULL, 0);
if (node == NULL) {
dbg_xfrin("Failed to create a new node.\n");
return NULL;
@@ -2027,36 +1899,22 @@ static knot_node_t *xfrin_add_new_node(knot_zone_contents_t *contents,
// dbg_xfrin("Adding new node to zone. From owner: %s type %s\n",
// knot_dname_to_str(node->owner),
// knot_rrtype_to_string(rrset->type));
- if (knot_rrset_type(rrset) == KNOT_RRTYPE_NSEC3) {
+ if (is_nsec3) {
ret = knot_zone_contents_add_nsec3_node(contents, node, 1, 0,
1);
} else {
- ret = knot_zone_contents_add_node(contents, node, 1,
- KNOT_NODE_FLAGS_NEW, 1);
+ ret = knot_zone_contents_add_node(contents, node, 1, 0, 1);
}
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new node to zone contents.\n");
return NULL;
}
- // find previous node and connect the new one to it
- knot_node_t *prev = NULL;
- if (knot_rrset_type(rrset) == KNOT_RRTYPE_NSEC3) {
- prev = knot_zone_contents_get_previous_nsec3(contents,
- knot_rrset_owner(rrset));
- } else {
- prev = knot_zone_contents_get_previous(contents,
- knot_rrset_owner(rrset));
- }
-
- // fix prev and next pointers
- if (prev != NULL) {
- knot_node_set_previous(node, prev);
- }
+ /*!
+ * \note It is not needed to set the previous node, we will do this
+ * in adjusting after the transfer.
+ */
-// printf("contents owned by: %s (%p)\n",
-// knot_dname_to_str(contents->apex->owner),
-// contents);
assert(contents->zone != NULL);
knot_node_set_zone(node, contents->zone);
@@ -2068,12 +1926,14 @@ static knot_node_t *xfrin_add_new_node(knot_zone_contents_t *contents,
static int xfrin_apply_add_normal(xfrin_changes_t *changes,
knot_rrset_t *add,
knot_node_t *node,
- knot_rrset_t **rrset)
+ knot_rrset_t **rrset,
+ knot_zone_contents_t *contents)
{
assert(changes != NULL);
assert(add != NULL);
assert(node != NULL);
assert(rrset != NULL);
+ assert(contents != NULL);
int ret;
@@ -2104,15 +1964,22 @@ dbg_xfrin_exec_verb(
/*! \todo What about domain names?? Shouldn't we use the
* zone-contents' version of this function??
*/
- ret = knot_node_add_rrset(node, add, 0);
-// ret = knot_zone_contents_add_rrset(node->zone->contents,
-// rrset, node,
-// KNOT_RRSET_DUPL_MERGE,
-// 1);
- if (ret != KNOT_EOK) {
+ /*!
+ * \note The new zone must be adjusted nevertheless, so it
+ * doesn't matter whether there are some extra dnames to
+ * be added to the table or not.
+ */
+// ret = knot_node_add_rrset(node, add, 0);
+ ret = knot_zone_contents_add_rrset(contents, add, &node,
+ KNOT_RRSET_DUPL_SKIP, 1);
+
+ if (ret < 0) {
dbg_xfrin("Failed to add RRSet to node.\n");
return KNOT_ERROR;
}
+
+ assert(ret == 0);
+
return 1; // return 1 to indicate the add RRSet was used
}
@@ -2124,7 +1991,7 @@ dbg_xfrin_exec(
knot_rrtype_to_string(knot_rrset_type(*rrset)));
free(name);
);
- knot_rrset_dump(*rrset, 1);
+// knot_rrset_dump(*rrset, 1);
ret = xfrin_copy_old_rrset(old, rrset, changes);
if (ret != KNOT_EOK) {
assert(0);
@@ -2149,7 +2016,7 @@ dbg_xfrin_exec(
dbg_xfrin("Merging RRSets with owners: %s %s types: %d %d\n",
(*rrset)->owner->name, add->owner->name, (*rrset)->type,
add->type);
- dbg_xfrin_detail("RDATA in RRSet1: %p, RDATA in RRSet2: %p\n",
+ dbg_xfrin_detail("RDATA in RRSet1: %p, RDATA in RRSet2: %p\n",
(*rrset)->rdata, add->rdata);
ret = knot_rrset_merge((void **)rrset, (void **)&add);
if (ret != KNOT_EOK) {
@@ -2172,19 +2039,31 @@ dbg_xfrin_exec(
static int xfrin_apply_add_rrsig(xfrin_changes_t *changes,
knot_rrset_t *add,
knot_node_t *node,
- knot_rrset_t **rrset)
+ knot_rrset_t **rrset,
+ knot_zone_contents_t *contents)
{
assert(changes != NULL);
assert(add != NULL);
assert(node != NULL);
assert(rrset != NULL);
assert(knot_rrset_type(add) == KNOT_RRTYPE_RRSIG);
+ assert(contents != NULL);
int ret;
knot_rr_type_t type = knot_rdata_rrsig_type_covered(
knot_rrset_rdata(add));
+dbg_xfrin_exec(
+ 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",
+ name, typestr);
+ free(name);
+);
+
+ int copied = 0;
+
if (!*rrset
|| knot_dname_compare(knot_rrset_owner(*rrset),
knot_node_owner(node)) != 0
@@ -2194,7 +2073,10 @@ static int xfrin_apply_add_rrsig(xfrin_changes_t *changes,
ret = xfrin_copy_rrset(node, type, rrset, changes);
if (ret < 0) {
return ret;
+ } else if (ret != KNOT_EOK) {
+ *rrset = NULL;
}
+ copied = 1;
} else {
// we should have the right RRSIG RRSet in *rrset
assert(knot_rrset_type(*rrset) == type);
@@ -2205,6 +2087,7 @@ static int xfrin_apply_add_rrsig(xfrin_changes_t *changes,
if (*rrset == NULL) {
dbg_xfrin("RRSet to be added not found in zone.\n");
+ dbg_xfrin("Creating new RRSet for RRSIG.\n");
// create a new RRSet to add the RRSIGs into
*rrset = knot_rrset_new(knot_node_get_owner(node), type,
knot_rrset_class(add),
@@ -2213,13 +2096,30 @@ static int xfrin_apply_add_rrsig(xfrin_changes_t *changes,
dbg_xfrin("Failed to create new RRSet for RRSIGs.\n");
return KNOT_ENOMEM;
}
-
- // add the RRSet from the changeset to the node
+
+ // add the RRset to the list of new RRsets
+ ret = xfrin_changes_check_rrsets(
+ &changes->new_rrsets,
+ &changes->new_rrsets_count,
+ &changes->new_rrsets_allocated, 1);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to add old RRSet to "
+ "list.\n");
+ knot_rrset_free(rrset);
+ return ret;
+ }
+
+ // add the new RRSet to the node
+ // not needed to insert it through the zone_contents() function,
+ // as the owner is already in the dname table
ret = knot_node_add_rrset(node, *rrset, 0);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add RRSet to node.\n");
+ knot_rrset_free(rrset);
return KNOT_ERROR;
}
+
+ changes->new_rrsets[changes->new_rrsets_count++] = *rrset;
}
dbg_xfrin_exec(
@@ -2230,11 +2130,18 @@ dbg_xfrin_exec(
);
if (knot_rrset_rrsigs(*rrset) == NULL) {
- ret = knot_rrset_set_rrsigs(*rrset, add);
- if (ret != KNOT_EOK) {
+
+ dbg_xfrin("Adding new RRSIGs to RRSet.\n");
+ ret = knot_zone_contents_add_rrsigs(contents, add, rrset, &node,
+ KNOT_RRSET_DUPL_SKIP, 1);
+
+// ret = knot_rrset_set_rrsigs(*rrset, add);
+ if (ret < 0) {
dbg_xfrin("Failed to add RRSIGs to the RRSet.\n");
return KNOT_ERROR;
}
+
+ assert(ret == 0);
return 1;
} else {
@@ -2242,21 +2149,24 @@ dbg_xfrin_exec(
assert(old != NULL);
knot_rrset_t *rrsig;
- ret = xfrin_copy_old_rrset(old, &rrsig, changes);
- if (ret != KNOT_EOK) {
- return ret;
+ if (!copied) {
+ ret = xfrin_copy_old_rrset(old, &rrsig, changes);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+ } else {
+ rrsig = old;
}
// replace the old RRSIGs with the new ones
knot_rrset_set_rrsigs(*rrset, rrsig);
// merge the changeset RRSet to the copy
- /*! \todo What if the update fails?
- *
- */
+ dbg_xfrin("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 RRSet to copy.\n");
+ dbg_xfrin("Failed to merge changeset RRSIG to copy: %s"
+ ".\n", knot_strerror(ret));
return KNOT_ERROR;
}
@@ -2268,83 +2178,416 @@ dbg_xfrin_exec(
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_add(knot_zone_contents_t *contents,
- knot_changeset_t *chset,
- xfrin_changes_t *changes)
+static void xfrin_cleanup_update(xfrin_changes_t *changes)
+{
+
+ for (int i = 0; i < changes->old_rrsets_count; ++i) {
+ dbg_xfrin_detail("Deleting old RRSet: %p\n",
+ changes->old_rrsets[i]);
+ knot_rrset_dump(changes->old_rrsets[i], 0);
+ knot_rrset_free(&changes->old_rrsets[i]);
+ }
+
+ // delete old RDATA
+ for (int i = 0; i < changes->old_rdata_count; ++i) {
+ dbg_xfrin_detail("Deleting old RDATA: %p, type: %s\n",
+ changes->old_rdata[i],
+ knot_rrtype_to_string(changes->old_rdata_types[i]));
+ knot_rdata_dump(changes->old_rdata[i],
+ changes->old_rdata_types[i], 0);
+ knot_rdata_t *rdata = changes->old_rdata[i];
+ if (rdata != NULL) {
+ do {
+ knot_rdata_t *tmp = rdata->next;
+ knot_rdata_deep_free(&rdata,
+ changes->old_rdata_types[i], 1);
+ rdata = tmp;
+ } while (rdata != NULL
+ && rdata != changes->old_rdata[i]);
+ }
+
+ }
+
+ // free allocated arrays of nodes and rrsets
+ free(changes->new_rrsets);
+ free(changes->new_rdata);
+ free(changes->new_rdata_types);
+ free(changes->old_nodes);
+ free(changes->old_nsec3);
+ free(changes->old_rrsets);
+ free(changes->old_rdata);
+ free(changes->old_rdata_types);
+}
+
+/*----------------------------------------------------------------------------*/
+/* New changeset applying */
+/*----------------------------------------------------------------------------*/
+
+static void xfrin_switch_nodes_in_node(knot_node_t *node, void *data)
+{
+ assert(node != NULL);
+ UNUSED(data);
+
+ assert(knot_node_new_node(node) == NULL);
+
+ knot_node_update_refs(node);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void xfrin_switch_node_in_hash_table(ck_hash_table_item_t *item,
+ void *data)
+{
+ UNUSED(data);
+
+ if (item == NULL) {
+ return;
+ }
+
+ knot_node_t *node = (knot_node_t *)item->value;
+ knot_node_t *new_node = knot_node_get_new_node(node);
+
+ assert(new_node != NULL);
+
+ if (new_node != NULL) {
+ item->value = new_node;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void xfrin_switch_node_in_dname_table(knot_dname_t *dname, void *data)
+{
+ UNUSED(data);
+
+ if (knot_dname_node(dname) == NULL) {
+ return;
+ }
+
+ assert(knot_node_new_node(knot_dname_node(dname)) != NULL);
+ knot_dname_set_node(dname, knot_node_get_new_node(
+ knot_dname_get_node(dname)));
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int xfrin_switch_nodes(knot_zone_contents_t *contents_copy)
+{
+ assert(contents_copy != NULL);
+
+ // Traverse the trees and for each node check every reference
+ // stored in that node. The node itself should be new.
+ knot_zone_contents_tree_apply_inorder(contents_copy,
+ xfrin_switch_nodes_in_node, NULL);
+
+ knot_zone_contents_nsec3_apply_inorder(contents_copy,
+ xfrin_switch_nodes_in_node, NULL);
+
+ // Then traverse the hash table and change each pointer in hash table
+ // item from old node to new node.
+ int ret = ck_apply(knot_zone_contents_get_hash_table(contents_copy),
+ xfrin_switch_node_in_hash_table, NULL);
+ assert(ret == 0);
+
+ // Traverse also the dname table and change the node pointers in dnames
+ knot_zone_contents_dname_table_apply(contents_copy,
+ xfrin_switch_node_in_dname_table,
+ NULL);
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void xfrin_zone_contents_free2(knot_zone_contents_t **contents)
{
- // iterate over removed RRSets, copy appropriate nodes and remove
- // the rrsets from them
+ /*! \todo This should be all in some API!! */
+
+ if ((*contents)->table != NULL) {
+ ck_destroy_table(&(*contents)->table, NULL, 0);
+// ck_table_free(&(*contents)->table);
+ }
+
+ // free the zone tree, but only the structure
+ // (nodes are already destroyed)
+ dbg_zone("Destroying zone tree.\n");
+ knot_zone_tree_deep_free(&(*contents)->nodes);
+ dbg_zone("Destroying NSEC3 zone tree.\n");
+ knot_zone_tree_deep_free(&(*contents)->nsec3_nodes);
+
+ knot_nsec3_params_free(&(*contents)->nsec3_params);
+
+ knot_dname_table_deep_free(&(*contents)->dname_table);
+
+ free(*contents);
+ *contents = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void xfrin_cleanup_old_nodes(knot_node_t *node, void *data)
+{
+ UNUSED(data);
+ assert(node != NULL);
+
+ knot_node_set_new_node(node, NULL);
+ knot_dname_set_node(knot_node_get_owner(node), node);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void xfrin_rollback_update2(knot_zone_contents_t *old_contents,
+ knot_zone_contents_t *new_contents,
+ xfrin_changes_t *changes)
+{
+ // discard new RRSets
+ for (int i = 0; i < changes->new_rrsets_count; ++i) {
+ //knot_rrset_deep_free(&changes->new_rrsets[i], 0, 1, 1);
+ knot_rrset_free(&changes->new_rrsets[i]);
+ }
+
+ for (int i = 0; i < changes->new_rdata_count; ++i) {
+ // discard the whole chain of RDATA
+ knot_rdata_t *rdata = changes->new_rdata[i];
+ knot_rdata_t *rdata_next = NULL;
+
+ while (rdata != NULL && rdata->next != changes->new_rdata[i]) {
+ rdata_next = rdata->next;
+ knot_rdata_deep_free(&rdata,
+ changes->new_rdata_types[i], 1);
+ rdata = rdata_next;
+ }
+
+ assert(rdata == NULL || rdata->next == changes->new_rdata[i]);
+
+ knot_rdata_deep_free(&rdata, changes->new_rdata_types[i], 1);
+
+ changes->new_rdata[i] = NULL;
+ }
+
+ // free allocated arrays of nodes and rrsets
+ free(changes->new_rrsets);
+ free(changes->new_rdata);
+ free(changes->new_rdata_types);
+ free(changes->old_nodes);
+ free(changes->old_nsec3);
+ free(changes->old_rrsets);
+ free(changes->old_rdata);
+ free(changes->old_rdata_types);
+
+ // destroy the shallow copy of zone
+ xfrin_zone_contents_free2(&new_contents);
+
+ // cleanup old zone tree - reset pointers to new node to NULL
+ // also set pointers from dnames to old nodes
+ knot_zone_contents_tree_apply_inorder(old_contents,
+ xfrin_cleanup_old_nodes, NULL);
+
+ knot_zone_contents_nsec3_apply_inorder(old_contents,
+ xfrin_cleanup_old_nodes, NULL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int xfrin_apply_remove2(knot_zone_contents_t *contents,
+ knot_changeset_t *chset,
+ xfrin_changes_t *changes)
+{
+ /*
+ * Iterate over removed RRSets, and remove them from the new nodes
+ * in 'contents'. By default, the RRSet should be copied so that
+ * RDATA may be removed from it.
+ */
int ret = 0;
knot_node_t *node = NULL;
knot_rrset_t *rrset = NULL;
+ int is_nsec3 = 0;
+
+ for (int i = 0; i < chset->remove_count; ++i) {
+
+ is_nsec3 = 0;
+
+ // check if the RRSet belongs to the NSEC3 tree
+ if ((knot_rrset_type(chset->remove[i]) == KNOT_RRTYPE_NSEC3)
+ || (knot_rrset_type(chset->remove[i]) == KNOT_RRTYPE_RRSIG
+ && knot_rdata_rrsig_type_covered(
+ knot_rrset_rdata(chset->remove[i]))
+ == KNOT_RRTYPE_NSEC3))
+ {
+ is_nsec3 = 1;
+ }
+
+ // check if the old node is not the one we should use
+ if (!node || knot_rrset_owner(chset->remove[i])
+ != knot_node_owner(node)) {
+ if (is_nsec3) {
+ node = knot_zone_contents_get_nsec3_node(
+ contents,
+ knot_rrset_owner(chset->remove[i]));
+ } else {
+ node = knot_zone_contents_get_node(contents,
+ knot_rrset_owner(chset->remove[i]));
+ }
+ if (node == NULL) {
+ dbg_xfrin("Node not found for RR to be removed"
+ "!\n");
+ continue;
+ }
+ }
+
+ assert(node != NULL);
+
+ // first check if all RRSets should be removed
+ if (knot_rrset_class(chset->remove[i]) == KNOT_CLASS_ANY) {
+ ret = xfrin_apply_remove_all_rrsets(
+ changes, node,
+ knot_rrset_type(chset->remove[i]));
+ } else if (knot_rrset_type(chset->remove[i])
+ == KNOT_RRTYPE_RRSIG) {
+ // this should work also for UPDATE
+ ret = xfrin_apply_remove_rrsigs(changes,
+ chset->remove[i],
+ node, &rrset);
+ } else {
+ // this should work also for UPDATE
+ ret = xfrin_apply_remove_normal(changes,
+ chset->remove[i],
+ node, &rrset);
+ }
+
+ dbg_xfrin("xfrin_apply_remove() ret = %d\n", ret);
+
+ if (ret > 0) {
+ continue;
+ } else if (ret != KNOT_EOK) {
+ return ret;
+ }
+ }
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int xfrin_apply_add2(knot_zone_contents_t *contents,
+ knot_changeset_t *chset,
+ xfrin_changes_t *changes)
+{
+ int ret = 0;
+ knot_node_t *node = NULL;
+ knot_rrset_t *rrset = NULL;
+
+ int is_nsec3 = 0;
+
for (int i = 0; i < chset->add_count; ++i) {
dbg_xfrin_detail("Adding RRSet:\n");
knot_rrset_dump(chset->add[i], 0);
+
+ is_nsec3 = 0;
+
+ // check if the RRSet belongs to the NSEC3 tree
+ if ((knot_rrset_type(chset->add[i]) == KNOT_RRTYPE_NSEC3)
+ || (knot_rrset_type(chset->add[i]) == KNOT_RRTYPE_RRSIG
+ && knot_rdata_rrsig_type_covered(
+ knot_rrset_rdata(chset->add[i]))
+ == KNOT_RRTYPE_NSEC3))
+ {
+ dbg_xfrin_verb("This is NSEC3-related RRSet.\n");
+ is_nsec3 = 1;
+ }
+
// check if the old node is not the one we should use
if (!node || knot_rrset_owner(chset->add[i])
!= knot_node_owner(node)) {
- node = knot_zone_contents_get_node(contents,
- knot_rrset_owner(chset->add[i]));
+ dbg_xfrin_verb("Searching for node...\n");
+ if (is_nsec3) {
+ node = knot_zone_contents_get_nsec3_node(
+ contents,
+ knot_rrset_owner(chset->add[i]));
+ } else {
+ node = knot_zone_contents_get_node(contents,
+ knot_rrset_owner(chset->add[i]));
+ }
if (node == NULL) {
// create new node, connect it properly to the
// zone nodes
- dbg_xfrin("Creating new node from.\n");
+ dbg_xfrin("Node not found. Creating new.\n");
node = xfrin_add_new_node(contents,
- chset->add[i]);
+ chset->add[i],
+ is_nsec3);
if (node == NULL) {
dbg_xfrin("Failed to create new node "
"in zone.\n");
return KNOT_ERROR;
}
-// continue; // continue with another RRSet
}
}
- // create a copy of the node if not already created
- if (!knot_node_is_new(node)) {
- xfrin_get_node_copy(&node, changes);
- }
-
assert(node != NULL);
- assert(knot_node_is_new(node));
-
+
if (knot_rrset_type(chset->add[i]) == KNOT_RRTYPE_RRSIG) {
ret = xfrin_apply_add_rrsig(changes, chset->add[i],
- node, &rrset);
+ node, &rrset, contents);
} else {
ret = xfrin_apply_add_normal(changes, chset->add[i],
- node, &rrset);
+ node, &rrset, contents);
}
-
+
+ assert(ret != KNOT_EOK);
+
dbg_xfrin("xfrin_apply_..() returned %d, rrset: %p\n", ret,
rrset);
-
- if (ret == 1) {
- // the ADD RRSet was used, i.e. it should be removed
- // from the changeset and saved in the list of new
- // RRSets
- ret = xfrin_changes_check_rrsets(
- &changes->new_rrsets,
- &changes->new_rrsets_count,
- &changes->new_rrsets_allocated, 1);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add old RRSet to list.\n");
- return ret;
+
+ if (ret > 0) {
+ // store the new RDATA
+ // in both cases it must be deleted if the transfer
+ // fails
+
+ // connect the RDATA to the list of old RDATA
+ int res = xfrin_changes_check_rdata(&changes->new_rdata,
+ &changes->new_rdata_types,
+ changes->new_rdata_count,
+ &changes->new_rdata_allocated, 1);
+ if (res != KNOT_EOK) {
+ return res;
}
- changes->new_rrsets[changes->new_rrsets_count++] =
- chset->add[i];
+ changes->new_rdata[changes->new_rdata_count] =
+ knot_rrset_get_rdata(chset->add[i]);
+ changes->new_rdata_types[changes->new_rdata_count] =
+ knot_rrset_type(chset->add[i]);
+ ++changes->new_rdata_count;
+
+ if (ret == 1) {
+ // the ADD RRSet was used, i.e. it should be
+ // removed from the changeset and saved in the
+ // list of new RRSets
+ ret = xfrin_changes_check_rrsets(
+ &changes->new_rrsets,
+ &changes->new_rrsets_count,
+ &changes->new_rrsets_allocated, 1);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to add old RRSet to "
+ "list.\n");
+ return ret;
+ }
+
+ changes->new_rrsets[changes->new_rrsets_count++]
+ = chset->add[i];
+
+ chset->add[i] = NULL;
+ } else if (ret == 2) {
+ // the copy of the RRSet was used, but it was
+ // already stored in the new RRSets list
+ // just delete the add RRSet, but without RDATA
+ // as these were merged to the copied RRSet
+ knot_rrset_free(&chset->add[i]);
+ } else {
+ assert(0);
+ }
- chset->add[i] = NULL;
- } else if (ret == 2) {
- // the copy of the RRSet was used, but it was already
- // stored in the new RRSets list
- // just delete the add RRSet, but without RDATA
- // as these were merged to the copied RRSet
- knot_rrset_free(&chset->add[i]);
} else if (ret != KNOT_EOK) {
-
return ret;
}
}
@@ -2353,51 +2596,18 @@ static int xfrin_apply_add(knot_zone_contents_t *contents,
}
/*----------------------------------------------------------------------------*/
-/*!
- * \todo This must be tested!! Simulate failure somehow.
- */
-static void xfrin_clean_changes_after_fail(xfrin_changes_t *changes)
-{
- /* 1) Delete copies of RRSets created because they were updated.
- * Do not delete their RDATA or owners.
- */
- for (int i = 0; i < changes->new_rrsets_count; ++i) {
- knot_rrset_free(&changes->new_rrsets[i]);
- }
-
- /* 2) Delete copies of nodes created because they were updated.
- * Do not delete their RRSets.
- */
- for (int i = 0; i < changes->new_nodes_count; ++i) {
- knot_node_free(&changes->new_nodes[i], 0, 1);
- }
-
- // changesets will be deleted elsewhere
- // so just delete the changes structure
- xfrin_changes_free(&changes);
-}
-
-/*----------------------------------------------------------------------------*/
-static int xfrin_apply_replace_soa(knot_zone_contents_t *contents,
- xfrin_changes_t *changes,
- knot_changeset_t *chset)
+static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
+ xfrin_changes_t *changes,
+ knot_changeset_t *chset)
{
knot_node_t *node = knot_zone_contents_get_apex(contents);
assert(node != NULL);
int ret = 0;
- // create a copy of the node if not already created
- if (!knot_node_is_new(node)) {
- ret = xfrin_get_node_copy(&node, changes);
- if (ret != KNOT_EOK) {
- return ret;
- }
- }
+ assert(node != NULL);
- assert(knot_node_is_new(node));
-
// set the node copy as the apex of the contents
contents->apex = node;
@@ -2431,7 +2641,17 @@ static int xfrin_apply_replace_soa(knot_zone_contents_t *contents,
&changes->new_rrsets_count,
&changes->new_rrsets_allocated, 1);
if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add old RRSet to list.\n");
+ dbg_xfrin("Failed to add new RRSet to list.\n");
+ return ret;
+ }
+
+ // save the new SOA RDATA
+ ret = xfrin_changes_check_rdata(&changes->new_rdata,
+ &changes->new_rdata_types,
+ changes->new_rdata_count,
+ &changes->new_rdata_allocated, 1);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to add new RDATA to list.\n");
return ret;
}
@@ -2442,15 +2662,27 @@ static int xfrin_apply_replace_soa(knot_zone_contents_t *contents,
changes->old_rdata_types[changes->old_rdata_count] = KNOT_RRTYPE_SOA;
++changes->old_rdata_count;
+ // store RRSIGs from the old SOA to the new SOA
+ knot_rrset_set_rrsigs(chset->soa_to, knot_rrset_get_rrsigs(rrset));
+
// insert the new SOA RRSet to the node
dbg_xfrin_verb("Adding SOA.\n");
- ret = knot_node_add_rrset(node, chset->soa_to, 0);
- if (ret != KNOT_EOK) {
+ //ret = knot_node_add_rrset(node, chset->soa_to, 0);
+ ret = knot_zone_contents_add_rrset(contents, chset->soa_to, &node,
+ KNOT_RRSET_DUPL_SKIP, 1);
+
+ if (ret < 0) {
dbg_xfrin("Failed to add RRSet to node.\n");
return KNOT_ERROR;
}
+ assert(ret == 0);
changes->new_rrsets[changes->new_rrsets_count++] = chset->soa_to;
+ changes->new_rdata[changes->new_rdata_count] =
+ knot_rrset_get_rdata(chset->soa_to);
+ changes->new_rdata_types[changes->new_rdata_count] =
+ knot_rrset_type(chset->soa_to);
+ ++changes->new_rdata_count;
// remove the SOA from the changeset, so it will not be deleted after
// successful apply
@@ -2461,9 +2693,9 @@ static int xfrin_apply_replace_soa(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_changeset(knot_zone_contents_t *contents,
- xfrin_changes_t *changes,
- knot_changeset_t *chset)
+static int xfrin_apply_changeset2(knot_zone_contents_t *contents,
+ xfrin_changes_t *changes,
+ knot_changeset_t *chset)
{
/*
* Applies one changeset to the zone. Checks if the changeset may be
@@ -2481,383 +2713,293 @@ static int xfrin_apply_changeset(knot_zone_contents_t *contents,
return KNOT_ERROR;
}
- int ret = xfrin_apply_remove(contents, chset, changes);
+ int ret = xfrin_apply_remove2(contents, chset, changes);
if (ret != KNOT_EOK) {
- xfrin_clean_changes_after_fail(changes);
+// xfrin_clean_changes_after_fail2(changes);
return ret;
}
- ret = xfrin_apply_add(contents, chset, changes);
+ ret = xfrin_apply_add2(contents, chset, changes);
if (ret != KNOT_EOK) {
- xfrin_clean_changes_after_fail(changes);
+// xfrin_clean_changes_after_fail(changes);
return ret;
}
- /*! \todo Only if SOA is present? */
- return xfrin_apply_replace_soa(contents, changes, chset);
+ return xfrin_apply_replace_soa2(contents, changes, chset);
}
/*----------------------------------------------------------------------------*/
-static void xfrin_check_node_in_tree(knot_zone_tree_node_t *tnode, void *data)
+static void xfrin_mark_empty(knot_node_t *node, void *data)
{
- assert(tnode != NULL);
+ assert(node != NULL);
assert(data != NULL);
- assert(tnode->node != NULL);
-
- xfrin_changes_t *changes = (xfrin_changes_t *)data;
-
- knot_node_t *node = knot_node_get_new_node(tnode->node);
-
- if (node == NULL) {
- // no RRSets were removed from this node, thus it cannot be
- // empty
- return;
- }
- dbg_xfrin("xfrin_check_node_in_tree: children of old node: %u, "
- "children of new node: %u.\n",
- knot_node_children(node),
- knot_node_children(tnode->node));
+ xfrin_changes_t *changes = (xfrin_changes_t *)data;
-
- // check if the node is empty and has no children
- // to be sure, check also the count of children of the old node
if (knot_node_rrset_count(node) == 0
- && knot_node_children(node) == 0
- && knot_node_children(tnode->node) == 0) {
- // in this case the new node copy should be removed
- // but it cannot be deleted because if a rollback happens,
- // the node must be in the new nodes list
- // just add it to the old nodes list so that it is deleted
- // after successful update
-
- // set the new node of the old node to NULL
- knot_node_set_new_node(tnode->node, NULL);
-
- // if the parent has a new copy, decrease the number of
- // children of that copy
- if (knot_node_new_node(knot_node_parent(node, 0))) {
- /*! \todo Replace by some API. */
- --node->parent->new_node->children;
- }
-
- // put the new node to te list of old nodes
- if (xfrin_changes_check_nodes(&changes->old_nodes,
- &changes->old_nodes_count,
- &changes->old_nodes_allocated)
- != KNOT_EOK) {
- /*! \todo Notify about the error!!! */
+ && knot_node_children(node) == 0) {
+ int ret = xfrin_changes_check_nodes(&changes->old_nodes,
+ &changes->old_nodes_count,
+ &changes->old_nodes_allocated);
+ if (ret != KNOT_EOK) {
+ /*! \todo Stop on error? */
return;
}
-
+
changes->old_nodes[changes->old_nodes_count++] = node;
-
- // leave the old node in the old node list, we will delete
- // it later
+
+ if (node->parent != NULL) {
+ assert(node->parent->children > 0);
+ --node->parent->children;
+ if (node->parent->wildcard_child == node) {
+ node->parent->wildcard_child = NULL;
+ }
+ node->parent = NULL;
+ }
}
}
/*----------------------------------------------------------------------------*/
-static int xfrin_finalize_remove_nodes(knot_zone_contents_t *contents,
- xfrin_changes_t *changes)
+static void xfrin_mark_empty_nsec3(knot_node_t *node, void *data)
{
- assert(contents != NULL);
- assert(changes != NULL);
-
- knot_node_t *node;
- knot_zone_tree_node_t *removed;
- ck_hash_table_item_t *rem_hash;
- int ret;
-
- for (int i = 0; i < changes->old_nodes_count; ++i) {
- node = changes->old_nodes[i];
+ assert(node != NULL);
+ assert(data != NULL);
- // if the node is marked as old and has no new node copy
- // remove it from the zone structure but do not delete it
- // that may be done only after the grace period
- if (knot_node_is_old(node)
- && knot_node_new_node(node) == NULL) {
-
- if (knot_node_rrset(node, KNOT_RRTYPE_NSEC3)
- != NULL) {
- ret = knot_zone_contents_remove_nsec3_node(
- contents, node, &removed);
- } else {
- ret = knot_zone_contents_remove_node(
- contents, node, &removed, &rem_hash);
- }
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to remove node from zone"
- "!\n");
- return KNOT_ENONODE;
- }
-
- assert(removed != NULL);
- assert(removed->node == node);
- // delete the tree node (not needed)
- free(removed);
-
- if (rem_hash != NULL) {
- // save the removed hash table item
- ret = xfrin_changes_check_hash_items(
- &changes->old_hash_items,
- &changes->old_hash_items_count,
- &changes->old_hash_items_allocated);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to save the hash"
- " table item to list of "
- "old items.\n");
- return ret;
- }
- changes->old_hash_items[
- changes->old_hash_items_count++]
- = rem_hash;
+ xfrin_changes_t *changes = (xfrin_changes_t *)data;
+
+ if (knot_node_rrset_count(node) == 0
+ && knot_node_children(node) == 0) {
+ int ret = xfrin_changes_check_nodes(&changes->old_nsec3,
+ &changes->old_nsec3_count,
+ &changes->old_nsec3_allocated);
+ if (ret != KNOT_EOK) {
+ /*! \todo Stop on error? */
+ return;
+ }
+
+ changes->old_nsec3[changes->old_nsec3_count++] = node;
+
+ if (node->parent != NULL) {
+ assert(node->parent->children > 0);
+ --node->parent->children;
+ if (node->parent->wildcard_child == node) {
+ node->parent->wildcard_child = NULL;
}
+ node->parent = NULL;
}
}
- return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int xfrin_finalize_contents(knot_zone_contents_t *contents,
- xfrin_changes_t *changes)
+static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
+ xfrin_changes_t *changes)
{
- // don't know what should have been done here, except for one thing:
- // walk through the zone and remove empty nodes (save them in the
- // old nodes list). But only those having no children!!!
-
- /*
- * Walk through the zone and remove empty nodes.
- * We must walk backwards, so that children are processed before
- * their parents. This will allow to remove chain of parent-children
- * nodes.
- * We cannot remove the nodes right away as it would modify the very
- * structure used for walking through the zone. Just put the nodes
- * to the list of old nodes to be removed.
- * We must also decrease the node's parent's children count now
- * and not when deleting the node, so that the chain of parent-child
- * nodes may be removed.
- */
- knot_zone_tree_t *t = knot_zone_contents_get_nodes(contents);
- assert(t != NULL);
-
+ 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);
+
// walk through the zone and select nodes to be removed
- knot_zone_tree_reverse_apply_postorder(t, xfrin_check_node_in_tree,
- (void *)changes);
-
+ ret = knot_zone_contents_tree_apply_inorder_reverse(contents,
+ xfrin_mark_empty,
+ (void *)changes);
+ assert(ret == KNOT_EOK);
+
// Do the same with NSEC3 nodes.
- t = knot_zone_contents_get_nsec3_nodes(contents);
- assert(t != NULL);
-
- knot_zone_tree_reverse_apply_postorder(t, xfrin_check_node_in_tree,
- (void *)changes);
-
- // remove the nodes one by one
- return xfrin_finalize_remove_nodes(contents, changes);
-}
+ ret = knot_zone_contents_nsec3_apply_inorder_reverse(contents,
+ xfrin_mark_empty_nsec3,
+ (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);
-static void xfrin_fix_refs_in_node(knot_zone_tree_node_t *tnode, void *data)
-{
- /*! \todo Passed data is always seto to NULL. */
- assert(tnode != NULL);
- //assert(data != NULL);
+ // remove these nodes from both hash table and the tree
+ ck_hash_table_item_t *hash_item = NULL;
+ knot_zone_tree_node_t *zone_node = NULL;
- //xfrin_changes_t *changes = (xfrin_changes_t *)data;
+ for (int i = 0; i < changes->old_nodes_count; ++i) {
+ zone_node = NULL;
+ hash_item = NULL;
- // 1) Fix the reference to the node to the new one if there is some
- knot_node_t *node = tnode->node;
+ char *name = knot_dname_to_str(knot_node_owner(
+ changes->old_nodes[i]));
+ dbg_xfrin_detail("Old node #%d: %p, %s\n", i,
+ changes->old_nodes[i], name);
+ free(name);
- knot_node_t *new_node = knot_node_get_new_node(node);
- if (new_node != NULL) {
- //assert(knot_node_rrset_count(new_node) > 0);
- node = new_node;
- tnode->node = new_node;
- }
+ ret = knot_zone_contents_remove_node(
+ contents, changes->old_nodes[i], &zone_node,
+ &hash_item);
- // 2) fix references from the node remaining in the zone
- knot_node_update_refs(node);
-}
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to remove node from zone!\n");
+ return KNOT_ENONODE;
+ }
-/*----------------------------------------------------------------------------*/
+ free(hash_item);
+ free(zone_node);
+ knot_node_free(&changes->old_nodes[i], 0);
+ }
+ changes->old_nodes_count = 0;
-static void xfrin_fix_gen_in_node(knot_zone_tree_node_t *tnode, void *data)
-{
- /*! \todo Passed data is always seto to NULL. */
- assert(tnode != NULL);
-
- knot_node_t *node = tnode->node;
+ // remove NSEC3 nodes
+ for (int i = 0; i < changes->old_nsec3_count; ++i) {
+ zone_node = NULL;
- knot_node_set_old(node);
-}
+ char *name = knot_dname_to_str(knot_node_owner(
+ changes->old_nsec3[i]));
+ dbg_xfrin_detail("Old NSEC3 node #%d: %p, %s\n", i,
+ changes->old_nsec3[i], name);
+ free(name);
-/*----------------------------------------------------------------------------*/
+ ret = knot_zone_contents_remove_nsec3_node(
+ contents, changes->old_nsec3[i], &zone_node);
-static void xfrin_fix_hash_refs(ck_hash_table_item_t *item, void *data)
-{
- if (item == NULL) {
- return;
- }
-
- knot_node_t *new_node = knot_node_get_new_node(
- (knot_node_t *)item->value);
- if (new_node != NULL) {
- assert(item->key_length
- == knot_dname_size(knot_node_owner(new_node)));
- assert(strncmp(item->key, (const char *)knot_dname_name(
- knot_node_owner(new_node)), item->key_length) == 0);
- item->value = (void *)new_node;
- item->key = (const char *)knot_dname_name(
- knot_node_owner(new_node));
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to remove NSEC3 node from zone!\n");
+ return KNOT_ENONODE;
+ }
+
+ free(zone_node);
+ knot_node_free(&changes->old_nsec3[i], 0);
}
+ changes->old_nsec3_count = 0;
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static void xfrin_fix_dname_refs(knot_dname_t *dname, void *data)
-{
- UNUSED(data);
- knot_dname_update_node(dname);
-}
+//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 int xfrin_fix_references(knot_zone_contents_t *contents)
+static void xfrin_check_contents_copy_node(knot_node_t *node, void *data)
{
- /*! \todo This function must not fail!! */
+ assert(node != NULL);
+ assert(data != NULL);
- /*
- * Now the contents are already switched, and we should update all
- * references not updated yet, so that the old contents may be removed.
- *
- * Walk through the zone tree, so that each node will be checked
- * and updated.
- */
- // fix references in normal nodes
- knot_zone_tree_t *tree = knot_zone_contents_get_nodes(contents);
- knot_zone_tree_forward_apply_inorder(tree, xfrin_fix_refs_in_node,
- NULL);
+ int *err = (int *)data;
- // fix refereces in NSEC3 nodes
- tree = knot_zone_contents_get_nsec3_nodes(contents);
- knot_zone_tree_forward_apply_inorder(tree, xfrin_fix_refs_in_node,
- NULL);
+ if (*err != KNOT_EOK) {
+ return;
+ }
- // fix references in hash table
- ck_hash_table_t *table = knot_zone_contents_get_hash_table(contents);
- ck_apply(table, xfrin_fix_hash_refs, NULL);
-
- // fix references dname table
- int ret = knot_zone_contents_dname_table_apply(contents,
- xfrin_fix_dname_refs, NULL);
- assert(ret == KNOT_EOK);
-
- return KNOT_EOK;
+ if (knot_node_new_node(node) == NULL) {
+ *err = KNOT_ENONODE;
+ }
}
/*----------------------------------------------------------------------------*/
-static int xfrin_fix_generation(knot_zone_contents_t *contents)
+static int xfrin_check_contents_copy(knot_zone_contents_t *old_contents)
{
- assert(contents != NULL);
-
- knot_zone_tree_t *tree = knot_zone_contents_get_nodes(contents);
- knot_zone_tree_forward_apply_inorder(tree, xfrin_fix_gen_in_node,
- NULL);
-
- tree = knot_zone_contents_get_nsec3_nodes(contents);
- knot_zone_tree_forward_apply_inorder(tree, xfrin_fix_gen_in_node,
- NULL);
-
- return KNOT_EOK;
-}
+ int err = KNOT_EOK;
-/*----------------------------------------------------------------------------*/
+ int ret = knot_zone_contents_tree_apply_inorder(old_contents,
+ xfrin_check_contents_copy_node,
+ &err);
-static void xfrin_cleanup_update(xfrin_changes_t *changes)
-{
- // free old nodes but do not destroy their RRSets
- // remove owners also, because of reference counting
- for (int i = 0; i < changes->old_nodes_count; ++i) {
- dbg_xfrin_detail("Deleting old node: %p\n", changes->old_nodes[i]);
- knot_node_dump(changes->old_nodes[i], 0);
- knot_node_free(&changes->old_nodes[i], 1, 0);
- }
-
- // free old RRSets, and destroy also domain names in them
- // because of reference counting
-
- // check if there are not some duplicate RRSets
-// for (int i = 0; i < changes->old_rrsets_count; ++i) {
-// for (int j = i + 1; j < changes->old_rrsets_count; ++j) {
-// if (changes->old_rrsets[i] == changes->old_rrsets[j]) {
-// assert(0);
-// }
-// if (changes->old_rrsets[i]->rdata != NULL
-// && changes->old_rrsets[i]->rdata
-// == changes->old_rrsets[j]->rdata) {
-// assert(0);
-// }
-// }
-// }
+ assert(ret == KNOT_EOK);
- for (int i = 0; i < changes->old_rrsets_count; ++i) {
-// knot_rrset_deep_free(&changes->old_rrsets[i], 1, 1, 1);
- dbg_xfrin_detail("Deleting old RRSet: %p\n", changes->old_rrsets[i]);
- knot_rrset_dump(changes->old_rrsets[i], 0);
- knot_rrset_free(&changes->old_rrsets[i]);
+ if (err == KNOT_EOK) {
+ ret = knot_zone_contents_nsec3_apply_inorder(old_contents,
+ xfrin_check_contents_copy_node,
+ &err);
}
- // delete old RDATA
- for (int i = 0; i < changes->old_rdata_count; ++i) {
- dbg_xfrin_detail("Deleting old RDATA: %p, type: %s\n",
- changes->old_rdata[i],
- knot_rrtype_to_string(changes->old_rdata_types[i]));
- knot_rdata_dump(changes->old_rdata[i], changes->old_rdata_types[i], 0);
- knot_rdata_t *rdata = changes->old_rdata[i];
- assert(rdata != NULL);
- do {
- knot_rdata_t *tmp = rdata->next;
- knot_rdata_deep_free(&rdata,
- changes->old_rdata_types[i], 1);
- rdata = tmp;
- } while (rdata != NULL && rdata != changes->old_rdata[i]);
- changes->old_rdata[i] = NULL;
- }
-
- // free old hash table items, but do not touch their contents
- for (int i = 0; i < changes->old_hash_items_count; ++i) {
- free(changes->old_hash_items[i]);
+ assert(ret == KNOT_EOK);
+
+ if (knot_node_new_node(knot_zone_contents_apex(old_contents)) == NULL) {
+ return KNOT_ENONODE;
}
- free(changes->old_hash_items);
- // free allocated arrays of nodes and rrsets
- free(changes->new_nodes);
- free(changes->old_nodes);
- free(changes->new_rrsets);
- free(changes->old_rrsets);
- free(changes->old_rdata);
- free(changes->old_rdata_types);
+ return err;
}
/*----------------------------------------------------------------------------*/
-int xfrin_apply_changesets_to_zone(knot_zone_t *zone,
- knot_changesets_t *chsets)
+int xfrin_apply_changesets(knot_zone_t *zone,
+ knot_changesets_t *chsets)
{
if (zone == NULL || chsets == NULL || chsets->count == 0) {
return KNOT_EBADARG;
}
-
+
knot_zone_contents_t *old_contents = knot_zone_get_contents(zone);
if (!old_contents) {
return KNOT_EBADARG;
}
-
+
+ dbg_xfrin("Applying changesets to zone...\n");
+
// dbg_xfrin("\nOLD ZONE CONTENTS:\n\n");
// knot_zone_contents_dump(old_contents, 1);
@@ -2877,137 +3019,116 @@ int xfrin_apply_changesets_to_zone(knot_zone_t *zone,
* updated.
*
* This will create new zone contents structures (normal nodes' tree,
- * NSEC3 tree, hash table, domain name table), but fill them with the
- * data from the old contents.
+ * NSEC3 tree, hash table, domain name table), and copy all nodes.
+ * The data in the nodes (RRSets) remain the same though.
*/
knot_zone_contents_t *contents_copy = NULL;
- int ret = knot_zone_contents_shallow_copy(old_contents,
- &contents_copy);
+ dbg_xfrin("Copying zone contents.\n");
+ int ret = knot_zone_contents_shallow_copy2(old_contents,
+ &contents_copy);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to create shallow copy of zone: %s\n",
knot_strerror(ret));
return ret;
}
- /*
- * Now, apply one changeset after another until all are applied.
- * Changesets may be either from IXFR or from a dynamic update.
- * Dynamic updates use special TYPE and CLASS values to distinguish
- * requests, such as "remove all RRSets from a node", "remove all RRs
- * with the specified type from a node", etc.
- *
- * When updating anything within some node (removing RR, adding RR),
- * the node structure is copied, but the RRSets within are not.
- *
- * 1) When removing RRs from node, The affected RRSet is copied. This
- * it also a 'shallow copy', i.e. the RDATA remain the exact same.
- * The specified RRs (i.e. RDATA) are then removed from the copied
- * RRSet.
- * 2) When adding RRs to node, there are two cases:
- * a) If there is a RRSet that should contain these RRs
- * this RRSet is copied (shallow copy) and the RRs are added to
- * it (rrset_merge()).
- * b) If there is not such a RRSet, the whole RRSet from the
- * changeset is added to the new node (thus this RRSet must not
- * be deleted afterwards).
- *
- * A special case are RRSIG RRs. These functions assume that they
- * are grouped together in knot_rrset_t structures according to
- * their header (owner, type, class) AND their 'type covered', i.e.
- * there may be more RRSIG RRSets in one changeset (while there
- * should not be more RRSets of any other type).
- * 3) When removing RRSIG RRs from node, the appropriate RRSet holding
- * them must be found (according to the 'type covered' field). This
- * RRSet is then copied (shallow copy), Its RRSIGs are also copied
- * and the RRSIG RRs are added to the RRSIG copy.
- * 4) When adding RRSIG RRs to node, the same process is done - the
- * proper RRSet holding them is found, copied, its RRSIGs are
- * copied (if there are some) and the RRs are added to the copy.
- *
- * When a node is copied, reference to the copy is stored within the
- * old node (node_t.old_node). This is important, because when the
- * zone contents are switched to the new ones, references from old nodes
- * that should point to new nodes are not yet set (it would influence
- * replying from the old zone contents). While all these references
- * (such as node_t.prev, node_t.next, node_t.parent, etc.) are properly
- * modified, the search functions use old or new nodes accordingly
- * (old nodes while old contents are used, new nodes when new contents
- * are used). The 'check_version' parameter turns on this behaviour in
- * search functions.
- *
- * In case of error, we must remove all data created by the update, i.e.
- * - new nodes,
- * - new RRSets,
- * and remove the references to the new nodes from old nodes.
- *
- * In case of success, the RRSet structures from the changeset
- * structures must not be deleted, as they are either already used by
- * the server (stored within the new zone contents) or deleted when
- * cleaning up the temporary 'changes' structure.
- */
xfrin_changes_t changes;
memset(&changes, 0, sizeof(xfrin_changes_t));
+ /*!
+ * \todo Check if all nodes have their copy.
+ */
+ ret = xfrin_check_contents_copy(old_contents);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Contents copy check failed!\n");
+ xfrin_rollback_update2(old_contents, contents_copy, &changes);
+ return ret;
+ }
+
+ assert(knot_zone_contents_apex(contents_copy) != NULL);
+
+ /*
+ * Fix references to new nodes. Some references in new nodes may point
+ * to old nodes. Hash table contains only old nodes.
+ */
+ dbg_xfrin("Switching ptrs pointing to old nodes to the new nodes.\n");
+ ret = xfrin_switch_nodes(contents_copy);
+ assert(knot_zone_contents_apex(contents_copy) != NULL);
+
+ /*
+ * Apply the changesets.
+ */
+ dbg_xfrin("Applying changesets.\n");
+ dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
+ old_contents->apex, contents_copy->apex);
for (int i = 0; i < chsets->count; ++i) {
- if ((ret = xfrin_apply_changeset(contents_copy, &changes,
- &chsets->sets[i])) != KNOT_EOK) {
- xfrin_rollback_update(contents_copy, &changes);
+ if ((ret = xfrin_apply_changeset2(contents_copy, &changes,
+ &chsets->sets[i]))
+ != KNOT_EOK) {
+ xfrin_rollback_update2(old_contents,
+ contents_copy, &changes);
dbg_xfrin("Failed to apply changesets to zone: "
"%s\n", knot_strerror(ret));
return ret;
}
}
+ assert(knot_zone_contents_apex(contents_copy) != NULL);
+
+ /*!
+ * \todo Test failure of IXFR.
+ */
/*
- * When all changesets are applied, set generation 1 to the copy of
- * the zone so that new nodes are used instead of old ones.
+ * Finalize the new zone contents:
+ * - delete empty nodes
+ * - parse NSEC3PARAM
+ * - do adjusting of nodes and RDATA
+ * - ???
*/
-// knot_zone_contents_switch_generation(contents_copy);
- //contents_copy->generation = 1;
- knot_zone_contents_set_gen_new(contents_copy);
/*
- * Finalize the zone contents.
+ * Select and delete empty nodes.
*/
- ret = xfrin_finalize_contents(contents_copy, &changes);
+ ret = xfrin_remove_empty_nodes(contents_copy, &changes);
if (ret != KNOT_EOK) {
- xfrin_rollback_update(contents_copy, &changes);
- dbg_xfrin("Failed to finalize new zone contents: %s\n",
+ dbg_xfrin("Failed to remove empty nodes: %s\n",
knot_strerror(ret));
+ xfrin_rollback_update2(old_contents, contents_copy, &changes);
return ret;
}
- /*
- * Switch the zone contents
- */
+
+ dbg_xfrin("Adjusting zone contents.\n");
+ dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
+ old_contents->apex, contents_copy->apex);
+// ret = xfrin_adjust_contents(contents_copy, &changes);
+ ret = knot_zone_contents_adjust(contents_copy);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to finalize zone contents: %s\n",
+ knot_strerror(ret));
+ xfrin_rollback_update2(old_contents, contents_copy, &changes);
+ return ret;
+ }
+ assert(knot_zone_contents_apex(contents_copy) != NULL);
+
+ dbg_xfrin("Checking zone for CNAME loops.\n");
+ ret = knot_zone_contents_check_loops(contents_copy);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("CNAME loop check failed: %s\n", knot_strerror(ret));
+ xfrin_rollback_update2(old_contents, contents_copy, &changes);
+ return ret;
+ }
+
+ dbg_xfrin("Switching zone contents.\n");
+ dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
+ old_contents->apex, contents_copy->apex);
knot_zone_contents_t *old =
knot_zone_switch_contents(zone, contents_copy);
assert(old == old_contents);
- /*
- * From now on, the new contents of the zone are being used.
- * References to nodes may be updated in the meantime. However, we must
- * traverse the zone and fix all references that were not.
- */
- /*! \todo This operation must not fail!!! .*/
- ret = xfrin_fix_references(contents_copy);
- assert(ret == KNOT_EOK);
-
- // set generation to finished
- knot_zone_contents_set_gen_new_finished(contents_copy);
-
- // set generation of all nodes to the old one
- // now it is safe (no old nodes should be referenced)
- ret = xfrin_fix_generation(contents_copy);
- assert(ret == KNOT_EOK);
-
- /*
- * Now we may also set the generation back to 0 so that another
- * update is possible.
- */
- knot_zone_contents_set_gen_old(contents_copy);
-
+ dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
+ old_contents->apex, contents_copy->apex);
/*
* Wait until all readers finish reading
*/
@@ -3016,6 +3137,7 @@ int xfrin_apply_changesets_to_zone(knot_zone_t *zone,
/*
* Delete all old and unused data.
*/
+ dbg_xfrin("Cleaning up.\n");
xfrin_zone_contents_free(&old_contents);
xfrin_cleanup_update(&changes);
diff --git a/src/libknot/updates/xfr-in.h b/src/libknot/updates/xfr-in.h
index bb1b98b..233527b 100644
--- a/src/libknot/updates/xfr-in.h
+++ b/src/libknot/updates/xfr-in.h
@@ -181,6 +181,9 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr/*const uint8_t *pkt, size_t siz
int xfrin_apply_changesets_to_zone(knot_zone_t *zone,
knot_changesets_t *chsets);
+int xfrin_apply_changesets(knot_zone_t *zone,
+ knot_changesets_t *chsets);
+
#endif /* _KNOTXFR_IN_H_ */
/*! @} */
diff --git a/src/libknot/util/debug.c b/src/libknot/util/debug.c
index 0ca67c9..78cd4a4 100644
--- a/src/libknot/util/debug.c
+++ b/src/libknot/util/debug.c
@@ -47,8 +47,8 @@ void knot_rdata_dump(knot_rdata_t *rdata, uint32_t type, char loaded_zone)
desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ) {
assert(rdata->items[i].dname != NULL);
name = knot_dname_to_str(rdata->items[i].dname);
- fprintf(stderr, " DNAME: %d: %s\n",
- i, name);
+ fprintf(stderr, " DNAME: %d: %s (%p)\n",
+ i, name, rdata->items[i].dname);
free(name);
if (loaded_zone) {
if (rdata->items[i].dname->node) {
diff --git a/src/libknot/util/debug.h b/src/libknot/util/debug.h
index 2c03c9c..a7eb86a 100644
--- a/src/libknot/util/debug.h
+++ b/src/libknot/util/debug.h
@@ -57,10 +57,10 @@
//#define KNOT_NSEC3_DEBUG
//#define CUCKOO_DEBUG
//#define CUCKOO_DEBUG_HASH
-#define KNOT_NS_DEBUG
+//#define KNOT_NS_DEBUG
//#define KNOT_XFRIN_DEBUG
//#define KNOT_DDNS_DEBUG
-#define KNOT_TSIG_DEBUG
+//#define KNOT_TSIG_DEBUG
/*!
* \brief Dumps RDATA of the given type.
diff --git a/src/libknot/util/error.h b/src/libknot/util/error.h
index 2f34a28..317c681 100644
--- a/src/libknot/util/error.h
+++ b/src/libknot/util/error.h
@@ -65,7 +65,8 @@ enum knot_error {
KNOT_EXFRREFUSED, /*!< Zone transfer refused by the server. */
KNOT_ECONN, /*!< Connection reset. */
KNOT_EIXFRSPACE, /*!< IXFR reply did not fit in. */
- KNOT_ERROR_COUNT = 31
+ KNOT_ECNAME, /*!< CNAME loop found in zone. */
+ KNOT_ERROR_COUNT = 32
};
/*! \brief Table linking error messages to error codes. */
diff --git a/src/libknot/util/libknot_error.c b/src/libknot/util/libknot_error.c
index 5795a23..d922afb 100644
--- a/src/libknot/util/libknot_error.c
+++ b/src/libknot/util/libknot_error.c
@@ -50,5 +50,6 @@ const error_table_t knot_error_msgs[KNOT_ERROR_COUNT] = {
{KNOT_TSIG_EBADTIME, "TSIG signing time out of range." },
{KNOT_ECONN, "Connection reset."},
{KNOT_EIXFRSPACE, "IXFR reply did not fit in."},
+ {KNOT_ECNAME, "CNAME loop found in zone."},
{KNOT_ERROR, 0}
};
diff --git a/src/libknot/util/utils.h b/src/libknot/util/utils.h
index f43b8f0..ba7a6d2 100644
--- a/src/libknot/util/utils.h
+++ b/src/libknot/util/utils.h
@@ -89,6 +89,8 @@ size_t knot_strlcpy(char *dst, const char *src, size_t size);
*
* \param pos Data to read the 2 bytes from.
*
+ * \todo Wrong assumption of endianness (issue #1558).
+ *
* \return The 2 bytes read, in inverse endian.
*/
static inline uint16_t knot_wire_read_u16(const uint8_t *pos)
@@ -101,6 +103,8 @@ static inline uint16_t knot_wire_read_u16(const uint8_t *pos)
*
* \param pos Data to read the 4 bytes from.
*
+ * \todo Wrong assumption of endianness (issue #1558).
+ *
* \return The 4 bytes read, in inverse endian.
*/
static inline uint32_t knot_wire_read_u32(const uint8_t *pos)
@@ -113,6 +117,8 @@ static inline uint32_t knot_wire_read_u32(const uint8_t *pos)
*
* \param pos Data to read the 6 bytes from.
*
+ * \todo Wrong assumption of endianness (issue #1558).
+ *
* \return The 6 bytes read, in inverse endian.
*/
static inline uint64_t knot_wire_read_u48(const uint8_t *pos)
@@ -126,13 +132,15 @@ static inline uint64_t knot_wire_read_u48(const uint8_t *pos)
*
* The endian of the data is inverted.
*
+ * \todo Wrong assumption of endianness (issue #1558).
+ *
* \param pos Position where to put the 2 bytes.
* \param data Data to put.
*/
static inline void knot_wire_write_u16(uint8_t *pos, uint16_t data)
{
- pos[0] = (uint8_t)((data >> 8) & 0xff);
- pos[1] = (uint8_t)(data & 0xff);
+ *(pos++) = (uint8_t)((data >> 8) & 0xff);
+ *pos = (uint8_t)(data & 0xff);
}
/*!
@@ -140,15 +148,17 @@ static inline void knot_wire_write_u16(uint8_t *pos, uint16_t data)
*
* The endian of the data is inverted.
*
+ * \todo Wrong assumption of endianness (issue #1558).
+ *
* \param pos Position where to put the 4 bytes.
* \param data Data to put.
*/
static inline void knot_wire_write_u32(uint8_t *pos, uint32_t data)
{
- pos[0] = (uint8_t)((data >> 24) & 0xff);
- pos[1] = (uint8_t)((data >> 16) & 0xff);
- pos[2] = (uint8_t)((data >> 8) & 0xff);
- pos[3] = (uint8_t)(data & 0xff);
+ *(pos++) = (uint8_t)((data >> 24) & 0xff);
+ *(pos++) = (uint8_t)((data >> 16) & 0xff);
+ *(pos++) = (uint8_t)((data >> 8) & 0xff);
+ *pos = (uint8_t)(data & 0xff);
}
/*!
@@ -156,17 +166,19 @@ static inline void knot_wire_write_u32(uint8_t *pos, uint32_t data)
*
* The endian of the data is inverted.
*
+ * \todo Wrong assumption of endianness (issue #1558).
+ *
* \param pos Position where to put the 4 bytes.
* \param data Data to put.
*/
static inline void knot_wire_write_u48(uint8_t *pos, uint64_t data)
{
- pos[0] = (uint8_t)((data >> 40) & 0xff);
- pos[1] = (uint8_t)((data >> 32) & 0xff);
- pos[2] = (uint8_t)((data >> 24) & 0xff);
- pos[3] = (uint8_t)((data >> 16) & 0xff);
- pos[4] = (uint8_t)((data >> 8) & 0xff);
- pos[5] = (uint8_t)(data & 0xff);
+ *(pos++) = (uint8_t)((data >> 40) & 0xff);
+ *(pos++) = (uint8_t)((data >> 32) & 0xff);
+ *(pos++) = (uint8_t)((data >> 24) & 0xff);
+ *(pos++) = (uint8_t)((data >> 16) & 0xff);
+ *(pos++) = (uint8_t)((data >> 8) & 0xff);
+ *pos = (uint8_t)(data & 0xff);
}
/*!
diff --git a/src/libknot/zone/dname-table.c b/src/libknot/zone/dname-table.c
index c41b4bd..d2d97c2 100644
--- a/src/libknot/zone/dname-table.c
+++ b/src/libknot/zone/dname-table.c
@@ -217,7 +217,6 @@ int knot_dname_table_add_dname_check(knot_dname_table_t *table,
return 1; /*! \todo Error code? */
} else {
-
/* If the dname is already in the table, there is already
* a reference to it.
*/
@@ -308,3 +307,19 @@ void knot_dname_table_tree_inorder_apply(const knot_dname_table_t *table,
knot_dname_table_apply, &d);
}
+static void knot_dump_node_of_table(knot_dname_t *dname, void *data)
+{
+ UNUSED(data);
+ char *name = knot_dname_to_str(dname);
+ fprintf(stderr, "%s (%p)\n", name, dname);
+ free(name);
+}
+
+void knot_dname_table_dump(const knot_dname_table_t *table)
+{
+ fprintf(stderr, "-------DNAME TABLE-------\n");
+ knot_dname_table_tree_inorder_apply(table, knot_dump_node_of_table,
+ NULL);
+ fprintf(stderr, "-----END DNAME TABLE-----\n");
+}
+
diff --git a/src/libknot/zone/dname-table.h b/src/libknot/zone/dname-table.h
index dd86eaf..945b6de 100644
--- a/src/libknot/zone/dname-table.h
+++ b/src/libknot/zone/dname-table.h
@@ -162,6 +162,14 @@ void knot_dname_table_tree_inorder_apply(const knot_dname_table_t *table,
void *data);
+/*!
+ * \brief Dumps dname table to stderr.
+ *
+ * \param table Table to be dumped.
+ */
+void knot_dname_table_dump(const knot_dname_table_t *table);
+
+
#endif // _KNOT_DNAME_TABLE_H_
/*! @} */
diff --git a/src/libknot/zone/node.c b/src/libknot/zone/node.c
index 61ef3e4..27eb7f2 100644
--- a/src/libknot/zone/node.c
+++ b/src/libknot/zone/node.c
@@ -81,67 +81,67 @@ static inline void knot_node_flags_set_nonauth(uint8_t *flags)
*flags |= KNOT_NODE_FLAGS_NONAUTH;
}
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Returns the old node flag
- *
- * \param flags Flags to retrieve the flag from.
- *
- * \return A byte with only the old node flag set if it was set in \a flags.
- */
-static inline uint8_t knot_node_flags_get_old(uint8_t flags)
-{
- return flags & KNOT_NODE_FLAGS_OLD;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Sets the old node flag.
- *
- * \param flags Flags to set the flag in.
- */
-static inline void knot_node_flags_set_new(uint8_t *flags)
-{
- *flags |= KNOT_NODE_FLAGS_NEW;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Returns the new node flag
- *
- * \param flags Flags to retrieve the flag from.
- *
- * \return A byte with only the new node flag set if it was set in \a flags.
- */
-static inline uint8_t knot_node_flags_get_new(uint8_t flags)
-{
- return flags & KNOT_NODE_FLAGS_NEW;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Sets the new node flag.
- *
- * \param flags Flags to set the flag in.
- */
-static inline void knot_node_flags_set_old(uint8_t *flags)
-{
- *flags |= KNOT_NODE_FLAGS_OLD;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static inline void knot_node_flags_clear_new(uint8_t *flags)
-{
- *flags &= ~KNOT_NODE_FLAGS_NEW;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static inline void knot_node_flags_clear_old(uint8_t *flags)
-{
- *flags &= ~KNOT_NODE_FLAGS_OLD;
-}
+///*----------------------------------------------------------------------------*/
+///*!
+// * \brief Returns the old node flag
+// *
+// * \param flags Flags to retrieve the flag from.
+// *
+// * \return A byte with only the old node flag set if it was set in \a flags.
+// */
+//static inline uint8_t knot_node_flags_get_old(uint8_t flags)
+//{
+// return flags & KNOT_NODE_FLAGS_OLD;
+//}
+
+///*----------------------------------------------------------------------------*/
+///*!
+// * \brief Sets the old node flag.
+// *
+// * \param flags Flags to set the flag in.
+// */
+//static inline void knot_node_flags_set_new(uint8_t *flags)
+//{
+// *flags |= KNOT_NODE_FLAGS_NEW;
+//}
+
+///*----------------------------------------------------------------------------*/
+///*!
+// * \brief Returns the new node flag
+// *
+// * \param flags Flags to retrieve the flag from.
+// *
+// * \return A byte with only the new node flag set if it was set in \a flags.
+// */
+//static inline uint8_t knot_node_flags_get_new(uint8_t flags)
+//{
+// return flags & KNOT_NODE_FLAGS_NEW;
+//}
+
+///*----------------------------------------------------------------------------*/
+///*!
+// * \brief Sets the new node flag.
+// *
+// * \param flags Flags to set the flag in.
+// */
+//static inline void knot_node_flags_set_old(uint8_t *flags)
+//{
+// *flags |= KNOT_NODE_FLAGS_OLD;
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//static inline void knot_node_flags_clear_new(uint8_t *flags)
+//{
+// *flags &= ~KNOT_NODE_FLAGS_NEW;
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//static inline void knot_node_flags_clear_old(uint8_t *flags)
+//{
+// *flags &= ~KNOT_NODE_FLAGS_OLD;
+//}
/*----------------------------------------------------------------------------*/
/*!
@@ -167,30 +167,30 @@ static int compare_rrset_types(void *rr1, void *rr2)
/*----------------------------------------------------------------------------*/
-static int knot_node_zone_gen_is_new(const knot_node_t *node)
-{
- assert(node->zone != NULL);
- knot_zone_contents_t *cont = rcu_dereference(node->zone->contents);
- assert(cont != NULL);
- return knot_zone_contents_gen_is_new(cont);
-}
+//static int knot_node_zone_gen_is_new(const knot_node_t *node)
+//{
+// assert(node->zone != NULL);
+// knot_zone_contents_t *cont = rcu_dereference(node->zone->contents);
+// assert(cont != NULL);
+// return knot_zone_contents_gen_is_new(cont);
+//}
-/*----------------------------------------------------------------------------*/
+///*----------------------------------------------------------------------------*/
-static int knot_node_zone_gen_is_old(const knot_node_t *node)
-{
- assert(node->zone != NULL);
- knot_zone_contents_t *cont = rcu_dereference(node->zone->contents);
- assert(cont != NULL);
- return knot_zone_contents_gen_is_old(cont);
-}
+//static int knot_node_zone_gen_is_old(const knot_node_t *node)
+//{
+// assert(node->zone != NULL);
+// knot_zone_contents_t *cont = rcu_dereference(node->zone->contents);
+// assert(cont != NULL);
+// return knot_zone_contents_gen_is_old(cont);
+//}
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
knot_node_t *knot_node_new(knot_dname_t *owner, knot_node_t *parent,
- uint8_t flags)
+ uint8_t flags)
{
knot_node_t *ret = (knot_node_t *)calloc(1, sizeof(knot_node_t));
if (ret == NULL) {
@@ -289,13 +289,20 @@ short knot_node_rrset_count(const knot_node_t *node)
struct knot_node_save_rrset_arg {
knot_rrset_t **array;
size_t count;
+ size_t max_count;
};
static void save_rrset_to_array(void *node, void *data)
{
- knot_rrset_t *rrset = (knot_rrset_t *)node;
struct knot_node_save_rrset_arg *args =
(struct knot_node_save_rrset_arg *)data;
+ knot_rrset_t *rrset = (knot_rrset_t *)node;
+
+ if (args->count > args->max_count) {
+ ++args->count;
+ return;
+ }
+
args->array[args->count++] = rrset;
}
@@ -311,9 +318,9 @@ knot_rrset_t **knot_node_get_rrsets(const knot_node_t *node)
struct knot_node_save_rrset_arg args;
args.array = rrsets;
args.count = 0;
+ args.max_count = node->rrset_count;
- gen_tree_apply_inorder(node->rrset_tree, save_rrset_to_array,
- &args);
+ gen_tree_apply_inorder(node->rrset_tree, save_rrset_to_array, &args);
assert(args.count == node->rrset_count);
@@ -329,41 +336,54 @@ const knot_rrset_t **knot_node_rrsets(const knot_node_t *node)
/*----------------------------------------------------------------------------*/
-const knot_node_t *knot_node_parent(const knot_node_t *node,
- int check_version)
+static void count_rrsets(void *node, void *data)
{
-// assert(!check_version
-// || (node->zone != NULL && node->zone->contents != NULL));
-
- knot_node_t *parent = node->parent;
-
- if (check_version && node->zone != NULL) {
- int new_gen = knot_node_zone_gen_is_new(node);
-// short ver = knot_node_zone_generation(node);
-
- /*! \todo Remove, this will not be true during the reference
- * fixing.
- */
-// assert(new_gen || parent == NULL
-// || !knot_node_is_new(parent));
-
- if (new_gen && parent != NULL) {
- // we want the new node
- assert(node->parent->new_node != NULL);
- parent = parent->new_node;
- }
+ assert(node != NULL);
+ assert(data != NULL);
+
+ int *count = (int *)data;
+ ++(*count);
+}
+
+/*----------------------------------------------------------------------------*/
+
+int knot_node_count_rrsets(const knot_node_t *node)
+{
+ int count = 0;
+ gen_tree_apply_inorder(node->rrset_tree, count_rrsets, (void *)&count);
+
+ return count;
+}
+
+/*----------------------------------------------------------------------------*/
+
+const knot_node_t *knot_node_parent(const knot_node_t *node)
+{
+ return knot_node_get_parent(node);
+}
+
+/*----------------------------------------------------------------------------*/
+
+knot_node_t *knot_node_get_parent(const knot_node_t *node)
+{
+ if (node == NULL) {
+ return NULL;
}
-
- return parent;
+
+ return node->parent;
}
/*----------------------------------------------------------------------------*/
void knot_node_set_parent(knot_node_t *node, knot_node_t *parent)
{
+ if (node->parent == parent) {
+ return;
+ }
+
// decrease number of children of previous parent
if (node->parent != NULL) {
- --parent->children;
+ --node->parent->children;
}
// set the parent
node->parent = parent;
@@ -383,45 +403,27 @@ unsigned int knot_node_children(const knot_node_t *node)
/*----------------------------------------------------------------------------*/
-const knot_node_t *knot_node_previous(const knot_node_t *node,
- int check_version)
+const knot_node_t *knot_node_previous(const knot_node_t *node)
{
- return knot_node_get_previous(node, check_version);
+ return knot_node_get_previous(node);
}
/*----------------------------------------------------------------------------*/
-knot_node_t *knot_node_get_previous(const knot_node_t *node,
- int check_version)
+knot_node_t *knot_node_get_previous(const knot_node_t *node)
{
- assert(!check_version
- || (node->zone != NULL && node->zone->contents != NULL));
-
- knot_node_t *prev = node->prev;
-
- if (check_version && prev != NULL) {
- 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) { // we want old node
- while (knot_node_is_new(prev)) {
- prev = prev->prev;
- }
- assert(!knot_node_is_new(prev));
- } else if (new_gen) { // we want new node
- while (knot_node_is_old(prev)) {
- if (prev->new_node) {
- prev = prev->new_node;
- } else {
- prev = prev;
- }
- }
- assert(knot_node_is_new(prev));
- }
+ if (node == NULL) {
+ return NULL;
}
- return prev;
+ return node->prev;
+}
+
+/*----------------------------------------------------------------------------*/
+
+const knot_node_t *knot_node_next(const knot_node_t *node)
+{
+ return node->next;
}
/*----------------------------------------------------------------------------*/
@@ -429,48 +431,24 @@ knot_node_t *knot_node_get_previous(const knot_node_t *node,
void knot_node_set_previous(knot_node_t *node, knot_node_t *prev)
{
node->prev = prev;
- if (prev != NULL) {
- // set the prev pointer of the next node to the given node
- if (prev->next != NULL) {
- assert(prev->next->prev == prev);
- prev->next->prev = node;
- }
- node->next = prev->next;
- prev->next = node;
- }
}
/*----------------------------------------------------------------------------*/
-knot_node_t *knot_node_get_nsec3_node(const knot_node_t *node,
- int check_version)
+knot_node_t *knot_node_get_nsec3_node(const knot_node_t *node)
{
- knot_node_t *nsec3_node = node->nsec3_node;
- if (nsec3_node == NULL) {
+ if (node == NULL) {
return NULL;
}
- if (check_version) {
- 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);
- assert(new_gen || !knot_node_is_new(nsec3_node));
- if (old_gen && knot_node_is_new(nsec3_node)) {
- return NULL;
- } else if (new_gen && knot_node_is_old(nsec3_node)) {
- nsec3_node = nsec3_node->new_node;
- }
- }
-
- return nsec3_node;
+ return node->nsec3_node;
}
/*----------------------------------------------------------------------------*/
-const knot_node_t *knot_node_nsec3_node(const knot_node_t *node,
- int check_version)
+const knot_node_t *knot_node_nsec3_node(const knot_node_t *node)
{
- return knot_node_get_nsec3_node(node, check_version);
+ return knot_node_get_nsec3_node(node);
}
/*----------------------------------------------------------------------------*/
@@ -511,31 +489,19 @@ void knot_node_set_owner(knot_node_t *node, knot_dname_t* owner)
/*----------------------------------------------------------------------------*/
-const knot_node_t *knot_node_wildcard_child(const knot_node_t *node,
- int check_version)
+knot_node_t *knot_node_get_wildcard_child(const knot_node_t *node)
{
- knot_node_t *w = node->wildcard_child;
-
- if (check_version && w != 0) {
- 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(w)) {
- return NULL;
- } else if (new_gen && knot_node_is_old(w)) {
- assert(w->new_node != NULL);
- w = w->new_node;
- }
+ if (node == NULL) {
+ return NULL;
}
-
- return w;
+
+ return node->wildcard_child;
}
/*----------------------------------------------------------------------------*/
void knot_node_set_wildcard_child(knot_node_t *node,
- knot_node_t *wildcard_child)
+ knot_node_t *wildcard_child)
{
node->wildcard_child = wildcard_child;
// assert(wildcard_child->parent == node);
@@ -543,52 +509,59 @@ void knot_node_set_wildcard_child(knot_node_t *node,
/*----------------------------------------------------------------------------*/
-const knot_node_t *knot_node_current(const knot_node_t *node)
+const knot_node_t *knot_node_wildcard_child(const knot_node_t *node)
{
- if (node == NULL || node->zone == NULL
- || knot_zone_contents(node->zone) == NULL) {
- return node;
- }
+ return knot_node_get_wildcard_child(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;
-}
+//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;
- }
+//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);
+// 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;
- }
+// 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));
+// assert((old_gen && knot_node_is_old(node))
+// || (new_gen && knot_node_is_new(node))
+// || (!old_gen && !new_gen));
- return node;
-}
+// return node;
+//}
/*----------------------------------------------------------------------------*/
@@ -623,7 +596,10 @@ 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)) {
+// if (*ref != NULL && knot_node_is_old(*ref)) {
+// *ref = (*ref)->new_node;
+// }
+ if (*ref != NULL && (*ref)->new_node != NULL) {
*ref = (*ref)->new_node;
}
}
@@ -632,52 +608,18 @@ void knot_node_update_ref(knot_node_t **ref)
void knot_node_update_refs(knot_node_t *node)
{
- /* CLEANUP */
- /* OMG! */
// reference to previous node
knot_node_update_ref(&node->prev);
-// if (node->prev && knot_node_is_old(node->prev)) {
-// assert(node->prev->new_node != NULL);
-// node->prev = node->prev->new_node;
-// }
-
// reference to next node
knot_node_update_ref(&node->next);
-// if (node->next && knot_node_is_old(node->next)) {
-// assert(node->next->new_node != NULL);
-// node->next = node->next->new_node;
-// }
-
// reference to parent
-// if (node->parent && knot_node_is_old(node->parent)) {
-// assert(node->parent->new_node != NULL);
-// // do not use the API function to set parent, so that children count
-// // is not changed
-// //knot_node_set_parent(node, node->parent->new_node);
-// node->parent = node->parent->new_node;
-// }
knot_node_update_ref(&node->parent);
-
// reference to wildcard child
knot_node_update_ref(&node->wildcard_child);
-// if (node->wildcard_child && knot_node_is_old(node->wildcard_child)) {
-// assert(node->wildcard_child->new_node != NULL);
-// node->wildcard_child = node->wildcard_child->new_node;
-// }
-
// reference to NSEC3 node
knot_node_update_ref(&node->nsec3_node);
-// if (node->nsec3_node && knot_node_is_old(node->nsec3_node)) {
-// assert(node->nsec3_node->new_node != NULL);
-// node->nsec3_node = node->nsec3_node->new_node;
-// }
-
// reference to NSEC3 referrer
knot_node_update_ref(&node->nsec3_referer);
-// if (node->nsec3_referer && knot_node_is_old(node->nsec3_referer)) {
-// assert(node->nsec3_referer->new_node != NULL);
-// node->nsec3_referer = node->nsec3_referer->new_node;
-// }
}
/*----------------------------------------------------------------------------*/
@@ -715,47 +657,47 @@ int knot_node_is_auth(const knot_node_t *node)
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_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);
-}
+//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_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_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_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);
-}
+//void knot_node_clear_old(knot_node_t *node)
+//{
+// knot_node_flags_clear_old(&node->flags);
+//}
/*----------------------------------------------------------------------------*/
@@ -790,23 +732,28 @@ void knot_node_free_rrsets(knot_node_t *node, int free_rdata_dnames)
/*----------------------------------------------------------------------------*/
-void knot_node_free(knot_node_t **node, int free_owner, int fix_refs)
+void knot_node_free(knot_node_t **node, int fix_refs)
{
if (node == NULL || *node == NULL) {
return;
}
- dbg_node("Freeing node.\n");
+ dbg_node("Freeing node: %p\n", *node);
+
if ((*node)->rrset_tree != NULL) {
dbg_node("Freeing RRSets.\n");
gen_tree_destroy(&(*node)->rrset_tree, NULL, NULL);
}
- /*! \todo Always release owner? */
- //if (free_owner) {
- dbg_node("Releasing owner.\n");
- knot_dname_release((*node)->owner);
- //}
+ // set owner's node pointer to NULL, but only if the 'node' does
+ // not point to the owner's node
+ if (node != &(*node)->owner->node
+ && knot_dname_node(knot_node_owner(*node)) == *node) {
+ knot_dname_set_node((*node)->owner, NULL);
+ }
+
+ dbg_node("Releasing owner.\n");
+ knot_dname_release((*node)->owner);
// check nodes referencing this node and fix the references
@@ -866,11 +813,14 @@ 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)
{
// create new node
- *to = knot_node_new(from->owner, from->parent, from->flags);
+ *to = knot_node_new(from->owner, NULL, from->flags);
if (*to == NULL) {
return KNOT_ENOMEM;
}
+ // set the parent by hand, so that the children count is not affected
+ (*to)->parent = from->parent;
+
/* Free old rrset_tree, as it will be replaced by shallow copy. */
gen_tree_destroy(&(*to)->rrset_tree, 0, 0);
@@ -880,11 +830,8 @@ int knot_node_shallow_copy(const knot_node_t *from, knot_node_t **to)
memcpy(*to, from, sizeof(knot_node_t));
// copy RRSets
- // copy the skip list with the old references
- /* CLEANUP */
(*to)->rrset_tree = gen_tree_shallow_copy(from->rrset_tree);
-// assert((*to)->rrset_tree != from->rrset_tree);
-// (*to)->rrsets = skip_copy_list(from->rrsets);
+
if ((*to)->rrset_tree == NULL) {
free(*to);
*to = NULL;
diff --git a/src/libknot/zone/node.h b/src/libknot/zone/node.h
index eb0d242..583f248 100644
--- a/src/libknot/zone/node.h
+++ b/src/libknot/zone/node.h
@@ -204,6 +204,8 @@ knot_rrset_t **knot_node_get_rrsets(const knot_node_t *node);
*/
const knot_rrset_t **knot_node_rrsets(const knot_node_t *node);
+int knot_node_count_rrsets(const knot_node_t *node);
+
/*!
* \brief Returns the parent of the node.
*
@@ -212,8 +214,9 @@ const knot_rrset_t **knot_node_rrsets(const knot_node_t *node);
* \return Parent node of the given node or NULL if no parent has been set (e.g.
* node in a zone apex has no parent).
*/
-const knot_node_t *knot_node_parent(const knot_node_t *node,
- int check_version);
+const knot_node_t *knot_node_parent(const knot_node_t *node);
+
+knot_node_t *knot_node_get_parent(const knot_node_t *node);
/*!
* \brief Sets the parent of the node.
@@ -235,8 +238,7 @@ unsigned int knot_node_children(const knot_node_t *node);
* the first node in zone if \a node is the last node in zone.
* \retval NULL if previous node is not set.
*/
-const knot_node_t *knot_node_previous(const knot_node_t *node,
- int check_version);
+const knot_node_t *knot_node_previous(const knot_node_t *node);
/*!
* \brief Returns the previous authoritative node or delegation point in
@@ -251,8 +253,9 @@ const knot_node_t *knot_node_previous(const knot_node_t *node,
* the first node in zone if \a node is the last node in zone.
* \retval NULL if previous node is not set.
*/
-knot_node_t *knot_node_get_previous(const knot_node_t *node,
- int check_version);
+knot_node_t *knot_node_get_previous(const knot_node_t *node);
+
+const knot_node_t *knot_node_next(const knot_node_t *node);
/*!
* \brief Sets the previous node of the given node.
@@ -272,8 +275,7 @@ void knot_node_set_previous(knot_node_t *node, knot_node_t *prev);
* and the name of the zone \a node belongs to).
* \retval NULL if the NSEC3 node is not set.
*/
-knot_node_t *knot_node_get_nsec3_node(const knot_node_t *node,
- int check_version);
+knot_node_t *knot_node_get_nsec3_node(const knot_node_t *node);
/*!
* \brief Returns the NSEC3 node corresponding to the given node.
@@ -285,8 +287,7 @@ knot_node_t *knot_node_get_nsec3_node(const knot_node_t *node,
* and the name of the zone \a node belongs to).
* \retval NULL if the NSEC3 node is not set.
*/
-const knot_node_t *knot_node_nsec3_node(const knot_node_t *node,
- int check_version);
+const knot_node_t *knot_node_nsec3_node(const knot_node_t *node);
/*!
* \brief Sets the corresponding NSEC3 node of the given node.
@@ -327,8 +328,7 @@ void knot_node_set_owner(knot_node_t *node, knot_dname_t* owner);
*
* \return Wildcard child of the given node or NULL if it has none.
*/
-const knot_node_t *knot_node_wildcard_child(const knot_node_t *node,
- int check_version);
+const knot_node_t *knot_node_wildcard_child(const knot_node_t *node);
/*!
* \brief Sets the wildcard child of the node.
@@ -337,18 +337,19 @@ const knot_node_t *knot_node_wildcard_child(const knot_node_t *node,
* \param wildcard_child Wildcard child of the node.
*/
void knot_node_set_wildcard_child(knot_node_t *node,
- knot_node_t *wildcard_child);
+ knot_node_t *wildcard_child);
+
+knot_node_t *knot_node_get_wildcard_child(const knot_node_t *node);
-const knot_node_t *knot_node_current(const knot_node_t *node);
+//const knot_node_t *knot_node_current(const knot_node_t *node);
-knot_node_t *knot_node_get_current(knot_node_t *node);
+//knot_node_t *knot_node_get_current(knot_node_t *node);
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);
-void knot_node_set_new_node(knot_node_t *node,
- knot_node_t *new_node);
+void knot_node_set_new_node(knot_node_t *node, knot_node_t *new_node);
void knot_node_set_zone(knot_node_t *node, struct knot_zone *zone);
@@ -427,7 +428,7 @@ void knot_node_free_rrsets(knot_node_t *node, int free_rdata_dnames);
*
* \todo Document missing parameters.
*/
-void knot_node_free(knot_node_t **node, int free_owner, int fix_refs);
+void knot_node_free(knot_node_t **node, int fix_refs);
/*!
* \brief Compares two nodes according to their owner.
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c
index feec8e5..8a74e23 100644
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -35,7 +35,7 @@ typedef struct {
knot_node_t *first_node;
knot_zone_contents_t *zone;
knot_node_t *previous_node;
- int check_ver;
+ int err;
} knot_zone_adjust_arg_t;
/*----------------------------------------------------------------------------*/
@@ -52,7 +52,6 @@ static void knot_zone_tree_apply(knot_zone_tree_node_t *node,
}
/*----------------------------------------------------------------------------*/
-
/*!
* \brief Checks if the given node can be inserted into the given zone.
*
@@ -129,9 +128,133 @@ static void knot_zone_contents_destroy_node_owner_from_tree(
UNUSED(data);
/*!< \todo change completely! */
- knot_node_free(&tnode->node, 0, 0);
+ knot_node_free(&tnode->node, 0);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int knot_zone_contents_dnames_from_rdata_to_table(
+ knot_dname_table_t *table, knot_rdata_t *rdata,
+ knot_rrtype_descriptor_t *d)
+{
+ unsigned int count = knot_rdata_item_count(rdata);
+ int rc = 0;
+ if (d->fixed_items) {
+ assert(count <= d->length);
+ }
+ // for each RDATA item
+ for (unsigned int j = 0; j < count; ++j) {
+ if (d->wireformat[j]
+ == KNOT_RDATA_WF_COMPRESSED_DNAME
+ || d->wireformat[j]
+ == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
+ || d->wireformat[j]
+ == KNOT_RDATA_WF_LITERAL_DNAME) {
+// printf("Saving dname from rdata to dname table: "
+// "%p.\n", knot_rdata_get_item(rdata, j)->dname);
+ rc = knot_dname_table_add_dname_check(table,
+ &knot_rdata_get_item(rdata, j)->dname);
+// printf("Returned: %d\n", rc);
+ if (rc < 0) {
+ dbg_zone("Error: %s\n", knot_strerror(rc));
+ return rc;
+ }
+ }
+ }
+
+ dbg_zone("RDATA OK.\n");
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int knot_zone_contents_dnames_from_rrset_to_table(
+ knot_dname_table_t *table, knot_rrset_t *rrset, int replace_owner,
+ knot_dname_t *owner)
+{
+ assert(table != NULL && rrset != NULL && owner != NULL);
+
+ if (replace_owner) {
+ // discard the old owner and replace it with the new
+ knot_rrset_set_owner(rrset, owner);
+ }
+ dbg_zone("RRSet owner: %p\n", rrset->owner);
+
+ knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(
+ knot_rrset_type(rrset));
+ if (desc == NULL) {
+ // not recognized RR type, ignore
+ dbg_zone("RRSet type not recognized.\n");
+ return KNOT_EOK;
+ }
+ // for each RDATA in RRSet
+// char *name = knot_dname_to_str(rrset->owner);
+// char *type = knot_rrtype_to_string(rrset->type);
+// printf("Storing dnames from RDATA from RRSet %s, %s\n", name, type);
+// free(name);
+ knot_rdata_t *rdata = knot_rrset_get_rdata(rrset);
+ while (rdata != NULL) {
+ int rc = knot_zone_contents_dnames_from_rdata_to_table(table,
+ rdata, desc);
+ if (rc != KNOT_EOK) {
+ return rc;
+ }
+
+ rdata = knot_rrset_rdata_get_next(rrset, rdata);
+ }
+
+ dbg_zone("RRSet OK.\n");
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int knot_zone_contents_dnames_from_node_to_table(
+ knot_dname_table_t *table, knot_node_t *node)
+{
+ /*
+ * Assuming that all the RRSets have the same owner as the node.
+ */
+
+ // insert owner
+ char *name = knot_dname_to_str(node->owner);
+ dbg_zone("Node owner before inserting to dname table: %p.\n",
+ node->owner);
+ dbg_zone("Node owner before inserting to dname table: %s.\n",
+ name);
+ free(name);
+ //knot_dname_t *old_owner = node->owner;
+ int rc = knot_dname_table_add_dname_check(table, &node->owner);
+ if (rc < 0) {
+ dbg_zone("Failed to add dname to dname table.\n");
+ return rc;
+ }
+ int replace_owner = (rc > 0);
+ dbg_zone("Node owner after inserting to dname table: %p.\n",
+ node->owner);
+ name = knot_dname_to_str(node->owner);
+ dbg_zone("Node owner after inserting to dname table: %s.\n",
+ name);
+ free(name);
+
+ knot_rrset_t **rrsets = knot_node_get_rrsets(node);
+ // for each RRSet
+ for (int i = 0; i < knot_node_rrset_count(node); ++i) {
+ dbg_zone("Inserting RRSets from node to table.\n");
+ rc = knot_zone_contents_dnames_from_rrset_to_table(table,
+ rrsets[i], replace_owner, node->owner);
+ if (rc != KNOT_EOK) {
+ return rc;
+ }
+ }
+
+ free(rrsets);
+
+ dbg_zone("Node OK\n");
+ return KNOT_EOK;
}
+/*----------------------------------------------------------------------------*/
/*!
* \brief Finds and sets wildcard child for given node's owner.
*
@@ -340,10 +463,14 @@ static void knot_zone_contents_adjust_rrsets(knot_node_t *node,
*
* \param node Zone node to adjust.
* \param zone Zone the node belongs to.
+ *
+ * \todo Consider whether this function should replace RRSet owners with
+ * node owner + store this owner to the dname table. This is now done
+ * in the inserting function, though that may not be always used (e.g.
+ * old changeset processing).
*/
static void knot_zone_contents_adjust_node(knot_node_t *node,
- knot_zone_contents_t *zone,
- int check_ver)
+ knot_zone_contents_t *zone)
{
dbg_zone_exec(
@@ -356,15 +483,15 @@ dbg_zone_exec(
knot_zone_contents_adjust_rrsets(node, zone);
dbg_zone_exec(
- if (knot_node_parent(node, 1)) {
+ if (knot_node_parent(node)) {
char *name = knot_dname_to_str(knot_node_owner(
- knot_node_parent(node, check_ver)));
+ knot_node_parent(node)));
dbg_zone("Parent: %s\n", name);
dbg_zone("Parent is delegation point: %s\n",
- knot_node_is_deleg_point(knot_node_parent(node, check_ver))
+ knot_node_is_deleg_point(knot_node_parent(node))
? "yes" : "no");
dbg_zone("Parent is non-authoritative: %s\n",
- knot_node_is_non_auth(knot_node_parent(node, check_ver))
+ knot_node_is_non_auth(knot_node_parent(node))
? "yes" : "no");
free(name);
} else {
@@ -372,32 +499,32 @@ dbg_zone_exec(
}
);
// delegation point / non-authoritative node
- if (knot_node_parent(node, check_ver)
- && (knot_node_is_deleg_point(knot_node_parent(node, check_ver))
- || knot_node_is_non_auth(knot_node_parent(node, check_ver)))) {
+ if (knot_node_parent(node)
+ && (knot_node_is_deleg_point(knot_node_parent(node))
+ || knot_node_is_non_auth(knot_node_parent(node)))) {
knot_node_set_non_auth(node);
} else if (knot_node_rrset(node, KNOT_RRTYPE_NS) != NULL
&& node != zone->apex) {
knot_node_set_deleg_point(node);
}
- // authorative node?
-// if (!knot_node_is_non_auth(node)) {
- zone->node_count++;
-// }
-
// assure that owner has proper node
- if (knot_dname_node(knot_node_owner(node), 0) == NULL) {
- knot_dname_set_node(knot_node_get_owner(node), node);
+ if (knot_dname_node(knot_node_owner(node)) == NULL) {
knot_dname_set_node(knot_node_get_owner(node), node);
}
+ // check if this node is not a wildcard child of its parent
+ if (knot_dname_is_wildcard(knot_node_owner(node))) {
+ assert(knot_node_parent(node) != NULL);
+ knot_node_set_wildcard_child(knot_node_get_parent(node), node);
+ }
+
// NSEC3 node (only if NSEC3 tree is not empty)
const knot_node_t *prev;
const knot_node_t *nsec3;
int match = knot_zone_contents_find_nsec3_for_name(zone,
- knot_node_owner(node),
- &nsec3, &prev, check_ver);
+ knot_node_owner(node),
+ &nsec3, &prev);
if (match != KNOT_ZONE_NAME_FOUND) {
nsec3 = NULL;
}
@@ -430,14 +557,52 @@ static void knot_zone_contents_adjust_node_in_tree(
knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data;
knot_node_t *node = tnode->node;
+
+ if (args->err != KNOT_EOK) {
+ dbg_xfrin_detail("Error during adjusting: %s, skipping node.\n",
+ knot_strerror(args->err));
+ return;
+ }
+
+ /*
+ * 1) Set previous node pointer.
+ */
knot_node_set_previous(node, args->previous_node);
- args->previous_node = node;
+
if (args->first_node == NULL) {
args->first_node = node;
}
knot_zone_contents_t *zone = args->zone;
- knot_zone_contents_adjust_node(node, zone, args->check_ver);
+ /*
+ * 2) Store domain names to dname table.
+ *
+ * TODO: make optional!
+ */
+ assert(zone->dname_table != NULL);
+
+ int ret = knot_zone_contents_dnames_from_node_to_table(
+ zone->dname_table, node);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to add dnames from adjusted node to "
+ "table: %s\n", knot_strerror(ret));
+ args->err = ret;
+ return;
+ }
+
+ /*
+ * 3) Do other adjusting (flags, closest enclosers, wildcard children,
+ * etc.).
+ */
+ knot_zone_contents_adjust_node(node, zone);
+
+ /*
+ * 4) Store previous node depending on the type of this node.
+ */
+ if (!knot_node_is_non_auth(node)
+ && knot_node_rrset_count(node) > 0) {
+ args->previous_node = node;
+ }
}
/*----------------------------------------------------------------------------*/
@@ -459,15 +624,36 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree(
knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data;
knot_node_t *node = tnode->node;
+
+ // set previous node
knot_node_set_previous(node, args->previous_node);
+
+ // assure that owner has proper node
+ if (knot_dname_node(knot_node_owner(node)) == NULL) {
+ knot_dname_set_node(knot_node_get_owner(node), node);
+ }
+
+ /*
+ * Store domain names to dname table.
+ */
+ knot_zone_contents_t *zone = args->zone;
+ assert(zone != NULL);
+
+ int ret = knot_zone_contents_dnames_from_node_to_table(
+ zone->dname_table, node);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("Failed to add dnames from adjusted node to "
+ "table: %s\n", knot_strerror(ret));
+ args->err = ret;
+ return;
+ }
+
+ // here is nothing to consider, all nodes are the same
args->previous_node = node;
+
if (args->first_node == NULL) {
args->first_node = node;
}
-
- /* Not needed anymore. */
-// knot_zone_contents_t *zone = args->zone;
-// knot_zone_contents_adjust_nsec3_node(node, zone, 1);
}
/*----------------------------------------------------------------------------*/
@@ -595,9 +781,9 @@ dbg_zone_exec(
* node. \a previous is set properly.
*/
static int knot_zone_contents_find_in_tree(knot_zone_tree_t *tree,
- const knot_dname_t *name,
- knot_node_t **node,
- knot_node_t **previous)
+ const knot_dname_t *name,
+ knot_node_t **node,
+ knot_node_t **previous)
{
assert(tree != NULL);
assert(name != NULL);
@@ -607,8 +793,8 @@ static int knot_zone_contents_find_in_tree(knot_zone_tree_t *tree,
knot_node_t *found = NULL, *prev = NULL;
// knot_node_t *found2 = NULL, *prev2 = NULL;
- int exact_match = knot_zone_tree_get_less_or_equal(
- tree, name, &found, &prev, 1);
+ int exact_match = knot_zone_tree_get_less_or_equal(tree, name, &found,
+ &prev);
// assert(prev != NULL);
assert(exact_match >= 0);
@@ -652,11 +838,6 @@ static void knot_zone_contents_node_to_hash(knot_zone_tree_node_t *tnode,
*/
#ifdef USE_HASH_TABLE
-//dbg_zone_exec(
-// char *name = knot_dname_to_str(node->owner);
-// dbg_zone("Adding node with owner %s to hash table.\n", name);
-// free(name);
-//);
//assert(zone->table != NULL);
// add the node also to the hash table if authoritative, or deleg. point
if (zone->table != NULL
@@ -669,123 +850,164 @@ static void knot_zone_contents_node_to_hash(knot_zone_tree_node_t *tnode,
}
/*----------------------------------------------------------------------------*/
+/* CNAME chain checking */
+/*----------------------------------------------------------------------------*/
-static int knot_zone_contents_dnames_from_rdata_to_table(
- knot_dname_table_t *table, knot_rdata_t *rdata,
- knot_rrtype_descriptor_t *d)
+typedef struct cname_chain {
+ const knot_node_t *node;
+ struct cname_chain *next;
+} cname_chain_t;
+
+/*----------------------------------------------------------------------------*/
+
+static int cname_chain_add(cname_chain_t **last, const knot_node_t *node)
{
- unsigned int count = knot_rdata_item_count(rdata);
- int rc = 0;
- if (d->fixed_items) {
- assert(count <= d->length);
- }
- // for each RDATA item
- for (unsigned int j = 0; j < count; ++j) {
- if (d->wireformat[j]
- == KNOT_RDATA_WF_COMPRESSED_DNAME
- || d->wireformat[j]
- == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || d->wireformat[j]
- == KNOT_RDATA_WF_LITERAL_DNAME) {
- dbg_zone("Saving dname from "
- "rdata to dname table"
- ".\n");
- rc = knot_dname_table_add_dname_check(table,
- &knot_rdata_get_item(rdata, j)->dname);
- if (rc < 0) {
- dbg_zone("Error: %s\n",
- knot_strerror(rc));
- return rc;
- }
- }
+ assert(last != NULL);
+
+ cname_chain_t *new_cname =
+ (cname_chain_t *)malloc(sizeof(cname_chain_t));
+ CHECK_ALLOC_LOG(new_cname, KNOT_ENOMEM);
+
+ new_cname->node = node;
+ new_cname->next = NULL;
+
+ if (*last != NULL) {
+ (*last)->next = new_cname;
+ } else {
+ *last = new_cname;
}
- dbg_zone("RDATA OK.\n");
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int knot_zone_contents_dnames_from_rrset_to_table(
- knot_dname_table_t *table, knot_rrset_t *rrset, int replace_owner,
- knot_dname_t *owner)
+static int cname_chain_contains(cname_chain_t *chain, const knot_node_t *node)
{
- assert(table != NULL && rrset != NULL && owner != NULL);
-
- if (replace_owner) {
- // discard the old owner and replace it with the new
- knot_rrset_set_owner(rrset, owner);
+ cname_chain_t *act = chain;
+ while (act != NULL) {
+ if (act->node == node) {
+ return 1;
+ }
+ act = act->next;
}
- dbg_zone("RRSet owner: %p\n", rrset->owner);
- knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(
- knot_rrset_type(rrset));
- if (desc == NULL) {
- // not recognized RR type, ignore
- dbg_zone("RRSet type not recognized.\n");
- return KNOT_EOK;
- }
- // for each RDATA in RRSet
- knot_rdata_t *rdata = knot_rrset_get_rdata(rrset);
- while (rdata != NULL) {
- int rc = knot_zone_contents_dnames_from_rdata_to_table(table,
- rdata, desc);
- if (rc != KNOT_EOK) {
- return rc;
- }
+ return 0;
+}
- rdata = knot_rrset_rdata_get_next(rrset, rdata);
- }
+/*----------------------------------------------------------------------------*/
- dbg_zone("RRSet OK.\n");
- return KNOT_EOK;
+static void cname_chain_free(cname_chain_t *chain)
+{
+ cname_chain_t *act = chain;
+
+ while (act != NULL) {
+ chain = chain->next;
+ free(act);
+ act = chain;
+ }
}
/*----------------------------------------------------------------------------*/
-static int knot_zone_contents_dnames_from_node_to_table(
- knot_dname_table_t *table, knot_node_t *node)
+typedef struct loop_check_data {
+ knot_zone_contents_t *zone;
+ int err;
+} loop_check_data_t;
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zone_contents_check_loops_in_tree(knot_zone_tree_node_t *tnode,
+ void *data)
{
- /*
- * Assuming that all the RRSets have the same owner as the node.
- */
+ assert(tnode != NULL);
+ assert(tnode->node != NULL);
+ assert(data != NULL);
- // insert owner
- char *name = knot_dname_to_str(node->owner);
- dbg_zone("Node owner before inserting to dname table: %p.\n",
- node->owner);
- dbg_zone("Node owner before inserting to dname table: %s.\n",
- name);
- free(name);
- //knot_dname_t *old_owner = node->owner;
- int rc = knot_dname_table_add_dname_check(table, &node->owner);
- if (rc < 0) {
- dbg_zone("Failed to add dname to dname table.\n");
- return rc;
+ loop_check_data_t *args = (loop_check_data_t *)data;
+ const knot_node_t *node = tnode->node;
+
+ assert(args->zone != NULL);
+
+ if (args->err != KNOT_EOK) {
+ dbg_xfrin_detail("Error during CNAME loop checking, skipping "
+ "node.\n");
+ return;
}
- int replace_owner = (rc > 0);
- dbg_zone("Node owner after inserting to dname table: %p.\n",
- node->owner);
- name = knot_dname_to_str(node->owner);
- dbg_zone("Node owner after inserting to dname table: %s.\n",
- name);
- free(name);
- knot_rrset_t **rrsets = knot_node_get_rrsets(node);
- // for each RRSet
- for (int i = 0; i < knot_node_rrset_count(node); ++i) {
- dbg_zone("Inserting RRSets from node to table.\n");
- rc = knot_zone_contents_dnames_from_rrset_to_table(table,
- rrsets[i], replace_owner, node->owner);
- if (rc != KNOT_EOK) {
- return rc;
+ // if there is CNAME in the node
+ const knot_rrset_t *cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME);
+ cname_chain_t *chain = NULL;
+ cname_chain_t **act_cname = &chain;
+ int ret = 0;
+
+ while (cname != NULL && !cname_chain_contains(chain, node)) {
+ ret = cname_chain_add(act_cname, node);
+ if (ret != KNOT_EOK) {
+ cname_chain_free(chain);
+ args->err = ret;
+ return;
+ }
+ act_cname = &(*act_cname)->next;
+
+ // follow the CNAME chain, including wildcards and
+ // remember the nodes passed through
+ const knot_dname_t *next_name = knot_rdata_cname_name(
+ knot_rrset_rdata(cname));
+ assert(next_name != NULL);
+ const knot_node_t *next_node = knot_dname_node(next_name);
+ if (next_node == NULL) {
+ // try to find the name in the zone
+ const knot_node_t *ce = NULL;
+ ret = knot_zone_contents_find_dname_hash(
+ args->zone, next_name,
+ &next_node, &ce);
+
+// char *name1 = knot_dname_to_str(next_name);
+// char *name2 = (next_node != NULL)
+// ? knot_dname_to_str(knot_node_owner(next_node))
+// : "none";
+// char *name3 = (ce != NULL)
+// ? knot_dname_to_str(knot_node_owner(ce))
+// : "none";
+// printf("Searched: %s, found: %p (%s), %p (%s); ret: %d"
+// ".\n", name1, next_node, name2, ce, name3, ret);
+// free(name1);
+// if (next_node != NULL) {
+// free(name2);
+// }
+// if (ce != NULL) {
+// free(name3);
+// }
+
+ if (ret != KNOT_ZONE_NAME_FOUND
+ && ce != NULL) {
+ // try to find wildcard child
+ assert(knot_dname_is_subdomain(next_name,
+ knot_node_owner(ce)));
+ next_node = knot_node_wildcard_child(ce);
+ }
+
+ assert(next_node == NULL || knot_dname_compare(
+ knot_node_owner(next_node), next_name) == 0
+ || knot_dname_is_wildcard(knot_node_owner(next_node)));
+ }
+
+ if (next_node == NULL) {
+ // no CNAME node to follow
+ cname = NULL;
+ } else {
+ node = next_node;
+ cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME);
}
}
- free(rrsets);
+ if (cname != NULL) {
+ // this means the node is in the chain already
+ args->err = KNOT_ECNAME;
+ }
- dbg_zone("Node OK\n");
- return KNOT_EOK;
+ cname_chain_free(chain);
}
/*----------------------------------------------------------------------------*/
@@ -793,10 +1015,11 @@ static int knot_zone_contents_dnames_from_node_to_table(
/*----------------------------------------------------------------------------*/
knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
- uint node_count,
- int use_domain_table,
- struct knot_zone *zone)
+ uint node_count,
+ int use_domain_table,
+ struct knot_zone *zone)
{
+ dbg_zone("Creating contents for %u nodes.\n", node_count);
knot_zone_contents_t *contents = (knot_zone_contents_t *)
calloc(1, sizeof(knot_zone_contents_t));
if (contents == NULL) {
@@ -810,6 +1033,7 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
contents->apex = apex;
contents->zone = zone;
knot_node_set_zone(apex, zone);
+ contents->node_count = 1;
dbg_zone("Creating tree for normal nodes.\n");
contents->nodes = malloc(sizeof(knot_zone_tree_t));
@@ -836,7 +1060,7 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
contents->dname_table = NULL;
}
- contents->node_count = node_count;
+ //contents->node_count = node_count;
/* Initialize NSEC3 params */
dbg_zone("Initializing NSEC3 parameters.\n");
@@ -859,9 +1083,9 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
}
#ifdef USE_HASH_TABLE
- if (contents->node_count > 0) {
+ if (node_count > 0) {
dbg_zone("Creating hash table.\n");
- contents->table = ck_create_table(contents->node_count);
+ contents->table = ck_create_table(node_count);
if (contents->table == NULL) {
goto cleanup;
}
@@ -984,6 +1208,7 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
int ret = 0;
if ((ret = knot_zone_contents_check_node(zone, node)) != 0) {
+ dbg_zone("Node check failed.\n");
return ret;
}
@@ -993,10 +1218,20 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
return ret;
}
+ if (use_domain_table) {
+ ret = knot_zone_contents_dnames_from_node_to_table(
+ zone->dname_table, node);
+ if (ret != KNOT_EOK) {
+ /*! \todo Remove node from the tree and hash table.*/
+ dbg_zone("Failed to add dnames into table.\n");
+ return ret;
+ }
+ }
+
#ifdef USE_HASH_TABLE
- char *name = knot_dname_to_str(node->owner);
+// char *name = knot_dname_to_str(node->owner);
// dbg_zone("Adding node with owner %s to hash table.\n", name);
- free(name);
+// free(name);
//assert(zone->table != NULL);
// add the node also to the hash table if authoritative, or deleg. point
if (zone->table != NULL
@@ -1010,18 +1245,10 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
#endif
assert(knot_zone_contents_find_node(zone, node->owner));
- if (use_domain_table) {
- ret = knot_zone_contents_dnames_from_node_to_table(
- zone->dname_table, node);
- if (ret != KNOT_EOK) {
- /*! \todo Remove node from the tree and hash table.*/
- dbg_zone("Failed to add dnames into table.\n");
- return ret;
- }
- }
-
knot_node_set_zone(node, zone->zone);
+ ++zone->node_count;
+
if (!create_parents) {
return KNOT_EOK;
}
@@ -1030,21 +1257,38 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
knot_dname_t *chopped =
knot_dname_left_chop(knot_node_owner(node));
+ if(chopped == NULL) {
+ /* Root domain and root domain only. */
+ assert(node->owner && node->owner->labels &&
+ node->owner->labels[0] == 0);
+ return KNOT_EOK;
+ }
+
if (knot_dname_compare(knot_node_owner(zone->apex), chopped) == 0) {
dbg_zone("Zone apex is the parent.\n");
knot_node_set_parent(node, zone->apex);
+
+ // check if the node is not wildcard child of the parent
+ if (knot_dname_is_wildcard(
+ knot_node_owner(node))) {
+ knot_node_set_wildcard_child(zone->apex, node);
+ }
} else {
knot_node_t *next_node;
while ((next_node
- = knot_zone_contents_get_node(zone, chopped)) == NULL) {
+ = knot_zone_contents_get_node(zone, chopped)) == NULL &&
+ chopped != NULL) {
/* Adding new dname to zone + add to table. */
dbg_zone("Creating new node.\n");
+
+ assert(chopped);
next_node = knot_node_new(chopped, NULL, flags);
if (next_node == NULL) {
/* Directly discard. */
knot_dname_free(&chopped);
return KNOT_ENOMEM;
}
+
if (use_domain_table) {
ret =
knot_zone_contents_dnames_from_node_to_table(
@@ -1058,6 +1302,8 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
if (next_node->owner != chopped) {
/* Node owner was in RDATA */
+ knot_dname_release(chopped);
+ knot_dname_retain(next_node->owner);
chopped = next_node->owner;
}
@@ -1101,7 +1347,7 @@ dbg_zone_exec(
knot_dname_release(chopped);
return KNOT_EHASH;
}
-
+#endif
// set parent
knot_node_set_parent(node, next_node);
@@ -1113,7 +1359,9 @@ dbg_zone_exec(
knot_node_owner(node))) {
knot_node_set_wildcard_child(next_node, node);
}
-#endif
+
+ ++zone->node_count;
+
dbg_zone("Next parent.\n");
node = next_node;
knot_dname_t *chopped_last = chopped;
@@ -1127,7 +1375,7 @@ dbg_zone_exec(
}
// set the found parent (in the zone) as the parent of the last
// inserted node
- assert(knot_node_parent(node, 0) == NULL);
+ assert(knot_node_parent(node) == NULL);
knot_node_set_parent(node, next_node);
dbg_zone("Created all parents.\n");
@@ -1450,6 +1698,12 @@ int knot_zone_contents_remove_node(knot_zone_contents_t *contents,
const knot_dname_t *owner = knot_node_owner(node);
+dbg_zone_exec_verb(
+ char *name = knot_dname_to_str(owner);
+ dbg_zone_verb("Removing zone node: %s\n", name);
+ free(name);
+);
+
// 1) remove the node from hash table
*removed_hash = NULL;
*removed_hash = ck_remove_item(contents->table,
@@ -1677,7 +1931,7 @@ dbg_zone_exec(
while (matched_labels < knot_dname_label_count(
knot_node_owner((*closest_encloser)))) {
(*closest_encloser) =
- knot_node_parent((*closest_encloser), 1);
+ knot_node_parent((*closest_encloser));
assert(*closest_encloser);
}
}
@@ -1799,6 +2053,7 @@ dbg_zone_exec(
return KNOT_ERROR;
}
+ assert(zone->table != NULL);
const ck_hash_table_item_t *item = ck_find_item(zone->table,
name_tmp, name_size);
@@ -1865,8 +2120,7 @@ const knot_node_t *knot_zone_contents_find_nsec3_node(
int knot_zone_contents_find_nsec3_for_name(const knot_zone_contents_t *zone,
const knot_dname_t *name,
const knot_node_t **nsec3_node,
- const knot_node_t **nsec3_previous,
- int check_ver)
+ const knot_node_t **nsec3_previous)
{
if (zone == NULL || name == NULL
|| nsec3_node == NULL || nsec3_previous == NULL) {
@@ -1890,7 +2144,7 @@ dbg_zone_exec(
// create dummy node to use for lookup
int exact_match = knot_zone_tree_find_less_or_equal(
- zone->nsec3_nodes, nsec3_name, &found, &prev, check_ver);
+ zone->nsec3_nodes, nsec3_name, &found, &prev);
assert(exact_match >= 0);
knot_dname_release(nsec3_name);
@@ -1921,7 +2175,7 @@ dbg_zone_exec(
// set the previous node of the found node
assert(exact_match);
assert(*nsec3_node != NULL);
- *nsec3_previous = knot_node_previous(*nsec3_node, check_ver);
+ *nsec3_previous = knot_node_previous(*nsec3_node);
} else {
*nsec3_previous = prev;
}
@@ -1958,18 +2212,97 @@ knot_node_t *knot_zone_contents_get_apex(const knot_zone_contents_t *zone)
/*----------------------------------------------------------------------------*/
-//knot_dname_t *knot_zone_contents_name(const knot_zone_contents_t *zone)
-//{
-// if (zone == NULL) {
-// return NULL;
-// }
+int knot_zone_contents_adjust(knot_zone_contents_t *zone)
+{
+ if (zone == NULL) {
+ return KNOT_EBADARG;
+ }
-// return zone->name;
-//}
+ // load NSEC3PARAM (needed on adjusting function)
+ knot_zone_contents_load_nsec3param(zone);
+
+ knot_zone_adjust_arg_t adjust_arg;
+ adjust_arg.zone = zone;
+ adjust_arg.first_node = NULL;
+ adjust_arg.previous_node = NULL;
+ adjust_arg.err = KNOT_EOK;
+// adjust_arg.check_ver = check_ver;
+
+ dbg_zone("Adjusting normal nodes.\n");
+ int ret = knot_zone_tree_forward_apply_inorder(zone->nodes,
+ knot_zone_contents_adjust_node_in_tree,
+ &adjust_arg);
+ assert(ret == KNOT_EOK);
+
+ if (adjust_arg.err != KNOT_EOK) {
+ dbg_zone("Failed to adjust normal nodes: %s\n",
+ knot_strerror(adjust_arg.err));
+ return adjust_arg.err;
+ }
+
+ assert(zone->apex == adjust_arg.first_node);
+ knot_node_set_previous(zone->apex, adjust_arg.previous_node);
+
+ dbg_zone("Done.\n");
+
+ adjust_arg.first_node = NULL;
+ adjust_arg.previous_node = NULL;
+
+ dbg_zone("Adjusting NSEC3 nodes.\n");
+ ret = knot_zone_tree_forward_apply_inorder(
+ zone->nsec3_nodes,
+ knot_zone_contents_adjust_nsec3_node_in_tree,
+ &adjust_arg);
+ assert(ret == KNOT_EOK);
+
+ if (adjust_arg.err != KNOT_EOK) {
+ dbg_zone("Failed to adjust NSEC3 nodes: %s\n",
+ knot_strerror(adjust_arg.err));
+ return adjust_arg.err;
+ }
+
+ dbg_zone("Done.\n");
+ // set the last node as previous of the first node
+ if (adjust_arg.first_node) {
+ knot_node_set_previous(adjust_arg.first_node,
+ adjust_arg.previous_node);
+ }
+
+ return ret;
+}
/*----------------------------------------------------------------------------*/
-int knot_zone_contents_adjust(knot_zone_contents_t *zone, int check_ver)
+int knot_zone_contents_check_loops(knot_zone_contents_t *zone)
+{
+ if (zone == NULL) {
+ return KNOT_EBADARG;
+ }
+
+ dbg_zone("Checking CNAME and wildcard loops.\n");
+
+ loop_check_data_t data;
+ data.err = KNOT_EOK;
+ data.zone = zone;
+
+ assert(zone->nodes != NULL);
+ knot_zone_tree_forward_apply_inorder(zone->nodes,
+ knot_zone_contents_check_loops_in_tree,
+ (void *)&data);
+
+ if (data.err != KNOT_EOK) {
+ dbg_zone("Found CNAME loop in data. Aborting transfer.\n");
+ return data.err;
+ }
+
+ dbg_zone("Done\n");
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int knot_zone_contents_adjust_old(knot_zone_contents_t *zone)
{
if (zone == NULL) {
return KNOT_EBADARG;
@@ -1982,7 +2315,8 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone, int check_ver)
adjust_arg.zone = zone;
adjust_arg.first_node = NULL;
adjust_arg.previous_node = NULL;
- adjust_arg.check_ver = check_ver;
+// adjust_arg.check_ver = check_ver;
+ adjust_arg.err = KNOT_EOK;
dbg_zone("Adjusting normal nodes.\n");
int ret = knot_zone_tree_forward_apply_inorder(zone->nodes,
@@ -1991,6 +2325,12 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone, int check_ver)
if (ret != KNOT_EOK) {
return ret;
}
+ if (adjust_arg.err != KNOT_EOK) {
+ dbg_zone("Failed node adjusting: %s\n",
+ knot_strerror(adjust_arg.err));
+ return adjust_arg.err;
+ }
+
dbg_zone("Done.\n");
assert(zone->apex == adjust_arg.first_node);
@@ -2000,10 +2340,8 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone, int check_ver)
adjust_arg.previous_node = NULL;
dbg_zone("Adjusting NSEC3 nodes.\n");
- ret = knot_zone_tree_forward_apply_inorder(
- zone->nsec3_nodes,
- knot_zone_contents_adjust_nsec3_node_in_tree,
- &adjust_arg);
+ ret = knot_zone_tree_forward_apply_inorder(zone->nsec3_nodes,
+ knot_zone_contents_adjust_nsec3_node_in_tree, &adjust_arg);
dbg_zone("Done.\n");
if (adjust_arg.first_node) {
@@ -2023,7 +2361,7 @@ int knot_zone_contents_load_nsec3param(knot_zone_contents_t *zone)
}
const knot_rrset_t *rrset = knot_node_rrset(zone->apex,
- KNOT_RRTYPE_NSEC3PARAM);
+ KNOT_RRTYPE_NSEC3PARAM);
if (rrset != NULL) {
knot_nsec3_params_from_wire(&zone->nsec3_params, rrset);
@@ -2214,7 +2552,7 @@ int knot_zone_contents_dname_table_apply(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
- knot_zone_contents_t **to)
+ knot_zone_contents_t **to)
{
if (from == NULL || to == NULL) {
return KNOT_EBADARG;
@@ -2310,6 +2648,102 @@ cleanup:
/*----------------------------------------------------------------------------*/
+int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
+ knot_zone_contents_t **to)
+{
+ if (from == NULL || to == NULL) {
+ return KNOT_EBADARG;
+ }
+
+ /* Copy to same destination as source. */
+ if (from == *to) {
+ return KNOT_EBADARG;
+ }
+
+ int ret = KNOT_EOK;
+
+ knot_zone_contents_t *contents = (knot_zone_contents_t *)calloc(
+ 1, sizeof(knot_zone_contents_t));
+ if (contents == NULL) {
+ ERR_ALLOC_FAILED;
+ return KNOT_ENOMEM;
+ }
+
+ //contents->apex = from->apex;
+
+ contents->nodes = malloc(sizeof(knot_zone_tree_t));
+ if (contents->nodes == NULL) {
+ ERR_ALLOC_FAILED;
+ ret = KNOT_ENOMEM;
+ goto cleanup;
+ }
+
+ contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t));
+ if (contents->nsec3_nodes == NULL) {
+ ERR_ALLOC_FAILED;
+ ret = KNOT_ENOMEM;
+ goto cleanup;
+ }
+
+ if (from->dname_table != NULL) {
+ contents->dname_table = knot_dname_table_new();
+ if (contents->dname_table == NULL) {
+ ERR_ALLOC_FAILED;
+ ret = KNOT_ENOMEM;
+ goto cleanup;
+ }
+ if ((ret = knot_dname_table_shallow_copy(from->dname_table,
+ contents->dname_table)) != KNOT_EOK) {
+ goto cleanup;
+ }
+ } else {
+ contents->dname_table = NULL;
+ }
+
+ contents->node_count = from->node_count;
+ contents->generation = from->generation;
+
+ contents->zone = from->zone;
+
+// /* Initialize NSEC3 params */
+// memcpy(&contents->nsec3_params, &from->nsec3_params,
+// sizeof(knot_nsec3_params_t));
+
+ if ((ret = knot_zone_tree_deep_copy(from->nodes,
+ contents->nodes)) != KNOT_EOK
+ || (ret = knot_zone_tree_deep_copy(from->nsec3_nodes,
+ contents->nsec3_nodes)) != KNOT_EOK) {
+ goto cleanup;
+ }
+
+#ifdef USE_HASH_TABLE
+ if (from->table != NULL) {
+ ret = ck_deep_copy(from->table, &contents->table);
+ if (ret != 0) {
+ dbg_zone("knot_zone_contents_shallow_copy: "
+ "hash table copied\n");
+ ret = KNOT_ERROR;
+ goto cleanup;
+ }
+ }
+#endif
+ contents->apex = knot_node_get_new_node(from->apex);
+
+ dbg_zone("knot_zone_contents_shallow_copy: finished OK\n");
+
+ *to = contents;
+ return KNOT_EOK;
+
+cleanup:
+ knot_zone_tree_free(&contents->nodes);
+ knot_zone_tree_free(&contents->nsec3_nodes);
+ free(contents->dname_table);
+ free(contents);
+ return ret;
+}
+
+/*----------------------------------------------------------------------------*/
+
void knot_zone_contents_free(knot_zone_contents_t **contents)
{
if (contents == NULL || *contents == NULL) {
@@ -2396,3 +2830,635 @@ void knot_zone_contents_deep_free(knot_zone_contents_t **contents,
*contents = NULL;
}
+/*----------------------------------------------------------------------------*/
+/* Integrity check */
+/*----------------------------------------------------------------------------*/
+
+typedef struct check_data {
+ const knot_zone_contents_t *contents;
+ const knot_node_t *previous;
+ const knot_node_t *deleg_point;
+ const knot_node_t *parent;
+ int children;
+ int errors;
+} check_data_t;
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_previous(const knot_node_t *node,
+ check_data_t *check_data,
+ const char *name)
+{
+ // first, check if the previous and next pointers are set properly
+ if (check_data->previous != NULL) {
+ char *name_prev = knot_dname_to_str(
+ knot_node_owner(check_data->previous));
+
+ if (knot_node_previous(node) != check_data->previous) {
+ char *name2 = knot_dname_to_str(knot_node_owner(
+ knot_node_previous(node)));
+ fprintf(stderr, "Wrong previous node: node: %s, "
+ "previous: %s. Should be: %s.\n", name, name2,
+ name_prev);
+ free(name2);
+
+ ++check_data->errors;
+ }
+
+// if (knot_node_next(check_data->previous) != node) {
+// char *name2 = knot_dname_to_str(knot_node_owner(
+// knot_node_next(check_data->previous)));
+// fprintf(stderr, "Wrong next node: node %s, next %s. "
+// "Should be %s.\n", name_prev, name2 ,name);
+// free(name2);
+
+// ++check_data->errors;
+// }
+
+ free(name_prev);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_flags(const knot_node_t *node,
+ check_data_t *check_data,
+ char *name)
+{
+ if (node == knot_zone_contents_apex(check_data->contents)) {
+ if (!knot_node_is_auth(node)) {
+ fprintf(stderr, "Wrong flags: node %s, flags: %u. "
+ "Should be non-authoritative.\n", name,
+ node->flags);
+ ++check_data->errors;
+ }
+ return;
+ }
+
+ // check the flags
+ if (check_data->deleg_point != NULL
+ && knot_dname_is_subdomain(knot_node_owner(node),
+ knot_node_owner(check_data->deleg_point))) {
+ // this is a non-authoritative node
+ if (!knot_node_is_non_auth(node)) {
+ fprintf(stderr, "Wrong flags: node %s, flags: %u. "
+ "Should be non-authoritative.\n", name,
+ node->flags);
+ ++check_data->errors;
+ }
+ } else {
+ if (knot_node_rrset(node, KNOT_RRTYPE_NS) != NULL) {
+ // this is a delegation point
+ if (!knot_node_is_deleg_point(node)) {
+ fprintf(stderr, "Wrong flags: node %s, flags: "
+ "%u. Should be deleg. point.\n", name,
+ node->flags);
+ ++check_data->errors;
+ }
+ check_data->deleg_point = node;
+ } else {
+ // this is an authoritative node
+ if (!knot_node_is_auth(node)) {
+ fprintf(stderr, "Wrong flags: node %s, flags: "
+ "%u. Should be authoritative.\n", name,
+ node->flags);
+ ++check_data->errors;
+ }
+ check_data->deleg_point = NULL;
+ }
+
+ // in this case (authoritative or deleg-point), the node should
+ // be a previous of some next node only if it has some data
+ if (knot_node_rrset_count(node) > 0) {
+ check_data->previous = node;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_parent(const knot_node_t *node,
+ check_data_t *check_data,
+ char *name)
+{
+ if (check_data->parent == NULL) {
+ // this is only possible for apex
+ assert(node == knot_zone_contents_apex(check_data->contents));
+ check_data->parent = node;
+ return;
+ }
+
+ const knot_dname_t *node_owner = knot_node_owner(node);
+ const knot_dname_t *parent_owner = knot_node_owner(check_data->parent);
+ char *pname = knot_dname_to_str(parent_owner);
+
+ // if direct child
+ if (knot_dname_is_subdomain(node_owner, parent_owner)
+ && knot_dname_matched_labels(node_owner, parent_owner)
+ == knot_dname_label_count(parent_owner)) {
+
+// // increase the parent's children count
+// fprintf(stderr, "Parent: %s, node: %s. Increasing children count.\n",
+// pname, name);
+// ++check_data->children;
+
+ // check the parent pointer
+ const knot_node_t *parent = knot_node_parent(node);
+ if (parent != check_data->parent) {
+ char *name2 = (parent != NULL)
+ ? knot_dname_to_str(
+ knot_node_owner(parent))
+ : "none";
+ fprintf(stderr, "Wrong parent: node %s, parent %s. "
+ " Should be %s\n", name, name2, pname);
+ if (parent != NULL) {
+ free(name2);
+ }
+
+ ++check_data->errors;
+ } else {
+ // if parent is OK, check if the node is not a
+ // wildcard child of it; in such case it should be set
+ // as the wildcard child of its parent
+ if (knot_dname_is_wildcard(node_owner)
+ && knot_node_wildcard_child(check_data->parent)
+ != node) {
+ char *wc = (knot_node_wildcard_child(
+ check_data->parent) == NULL)
+ ? "none"
+ : knot_dname_to_str(knot_node_owner(
+ knot_node_wildcard_child(
+ check_data->parent)));
+ fprintf(stderr, "Wrong wildcard child: node %s,"
+ " wildcard child: %s. Should be %s\n",
+ pname, wc, name);
+ if (knot_node_wildcard_child(
+ check_data->parent) != NULL) {
+ free(wc);
+ }
+
+ ++check_data->errors;
+ }
+ }
+ } else {
+ // not a direct child, check children count
+// if (check_data->parent
+// && knot_node_children(check_data->parent)
+// != check_data->children) {
+// fprintf(stderr, "Wrong children count: node %s, count: "
+// "%u. Should be: %u\n", pname,
+// knot_node_children(check_data->parent),
+// check_data->children);
+
+// ++check_data->errors;
+// }
+
+ // reset the children count
+ //check_data->parent = node;
+// check_data->children = 0;
+ }
+
+ free(pname);
+ check_data->parent = node;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_rrset_count(const knot_node_t *node,
+ check_data_t *check_data,
+ const char *name)
+{
+ // count RRSets
+ int real_count = knot_node_count_rrsets(node);
+ int count = knot_node_rrset_count(node);
+
+ if (count != real_count) {
+ fprintf(stderr, "Wrong RRSet count: node %s, count %d. "
+ "Should be %d\n", name, count, real_count);
+
+ ++check_data->errors;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct find_dname_data {
+ const knot_dname_t *to_find;
+ const knot_dname_t *found;
+} find_dname_data_t;
+
+/*----------------------------------------------------------------------------*/
+
+void find_in_dname_table(knot_dname_t *dname, void *data)
+{
+ assert(dname != NULL);
+ assert(data != NULL);
+
+ find_dname_data_t *fdata = (find_dname_data_t *)data;
+
+ if (fdata->found != NULL) {
+ return;
+ }
+
+ if (knot_dname_compare(dname, fdata->to_find) == 0) {
+ fdata->found = dname;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int knot_zc_integrity_check_find_dname(const knot_zone_contents_t *zone,
+ const knot_dname_t *to_find,
+ const char *node_name)
+{
+ int ret = 0;
+
+// find_dname_data_t data_find;
+// data_find.found = NULL;
+// data_find.to_find = to_find;
+
+// int res = knot_zone_contents_dname_table_apply(
+// (knot_zone_contents_t *)zone,
+// find_in_dname_table, (void *)&data_find);
+// assert(res == KNOT_EOK);
+
+ knot_dname_t *found = knot_dname_table_find_dname(zone->dname_table,
+ (knot_dname_t *)to_find);
+
+ char *to_find_name = knot_dname_to_str(to_find);
+
+ if (!found || found != to_find) {
+ fprintf(stderr, "Dname not stored in dname table: "
+ "node %s, name %s, found some dname: %s\n", node_name,
+ to_find_name, (found != NULL) ? "yes" : "no");
+ fprintf(stderr, "Dname to find: %p, found dname: %p\n",
+ found, to_find);
+ ret = 1;
+ }
+
+ free(to_find_name);
+
+ knot_dname_release(found);
+
+ return ret;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_owner(const knot_node_t *node,
+ check_data_t *check_data,
+ const char *name)
+{
+ // check node stored in owner
+ const knot_node_t *owner_node =
+ knot_dname_node(knot_node_owner(node));
+ if (owner_node != node) {
+ char *name2 = (owner_node != NULL)
+ ? knot_dname_to_str(knot_node_owner(owner_node))
+ : "none";
+ fprintf(stderr, "Wrong owner's node: node %s, owner's node %s"
+ "\n", name, name2);
+ if (owner_node != NULL) {
+ free(name2);
+ }
+
+ ++check_data->errors;
+ }
+
+ // check if the owner is stored in dname table
+ check_data->errors += knot_zc_integrity_check_find_dname(
+ check_data->contents, knot_node_owner(node), name);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_dnames_in_rrset(const knot_rrset_t *rrset,
+ check_data_t *check_data,
+ const char *name)
+{
+ // check owner of the RRSet
+ check_data->errors += knot_zc_integrity_check_find_dname(
+ check_data->contents,
+ knot_rrset_owner(rrset), name);
+
+ knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(
+ knot_rrset_type(rrset));
+
+ assert(desc != NULL);
+
+ const knot_rdata_t *rdata = knot_rrset_rdata(rrset);
+ while (rdata != NULL) {
+ for (int i = 0; i < knot_rdata_item_count(rdata); ++i) {
+ if (desc->wireformat[i]
+ == KNOT_RDATA_WF_COMPRESSED_DNAME
+ || desc->wireformat[i]
+ == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
+ || desc->wireformat[i]
+ == KNOT_RDATA_WF_LITERAL_DNAME) {
+ knot_rdata_item_t *item = knot_rdata_get_item(
+ rdata, i);
+ check_data->errors +=
+ knot_zc_integrity_check_find_dname(
+ check_data->contents, item->dname, name);
+ }
+ }
+ rdata = knot_rrset_rdata_next(rrset, rdata);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_dnames(const knot_node_t *node,
+ check_data_t *check_data,
+ const char *name)
+{
+ // check all dnames in all RRSets - both owners and in RDATA
+ const knot_rrset_t **rrsets = knot_node_rrsets(node);
+ if (rrsets != NULL) {
+ for (int i = 0; i < knot_node_rrset_count(node); ++i) {
+ knot_zc_integrity_check_dnames_in_rrset(rrsets[i],
+ check_data, name);
+ }
+ }
+ free(rrsets);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_node(knot_node_t *node, void *data)
+{
+ assert(node != NULL);
+ assert(data != NULL);
+
+ const knot_dname_t *node_owner = knot_node_owner(node);
+ char *name = knot_dname_to_str(node_owner);
+
+ check_data_t *check_data = (check_data_t *)data;
+
+ // check previous-next chain
+ knot_zc_integrity_check_previous(node, check_data, name);
+
+ // check node flags
+ knot_zc_integrity_check_flags(node, check_data, name);
+
+ // check if the node is child of the saved parent & children count
+ // & wildcard child
+ knot_zc_integrity_check_parent(node, check_data, name);
+
+ // check RRSet count
+ knot_zc_integrity_check_rrset_count(node, check_data, name);
+
+ // check owner
+ knot_zc_integrity_check_owner(node, check_data, name);
+
+ // check dnames
+ knot_zc_integrity_check_dnames(node, check_data, name);
+
+ /*! \todo Check NSEC3 node. */
+
+ free(name);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zc_integrity_check_nsec3(knot_node_t *node, void *data)
+{
+ assert(node != NULL);
+ assert(data != NULL);
+
+ const knot_dname_t *node_owner = knot_node_owner(node);
+ char *name = knot_dname_to_str(node_owner);
+
+ check_data_t *check_data = (check_data_t *)data;
+
+ // check previous-next chain
+ knot_zc_integrity_check_previous(node, check_data, name);
+ // store the node as new previous
+ check_data->previous = node;
+
+ // check if the node is child of the zone apex
+ if (node->parent != check_data->parent) {
+ fprintf(stderr, "NSEC3 node's parent is not apex. Node: %s.\n",
+ name);
+ ++check_data->errors;
+ }
+
+ // check RRSet count
+ knot_zc_integrity_check_rrset_count(node, check_data, name);
+
+ // check owner
+ knot_zc_integrity_check_owner(node, check_data, name);
+
+ // check dnames
+ knot_zc_integrity_check_dnames(node, check_data, name);
+
+ free(name);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void reset_child_count(knot_zone_tree_node_t *tree_node, void *data)
+{
+ assert(tree_node != NULL);
+ assert(data != NULL);
+
+ knot_node_t **apex_copy = (knot_node_t **)data;
+ if (*apex_copy == NULL) {
+ *apex_copy = tree_node->node;
+ }
+
+ if (tree_node->node != NULL) {
+ tree_node->node->children = 0;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+void count_children(knot_zone_tree_node_t *tree_node, void *data)
+{
+ UNUSED(data);
+ if (tree_node->node != NULL && tree_node->node->parent != NULL) {
+ assert(tree_node->node->parent->new_node != NULL);
+ // fix parent pointer
+ tree_node->node->parent = tree_node->node->parent->new_node;
+ ++tree_node->node->parent->children;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+void check_child_count(knot_zone_tree_node_t *tree_node, void *data)
+{
+ assert(tree_node != NULL);
+ assert(data != NULL);
+
+ check_data_t *check_data = (check_data_t *)data;
+ knot_node_t *node = tree_node->node;
+
+ // find corresponding node in the given contents
+ const knot_node_t *found = NULL;
+ found = knot_zone_contents_find_node(check_data->contents,
+ knot_node_owner(node));
+ assert(found != NULL);
+
+ if (knot_node_children(node) != knot_node_children(found)) {
+ char *name = knot_dname_to_str(knot_node_owner(node));
+ fprintf(stderr, "Wrong children count: node (%p) %s, count %u. "
+ "Should be %u (%p)\n", found, name,
+ knot_node_children(found),
+ knot_node_children(node), node);
+ free(name);
+
+ ++check_data->errors;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void reset_new_nodes(knot_zone_tree_node_t *tree_node, void *data)
+{
+ assert(tree_node != NULL);
+ UNUSED(data);
+
+ knot_node_t *node = tree_node->node;
+ knot_node_set_new_node(node, NULL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+/*!< \todo remove debug code. */
+//static void print_child_count(knot_node_t *node, void *data)
+//{
+// UNUSED(data);
+// assert(node != NULL);
+
+// char *name = knot_dname_to_str(knot_node_owner(node));
+// fprintf(stderr, "Node: %s, children count: %d\n", name,
+// knot_node_children(node));
+// free(name);
+//}
+
+/*----------------------------------------------------------------------------*/
+
+static void count_nsec3_nodes(knot_zone_tree_node_t *tree_node, void *data)
+{
+ assert(tree_node != NULL);
+ assert(tree_node->node != NULL);
+ assert(data != NULL);
+
+// int *count = (int *)data;
+ knot_node_t *apex = (knot_node_t *)data;
+ assert(apex != NULL);
+
+ apex->children += 1;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int knot_zc_integrity_check_child_count(check_data_t *data)
+{
+ int errors = 0;
+
+ // do shallow copy of the node tree
+ knot_zone_tree_t *nodes_copy = (knot_zone_tree_t *)
+ malloc(sizeof(knot_zone_tree_t));
+ if (nodes_copy == NULL) {
+ return 1;
+ }
+
+ knot_zone_tree_init(nodes_copy);
+
+// int ret = knot_zone_contents_tree_apply_inorder(data->contents,
+// print_child_count,
+// NULL);
+
+ int ret = knot_zone_tree_deep_copy(data->contents->nodes, nodes_copy);
+ assert(ret == KNOT_EOK);
+
+
+ // set children count of all nodes to 0
+ // in the same walkthrough find the apex
+ knot_node_t *apex_copy = NULL;
+ knot_zone_tree_forward_apply_inorder(nodes_copy, reset_child_count,
+ (void *)&apex_copy);
+ assert(apex_copy != NULL);
+
+ // now count children of all nodes, presuming the parent pointers are ok
+ knot_zone_tree_forward_apply_inorder(nodes_copy, count_children, NULL);
+
+ // add count of NSEC3 nodes to the apex' children count
+// int nsec3_nodes = 0;
+ dbg_zone(stderr, "Children count of new apex before NSEC3: %d\n",
+ data->contents->apex->new_node->children);
+ knot_zone_tree_forward_apply_inorder(data->contents->nsec3_nodes,
+ count_nsec3_nodes,
+ (void *)apex_copy);
+
+
+ // now compare the children counts
+ // iterate over the old zone and search for nodes in the copy
+// data->children = nsec3_nodes;
+ knot_zone_tree_forward_apply_inorder(nodes_copy, check_child_count,
+ (void *)data);
+
+ // cleanup old zone tree - reset pointers to new node to NULL
+ knot_zone_tree_forward_apply_inorder(data->contents->nodes,
+ reset_new_nodes, NULL);
+
+ // destroy the shallow copy
+ knot_zone_tree_deep_free(&nodes_copy);
+
+ return errors;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents)
+{
+ /*
+ * 1) Check flags of nodes.
+ * - Those containing NS RRSets should have the 'delegation point'
+ * flag set.
+ * - Their descendants should be marked as non-authoritative.
+ * - Other nodes should be marked as authoritative.
+ *
+ * In the same walkthrough check:
+ * - if nodes are properly connected by 'previous' and 'next' pointers.
+ * Only authoritative nodes and delegation points should be.
+ * - parents - each node (except for the apex) should have a parent set
+ * and it should be a node with owner one label shorter.
+ * - RRSet counts.
+ * - etc...
+ */
+
+ check_data_t data;
+ data.errors = 0;
+ data.previous = NULL;
+ data.deleg_point = NULL;
+ data.parent = NULL;
+ data.children = 0;
+ data.contents = contents;
+
+ int ret = knot_zone_contents_tree_apply_inorder(
+ (knot_zone_contents_t *)contents,
+ knot_zc_integrity_check_node, (void *)&data);
+ assert(ret == KNOT_EOK);
+
+ // if OK, we can continue with checking children count
+ // (we need the parent pointers to be set well)
+ if (data.errors == 0) {
+ data.contents = contents;
+ knot_zc_integrity_check_child_count(&data);
+ }
+
+ data.previous = NULL;
+ data.children = 0;
+ data.parent = contents->apex;
+ ret = knot_zone_contents_nsec3_apply_inorder(
+ (knot_zone_contents_t *)contents,
+ knot_zc_integrity_check_nsec3, (void *)&data);
+ assert(ret == KNOT_EOK);
+
+ return data.errors;
+}
+
diff --git a/src/libknot/zone/zone-contents.h b/src/libknot/zone/zone-contents.h
index 2856f76..24fbcac 100644
--- a/src/libknot/zone/zone-contents.h
+++ b/src/libknot/zone/zone-contents.h
@@ -338,8 +338,7 @@ int knot_zone_contents_find_nsec3_for_name(
const knot_zone_contents_t *contents,
const knot_dname_t *name,
const knot_node_t **nsec3_node,
- const knot_node_t **nsec3_previous,
- int check_ver);
+ const knot_node_t **nsec3_previous);
/*!
* \brief Returns the apex node of the zone.
*
@@ -362,7 +361,9 @@ knot_node_t *knot_zone_contents_get_apex(
*
* \param zone Zone to adjust domain names in.
*/
-int knot_zone_contents_adjust(knot_zone_contents_t *contents, int check_ver);
+int knot_zone_contents_adjust(knot_zone_contents_t *contents);
+
+int knot_zone_contents_check_loops(knot_zone_contents_t *zone);
/*!
* \brief Parses the NSEC3PARAM record stored in the zone.
@@ -544,13 +545,24 @@ int knot_zone_contents_dname_table_apply(knot_zone_contents_t *contents,
* \retval KNOT_ENOMEM
*/
int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
- knot_zone_contents_t **to);
+ knot_zone_contents_t **to);
+
+int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
+ knot_zone_contents_t **to);
+
+//int knot_zone_contents_dnames_from_node_to_table(
+// knot_dname_table_t *table, knot_node_t *node);
+
+//void knot_zone_contents_adjust_node(knot_node_t *node,
+// knot_zone_contents_t *zone, int check_ver);
void knot_zone_contents_free(knot_zone_contents_t **contents);
void knot_zone_contents_deep_free(knot_zone_contents_t **contents,
int destroy_dname_table);
+int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents);
+
#endif
/*! @} */
diff --git a/src/libknot/zone/zone-tree.c b/src/libknot/zone/zone-tree.c
index cdf128e..de5df18 100644
--- a/src/libknot/zone/zone-tree.c
+++ b/src/libknot/zone/zone-tree.c
@@ -21,6 +21,7 @@
#include "zone-tree.h"
#include "zone/node.h"
#include "util/error.h"
+#include "util/debug.h"
/*----------------------------------------------------------------------------*/
/* Non-API functions */
@@ -87,6 +88,8 @@ static int knot_zone_tree_copy_node(knot_zone_tree_node_t *from,
if (ret != KNOT_EOK) {
knot_zone_tree_delete_subtree((*to)->avl.avl_left);
(*to)->avl.avl_left = NULL;
+ free(*to);
+ *to = NULL;
return ret;
}
@@ -96,24 +99,74 @@ static int knot_zone_tree_copy_node(knot_zone_tree_node_t *from,
/*----------------------------------------------------------------------------*/
static void knot_zone_tree_free_node(knot_zone_tree_node_t *node,
- int free_data, int free_owner)
+ int free_data)
{
if (node == NULL) {
return;
}
- knot_zone_tree_free_node(node->avl.avl_left, free_data, free_owner);
+ knot_zone_tree_free_node(node->avl.avl_left, free_data);
- knot_zone_tree_free_node(node->avl.avl_right, free_data, free_owner);
+ knot_zone_tree_free_node(node->avl.avl_right, free_data);
if (free_data) {
- knot_node_free(&node->node, free_owner, 0);
+ knot_node_free(&node->node, 0);
}
free(node);
}
/*----------------------------------------------------------------------------*/
+
+static int knot_zone_tree_deep_copy_node(knot_zone_tree_node_t *from,
+ knot_zone_tree_node_t **to)
+{
+ if (from == NULL) {
+ *to = NULL;
+ return KNOT_EOK;
+ }
+
+ *to = (knot_zone_tree_node_t *)malloc(sizeof(knot_zone_tree_node_t));
+ if (*to == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ int ret = knot_node_shallow_copy(from->node, &(*to)->node);
+// printf("Copied node: %p to node %p. New node1: %p, new node 2: %p\n",
+// from->node, (*to)->node, from->node->new_node, (*to)->node->new_node);
+ if (ret != KNOT_EOK) {
+ dbg_zone_verb("Failed to do shallow copy of node.\n");
+ free(*to);
+ return ret;
+ }
+
+ (*to)->avl.avl_height = from->avl.avl_height;
+
+ ret = knot_zone_tree_deep_copy_node(from->avl.avl_left,
+ &(*to)->avl.avl_left);
+ if (ret != KNOT_EOK) {
+ dbg_zone_verb("Failed to do shallow copy of left subtree.\n");
+ return ret;
+ }
+
+ ret = knot_zone_tree_deep_copy_node(from->avl.avl_right,
+ &(*to)->avl.avl_right);
+ if (ret != KNOT_EOK) {
+ dbg_zone_verb("Failed to do shallow copy of right subtree.\n");
+ knot_zone_tree_free_node((*to)->avl.avl_left, 1);
+ (*to)->avl.avl_left = NULL;
+ knot_node_free(&(*to)->node, 0);
+ free(*to);
+ *to = NULL;
+ return ret;
+ }
+
+ knot_node_set_new_node(from->node, (*to)->node);
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -197,7 +250,7 @@ int knot_zone_tree_get(knot_zone_tree_t *tree, const knot_dname_t *owner,
knot_zone_tree_node_t *n = TREE_FIND(tree, knot_zone_tree_node, avl,
tmp);
- knot_node_free(&tmp_data, 0, 0);
+ knot_node_free(&tmp_data, 0);
free(tmp);
if (n != NULL) {
@@ -212,15 +265,14 @@ int knot_zone_tree_get(knot_zone_tree_t *tree, const knot_dname_t *owner,
int knot_zone_tree_find_less_or_equal(knot_zone_tree_t *tree,
const knot_dname_t *owner,
const knot_node_t **found,
- const knot_node_t **previous,
- int check_version)
+ const knot_node_t **previous)
{
if (tree == NULL || owner == NULL || found == NULL || previous == NULL) {
return KNOT_EBADARG;
}
knot_node_t *f, *p;
- int ret = knot_zone_tree_get_less_or_equal(tree, owner, &f, &p, check_version);
+ int ret = knot_zone_tree_get_less_or_equal(tree, owner, &f, &p);
*found = f;
*previous = p;
@@ -233,8 +285,7 @@ int knot_zone_tree_find_less_or_equal(knot_zone_tree_t *tree,
int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
const knot_dname_t *owner,
knot_node_t **found,
- knot_node_t **previous,
- int check_version)
+ knot_node_t **previous)
{
if (tree == NULL || owner == NULL || found == NULL
|| previous == NULL) {
@@ -262,7 +313,7 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
int exact_match = TREE_FIND_LESS_EQUAL(
tree, knot_zone_tree_node, avl, tmp, &f, &prev);
- knot_node_free(&tmp_data, 0, 0);
+ knot_node_free(&tmp_data, 0);
free(tmp);
*found = (exact_match > 0) ? f->node : NULL;
@@ -271,7 +322,7 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
// previous is not really previous but should be the leftmost
// node in the tree; take it's previous
assert(prev != NULL);
- *previous = knot_node_get_previous(prev->node, check_version);
+ *previous = knot_node_get_previous(prev->node);
exact_match = 0;
} else if (prev == NULL) {
if (!exact_match) {
@@ -292,7 +343,7 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
// node
assert(exact_match > 0);
assert(f != NULL);
- *previous = knot_node_get_previous(f->node, check_version);
+ *previous = knot_node_get_previous(f->node);
} else {
// otherwise check if the previous node is not an empty
// non-terminal
@@ -300,7 +351,7 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
* to an empty non-terminal.
*/
*previous = (knot_node_rrset_count(prev->node) == 0)
- ? knot_node_get_previous(prev->node, check_version)
+ ? knot_node_get_previous(prev->node)
: prev->node;
}
@@ -342,7 +393,7 @@ int knot_zone_tree_remove(knot_zone_tree_t *tree,
/*! \todo How to know if this was successful? */
TREE_REMOVE(tree, knot_zone_tree_node, avl, tmp);
- knot_node_free(&tmp_data, 0, 0);
+ knot_node_free(&tmp_data, 0);
free(tmp);
// *removed = (n) ? n->node : NULL;
@@ -445,24 +496,43 @@ int knot_zone_tree_shallow_copy(knot_zone_tree_t *from,
/*----------------------------------------------------------------------------*/
+int knot_zone_tree_deep_copy(knot_zone_tree_t *from,
+ knot_zone_tree_t *to)
+{
+ if (to == NULL || from == NULL) {
+ return KNOT_EBADARG;
+ }
+ /*
+ * This function will copy the tree by hand, so that the nodes
+ * do not have to be inserted the normal way. It should be substantially
+ * faster.
+ */
+
+ to->th_cmp = from->th_cmp;
+
+ return knot_zone_tree_deep_copy_node(from->th_root, &to->th_root);
+}
+
+/*----------------------------------------------------------------------------*/
+
void knot_zone_tree_free(knot_zone_tree_t **tree)
{
if (tree == NULL || *tree == NULL) {
return;
}
- knot_zone_tree_free_node((*tree)->th_root, 0, 0);
+ knot_zone_tree_free_node((*tree)->th_root, 0);
free(*tree);
*tree = NULL;
}
/*----------------------------------------------------------------------------*/
-void knot_zone_tree_deep_free(knot_zone_tree_t **tree, int free_owners)
+void knot_zone_tree_deep_free(knot_zone_tree_t **tree)
{
if (tree == NULL || *tree == NULL) {
return;
}
- knot_zone_tree_free_node((*tree)->th_root, 1, free_owners);
+ knot_zone_tree_free_node((*tree)->th_root, 1);
free(*tree);
*tree = NULL;
}
diff --git a/src/libknot/zone/zone-tree.h b/src/libknot/zone/zone-tree.h
index 0971749..ca65fe6 100644
--- a/src/libknot/zone/zone-tree.h
+++ b/src/libknot/zone/zone-tree.h
@@ -125,8 +125,7 @@ int knot_zone_tree_get(knot_zone_tree_t *tree,
int knot_zone_tree_find_less_or_equal(knot_zone_tree_t *tree,
const knot_dname_t *owner,
const knot_node_t **found,
- const knot_node_t **previous,
- int check_version);
+ const knot_node_t **previous);
/*!
* \brief Tries to find the given domain name in the zone tree and returns the
@@ -153,8 +152,7 @@ int knot_zone_tree_find_less_or_equal(knot_zone_tree_t *tree,
int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
const knot_dname_t *owner,
knot_node_t **found,
- knot_node_t **previous,
- int check_version);
+ knot_node_t **previous);
/*!
* \brief Removes node with the given owner from the zone tree and returns it.
@@ -276,6 +274,9 @@ int knot_zone_tree_reverse_apply_postorder(knot_zone_tree_t *tree,
int knot_zone_tree_shallow_copy(knot_zone_tree_t *from,
knot_zone_tree_t *to);
+int knot_zone_tree_deep_copy(knot_zone_tree_t *from,
+ knot_zone_tree_t *to);
+
/*!
* \brief Destroys the zone tree, not touching the saved data.
*
@@ -290,7 +291,7 @@ void knot_zone_tree_free(knot_zone_tree_t **tree);
* \param free_owners Set to <> 0 if owners of the nodes should be destroyed
* as well. Set to 0 otherwise.
*/
-void knot_zone_tree_deep_free(knot_zone_tree_t **tree, int free_owners);
+void knot_zone_tree_deep_free(knot_zone_tree_t **tree);
/*----------------------------------------------------------------------------*/
diff --git a/src/libknot/zone/zonedb.c b/src/libknot/zone/zonedb.c
index 8f07d45..7b445dd 100644
--- a/src/libknot/zone/zonedb.c
+++ b/src/libknot/zone/zonedb.c
@@ -227,15 +227,21 @@ const knot_zone_t *knot_zonedb_find_zone_for_name(knot_zonedb_t *db,
}
knot_zone_t dummy_zone;
- dummy_zone.name = (knot_dname_t *)dname;
+ dummy_zone.name = knot_dname_deep_copy(dname);
void *found = NULL;
- int exact_match = gen_tree_find_less_or_equal(db->zone_tree,
- &dummy_zone,
- &found);
- UNUSED(exact_match);
+
+// int exact_match = gen_tree_find_less_or_equal(db->zone_tree,
+// &dummy_zone,
+// &found);
+// UNUSED(exact_match);
+ found = gen_tree_find(db->zone_tree, &dummy_zone);
+ while (found == NULL && knot_dname_label_count(dummy_zone.name) > 0) {
+ knot_dname_left_chop_no_copy(dummy_zone.name);
+ found = gen_tree_find(db->zone_tree, &dummy_zone);
+ }
knot_zone_t *zone = (found) ? (knot_zone_t *)found : NULL;
-
+
dbg_zonedb_exec(
char *name = knot_dname_to_str(dname);
dbg_zonedb("Found zone for name %s: %p\n", name, zone);
@@ -247,6 +253,8 @@ dbg_zonedb_exec(
zone = NULL;
}
+ knot_dname_free(&dummy_zone.name);
+
return zone;
}
diff --git a/src/tests/common/acl_tests.c b/src/tests/common/acl_tests.c
index e9af20c..a7613e7 100644
--- a/src/tests/common/acl_tests.c
+++ b/src/tests/common/acl_tests.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <sys/types.h>
#include <sys/socket.h>
#include "tests/common/acl_tests.h"
diff --git a/src/tests/common/fdset_tests.c b/src/tests/common/fdset_tests.c
index 7dd95a1..08e0577 100644
--- a/src/tests/common/fdset_tests.c
+++ b/src/tests/common/fdset_tests.c
@@ -120,7 +120,7 @@ static int fdset_tests_run(int argc, char *argv[])
pthread_create(&t, 0, thr_action, &fds[1]);
/* 4. Watch fdset. */
- ret = fdset_wait(set);
+ ret = fdset_wait(set, OS_EV_FOREVER);
gettimeofday(&te, 0);
size_t diff = timeval_diff(&ts, &te);
@@ -151,7 +151,7 @@ static int fdset_tests_run(int argc, char *argv[])
close(tmpfds[1]);
/* 9. Poll empty fdset. */
- ret = fdset_wait(set);
+ ret = fdset_wait(set, OS_EV_FOREVER);
ok(ret <= 0, "fdset: polling empty fdset returns -1 (ret=%d)", ret);
/* 10. Crash test. */
@@ -159,7 +159,7 @@ static int fdset_tests_run(int argc, char *argv[])
fdset_destroy(0);
fdset_add(0, -1, 0);
fdset_remove(0, -1);
- fdset_wait(0);
+ fdset_wait(0, OS_EV_NOWAIT);
fdset_begin(0, 0);
fdset_end(0, 0);
fdset_next(0, 0);
diff --git a/src/tests/libknot/libknot/dname_tests.c b/src/tests/libknot/libknot/dname_tests.c
index 9730756..22f6fbc 100644
--- a/src/tests/libknot/libknot/dname_tests.c
+++ b/src/tests/libknot/libknot/dname_tests.c
@@ -101,7 +101,7 @@ static int test_dname_create()
if (dname == NULL
|| knot_dname_name(dname) != NULL
|| knot_dname_size(dname) != 0
- || knot_dname_node(dname, 0) != NULL) {
+ || knot_dname_node(dname) != NULL) {
diag("New domain name not initialized properly!");
return 0;
}
@@ -161,10 +161,10 @@ static int check_domain_name(const knot_dname_t *dname,
}
if (check_node) {
- if (knot_dname_node(dname, 0) != NODE_ADDRESS) {
+ if (knot_dname_node(dname) != NODE_ADDRESS) {
diag("Node pointer in the created domain name is wrong:"
"%p (should be %p)",
- knot_dname_node(dname, 0), NODE_ADDRESS);
+ knot_dname_node(dname), NODE_ADDRESS);
++errors;
}
}
@@ -719,7 +719,7 @@ static int test_dname_node(knot_dname_t **dnames_fqdn,
for (int i = 0; i < TEST_DOMAINS_OK; i++) {
const knot_node_t *tmp_node;
- if ((tmp_node = knot_dname_node(dnames_fqdn[i], 0)) !=
+ if ((tmp_node = knot_dname_node(dnames_fqdn[i])) !=
NODE_ADDRESS) {
diag("Got bad node value from structure: "
"%p, should be: %p",
@@ -730,7 +730,7 @@ static int test_dname_node(knot_dname_t **dnames_fqdn,
for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
const knot_node_t *tmp_node;
- if ((tmp_node = knot_dname_node(dnames_non_fqdn[i], 0)) !=
+ if ((tmp_node = knot_dname_node(dnames_non_fqdn[i])) !=
NODE_ADDRESS) {
diag("Got bad node value from structure: "
"%s, should be: %s",
diff --git a/src/tests/libknot/libknot/node_tests.c b/src/tests/libknot/libknot/node_tests.c
index f04a202..d6b1e48 100644
--- a/src/tests/libknot/libknot/node_tests.c
+++ b/src/tests/libknot/libknot/node_tests.c
@@ -76,7 +76,7 @@ static int test_node_create()
errors++;
diag("Failed to create node structure");
}
- knot_node_free(&tmp, 0, 0);
+ knot_node_free(&tmp, 0);
}
return (errors == 0);
}
@@ -134,7 +134,7 @@ static int test_node_add_rrset()
diag("Values in found rrset are wrong");
}
- knot_node_free(&tmp, 0, 0);
+ knot_node_free(&tmp, 0);
}
return (errors == 0);
@@ -166,7 +166,7 @@ static int test_node_get_rrset()
diag("Failed to get proper rrset from node");
}
}
- knot_node_free(&nodes[i], 0, 0);
+ knot_node_free(&nodes[i], 0);
}
return (errors == 0);
@@ -190,11 +190,11 @@ static int test_node_get_parent()
for (int i = 0; i < TEST_NODES && !errors; i++) {
rrset = &rrsets[i];
- if (knot_node_parent(nodes[i], 0) != test_nodes[i].parent) {
+ if (knot_node_parent(nodes[i]) != test_nodes[i].parent) {
errors++;
diag("Failed to get proper parent from node");
}
- knot_node_free(&nodes[i], 0, 0);
+ knot_node_free(&nodes[i], 0);
}
return (errors == 0);
}
@@ -230,7 +230,7 @@ static int test_node_sorting()
// last = *((uint16_t *)node->key);
// }
- knot_node_free(&tmp, 0, 0);
+ knot_node_free(&tmp, 0);
return (errors == 0);
}
@@ -244,7 +244,7 @@ static int test_node_delete()
tmp_node = knot_node_new(&test_nodes[i].owner,
test_nodes[i].parent, 0);
- knot_node_free(&tmp_node, 0, 0);
+ knot_node_free(&tmp_node, 0);
errors += (tmp_node != NULL);
}
@@ -269,9 +269,9 @@ static int test_node_set_parent()
diag("Parent node is wrongly set.");
errors++;
}
- knot_node_free(&tmp_node, 0, 0);
+ knot_node_free(&tmp_node, 0);
}
- knot_node_free(&tmp_parent, 0, 0);
+ knot_node_free(&tmp_parent, 0);
return (errors == 0);
}
@@ -289,7 +289,7 @@ static int test_node_free_rrsets()
// errors += (tmp_node->rrsets != NULL);
- knot_node_free(&tmp_node, 0, 0);
+ knot_node_free(&tmp_node, 0);
}
return (errors == 0);
}
diff --git a/src/tests/libknot/libknot/response_tests.c b/src/tests/libknot/libknot/response_tests.c
index 93cf2df..f40bb76 100644
--- a/src/tests/libknot/libknot/response_tests.c
+++ b/src/tests/libknot/libknot/response_tests.c
@@ -234,7 +234,7 @@ static int test_response_add_opt()
opt.size = 25; // does it matter?
lives_ok({
- if (knot_response_add_opt(NULL, NULL, 0) != KNOT_EBADARG) {
+ if (knot_response_add_opt(NULL, NULL, 0, 0) != KNOT_EBADARG) {
diag("Calling response add opt with NULL arguments "
"did not result to KNOT_EBADARG");
errors++;
@@ -245,7 +245,7 @@ static int test_response_add_opt()
assert(response);
lived = 0;
if (knot_response_add_opt(response,
- NULL, 0) != KNOT_EBADARG) {
+ NULL, 0, 0) != KNOT_EBADARG) {
diag("Calling response add opt with NULL OPT RR "
"did not result to KNOT_EBADARG");
errors++;
@@ -254,7 +254,7 @@ static int test_response_add_opt()
lived = 0;
if (knot_response_add_opt(NULL,
- &opt, 0) != KNOT_EBADARG) {
+ &opt, 0, 0) != KNOT_EBADARG) {
diag("Calling response add opt with NULL response "
"did not result to KNOT_EBADARG");
errors++;
@@ -270,21 +270,21 @@ static int test_response_add_opt()
knot_packet_set_max_size(response, KNOT_PACKET_PREALLOC_RESPONSE * 100);
assert(knot_response_init(response) == KNOT_EOK);;
- if (knot_response_add_opt(response, &opt, 0) != KNOT_EOK) {
+ if (knot_response_add_opt(response, &opt, 0, 0) != KNOT_EOK) {
diag("Adding valid OPT RR to response "
"did not return KNOT_EOK");
errors++;
}
opt.payload = response->max_size + 1;
- if (knot_response_add_opt(response, &opt, 1) != KNOT_EPAYLOAD) {
+ if (knot_response_add_opt(response, &opt, 1, 0) != KNOT_EPAYLOAD) {
diag("If OPT RR payload is bigger than response max size "
"response_add_opt does not return KNOT_EPAYLOAD!");
errors++;
}
opt.payload = 0;
- if (knot_response_add_opt(response, &opt, 1) != KNOT_EBADARG) {
+ if (knot_response_add_opt(response, &opt, 1, 0) != KNOT_EBADARG) {
diag("Calling response_add_opt with OPT RR payload set to 0 "
"did not return KNOT_EBADARG");
}
@@ -294,14 +294,14 @@ static int test_response_add_opt()
}
static int test_response_add_generic(int (*func)(knot_packet_t *,
- const knot_rrset_t *,
- int, int, int))
+ knot_rrset_t *,
+ int, int, int, int))
{
int errors = 0;
int lived = 0;
lives_ok({
- if (func(NULL, NULL, 0, 0, 0) != KNOT_EBADARG) {
+ if (func(NULL, NULL, 0, 0, 0, 0) != KNOT_EBADARG) {
diag("Calling response add rrset with NULL "
"arguments did not return KNOT_EBADARG!");
errors++;
@@ -311,7 +311,7 @@ static int test_response_add_generic(int (*func)(knot_packet_t *,
knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
assert(response);
lived = 0;
- if (func(response, NULL, 0, 0, 0) != KNOT_EBADARG) {
+ if (func(response, NULL, 0, 0, 0, 0) != KNOT_EBADARG) {
diag("Calling response add rrset with NULL rrset "
"did not return KNOT_EBADARG!");
errors++;
@@ -327,7 +327,7 @@ static int test_response_add_generic(int (*func)(knot_packet_t *,
KNOT_CLASS_IN, 3600);
assert(rrset);
lived = 0;
- if (func(NULL, rrset, 0, 0, 0) != KNOT_EBADARG) {
+ if (func(NULL, rrset, 0, 0, 0, 0) != KNOT_EBADARG) {
diag("Calling response add rrset with NULL response "
"did not return KNOT_EBADARG!");
errors++;
@@ -354,7 +354,7 @@ static int test_response_add_generic(int (*func)(knot_packet_t *,
knot_rrset_new(owner, KNOT_RRTYPE_NS,
KNOT_CLASS_IN, 3600);
assert(rrset);
- if (func(response, rrset, 0, 0, 0) != KNOT_EOK) {
+ if (func(response, rrset, 0, 0, 0, 0) != KNOT_EOK) {
diag("Adding valid RRSet to response did not result to "
"KNOT_EOK");
errors++;
diff --git a/src/tests/libknot/libknot/tsig_tests.c b/src/tests/libknot/libknot/tsig_tests.c
index e8cab14..31720ec 100644
--- a/src/tests/libknot/libknot/tsig_tests.c
+++ b/src/tests/libknot/libknot/tsig_tests.c
@@ -23,6 +23,7 @@
#include "libknot/util/error.h"
#include "libknot/util/wire.h"
#include "libknot/tsig-op.h"
+#include "common/print.h"
#include "tsig_tests.h"
@@ -239,8 +240,8 @@ static int test_knot_tsig_sign()
knot_wire_set_arcount(msg, 0);
/* Wire now should be identical. Compare with its pre-signing copy. */
if (strncmp((char *)msg, (char *)msg_copy, msg_len) != 0) {
- hex_print(msg, msg_len);
- hex_print(msg_copy, msg_len);
+ hex_print((const char*)msg, msg_len);
+ hex_print((const char*)msg_copy, msg_len);
diag("knot_tsig_sign has changed the signed wire!");
errors++;
}
@@ -267,8 +268,8 @@ static int test_knot_tsig_sign()
knot_wire_set_arcount(msg, 0);
/* Wire now should be identical. Compare with its pre-signing copy. */
if (strncmp((char *)msg, (char *)msg_copy, msg_len) != 0) {
- hex_print(msg, msg_len);
- hex_print(msg_copy, msg_len);
+ hex_print((const char*)msg, msg_len);
+ hex_print((const char*)msg_copy, msg_len);
diag("knot_tsig_sign has changed the signed wire!");
errors++;
}
diff --git a/src/tests/libknot/libknot/zone_tests.c b/src/tests/libknot/libknot/zone_tests.c
index 2fdd61a..192996c 100644
--- a/src/tests/libknot/libknot/zone_tests.c
+++ b/src/tests/libknot/libknot/zone_tests.c
@@ -95,13 +95,13 @@ static int test_zone_create(knot_zone_contents_t **zone)
if ((*zone) == NULL) {
diag("zone: Failed to create zone.");
- knot_node_free(&node, 1, 0);
+ knot_node_free(&node, 0);
return 0;
}
if ((*zone)->apex != node) {
diag("zone: Zone apex not set right.");
- knot_node_free(&node, 1, 0);
+ knot_node_free(&node, 0);
return 0;
}
@@ -133,7 +133,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
: knot_zone_contents_add_node(zone, node, 0, 0, 0))) != 0) {
diag("zone: Failed to insert node into zone (returned"
" %d).", res);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
++errors;
}
/* TODO check values in the node as well */
@@ -157,7 +157,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
KNOT_EBADZONE);
++errors;
}
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
}
//note("NULL zone");
@@ -179,7 +179,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
++errors;
}
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
//note("NULL node");
note("Inserting NULL node...\n");
@@ -211,7 +211,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
++errors;
}
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
}
// check if all nodes are inserted
diff --git a/src/tests/libknot/libknot/zone_tree_tests.c b/src/tests/libknot/libknot/zone_tree_tests.c
index c26746e..207afea 100644
--- a/src/tests/libknot/libknot/zone_tree_tests.c
+++ b/src/tests/libknot/libknot/zone_tree_tests.c
@@ -238,14 +238,14 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_find_less_or_equal(NULL,
NULL,
NULL,
- NULL, 0) !=
+ NULL) !=
KNOT_EBADARG) {
errors++;
}
lived = 1;
lived = 0;
if (knot_zone_tree_find_less_or_equal(tree, NULL,
- NULL, NULL, 0) !=
+ NULL, NULL) !=
KNOT_EBADARG) {
errors++;
}
@@ -254,7 +254,7 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_find_less_or_equal(tree,
node->owner,
NULL,
- NULL, 0) !=
+ NULL) !=
KNOT_EBADARG) {
errors++;
}
@@ -262,7 +262,7 @@ static int test_tree_finding_less_or_equal()
const knot_node_t *found_node = NULL;
lived = 0;
if (knot_zone_tree_find_less_or_equal(NULL, node->owner,
- &found_node, NULL, 0) !=
+ &found_node, NULL) !=
KNOT_EBADARG) {
errors++;
}
@@ -271,7 +271,7 @@ static int test_tree_finding_less_or_equal()
lived = 0;
if (knot_zone_tree_find_less_or_equal(tree, NULL,
&found_node,
- &previous_node, 0) !=
+ &previous_node) !=
KNOT_EBADARG) {
errors++;
}
@@ -296,7 +296,7 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_find_less_or_equal(tree,
node->owner,
&found_node,
- &previous_node, 0) <= 0) {
+ &previous_node) <= 0) {
diag("Calling zone tree find less with valid arguments did "
"not return KNOT_EOK");
errors++;
@@ -309,8 +309,8 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_get_less_or_equal(tree, node->owner,
(knot_node_t **)&found_node,
- (knot_node_t **)&previous_node, 0) <=
- 0) {
+ (knot_node_t **)&previous_node)
+ <= 0) {
diag("Calling zone tree get less with valid arguments did "
"not return KNOT_EOK");
errors++;
@@ -331,7 +331,7 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_find_less_or_equal(tree,
less_dname,
&found_node,
- &previous_node, 0) <= 0) {
+ &previous_node) <= 0) {
diag("Calling zone tree find less or equal "
"with valid arguments did "
"not return > 0");
@@ -345,8 +345,8 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_get_less_or_equal(tree, less_dname,
(knot_node_t **)&found_node,
- (knot_node_t **)&previous_node, 0) <=
- 0) {
+ (knot_node_t **)&previous_node)
+ <= 0) {
diag("Calling zone tree less or equal with valid arguments did "
"not return > 0");
errors++;
@@ -365,7 +365,7 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_find_less_or_equal(tree, alien_dname,
&found_node,
- &previous_node, 0) !=
+ &previous_node) !=
0) {
diag("Calling zone tree find less with valid arguments did "
"not return 0");
@@ -375,8 +375,8 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_get_less_or_equal(tree,
alien_dname,
(knot_node_t **)&found_node,
- (knot_node_t **)&previous_node, 0) !=
- 0) {
+ (knot_node_t **)&previous_node)
+ != 0) {
diag("Calling zone tree get with valid arguments did "
"not return 0");
errors++;
@@ -392,7 +392,7 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_find_less_or_equal(tree, node->owner,
&found_node,
- &previous_node, 0) <=
+ &previous_node) <=
0) {
diag("Calling zone tree find with valid arguments did "
"not return > 0");
@@ -407,8 +407,8 @@ static int test_tree_finding_less_or_equal()
if (knot_zone_tree_get_less_or_equal(tree, node->owner,
(knot_node_t **)&found_node,
- (knot_node_t **)&previous_node, 0) <=
- 0) {
+ (knot_node_t **)&previous_node)
+ <= 0) {
diag("Calling zone tree get with valid arguments did "
"not return > 0");
errors++;
diff --git a/src/tests/libknot/realdata/libknot/node_tests_realdata.c b/src/tests/libknot/realdata/libknot/node_tests_realdata.c
index 3218c8e..b9415ef 100644
--- a/src/tests/libknot/realdata/libknot/node_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/node_tests_realdata.c
@@ -94,7 +94,7 @@ static int test_node_create(const list *node_list)
errors++;
diag("Failed to create node structure");
}
- knot_node_free(&tmp, 0, 0);
+ knot_node_free(&tmp, 0);
}
return (errors == 0);
@@ -168,7 +168,7 @@ static int test_node_add_rrset(list *rrset_list)
diag("Values in found rrset are wrong");
}
- knot_node_free(&tmp, 1, 0);
+ knot_node_free(&tmp, 0);
}
return (errors == 0);
diff --git a/src/tests/libknot/realdata/libknot/response_tests_realdata.c b/src/tests/libknot/realdata/libknot/response_tests_realdata.c
index 5bbda36..7dac341 100644
--- a/src/tests/libknot/realdata/libknot/response_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/response_tests_realdata.c
@@ -105,8 +105,8 @@ static int test_response_init_from_query(list query_list)
extern knot_rrset_t *rrset_from_test_rrset(test_rrset_t *test_rrset);
static int test_response_add_generic(int (*func)(knot_packet_t *,
- const knot_rrset_t *,
- int, int, int),
+ knot_rrset_t *,
+ int, int, int, int),
list rrset_list)
{
/*!< \todo Now adding only one RRSet at the time, try more, use nodes */
@@ -125,7 +125,7 @@ static int test_response_add_generic(int (*func)(knot_packet_t *,
assert(rrset);
int ret = 0;
- if ((ret = func(response, rrset, 0, 1, 0)) != KNOT_EOK) {
+ if ((ret = func(response, rrset, 0, 1, 0, 0)) != KNOT_EOK) {
diag("Could not add RRSet to response! Returned: %d",
ret);
diag("(owner: %s type %s)",
diff --git a/src/tests/libknot/realdata/libknot/zone_tests_realdata.c b/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
index 445997f..2738dab 100644
--- a/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
@@ -77,7 +77,7 @@ static int test_zone_create(list node_list)
errors++;
}
knot_node_free_rrsets(node, 1);
- knot_node_free(&node, 0, 0);
+ knot_node_free(&node, 0);
}
return (errors == 0);
diff --git a/src/tests/xfr_tests.c b/src/tests/xfr_tests.c
index 8a0b703..9ea19fe 100644
--- a/src/tests/xfr_tests.c
+++ b/src/tests/xfr_tests.c
@@ -21,7 +21,6 @@
* - signal handler now handles one more signal
* SIGCONT is used to signal this
* binary that an integrity check should be done
- * - once the integrity check is completed, the server signal the script
*/
#include <time.h>
@@ -46,10 +45,8 @@
static volatile short sig_req_stop = 0;
static volatile short sig_req_reload = 0;
static volatile short sig_stopping = 0;
+static volatile short sig_integrity_check = 0;
-/* Global PID of invoking script. */
-static pid_t script_pid;
-static const char *zone;
// SIGINT signal handler
void interrupt_handle(int s)
@@ -73,12 +70,8 @@ void interrupt_handle(int s)
// Start zone integrity check
if (s == SIGCONT) {
- /*!< \todo Insert actual integrity check! */
- if (1) {
- kill(script_pid, SIGCONT);
- } else {
- kill(script_pid, SIGHUP);
- }
+ sig_integrity_check = 1;
+ return;
}
}
@@ -88,6 +81,7 @@ void help(int argc, char **argv)
PACKAGE_NAME);
printf("Parameters:\n"
" -c, --config [file] Select configuration file.\n"
+ " -z, --zone [origin] Inspected zone origin.\n"
" -d, --daemonize Run server as a daemon.\n"
" -v, --verbose Verbose mode - additional runtime information.\n"
" -V, --version Print version of the server.\n"
@@ -97,15 +91,17 @@ void help(int argc, char **argv)
int main(int argc, char **argv)
{
// Parse command line arguments
+ int check_iteration = 0;
int c = 0, li = 0;
int verbose = 0;
int daemonize = 0;
- char* config_fn = 0;
+ char* config_fn = NULL;
+ char *zone = NULL;
/* Long options. */
struct option opts[] = {
{"config", required_argument, 0, 'c'},
- {"script_pid",required_argument, 0, 'p'},
+ {"zone", required_argument, 0, 'z'},
{"daemonize", no_argument, 0, 'd'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
@@ -113,7 +109,7 @@ int main(int argc, char **argv)
{0, 0, 0, 0}
};
- while ((c = getopt_long(argc, argv, "c:p:dvVh", opts, &li)) != -1) {
+ while ((c = getopt_long(argc, argv, "c:z:dvVh", opts, &li)) != -1) {
switch (c)
{
case 'c':
@@ -128,9 +124,6 @@ int main(int argc, char **argv)
case 'V':
printf("%s, version %s\n", "Knot DNS", PACKAGE_VERSION);
return 0;
- case 'p':
- script_pid = atoi(optarg);
- break;
case 'z':
zone = strdup(optarg);
break;
@@ -144,7 +137,9 @@ int main(int argc, char **argv)
// Now check if we want to daemonize
if (daemonize) {
- if (daemon(1, 0) != 0) {
+ if (daemon(1, 0) != 0) {
+ free(zone);
+ free(config_fn);
fprintf(stderr, "Daemonization failed, "
"shutting down...\n");
return 1;
@@ -214,11 +209,16 @@ int main(int argc, char **argv)
}
// Open configuration
- log_server_info("Parsing configuration '%s' ...\n", config_fn);
- if (conf_open(config_fn) != KNOTD_EOK) {
-
- log_server_error("Failed to parse configuration file '%s'.\n",
- config_fn);
+ log_server_info("Reading configuration '%s' ...\n", config_fn);
+ int conf_ret = conf_open(config_fn);
+ if (conf_ret != KNOTD_EOK) {
+ if (conf_ret == KNOTD_ENOENT) {
+ log_server_error("Couldn't open configuration file "
+ "'%s'.\n", config_fn);
+ } else {
+ log_server_error("Failed to parse configuration '%s'.\n",
+ config_fn);
+ }
server_destroy(&server);
free(config_fn);
return 1;
@@ -313,6 +313,17 @@ int main(int argc, char **argv)
break;
}
}
+ if (zone == NULL) sig_integrity_check = 0;
+ if (sig_integrity_check) {
+ log_server_info("Starting integrity check of zone: %s\n", zone);
+ knot_dname_t* zdn = knot_dname_new_from_str(zone, strlen(zone), NULL);
+ knot_zone_t *z = knot_zonedb_find_zone(server->nameserver->zone_db, zdn);
+ int ic_ret = knot_zone_contents_integrity_check(z->contents);
+ log_server_info("Integrity check: %d errors discovered.\n", ic_ret);
+ knot_dname_free(&zdn);
+ log_server_info("Integrity check %d finished.\n", check_iteration);
+ ++check_iteration;
+ }
/* Events. */
if (ret > 0) {
@@ -357,6 +368,7 @@ int main(int argc, char **argv)
evqueue_free(&q);
// Free default config filename if exists
+ free(zone);
free(config_fn);
if (!daemonize) {
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
index 7038cd4..f02fdcf 100644
--- a/src/zcompile/zcompile.c
+++ b/src/zcompile/zcompile.c
@@ -527,7 +527,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
//assert(origin_node->next == NULL);
- assert(knot_node_parent(origin_node, 0) == NULL);
+ assert(knot_node_parent(origin_node) == NULL);
if (origin_node == NULL) {
knot_dname_release(dname);
return KNOTDZCOMPILE_ENOMEM;
@@ -609,7 +609,8 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
parser->errors++;
}
- knot_zone_contents_adjust(contents, 0);
+ /*! \todo Check return value. */
+ knot_zone_contents_adjust(contents);
dbg_zp("rdata adjusted\n");