summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-02-29 18:44:04 +0100
committerOndřej Surý <ondrej@sury.org>2012-02-29 18:44:04 +0100
commit12850a9ff76121bd81835b48e7c9fc8bb40a6d18 (patch)
treea58b8511d1c335eb6be9e1acc330478251ca21a0
parent7b6c64f3ce94255fb39db56d5d39e00083cc367d (diff)
parent329f909f84efaecfc56fa80a329fb91e576b4f31 (diff)
downloadknot-12850a9ff76121bd81835b48e7c9fc8bb40a6d18.tar.gz
Merge commit 'upstream/1.0.0' into debian-sid
-rw-r--r--KNOWN_ISSUES5
-rw-r--r--RELNOTES14
-rwxr-xr-xconfigure68
-rw-r--r--configure.ac26
-rw-r--r--src/common/acl.c130
-rw-r--r--src/common/acl.h10
-rw-r--r--src/common/dynamic-array.c1
-rw-r--r--src/common/evsched.c2
-rw-r--r--src/common/fdset_kqueue.c1
-rw-r--r--src/common/general-tree.c2
-rw-r--r--src/common/libtap/tap.c128
-rw-r--r--src/common/libtap/tap.h126
-rw-r--r--src/common/skip-list.c10
-rw-r--r--src/common/sockaddr.c13
-rw-r--r--src/common/sockaddr.h16
-rw-r--r--src/config.h.in27
-rw-r--r--src/knot/conf/cf-parse.y169
-rw-r--r--src/knot/conf/conf.c103
-rw-r--r--src/knot/conf/conf.h1
-rw-r--r--src/knot/ctl/knotc_main.c11
-rw-r--r--src/knot/ctl/process.c2
-rw-r--r--src/knot/main.c2
-rw-r--r--src/knot/other/debug.h37
-rw-r--r--src/knot/other/error.c2
-rw-r--r--src/knot/server/journal.c78
-rw-r--r--src/knot/server/journal.h31
-rw-r--r--src/knot/server/notify.c5
-rw-r--r--src/knot/server/tcp-handler.c1
-rw-r--r--src/knot/server/udp-handler.c12
-rw-r--r--src/knot/server/xfr-handler.c489
-rw-r--r--src/knot/server/zones.c382
-rw-r--r--src/knot/server/zones.h21
-rw-r--r--src/knot/zone/semantic-check.c99
-rw-r--r--src/knot/zone/zone-dump-text.c59
-rw-r--r--src/knot/zone/zone-dump-text.h4
-rw-r--r--src/knot/zone/zone-dump.c504
-rw-r--r--src/knot/zone/zone-dump.h20
-rw-r--r--src/knot/zone/zone-load.c90
-rw-r--r--src/libknot/dname.c17
-rw-r--r--src/libknot/dname.h8
-rw-r--r--src/libknot/edns.c6
-rw-r--r--src/libknot/hash/cuckoo-hash-table.c44
-rw-r--r--src/libknot/nameserver/name-server.c113
-rw-r--r--src/libknot/nameserver/name-server.h2
-rw-r--r--src/libknot/packet/response.c1
-rw-r--r--src/libknot/rdata.c95
-rw-r--r--src/libknot/rrset.c16
-rw-r--r--src/libknot/tsig-op.c10
-rw-r--r--src/libknot/tsig.c7
-rw-r--r--src/libknot/updates/changesets.c2
-rw-r--r--src/libknot/updates/changesets.h49
-rw-r--r--src/libknot/updates/xfr-in.c502
-rw-r--r--src/libknot/updates/xfr-in.h16
-rw-r--r--src/libknot/util/debug.c1
-rw-r--r--src/libknot/util/debug.h67
-rw-r--r--src/libknot/util/libknot_error.c2
-rw-r--r--src/libknot/util/utils.h5
-rw-r--r--src/libknot/zone/node.h28
-rw-r--r--src/libknot/zone/zone-contents.c319
-rw-r--r--src/libknot/zone/zone-contents.h14
-rw-r--r--src/libknot/zone/zone-tree.c30
-rw-r--r--src/libknot/zone/zone.c3
-rw-r--r--src/libknot/zone/zonedb.c13
-rw-r--r--src/tests/common/acl_tests.c51
-rw-r--r--src/tests/knot/journal_tests.c31
-rw-r--r--src/tests/libknot/libknot/node_tests.c8
-rw-r--r--src/tests/libknot/libknot/rdata_tests.c8
-rw-r--r--src/tests/libknot/libknot/rrset_tests.c6
-rw-r--r--src/tests/libknot/libknot/tsig_tests.c16
-rw-r--r--src/tests/libknot/libknot/zone_tests.c18
-rw-r--r--src/zcompile/parser-util.c4
-rw-r--r--src/zcompile/zcompile.c177
-rw-r--r--src/zcompile/zcompile.h1
-rw-r--r--src/zcompile/zcompile_main.c2
-rw-r--r--src/zcompile/zparser.y13
75 files changed, 2629 insertions, 1777 deletions
diff --git a/KNOWN_ISSUES b/KNOWN_ISSUES
index e46c167..1d87958 100644
--- a/KNOWN_ISSUES
+++ b/KNOWN_ISSUES
@@ -4,14 +4,11 @@ Features not supported
Here is a list of the most notable features that are not supported in the
current version of Knot.
-* NSID (RFC5001)
-* Root zone support
* Other DNS classes than IN (CH, CS, HS)
* Dynamic updates
Known bugs
==========
-* Few minor bugs
-* IXFR code might be flaky sometimes
* IXFR may be slow when too much (10 000+) RRSets are transfered at once.
+* Slow start with too many zones.
diff --git a/RELNOTES b/RELNOTES
index aeeaf51..85a3121 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -1,3 +1,17 @@
+v1.0.0 - Feb 29, 2012
+---------------------
+
+New features:
+ * Support for subnets in ACL.
+ * Debug messages enabling in configure.
+ * Optimized memory consuption of zone structures.
+
+Bugfixes:
+ * Memory errors and leaks.
+ * Fixed improper handling of failed IXFR/IN.
+ * Several other minor bugfixes.
+
+
v1.0-rc1 - Feb 14, 2012
-----------------------
diff --git a/configure b/configure
index 0becd5b..89e5f3d 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for knot 1.0-rc1.
+# Generated by GNU Autoconf 2.68 for knot 1.0.0.
#
# Report bugs to <knot-dns@labs.nic.cz>.
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='knot'
PACKAGE_TARNAME='knot'
-PACKAGE_VERSION='1.0-rc1'
-PACKAGE_STRING='knot 1.0-rc1'
+PACKAGE_VERSION='1.0.0'
+PACKAGE_STRING='knot 1.0.0'
PACKAGE_BUGREPORT='knot-dns@labs.nic.cz'
PACKAGE_URL=''
@@ -747,6 +747,7 @@ with_sysroot
enable_libtool_lock
enable_ldns
enable_debug
+enable_debuglevel
enable_recvmmsg
'
ac_precious_vars='build_alias
@@ -1302,7 +1303,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures knot 1.0-rc1 to adapt to many kinds of systems.
+\`configure' configures knot 1.0.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1372,7 +1373,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of knot 1.0-rc1:";;
+ short | recursive ) echo "Configuration of knot 1.0.0:";;
esac
cat <<\_ACEOF
@@ -1390,7 +1391,9 @@ Optional Features:
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
--enable-ldns=yes|no Enable tests with ldns [default=no]
- --enable-debug=brief|verbose|details
+ --enable-debug=server,zones,xfr,packet,dname,rr,ns,hash,compiler
+ compile selected debug modules [default=none]
+ --enable-debuglevel=brief|verbose|details
enable given debug level [default=disabled]
--enable-recvmmsg=yes|no
enable recvmmsg() network API under Linux (kernel
@@ -1488,7 +1491,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-knot configure 1.0-rc1
+knot configure 1.0.0
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2038,7 +2041,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by knot $as_me 1.0-rc1, which was
+It was created by knot $as_me 1.0.0, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -2856,7 +2859,7 @@ fi
# Define the identity of the package.
PACKAGE='knot'
- VERSION='1.0-rc1'
+ VERSION='1.0.0'
cat >>confdefs.h <<_ACEOF
@@ -13134,10 +13137,49 @@ else
fi
-# Debug level
+# Debug modules
# Check whether --enable-debug was given.
if test "${enable_debug+set}" = set; then :
- enableval=$enable_debug; # Not all shells support fall-through with ;& so I have to duplicate
+ enableval=$enable_debug;
+ echo ${enableval}|tr "," "\n"|while read val; do
+ case "${val}" in
+ server)
+$as_echo "#define KNOTD_SERVER_DEBUG 1" >>confdefs.h
+ ;;
+ zones)
+$as_echo "#define KNOT_ZONES_DEBUG 1" >>confdefs.h
+ ;;
+ xfr)
+$as_echo "#define KNOT_XFR_DEBUG 1" >>confdefs.h
+ ;;
+ packet)
+$as_echo "#define KNOT_PACKET_DEBUG 1" >>confdefs.h
+ ;;
+ dname)
+$as_echo "#define KNOT_DNAME_DEBUG 1" >>confdefs.h
+ ;;
+ rr)
+$as_echo "#define KNOT_RR_DEBUG 1" >>confdefs.h
+ ;;
+ ns)
+$as_echo "#define KNOT_NS_DEBUG 1" >>confdefs.h
+ ;;
+ hash)
+$as_echo "#define KNOT_HASH_DEBUG 1" >>confdefs.h
+ ;;
+ compiler)
+$as_echo "#define KNOT_COMPILER_DEBUG 1" >>confdefs.h
+ ;;
+ esac
+ done
+
+fi
+
+
+# Debug level
+# Check whether --enable-debuglevel was given.
+if test "${enable_debuglevel+set}" = set; then :
+ enableval=$enable_debuglevel; # Not all shells support fall-through with ;& so I have to duplicate
case "x${enableval}" in
xdetails)
@@ -14850,7 +14892,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by knot $as_me 1.0-rc1, which was
+This file was extended by knot $as_me 1.0.0, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14916,7 +14958,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-knot config.status 1.0-rc1
+knot config.status 1.0.0
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index e1fb61d..f5551dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
AC_PREREQ([2.65])
-AC_INIT([knot], [1.0-rc1], [knot-dns@labs.nic.cz])
+AC_INIT([knot], [1.0.0], [knot-dns@labs.nic.cz])
AM_INIT_AUTOMAKE([gnu -Wall -Werror])
AC_CONFIG_SRCDIR([src/knot/main.c])
AC_CONFIG_HEADERS([src/config.h])
@@ -64,10 +64,30 @@ AC_ARG_ENABLE([ldns],
no) ldns=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ldns]) ;;
esac],[ldns=false])
+
+# Debug modules
+AC_ARG_ENABLE([debug],
+ AS_HELP_STRING([--enable-debug=server,zones,xfr,packet,dname,rr,ns,hash,compiler],
+ [compile selected debug modules [default=none]]),
+ [
+ echo ${enableval}|tr "," "\n"|while read val; do
+ case "${val}" in
+ server) AC_DEFINE([KNOTD_SERVER_DEBUG], [1], [Server debug.]) ;;
+ zones) AC_DEFINE([KNOT_ZONES_DEBUG], [1], [Zones debug.]) ;;
+ xfr) AC_DEFINE([KNOT_XFR_DEBUG], [1], [XFR debug.]) ;;
+ packet) AC_DEFINE([KNOT_PACKET_DEBUG], [1], [Packet debug.]) ;;
+ dname) AC_DEFINE([KNOT_DNAME_DEBUG], [1], [Domain names debug.]) ;;
+ rr) AC_DEFINE([KNOT_RR_DEBUG], [1], [RR debug.]) ;;
+ ns) AC_DEFINE([KNOT_NS_DEBUG], [1], [Nameserver debug.]) ;;
+ hash) AC_DEFINE([KNOT_HASH_DEBUG], [1], [Hashtable debug.]) ;;
+ compiler) AC_DEFINE([KNOT_COMPILER_DEBUG], [1], [Zone compiler debug.]) ;;
+ esac
+ done
+ ], [])
# Debug level
-AC_ARG_ENABLE([debug],
- AS_HELP_STRING([--enable-debug=brief|verbose|details], [enable given debug level [default=disabled]]),
+AC_ARG_ENABLE([debuglevel],
+ AS_HELP_STRING([--enable-debuglevel=brief|verbose|details], [enable given debug level [default=disabled]]),
# Not all shells support fall-through with ;& so I have to duplicate
[case "x${enableval}" in
xdetails)
diff --git a/src/common/acl.c b/src/common/acl.c
index a1c3a6e..d739319 100644
--- a/src/common/acl.c
+++ b/src/common/acl.c
@@ -16,9 +16,30 @@
#include <string.h>
#include <stdlib.h>
+#include <assert.h>
#include "common/acl.h"
+static inline uint32_t acl_sa_ipv4(sockaddr_t *a) {
+ return a->addr4.sin_addr.s_addr;
+}
+
+static inline uint32_t acl_fill_mask32(short c) {
+ /*! \todo Consider optimizing using LUT. */
+ assert(c >= 0 && c <= 32);
+ unsigned r = 0;
+ /*! This actually builds big-endian mask
+ * as we will match against addresses in
+ * network byte-order (big-endian).
+ * Otherwise it should be built from
+ * HO bit -> LO bit.
+ */
+ for (char i = 0; i < c; ++i) {
+ r |= (1 << i);
+ }
+ return r;
+}
+
static int acl_compare(void *k1, void *k2)
{
sockaddr_t* a1 = (sockaddr_t *)k1;
@@ -32,56 +53,54 @@ static int acl_compare(void *k1, void *k2)
/* Compare integers if IPv4. */
if (a1->len == sizeof(struct sockaddr_in)) {
-
- /* Allow if k1 == INADDR_ANY. */
- if (a1->addr4.sin_addr.s_addr == 0) {
- return 0;
- }
+
+ /* Compute mask .*/
+ uint32_t mask = acl_fill_mask32(a1->prefix);
/* Compare address. */
- ldiff = a1->addr4.sin_addr.s_addr - a2->addr4.sin_addr.s_addr;
- if (ldiff != 0) {
- return ldiff < 0 ? -1 : 1;
- }
-
- /* Port = 0 means any port match. */
- if (a1->addr4.sin_port == 0) {
+ ldiff = (int)((acl_sa_ipv4(a1) & mask) - (acl_sa_ipv4(a2) & mask));
+ if (ldiff < 0) {
+ return -1;
+ } else if (ldiff > 0) {
+ return 1;
+ } else {
return 0;
}
- /* Compare ports on address match. */
- ldiff = ntohs(a1->addr4.sin_port) - ntohs(a2->addr4.sin_port);
- if (ldiff != 0) {
- return ldiff < 0 ? -1 : 1;
- }
return 0;
}
/* IPv6 matching. */
#ifndef DISABLE_IPV6
if (a1->len == sizeof(struct sockaddr_in6)) {
-
- /* Compare address. */
- ldiff = memcmp(&a1->addr6.sin6_addr,
- &a2->addr6.sin6_addr,
- sizeof(struct in6_addr));
- if (ldiff < 0) {
- return -1;
- }
- if (ldiff > 0) {
- return 1;
- }
-
- /* Port = 0 means any port match. */
- if (a1->addr6.sin6_port == 0) {
- return 0;
+
+ /* Get mask .*/
+ short chunk = a1->prefix;
+
+ /* Compare address by 32bit chunks. */
+ uint32_t* a1p = (uint32_t*)&a1->addr6.sin6_addr;
+ uint32_t* a2p = (uint32_t*)&a2->addr6.sin6_addr;
+
+ /* Mask 0 = 0 bits to compare from LO->HO (in big-endian).
+ * Mask 128 = 128 bits to compare.
+ */
+ while (chunk > 0) {
+ uint32_t mask = 0xffffffff;
+ if (chunk > sizeof(mask) << 3) {
+ chunk -= sizeof(mask) << 3;
+ } else {
+ mask = acl_fill_mask32(chunk);
+ chunk = 0;
+ }
+
+ ldiff = (*(a1p++) & mask) ^ (*(a2p++) & mask);
+ if (ldiff < 0) {
+ return -1;
+ } else if (ldiff > 0) {
+ return 1;
+ }
}
- /* Compare ports on address match. */
- ldiff = ntohs(a1->addr6.sin6_port) - ntohs(a2->addr6.sin6_port);
- if (ldiff != 0) {
- return ldiff < 0 ? -1 : 1;
- }
return 0;
}
#endif
@@ -111,6 +130,19 @@ acl_t *acl_new(acl_rule_t default_rule, const char *name)
free(acl);
return 0;
}
+
+ /* Initialize skip list for rules with TSIG. */
+ /*! \todo This needs a better structure to make
+ * nodes with TSIG preferred, but for now
+ * it will do to sort nodes into two lists.
+ * (issue #1675)
+ */
+ acl->rules_pref = skip_create_list(acl_compare);
+ if (!acl->rules_pref) {
+ skip_destroy_list(&acl->rules, 0, free);
+ free(acl);
+ return 0;
+ }
/* Initialize. */
memcpy(&acl->name, name, name_len);
@@ -134,7 +166,8 @@ void acl_delete(acl_t **acl)
*acl = 0;
}
-int acl_create(acl_t *acl, const sockaddr_t* addr, acl_rule_t rule, void *val)
+int acl_create(acl_t *acl, const sockaddr_t* addr, acl_rule_t rule, void *val,
+ unsigned flags)
{
if (!acl || !addr) {
return ACL_ERROR;
@@ -142,12 +175,21 @@ int acl_create(acl_t *acl, const sockaddr_t* addr, acl_rule_t rule, void *val)
/* Insert into skip list. */
acl_key_t *key = malloc(sizeof(acl_key_t));
+ if (key == NULL) {
+ return ACL_ERROR;
+ }
+
memcpy(&key->addr, addr, sizeof(sockaddr_t));
sockaddr_update(&key->addr);
key->rule = rule;
key->val = val;
- skip_insert(acl->rules, &key->addr, key, 0);
+
+ if (flags & ACL_PREFER) {
+ skip_insert(acl->rules_pref, &key->addr, key, 0);
+ } else {
+ skip_insert(acl->rules, &key->addr, key, 0);
+ }
return ACL_ACCEPT;
}
@@ -158,15 +200,18 @@ int acl_match(acl_t *acl, const sockaddr_t* addr, acl_key_t **key)
return ACL_ERROR;
}
- acl_key_t *found = skip_find(acl->rules, (void*)addr);
+ acl_key_t *found = skip_find(acl->rules_pref, (void*)addr);
+ if (found == NULL) {
+ found = skip_find(acl->rules, (void*)addr);
+ }
/* Set stored value if exists. */
- if (key != 0) {
+ if (key != NULL) {
*key = found;
}
/* Return appropriate rule. */
- if (!found) {
+ if (found == NULL) {
return acl->default_rule;
}
@@ -181,6 +226,7 @@ int acl_truncate(acl_t *acl)
/* Destroy all rules. */
skip_destroy_list(&acl->rules, 0, free);
+ skip_destroy_list(&acl->rules_pref, 0, free);
return ACL_ACCEPT;
}
diff --git a/src/common/acl.h b/src/common/acl.h
index 7303de8..7ce8f26 100644
--- a/src/common/acl.h
+++ b/src/common/acl.h
@@ -40,10 +40,16 @@ typedef enum acl_rule_t {
ACL_ACCEPT = 1
} acl_rule_t;
+/*! \brief ACL flags. */
+enum acl_flag_t {
+ ACL_PREFER = 1 << 0 /* Preferred node. */
+};
+
/*! \brief ACL structure. */
typedef struct acl_t {
acl_rule_t default_rule; /*!< \brief Default rule. */
skip_list_t *rules; /*!< \brief Data container. */
+ skip_list_t *rules_pref; /*!< \brief Preferred data container. */
const char name[]; /*!< \brief ACL semantic name. */
} acl_t;
@@ -81,11 +87,13 @@ void acl_delete(acl_t **acl);
* \param addr IP address.
* \param rule Rule for given address.
* \param val Value to be stored for given address (or NULL).
+ * \param flags Bitfield of ACL flags.
*
* \retval ACL_ACCEPT if successful.
* \retval ACP_ERROR on error.
*/
-int acl_create(acl_t *acl, const sockaddr_t* addr, acl_rule_t rule, void *val);
+int acl_create(acl_t *acl, const sockaddr_t* addr, acl_rule_t rule, void *val,
+ unsigned flags);
/*!
* \brief Match address against ACL.
diff --git a/src/common/dynamic-array.c b/src/common/dynamic-array.c
index 1e2efac..e948821 100644
--- a/src/common/dynamic-array.c
+++ b/src/common/dynamic-array.c
@@ -118,6 +118,7 @@ int da_initialize(da_array_t *array, unsigned count, size_t item_size)
array->allocated = 0;
array->count = 0;
ERR_ALLOC_FAILED;
+ pthread_mutex_unlock(&array->mtx);
return -1;
}
diff --git a/src/common/evsched.c b/src/common/evsched.c
index 067977f..386478a 100644
--- a/src/common/evsched.c
+++ b/src/common/evsched.c
@@ -165,10 +165,10 @@ event_t* evsched_next(evsched_t *s)
/* Immediately return. */
if (timercmp(&dt, &next_ev->tv, >=)) {
+ s->current = next_ev;
rem_node(&next_ev->n);
pthread_mutex_unlock(&s->mx);
pthread_mutex_lock(&s->rl);
- s->current = next_ev;
return next_ev;
}
diff --git a/src/common/fdset_kqueue.c b/src/common/fdset_kqueue.c
index bbb35fc..b9f639d 100644
--- a/src/common/fdset_kqueue.c
+++ b/src/common/fdset_kqueue.c
@@ -15,7 +15,6 @@
*/
#include <config.h>
-
#ifdef HAVE_KQUEUE
#include <stdint.h>
diff --git a/src/common/general-tree.c b/src/common/general-tree.c
index 202b31a..e1048e7 100644
--- a/src/common/general-tree.c
+++ b/src/common/general-tree.c
@@ -19,7 +19,6 @@
#include <string.h>
#include <assert.h>
#include "common/general-tree.h"
-#include "common/errors.h"
MOD_TREE_DEFINE(general_tree_node, avl);
@@ -202,6 +201,7 @@ general_tree_t *gen_tree_shallow_copy(general_tree_t *tree)
if (gen_tree_copy_node(tree->tree->th_root,
&new_tree->tree->th_root) != 0) {
+ free(new_tree);
return NULL;
}
diff --git a/src/common/libtap/tap.c b/src/common/libtap/tap.c
index 8b660fe..d6bb995 100644
--- a/src/common/libtap/tap.c
+++ b/src/common/libtap/tap.c
@@ -1,26 +1,14 @@
-/* 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/>.
- */
+/*
+libtap - Write tests in C
+Copyright (C) 2011 Jake Gelbman <gelbman@gmail.com>
+This file is licensed under the GPL v3
+*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-
-//#include "common.h"
#include "tap.h"
static int expected_tests = NO_PLAN;
@@ -28,13 +16,6 @@ static int failed_tests;
static int current_test;
static char *todo_mesg;
-void
-plan (int tests) {
- expected_tests = tests;
- if (tests != NO_PLAN)
- printf("1..%d\n", tests);
-}
-
static char *
vstrdupf (const char *fmt, va_list args) {
char *str;
@@ -50,42 +31,57 @@ vstrdupf (const char *fmt, va_list args) {
return str;
}
+void
+cplan (int tests, const char *fmt, ...) {
+ expected_tests = tests;
+ if (tests == SKIP_ALL) {
+ char *why;
+ va_list args;
+ va_start(args, fmt);
+ why = vstrdupf(fmt, args);
+ va_end(args);
+ printf("1..0 ");
+ note("SKIP %s\n", why);
+ exit(0);
+ }
+ if (tests != NO_PLAN) {
+ printf("1..%d\n", tests);
+ }
+}
+
int
-vok_at_loc (const char *file, int line, int test, int verbose, const char *fmt,
+vok_at_loc (const char *file, int line, int test, const char *fmt,
va_list args)
{
- if (verbose) {
- char *name = vstrdupf(fmt, args);
- printf("%sok %d", test ? "" : "not ", ++current_test);
- if (*name)
- printf(" - %s", name);
- if (todo_mesg) {
- printf(" # TODO");
- if (*todo_mesg)
- printf(" %s", todo_mesg);
- }
- printf("\n");
- if (!test) {
- if (*name)
- diag(" Failed%s test '%s'\n at %s line %d.",
- todo_mesg ? " (TODO)" : "", name, file, line);
- else
- diag(" Failed%s test at %s line %d.",
- todo_mesg ? " (TODO)" : "", file, line);
- if (!todo_mesg)
- failed_tests++;
-
- free(name);
- }
+ char *name = vstrdupf(fmt, args);
+ printf("%sok %d", test ? "" : "not ", ++current_test);
+ if (*name)
+ printf(" - %s", name);
+ if (todo_mesg) {
+ printf(" # TODO");
+ if (*todo_mesg)
+ printf(" %s", todo_mesg);
}
+ printf("\n");
+ if (!test) {
+ if (*name)
+ diag(" Failed%s test '%s'\n at %s line %d.",
+ todo_mesg ? " (TODO)" : "", name, file, line);
+ else
+ diag(" Failed%s test at %s line %d.",
+ todo_mesg ? " (TODO)" : "", file, line);
+ if (!todo_mesg)
+ failed_tests++;
+ }
+ free(name);
return test;
}
int
-ok_at_loc (const char *file, int line, int verbose, int test, const char *fmt, ...) {
+ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
- vok_at_loc(file, line, test, verbose, fmt, args);
+ vok_at_loc(file, line, test, fmt, args);
va_end(args);
return test;
}
@@ -105,7 +101,7 @@ is_at_loc (const char *file, int line, const char *got, const char *expected,
int test = eq(got, expected);
va_list args;
va_start(args, fmt);
- vok_at_loc(file, line, test, 1, fmt, args);
+ vok_at_loc(file, line, test, fmt, args);
va_end(args);
if (!test) {
diag(" got: '%s'", got);
@@ -116,13 +112,12 @@ is_at_loc (const char *file, int line, const char *got, const char *expected,
int
isnt_at_loc (const char *file, int line, const char *got, const char *expected,
- int verbose,
const char *fmt, ...)
{
int test = ne(got, expected);
va_list args;
va_start(args, fmt);
- vok_at_loc(file, line, test, verbose, fmt, args);
+ vok_at_loc(file, line, test, fmt, args);
va_end(args);
if (!test) {
diag(" got: '%s'", got);
@@ -156,7 +151,7 @@ cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b,
: diag("unrecognized operator '%s'", op);
va_list args;
va_start(args, fmt);
- vok_at_loc(file, line, test, 1, fmt, args);
+ vok_at_loc(file, line, test, fmt, args);
va_end(args);
if (!test) {
diag(" %d", a);
@@ -179,9 +174,10 @@ vdiag_to_fh (FILE *fh, const char *fmt, va_list args) {
if (!c || c == '\n') {
mesg[i] = '\0';
fprintf(fh, "# %s\n", line);
- if (!c) break;
+ if (!c)
+ break;
mesg[i] = c;
- line = &mesg[i+1];
+ line = mesg + i + 1;
}
}
free(mesg);
@@ -228,6 +224,18 @@ exit_status () {
return retval;
}
+int
+bail_out (int ignore, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ printf("Bail out! ");
+ vprintf(fmt, args);
+ printf("\n");
+ va_end(args);
+ exit(255);
+ return 0;
+}
+
void
skippy (int n, const char *fmt, ...) {
char *why;
@@ -260,7 +268,7 @@ cendtodo () {
#include <sys/mman.h>
#include <regex.h>
-#ifndef MAP_ANONYMOUS
+#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
@@ -282,10 +290,11 @@ tap_test_died (int status) {
int
like_at_loc (int for_match, const char *file, int line, const char *got,
- const char *expected, int verbose, const char *fmt, ...)
+ const char *expected, const char *fmt, ...)
{
int test;
regex_t re;
+ va_list args;
int err = regcomp(&re, expected, REG_EXTENDED);
if (err) {
char errbuf[256];
@@ -297,9 +306,8 @@ like_at_loc (int for_match, const char *file, int line, const char *got,
err = regexec(&re, got, 0, NULL, 0);
regfree(&re);
test = for_match ? !err : err;
- va_list args;
va_start(args, fmt);
- vok_at_loc(file, line, test, verbose, fmt, args);
+ vok_at_loc(file, line, test, fmt, args);
va_end(args);
if (!test) {
if (for_match) {
diff --git a/src/common/libtap/tap.h b/src/common/libtap/tap.h
index 4522fbb..89484f4 100644
--- a/src/common/libtap/tap.h
+++ b/src/common/libtap/tap.h
@@ -1,104 +1,114 @@
-/* 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/>.
- */
+/*
+libtap - Write tests in C
+Copyright (C) 2011 Jake Gelbman <gelbman@gmail.com>
+This file is licensed under the GPL v3
+*/
#ifndef __TAP_H__
#define __TAP_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy __va_copy
+#else
+#define va_copy(d, s) ((d) = (s))
+#endif
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-#define NO_PLAN -1
-#define ok(...) ok_at_loc(__FILE__, __LINE__, 1, __VA_ARGS__, NULL)
-#define pass(...) ok(1, ## __VA_ARGS__)
-#define fail(...) ok(0, ## __VA_ARGS__)
-#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
-#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
-#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
-
-int vok_at_loc (const char *file, int line, int test, int verbose, const char *fmt,
+int vok_at_loc (const char *file, int line, int test, const char *fmt,
va_list args);
-void plan (int tests);
-int ok_at_loc (const char *file, int line, int test, int verbose, const char *fmt,
+int ok_at_loc (const char *file, int line, int test, const char *fmt,
...);
+int is_at_loc (const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...);
+int isnt_at_loc (const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...);
+int cmp_ok_at_loc (const char *file, int line, int a, const char *op,
+ int b, const char *fmt, ...);
+int bail_out (int ignore, const char *fmt, ...);
+void cplan (int tests, const char *fmt, ...);
int diag (const char *fmt, ...);
int note (const char *fmt, ...);
int exit_status (void);
void skippy (int n, const char *fmt, ...);
void ctodo (int ignore, const char *fmt, ...);
void cendtodo (void);
-int is_at_loc (const char *file, int line, const char *got,
- const char *expected,
- const char *fmt, ...);
-int isnt_at_loc (const char *file, int line, const char *got,
- const char *expected, int verbose, const char *fmt, ...);
-int cmp_ok_at_loc (const char *file, int line, int a, const char *op,
- int b, const char *fmt, ...);
-#ifdef _WIN32
-#define like(...) skippy(1, "like is not implemented on MSWin32")
-#define unlike(...) like()
-#else
-#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL)
-#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL)
-int like_at_loc (int for_match, const char *file, int line,
- const char *got, const char *expected,
- int verbose,
- const char *fmt, ...);
-#endif
+#define NO_PLAN -1
+#define SKIP_ALL -2
+#define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define plan(...) cplan(__VA_ARGS__, NULL)
+#define done_testing() return exit_status()
+#define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL)
+#define pass(...) ok(1, "" __VA_ARGS__)
+#define fail(...) ok(0, "" __VA_ARGS__)
#define skip(test, ...) do {if (test) {skippy(__VA_ARGS__, NULL); break;}
#define endskip } while (0)
-#define todo(...) ctodo(0, ## __VA_ARGS__, NULL)
+#define todo(...) ctodo(0, "" __VA_ARGS__, NULL)
#define endtodo cendtodo()
-#define dies_ok(code, ...) dies_ok_common(code, 1, 1, ## __VA_ARGS__)
-#define lives_ok(code, ...) dies_ok_common(code, 0, 1, ## __VA_ARGS__)
-#define lives_ok_silent(code, ...) dies_ok_common(code, 0, 0, ## __VA_ARGS__)
+#define dies_ok(...) dies_ok_common(1, __VA_ARGS__)
+#define lives_ok(...) dies_ok_common(0, __VA_ARGS__)
#ifdef _WIN32
+#define like(...) skippy(1, "like is not implemented on MSWin32")
+#define unlike like
#define dies_ok_common(...) \
skippy(1, "Death detection is not supported on MSWin32")
#else
+#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL)
+#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL)
+int like_at_loc (int for_match, const char *file, int line,
+ const char *got, const char *expected,
+ const char *fmt, ...);
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int tap_test_died (int status);
-#define dies_ok_common(code, for_death, verbose, ...) \
+#define dies_ok_common(for_death, code, ...) \
do { \
+ int cpid; \
+ int it_died; \
tap_test_died(1); \
- int cpid = fork(); \
+ cpid = fork(); \
switch (cpid) { \
case -1: \
perror("fork error"); \
- exit(EXIT_FAILURE); \
- case 0: /* child */ \
- close(1); close(2); \
+ exit(1); \
+ case 0: \
+ close(1); \
+ close(2); \
code \
tap_test_died(0); \
- exit(EXIT_SUCCESS); \
+ exit(0); \
} \
if (waitpid(cpid, NULL, 0) < 0) { \
perror("waitpid error"); \
- exit(EXIT_FAILURE); \
+ exit(1); \
} \
- int it_died = tap_test_died(0); \
- if (!it_died) {code} \
- ok_at_loc(__FILE__, __LINE__, verbose, for_death ? it_died : !it_died, ## __VA_ARGS__); \
+ it_died = tap_test_died(0); \
+ if (!it_died) \
+ {code} \
+ ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \
} while (0)
#endif
+
+#ifdef __cplusplus
+}
#endif
+
+#endif
+
diff --git a/src/common/skip-list.c b/src/common/skip-list.c
index 79e9429..cde08d7 100644
--- a/src/common/skip-list.c
+++ b/src/common/skip-list.c
@@ -66,10 +66,10 @@ static float frand()
/*!
* \brief Returns random level between 0 and MAX_LEVEL.
*/
-static int skip_random_level()
+static unsigned skip_random_level()
{
static int first = 1;
- int lvl = 0;
+ unsigned lvl = 0;
if (first) {
first = 0;
@@ -216,6 +216,7 @@ void *skip_find(const skip_list_t *list, void *key)
&& list->compare_keys(x->forward[i]->key, key) == -1) {
x = x->forward[i];
}
+ if (i == 0) break;
}
x = x->forward[0];
@@ -240,6 +241,7 @@ void *skip_find_less_or_equal(const skip_list_t *list, void *key)
&& list->compare_keys(x->forward[i]->key, key) <= 0) {
x = x->forward[i];
}
+ if (i == 0) break;
}
return x->value;
@@ -265,11 +267,12 @@ int skip_insert(skip_list_t *list, void *key, void *value,
x = x->forward[i];
}
update[i] = x;
+ if (i == 0) break;
}
x = x->forward[0];
if (x == NULL || list->compare_keys(x->key, key) != 0) {
- int lvl = skip_random_level();
+ unsigned lvl = skip_random_level();
if (lvl > list->level) {
for (i = list->level + 1; i <= lvl; i++) {
@@ -319,6 +322,7 @@ int skip_remove(skip_list_t *list, void *key, void (*destroy_key)(void *),
x = x->forward[i];
}
update[i] = x;
+ if (i == 0) break;
}
x = x->forward[0];
diff --git a/src/common/sockaddr.c b/src/common/sockaddr.c
index cd3a4b9..48551bc 100644
--- a/src/common/sockaddr.c
+++ b/src/common/sockaddr.c
@@ -32,10 +32,12 @@ int sockaddr_init(sockaddr_t *addr, int af)
switch(af) {
case AF_INET:
addr->len = sizeof(struct sockaddr_in);
+ addr->prefix = IPV4_PREFIXLEN;
break;
#ifndef DISABLE_IPV6
case AF_INET6:
addr->len = sizeof(struct sockaddr_in6);
+ addr->prefix = IPV6_PREFIXLEN;
break;
#endif
default:
@@ -86,6 +88,7 @@ int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port)
dst->addr4.sin_port = htons(port);
paddr = &dst->addr4.sin_addr;
dst->addr4.sin_addr.s_addr = INADDR_ANY;
+ dst->prefix = IPV4_PREFIXLEN;
break;
#ifndef DISABLE_IPV6
case AF_INET6:
@@ -94,6 +97,7 @@ int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port)
paddr = &dst->addr6.sin6_addr;
memcpy(&dst->addr6.sin6_addr,
&in6addr_any, sizeof(in6addr_any));
+ dst->prefix = IPV6_PREFIXLEN;
break;
#endif
default:
@@ -104,6 +108,15 @@ int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port)
return inet_pton(family, addr, paddr);
}
+int sockaddr_setprefix(sockaddr_t *dst, int prefix)
+{
+ if (dst == NULL || prefix < 0) {
+ return -1;
+ }
+
+ return dst->prefix = prefix;
+}
+
int sockaddr_tostr(sockaddr_t *addr, char *dst, size_t size)
{
if (!addr || !dst || size == 0) {
diff --git a/src/common/sockaddr.h b/src/common/sockaddr.h
index 51ba779..b2725c0 100644
--- a/src/common/sockaddr.h
+++ b/src/common/sockaddr.h
@@ -38,6 +38,7 @@
/*! \brief Universal socket address. */
typedef struct sockaddr_t {
int family; /*!< Address family. */
+ short prefix; /*!< Address prefix. */
struct sockaddr* ptr; /*!< Pointer to used sockaddr. */
socklen_t len; /*!< Length of used sockaddr. */
union {
@@ -48,6 +49,10 @@ typedef struct sockaddr_t {
};
} sockaddr_t;
+/* Subnet maximum prefix length. */
+#define IPV4_PREFIXLEN 32
+#define IPV6_PREFIXLEN 128
+
/*! \brief Maximum address length in string format. */
#ifdef DISABLE_IPV6
#define SOCKADDR_STRLEN INET_ADDRSTRLEN
@@ -94,6 +99,17 @@ int sockaddr_update(sockaddr_t *addr);
int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port);
/*!
+ * \brief Set address prefix.
+ *
+ * \param dst Target address structure.
+ * \param prefix Prefix.
+ *
+ * \retval 0 if success.
+ * \retval -1 on error.
+ */
+int sockaddr_setprefix(sockaddr_t *dst, int prefix);
+
+/*!
* \brief Return string representation of socket address.
*
* \param addr Socket address structure.
diff --git a/src/config.h.in b/src/config.h.in
index 4761e6b..dfcea86 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -210,6 +210,33 @@
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
+/* Server debug. */
+#undef KNOTD_SERVER_DEBUG
+
+/* Zone compiler debug. */
+#undef KNOT_COMPILER_DEBUG
+
+/* Domain names debug. */
+#undef KNOT_DNAME_DEBUG
+
+/* Hashtable debug. */
+#undef KNOT_HASH_DEBUG
+
+/* Nameserver debug. */
+#undef KNOT_NS_DEBUG
+
+/* Packet debug. */
+#undef KNOT_PACKET_DEBUG
+
+/* RR debug. */
+#undef KNOT_RR_DEBUG
+
+/* XFR debug. */
+#undef KNOT_XFR_DEBUG
+
+/* Zones debug. */
+#undef KNOT_ZONES_DEBUG
+
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index 9d68d90..c7efa10 100644
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
+#include "common/sockaddr.h"
#include "libknot/dname.h"
#include "knot/conf/conf.h"
#include "libknotd_la-cf-parse.h" /* Automake generated header. */
@@ -27,9 +28,13 @@ static conf_log_t *this_log = 0;
static conf_log_map_t *this_logmap = 0;
//#define YYERROR_VERBOSE 1
-static void conf_start_iface(char* ifname)
+static void conf_start_iface(void *scanner, char* ifname)
{
this_iface = malloc(sizeof(conf_iface_t));
+ if (this_iface == NULL) {
+ cf_error(scanner, "not enough memory when allocating interface");
+ return;
+ }
memset(this_iface, 0, sizeof(conf_iface_t));
this_iface->name = ifname;
this_iface->port = CONFIG_DEFAULT_PORT;
@@ -37,9 +42,13 @@ static void conf_start_iface(char* ifname)
++new_config->ifaces_count;
}
-static void conf_start_remote(char *remote)
+static void conf_start_remote(void *scanner, char *remote)
{
this_remote = malloc(sizeof(conf_iface_t));
+ if (this_remote == NULL) {
+ cf_error(scanner, "not enough memory when allocating remote");
+ return;
+ }
memset(this_remote, 0, sizeof(conf_iface_t));
this_remote->name = remote;
add_tail(&new_config->remotes, &this_remote->n);
@@ -149,6 +158,69 @@ static int conf_key_add(void *scanner, knot_key_t **key, char *item)
return 1;
}
+static void conf_zone_start(void *scanner, char *name) {
+ this_zone = malloc(sizeof(conf_zone_t));
+ if (this_zone == NULL || name == NULL) {
+ cf_error(scanner, "out of memory while allocating zone config");
+ return;
+ }
+ memset(this_zone, 0, sizeof(conf_zone_t));
+ this_zone->enable_checks = -1; // Default policy applies
+ this_zone->notify_timeout = -1; // Default policy applies
+ this_zone->notify_retries = 0; // Default policy applies
+ this_zone->ixfr_fslimit = -1; // Default policy applies
+ this_zone->dbsync_timeout = -1; // Default policy applies
+
+ // Append mising dot to ensure FQDN
+ size_t nlen = strlen(name);
+ if (name[nlen - 1] != '.') {
+ this_zone->name = malloc(nlen + 2);
+ if (this_zone->name != NULL) {
+ memcpy(this_zone->name, name, nlen);
+ this_zone->name[nlen] = '.';
+ this_zone->name[nlen + 1] = '\0';
+ }
+ free(name);
+ } else {
+ this_zone->name = name; /* Already FQDN */
+ }
+
+ /* Check domain name. */
+ knot_dname_t *dn = NULL;
+ if (this_zone->name != NULL) {
+ dn = knot_dname_new_from_str(this_zone->name, nlen + 1, 0);
+ }
+ if (dn == NULL) {
+ free(this_zone->name);
+ free(this_zone);
+ this_zone = NULL;
+ cf_error(scanner, "invalid zone origin");
+ } else {
+ /* Directly discard dname, won't be needed. */
+ knot_dname_free(&dn);
+ add_tail(&new_config->zones, &this_zone->n);
+ ++new_config->zones_count;
+
+ /* Initialize ACL lists. */
+ init_list(&this_zone->acl.xfr_in);
+ init_list(&this_zone->acl.xfr_out);
+ init_list(&this_zone->acl.notify_in);
+ init_list(&this_zone->acl.notify_out);
+ }
+}
+
+static int conf_mask(void* scanner, int nval, int prefixlen) {
+ if (nval < 0 || nval > prefixlen) {
+ char buf[512];
+ snprintf(buf, sizeof(buf), "IPv%c subnet prefix '%d' is "
+ "out of range <0,%d>",
+ prefixlen == IPV4_PREFIXLEN ? '4' : '6', nval, prefixlen);
+ cf_error(scanner, buf);
+ return prefixlen; /* single host */
+ }
+ return nval;
+}
+
%}
%pure-parser
@@ -212,11 +284,11 @@ conf_entries:
;
interface_start:
- | TEXT { conf_start_iface($1.t); }
- | REMOTES { conf_start_iface(strdup($1.t)); } /* Allow strings reserved by token. */
- | LOG_SRC { conf_start_iface(strdup($1.t)); }
- | LOG { conf_start_iface(strdup($1.t)); }
- | LOG_LEVEL { conf_start_iface(strdup($1.t)); }
+ | TEXT { conf_start_iface(scanner, $1.t); }
+ | REMOTES { conf_start_iface(scanner, strdup($1.t)); } /* Allow strings reserved by token. */
+ | LOG_SRC { conf_start_iface(scanner, strdup($1.t)); }
+ | LOG { conf_start_iface(scanner, strdup($1.t)); }
+ | LOG_LEVEL { conf_start_iface(scanner, strdup($1.t)); }
;
interface:
@@ -382,10 +454,10 @@ keys:
}
remote_start:
- | TEXT { conf_start_remote($1.t); }
- | LOG_SRC { conf_start_remote(strdup($1.t)); }
- | LOG { conf_start_remote(strdup($1.t)); }
- | LOG_LEVEL { conf_start_remote(strdup($1.t)); }
+ | TEXT { conf_start_remote(scanner, $1.t); }
+ | LOG_SRC { conf_start_remote(scanner, strdup($1.t)); }
+ | LOG { conf_start_remote(scanner, strdup($1.t)); }
+ | LOG_LEVEL { conf_start_remote(scanner, strdup($1.t)); }
;
remote:
@@ -402,15 +474,26 @@ remote:
cf_error(scanner, "only one address is allowed in remote section\n");
} else {
this_remote->address = $3.t;
+ this_remote->prefix = IPV4_PREFIXLEN;
this_remote->family = AF_INET;
}
}
+ | remote ADDRESS IPA '/' NUM ';' {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = $3.t;
+ this_remote->family = AF_INET;
+ this_remote->prefix = conf_mask(scanner, $5.i, IPV4_PREFIXLEN);
+ }
+ }
| remote ADDRESS IPA '@' NUM ';' {
if (this_remote->address != 0) {
cf_error(scanner, "only one address is allowed in remote section\n");
} else {
this_remote->address = $3.t;
this_remote->family = AF_INET;
+ this_remote->prefix = IPV4_PREFIXLEN;
if (this_remote->port != 0) {
cf_error(scanner, "only one port definition is allowed in remote section\n");
} else {
@@ -424,14 +507,25 @@ remote:
} else {
this_remote->address = $3.t;
this_remote->family = AF_INET6;
+ this_remote->prefix = IPV6_PREFIXLEN;
}
}
+ | remote ADDRESS IPA6 '/' NUM ';' {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = $3.t;
+ this_remote->family = AF_INET6;
+ this_remote->prefix = conf_mask(scanner, $5.i, IPV6_PREFIXLEN);
+ }
+ }
| remote ADDRESS IPA6 '@' NUM ';' {
if (this_remote->address != 0) {
cf_error(scanner, "only one address is allowed in remote section\n");
} else {
this_remote->address = $3.t;
this_remote->family = AF_INET6;
+ this_remote->prefix = IPV6_PREFIXLEN;
if (this_remote->port != 0) {
cf_error(scanner, "only one port definition is allowed in remote section\n");
} else {
@@ -528,52 +622,13 @@ zone_acl:
}
;
-zone_start: TEXT {
- this_zone = malloc(sizeof(conf_zone_t));
- memset(this_zone, 0, sizeof(conf_zone_t));
- this_zone->enable_checks = -1; // Default policy applies
- this_zone->notify_timeout = -1; // Default policy applies
- this_zone->notify_retries = 0; // Default policy applies
- this_zone->ixfr_fslimit = -1; // Default policy applies
- this_zone->dbsync_timeout = -1; // Default policy applies
-
- // Append mising dot to ensure FQDN
- char *name = $1.t;
- size_t nlen = strlen(name);
- if (name[nlen - 1] != '.') {
- this_zone->name = malloc(nlen + 2);
- if (this_zone->name != NULL) {
- memcpy(this_zone->name, name, nlen);
- this_zone->name[nlen] = '.';
- this_zone->name[nlen + 1] = '\0';
- }
- free(name);
- } else {
- this_zone->name = name; /* Already FQDN */
- }
-
- /* Check domain name. */
- knot_dname_t *dn = NULL;
- if (this_zone->name != NULL) {
- dn = knot_dname_new_from_str(this_zone->name, nlen + 1, 0);
- }
- if (dn == NULL) {
- free(this_zone->name);
- free(this_zone);
- cf_error(scanner, "invalid zone origin");
- } else {
- /* Directly discard dname, won't be needed. */
- knot_dname_free(&dn);
- add_tail(&new_config->zones, &this_zone->n);
- ++new_config->zones_count;
-
- /* Initialize ACL lists. */
- init_list(&this_zone->acl.xfr_in);
- init_list(&this_zone->acl.xfr_out);
- init_list(&this_zone->acl.notify_in);
- init_list(&this_zone->acl.notify_out);
- }
- }
+zone_start:
+ | TEXT { conf_zone_start(scanner, $1.t); }
+ | USER { conf_zone_start(scanner, strdup($1.t)); }
+ | REMOTES { conf_zone_start(scanner, strdup($1.t)); }
+ | LOG_SRC { conf_zone_start(scanner, strdup($1.t)); }
+ | LOG { conf_zone_start(scanner, strdup($1.t)); }
+ | LOG_LEVEL { conf_zone_start(scanner, strdup($1.t)); }
;
zone:
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index a382bba..2c5747a 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -43,26 +43,6 @@ static const char *DEFAULT_CONFIG[] = {
* Utilities.
*/
-/*!
- * \brief Recursively create directories.
- *
- * Similar to "mkdir -p".
- * * \retval 0 on success.
- * \retval <0 on error.
- */
-static int rmkdir(char *path, int mode)
-{
- char *p = path;
- while((p = strchr(p + 1, '/'))) {
- *p = '\0';
- mkdir(path, mode);
- *p = '/';
- }
-
- // Final path
- return mkdir(path, mode);
-}
-
/* Prototypes for cf-parse.y */
extern int cf_parse(void *scanner);
extern int cf_get_lineno(void *scanner);
@@ -192,27 +172,36 @@ static void conf_update_hooks(conf_t *conf)
static int conf_process(conf_t *conf)
{
// Check
- if (!conf->storage) {
+ if (conf->storage == NULL) {
conf->storage = strdup("/var/lib/"PROJECT_EXEC);
+ if (conf->storage == NULL) {
+ return KNOTD_ENOMEM;
+ }
}
// Normalize paths
conf->storage = strcpath(conf->storage);
+
+ // Storage directory exists?
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);
- }
- }
+ if (stat(conf->storage, &st) == -1) {
+ log_server_error("Could not open storage directory '%s'\n", conf->storage);
+ // I assume that conf->* is freed elsewhere
+ return KNOTD_EINVAL;
+ }
+
+ // Storage directory is a directory?
+ if (S_ISDIR(st.st_mode) == 0) {
+ log_server_error("Configured storage '%s' not a directory\n", conf->storage);
+ return KNOTD_EINVAL;
}
// Create PID file
if (conf->pidfile == NULL) {
conf->pidfile = strcdup(conf->storage, "/" PID_FILE);
+ if (conf->pidfile == NULL) {
+ return KNOTD_ENOMEM;
+ }
}
// Postprocess zones
@@ -248,32 +237,40 @@ static int conf_process(conf_t *conf)
// Normalize zone filename
zone->file = strcpath(zone->file);
+ if (zone->file == NULL) {
+ zone->db = NULL;
+ ret = KNOTD_ENOMEM;
+ continue;
+ }
// Create zone db filename
size_t zname_len = strlen(zone->name);
size_t stor_len = strlen(conf->storage);
- size_t size = stor_len + zname_len + 4; // db/,\0
+ size_t size = stor_len + zname_len + 4; // /db,\0
char *dest = malloc(size);
if (dest == NULL) {
zone->db = NULL; /* Not enough memory. */
ret = KNOTD_ENOMEM; /* Error report. */
continue;
}
+ char *dpos = dest;
/* Since we have already allocd dest to accomodate
* storage/zname length strcpy is safe. */
- strncpy(dest, conf->storage, stor_len + 1);
- if (conf->storage[stor_len - 1] != '/') {
- strncat(dest, "/", 1);
+ memcpy(dpos, conf->storage, stor_len + 1);
+ dpos += stor_len;
+ if (*(dpos - 1) != '/') {
+ *(dpos++) = '/';
+ *dpos = '\0';
}
- strncat(dest, zone->name, zname_len);
- strncat(dest, "db", 2);
+ memcpy(dpos, zone->name, zname_len + 1);
+ memcpy(dpos + zname_len, "db", 3);
zone->db = dest;
// Create IXFR db filename
stor_len = strlen(conf->storage);
- size = stor_len + zname_len + 9; // diff.db/,\0
+ size = stor_len + zname_len + 9; // /diff.db,\0
dest = malloc(size);
if (dest == NULL) {
zone->ixfr_db = NULL; /* Not enough memory. */
@@ -483,10 +480,11 @@ int conf_parse(conf_t *conf)
int ret = conf_fparser(conf);
/* Postprocess config. */
- conf_process(conf);
-
- /* Update hooks. */
- conf_update_hooks(conf);
+ if (ret == 0) {
+ ret = conf_process(conf);
+ /* Update hooks. */
+ conf_update_hooks(conf);
+ }
if (ret < 0) {
return KNOTD_EPARSEFAIL;
@@ -649,6 +647,11 @@ int conf_open(const char* path)
/* Parse config. */
int ret = conf_fparser(nconf);
+ if (ret == KNOTD_EOK) {
+ /* Postprocess config. */
+ ret = conf_process(nconf);
+ }
+
if (ret != KNOTD_EOK) {
conf_free(nconf);
return ret;
@@ -667,9 +670,6 @@ int conf_open(const char* path)
}
}
- /* Postprocess config. */
- conf_process(nconf);
-
/* Synchronize. */
synchronize_rcu();
@@ -719,6 +719,10 @@ char* strcpath(char *path)
// Expand '~'
char* remainder = strchr(path,'~');
if (remainder != NULL) {
+ if (remainder[1] != '/') {
+ log_server_warning("Cannot expand non-login user home directory '%s', use full path instead", path);
+ }
+
// Get full path
char *tild_exp_unsafe = getenv("HOME");
if (tild_exp_unsafe == NULL) {
@@ -726,11 +730,12 @@ char* strcpath(char *path)
}
// Sanitize
size_t tild_len = strlen(tild_exp_unsafe);
- char *tild_exp = malloc(tild_len);
+ char *tild_exp = malloc(tild_len + 1);
if (tild_exp == NULL) {
return NULL;
}
- strncpy(tild_exp, tild_exp_unsafe, tild_len + 1);
+ // Duplicate tild_exp including terminating NULL
+ memcpy(tild_exp, tild_exp_unsafe, tild_len + 1);
if (tild_exp[tild_len - 1] == '/') {
tild_exp[--tild_len] = '\0';
}
@@ -747,11 +752,11 @@ char* strcpath(char *path)
// Append remainder
++remainder;
- size_t remainder_len = strlen(remainder);
- strncat(npath, remainder, remainder_len);
+ strncat(npath, remainder, strlen(remainder));
+
+ free(tild_exp);
free(path);
path = npath;
- free(tild_exp);
}
return path;
diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h
index b5c1afa..1e6644e 100644
--- a/src/knot/conf/conf.h
+++ b/src/knot/conf/conf.h
@@ -56,6 +56,7 @@ typedef struct conf_iface_t {
node n;
char *name; /*!< Internal name for the interface. */
char *address; /*!< IP (IPv4/v6) address for this interface */
+ unsigned prefix; /*!< IP subnet prefix. */
int port; /*!< Port number for this interface */
int family; /*!< Address family. */
knot_key_t *key; /*!< TSIG key (only valid for remotes). */
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index f111f25..59556c1 100644
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -271,6 +271,15 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
int valid_cmd = 0;
int rc = 0;
if (strcmp(action, "start") == 0) {
+ // Check pidfile for w+
+ FILE* chkf = fopen(pidfile, "w+");
+ if (chkf == NULL) {
+ fprintf(stderr, "control: PID file '%s' is not writeable, refusing to start\n", pidfile);
+ return 1;
+ } else {
+ fclose(chkf);
+ chkf = NULL;
+ }
// Check PID
valid_cmd = 1;
@@ -573,7 +582,7 @@ int main(int argc, char **argv)
{"verbose", no_argument, 0, 'v'},
{"interactive", no_argument, 0, 'i'},
{"auto", no_argument, 0, 'a'},
- {"jobs", required_argument, 0, 'c'},
+ {"jobs", required_argument, 0, 'j'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
diff --git a/src/knot/ctl/process.c b/src/knot/ctl/process.c
index e46fa37..bb61804 100644
--- a/src/knot/ctl/process.c
+++ b/src/knot/ctl/process.c
@@ -33,7 +33,7 @@ char* pid_filename()
/* Read configuration. */
char* ret = 0;
- if (conf()) {
+ if (conf() && conf()->pidfile != NULL) {
ret = strdup(conf()->pidfile);
}
diff --git a/src/knot/main.c b/src/knot/main.c
index d4c6bca..f63916a 100644
--- a/src/knot/main.c
+++ b/src/knot/main.c
@@ -55,7 +55,6 @@ void interrupt_handle(int s)
sig_req_stop = 1;
sig_stopping = 1;
} else {
- log_server_notice("OK! Exiting immediately.\n");
exit(1);
}
}
@@ -234,6 +233,7 @@ int main(int argc, char **argv)
log_server_error("Failed to parse configuration '%s'.\n",
config_fn);
}
+ server_wait(server);
server_destroy(&server);
free(config_fn);
return 1;
diff --git a/src/knot/other/debug.h b/src/knot/other/debug.h
index 93b52fe..7768d22 100644
--- a/src/knot/other/debug.h
+++ b/src/knot/other/debug.h
@@ -29,20 +29,29 @@
#include "config.h" /* autoconf generated */
+#ifdef KNOTD_SERVER_DEBUG
+ #define KNOTD_THREADS_DEBUG
+ #define KNOTD_JOURNAL_DEBUG
+ #define KNOTD_NET_DEBUG
+#endif
+
+#ifdef KNOT_ZONES_DEBUG
+ #define KNOTD_ZONES_DEBUG
+#endif
+
+#ifdef KNOT_XFR_DEBUG
+ #define KNOTD_XFR_DEBUG
+ #define KNOTD_NOTIFY_DEBUG
+#endif
+
+#ifdef KNOT_COMPILER_DEBUG
+ #define KNOTD_ZDUMP_DEBUG
+ #define KNOTD_ZLOAD_DEBUG
+#endif
+
#include "knot/other/log.h"
#include "common/print.h"
-/*! \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_XFR_DEBUG
-//#define KNOTD_NOTIFY_DEBUG
-//#define KNOTD_ZDUMP_DEBUG
-//#define KNOTD_ZLOAD_DEBUG
-
/******************************************************************************/
#ifdef KNOTD_NOTIFY_DEBUG
@@ -363,9 +372,11 @@
#ifdef DEBUG_ENABLE_DETAILS
#define dbg_zdump_detail(msg...) log_msg(LOG_SERVER, LOG_DEBUG, msg)
#define dbg_zdump_hex_detail(data, len) hex_log(LOG_SERVER, (data), (len))
+#define dbg_zdump_exec_detail(cmds) do { cmds } while (0)
#else
#define dbg_zdump_detail(msg...)
#define dbg_zdump_hex_detail(data, len)
+#define dbg_zdump_exec_detail(cmds)
#endif
/* No messages. */
@@ -376,6 +387,7 @@
#define dbg_zdump_hex_verb(data, len)
#define dbg_zdump_detail(msg...)
#define dbg_zdump_hex_detail(data, len)
+#define dbg_zdump_exec_detail(cmds)
#endif
/******************************************************************************/
@@ -404,9 +416,11 @@
#ifdef DEBUG_ENABLE_DETAILS
#define dbg_zload_detail(msg...) log_msg(LOG_SERVER, LOG_DEBUG, msg)
#define dbg_zload_hex_detail(data, len) hex_log(LOG_SERVER, (data), (len))
+#define dbg_zload_exec_detail(cmds) do { cmds } while (0)
#else
#define dbg_zload_detail(msg...)
#define dbg_zload_hex_detail(data, len)
+#define dbg_zload_exec_detail(cmds)
#endif
/* No messages. */
@@ -417,6 +431,7 @@
#define dbg_zload_hex_verb(data, len)
#define dbg_zload_detail(msg...)
#define dbg_zload_hex_detail(data, len)
+#define dbg_zload_exec_detail(cmds)
#endif
/******************************************************************************/
diff --git a/src/knot/other/error.c b/src/knot/other/error.c
index a149966..0ab7568 100644
--- a/src/knot/other/error.c
+++ b/src/knot/other/error.c
@@ -27,7 +27,7 @@ const error_table_t knotd_error_msgs[] = {
{KNOTD_EBUSY, "Requested resource is busy."},
{KNOTD_EAGAIN, "The system lacked the necessary resource, try again."},
{KNOTD_EACCES, "Permission to perform requested operation is denied."},
- {KNOTD_ECONNREFUSED, "Connection is refused."},
+ {KNOTD_ECONNREFUSED, "Connection refused."},
{KNOTD_EISCONN, "Already connected."},
{KNOTD_EADDRINUSE, "Address already in use."},
{KNOTD_ENOENT, "Resource not found."},
diff --git a/src/knot/server/journal.c b/src/knot/server/journal.c
index cd3e342..02e0547 100644
--- a/src/knot/server/journal.c
+++ b/src/knot/server/journal.c
@@ -133,6 +133,10 @@ static int journal_recover(journal_t *j)
int journal_create(const char *fn, uint16_t max_nodes)
{
+ if (fn == NULL) {
+ return KNOTD_EINVAL;
+ }
+
/* File lock. */
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
@@ -143,7 +147,7 @@ int journal_create(const char *fn, uint16_t max_nodes)
fl.l_pid = getpid();
/* Create journal file. */
- int fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU|S_IRWXG);
+ int fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
if (fd < 0) {
dbg_journal("journal: failed to create file '%s'\n", fn);
return KNOTD_EINVAL;
@@ -219,10 +223,28 @@ int journal_create(const char *fn, uint16_t max_nodes)
return KNOTD_EOK;
}
-journal_t* journal_open(const char *fn, size_t fslimit, uint16_t bflags)
+journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflags)
{
/*! \todo Memory mapping may be faster than stdio? (issue #964) */
+ if (fn == NULL) {
+ return NULL;
+ }
+ /* Check for lazy mode. */
+ if (mode & JOURNAL_LAZY) {
+ dbg_journal("journal: opening journal %s lazily\n", fn);
+ journal_t *j = malloc(sizeof(journal_t));
+ if (j != NULL) {
+ memset(j, 0, sizeof(journal_t));
+ j->fd = -1;
+ j->path = strdup(fn);
+ j->fslimit = fslimit;
+ j->bflags = bflags;
+ j->refs = 1;
+ }
+ return j;
+ }
+
/* File lock. */
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
@@ -277,6 +299,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, uint16_t bflags)
/* Allocate journal structure. */
const size_t node_len = sizeof(journal_node_t);
journal_t *j = malloc(sizeof(journal_t) + max_nodes * node_len);
+ memset(j, 0, sizeof(journal_t) + max_nodes * node_len);
if (!j) {
dbg_journal_detail("journal: cannot allocate journal\n");
fcntl(fd, F_SETLK, &fl);
@@ -287,6 +310,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, uint16_t bflags)
j->fd = fd;
j->max_nodes = max_nodes;
j->bflags = bflags;
+ j->refs = 1;
/* Load node queue state. */
if (!sfread(&j->qhead, sizeof(uint16_t), fd)) {
@@ -646,18 +670,54 @@ int journal_close(journal_t *journal)
return KNOTD_EINVAL;
}
- /* Unlock journal file. */
- journal->fl.l_type = F_UNLCK;
- fcntl(journal->fd, F_SETLK, &journal->fl);
- dbg_journal("journal: unlocked journal %p\n", journal);
-
- /* Close file. */
- close(journal->fd);
+ /* Check if lazy. */
+ if (journal->fd < 0) {
+ free(journal->path);
+ } else {
+ /* Unlock journal file. */
+ journal->fl.l_type = F_UNLCK;
+ fcntl(journal->fd, F_SETLK, &journal->fl);
+ dbg_journal("journal: unlocked journal %p\n", journal);
+ /* Close file. */
+ close(journal->fd);
+ }
+
dbg_journal("journal: closed journal %p\n", journal);
/* Free allocated resources. */
+
free(journal);
return KNOTD_EOK;
}
+
+journal_t *journal_retain(journal_t *journal)
+{
+ /* Return active journal if opened lazily. */
+ if (journal != NULL) {
+ if (journal->fd < 0) {
+ dbg_journal("journal: retain(), opening for rw\n");
+ journal = journal_open(journal->path, journal->fslimit,
+ 0, journal->bflags);
+ } else {
+ ++journal->refs;
+ dbg_journal("journal: retain(), ++refcount\n");
+ }
+ }
+
+ return journal;
+}
+
+
+void journal_release(journal_t *journal) {
+ if (journal != NULL) {
+ if (journal->refs == 1) {
+ dbg_journal("journal: release(), closing last\n");
+ journal_close(journal);
+ } else {
+ --journal->refs;
+ dbg_journal_verb("journal: release(), --refcount\n");
+ }
+ }
+}
diff --git a/src/knot/server/journal.h b/src/knot/server/journal.h
index 564f0fe..b04945d 100644
--- a/src/knot/server/journal.h
+++ b/src/knot/server/journal.h
@@ -55,6 +55,14 @@ typedef enum journal_flag_t {
} journal_flag_t;
/*!
+ * \brief Journal mode.
+ */
+typedef enum journal_mode_t {
+ JOURNAL_PERSISTENT = 0 << 0, /*!< Persistent mode (open keeps fd). */
+ JOURNAL_LAZY = 1 << 0 /*!< Lazy mode (open doesn't keep fd). */
+} journal_mode_t;
+
+/*!
* \brief Journal node structure.
*
* Each node represents journal entry and points
@@ -83,6 +91,8 @@ typedef struct journal_t
{
int fd;
struct flock fl; /*!< File lock. */
+ char *path; /*!< Path to journal file. */
+ int refs; /*!< Number of references. */
uint16_t max_nodes; /*!< Number of nodes. */
uint16_t qhead; /*!< Node queue head. */
uint16_t qtail; /*!< Node queue tail. */
@@ -133,12 +143,13 @@ int journal_create(const char *fn, uint16_t max_nodes);
*
* \param fn Journal file name.
* \param fslimit File size limit (0 for no limit).
+ * \param mode Open mode (0 for normal).
* \param bflags Initial flags for each written node.
*
* \retval new journal instance if successful.
* \retval NULL on error.
*/
-journal_t* journal_open(const char *fn, size_t fslimit, uint16_t bflags);
+journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflags);
/*!
* \brief Fetch entry node for given identifier.
@@ -240,4 +251,22 @@ int journal_update(journal_t *journal, journal_node_t *n);
*/
int journal_close(journal_t *journal);
+/*!
+ * \brief Retain journal for use.
+ *
+ * Allows to track usage of lazily-opened journals.
+ *
+ * \param journal Journal.
+ *
+ * \return Retained journal.
+ */
+journal_t *journal_retain(journal_t *journal);
+
+/*!
+ * \brief Release retained journal.
+ *
+ * \param journal Retained journal.
+ */
+void journal_release(journal_t *journal);
+
#endif /* _KNOTD_JOURNAL_H_ */
diff --git a/src/knot/server/notify.c b/src/knot/server/notify.c
index 8736372..566d66f 100644
--- a/src/knot/server/notify.c
+++ b/src/knot/server/notify.c
@@ -317,8 +317,6 @@ int notify_process_response(knot_nameserver_t *nameserver,
/* Found waiting NOTIFY query? */
if (!match) {
- log_server_notice("No pending NOTIFY query found for ID=%u\n",
- pkt_id);
pthread_mutex_unlock(&zd->lock);
return KNOTD_ERROR;
}
@@ -329,9 +327,6 @@ int notify_process_response(knot_nameserver_t *nameserver,
/* Zone was removed/reloaded. */
pthread_mutex_unlock(&zd->lock);
- log_server_info("Received response for pending NOTIFY query ID=%u\n",
- pkt_id);
-
return KNOTD_EOK;
}
diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index 0af85a9..8f4b990 100644
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -31,7 +31,6 @@
#include "common/sockaddr.h"
#include "common/skip-list.h"
#include "common/fdset.h"
-#include "common/prng.h"
#include "knot/common.h"
#include "knot/server/tcp-handler.h"
#include "knot/server/xfr-handler.h"
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index 60b0843..5276c24 100644
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -202,7 +202,13 @@ static inline int udp_master_recvfrom(dthread_t *thread, stat_t *thread_stat)
return KNOTD_ENOTSUP;
}
- int sock = dup(h->fd);
+ int sock = h->fd;
+ int sock_dup = dup(h->fd);
+ if (sock_dup < 0) {
+ log_server_warning("Couldn't duplicate UDP socket for listening.\n");
+ } else {
+ sock = sock_dup;
+ }
uint8_t qbuf[SOCKET_MTU_SZ];
/* Loop until all data is read. */
@@ -254,7 +260,9 @@ static inline int udp_master_recvfrom(dthread_t *thread, stat_t *thread_stat)
}
/* Free allocd resources. */
- close(sock);
+ if (sock_dup >= 0) {
+ close(sock_dup);
+ }
return KNOTD_EOK;
}
diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index fe7c0ab..588670c 100644
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -51,6 +51,14 @@ void xfr_interrupt(xfrhandler_t *h)
}
}
+static void xfr_request_deinit(knot_ns_xfr_t *r)
+{
+ if (r) {
+ free(r->msgpref);
+ r->msgpref = NULL;
+ }
+}
+
/*!
* \brief SOA query timeout handler.
*/
@@ -69,19 +77,11 @@ static int xfr_udp_timeout(event_t *e)
}
}
- sockaddr_update(&data->addr);
- char r_addr[SOCKADDR_STRLEN];
- sockaddr_tostr(&data->addr, r_addr, sizeof(r_addr));
- int r_port = sockaddr_portnum(&data->addr);
-
/* Close socket. */
knot_zone_t *z = data->zone;
if (z && knot_zone_get_contents(z) && knot_zone_data(z)) {
- zonedata_t *zd = (zonedata_t *)knot_zone_data(z);
- log_zone_info("%s '%s' query to %s:%d - timeout exceeded.\n",
- data->type == XFR_TYPE_SOA ? "SOA" : "NOTIFY",
- zd->conf->name,
- r_addr, r_port);
+ log_zone_info("%s Failed, timeout exceeded.\n",
+ data->msgpref);
}
knot_ns_xfr_t cr = {};
@@ -179,6 +179,9 @@ static void xfr_free_task(knot_ns_xfr_t *task)
pthread_mutex_lock(&h->tasks_mx);
skip_remove(h->tasks, (void*)((size_t)task->session), 0, 0);
pthread_mutex_unlock(&h->tasks_mx);
+
+ /* Deinitialize */
+ xfr_request_deinit(task);
close(task->session);
free(task);
@@ -189,7 +192,7 @@ 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));
if (!t) {
- return 0;
+ return NULL;
}
memcpy(t, req, sizeof(knot_ns_xfr_t));
@@ -199,16 +202,27 @@ static knot_ns_xfr_t *xfr_register_task(xfrworker_t *w, knot_ns_xfr_t *req)
t->wire = 0; /* Invalidate shared buffer. */
t->wire_size = 0;
t->data = 0; /* New zone will be built. */
+ t->msgpref = strdup(t->msgpref); /* Copy message. */
/* Register data. */
xfrhandler_t * h = w->master;
pthread_mutex_lock(&h->tasks_mx);
- skip_insert(h->tasks, (void*)((ssize_t)t->session), t, 0);
+ int ret = skip_insert(h->tasks, (void*)((ssize_t)t->session), t, 0);
pthread_mutex_unlock(&h->tasks_mx);
/* Add to set. */
- fdset_add(w->fdset, t->session, OS_EV_READ);
- t->owner = w;
+ if (ret == 0) {
+ ret = fdset_add(w->fdset, t->session, OS_EV_READ);
+ }
+ /* Evaluate final return code. */
+ if (ret == 0) {
+ t->owner = w;
+ } else {
+ /* Attempt to remove from list anyway. */
+ skip_remove(h->tasks, (void*)((ssize_t)t->session), NULL, NULL);
+ free(t);
+ t = NULL;
+ }
return t;
}
@@ -222,11 +236,11 @@ static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
switch(data->type) {
case XFR_TYPE_AIN:
- if (data->data) {
- if (data->flags & XFR_FLAG_AXFR_FINISHED) {
- knot_zone_contents_deep_free(
- (knot_zone_contents_t **)&data->data, 0);
- } else {
+ if (data->flags & XFR_FLAG_AXFR_FINISHED) {
+ knot_zone_contents_deep_free(
+ &data->new_contents, 1);
+ } else {
+ if (data->data) {
xfrin_constructed_zone_t *constr_zone =
(xfrin_constructed_zone_t *)data->data;
knot_zone_contents_deep_free(
@@ -242,6 +256,10 @@ static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
chs = (knot_changesets_t *)data->data;
knot_free_changesets(&chs);
}
+
+ // this function is called before new contents are created
+ assert(data->new_contents == NULL);
+
break;
}
@@ -259,10 +277,6 @@ static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
*/
static int xfr_xfrin_finalize(xfrworker_t *w, knot_ns_xfr_t *data)
{
- knot_zone_t *zone = (knot_zone_t *)data->zone;
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- const char *zorigin = zd->conf->name;
-
/* CLEANUP */
// // get the zone name from Question
// dbg_xfr_verb("Query: %p, response: %p\n", data->query, data->response);
@@ -281,54 +295,105 @@ static int xfr_xfrin_finalize(xfrworker_t *w, knot_ns_xfr_t *data)
ret = zones_save_zone(data);
if (ret != KNOTD_EOK) {
xfr_xfrin_cleanup(w, data);
- log_zone_error("AXFR failed to save "
- "transferred zone '%s/IN' - %s\n",
- zorigin, knotd_strerror(ret));
+ log_zone_error("%s Failed to save transferred zone - %s\n",
+ data->msgpref, knotd_strerror(ret));
} else {
dbg_xfr("xfr: AXFR/IN new zone saved.\n");
ret = knot_ns_switch_zone(w->ns, data);
- if (ret != KNOTD_EOK) {
- log_zone_error("AXFR failed to "
- "switch in-memory zone "
- "'%s/IN' - %s\n",
- zorigin,
- knotd_strerror(ret));
+ if (ret != KNOT_EOK) {
+ log_zone_error("%s Failed to switch in-memory "
+ "zone - %s\n", data->msgpref,
+ knot_strerror(ret));
+ xfr_xfrin_cleanup(w, data);
}
}
- log_zone_info("AXFR transfer of zone '%s/IN' "
- "%s.\n", zorigin,
- ret == KNOTD_EOK ? "finished" : "failed");
+ if (ret == KNOTD_EOK) {
+ log_zone_info("%s Finished.\n", data->msgpref);
+ }
break;
case XFR_TYPE_IIN:
+ chs = (knot_changesets_t *)data->data;
+
+ /* First, serialize changesets. */
+ ret = zones_changesets_to_binary(chs);
+ if (ret != KNOTD_EOK) {
+ log_zone_error("%s Failed to serialize changesets - %s"
+ "\n", data->msgpref,
+ knotd_strerror(ret));
+ /* Free changesets, but not the data. */
+ knot_free_changesets(&chs);
+ data->data = 0;
+ break;
+ }
+
+ /* Now, try to apply the changesets to the zone. */
+ ret = xfrin_apply_changesets(data->zone, chs,
+ &data->new_contents);
+
+ if (ret != KNOT_EOK) {
+ log_zone_error("%s Failed to apply changesets - %s\n",
+ data->msgpref,
+ knot_strerror(ret));
+
+ /* Free changesets, but not the data. */
+ knot_free_changesets(&chs);
+ data->data = 0;
+
+ ret = KNOTD_ERROR;
+ break;
+ }
/* Save changesets. */
dbg_xfr("xfr: IXFR/IN saving changesets\n");
+
+ /*! \note Here, the changesets may already be modified.
+ * Only the 'data' field of each changeset contains the
+ * proper serialized changesets. Serials should be
+ * OK too.
+ */
ret = zones_store_changesets(data);
if (ret != KNOTD_EOK) {
- log_zone_error("IXFR failed to save "
- "transferred changesets "
- "for zone '%s/IN' - %s\n",
- zorigin, knotd_strerror(ret));
- } else {
- /* Update zone. */
- ret = zones_apply_changesets(data);
- if (ret != KNOT_EOK) {
- log_zone_error("IXFR failed to "
- "apply changesets to "
- "zone '%s/IN' - %s\n",
- zorigin,
- knot_strerror(ret));
- }
+ log_zone_error("%s Failed to save "
+ "transferred changesets - %s\n",
+ data->msgpref, knotd_strerror(ret));
+
+ // Cleanup old and new contents
+ xfrin_rollback_update(data->zone->contents,
+ &data->new_contents,
+ &chs->changes);
+ /* Free changesets, but not the data. */
+ knot_free_changesets(&chs);
+ data->data = 0;
+ break;
}
+ /* Switch zone contents. */
+ ret = xfrin_switch_zone(data->zone, data->new_contents,
+ data->type);
+
+ if (ret != KNOT_EOK) {
+ log_zone_error("%s Failed to replace "
+ "current zone - %s\n",
+ data->msgpref,
+ knot_strerror(ret));
+ // Cleanup old and new contents
+ xfrin_rollback_update(data->zone->contents,
+ &data->new_contents,
+ &chs->changes);
+
+ /* Free changesets, but not the data. */
+ knot_free_changesets(&chs);
+ data->data = 0;
+
+ ret = KNOTD_ERROR;
+ break;
+ }
+
+ xfrin_cleanup_successful_update( &chs->changes);
+
/* Free changesets, but not the data. */
- chs = (knot_changesets_t *)data->data;
knot_free_changesets(&chs);
- /* CLEANUP */
-// free(chs->sets);
-// free(chs);
data->data = 0;
- log_zone_info("IXFR transfer of zone '%s/IN' "
- "%s.\n", zorigin,
- ret == KNOTD_EOK ? "finished" : "failed");
+ assert(ret == KNOTD_EOK);
+ log_zone_info("%s Finished.\n", data->msgpref);
break;
default:
ret = KNOTD_EINVAL;
@@ -364,7 +429,7 @@ static int xfr_prepare_tsig(knot_ns_xfr_t *xfr, knot_key_t *key)
/*!
* \brief Check TSIG if exists.
*/
-static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode)
+static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode, char **tag)
{
/* Parse rest of the packet. */
int ret = KNOT_EOK;
@@ -382,6 +447,10 @@ static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode)
if (knot_rrset_type(tsig_rr) == KNOT_RRTYPE_TSIG) {
dbg_xfr("xfr: found TSIG in AR\n");
kname = knot_rrset_owner(tsig_rr);
+ if (tag) {
+ *tag = knot_dname_to_str(kname);
+
+ }
} else {
tsig_rr = 0;
}
@@ -390,8 +459,6 @@ static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode)
dbg_xfr("xfr: TSIG not found in AR\n");
char *name = knot_dname_to_str(
knot_zone_name(xfr->zone));
- log_answer_warning("Unauthorized request for XFR '%s/"
- "OUT'. (TSIG)\n", name);
free(name);
// return REFUSED
@@ -402,9 +469,10 @@ static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode)
if (tsig_rr) {
tsig_algorithm_t alg = tsig_rdata_alg(tsig_rr);
if (tsig_alg_digest_length(alg) == 0) {
- log_server_info("Unsupported digest algorithm "
+ log_server_info("%s Unsupported digest algorithm "
"requested, treating as "
- "bad key.\n");
+ "bad key.\n",
+ xfr->msgpref);
*rcode = KNOT_RCODE_NOTAUTH;
xfr->tsig_key = NULL;
xfr->tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
@@ -518,23 +586,10 @@ 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. */
+ knot_zone_t *zone = (knot_zone_t *)data->zone;
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) {
@@ -566,11 +621,10 @@ 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 of '%s/IN' with %s:%d - "
- "Fallback to AXFR/IN.\n",
- zname, r_addr, r_port);
assert(data->type == XFR_TYPE_IIN);
+ log_server_notice("%s Fallback to AXFR/IN.\n", data->msgpref);
data->type = XFR_TYPE_AIN;
+ data->msgpref[0] = 'A';
ret = knot_ns_process_axfrin(w->ns, data);
}
@@ -585,9 +639,8 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* IXFR refused, try again with AXFR. */
if (zone && data->type == XFR_TYPE_IIN && ret == KNOT_EXFRREFUSED) {
- log_server_notice("IXFR of '%s/IN' with %s:%d failed, attempting "
- "to use AXFR/IN instead.\n",
- zname, r_addr, r_port);
+ log_server_notice("%s Transfer failed, fallback to AXFR/IN.\n",
+ data->msgpref);
size_t bufsize = buflen;
data->wire_size = buflen; /* Reset maximum bufsize */
ret = xfrin_create_axfr_query(zone->name, data,
@@ -599,6 +652,7 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* Switch to AIN type XFR and return now. */
if (ret == bufsize) {
data->type = XFR_TYPE_AIN;
+ data->msgpref[0] = 'A';
return KNOTD_EOK;
}
}
@@ -606,17 +660,11 @@ 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 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));
+ log_server_warning("%s Finished, %s\n",
+ data->msgpref, knot_strerror(ret));
} else if (ret < 0) {
- 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));
+ log_server_error("%s %s\n",
+ data->msgpref, knot_strerror(ret));
}
@@ -638,9 +686,9 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
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",
- zname, tmr_s/1000);
+ log_zone_info("%s Next attempt to bootstrap "
+ "in %d seconds.\n",
+ data->msgpref, tmr_s / 1000);
}
rcu_read_unlock();
@@ -698,18 +746,14 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
if (nextw == 0) {
nextw = w;
}
+
+ /* Free data updated in this processing. */
evqueue_write(nextw->q, data, sizeof(knot_ns_xfr_t));
return KNOTD_EOK;
} else {
zd->xfr_in.wrkr = w;
}
- /* Update address. */
- sockaddr_update(&data->addr);
- char r_addr[SOCKADDR_STRLEN];
- sockaddr_tostr(&data->addr, r_addr, sizeof(r_addr));
- int r_port = sockaddr_portnum(&data->addr);
-
/* Connect to remote. */
if (data->session <= 0) {
int fd = socket_create(data->addr.family, SOCK_STREAM);
@@ -722,21 +766,18 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
}
} else {
pthread_mutex_unlock(&zd->xfr_in.lock);
- log_server_warning("Failed to create socket "
- "(type=%s, family=%s).\n",
- "SOCK_STREAM",
- data->addr.family == AF_INET ?
- "AF_INET" : "AF_INET6");
+ log_server_warning("%s Failed to create socket "
+ "(type=%s, family=%s).\n",
+ "SOCK_STREAM",
+ data->msgpref,
+ data->addr.family == AF_INET ?
+ "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);
- log_server_warning("Failed to connect to %cXFR master "
- "at %s:%d.\n",
- data->type == XFR_TYPE_AIN ? 'A' : 'I',
- r_addr, r_port);
if (!knot_zone_contents(zone)) {
/* Reschedule request (120 - 240s random delay). */
int tmr_s = AXFR_BOOTSTRAP_RETRY * 2; /* Malus x2 */
@@ -746,9 +787,9 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
evsched_cancel(ev->parent, ev);
evsched_schedule(ev->parent, ev, tmr_s);
}
- log_zone_notice("Zone AXFR bootstrap failed, "
- "another attempt in %d seconds."
- "\n", tmr_s / 1000);
+ log_zone_notice("%s Bootstrap failed, next "
+ "attempt in %d seconds.\n",
+ data->msgpref, tmr_s / 1000);
}
return KNOTD_ECONNREFUSED;
}
@@ -766,8 +807,8 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
if (!contents && data->type == XFR_TYPE_IIN) {
pthread_mutex_unlock(&zd->xfr_in.lock);
rcu_read_unlock();
- log_server_warning("Failed start IXFR on zone with no "
- "contents\n");
+ log_server_warning("%s Refusing to start IXFR/IN on zone with no "
+ "contents.\n", data->msgpref);
return KNOTD_EINVAL;
}
@@ -806,7 +847,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
/* Handle errors. */
if (ret != KNOT_EOK) {
pthread_mutex_unlock(&zd->xfr_in.lock);
- dbg_xfr("xfr: failed to create XFR query type %d: %s\n",
+ fprintf(stderr, "xfr: failed to create XFR query type %d: %s\n",
data->type, knot_strerror(ret));
return KNOTD_ERROR;
}
@@ -814,24 +855,19 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
/* Unlock zone contents. */
rcu_read_unlock();
- /* Add to pending transfers. */
- knot_ns_xfr_t *task = xfr_register_task(w, data);
-
+ /* Start transfer. */
ret = data->send(data->session, &data->addr, data->wire, bufsize);
if (ret != bufsize) {
+ log_server_info("%s Failed to send query.\n", data->msgpref);
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);
- return KNOTD_ERROR;
+ return KNOTD_ECONNREFUSED;
}
+ /* Add to pending transfers. */
+ knot_ns_xfr_t *task = xfr_register_task(w, data);
+
/* Send XFR query. */
- log_server_info("%cXFR transfer of zone '%s/IN' with %s:%d started.\n",
- data->type == XFR_TYPE_AIN ? 'A' : 'I',
- zd->conf->name,
- r_addr, r_port);
-
+ log_server_info("%s Started.\n", task->msgpref);
return KNOTD_EOK;
}
@@ -883,12 +919,12 @@ static int xfr_answer_ixfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
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: "
+ log_server_info("%s Failed to load data from journal: "
" Incomplete history. "
"Fallback to AXFR.\n",
- xfr->zname);
+ xfr->msgpref);
xfr->type = XFR_TYPE_AOUT;
+ xfr->msgpref[0] = 'A';
return xfr_answer_axfr(ns, xfr);
} else if (chsload == KNOTD_EMALF) {
xfr->rcode = KNOT_RCODE_FORMERR;
@@ -909,6 +945,101 @@ static int xfr_answer_ixfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
return ret;
}
+static int xfr_update_msgpref(knot_ns_xfr_t *req, const char *keytag)
+{
+ /* Check */
+ if (req == NULL) {
+ return KNOTD_EINVAL;
+ }
+
+ /* Update address. */
+ if (req->msgpref) {
+ free(req->msgpref);
+ req->msgpref = NULL;
+ }
+
+ char r_addr[SOCKADDR_STRLEN];
+ char *r_key = NULL;
+ int r_port = sockaddr_portnum(&req->addr);
+ sockaddr_tostr(&req->addr, r_addr, sizeof(r_addr));
+ char *tag = NULL;
+ if (keytag) {
+ tag = strdup(keytag);
+ } else if (req->tsig_key) {
+ tag = knot_dname_to_str(req->tsig_key->name);
+ }
+ if (tag) {
+ /* Allocate: " key '$key' " (7 extra bytes + \0) */
+ size_t dnlen = strlen(tag);
+ r_key = malloc(dnlen + 7 + 1);
+ if (r_key) {
+ char *kp = r_key;
+ memcpy(kp, " key '", 6); kp += 6;
+ /* Trim trailing '.' */
+ memcpy(kp, tag, dnlen); kp += dnlen - 1;
+ memcpy(kp, "'", 2); /* 1 + '\0' */
+ }
+ free(tag);
+ tag = NULL;
+ }
+
+ /* Prepare log message. */
+ conf_read_lock();
+ const char *zname = req->zname;
+ if (zname == NULL && req->zone != NULL) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(req->zone);
+ if (zd == NULL) {
+ free(r_key);
+ return KNOTD_EINVAL;
+ } else {
+ zname = zd->conf->name;
+ }
+ }
+ const char *pformat = NULL;
+ switch (req->type) {
+ case XFR_TYPE_AIN:
+ pformat = "AXFR transfer of '%s/IN' with %s:%d%s:";
+ break;
+ case XFR_TYPE_IIN:
+ pformat = "IXFR transfer of '%s/IN' with %s:%d%s:";
+ break;
+ case XFR_TYPE_AOUT:
+ pformat = "AXFR transfer of '%s/OUT' to %s:%d%s:";
+ break;
+ case XFR_TYPE_IOUT:
+ pformat = "IXFR transfer of '%s/OUT' to %s:%d%s:";
+ break;
+ case XFR_TYPE_NOTIFY:
+ pformat = "NOTIFY query of '%s' to %s:%d%s:";
+ break;
+ case XFR_TYPE_SOA:
+ pformat = "SOA query of '%s' to %s:%d%s:";
+ break;
+ default:
+ pformat = "";
+ break;
+ }
+
+ int len = 512;
+ char *msg = malloc(len + 1);
+ if (msg) {
+ memset(msg, 0, len + 1);
+ len = snprintf(msg, len + 1, pformat, zname, r_addr, r_port,
+ r_key ? r_key : "");
+ /* Shorten as some implementations (<C99) don't allow
+ * printing to NULL to estimate size. */
+ if (len > 0) {
+ msg = realloc(msg, len + 1);
+ }
+
+ req->msgpref = msg;
+ }
+
+ conf_read_unlock();
+ free(r_key);
+ return KNOTD_EOK;
+}
+
/*
* Public APIs.
*/
@@ -1094,7 +1225,7 @@ int xfr_request(xfrhandler_t *handler, knot_ns_xfr_t *req)
evqueue_t *q = handler->workers[handler->rr]->q;
handler->rr = get_next_rr(handler->rr, handler->unit->size);
pthread_mutex_unlock(&handler->rr_mx);
-
+
/* Delegate request. */
int ret = evqueue_write(q, req, sizeof(knot_ns_xfr_t));
if (ret < 0) {
@@ -1113,6 +1244,16 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
int ret = knot_ns_init_xfr(ns, xfr);
int xfr_failed = (ret != KNOT_EOK);
const char * errstr = knot_strerror(ret);
+
+ // use the QNAME as the zone name to get names also for
+ // zones that are not in the server
+ /*! \todo Update msgpref with zname from query. */
+ 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)");
+ }
/* Check requested zone. */
if (!xfr_failed) {
@@ -1122,12 +1263,19 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
}
/* Check TSIG. */
+ char *keytag = NULL;
if (!xfr_failed && xfr->tsig_key != NULL) {
- ret = xfr_check_tsig(xfr, &xfr->rcode);
+ ret = xfr_check_tsig(xfr, &xfr->rcode, &keytag);
xfr_failed = (ret != KNOT_EOK);
errstr = knot_strerror(ret);
}
+ ret = xfr_update_msgpref(xfr, keytag);
+ free(keytag);
+ if (ret != KNOTD_EOK) {
+ xfr->msgpref = strdup("XFR:");
+ }
+
/* Prepare place for TSIG data */
xfr->tsig_data = malloc(KNOT_NS_TSIG_DATA_MAX_SIZE);
if (xfr->tsig_data) {
@@ -1140,15 +1288,6 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
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) {
@@ -1167,33 +1306,22 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
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);
+ log_server_notice("%s %s\n", xfr->msgpref, 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);
+ log_server_info("%s Finished.\n", xfr->msgpref);
ret = KNOTD_EOK;
}
/* Free allocated data. */
free(xfr->tsig_data);
xfr->tsig_data = NULL;
+ xfr_request_deinit(xfr);
/* Cleanup. */
free(xfr->digest);
@@ -1214,14 +1342,13 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
dbg_xfr_verb("xfr: evqueue_read() returned %d.\n", ret);
return KNOTD_ENOTRUNNING;
}
-
+
/* Update request. */
- sockaddr_update(&xfr.addr);
xfr.wire = buf;
xfr.wire_size = buflen;
- char r_addr[SOCKADDR_STRLEN];
- sockaddr_tostr(&xfr.addr, r_addr, sizeof(r_addr));
- int r_port = sockaddr_portnum(&xfr.addr);
+
+ /* Update XFR message prefix. */
+ xfr_update_msgpref(&xfr, NULL);
conf_read_lock();
@@ -1230,27 +1357,21 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
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_ns_xfr_t *task = NULL;
+ evsched_t *sch = NULL;
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_AIN:
case XFR_TYPE_IIN:
- if (xfr.type == XFR_TYPE_IIN) {
- req_type = "IXFR/IN";
- } else {
- 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));
+ log_server_error("%s %s\n",
+ xfr.msgpref, knotd_strerror(ret));
}
+
break;
case XFR_TYPE_SOA:
case XFR_TYPE_NOTIFY:
@@ -1260,11 +1381,7 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
ret = KNOTD_ENOMEM;
break;
}
-
- req_type = "SOA or NOTIFY";
- dbg_xfr("xfr: waiting for %s query response\n",
- xfr.type == XFR_TYPE_SOA ? "SOA" : "NOTIFY");
-
+
/* Add timeout. */
sch = ((server_t *)knot_ns_get_data(w->ns))->sched;
task->data = evsched_schedule_cb(sch, xfr_udp_timeout,
@@ -1272,6 +1389,7 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
if (zd && xfr.type == XFR_TYPE_SOA) {
zd->soa_pending = (event_t*)task->data;
}
+ log_server_info("%s Query issued.\n", xfr.msgpref);
ret = KNOTD_EOK;
break;
/* Socket close event. */
@@ -1286,6 +1404,11 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
conf_read_unlock();
+ /* Deinitialize (it is already registered, or discarded).
+ * Right now, this only frees temporary msgpref.
+ */
+ xfr_request_deinit(&xfr);
+
return ret;
}
@@ -1350,6 +1473,20 @@ int xfr_worker(dthread_t *thread)
pthread_mutex_lock(&h->tasks_mx);
data = skip_find(h->tasks, (void*)((size_t)it.fd));
pthread_mutex_unlock(&h->tasks_mx);
+ if (data == NULL) {
+ dbg_xfr_verb("xfr: worker=%p processing event on "
+ "fd=%d got empty data.\n",
+ w, it.fd);
+ fdset_remove(w->fdset, it.fd);
+ close(it.fd); /* Always dup()'d or created. */
+
+ /* Next fd. */
+ if (fdset_next(w->fdset, &it) < 0) {
+ break;
+ } else {
+ continue;
+ }
+ }
dbg_xfr_verb("xfr: worker=%p processing event on "
"fd=%d data=%p.\n",
w, it.fd, data);
diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c
index a196462..dbc1340 100644
--- a/src/knot/server/zones.c
+++ b/src/knot/server/zones.c
@@ -15,6 +15,7 @@
*/
#include <sys/stat.h>
+#include <unistd.h>
#include "common/lists.h"
#include "common/prng.h"
@@ -42,6 +43,9 @@
static const size_t XFRIN_CHANGESET_BINARY_SIZE = 100;
static const size_t XFRIN_CHANGESET_BINARY_STEP = 100;
+/* Forward declarations. */
+static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *zf);
+
/*----------------------------------------------------------------------------*/
/*!
@@ -111,7 +115,7 @@ static int zonedata_destroy(knot_zone_t *zone)
acl_delete(&zd->notify_out);
/* Close IXFR db. */
- journal_close(zd->ixfr_db);
+ journal_release(zd->ixfr_db);
free(zd);
@@ -161,7 +165,7 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
/* Initialize IXFR database. */
zd->ixfr_db = journal_open(cfg->ixfr_db, cfg->ixfr_fslimit,
- JOURNAL_DIRTY);
+ JOURNAL_LAZY, JOURNAL_DIRTY);
if (!zd->ixfr_db) {
int ret = journal_create(cfg->ixfr_db, JOURNAL_NCOUNT);
if (ret != KNOTD_EOK) {
@@ -169,7 +173,7 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
"'%s'\n", cfg->ixfr_db);
}
zd->ixfr_db = journal_open(cfg->ixfr_db, cfg->ixfr_fslimit,
- JOURNAL_DIRTY);
+ JOURNAL_LAZY, JOURNAL_DIRTY);
}
if (zd->ixfr_db == 0) {
@@ -194,6 +198,7 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
if (contents) {
soa_rrs = knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
+ assert(soa_rrs != NULL);
soa_rr = knot_rrset_rdata(soa_rrs);
int64_t serial = knot_rdata_soa_serial(soa_rr);
zd->zonefile_serial = (uint32_t)serial;
@@ -232,6 +237,7 @@ static uint32_t zones_soa_timer(knot_zone_t *zone,
soa_rrs = knot_node_rrset(knot_zone_contents_apex(zc),
KNOT_RRTYPE_SOA);
+ assert(soa_rrs != NULL);
soa_rr = knot_rrset_rdata(soa_rrs);
ret = rr_func(soa_rr);
@@ -542,7 +548,7 @@ static int zones_notify_send(event_t *e)
/* Check number of retries. */
if (ev->retries < 0) {
log_server_notice("NOTIFY query maximum number of retries "
- "for zone %s exceeded.\n",
+ "for zone '%s' exceeded.\n",
zd->conf->name);
pthread_mutex_lock(&zd->lock);
rem_node(&ev->n);
@@ -593,14 +599,7 @@ static int zones_notify_send(event_t *e)
/* Store ID of the awaited response. */
if (ret == buflen) {
- char r_addr[SOCKADDR_STRLEN];
- 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 '%s' NOTIFY query to %s:%d, "
- "expecting response ID=%d\n",
- zd->conf->name, r_addr, r_port,
- ev->msgid);
}
@@ -611,6 +610,7 @@ static int zones_notify_send(event_t *e)
req.type = XFR_TYPE_NOTIFY;
req.zone = zone;
memcpy(&req.addr, &ev->addr, sizeof(sockaddr_t));
+ memcpy(&req.saddr, &ev->saddr, sizeof(sockaddr_t));
xfr_request(zd->server->xfr_h, &req);
/* Unlock RCU */
@@ -656,7 +656,9 @@ static int zones_zonefile_sync_ev(event_t *e)
}
/* Execute zonefile sync. */
- int ret = zones_zonefile_sync(zone);
+ journal_t *j = journal_retain(zd->ixfr_db);
+ int ret = zones_zonefile_sync(zone, j);
+ journal_release(j);
if (ret == KNOTD_EOK) {
log_zone_info("Applied differences of '%s' to zonefile.\n",
zd->conf->name);
@@ -710,11 +712,20 @@ static int zones_set_acl(acl_t **acl, list* acl_list)
sockaddr_t addr;
conf_iface_t *cfg_if = r->remote;
int ret = sockaddr_set(&addr, cfg_if->family,
- cfg_if->address, 0);
+ cfg_if->address, 0);
+ sockaddr_setprefix(&addr, cfg_if->prefix);
/* Load rule. */
if (ret > 0) {
- acl_create(*acl, &addr, ACL_ACCEPT, cfg_if);
+ /*! \todo Correct search for the longest prefix match.
+ * This just favorizes remotes with TSIG.
+ * (issue #1675)
+ */
+ unsigned flags = 0;
+ if (cfg_if->key != NULL) {
+ flags = ACL_PREFER;
+ }
+ acl_create(*acl, &addr, ACL_ACCEPT, cfg_if, flags);
}
}
@@ -1040,18 +1051,22 @@ static int zones_load_changesets(const knot_zone_t *zone,
dbg_zones_detail("Bad arguments: zd->ixfr_db=%p\n", zone->data);
return KNOTD_EINVAL;
}
+
+ /* Retain journal for changeset loading. */
+ journal_t *j = journal_retain(zd->ixfr_db);
/* Read entries from starting serial until finished. */
uint32_t found_to = from;
journal_node_t *n = 0;
- int ret = journal_fetch(zd->ixfr_db, from, ixfrdb_key_from_cmp, &n);
+ int ret = journal_fetch(j, from, ixfrdb_key_from_cmp, &n);
if (ret != KNOTD_EOK) {
dbg_xfr("xfr: failed to fetch starting changeset: %s\n",
knotd_strerror(ret));
+ journal_release(j);
return ret;
}
- while (n != 0 && n != journal_end(zd->ixfr_db)) {
+ while (n != 0 && n != journal_end(j)) {
/* Check for history end. */
if (to == found_to) {
@@ -1068,6 +1083,7 @@ static int zones_load_changesets(const knot_zone_t *zone,
--dst->count;
dbg_xfr("xfr: failed to check changesets size: %s\n",
knot_strerror(ret));
+ journal_release(j);
return KNOTD_ERROR;
}
@@ -1079,15 +1095,16 @@ static int zones_load_changesets(const knot_zone_t *zone,
chs->serial_to = ixfrdb_key_to(n->id);
chs->data = malloc(n->len);
if (!chs->data) {
+ journal_release(j);
return KNOTD_ENOMEM;
}
/* Read journal entry. */
- ret = journal_read(zd->ixfr_db, n->id,
- 0, (char*)chs->data);
+ ret = journal_read(j, n->id, 0, (char*)chs->data);
if (ret != KNOTD_EOK) {
dbg_xfr("xfr: failed to read data from journal\n");
free(chs->data);
+ journal_release(j);
return KNOTD_ERROR;
}
@@ -1103,6 +1120,7 @@ static int zones_load_changesets(const knot_zone_t *zone,
}
dbg_xfr_detail("xfr: Journal entries read.\n");
+ journal_release(j);
/* Unpack binary data. */
int unpack_ret = zones_changesets_from_binary(dst);
@@ -1153,6 +1171,7 @@ static int zones_journal_apply(knot_zone_t *zone)
const knot_rdata_t *soa_rr = 0;
soa_rrs = knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
+ assert(soa_rrs != NULL);
soa_rr = knot_rrset_rdata(soa_rrs);
int64_t serial_ret = knot_rdata_soa_serial(soa_rr);
if (serial_ret < 0) {
@@ -1173,13 +1192,39 @@ 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(zone, chsets);
+ knot_zone_contents_t *contents = NULL;
+ int apply_ret = xfrin_apply_changesets(zone, chsets,
+ &contents);
if (apply_ret != KNOT_EOK) {
- log_server_error("Failed to apply changesets to "
- "'%s' - %s\n",
+ log_server_error("Failed to apply changesets to"
+ "'%s' - Apply failed: %s\n",
zd->conf->name,
knot_strerror(apply_ret));
ret = KNOTD_ERROR;
+
+ // Cleanup old and new contents
+ xfrin_rollback_update(zone->contents,
+ &contents,
+ &chsets->changes);
+ }
+
+ /* Switch zone immediately. */
+ apply_ret = xfrin_switch_zone(zone, contents,
+ XFR_TYPE_IIN);
+ if (apply_ret == KNOT_EOK) {
+ xfrin_cleanup_successful_update(
+ &chsets->changes);
+ } else {
+ log_server_error("Failed to apply changesets to"
+ " '%s' - Switch failed: %s\n",
+ zd->conf->name,
+ knot_strerror(apply_ret));
+ ret = KNOTD_ERROR;
+
+ // Cleanup old and new contents
+ xfrin_rollback_update(zone->contents,
+ &contents,
+ &chsets->changes);
}
}
} else {
@@ -1238,9 +1283,9 @@ static int zones_insert_zones(knot_nameserver_t *ns,
int reload = 0;
/* Attempt to bootstrap if db or source does not exist. */
- struct stat s;
+ struct stat s = {};
int stat_ret = stat(z->file, &s);
- if (zone != NULL) {
+ if (zone != NULL && stat_ret == 0) {
/* if found, check timestamp of the file against the
* loaded zone
*/
@@ -1325,8 +1370,11 @@ static int zones_insert_zones(knot_nameserver_t *ns,
dbg_zones_verb("zones: found '%s' in old database, "
"copying to new.\n",
z->name);
- log_server_info("Zone '%s' is up-to-date, no need "
- "for reload.\n", z->name);
+ /* Only if zone file exists. */
+ if (stat_ret == 0) {
+ log_server_info("Zone '%s' is up-to-date, no need "
+ "for reload.\n", z->name);
+ }
int ret = knot_zonedb_add_zone(db_new, zone);
if (ret != KNOT_EOK) {
log_server_error("Error adding known zone '%s' to"
@@ -1691,7 +1739,7 @@ int zones_update_db_from_config(const conf_t *conf, knot_nameserver_t *ns,
return KNOTD_EOK;
}
-int zones_zonefile_sync(knot_zone_t *zone)
+int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal)
{
if (!zone) {
return KNOTD_EINVAL;
@@ -1718,6 +1766,8 @@ int zones_zonefile_sync(knot_zone_t *zone)
const knot_rdata_t *soa_rr = 0;
soa_rrs = knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
+ assert(soa_rrs != NULL);
+
soa_rr = knot_rrset_rdata(soa_rrs);
int64_t serial_ret = knot_rdata_soa_serial(soa_rr);
if (serial_ret < 0) {
@@ -1734,14 +1784,21 @@ int zones_zonefile_sync(knot_zone_t *zone)
dbg_zones("zones: syncing '%s' differences to '%s' "
"(SOA serial %u)\n",
zd->conf->name, zd->conf->file, serial_to);
- zone_dump_text(contents, zd->conf->file);
+ ret = zones_dump_zone_text(contents, zd->conf->file);
+ if (ret != KNOTD_EOK) {
+ dbg_zones("zones: failed to sync '%s' to '%s'\n",
+ zd->conf->name, zd->conf->file);
+ pthread_mutex_unlock(&zd->lock);
+ return ret;
+ }
+
conf_read_unlock();
/* Update journal entries. */
dbg_zones_verb("zones: unmarking all dirty nodes "
"in '%s' journal\n",
zd->conf->name);
- journal_walk(zd->ixfr_db, zones_ixfrdb_sync_apply);
+ journal_walk(journal, zones_ixfrdb_sync_apply);
/* Update zone file serial. */
dbg_zones("zones: new '%s' zonefile serial is %u\n",
@@ -1766,7 +1823,10 @@ int zones_query_check_zone(const knot_zone_t *zone, const sockaddr_t *addr,
{
if (addr == NULL || tsig_key == NULL || rcode == NULL) {
dbg_zones_verb("Wrong arguments.\n");
- *rcode = KNOT_RCODE_SERVFAIL;
+
+ if (rcode != NULL) {
+ *rcode = KNOT_RCODE_SERVFAIL;
+ }
return KNOTD_EINVAL;
}
@@ -2107,7 +2167,8 @@ int zones_process_response(knot_nameserver_t *nameserver,
/* Check SOA SERIAL. */
int ret = xfrin_transfer_needed(contents, packet);
- dbg_zones_verb("xfrin_transfer_needed() returned %d\n", ret);
+ dbg_zones_verb("xfrin_transfer_needed() returned %s\n",
+ knot_strerror(ret));
if (ret < 0) {
/* RETRY/EXPIRE timers running, do not interfere. */
rcu_read_unlock();
@@ -2118,8 +2179,12 @@ int zones_process_response(knot_nameserver_t *nameserver,
evsched_t *sched =
((server_t *)knot_ns_get_data(nameserver))->sched;
if (ret == 0) {
- log_zone_info("SOA query for zone '%s' answered, no "
- "transfer needed.\n", zd->conf->name);
+ char r_addr[SOCKADDR_STRLEN];
+ int r_port = sockaddr_portnum(from);
+ sockaddr_tostr(from, r_addr, sizeof(r_addr));
+ log_zone_info("SOA query of '%s' to %s:%d: Answered, no "
+ "transfer needed.\n",
+ zd->conf->name, r_addr, r_port);
rcu_read_unlock();
/* Reinstall timers. */
@@ -2217,136 +2282,171 @@ static int zones_find_zone_for_xfr(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
-static char *zones_find_free_filename(const char *old_name)
+static int zones_open_free_filename(const char *old_name, char **new_name)
{
/* find zone name not present on the disk */
- int free_name = 0;
size_t name_size = strlen(old_name);
-
- char *new_name = malloc(name_size + 3);
- if (new_name == NULL) {
- return NULL;
- }
- memcpy(new_name, old_name, name_size);
- new_name[name_size] = '.';
- new_name[name_size + 2] = 0;
-
- dbg_zones_verb("zones: finding free name for the zone file.\n");
- int c = 48;
- FILE *file;
- while (!free_name && c < 58) {
- new_name[name_size + 1] = c;
- dbg_zones_verb("zones: trying file name %s\n", new_name);
- if ((file = fopen(new_name, "r")) != NULL) {
- fclose(file);
- ++c;
- } else {
- free_name = 1;
- }
- }
-
- if (free_name) {
- return new_name;
- } else {
- free(new_name);
- return NULL;
+ *new_name = malloc(name_size + 7 + 1);
+ if (*new_name == NULL) {
+ return -1;
+ }
+ memcpy(*new_name, old_name, name_size + 1);
+ strncat(*new_name, ".XXXXXX", 7);
+ dbg_zones_verb("zones: creating temporary zone file\n");
+ mode_t old_mode = umask(077);
+ int fd = mkstemp(*new_name);
+ (void) umask(old_mode);
+ if (fd < 0) {
+ dbg_zones_verb("zones: couldn't create temporary zone file\n");
+ free(*new_name);
+ *new_name = NULL;
}
+
+ return fd;
}
/*----------------------------------------------------------------------------*/
-static int zones_dump_xfr_zone_text(knot_zone_contents_t *zone,
- const char *zonefile)
+static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
{
- assert(zone != NULL && zonefile != NULL);
-
- /*! \todo new_zonefile may be created by another process,
- * 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);
+ assert(zone != NULL && fname != NULL);
- if (new_zonefile == NULL) {
+ char *new_fname = NULL;
+ int fd = zones_open_free_filename(fname, &new_fname);
+ if (fd < 0) {
log_zone_warning("Failed to find filename for temporary "
"storage of the transferred zone.\n");
- return KNOTD_ERROR; /*! \todo New error code? */
+ return KNOTD_ERROR;
}
-
- int rc = zone_dump_text(zone, new_zonefile);
-
- if (rc != KNOTD_EOK) {
+
+ if (zone_dump_text(zone, fd) != KNOTD_EOK) {
log_zone_warning("Failed to save the transferred zone to '%s'.\n",
- new_zonefile);
- free(new_zonefile);
+ new_fname);
+ close(fd);
+ unlink(new_fname);
+ free(new_fname);
return KNOTD_ERROR;
}
- /*! \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) {
+ /* Swap temporary zonefile and new zonefile. */
+ close(fd);
+ int ret = rename(new_fname, fname);
+ if (ret < 0 && ret != EEXIST) {
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 (issue #1587)
- */
- zone_dump_text(zone, zonefile);
- free(new_zonefile);
+ " zone file '%s'.\n", fname, new_fname);
+ unlink(new_fname);
+ free(new_fname);
return KNOTD_ERROR;
}
- free(new_zonefile);
+ free(new_fname);
return KNOTD_EOK;
}
/*----------------------------------------------------------------------------*/
-static int ns_dump_xfr_zone_binary(knot_zone_contents_t *zone,
+static int zones_dump_zone_binary(knot_zone_contents_t *zone,
const char *zonedb,
const char *zonefile)
{
assert(zone != NULL && zonedb != NULL);
- /*! \todo new_zonedb may be created by another process,
- * 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);
-
- if (new_zonedb == NULL) {
+ char *new_zonedb = NULL;
+ int fd = zones_open_free_filename(zonedb, &new_zonedb);
+ if (fd < 0) {
dbg_zones("zones: failed to find free filename for temporary "
"storage of the zone binary file '%s'\n",
zonedb);
- return KNOTD_ERROR; /*! \todo New error code? */
+ return KNOTD_ERROR;
}
- /*! \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);
+ crc_t crc_value;
+ if (knot_zdump_dump(zone, fd, zonefile, &crc_value) != KNOT_EOK) {
+ close(fd);
+ unlink(new_zonedb);
+ free(new_zonedb);
+ return KNOTD_ERROR;
+ }
- if (rc != KNOT_EOK) {
+ /* Delete old CRC file. */
+ char *zonedb_crc = knot_zdump_crc_file(zonedb);
+ if (zonedb_crc == NULL) {
+ close(fd);
+ unlink(new_zonedb);
+ free(new_zonedb);
+ return KNOTD_ENOMEM;
+ }
+ remove(zonedb_crc);
+
+ /* New CRC file. */
+ char *new_zonedb_crc = knot_zdump_crc_file(new_zonedb);
+ if (new_zonedb_crc == NULL) {
+ dbg_zdump("Failed to create CRC file path from %s.\n",
+ new_zonedb);
+ free(zonedb_crc);
+ close(fd);
+ unlink(new_zonedb);
+ free(new_zonedb);
+ return KNOTD_ENOMEM;
+ }
+
+ /* Write CRC value to CRC file. */
+ FILE *f_crc = fopen(new_zonedb_crc, "w");
+ if (f_crc == NULL) {
+ dbg_zdump("Cannot open CRC file %s!\n",
+ zonedb_crc);
+ unlink(new_zonedb);
return KNOTD_ERROR;
+ } else {
+ fprintf(f_crc, "%lu\n",
+ (unsigned long)crc_value);
+ fclose(f_crc);
}
+ /* Swap CRC files. */
+ int ret = KNOTD_EOK;
+ if (rename(new_zonedb_crc, zonedb_crc) < 0) {
+ dbg_zdump("Failed to replace old zonedb CRC %s "
+ "with new CRC zone file %s.\n",
+ zonedb_crc,
+ new_zonedb_crc);
+ unlink(new_zonedb);
+ unlink(new_zonedb_crc);
+ ret = KNOTD_ERROR;
+ } else {
+ /* Swap zone databases. */
+ int swap_res = rename(new_zonedb, zonedb);
+ if (swap_res < 0 && swap_res != EEXIST) {
+ dbg_zdump("Failed to replace old zonedb %s "
+ "with new zone file %s.\n",
+ new_zonedb,
+ zonedb);
+ ret = KNOTD_ERROR;
+ unlink(new_zonedb);
+ } else {
- return KNOTD_EOK;
+ }
+ }
+
+ free(new_zonedb_crc);
+ free(zonedb_crc);
+ close(fd);
+ free(new_zonedb);
+
+
+ return ret;
}
/*----------------------------------------------------------------------------*/
int zones_save_zone(const knot_ns_xfr_t *xfr)
{
- if (xfr == NULL || xfr->data == NULL) {
+ if (xfr == NULL || xfr->new_contents == NULL) {
return KNOTD_EINVAL;
}
- knot_zone_contents_t *zone =
- (knot_zone_contents_t *)xfr->data;
+ knot_zone_contents_t *zone = xfr->new_contents;
const char *zonefile = NULL;
const char *zonedb = NULL;
@@ -2359,12 +2459,12 @@ int zones_save_zone(const knot_ns_xfr_t *xfr)
assert(zonefile != NULL && zonedb != NULL);
/* dump the zone into text zone file */
- ret = zones_dump_xfr_zone_text(zone, zonefile);
+ ret = zones_dump_zone_text(zone, zonefile);
if (ret != KNOTD_EOK) {
return KNOTD_ERROR;
}
/* dump the zone into binary db file */
- ret = ns_dump_xfr_zone_binary(zone, zonedb, zonefile);
+ ret = zones_dump_zone_binary(zone, zonedb, zonefile);
if (ret != KNOTD_EOK) {
return KNOTD_ERROR;
}
@@ -2447,13 +2547,15 @@ static int zones_changeset_rrset_to_binary(uint8_t **data, size_t *size,
size_t actual_size = 0;
int ret = knot_zdump_rrset_serialize(rrset, &binary, &actual_size);
if (ret != KNOT_EOK || binary == NULL) {
+ dbg_zones("knot_zdump_rrset_serialize() returned %s\n",
+ knot_strerror(ret));
return KNOTD_ERROR; /*! \todo Other code? */
}
ret = zones_check_binary_size(data, allocated, *size + actual_size);
- if (ret != KNOT_EOK) {
+ if (ret != KNOTD_EOK) {
free(binary);
- return KNOTD_ERROR;
+ return ret;
}
memcpy(*data + *size, binary, actual_size);
@@ -2465,7 +2567,7 @@ static int zones_changeset_rrset_to_binary(uint8_t **data, size_t *size,
/*----------------------------------------------------------------------------*/
-static int zones_changesets_to_binary(knot_changesets_t *chgsets)
+int zones_changesets_to_binary(knot_changesets_t *chgsets)
{
assert(chgsets != NULL);
assert(chgsets->allocated >= chgsets->count);
@@ -2484,12 +2586,12 @@ static int zones_changesets_to_binary(knot_changesets_t *chgsets)
/* 1) origin SOA */
ret = zones_changeset_rrset_to_binary(&ch->data, &ch->size,
&ch->allocated, ch->soa_from);
- if (ret != KNOT_EOK) {
+ if (ret != KNOTD_EOK) {
free(ch->data);
ch->data = NULL;
dbg_zones("zones_changeset_rrset_to_binary(): %s\n",
knot_strerror(ret));
- return KNOTD_ERROR;
+ return ret;
}
int j;
@@ -2501,24 +2603,24 @@ static int zones_changesets_to_binary(knot_changesets_t *chgsets)
&ch->size,
&ch->allocated,
ch->remove[j]);
- if (ret != KNOT_EOK) {
+ if (ret != KNOTD_EOK) {
free(ch->data);
ch->data = NULL;
dbg_zones("zones_changeset_rrset_to_binary(): %s\n",
knot_strerror(ret));
- return KNOTD_ERROR;
+ return ret;
}
}
/* 3) new SOA */
ret = zones_changeset_rrset_to_binary(&ch->data, &ch->size,
&ch->allocated, ch->soa_to);
- if (ret != KNOT_EOK) {
+ if (ret != KNOTD_EOK) {
free(ch->data);
ch->data = NULL;
dbg_zones("zones_changeset_rrset_to_binary(): %s\n",
knot_strerror(ret));
- return KNOTD_ERROR;
+ return ret;
}
/* 4) add RRsets */
@@ -2528,12 +2630,12 @@ static int zones_changesets_to_binary(knot_changesets_t *chgsets)
&ch->size,
&ch->allocated,
ch->add[j]);
- if (ret != KNOT_EOK) {
+ if (ret != KNOTD_EOK) {
free(ch->data);
ch->data = NULL;
dbg_zones("zones_changeset_rrset_to_binary(): %s\n",
knot_strerror(ret));
- return KNOTD_ERROR;
+ return ret;
}
}
}
@@ -2551,11 +2653,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;
-
- int ret = zones_changesets_to_binary(src);
- if (ret != KNOTD_EOK) {
- return ret;
- }
/* Fetch zone-specific data. */
zonedata_t *zd = (zonedata_t *)zone->data;
@@ -2563,6 +2660,9 @@ int zones_store_changesets(knot_ns_xfr_t *xfr)
return KNOTD_EINVAL;
}
+ /* Retain journal for changeset loading. */
+ journal_t *j = journal_retain(zd->ixfr_db);
+
/* Begin writing to journal. */
for (unsigned i = 0; i < src->count; ++i) {
@@ -2571,8 +2671,7 @@ int zones_store_changesets(knot_ns_xfr_t *xfr)
uint64_t k = ixfrdb_key_make(chs->serial_from, chs->serial_to);
/* Write entry. */
- int ret = journal_write(zd->ixfr_db, k, (const char*)chs->data,
- chs->size);
+ int ret = journal_write(j, k, (const char*)chs->data, chs->size);
/* Check for errors. */
while (ret != KNOTD_EOK) {
@@ -2593,7 +2692,7 @@ int zones_store_changesets(knot_ns_xfr_t *xfr)
dbg_xfr_verb("xfr: forcing zonefile SYNC "
"of '%s'\n",
zd->conf->name);
- ret = zones_zonefile_sync(zone);
+ ret = zones_zonefile_sync(zone, j);
if (ret != KNOTD_EOK && ret != KNOTD_ERANGE) {
continue;
}
@@ -2616,11 +2715,11 @@ int zones_store_changesets(knot_ns_xfr_t *xfr)
}
/* Attempt to write again. */
- ret = journal_write(zd->ixfr_db, k,
- (const char*)chs->data,
+ ret = journal_write(j, k, (const char*)chs->data,
chs->size);
} else {
/* Other errors. */
+ journal_release(j);
return KNOTD_ERROR;
}
}
@@ -2630,6 +2729,9 @@ int zones_store_changesets(knot_ns_xfr_t *xfr)
chs->data = 0;
chs->size = 0;
}
+
+ /* Release journal. */
+ journal_release(j);
/* Written changesets to journal. */
return KNOTD_EOK;
@@ -2676,18 +2778,6 @@ 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 KNOT_EBADARG;
- }
-
- return xfrin_apply_changesets(xfr->zone,
- (knot_changesets_t *)xfr->data);
-}
-
-/*----------------------------------------------------------------------------*/
-
int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
{
if (!sch || !zone) {
diff --git a/src/knot/server/zones.h b/src/knot/server/zones.h
index 53c5290..1822b84 100644
--- a/src/knot/server/zones.h
+++ b/src/knot/server/zones.h
@@ -73,9 +73,9 @@ typedef struct zonedata_t
knot_key_t tsig_key; /*!< Master TSIG key. */
struct event_t *timer; /*!< Timer for REFRESH/RETRY. */
struct event_t *expire; /*!< Timer for REFRESH. */
- int next_id; /*!< ID of the next awaited SOA resp.*/
pthread_mutex_t lock; /*!< Pending XFR/IN lock. */
void *wrkr; /*!< Pending XFR/IN worker. */
+ int next_id; /*!< ID of the next awaited SOA resp.*/
uint32_t bootstrap_retry;/*!< AXFR/IN bootstrap retry. */
} xfr_in;
@@ -125,13 +125,14 @@ int zones_update_db_from_config(const conf_t *conf, knot_nameserver_t *ns,
* \note Current implementation rewrites the zone file.
*
* \param zone Evaluated zone.
+ * \param journal Journal to sync.
*
* \retval KNOTD_EOK if successful.
* \retval KNOTD_ERANGE if zonefile is in sync with journal.
* \retval KNOTD_EINVAL on invalid parameter.
* \retval KNOTD_ERROR on unspecified error during processing.
*/
-int zones_zonefile_sync(knot_zone_t *zone);
+int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal);
/*!
* \todo Document me.
@@ -213,6 +214,8 @@ int zones_ns_conf_hook(const struct conf_t *conf, void *data);
*/
int zones_store_changesets(knot_ns_xfr_t *xfr);
+int zones_changesets_to_binary(knot_changesets_t *chgsets);
+
/*!
* \brief Load changesets from journal.
*
@@ -237,20 +240,6 @@ int zones_xfr_load_changesets(knot_ns_xfr_t *xfr, uint32_t serial_from,
uint32_t serial_to);
/*!
- * \brief Apply changesets to zone.
- *
- * Applies a list of XFR-style changesets to the given zone. Also checks if the
- * changesets are applicable (i.e. zone is right and has the right serial).
- *
- * \param zone Zone to which the changesets should be applied.
- * \param chsets Changesets to be applied to the zone.
- *
- * \retval KNOTD_EOK
- * \retval KNOTD_EINVAL
- */
-int zones_apply_changesets(knot_ns_xfr_t *xfr);
-
-/*!
* \brief Update zone timers.
*
* REFRESH/RETRY/EXPIRE timers are updated according to SOA.
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index f511f35..f900951 100644
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -156,12 +156,11 @@ int err_handler_handle_error(err_handler_t *handler,
assert(handler && node);
if ((error != 0) &&
(error > ZC_ERR_GLUE_GENERAL_ERROR)) {
- return ZC_ERR_UNKNOWN;
+ return KNOT_EBADARG;
}
/*!< \todo this is so wrong! This should not even return anything. */
- if (error == ZC_ERR_ALLOC || error == KNOT_ERROR
- || error == KNOT_EBADARG) {
+ if (error == ZC_ERR_ALLOC || error == 0) {
return KNOT_EBADARG;
}
@@ -382,10 +381,13 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
knot_dname_new_from_str("*", strlen("*"),
NULL);
if (wc == NULL) {
+ knot_dname_free(&chopped_next);
return KNOT_ENOMEM;
}
if (knot_dname_cat(wc, chopped_next) == NULL) {
+ knot_dname_free(&chopped_next);
+ knot_dname_free(&wc);
return KNOT_ERROR;
}
@@ -552,6 +554,9 @@ static int dnskey_to_wire(const knot_rdata_t *rdata, uint8_t **wire,
/* TODO check if we really have that many items */
if (rdata->count < 4) {
+ free(*wire);
+ *wire = NULL;
+ *size = 0;
return KNOT_ERROR;
}
@@ -915,16 +920,14 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
knot_node_rrset(knot_zone_contents_apex(zone),
KNOT_RRTYPE_SOA);
assert(soa_rrset);
-
- uint32_t minimum_ttl =
- knot_wire_read_u32((uint8_t *)
- rdata_item_data(
- knot_rdata_item(
- knot_rrset_rdata(
- knot_node_rrset(
- knot_zone_contents_apex(zone), KNOT_RRTYPE_SOA)), 6)));
- /* Are those getters even worth this?
- * Now I have no idea what this code does. */
+
+ const knot_rdata_t *soa_rdata = knot_rrset_rdata(soa_rrset);
+ if (soa_rdata == NULL) {
+ err_handler_handle_error(handler, node, ZC_ERR_UNKNOWN);
+ return KNOT_EOK;
+ }
+
+ uint32_t minimum_ttl = knot_rdata_soa_minimum(soa_rdata);
if (knot_rrset_ttl(nsec3_rrset) != minimum_ttl) {
err_handler_handle_error(handler, node,
@@ -1012,6 +1015,22 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
return KNOT_EOK;
}
+struct sem_check_param {
+ int node_count;
+};
+
+/*!
+ * \brief Used only to count number of nodes in zone tree.
+ *
+ * \param node Node to be counted
+ * \param data Count casted to void *
+ */
+static void count_nodes_in_tree(knot_node_t *node, void *data)
+{
+ struct sem_check_param *param = (struct sem_check_param *)data;
+ param->node_count++;
+}
+
/*!
* \brief Run semantic checks for node without DNSSEC-related types.
*
@@ -1089,9 +1108,34 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
}
if (node->children != 0) {
- *fatal_error = 1;
- err_handler_handle_error(handler, node,
- ZC_ERR_DNAME_CHILDREN);
+ /*
+ * With DNSSEC and node being zone apex,
+ * NSEC3 and its RRSIG can be present.
+ */
+
+ /* The NSEC3 tree can thus only have one node. */
+ struct sem_check_param param;
+ param.node_count = 0;
+ int ret_apply =
+ knot_zone_contents_nsec3_apply_inorder(zone,
+ count_nodes_in_tree,
+ &param);
+ if (ret_apply != KNOT_EOK || param.node_count != 1) {
+ *fatal_error = 1;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_DNAME_CHILDREN);
+ /*
+ * Valid case: Node is apex, it has NSEC3 node
+ * and that node has only one RRSet.
+ */
+ } else if (!((knot_zone_contents_apex(zone) == node) &&
+ knot_node_nsec3_node(node) &&
+ knot_node_rrset_count(knot_node_nsec3_node(
+ node)) == 1)) {
+ *fatal_error = 1;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_DNAME_CHILDREN);
+ }
}
}
@@ -1173,10 +1217,6 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
if (auth && !deleg &&
(ret = check_rrsig_in_rrset(rrset, dnskey_rrset,
nsec3)) != 0) {
- /* CLEANUP */
-/* log_zone_error("RRSIG %d node %s\n", ret,
- knot_dname_to_str(node->owner));*/
-
err_handler_handle_error(handler, node, ret);
}
@@ -1189,13 +1229,6 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
if (nsec_rrset == NULL) {
err_handler_handle_error(handler, node,
ZC_ERR_NO_NSEC);
- /* CLEANUP */
-/* char *name =
- knot_dname_to_str(node->owner);
- log_zone_error("Missing NSEC in node: "
- "%s\n", name);
- free(name);
- return; */
} else {
/* check NSEC/NSEC3 bitmap */
@@ -1229,18 +1262,6 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
handler,
node,
ZC_ERR_NSEC_RDATA_BITMAP);
- /* CLEANUP */
- /* char *name =
- knot_dname_to_str(
- knot_node_owner(node));
-
- log_zone_error("Node %s does "
- "not contain RRSet of type %s "
- "but NSEC bitmap says "
- "it does!\n", name,
- knot_rrtype_to_string(type));
-
- free(name); */
}
}
free(array);
diff --git a/src/knot/zone/zone-dump-text.c b/src/knot/zone/zone-dump-text.c
index dcb9add..4a45d64 100644
--- a/src/knot/zone/zone-dump-text.c
+++ b/src/knot/zone/zone-dump-text.c
@@ -54,7 +54,7 @@
#include "common/skip-list.h"
#include "common/base32hex.h"
-/* TODO max length of alg */
+/*!< \todo #1683 Find all maximum lengths to be used in strcnat. */
enum uint_max_length {
U8_MAX_STR_LEN = 4, U16_MAX_STR_LEN = 6,
@@ -114,7 +114,6 @@ enum uint_max_length {
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/types.h>
-#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -361,30 +360,30 @@ static char *rdata_txt_data_to_string(const uint8_t *data)
}
memset(ret, 0, current_length);
- strcat(ret, "\"");
+ strncat(ret, "\"", 3);
for (i = 1; i <= length; i++) {
char ch = (char) data[i];
if (isprint((int)ch)) {
if (ch == '"' || ch == '\\') {
- strcat(ret, "\"");
+ strncat(ret, "\"", 3);
}
/* for the love of god, how to this better,
but w/o obscure self-made functions */
char tmp_str[2];
tmp_str[0] = ch;
tmp_str[1] = 0;
- strcat(ret, tmp_str);
+ strncat(ret, tmp_str, 2);
} else {
- strcat(ret, "\\");
+ strncat(ret, "\\", 3);
char tmp_str[2];
tmp_str[0] = ch - '0';
tmp_str[1] = 0;
- strcat(ret, tmp_str);
+ strncat(ret, tmp_str, 2);
}
}
- strcat(ret, "\"");
+ strncat(ret, "\"", 3);
return ret;
}
@@ -412,8 +411,8 @@ char *rdata_text_to_string(knot_rdata_item_t item)
char del[2];
del[0] = ' ';
del[1] = '\0';
- strcat(ret, txt);
- strcat(ret, del);
+ strncat(ret, txt, strlen(txt));
+ strncat(ret, del, 2);
free(txt);
}
@@ -423,7 +422,7 @@ char *rdata_text_to_string(knot_rdata_item_t item)
char *rdata_byte_to_string(knot_rdata_item_t item)
{
assert(item.raw_data[0] == 1);
- uint8_t data = item.raw_data[1];
+ uint8_t data = *((uint8_t *)(item.raw_data + 1));
char *ret = malloc(sizeof(char) * U8_MAX_STR_LEN);
snprintf(ret, U8_MAX_STR_LEN, "%d", (char) data);
return ret;
@@ -629,7 +628,7 @@ char *rdata_nsap_to_string(knot_rdata_item_t item)
return NULL;
}
- strcat(ret, converted);
+ strncat(ret, converted, rdata_item_size(item) * 2 + 1);
free(converted);
return ret;
}
@@ -729,9 +728,10 @@ char *rdata_services_to_string(knot_rdata_item_t item)
if (proto) {
int i;
- strcpy(ret, proto->p_name);
+ /*!< \todo #1863 see below, but we can trust getprotobynumber... */
+ strncpy(ret, proto->p_name, strlen(proto->p_name));
- strcat(ret, " ");
+ strncat(ret, " ", 2);
for (i = 0; i < bitmap_size * 8; ++i) {
if (get_bit(bitmap, i)) {
@@ -739,13 +739,20 @@ char *rdata_services_to_string(knot_rdata_item_t item)
getservbyport((int)htons(i),
proto->p_name);
if (service) {
- strcat(ret, service->s_name);
- strcat(ret, " ");
+ /*!< \todo #1863
+ * using strncat with strlen
+ * does not make a whole lot of sense.
+ * At least it will crash wil
+ * Use max length of service name!
+ */
+ strncat(ret, service->s_name,
+ strlen(service->s_name));
+ strncat(ret, " ", 2);
} else {
char tmp[U32_MAX_STR_LEN];
snprintf(tmp, U32_MAX_STR_LEN,
"%d ", i);
- strcat(ret, tmp);
+ strncat(ret, tmp, U32_MAX_STR_LEN);
}
}
}
@@ -832,8 +839,9 @@ char *rdata_nxt_to_string(knot_rdata_item_t item)
for (i = 0; i < bitmap_size * 8; ++i) {
if (get_bit(bitmap, i)) {
- strcat(ret, knot_rrtype_to_string(i));
- strcat(ret, " ");
+ strncat(ret, knot_rrtype_to_string(i),
+ MAX_RR_TYPE_LEN);
+ strncat(ret, " ", 2);
}
}
@@ -871,10 +879,11 @@ char *rdata_nsec_to_string(knot_rdata_item_t item)
for (int j = 0; j < bitmap_size * 8; j++) {
if (get_bit(bitmap, j)) {
- strcat(ret,
+ strncat(ret,
knot_rrtype_to_string(j +
- window * 256));
- strcat(ret, " ");
+ window * 256),
+ MAX_RR_TYPE_LEN);
+ strncat(ret, " ", 2);
}
}
@@ -925,7 +934,7 @@ char *rdata_unknown_to_string(knot_rdata_item_t item)
strlen("\\# ") + U16_MAX_STR_LEN + 1, "%lu ",
(unsigned long) size);
char *converted = hex_to_string(rdata_item_data(item), size);
- strcat(ret, converted);
+ strncat(ret, converted, size * 2 + 1);
free(converted);
return ret;
}
@@ -1131,9 +1140,9 @@ void node_dump_text(knot_node_t *node, void *data)
free(rrsets);
}
-int zone_dump_text(knot_zone_contents_t *zone, const char *filename)
+int zone_dump_text(knot_zone_contents_t *zone, int fd)
{
- FILE *f = fopen(filename, "w");
+ FILE *f = fdopen(fd, "w");
if (f == NULL) {
return KNOT_EBADARG;
}
diff --git a/src/knot/zone/zone-dump-text.h b/src/knot/zone/zone-dump-text.h
index 70dcff4..2a35643 100644
--- a/src/knot/zone/zone-dump-text.h
+++ b/src/knot/zone/zone-dump-text.h
@@ -34,12 +34,12 @@
* \brief Dumps given zone to text (BIND-like) file.
*
* \param zone Zone to be saved.
- * \param filename Name of file to be created.
+ * \param fd File descriptor to write to.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EBADARG if the specified file is not valid for writing.
*/
-int zone_dump_text(knot_zone_contents_t *zone, const char *filename);
+int zone_dump_text(knot_zone_contents_t *zone, int fd);
#endif // _KNOT_ZONE_DUMP_TEXT_H_
diff --git a/src/knot/zone/zone-dump.c b/src/knot/zone/zone-dump.c
index 0be1ac7..6ca969f 100644
--- a/src/knot/zone/zone-dump.c
+++ b/src/knot/zone/zone-dump.c
@@ -51,16 +51,15 @@
* or raw data stored like this: data_len [data]
*/
-static inline int fwrite_to_file_crc(const void *src,
- size_t size, size_t n, FILE *f,
+static inline int write_to_file_crc(const void *src,
+ size_t size, size_t n, int fd,
crc_t *crc)
{
- size_t rc = fwrite(src, size, n, f);
- if (rc != n) {
+ ssize_t rc = write(fd, src, size * n);
+ if (rc != size * n) {
fprintf(stderr, "fwrite: invalid write %zu (expected %zu)\n", rc,
n);
}
- /* \todo this seems to be wrong, if you fwrite less than n items, you probably should not continue */
if (size * n > 0) {
*crc =
@@ -68,13 +67,16 @@ static inline int fwrite_to_file_crc(const void *src,
size * n);
}
- /* \todo the rc return is certainly wrong as it is used in the caller function */
-// return rc == n;
- return (int)rc;
+ /*
+ * It was meant differtely, caller function does not
+ * care how many bytes had been written, it just cares about
+ * success/fail (not that it is checked anyway) (#1684).
+ */
+ return rc == n;
}
-static inline int fwrite_to_stream(const void *src,
+static inline int write_to_stream(const void *src,
size_t size, size_t n,
uint8_t **stream,
size_t *stream_size)
@@ -97,17 +99,17 @@ static inline int fwrite_to_stream(const void *src,
return KNOT_EOK;
}
-static int fwrite_wrapper(const void *src,
- size_t size, size_t n, FILE *fp,
+static int write_wrapper(const void *src,
+ size_t size, size_t n, int fd,
uint8_t **stream, size_t *stream_size, crc_t *crc)
{
- if (fp == NULL) {
+ if (fd < 0) {
assert(stream && stream_size);
assert(crc == NULL);
- return fwrite_to_stream(src, size, n, stream, stream_size);
+ return write_to_stream(src, size, n, stream, stream_size);
} else {
assert(stream == NULL && stream_size == NULL);
- return fwrite_to_file_crc(src, size, n, fp, crc);
+ return write_to_file_crc(src, size, n, fd, crc);
}
}
@@ -117,17 +119,17 @@ static int fwrite_wrapper(const void *src,
* \param dname Dname whose labels are to be dumped.
* \param f Output file.
*/
-static void knot_labels_dump_binary(const knot_dname_t *dname, FILE *f,
+static void knot_labels_dump_binary(const knot_dname_t *dname, int fd,
uint8_t **stream, size_t *stream_size,
crc_t *crc)
{
dbg_zdump("label count: %d\n", dname->label_count);
uint16_t label_count = dname->label_count;
- /* \todo check the return value */
- fwrite_wrapper(&label_count, sizeof(label_count), 1, f, stream,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&label_count, sizeof(label_count), 1, fd, stream,
stream_size, crc);
- /* \todo check the return value */
- fwrite_wrapper(dname->labels, sizeof(uint8_t), dname->label_count, f,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(dname->labels, sizeof(uint8_t), dname->label_count, fd,
stream, stream_size, crc);
}
@@ -137,31 +139,31 @@ static void knot_labels_dump_binary(const knot_dname_t *dname, FILE *f,
* \param dname Dname to be dumped.
* \param f Output file.
*/
-static void knot_dname_dump_binary(const knot_dname_t *dname, FILE *f,
+static void knot_dname_dump_binary(const knot_dname_t *dname, int fd,
uint8_t **stream, size_t *stream_size,
crc_t *crc)
{
uint32_t dname_size = dname->size;
- /* \todo check the return value */
- fwrite_wrapper(&dname_size, sizeof(dname_size), 1, f, stream,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&dname_size, sizeof(dname_size), 1, fd, stream,
stream_size, crc);
- /* \todo check the return value */
- fwrite_wrapper(dname->name, sizeof(uint8_t), dname->size, f,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(dname->name, sizeof(uint8_t), dname->size, fd,
stream, stream_size, crc);
dbg_zdump("dname size: %d\n", dname->size);
- knot_labels_dump_binary(dname, f, stream, stream_size, crc);
+ knot_labels_dump_binary(dname, fd, stream, stream_size, crc);
}
-/*!< \todo some global variable indicating error! */
-static void dump_dname_with_id(const knot_dname_t *dname, FILE *f,
+/*!< \todo #1684 some global variable indicating error! */
+static void dump_dname_with_id(const knot_dname_t *dname, int fd,
uint8_t **stream, size_t *stream_size,
crc_t *crc)
{
uint32_t id = dname->id;
- /* \todo check the return value */
- fwrite_wrapper(&id, sizeof(id), 1, f, stream, stream_size, crc);
- knot_dname_dump_binary(dname, f, stream, stream_size, crc);
-/* if (!fwrite_wrapper_safe(&dname->id, sizeof(dname->id), 1, f)) {
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&id, sizeof(id), 1, fd, stream, stream_size, crc);
+ knot_dname_dump_binary(dname, fd, stream, stream_size, crc);
+/* if (!write_wrapper_safe(&dname->id, sizeof(dname->id), 1, f)) {
return KNOT_ERROR;
} */
}
@@ -174,11 +176,10 @@ static void dump_dname_with_id(const knot_dname_t *dname, FILE *f,
* \param data Arguments to be propagated.
*/
static void knot_rdata_dump_binary(knot_rdata_t *rdata,
- uint32_t type, void *data, int use_ids,
+ uint32_t type, int fd, int use_ids,
uint8_t **stream, size_t *stream_size,
crc_t *crc)
{
- FILE *f = (FILE *)((arg_t *)data)->arg1;
knot_rrtype_descriptor_t *desc =
knot_rrtype_descriptor_by_type(type);
assert(desc != NULL);
@@ -190,9 +191,9 @@ static void knot_rdata_dump_binary(knot_rdata_t *rdata,
}
/* Write rdata count. */
- /* \todo check the return value */
- fwrite_wrapper(&(rdata->count),
- sizeof(rdata->count), 1, f, stream, stream_size, crc);
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&(rdata->count),
+ sizeof(rdata->count), 1, fd, stream, stream_size, crc);
for (int i = 0; i < rdata->count; i++) {
if (&(rdata->items[i]) == NULL) {
@@ -215,48 +216,46 @@ static void knot_rdata_dump_binary(knot_rdata_t *rdata,
if (use_ids) {
/* Write ID. */
- dbg_zload("%s \n",
- knot_dname_to_str(rdata->items[i].dname));
assert(rdata->items[i].dname->id != 0);
uint32_t id = rdata->items[i].dname->id;
- /* \todo check the return value */
- fwrite_wrapper(&id,
- sizeof(id), 1, f, stream, stream_size,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&id,
+ sizeof(id), 1, fd, stream, stream_size,
crc);
} else {
// assert(rdata->items[i].dname->id != 0);
dump_dname_with_id(rdata->items[i].dname,
- f, stream,
+ fd, stream,
stream_size, crc);
}
/* Write in the zone bit */
if (rdata->items[i].dname->node != NULL && !wildcard) {
- /* \todo check the return value */
- fwrite_wrapper((uint8_t *)"\1",
- sizeof(uint8_t), 1, f, stream,
+ /*!< \todo #1684 check the return value */
+ write_wrapper((uint8_t *)"\1",
+ sizeof(uint8_t), 1, fd, stream,
stream_size, crc);
} else {
- /* \todo check the return value */
- fwrite_wrapper((uint8_t *)"\0", sizeof(uint8_t),
- 1, f, stream, stream_size, crc);
+ /*!< \todo #1684 check the return value */
+ write_wrapper((uint8_t *)"\0", sizeof(uint8_t),
+ 1, fd, stream, stream_size, crc);
}
if (use_ids && wildcard) {
- /* \todo check the return value */
- fwrite_wrapper((uint8_t *)"\1",
- sizeof(uint8_t), 1, f, stream,
+ /*!< \todo #1684 check the return value */
+ write_wrapper((uint8_t *)"\1",
+ sizeof(uint8_t), 1, fd, stream,
stream_size, crc);
uint32_t wildcard_id = wildcard->id;
- /* \todo check the return value */
- fwrite_wrapper(&wildcard_id,
- sizeof(wildcard_id), 1, f, stream,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&wildcard_id,
+ sizeof(wildcard_id), 1, fd, stream,
stream_size, crc);
} else {
- /* \todo check the return value */
- fwrite_wrapper((uint8_t *)"\0", sizeof(uint8_t),
- 1, f, stream,
+ /*!< \todo #1684 check the return value */
+ write_wrapper((uint8_t *)"\0", sizeof(uint8_t),
+ 1, fd, stream,
stream_size, crc);
}
@@ -264,10 +263,10 @@ static void knot_rdata_dump_binary(knot_rdata_t *rdata,
dbg_zdump("Writing raw data. Item nr.: %d\n",
i);
assert(rdata->items[i].raw_data != NULL);
- /* \todo check the return value */
- fwrite_wrapper(rdata->items[i].raw_data,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(rdata->items[i].raw_data,
sizeof(uint8_t),
- rdata->items[i].raw_data[0] + 2, f,
+ rdata->items[i].raw_data[0] + 2, fd,
stream, stream_size, crc);
dbg_zdump("Written %d long raw data\n",
@@ -282,22 +281,25 @@ static void knot_rdata_dump_binary(knot_rdata_t *rdata,
* \param rrsig RRSIG to be dumped.
* \param data Arguments to be propagated.
*/
-static void knot_rrsig_set_dump_binary(knot_rrset_t *rrsig, arg_t *data,
+static void knot_rrsig_set_dump_binary(knot_rrset_t *rrsig, int fd,
int use_ids,
uint8_t **stream, size_t *stream_size,
crc_t *crc)
{
- dbg_zdump("Dumping rrset \\w owner: %s\n",
- knot_dname_to_str(rrsig->owner));
+dbg_zdump_exec_detail(
+ char *name = knot_dname_to_str(knot_rrset_owner(rrsig));
+ dbg_zdump("Dumping RRSIG \\w owner: %s\n",
+ name);
+ free(name);
+);
assert(rrsig->type == KNOT_RRTYPE_RRSIG);
assert(rrsig->rdata);
- FILE *f = (FILE *)((arg_t *)data)->arg1;
- /* \todo check the return value */
- fwrite_wrapper(&rrsig->type, sizeof(rrsig->type), 1, f,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&rrsig->type, sizeof(rrsig->type), 1, fd,
stream, stream_size, crc);
- fwrite_wrapper(&rrsig->rclass, sizeof(rrsig->rclass), 1, f,
+ write_wrapper(&rrsig->rclass, sizeof(rrsig->rclass), 1, fd,
stream, stream_size, crc);
- fwrite_wrapper(&rrsig->ttl, sizeof(rrsig->ttl), 1, f,
+ write_wrapper(&rrsig->ttl, sizeof(rrsig->ttl), 1, fd,
stream, stream_size, crc);
uint32_t rdata_count = 1;
@@ -308,16 +310,16 @@ static void knot_rrsig_set_dump_binary(knot_rrset_t *rrsig, arg_t *data,
rdata_count++;
}
- fwrite_wrapper(&rdata_count, sizeof(rdata_count), 1, f,
+ write_wrapper(&rdata_count, sizeof(rdata_count), 1, fd,
stream, stream_size, crc);
tmp_rdata = rrsig->rdata;
while (tmp_rdata->next != rrsig->rdata) {
- knot_rdata_dump_binary(tmp_rdata, KNOT_RRTYPE_RRSIG, data,
+ knot_rdata_dump_binary(tmp_rdata, KNOT_RRTYPE_RRSIG, fd,
use_ids, stream, stream_size, crc);
tmp_rdata = tmp_rdata->next;
}
- knot_rdata_dump_binary(tmp_rdata, KNOT_RRTYPE_RRSIG, data, use_ids,
+ knot_rdata_dump_binary(tmp_rdata, KNOT_RRTYPE_RRSIG, fd, use_ids,
stream, stream_size, crc);
}
@@ -327,23 +329,24 @@ static void knot_rrsig_set_dump_binary(knot_rrset_t *rrsig, arg_t *data,
* \param rrset RRSSet to be dumped.
* \param data Arguments to be propagated.
*/
-static void knot_rrset_dump_binary(const knot_rrset_t *rrset, void *data,
+static void knot_rrset_dump_binary(const knot_rrset_t *rrset, int fd,
int use_ids,
uint8_t **stream, size_t *stream_size,
crc_t *crc)
{
- FILE *f = (FILE *)((arg_t *)data)->arg1;
+ dbg_zdump_detail("zdump: rrset_dump_binary: Dumping rrset to fd=%d\n",
+ fd);
if (!use_ids) {
- dump_dname_with_id(rrset->owner, f, stream, stream_size, crc);
+ dump_dname_with_id(rrset->owner, fd, stream, stream_size, crc);
}
- /* \todo check the return value */
- fwrite_wrapper(&rrset->type, sizeof(rrset->type), 1, f,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&rrset->type, sizeof(rrset->type), 1, fd,
stream, stream_size, crc);
- fwrite_wrapper(&rrset->rclass, sizeof(rrset->rclass), 1, f,
+ write_wrapper(&rrset->rclass, sizeof(rrset->rclass), 1, fd,
stream, stream_size, crc);
- fwrite_wrapper(&rrset->ttl, sizeof(rrset->ttl), 1, f,
+ write_wrapper(&rrset->ttl, sizeof(rrset->ttl), 1, fd,
stream, stream_size, crc);
uint32_t rdata_count = 1;
@@ -356,26 +359,30 @@ static void knot_rrset_dump_binary(const knot_rrset_t *rrset, void *data,
rdata_count++;
}
- fwrite_wrapper(&rdata_count, sizeof(rdata_count), 1, f,
+ write_wrapper(&rdata_count, sizeof(rdata_count), 1, fd,
stream, stream_size, crc);
- fwrite_wrapper(&has_rrsig, sizeof(has_rrsig), 1, f,
+ write_wrapper(&has_rrsig, sizeof(has_rrsig), 1, fd,
stream, stream_size, crc);
+
+ dbg_zdump_detail("zdump: rrset_dump_binary: Static data dumped.\n");
tmp_rdata = rrset->rdata;
while (tmp_rdata->next != rrset->rdata) {
- knot_rdata_dump_binary(tmp_rdata, rrset->type, data, use_ids,
+ knot_rdata_dump_binary(tmp_rdata, rrset->type, fd, use_ids,
stream, stream_size, crc);
tmp_rdata = tmp_rdata->next;
}
- knot_rdata_dump_binary(tmp_rdata, rrset->type, data, use_ids,
+ knot_rdata_dump_binary(tmp_rdata, rrset->type, fd, use_ids,
stream, stream_size, crc);
+
+ dbg_zdump_detail("zdump: rrset_dump_binary: Rdata dumped.\n");
/* This is now obsolete, although I'd rather not use recursion - that
* would probably not work */
if (rrset->rrsigs != NULL) {
- knot_rrsig_set_dump_binary(rrset->rrsigs, data, use_ids,
+ knot_rrsig_set_dump_binary(rrset->rrsigs, fd, use_ids,
stream, stream_size, crc);
}
}
@@ -386,38 +393,42 @@ static void knot_rrset_dump_binary(const knot_rrset_t *rrset, void *data,
* \param node Node to dumped.
* \param data Arguments to be propagated.
*/
-static void knot_node_dump_binary(knot_node_t *node, void *data,
+static void knot_node_dump_binary(knot_node_t *node, int fd,
uint8_t **stream, size_t *stream_size,
crc_t *crc)
{
- arg_t *args = (arg_t *)data;
- FILE *f = (FILE *)args->arg1;
-
-// node_count++;
+ if (node == NULL) {
+ return;
+ }
+
/* first write dname */
assert(node->owner != NULL);
/* Write owner ID. */
+dbg_zdump_exec_detail(
+ char *name = knot_dname_to_str(knot_node_owner(node));
dbg_zdump("Dumping node owned by %s\n",
- knot_dname_to_str(node->owner));
+ name);
+ free(name);
+);
assert(node->owner->id != 0);
uint32_t owner_id = node->owner->id;
- /* \todo check the return value */
- fwrite_wrapper(&owner_id, sizeof(owner_id), 1, f, stream, stream_size,
+ /*!< \todo #1684 check the return value */
+ write_wrapper(&owner_id, sizeof(owner_id), 1, fd, stream, stream_size,
crc);
if (knot_node_parent(node) != NULL) {
uint32_t parent_id = knot_dname_id(
knot_node_owner(knot_node_parent(node)));
- fwrite_wrapper(&parent_id, sizeof(parent_id), 1, f,
+ write_wrapper(&parent_id, sizeof(parent_id), 1, fd,
stream, stream_size, crc);
} else {
uint32_t parent_id = 0;
- fwrite_wrapper(&parent_id, sizeof(parent_id), 1, f,
+ write_wrapper(&parent_id, sizeof(parent_id), 1, fd,
stream, stream_size, crc);
}
- fwrite_wrapper(&(node->flags), sizeof(node->flags), 1, f,
+ write_wrapper(&(node->flags), sizeof(node->flags), 1, fd,
stream, stream_size, crc);
dbg_zdump("Written flags: %u\n", node->flags);
@@ -425,13 +436,13 @@ static void knot_node_dump_binary(knot_node_t *node, void *data,
if (knot_node_nsec3_node(node) != NULL) {
uint32_t nsec3_id =
knot_node_owner(knot_node_nsec3_node(node))->id;
- fwrite_wrapper(&nsec3_id, sizeof(nsec3_id), 1, f,
+ write_wrapper(&nsec3_id, sizeof(nsec3_id), 1, fd,
stream, stream_size, crc);
dbg_zdump("Written nsec3 node id: %u\n",
knot_node_owner(knot_node_nsec3_node(node))->id);
} else {
uint32_t nsec3_id = 0;
- fwrite_wrapper(&nsec3_id, sizeof(nsec3_id), 1, f,
+ write_wrapper(&nsec3_id, sizeof(nsec3_id), 1, fd,
stream, stream_size, crc);
}
@@ -439,37 +450,18 @@ static void knot_node_dump_binary(knot_node_t *node, void *data,
* but that number is yet unknown */
uint16_t rrset_count = node->rrset_count;
- fwrite_wrapper(&rrset_count, sizeof(rrset_count), 1, f,
+ write_wrapper(&rrset_count, sizeof(rrset_count), 1, fd,
stream, stream_size, crc);
- /* CLEANUP */
-// const skip_node_t *skip_node = skip_first(node->rrsets);
-
const knot_rrset_t **node_rrsets = knot_node_rrsets(node);
for (int i = 0; i < rrset_count; i++)
{
- knot_rrset_dump_binary(node_rrsets[i], data, 1,
+ knot_rrset_dump_binary(node_rrsets[i], fd, 1,
stream, stream_size, crc);
}
- /* CLEANUP */
-// if (skip_node == NULL) {
-// /* we can return, count is set to 0 */
-// return;
-// }
-
-// knot_rrset_t *tmp;
-
-// do {
-// tmp = (knot_rrset_t *)skip_node->value;
-// knot_rrset_dump_binary(tmp, data, 1);
-// } while ((skip_node = skip_next(skip_node)) != NULL);
-
free(node_rrsets);
- dbg_zdump("Position after all rrsets: %ld\n", ftell(f));
- dbg_zdump("Writing here: %ld\n", ftell(f));
- dbg_zdump("Function ends with: %ld\n\n", ftell(f));
}
int zone_is_secure(knot_zone_contents_t *zone)
@@ -487,50 +479,32 @@ int zone_is_secure(knot_zone_contents_t *zone)
}
}
-/*!
- * \brief Safe wrapper around fwrite.
- *
- * \param dst Destination pointer.
- * \param size Size of element to be written.
- * \param n Number of elements to be written.
- * \param fp File to write to.
- *
- * \retval > 0 if succesfull.
- * \retval 0 if failed.
- */
-//static inline int fwrite_wrapper_safe(const void *src,
-// size_t size, size_t n, FILE *fp)
-//{
-// int rc = fwrite_wrapper(src, size, n, fp);
-// if (rc != n) {
-// fprintf(stderr, "fwrite_wrapper: invalid write %d (expected %zu)\n", rc,
-// n);
-// }
-
-// return rc == n;
-//}
-
static void dump_dname_from_tree(knot_dname_t *dname,
void *data)
{
arg_t *arg = (arg_t *)data;
- FILE *f = (FILE *)arg->arg1;
+ int *fd_pointer = (int *)arg->arg1;
+ int fd = -1;
+ if (fd_pointer != NULL) {
+ fd = *fd_pointer;
+ } else {
+ dbg_zdump("zdump: dump_dname_from_tree: Bad fd.\n");
+ return;
+ }
+
crc_t *crc = (crc_t*)arg->arg2;
- dump_dname_with_id(dname, f, NULL, NULL, crc);
+ dump_dname_with_id(dname, fd, NULL, NULL, crc);
}
static int knot_dump_dname_table(const knot_dname_table_t *dname_table,
- FILE *f, crc_t *crc)
+ int fd, crc_t *crc)
{
arg_t arg;
- arg.arg1 = f;
+ arg.arg1 = &fd;
arg.arg2 = crc;
/* Go through the tree and dump each dname along with its ID. */
knot_dname_table_tree_inorder_apply(dname_table,
dump_dname_from_tree, &arg);
- /* CLEANUP */
-// TREE_FORWARD_APPLY(dname_table->tree, dname_table_node, avl,
-// dump_dname_from_tree, (void *)f);
return KNOT_EOK;
}
@@ -550,10 +524,16 @@ static void save_node_from_tree(knot_node_t *node, void *data)
static void dump_node_to_file(knot_node_t *node, void *data)
{
arg_t *arg = (arg_t *)data;
- knot_node_dump_binary(node, data, NULL, NULL, (crc_t *)arg->arg7);
+ int *fd_pointer = (int *)arg->arg1;
+ int fd = -1;
+ if (fd_pointer != NULL) {
+ fd = *fd_pointer;
+ }
+
+ knot_node_dump_binary(node, fd, NULL, NULL, (crc_t *)arg->arg7);
}
-static char *knot_zdump_crc_file(const char* filename)
+char *knot_zdump_crc_file(const char* filename)
{
char *crc_path =
malloc(sizeof(char) * (strlen(filename) +
@@ -564,31 +544,18 @@ static char *knot_zdump_crc_file(const char* filename)
strlen(".crc") + 1));
memcpy(crc_path, filename,
sizeof(char) * strlen(filename));
- crc_path = strcat(crc_path, ".crc");
+ crc_path = strncat(crc_path, ".crc", strlen(".crc"));
return crc_path;
}
-int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
- int do_checks, const char *sfilename)
+int knot_zdump_binary(knot_zone_contents_t *zone, int fd,
+ int do_checks, const char *sfilename,
+ crc_t *crc)
{
- /* Open .new file. */
- char new_path[strlen(filename) + strlen(".new") + 1];
- memcpy(new_path, filename, strlen(filename) + 1);
- strcat(new_path, ".new");
- 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));
+ if (fd < 0 || sfilename == NULL) {
return KNOT_EBADARG;
}
- FILE *f = fdopen(fd, "wb");
- assert(f);
-
- /* CLEANUP */
-// skip_list_t *encloser_list = skip_create_list(compare_pointers);
arg_t arguments;
/* Memory to be derefenced in the save_node_from_tree function. */
uint32_t node_count = 0;
@@ -615,7 +582,8 @@ 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);
}
-
+
+ /* FIXME(OS): Really descriptive call 1,1,1,1, some #defines here? */
err_handler_t *handler = handler_new(1, 1, 1, 1, 1);
if (handler == NULL) {
return KNOT_ENOMEM;
@@ -640,154 +608,60 @@ int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
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();
+ *crc = crc_init();
/* Start writing header - magic bytes. */
static const uint8_t MAGIC[MAGIC_LENGTH] = MAGIC_BYTES;
- fwrite_wrapper(&MAGIC, sizeof(uint8_t), MAGIC_LENGTH, f, NULL, NULL,
- &crc);
+ write_wrapper(&MAGIC, sizeof(uint8_t), MAGIC_LENGTH, fd, NULL, NULL,
+ crc);
/* Write source file length. */
- uint32_t sflen = 0;
- if (sfilename) {
- sflen = strlen(sfilename) + 1;
- }
- fwrite_wrapper(&sflen, sizeof(uint32_t), 1, f, NULL, NULL, &crc);
+ uint32_t sflen = strlen(sfilename) + 1;
+ write_wrapper(&sflen, sizeof(uint32_t), 1, fd, NULL, NULL, crc);
/* Write source file. */
- fwrite_wrapper(sfilename, sflen, 1, f, NULL, NULL, &crc);
+ write_wrapper(sfilename, sflen, 1, fd, NULL, NULL, crc);
/* Notice: End of header,
*/
/* Start writing compiled data. */
- fwrite_wrapper(&normal_node_count, sizeof(normal_node_count), 1, f,
- NULL, NULL, &crc);
- fwrite_wrapper(&nsec3_node_count, sizeof(nsec3_node_count), 1, f,
- NULL, NULL, &crc);
+ write_wrapper(&normal_node_count, sizeof(normal_node_count), 1, fd,
+ NULL, NULL, crc);
+ write_wrapper(&nsec3_node_count, sizeof(nsec3_node_count), 1, fd,
+ NULL, NULL, crc);
uint32_t auth_node_count = zone->node_count;
- fwrite_wrapper(&auth_node_count,
- sizeof(auth_node_count), 1, f, NULL, NULL, &crc);
+ write_wrapper(&auth_node_count,
+ sizeof(auth_node_count), 1, fd, NULL, NULL, crc);
/* Write total number of dnames */
assert(zone->dname_table);
uint32_t total_dnames = zone->dname_table->id_counter;
- fwrite_wrapper(&total_dnames,
- sizeof(total_dnames), 1, f, NULL, NULL, &crc);
+ write_wrapper(&total_dnames,
+ sizeof(total_dnames), 1, fd, NULL, NULL, crc);
/* Write dname table. */
- if (knot_dump_dname_table(zone->dname_table, f, &crc)
+ if (knot_dump_dname_table(zone->dname_table, fd, 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;
}
-
- arguments.arg1 = (void *)f;
+
+ arguments.arg1 = &fd;
arguments.arg3 = zone;
- arguments.arg7 = &crc;
+ arguments.arg7 = crc;
- /* TODO is there a way how to stop the traversal upon error? */
+ /*!< \todo #1685 Stop traversal upon error. */
knot_zone_contents_tree_apply_inorder(zone, dump_node_to_file,
(void *)&arguments);
knot_zone_contents_nsec3_apply_inorder(zone, dump_node_to_file,
(void *)&arguments);
- fclose(f);
-
- crc = crc_finalize(crc);
- /* Write CRC to separate .crc file. */
- /*!< \todo There is now function doing this. */
- char *crc_path =
- 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,
- sizeof(char) * (strlen(filename) + strlen(".crc") + 1));
- memcpy(crc_path, filename, sizeof(char) * strlen(filename));
-
- crc_path = strcat(crc_path, ".crc");
- FILE *f_crc = fopen(crc_path, "w");
- if (unlikely(!f_crc)) {
- 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;
- }
- free(crc_path);
-
- fprintf(f_crc, "%lu\n", (unsigned long)crc);
- fclose(f_crc);
-
- close(fd);
- mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- fd = open(filename, O_WRONLY | O_CREAT, mode);
- if (fd == -1) {
- 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;
- }
-
- /* Try to obtain exclusive lock for originally given file. */
- if (fcntl(fd, F_SETLK, knot_file_lock(F_WRLCK, SEEK_SET)) == -1) {
- 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;
- }
-
- /* Move .new file to original file. */
- if (rename(new_path, filename) != 0) {
- 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;
- }
-
- close(fd);
-
+ *crc = crc_finalize(*crc);
+
return KNOT_EOK;
}
@@ -796,74 +670,28 @@ int knot_zdump_rrset_serialize(const knot_rrset_t *rrset, uint8_t **stream,
{
if (stream == NULL || *stream != NULL || rrset == NULL ||
size == NULL) {
+ dbg_zdump("zdump: rrset_serialize: Bad arguments.\n");
return KNOT_EBADARG;
}
*size = 0;
arg_t arguments;
memset(&arguments, 0, sizeof(arg_t));
+
+ /* This fd will signal functions to use streams. */
+ int fd = -1;
- knot_rrset_dump_binary(rrset, &arguments, 0, stream, size, NULL);
+ knot_rrset_dump_binary(rrset, fd, 0, stream, size, NULL);
return KNOT_EOK;
}
-int knot_zdump_dump_and_swap(knot_zone_contents_t *zone,
- const char *temp_zonedb,
- const char *destination_zonedb,
- const char *sfilename)
+int knot_zdump_dump(knot_zone_contents_t *zone, int fd, const char *sfilename,
+ crc_t *crc)
{
- int rc = knot_zdump_binary(zone, temp_zonedb, 0, sfilename);
-
+ int rc = knot_zdump_binary(zone, fd, 0, sfilename, crc);
if (rc != KNOT_EOK) {
- dbg_zdump("Failed to save the zone to binary zone db %s."
- "\n", temp_zonedb);
- return KNOT_ERROR;
- }
-
- /*! \todo this would also need locking as well. */
- rc = remove(destination_zonedb);
- if (rc == 0 || (rc != 0 && errno == ENOENT)) {
-
- /* Delete old CRC file. */
- char *destination_zonedb_crc =
- knot_zdump_crc_file(destination_zonedb);
- if (destination_zonedb_crc == NULL) {
- return KNOT_ENOMEM;
- }
- remove(destination_zonedb_crc);
-
- /* Move CRC file. */
- char *temp_zonedb_crc =
- knot_zdump_crc_file(temp_zonedb);
- if (temp_zonedb_crc == NULL) {
- return KNOT_ENOMEM;
- }
-
- if (rename(temp_zonedb_crc, destination_zonedb_crc) != 0) {
- dbg_zdump("Failed to replace old zonedb CRC %s "
- "with new CRC zone file %s.\n",
- destination_zonedb_crc,
- temp_zonedb_crc);
- return KNOT_ERROR;
- }
- free(temp_zonedb_crc);
- free(destination_zonedb_crc);
-
- /* Rename zonedb. */
- if (rename(temp_zonedb, destination_zonedb) != 0) {
- dbg_zdump("Failed to replace old zonedb %s "
- "with new zone file %s.\n",
- temp_zonedb,
- destination_zonedb);
- /*! \todo with proper locking, this shouldn't happen,
- * revise it later on.
- */
- return KNOT_ERROR;
- }
- } else {
- dbg_zdump("Failed to replace old zonedb '%s'', %s.\n",
- destination_zonedb, strerror(errno));
+ dbg_zdump("Failed to save the zone to binary zone db\n.");
return KNOT_ERROR;
}
diff --git a/src/knot/zone/zone-dump.h b/src/knot/zone/zone-dump.h
index 97f1318..77a395c 100644
--- a/src/knot/zone/zone-dump.h
+++ b/src/knot/zone/zone-dump.h
@@ -44,15 +44,17 @@ enum {
* \brief Dumps given zone to binary file.
*
* \param zone Zone to be saved.
- * \param filename Name of file to be created.
+ * \param fd File descriptor to be written to.
* \param do_checks Set to 1 to enable checking the zone for semantic errors.
* \param sfilename Source filename of the text zone file.
+ * \param crc Returns a calculated CRC.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EBADARG if the file cannot be opened for writing.
*/
-int knot_zdump_binary(knot_zone_contents_t *zone, const char *filename,
- int do_checks, const char *sfilename);
+int knot_zdump_binary(knot_zone_contents_t *zone, int fd,
+ int do_checks, const char *sfilename,
+ crc_t *crc);
/*!
* \brief Serializes RRSet into binary stream. Expects NULL pointer, memory
@@ -95,10 +97,14 @@ int knot_zdump_rrset_serialize(const knot_rrset_t *rrset, uint8_t **stream,
*/
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,
- const char *sfilename);
+/*! \todo Document me (issue #1586). */
+int knot_zdump_dump(knot_zone_contents_t *zone, int fd, const char *sfilename,
+ crc_t *crc);
+
+/*!
+ * \brief Return name of the CRC file associated with filename.
+ */
+char *knot_zdump_crc_file(const char* filename);
#endif /* _KNOT_ZONEDUMP_H_ */
diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c
index 5710fe9..f64cfaa 100644
--- a/src/knot/zone/zone-load.c
+++ b/src/knot/zone/zone-load.c
@@ -235,6 +235,9 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
int use_ids)
{
knot_rdata_t *rdata = knot_rdata_new();
+ if (rdata == NULL) {
+ return NULL;
+ }
knot_rrtype_descriptor_t *desc =
knot_rrtype_descriptor_by_type(type);
@@ -246,6 +249,7 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
uint32_t rdata_count = 0;
if(!fread_wrapper(&rdata_count, sizeof(rdata_count), 1, f)) {
+ knot_rdata_free(&rdata);
return NULL;
}
@@ -267,7 +271,9 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ) {
- /* TODO maybe this does not need to be stored this big*/
+ /*!< \todo #1686
+ * Refactor these variables, some might be too big.
+ */
uint32_t dname_id = 0;
uint8_t has_wildcard = 0;
@@ -321,8 +327,9 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
load_rdata_purge(rdata, items, i, desc, type);
return NULL;
}
-
- items[i].raw_data =
+
+ /*!< \todo this is not proper fix, see #1678 */
+ items[i].raw_data = (uint16_t *)
malloc(sizeof(uint8_t) * (raw_data_length + 2));
items[i].raw_data[0] = raw_data_length;
@@ -441,35 +448,60 @@ static knot_rrset_t *knot_load_rrset(FILE *f, knot_dname_t **id_array,
}
if (!fread_wrapper(&rrset_type, sizeof(rrset_type), 1, f)) {
+ if (!use_ids) {
+ knot_dname_free(&owner);
+ }
return NULL;
}
dbg_zload("Zone load: rrset load: type: %u\n", rrset_type);
if (!fread_wrapper(&rrset_class, sizeof(rrset_class), 1, f)) {
+ if (!use_ids) {
+ knot_dname_free(&owner);
+ }
return NULL;
}
dbg_zload("Zone load: rrset class: type: %u\n", rrset_class);
if (!fread_wrapper(&rrset_ttl, sizeof(rrset_ttl), 1, f)) {
+ if (!use_ids) {
+ knot_dname_free(&owner);
+ }
return NULL;
}
dbg_zload("Zone load: rrset ttl: type: %u\n", rrset_ttl);
if (!fread_wrapper(&rdata_count, sizeof(rdata_count), 1, f)) {
+ if (!use_ids) {
+ knot_dname_free(&owner);
+ }
return NULL;
}
dbg_zload("Zone load: rrset load: rdata count: %u\n", rdata_count);
if (!fread_wrapper(&rrsig_count, sizeof(rrsig_count), 1, f)) {
+ if (!use_ids) {
+ knot_dname_free(&owner);
+ }
return NULL;
}
dbg_zload("Zone load: rrset load: type: %u\n", rrset_type);
+dbg_zload_exec_detail(
+ char *name = knot_dname_to_str(owner);
dbg_zload("Loading RRSet owned by: %s\n",
- knot_dname_to_str(owner));
+ name);
+ free(name);
+);
rrset = knot_rrset_new(owner, rrset_type, rrset_class, rrset_ttl);
+
+ if (rrset == NULL) {
+ dbg_zload("zload: load_rrset: Could not create rrset.");
+ knot_dname_free(&owner);
+ return NULL;
+ }
if (!use_ids) {
/* Directly release if allocated locally. */
knot_dname_release(owner);
- owner = 0;
+ owner = NULL;
}
dbg_zload("RRSet type: %d\n", rrset->type);
@@ -581,7 +613,9 @@ 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, 0);
- //TODO what else to free?
+ /*!< \todo #1686
+ * Refactor freeing, might not be enough.
+ */
fprintf(stderr, "zone: Could not load rrset.\n");
return NULL;
}
@@ -697,11 +731,12 @@ static unsigned long calculate_crc(FILE *f)
int knot_zload_open(zloader_t **dst, const char *filename)
{
- *dst = 0;
if (!dst || !filename) {
return KNOT_EBADARG;
}
+ *dst = 0;
+
fread_wrapper = fread_safe_from_file;
/* Open file for binary read. */
@@ -727,7 +762,7 @@ int knot_zload_open(zloader_t **dst, const char *filename)
memcpy(crc_path, filename, sizeof(char) * strlen(filename));
- crc_path = strcat(crc_path, ".crc");
+ crc_path = strncat(crc_path, ".crc", strlen(".crc"));
FILE *f_crc = fopen(crc_path, "r");
if (unlikely(!f_crc)) {
dbg_zload("knot_zload_open: failed to open '%s'\n",
@@ -738,7 +773,7 @@ int knot_zload_open(zloader_t **dst, const char *filename)
}
unsigned long crc_from_file = 0;
- if (fscanf(f_crc, "%lu\n", &crc_from_file) != 1) {
+ if (fscanf(f_crc, "%64lu\n", &crc_from_file) != 1) {
dbg_zload("knot_zload_open: could not read "
"CRC from file '%s'\n",
crc_path);
@@ -893,12 +928,13 @@ static knot_dname_t **create_dname_array(FILE *f, uint max_id)
knot_dname_t **array =
malloc(sizeof(knot_dname_t *) * ( max_id + 1));
- memset(array, 0, sizeof(knot_dname_t *) * (max_id + 1));
if (array == NULL) {
ERR_ALLOC_FAILED;
return NULL;
}
+ memset(array, 0, sizeof(knot_dname_t *) * (max_id + 1));
+
for (uint i = 0; i < max_id - 1; i++) {
knot_dname_t *read_dname = read_dname_with_id(f);
if (read_dname == NULL) {
@@ -948,14 +984,6 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
knot_node_t *tmp_node;
- /* Load the dname table. */
- /* CLEANUP */
-// const knot_dname_table_t *dname_table =
-// create_dname_table(f, total_dnames);
-// if (dname_table == NULL) {
-// return NULL;
-// }
-
uint32_t node_count;
uint32_t nsec3_node_count;
uint32_t auth_node_count;
@@ -997,6 +1025,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
if (dname_table == NULL) {
ERR_ALLOC_FAILED;
cleanup_id_array(id_array, 1, total_dnames);
+ free(dname_table);
return NULL;
}
@@ -1007,6 +1036,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
loader->filename);
cleanup_id_array(id_array, 1,
node_count + nsec3_node_count + 1);
+ free(dname_table);
return NULL;
}
@@ -1017,6 +1047,8 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
cleanup_id_array(id_array, 1,
node_count + nsec3_node_count + 1);
dbg_zload("Failed to create new zone from apex!\n");
+ knot_node_free(&apex, 0);
+ free(dname_table);
return NULL;
}
@@ -1026,8 +1058,6 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
/* Assign dname table to the new zone. */
contents->dname_table = dname_table;
- /* CLEANUP */
-// apex->prev = NULL;
knot_node_set_previous(apex, NULL);
knot_node_t *last_node = 0;
@@ -1049,8 +1079,6 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
}
knot_node_set_previous(tmp_node, last_node);
- /* CLEANUP */
-// tmp_node->prev = last_node;
if (tmp_node->rrset_count &&
(knot_node_is_deleg_point(tmp_node) ||
@@ -1083,16 +1111,12 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
fprintf(stderr, "!! cannot add first nsec3 node, "
"exiting.\n");
knot_zone_deep_free(&zone, 0);
- free(id_array);
- /* TODO this will leak dnames from id_array that were
- * not assigned. */
+ cleanup_id_array(id_array, node_count + 1,
+ nsec3_node_count + 1);
return NULL;
}
knot_node_set_previous(nsec3_first, NULL);
- /* CLEANUP */
-// nsec3_first->prev = NULL;
-
last_node = nsec3_first;
}
@@ -1107,8 +1131,6 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
}
knot_node_set_previous(tmp_node, last_node);
- /* CLEANUP */
-// tmp_node->prev = last_node;
last_node = tmp_node;
} else {
@@ -1120,8 +1142,6 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
if (nsec3_node_count) {
assert(knot_node_previous(nsec3_first) == NULL);
knot_node_set_previous(nsec3_first, last_node);
- /* CLEANUP */
-// nsec3_first->prev = last_node;
}
/* ID array is now useless */
@@ -1133,12 +1153,6 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
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 e4b7d5f..0ab3d11 100644
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -500,8 +500,19 @@ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire,
if (knot_wire_is_pointer(wire + p)) {
// pointer.
+
// printf("Pointer.\n");
- p = knot_wire_get_pointer(wire + p);
+ size_t ptr = knot_wire_get_pointer(wire + p);
+
+ /* Check that the pointer points backwards
+ * otherwise it could result in infinite loop
+ */
+ if (ptr >= p) {
+ return NULL;
+ }
+
+ p = ptr;
+
if (!pointer_used) {
*pos += 2;
pointer_used = 1;
@@ -817,9 +828,9 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname)
void knot_dname_left_chop_no_copy(knot_dname_t *dname)
{
// copy the name
- short first_label_length = dname->labels[1];
-
if (dname->label_count > 1) {
+ short first_label_length = dname->labels[1];
+
memmove(dname->name, &dname->name[dname->labels[1]],
dname->size - first_label_length);
// adjust labels
diff --git a/src/libknot/dname.h b/src/libknot/dname.h
index bb5e2db..5a182ae 100644
--- a/src/libknot/dname.h
+++ b/src/libknot/dname.h
@@ -45,15 +45,17 @@ struct knot_node;
struct knot_dname {
ref_t ref; /*!< Reference counting. */
uint8_t *name; /*!< Wire format of the domain name. */
+ uint8_t *labels;
+ struct knot_node *node; /*!< Zone node the domain name belongs to. */
+ unsigned int id; /*!< ID of domain name used in zone dumping. */
+
/*!
* \brief Size of the domain name in octets.
* \todo Is this needed? Every dname should end with \0 or pointer.
*/
unsigned int size;
- uint8_t *labels;
+
unsigned short label_count;
- struct knot_node *node; /*!< Zone node the domain name belongs to. */
- unsigned int id; /*!< ID of domain name used in zone dumping. */
};
typedef struct knot_dname knot_dname_t;
diff --git a/src/libknot/edns.c b/src/libknot/edns.c
index 435e27c..d12861c 100644
--- a/src/libknot/edns.c
+++ b/src/libknot/edns.c
@@ -428,9 +428,9 @@ 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);
+ knot_opt_option_t *option = &(opt_rr->options[i]);
+ if (option->data != NULL) {
+ free(option->data);
}
}
free(opt_rr->options);
diff --git a/src/libknot/hash/cuckoo-hash-table.c b/src/libknot/hash/cuckoo-hash-table.c
index 6688a40..73d1980 100644
--- a/src/libknot/hash/cuckoo-hash-table.c
+++ b/src/libknot/hash/cuckoo-hash-table.c
@@ -732,6 +732,7 @@ ck_hash_table_t *ck_create_table(uint items)
if (table->table_size_exp == 0) {
dbg_ck("Failed to count exponent of the hash table.\n");
+ free(table);
return NULL;
}
@@ -970,6 +971,8 @@ int ck_insert_item(ck_hash_table_t *table, const char *key,
dbg_ck("Table is full, resize needed.\n");
if (ck_resize_table(table) != 0) {
dbg_ck("Failed to resize hash table!\n");
+ free(new_item);
+ pthread_mutex_unlock(&table->mtx_table);
return -1;
}
}
@@ -994,6 +997,8 @@ int ck_insert_item(ck_hash_table_t *table, const char *key,
dbg_ck("Stash is full, resize needed.\n");
if (ck_resize_table(table) != 0) {
dbg_ck("Failed to resize hash table!\n");
+ /*! \todo Shouldn't 'new_item' be freed? */
+ pthread_mutex_unlock(&table->mtx_table);
return -1;
}
}
@@ -1332,35 +1337,48 @@ int ck_deep_copy(ck_hash_table_t *from, ck_hash_table_t **to)
}
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);
+// 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->item == NULL) {
+ si_new->item = NULL;
+ si_new->next = NULL;
+ } else {
+ 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;
- }
+ if (si_new->item == NULL) {
+ ERR_ALLOC_FAILED;
+ free(si_new);
+ ck_deep_copy_cleanup(*to, (*to)->table_count);
+ return -2;
+ }
- memcpy(si_new->item, si->item, sizeof(ck_hash_table_item_t));
+ memcpy(si_new->item, si->item,
+ sizeof(ck_hash_table_item_t));
+ si_new->next = NULL;
+ }
*pos = si_new;
pos = &si_new->next;
si = si->next;
-
+dbg_ck_exec(
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);
+ if (si != NULL && si->item != 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);
+ (si_new) ? si_new->item : NULL);
+
+ assert(si_new != NULL);
+ assert(si_new->item != NULL);
dbg_ck("key: %.*s\n", (int)si_new->item->key_length,
si_new->item->key);
+);
}
*pos = NULL;
diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c
index 547a629..dea16ec 100644
--- a/src/libknot/nameserver/name-server.c
+++ b/src/libknot/nameserver/name-server.c
@@ -625,6 +625,8 @@ static void ns_put_authority_ns(const knot_zone_contents_t *zone,
static int ns_put_authority_soa(const knot_zone_contents_t *zone,
knot_packet_t *resp)
{
+ int ret;
+
knot_rrset_t *soa_rrset = knot_node_get_rrset(
knot_zone_contents_apex(zone), KNOT_RRTYPE_SOA);
assert(soa_rrset != NULL);
@@ -634,7 +636,12 @@ static int ns_put_authority_soa(const knot_zone_contents_t *zone,
uint32_t min = knot_rdata_soa_minimum(knot_rrset_rdata(soa_rrset));
if (min < knot_rrset_ttl(soa_rrset)) {
knot_rrset_t *soa_copy = NULL;
- knot_rrset_deep_copy(soa_rrset, &soa_copy);
+ ret = knot_rrset_deep_copy(soa_rrset, &soa_copy);
+
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
CHECK_ALLOC_LOG(soa_copy, KNOT_ENOMEM);
knot_rrset_set_ttl(soa_copy, min);
@@ -643,13 +650,15 @@ static int ns_put_authority_soa(const knot_zone_contents_t *zone,
assert(soa_rrset != NULL);
- int ret = knot_response_add_rrset_authority(resp, soa_rrset, 0, 0, 0, 1);
- if (ret == KNOT_EOK) {
- ret = ns_add_rrsigs(soa_rrset, resp,
- knot_node_owner(knot_zone_contents_apex(zone)),
- knot_response_add_rrset_authority, 1);
+ ret = knot_response_add_rrset_authority(resp, soa_rrset, 0, 0, 0, 1);
+ if (ret != KNOT_EOK) {
+ return ret;
}
+ ret = ns_add_rrsigs(soa_rrset, resp,
+ knot_node_owner(knot_zone_contents_apex(zone)),
+ knot_response_add_rrset_authority, 1);
+
return ret;
}
@@ -2690,6 +2699,48 @@ knot_nameserver_t *knot_ns_create()
/*----------------------------------------------------------------------------*/
+static int knot_ns_replace_nsid(knot_opt_rr_t *opt_rr, const char *nsid,
+ size_t len)
+{
+ assert(opt_rr != NULL);
+ if (nsid == NULL || len == 0) {
+ return KNOT_EOK;
+ }
+
+ int found = 0;
+ int i = 0;
+
+ while (i < opt_rr->option_count && !found) {
+ if (opt_rr->options[i].code == EDNS_OPTION_NSID) {
+ found = 1;
+ } else {
+ ++i;
+ }
+ }
+
+ if (found) {
+ uint8_t *new_data = (uint8_t *)malloc(len);
+ if (new_data == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ memcpy(new_data, nsid, len);
+ uint8_t *old = opt_rr->options[i].data;
+
+ opt_rr->options[i].data = new_data;
+ opt_rr->options[i].length = len;
+
+ free(old);
+
+ return KNOT_EOK;
+ } else {
+ return knot_edns_add_option(opt_rr, EDNS_OPTION_NSID,
+ len, (const uint8_t *)nsid);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid, size_t len)
{
if (nameserver == NULL) {
@@ -2702,8 +2753,10 @@ void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid, size_t le
return;
}
- int ret = knot_edns_add_option(nameserver->opt_rr, EDNS_OPTION_NSID,
- len, (const uint8_t *)nsid);
+ int ret = knot_ns_replace_nsid(nameserver->opt_rr, nsid, len);
+
+// 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;
@@ -3326,7 +3379,7 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
}
// save the zone contents to the xfr->data
- xfr->data = zone;
+ xfr->new_contents = zone;
xfr->flags |= XFR_FLAG_AXFR_FINISHED;
assert(zone->nsec3_nodes != NULL);
@@ -3338,12 +3391,10 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
//knot_zone_contents_dump(zone, 0);
// check zone integrity
-#ifdef KNOT_XFRIN_DEBUG
-#ifdef DEBUG_ENABLE_BRIEF
+dbg_xfrin_exec(
int errs = knot_zone_contents_integrity_check(zone);
- dbg_ns("Zone integrity check: %d errors.\n", errs);
-#endif
-#endif
+ dbg_xfrin("Zone integrity check: %d errors.\n", errs);
+);
}
/*!
@@ -3358,13 +3409,17 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
int knot_ns_switch_zone(knot_nameserver_t *nameserver,
knot_ns_xfr_t *xfr)
{
- if (xfr == NULL || nameserver == NULL || xfr->data == NULL) {
+ if (xfr == NULL || nameserver == NULL || xfr->new_contents == NULL) {
return KNOT_EBADARG;
}
- knot_zone_contents_t *zone = (knot_zone_contents_t *)xfr->data;
+ knot_zone_contents_t *zone = (knot_zone_contents_t *)xfr->new_contents;
dbg_ns("Replacing zone by new one: %p\n", zone);
+ if (zone == NULL) {
+ dbg_ns("No new zone!\n");
+ return KNOT_ENOZONE;
+ }
// find the zone in the zone db
knot_zone_t *z = knot_zonedb_find_zone(nameserver->zone_db,
@@ -3375,32 +3430,17 @@ int knot_ns_switch_zone(knot_nameserver_t *nameserver,
dbg_ns("Failed to replace zone %s, old zone "
"not found\n", name);
free(name);
+
+ return KNOT_ENOZONE;
} else {
zone->zone = z;
}
- knot_zone_contents_t *old = rcu_xchg_pointer(&z->contents, zone);
-
-// knot_zone_t *old = knot_zonedb_replace_zone(nameserver->zone_db,
-// zone);
- dbg_ns("Old zone: %p\n", old);
-// if (old == NULL) {
-// char *name = knot_dname_to_str(
-// knot_node_owner(knot_zone_apex(zone)));
-// dbg_ns("Failed to replace zone %s\n", name);
-// free(name);
-// }
-
- // wait for readers to finish
- dbg_ns("Waiting for readers to finish...\n");
- synchronize_rcu();
- // destroy the old zone
- dbg_ns("Freeing old zone: %p\n", old);
- knot_zone_contents_deep_free(&old, 0);
+ int ret = xfrin_switch_zone(z, zone, xfr->type);
dbg_ns_exec(
dbg_ns("Zone db contents: (zone count: %zu)\n",
- nameserver->zone_db->zone_count);
+ nameserver->zone_db->zone_count);
const knot_zone_t **zones = knot_zonedb_zones(nameserver->zone_db);
for (int i = 0; i < knot_zonedb_zone_count
@@ -3413,7 +3453,7 @@ dbg_ns_exec(
free(zones);
);
- return KNOT_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -3654,6 +3694,7 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
* Maybe only this case will be EOK, other cases some error.
*/
+ knot_ddns_prereqs_free(&prereqs);
knot_packet_free(&response);
return KNOT_EOK;
}
diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h
index 3bf9552..8ec3e50 100644
--- a/src/libknot/nameserver/name-server.h
+++ b/src/libknot/nameserver/name-server.h
@@ -103,6 +103,8 @@ typedef struct knot_ns_xfr {
knot_zone_t *zone;
char* zname;
void *owner;
+ knot_zone_contents_t *new_contents;
+ char *msgpref;
/*! \note [TSIG] TSIG fields */
/*! \brief Message(s) to sign in wireformat.
diff --git a/src/libknot/packet/response.c b/src/libknot/packet/response.c
index c9f2ba7..3c7236e 100644
--- a/src/libknot/packet/response.c
+++ b/src/libknot/packet/response.c
@@ -454,7 +454,6 @@ dbg_response_exec(
* It is meaningful only if the found name is the one from QNAME
* and thus its parents are not stored yet.
*/
- assert(compr->wire_pos >= 0);
if (knot_response_store_dname_pos(compr->table, dname, not_matched,
compr->wire_pos, offset, compr_cs)
diff --git a/src/libknot/rdata.c b/src/libknot/rdata.c
index 51a1a70..8e9e8c1 100644
--- a/src/libknot/rdata.c
+++ b/src/libknot/rdata.c
@@ -147,6 +147,47 @@ static const knot_dname_t *knot_rdata_srv_name(const knot_rdata_t *rdata)
}
/*----------------------------------------------------------------------------*/
+
+static void knot_rdata_free_items(knot_rdata_item_t *items, unsigned int count,
+ uint type, int free_all_dnames)
+{
+ if (items == NULL) {
+ return;
+ }
+
+ knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(type);
+ assert(desc != NULL);
+
+ assert(count <= desc->length);
+
+ for (int i = 0; i < count; i++) {
+ if (&(items[i]) == NULL) {
+ continue;
+ }
+ 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) {
+ if ((items[i].dname != NULL)) {
+ /*! \todo This is hack to prevent memory errors,
+ * as the rdata_set_items() cannot determine
+ * items type and so cannot increment
+ * reference count in case of dname type.
+ * Free would then release dnames that
+ * aren't referenced by the rdata.
+ */
+ if (free_all_dnames) {
+ knot_dname_release(items[i].dname);
+ }
+ }
+ } else {
+ free(items[i].raw_data);
+ }
+ }
+
+ free(items);
+}
+
+/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -272,14 +313,17 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
dname = knot_dname_parse_from_wire(
wire, &pos2, total_size, NULL);
if (dname == NULL) {
+ knot_rdata_free_items(items, i,
+ desc->type, 1);
return KNOT_ERROR;
}
items[i].raw_data = (uint16_t *)malloc(
knot_dname_size(dname) + 2);
if (items[i].raw_data == NULL) {
- /*! \todo This will leak. */
- free(items);
+ knot_dname_free(&dname);
+ knot_rdata_free_items(items, i,
+ desc->type, 1);
return KNOT_ENOMEM;
}
@@ -307,21 +351,23 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
break;
default:
+ knot_rdata_free_items(items, i,
+ desc->type, 1);
return KNOT_EMALF;
}
if (item_size != 0) {
if (parsed + item_size > rdlength) {
- /*! \todo This will leak a lot. */
- free(items);
+ knot_rdata_free_items(items, i,
+ desc->type, 1);
return KNOT_EFEWDATA;
}
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. */
+ knot_rdata_free_items(items, i,
+ desc->type, 1);
return KNOT_ENOMEM;
}
memcpy(items[i].raw_data, &item_size, 2);
@@ -335,7 +381,8 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
// and should create an empty RDATA item
items[i].raw_data = (uint16_t *)malloc(2);
if (items[i].raw_data == NULL) {
- free(items);
+ knot_rdata_free_items(items, i,
+ desc->type, 1);
return KNOT_ENOMEM;
}
memcpy(items[i].raw_data, &item_size, 2);
@@ -494,39 +541,9 @@ void knot_rdata_deep_free(knot_rdata_t **rdata, uint type,
return;
}
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- assert(desc != NULL);
-
- assert((*rdata)->count <= desc->length);
-
- for (int i = 0; i < (*rdata)->count; i++) {
- if (&((*rdata)->items[i]) == NULL) {
- continue;
- }
- 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 ) {
- if (((*rdata)->items[i].dname != NULL)) {
- /*! \todo This is hack to prevent memory errors,
- * as the rdata_set_items() cannot determine
- * items type and so cannot increment
- * reference count in case of dname type.
- * Free would then release dnames that
- * aren't referenced by the rdata.
- */
- if (free_all_dnames) {
- knot_dname_release((*rdata)->items[i].dname);
- }
- }
- } else {
- free((*rdata)->items[i].raw_data);
- }
- }
+ knot_rdata_free_items((*rdata)->items, (*rdata)->count, type,
+ free_all_dnames);
- if ((*rdata)->items) {
- free((*rdata)->items);
- }
free(*rdata);
*rdata = NULL;
}
diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index d968378..d665c63 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -353,8 +353,8 @@ int knot_rrset_compare_rdata(const knot_rrset_t *r1, const knot_rrset_t *r2)
}
if (rdata2 == NULL) {
- // RDATA from r1 not found in r2
- return 0;
+ // RDATA from r1 not found in r2
+ return 0;
}
// otherwise it was found, continue with next r1 RDATA
@@ -365,14 +365,16 @@ int knot_rrset_compare_rdata(const knot_rrset_t *r1, const knot_rrset_t *r2)
rdata2 = knot_rrset_rdata(r2);
while (rdata2 != NULL) {
rdata1 = knot_rrset_rdata(r1);
- while (rdata2 != NULL && knot_rdata_compare(rdata1, rdata2,
- desc->wireformat)) {
+
+ while (rdata2 != NULL && rdata1 != NULL
+ && knot_rdata_compare(rdata1, rdata2,
+ desc->wireformat)) {
rdata1 = knot_rrset_rdata_next(r1, rdata1);
}
if (rdata1 == NULL) {
- // RDATA from r1 not found in r2
- return 0;
+ // RDATA from r2 not found in r1
+ return 0;
}
// otherwise it was found, continue with next r1 RDATA
@@ -630,7 +632,7 @@ int knot_rrset_shallow_copy(const knot_rrset_t *from, knot_rrset_t **to)
void knot_rrset_rotate(knot_rrset_t *rrset)
{
- rrset->rdata = rrset->rdata->next;
+ //rrset->rdata = rrset->rdata->next;
}
/*----------------------------------------------------------------------------*/
diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c
index bdaf083..148fc87 100644
--- a/src/libknot/tsig-op.c
+++ b/src/libknot/tsig-op.c
@@ -19,7 +19,6 @@
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <time.h>
-#include <ctype.h>
#include "common.h"
#include "tsig.h"
@@ -573,7 +572,6 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
if (ret != KNOT_EOK) {
dbg_tsig("TSIG: could not create wire or sign wire: %s\n",
knot_strerror(ret));
- free(items);
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
@@ -593,7 +591,6 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
if (ret != KNOT_EOK) {
dbg_tsig_detail("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
*digest_len = 0;
- free(items);
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
return ret;
@@ -983,7 +980,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
knot_rdata_item_t *items =
malloc(sizeof(knot_rdata_item_t) * desc->length);
- if (!items) {
+ if (items == NULL) {
dbg_tsig_detail("TSIG: items = NULL\n");
ERR_ALLOC_FAILED;
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
@@ -993,18 +990,19 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
memset(items, 0, sizeof(knot_rdata_item_t) * desc->length);
int ret = knot_rdata_set_items(rdata, items, desc->length);
+ free(items);
if (ret != KNOT_EOK) {
dbg_tsig_detail("TSIG: rdata_set_items returned %s\n",
knot_strerror(ret));
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
return ret;
}
- free(items);
knot_dname_t *alg_name =
knot_dname_deep_copy(tsig_rdata_alg_name(tsig_rr));
if (alg_name == NULL) {
dbg_tsig_detail("TSIG: failed to copy alg name\n");
+ knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
return KNOT_ERROR;
}
@@ -1012,6 +1010,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
tsig_rdata_set_time_signed(tmp_tsig, tsig_rdata_time_signed(tsig_rr));
tsig_rdata_set_fudge(tmp_tsig, tsig_rdata_fudge(tsig_rr));
tsig_rdata_set_mac(tmp_tsig, 0, NULL);
+ knot_dname_release(alg_name); /* Already copied in tsig_rdata_set_alg_name() */
/* Set original ID */
tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
@@ -1036,6 +1035,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
}
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_dname_release(key_name);
*msg_len += tsig_wire_len;
diff --git a/src/libknot/tsig.c b/src/libknot/tsig.c
index 5790b68..e9da295 100644
--- a/src/libknot/tsig.c
+++ b/src/libknot/tsig.c
@@ -331,16 +331,13 @@ tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
}
knot_lookup_table_t *item = knot_lookup_by_name(tsig_alg_table, name);
+ free(name);
if (!item) {
dbg_tsig_detail("TSIG: rdata: unknown algorithm.\n");
return KNOT_TSIG_ALG_NULL;
}
- free(name);
-
- int id = item->id;
-
- return id;
+ return item->id;
}
uint64_t tsig_rdata_time_signed(const knot_rrset_t *tsig)
diff --git a/src/libknot/updates/changesets.c b/src/libknot/updates/changesets.c
index cf9e6a0..1c3d3b9 100644
--- a/src/libknot/updates/changesets.c
+++ b/src/libknot/updates/changesets.c
@@ -287,6 +287,8 @@ void knot_free_changesets(knot_changesets_t **changesets)
knot_rrset_deep_free(&(*changesets)->first_soa, 1, 1, 1);
+ assert((*changesets)->changes == NULL);
+
free(*changesets);
*changesets = NULL;
}
diff --git a/src/libknot/updates/changesets.h b/src/libknot/updates/changesets.h
index e8d5e39..0570fc9 100644
--- a/src/libknot/updates/changesets.h
+++ b/src/libknot/updates/changesets.h
@@ -28,6 +28,7 @@
#define _KNOT_CHANGESETS_H_
#include "rrset.h"
+#include "zone/node.h"
/*! \todo Changeset must be serializable/deserializable, so
* all data and pointers have to be changeset-exclusive,
@@ -57,10 +58,58 @@ typedef struct {
/*----------------------------------------------------------------------------*/
typedef struct {
+ /*!
+ * Deleted (without owners and RDATA) after successful update.
+ */
+ knot_rrset_t **old_rrsets;
+ int old_rrsets_count;
+ int old_rrsets_allocated;
+
+ /*!
+ * Deleted after successful update.
+ */
+ knot_rdata_t **old_rdata;
+ unsigned *old_rdata_types;
+ int old_rdata_count;
+ int old_rdata_allocated;
+
+ /*!
+ * \brief Copied RRSets (i.e. modified by the update).
+ *
+ * Deleted (without owners and RDATA) after failed update.
+ */
+ knot_rrset_t **new_rrsets;
+ int new_rrsets_count;
+ int new_rrsets_allocated;
+
+ /*!
+ * Deleted after failed update.
+ */
+ knot_rdata_t **new_rdata;
+ unsigned *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;
+
+ knot_node_t **old_nsec3;
+ int old_nsec3_count;
+ int old_nsec3_allocated;
+} knot_changes_t;
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct {
knot_changeset_t *sets;
size_t count;
size_t allocated;
knot_rrset_t *first_soa;
+ knot_changes_t *changes;
} knot_changesets_t;
/*----------------------------------------------------------------------------*/
diff --git a/src/libknot/updates/xfr-in.c b/src/libknot/updates/xfr-in.c
index c1ea13d..f411e47 100644
--- a/src/libknot/updates/xfr-in.c
+++ b/src/libknot/updates/xfr-in.c
@@ -22,13 +22,10 @@
#include "nameserver/name-server.h"
#include "util/wire.h"
#include "util/debug.h"
-// #include "knot/zone/zone-dump.h"
-// #include "knot/zone/zone-load.h"
#include "packet/packet.h"
#include "dname.h"
#include "zone/zone.h"
#include "packet/query.h"
-#include "packet/response.h"
#include "util/error.h"
#include "updates/changesets.h"
#include "tsig.h"
@@ -174,6 +171,8 @@ int xfrin_transfer_needed(const knot_zone_contents_t *zone,
if (soa_response->parsed < soa_response->size) {
ret = knot_packet_parse_rest(soa_response);
if (ret != KNOT_EOK) {
+ dbg_xfrin_verb("knot_packet_parse_rest() returned %s\n",
+ knot_strerror(ret));
return KNOT_EMALF;
}
}
@@ -403,6 +402,7 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
if (ret != KNOT_EOK) {
/*! \note [TSIG] No need to check TSIG error
* here, propagate and check elsewhere.*/
+ knot_rrset_deep_free(&tsig, 1, 1, 1);
return ret;
}
@@ -412,6 +412,7 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
// Extract the digest from the TSIG RDATA and store it.
if (xfr->digest_max_size < tsig_rdata_mac_length(tsig)) {
+ knot_rrset_deep_free(&tsig, 1, 1, 1);
return KNOT_ESPACE;
}
memcpy(xfr->digest, tsig_rdata_mac(tsig),
@@ -429,6 +430,7 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
}*/
} else if (tsig != NULL) {
// TSIG where it should not be
+ knot_rrset_deep_free(&tsig, 1, 1, 1);
return KNOT_EMALF;
}
@@ -630,7 +632,7 @@ dbg_xfrin_exec(
while (ret == KNOT_EOK && rr != NULL) {
// process the parsed RR
- dbg_xfrin("\nNext RR:\n\n");
+ dbg_rrset_detail("\nNext RR:\n\n");
knot_rrset_dump(rr, 0);
if (node != NULL
@@ -834,6 +836,7 @@ dbg_xfrin_exec(
ret = knot_zone_contents_add_rrset(zone, rr, &node,
KNOT_RRSET_DUPL_MERGE, 1);
if (ret < 0) {
+ knot_packet_free(&packet);
dbg_xfrin("Failed to add RRSet to zone:"
"%s.\n", knot_strerror(ret));
return KNOT_ERROR;
@@ -858,9 +861,12 @@ dbg_xfrin_exec(
dbg_xfrin("Could not parse next RR: %s.\n",
knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0);
+
+ if (!in_zone) {
+ knot_node_free(&node, 0);
+ }
+
knot_rrset_deep_free(&rr, 1, 1, 1);
- /*! \todo Cleanup. */
return KNOT_EMALF;
}
@@ -903,8 +909,11 @@ dbg_xfrin_exec(
static int xfrin_parse_first_rr(knot_packet_t **packet, const uint8_t *pkt,
size_t size, knot_rrset_t **rr)
{
+ assert(packet != NULL);
+ assert(rr != NULL);
+
*packet = knot_packet_new(KNOT_PACKET_PREALLOC_NONE);
- if (packet == NULL) {
+ if (*packet == NULL) {
dbg_xfrin("Could not create packet structure.\n");
return KNOT_ENOMEM;
}
@@ -1003,6 +1012,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
// parse the next one
ret = knot_packet_parse_next_rr_answer(packet, &rr);
if (ret != KNOT_EOK) {
+ knot_packet_free(&packet);
return ret;
}
@@ -1035,7 +1045,8 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
}
} else {
if ((*chs)->first_soa == NULL) {
- dbg_xfrin("Changesets don't contain frist SOA!\n");
+ dbg_xfrin("Changesets don't contain SOA first!\n");
+ knot_rrset_deep_free(&rr, 1, 1, 1);
ret = KNOT_EBADARG;
goto cleanup;
}
@@ -1211,8 +1222,9 @@ dbg_xfrin_exec(
}
}
break;
- default:
- assert(0);
+ // dead code
+// default:
+// assert(0);
}
// parse the next RR
@@ -1254,53 +1266,6 @@ cleanup:
/* Applying changesets to zone */
/*----------------------------------------------------------------------------*/
-typedef struct {
- /*!
- * Deleted (without owners and RDATA) after successful update.
- */
- knot_rrset_t **old_rrsets;
- int old_rrsets_count;
- int old_rrsets_allocated;
-
- /*!
- * Deleted after successful update.
- */
- knot_rdata_t **old_rdata;
- uint *old_rdata_types;
- int old_rdata_count;
- int old_rdata_allocated;
-
- /*!
- * \brief Copied RRSets (i.e. modified by the update).
- *
- * Deleted (without owners and RDATA) after failed update.
- */
- knot_rrset_t **new_rrsets;
- int new_rrsets_count;
- int new_rrsets_allocated;
-
- /*!
- * 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;
-
- knot_node_t **old_nsec3;
- int old_nsec3_count;
- int old_nsec3_allocated;
-} xfrin_changes_t;
-
-/*----------------------------------------------------------------------------*/
-
static int xfrin_changes_check_rrsets(knot_rrset_t ***rrsets,
int *count, int *allocated, int to_add)
{
@@ -1383,6 +1348,7 @@ static int xfrin_changes_check_rdata(knot_rdata_t ***rdatas, uint **types,
uint *types_new = malloc(new_count * sizeof(uint));
if (types_new == NULL) {
+ free(rdatas_new);
return KNOT_ENOMEM;
}
@@ -1405,6 +1371,36 @@ static int xfrin_changes_check_rdata(knot_rdata_t ***rdatas, uint **types,
/*----------------------------------------------------------------------------*/
+static void xfrin_changes_add_rdata(knot_rdata_t **rdatas, uint *types,
+ int *count, knot_rdata_t *rdata, uint type)
+{
+ dbg_xfrin_detail("Adding RDATA to new RDATA list: %p\n", rdata);
+
+dbg_xfrin_exec_detail(
+ // try to find the first RDATA in the given list
+ for (int i = 0; i < *count; ++i) {
+ knot_rdata_t *r = rdatas[i];
+ while (r->next != rdatas[i]) {
+ if (r == rdata) {
+ dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
+ knot_rdata_dump(rdata, type, 0);
+ }
+ r = r->next;
+ }
+ if (r == rdata) {
+ dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
+ knot_rdata_dump(rdata, type, 0);
+ }
+ }
+);
+
+ rdatas[*count] = rdata;
+ types[*count] = type;
+ ++*count;
+}
+
+/*----------------------------------------------------------------------------*/
+
static void xfrin_zone_contents_free(knot_zone_contents_t **contents)
{
/*! \todo This should be all in some API!! */
@@ -1456,7 +1452,7 @@ static knot_rdata_t *xfrin_remove_rdata(knot_rrset_t *from,
/*----------------------------------------------------------------------------*/
static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
- xfrin_changes_t *changes)
+ knot_changes_t *changes)
{
// create new RRSet by copying the old one
// int ret = knot_rrset_shallow_copy(old, copy);
@@ -1489,21 +1485,21 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
}
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;
+
+ xfrin_changes_add_rdata(changes->new_rdata, changes->new_rdata_types,
+ &changes->new_rdata_count,
+ knot_rrset_get_rdata(*copy),
+ knot_rrset_type(*copy));
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;
+ xfrin_changes_add_rdata(changes->new_rdata,
+ changes->new_rdata_types,
+ &changes->new_rdata_count,
+ knot_rrset_get_rdata((*copy)->rrsigs),
+ KNOT_RRTYPE_RRSIG);
}
// add the old RRSet to the list of old RRSets
@@ -1526,19 +1522,20 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
}
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;
+
+ xfrin_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
+ &changes->old_rdata_count, old->rdata,
+ knot_rrset_type(old));
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;
+
+ xfrin_changes_add_rdata(changes->old_rdata,
+ changes->old_rdata_types,
+ &changes->old_rdata_count,
+ old->rrsigs->rdata,
+ KNOT_RRTYPE_RRSIG);
}
return KNOT_EOK;
@@ -1547,7 +1544,7 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
/*----------------------------------------------------------------------------*/
static int xfrin_copy_rrset(knot_node_t *node, knot_rr_type_t type,
- knot_rrset_t **rrset, xfrin_changes_t *changes)
+ knot_rrset_t **rrset, knot_changes_t *changes)
{
knot_rrset_t *old = knot_node_remove_rrset(node, type);
@@ -1575,7 +1572,7 @@ static int xfrin_copy_rrset(knot_node_t *node, knot_rr_type_t type,
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
+static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
const knot_rrset_t *remove,
knot_node_t *node,
knot_rrset_t **rrset)
@@ -1662,10 +1659,9 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
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;
+ xfrin_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
+ &changes->old_rdata_count, rdata,
+ knot_rrset_type(remove));
// 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
@@ -1722,7 +1718,7 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_remove_normal(xfrin_changes_t *changes,
+static int xfrin_apply_remove_normal(knot_changes_t *changes,
const knot_rrset_t *remove,
knot_node_t *node,
knot_rrset_t **rrset)
@@ -1800,10 +1796,9 @@ dbg_xfrin_exec_detail(
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;
+ xfrin_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
+ &changes->old_rdata_count, rdata,
+ knot_rrset_type(remove));
// 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
@@ -1838,7 +1833,7 @@ dbg_xfrin_exec_detail(
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_remove_all_rrsets(xfrin_changes_t *changes,
+static int xfrin_apply_remove_all_rrsets(knot_changes_t *changes,
knot_node_t *node, uint16_t type)
{
int ret;
@@ -1923,7 +1918,7 @@ static knot_node_t *xfrin_add_new_node(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_add_normal(xfrin_changes_t *changes,
+static int xfrin_apply_add_normal(knot_changes_t *changes,
knot_rrset_t *add,
knot_node_t *node,
knot_rrset_t **rrset,
@@ -1994,7 +1989,6 @@ dbg_xfrin_exec(
// knot_rrset_dump(*rrset, 1);
ret = xfrin_copy_old_rrset(old, rrset, changes);
if (ret != KNOT_EOK) {
- assert(0);
return ret;
}
@@ -2036,7 +2030,7 @@ dbg_xfrin_exec(
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_add_rrsig(xfrin_changes_t *changes,
+static int xfrin_apply_add_rrsig(knot_changes_t *changes,
knot_rrset_t *add,
knot_node_t *node,
knot_rrset_t **rrset,
@@ -2178,45 +2172,48 @@ dbg_xfrin_exec(
/*----------------------------------------------------------------------------*/
-static void xfrin_cleanup_update(xfrin_changes_t *changes)
+void xfrin_cleanup_successful_update(knot_changes_t **changes)
{
- for (int i = 0; i < changes->old_rrsets_count; ++i) {
+ 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]);
+ (*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) {
+ 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];
+ (*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);
+ (*changes)->old_rdata_types[i], 1);
rdata = tmp;
} while (rdata != NULL
- && rdata != changes->old_rdata[i]);
+ && 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);
+ 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);
+
+ free((*changes));
+ *changes = NULL;
}
/*----------------------------------------------------------------------------*/
@@ -2336,62 +2333,108 @@ static void xfrin_cleanup_old_nodes(knot_node_t *node, void *data)
/*----------------------------------------------------------------------------*/
-static void xfrin_rollback_update2(knot_zone_contents_t *old_contents,
- knot_zone_contents_t *new_contents,
- xfrin_changes_t *changes)
+static void xfrin_cleanup_failed_update(knot_zone_contents_t *old_contents,
+ knot_zone_contents_t **new_contents)
{
- // 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]);
+ if (old_contents == NULL && new_contents == NULL) {
+ return;
+ }
+
+ if (*new_contents != NULL) {
+ // destroy the shallow copy of zone
+ xfrin_zone_contents_free2(new_contents);
}
- 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;
+ if (old_contents != NULL) {
+ // 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);
- 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;
+ knot_zone_contents_nsec3_apply_inorder(old_contents,
+ xfrin_cleanup_old_nodes,
+ NULL);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+void xfrin_rollback_update(knot_zone_contents_t *old_contents,
+ knot_zone_contents_t **new_contents,
+ knot_changes_t **changes)
+{
+ assert(changes != NULL);
+
+ if (*changes != NULL) {
+ // 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]);
}
- assert(rdata == NULL || rdata->next == changes->new_rdata[i]);
+ for (int i = 0; i < (*changes)->new_rdata_count; ++i) {
+ fprintf(stderr, "Freeing %d. RDATA chain: %p\n", i,
+ (*changes)->new_rdata[i]);
+
+ /*
+ * In some case, the same RDATA may be stored in
+ * different positions in different RDATA chains, so
+ * some ivalid reads occur.
+ *
+ * More precisely, the same chain is stored multiple
+ * times, but starting from different RDATA.
+ *
+ * We may check every RDATA against every one
+ * already deleted, but that may be very time-consuming.
+ */
+
+ // 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]) {
+ assert(rdata->next != rdata);
+ rdata_next = rdata->next;
+ fprintf(stderr, " Deleting RDATA: %p\n", rdata);
+ knot_rdata_deep_free(&rdata,
+ (*changes)->new_rdata_types[i], 1);
+ rdata = rdata_next;
+ }
+
+ assert(rdata == NULL
+ || rdata->next == (*changes)->new_rdata[i]);
+
+ fprintf(stderr, " Deleting RDATA: %p\n", rdata);
+ knot_rdata_deep_free(&rdata,
+ (*changes)->new_rdata_types[i], 1);
+
+ //(*changes)->new_rdata[i] = NULL;
+ }
- knot_rdata_deep_free(&rdata, changes->new_rdata_types[i], 1);
+ // 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);
- changes->new_rdata[i] = NULL;
+ free(*changes);
+ *changes = 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);
+ xfrin_cleanup_failed_update(old_contents, new_contents);
}
/*----------------------------------------------------------------------------*/
static int xfrin_apply_remove2(knot_zone_contents_t *contents,
knot_changeset_t *chset,
- xfrin_changes_t *changes)
+ knot_changes_t *changes)
{
/*
* Iterate over removed RRSets, and remove them from the new nodes
@@ -2472,7 +2515,7 @@ static int xfrin_apply_remove2(knot_zone_contents_t *contents,
static int xfrin_apply_add2(knot_zone_contents_t *contents,
knot_changeset_t *chset,
- xfrin_changes_t *changes)
+ knot_changes_t *changes)
{
int ret = 0;
knot_node_t *node = NULL;
@@ -2540,25 +2583,6 @@ static int xfrin_apply_add2(knot_zone_contents_t *contents,
rrset);
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_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
@@ -2576,6 +2600,23 @@ static int xfrin_apply_add2(knot_zone_contents_t *contents,
changes->new_rrsets[changes->new_rrsets_count++]
= chset->add[i];
+ // the same goes for the RDATA
+
+ // connect the RDATA to the list of new 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;
+ }
+
+ xfrin_changes_add_rdata(changes->new_rdata,
+ changes->new_rdata_types,
+ &changes->new_rdata_count,
+ knot_rrset_get_rdata(chset->add[i]),
+ knot_rrset_type(chset->add[i]));
+
chset->add[i] = NULL;
} else if (ret == 2) {
// the copy of the RRSet was used, but it was
@@ -2583,6 +2624,11 @@ static int xfrin_apply_add2(knot_zone_contents_t *contents,
// just delete the add RRSet, but without RDATA
// as these were merged to the copied RRSet
knot_rrset_free(&chset->add[i]);
+
+ // In this case, the RDATA does not have to be
+ // stored in the list of new RDATA, because
+ // it is joined to the copy of RDATA, that is
+ // already stored there
} else {
assert(0);
}
@@ -2598,7 +2644,7 @@ static int xfrin_apply_add2(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
- xfrin_changes_t *changes,
+ knot_changes_t *changes,
knot_changeset_t *chset)
{
knot_node_t *node = knot_zone_contents_get_apex(contents);
@@ -2658,9 +2704,9 @@ static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
changes->old_rrsets[changes->old_rrsets_count++] = rrset;
/*! \todo Maybe check if the SOA does not have more RDATA? */
- changes->old_rdata[changes->old_rdata_count] = rrset->rdata;
- changes->old_rdata_types[changes->old_rdata_count] = KNOT_RRTYPE_SOA;
- ++changes->old_rdata_count;
+ xfrin_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
+ &changes->old_rdata_count, rrset->rdata,
+ KNOT_RRTYPE_SOA);
// store RRSIGs from the old SOA to the new SOA
knot_rrset_set_rrsigs(chset->soa_to, knot_rrset_get_rrsigs(rrset));
@@ -2678,11 +2724,12 @@ static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
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;
+
+ xfrin_changes_add_rdata(changes->new_rdata,
+ changes->new_rdata_types,
+ &changes->new_rdata_count,
+ knot_rrset_get_rdata(chset->soa_to),
+ knot_rrset_type(chset->soa_to));
// remove the SOA from the changeset, so it will not be deleted after
// successful apply
@@ -2694,7 +2741,7 @@ static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
static int xfrin_apply_changeset2(knot_zone_contents_t *contents,
- xfrin_changes_t *changes,
+ knot_changes_t *changes,
knot_changeset_t *chset)
{
/*
@@ -2735,7 +2782,7 @@ static void xfrin_mark_empty(knot_node_t *node, void *data)
assert(node != NULL);
assert(data != NULL);
- xfrin_changes_t *changes = (xfrin_changes_t *)data;
+ knot_changes_t *changes = (knot_changes_t *)data;
if (knot_node_rrset_count(node) == 0
&& knot_node_children(node) == 0) {
@@ -2767,7 +2814,7 @@ static void xfrin_mark_empty_nsec3(knot_node_t *node, void *data)
assert(node != NULL);
assert(data != NULL);
- xfrin_changes_t *changes = (xfrin_changes_t *)data;
+ knot_changes_t *changes = (knot_changes_t *)data;
if (knot_node_rrset_count(node) == 0
&& knot_node_children(node) == 0) {
@@ -2795,7 +2842,7 @@ static void xfrin_mark_empty_nsec3(knot_node_t *node, void *data)
/*----------------------------------------------------------------------------*/
static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
- xfrin_changes_t *changes)
+ knot_changes_t *changes)
{
int ret;
@@ -2987,9 +3034,11 @@ static int xfrin_check_contents_copy(knot_zone_contents_t *old_contents)
/*----------------------------------------------------------------------------*/
int xfrin_apply_changesets(knot_zone_t *zone,
- knot_changesets_t *chsets)
+ knot_changesets_t *chsets,
+ knot_zone_contents_t **new_contents)
{
- if (zone == NULL || chsets == NULL || chsets->count == 0) {
+ if (zone == NULL || chsets == NULL || chsets->count == 0
+ || new_contents == NULL) {
return KNOT_EBADARG;
}
@@ -3033,8 +3082,15 @@ int xfrin_apply_changesets(knot_zone_t *zone,
return ret;
}
- xfrin_changes_t changes;
- memset(&changes, 0, sizeof(xfrin_changes_t));
+ knot_changes_t *changes = (knot_changes_t *)malloc(
+ sizeof(knot_changes_t));
+ if (changes == NULL) {
+ dbg_xfrin("Failed to allocate structure for changes!\n");
+ xfrin_rollback_update(old_contents, &contents_copy, &changes);
+ return KNOT_ENOMEM;
+ }
+
+ memset(changes, 0, sizeof(knot_changes_t));
/*!
* \todo Check if all nodes have their copy.
@@ -3042,7 +3098,7 @@ int xfrin_apply_changesets(knot_zone_t *zone,
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);
+ xfrin_rollback_update(old_contents, &contents_copy, &changes);
return ret;
}
@@ -3063,11 +3119,11 @@ int xfrin_apply_changesets(knot_zone_t *zone,
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_changeset2(contents_copy, &changes,
+ if ((ret = xfrin_apply_changeset2(contents_copy, changes,
&chsets->sets[i]))
!= KNOT_EOK) {
- xfrin_rollback_update2(old_contents,
- contents_copy, &changes);
+ xfrin_rollback_update(old_contents,
+ &contents_copy, &changes);
dbg_xfrin("Failed to apply changesets to zone: "
"%s\n", knot_strerror(ret));
return ret;
@@ -3090,11 +3146,11 @@ int xfrin_apply_changesets(knot_zone_t *zone,
/*
* Select and delete empty nodes.
*/
- ret = xfrin_remove_empty_nodes(contents_copy, &changes);
+ ret = xfrin_remove_empty_nodes(contents_copy, changes);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to remove empty nodes: %s\n",
knot_strerror(ret));
- xfrin_rollback_update2(old_contents, contents_copy, &changes);
+ xfrin_rollback_update(old_contents, &contents_copy, &changes);
return ret;
}
@@ -3107,7 +3163,7 @@ int xfrin_apply_changesets(knot_zone_t *zone,
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to finalize zone contents: %s\n",
knot_strerror(ret));
- xfrin_rollback_update2(old_contents, contents_copy, &changes);
+ xfrin_rollback_update(old_contents, &contents_copy, &changes);
return ret;
}
assert(knot_zone_contents_apex(contents_copy) != NULL);
@@ -3116,30 +3172,50 @@ int xfrin_apply_changesets(knot_zone_t *zone,
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);
+ xfrin_rollback_update(old_contents, &contents_copy, &changes);
return ret;
}
+ //xfrin_cleanup_update(&changes);
+ chsets->changes = changes;
+ *new_contents = contents_copy;
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int xfrin_switch_zone(knot_zone_t *zone,
+ knot_zone_contents_t *new_contents,
+ int transfer_type)
+{
+ if (zone == NULL || new_contents == NULL) {
+ return KNOT_EBADARG;
+ }
+
dbg_xfrin("Switching zone contents.\n");
- dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
- old_contents->apex, contents_copy->apex);
+ dbg_xfrin_verb("Old contents: %p, apex: %p, new apex: %p\n",
+ zone->contents, (zone->contents)
+ ? zone->contents->apex : NULL, new_contents->apex);
+
knot_zone_contents_t *old =
- knot_zone_switch_contents(zone, contents_copy);
- assert(old == old_contents);
+ knot_zone_switch_contents(zone, new_contents);
- dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
- old_contents->apex, contents_copy->apex);
- /*
- * Wait until all readers finish reading
- */
+ dbg_xfrin_verb("Old contents: %p, apex: %p, new apex: %p\n",
+ old, (old) ? old->apex : NULL, new_contents->apex);
+
+ // wait for readers to finish
+ dbg_xfrin_verb("Waiting for readers to finish...\n");
synchronize_rcu();
+ // destroy the old zone
+ dbg_xfrin_verb("Freeing old zone: %p\n", old);
- /*
- * Delete all old and unused data.
- */
- dbg_xfrin("Cleaning up.\n");
- xfrin_zone_contents_free(&old_contents);
- xfrin_cleanup_update(&changes);
+ if (transfer_type == XFR_TYPE_AIN) {
+ knot_zone_contents_deep_free(&old, 0);
+ } else {
+ assert(old != NULL);
+ xfrin_zone_contents_free(&old);
+ }
return KNOT_EOK;
}
diff --git a/src/libknot/updates/xfr-in.h b/src/libknot/updates/xfr-in.h
index 233527b..b009152 100644
--- a/src/libknot/updates/xfr-in.h
+++ b/src/libknot/updates/xfr-in.h
@@ -182,7 +182,21 @@ 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);
+ knot_changesets_t *chsets,
+ knot_zone_contents_t **new_contents);
+
+int xfrin_switch_zone(knot_zone_t *zone,
+ knot_zone_contents_t *new_contents,
+ int deep_free);
+
+//void xfrin_cleanup_failed_update(knot_zone_contents_t *old_contents,
+// knot_zone_contents_t **new_contents);
+
+void xfrin_cleanup_successful_update(knot_changes_t **changes);
+
+void xfrin_rollback_update(knot_zone_contents_t *old_contents,
+ knot_zone_contents_t **new_contents,
+ knot_changes_t **changes);
#endif /* _KNOTXFR_IN_H_ */
diff --git a/src/libknot/util/debug.c b/src/libknot/util/debug.c
index 78cd4a4..f14c3cd 100644
--- a/src/libknot/util/debug.c
+++ b/src/libknot/util/debug.c
@@ -22,7 +22,6 @@
#include "util/utils.h"
#include "util/debug.h"
-#include "libknot.h"
#include "common/print.h"
void knot_rdata_dump(knot_rdata_t *rdata, uint32_t type, char loaded_zone)
diff --git a/src/libknot/util/debug.h b/src/libknot/util/debug.h
index a7eb86a..e02f988 100644
--- a/src/libknot/util/debug.h
+++ b/src/libknot/util/debug.h
@@ -34,6 +34,43 @@
#include "config.h" /* autoconf generated */
+/*
+ * Debug macros
+ */
+#ifdef KNOT_ZONES_DEBUG
+ #define KNOT_ZONE_DEBUG
+ #define KNOT_ZONEDB_DEBUG
+ #define KNOT_NODE_DEBUG
+#endif
+
+#ifdef KNOT_NS_DEBUG
+ #define KNOT_EDNS_DEBUG
+ #define KNOT_NSEC3_DEBUG
+#endif
+
+/* define KNOT_PACKET_DEBUG -- in configure.ac */
+#ifdef KNOT_PACKET_DEBUG
+ #define KNOT_RESPONSE_DEBUG
+#endif
+
+#ifdef KNOT_RR_DEBUG
+ #define KNOT_RRSET_DEBUG
+ #define KNOT_RDATA_DEBUG
+#endif
+
+#ifdef KNOT_HASH_DEBUG
+ #define CUCKOO_DEBUG
+ #define CUCKOO_DEBUG_HASH
+#endif
+
+#ifdef KNOT_XFR_DEBUG
+ #define KNOT_XFRIN_DEBUG
+ #define KNOT_TSIG_DEBUG
+#endif
+
+/* KNOT_DNAME_DEBUG -- in configure.ac */
+/* #define KNOT_DDNS_DEBUG -- \todo Use this or delete. */
+
#include "rdata.h"
#include "rrset.h"
#include "zone/node.h"
@@ -41,27 +78,6 @@
#include "util/utils.h"
#include "common/print.h"
-/*
- * Debug macros
- */
-/*! \todo Set these during configure. */
-//#define KNOT_ZONE_DEBUG
-//#define KNOT_RESPONSE_DEBUG
-//#define KNOT_ZONEDB_DEBUG
-//#define KNOT_DNAME_DEBUG
-//#define KNOT_NODE_DEBUG
-//#define KNOT_PACKET_DEBUG
-//#define KNOT_EDNS_DEBUG
-//#define KNOT_RRSET_DEBUG
-//#define KNOT_RDATA_DEBUG
-//#define KNOT_NSEC3_DEBUG
-//#define CUCKOO_DEBUG
-//#define CUCKOO_DEBUG_HASH
-//#define KNOT_NS_DEBUG
-//#define KNOT_XFRIN_DEBUG
-//#define KNOT_DDNS_DEBUG
-//#define KNOT_TSIG_DEBUG
-
/*!
* \brief Dumps RDATA of the given type.
*
@@ -541,37 +557,46 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
#ifdef DEBUG_ENABLE_BRIEF
#define dbg_ck(msg...) fprintf(stderr, msg)
#define dbg_ck_hex(data, len) hex_print((data), (len))
+#define dbg_ck_exec(cmds) do { cmds } while (0)
#else
#define dbg_ck(msg...)
#define dbg_ck_hex(data, len)
+#define dbg_ck_exec(cmds)
#endif
/* Verbose messages. */
#ifdef DEBUG_ENABLE_VERBOSE
#define dbg_ck_verb(msg...) fprintf(stderr, msg)
#define dbg_ck_hex_verb(data, len) hex_print((data), (len))
+#define dbg_ck_exec_verb(cmds) do { cmds } while (0)
#else
#define dbg_ck_verb(msg...)
#define dbg_ck_hex_verb(data, len)
+#define dbg_ck_exec_verb(cmds)
#endif
/* Detail messages. */
#ifdef DEBUG_ENABLE_DETAILS
#define dbg_ck_detail(msg...) fprintf(stderr, msg)
#define dbg_ck_hex_detail(data, len) hex_print((data), (len))
+#define dbg_ck_exec_detail(cmds) do { cmds } while (0)
#else
#define dbg_ck_detail(msg...)
#define dbg_ck_hex_detail(data, len)
+#define dbg_ck_exec_detail(cmds)
#endif
/* No messages. */
#else
#define dbg_ck(msg...)
#define dbg_ck_hex(data, len)
+#define dbg_ck_exec(cmds)
#define dbg_ck_verb(msg...)
#define dbg_ck_hex_verb(data, len)
+#define dbg_ck_exec_verb(cmds)
#define dbg_ck_detail(msg...)
#define dbg_ck_hex_detail(data, len)
+#define dbg_ck_exec_detail(cmds)
#endif
/******************************************************************************/
diff --git a/src/libknot/util/libknot_error.c b/src/libknot/util/libknot_error.c
index d922afb..a5a9de0 100644
--- a/src/libknot/util/libknot_error.c
+++ b/src/libknot/util/libknot_error.c
@@ -15,8 +15,6 @@
*/
#include "util/error.h"
-#include "util/utils.h"
-
#include "common/errors.h"
const error_table_t knot_error_msgs[KNOT_ERROR_COUNT] = {
diff --git a/src/libknot/util/utils.h b/src/libknot/util/utils.h
index ba7a6d2..fd275b3 100644
--- a/src/libknot/util/utils.h
+++ b/src/libknot/util/utils.h
@@ -123,8 +123,9 @@ static inline uint32_t knot_wire_read_u32(const uint8_t *pos)
*/
static inline uint64_t knot_wire_read_u48(const uint8_t *pos)
{
- return ((uint64_t)(pos[0]) << 40) | ((uint64_t)(pos[1]) << 32) | (pos[2] << 24) |
- (pos[3] << 16) | (pos[4] << 8) | pos[5];
+ return ((uint64_t)(pos[0]) << 40) | ((uint64_t)(pos[1]) << 32)
+ | ((uint64_t)(pos[2]) << 24) | ((uint64_t)(pos[3]) << 16)
+ | ((uint64_t)(pos[4]) << 8) | (uint64_t)pos[5];
}
/*!
diff --git a/src/libknot/zone/node.h b/src/libknot/zone/node.h
index 583f248..11cd0ce 100644
--- a/src/libknot/zone/node.h
+++ b/src/libknot/zone/node.h
@@ -50,8 +50,6 @@ struct knot_node {
/*! \brief Type-ordered list of RRSets belonging to this node. */
general_tree_t *rrset_tree;
- unsigned short rrset_count; /*!< Number of RRSets stored in the node. */
-
/*! \brief Wildcard node being the direct descendant of this node. */
struct knot_node *wildcard_child;
@@ -76,21 +74,14 @@ struct knot_node {
struct knot_node *nsec3_referer;
- /*!
- * \brief Various flags.
- *
- * Currently only two:
- * 0x01 - node is a delegation point
- * 0x02 - node is non-authoritative (under a delegation point)
- * 0x80 - node is old and will be removed (during update)
- * 0x40 - node is new, should not be used while zone is old
- */
- uint8_t flags;
+ struct knot_zone *zone;
struct knot_node *new_node;
unsigned int children;
-
+
+ unsigned short rrset_count; /*!< Number of RRSets stored in the node. */
+
/*!
* \brief Generation of node to be used.
*
@@ -100,7 +91,16 @@ struct knot_node {
*/
// short **generation;
- struct knot_zone *zone;
+ /*!
+ * \brief Various flags.
+ *
+ * Currently only two:
+ * 0x01 - node is a delegation point
+ * 0x02 - node is non-authoritative (under a delegation point)
+ * 0x80 - node is old and will be removed (during update)
+ * 0x40 - node is new, should not be used while zone is old
+ */
+ uint8_t flags;
};
typedef struct knot_node knot_node_t;
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c
index 8a74e23..3764acc 100644
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -261,21 +261,21 @@ static int knot_zone_contents_dnames_from_node_to_table(
* \param zone Current zone.
* \param node Node to be used.
*/
-static void find_and_set_wildcard_child(knot_zone_contents_t *zone,
- knot_node_t *node)
-{
- knot_dname_t *chopped = knot_dname_left_chop(node->owner);
- assert(chopped);
- knot_node_t *wildcard_parent;
- wildcard_parent =
- knot_zone_contents_get_node(zone, chopped);
+//static void find_and_set_wildcard_child(knot_zone_contents_t *zone,
+// knot_node_t *node)
+//{
+// knot_dname_t *chopped = knot_dname_left_chop(node->owner);
+// assert(chopped);
+// knot_node_t *wildcard_parent;
+// wildcard_parent =
+// knot_zone_contents_get_node(zone, chopped);
- knot_dname_free(&chopped);
+// knot_dname_free(&chopped);
- assert(wildcard_parent); /* it *has* to be there */
+// assert(wildcard_parent); /* it *has* to be there */
- knot_node_set_wildcard_child(wildcard_parent, node);
-}
+// knot_node_set_wildcard_child(wildcard_parent, node);
+//}
/*----------------------------------------------------------------------------*/
/*!
@@ -294,54 +294,54 @@ static void find_and_set_wildcard_child(knot_zone_contents_t *zone,
* \param zone Zone to which the RDATA belongs.
* \param pos Position of the RDATA item in the RDATA.
*/
-static void knot_zone_contents_adjust_rdata_item(knot_rdata_t *rdata,
- knot_zone_contents_t *zone,
- knot_node_t *node,
- int pos)
-{
- return;
- const knot_rdata_item_t *dname_item
- = knot_rdata_item(rdata, pos);
+//static void knot_zone_contents_adjust_rdata_item(knot_rdata_t *rdata,
+// knot_zone_contents_t *zone,
+// knot_node_t *node,
+// int pos)
+//{
+// return;
+// const knot_rdata_item_t *dname_item
+// = knot_rdata_item(rdata, pos);
- assert(dname_item);
+// assert(dname_item);
- if (dname_item != NULL) {
- knot_dname_t *dname = dname_item->dname;
- const knot_node_t *n = NULL;
- const knot_node_t *closest_encloser = NULL;
- const knot_node_t *prev = NULL;
+// if (dname_item != NULL) {
+// knot_dname_t *dname = dname_item->dname;
+// const knot_node_t *n = NULL;
+// const knot_node_t *closest_encloser = NULL;
+// const knot_node_t *prev = NULL;
- if (knot_dname_is_wildcard(dname)) {
- find_and_set_wildcard_child(zone, node);
- }
+// if (knot_dname_is_wildcard(dname)) {
+// find_and_set_wildcard_child(zone, node);
+// }
- int ret = knot_zone_contents_find_dname(zone, dname, &n,
- &closest_encloser, &prev);
+// int ret = knot_zone_contents_find_dname(zone, dname, &n,
+// &closest_encloser, &prev);
- // n = knot_zone_find_node(zone, dname);
+// // n = knot_zone_find_node(zone, dname);
- if (ret == KNOT_EBADARG || ret == KNOT_EBADZONE) {
- // TODO: do some cleanup if needed
- return;
- }
+// if (ret == KNOT_EBADARG || ret == KNOT_EBADZONE) {
+// // TODO: do some cleanup if needed
+// return;
+// }
- assert(ret != KNOT_ZONE_NAME_FOUND
- || n == closest_encloser);
-
- if (ret != KNOT_ZONE_NAME_FOUND
- && (closest_encloser != NULL)) {
- dbg_zone("Saving closest encloser to RDATA.\n");
- // save pointer to the closest encloser
- knot_rdata_item_t *item =
- knot_rdata_get_item(rdata, pos);
- assert(item->dname != NULL);
- assert(item->dname->node == NULL);
- //skip_insert(list, (void *)item->dname,
- // (void *)closest_encloser->owner, NULL);
- item->dname->node = closest_encloser->owner->node;
- }
- }
-}
+// assert(ret != KNOT_ZONE_NAME_FOUND
+// || n == closest_encloser);
+
+// if (ret != KNOT_ZONE_NAME_FOUND
+// && (closest_encloser != NULL)) {
+// dbg_zone("Saving closest encloser to RDATA.\n");
+// // save pointer to the closest encloser
+// knot_rdata_item_t *item =
+// knot_rdata_get_item(rdata, pos);
+// assert(item->dname != NULL);
+// assert(item->dname->node == NULL);
+// //skip_insert(list, (void *)item->dname,
+// // (void *)closest_encloser->owner, NULL);
+// item->dname->node = closest_encloser->owner->node;
+// }
+// }
+//}
/*----------------------------------------------------------------------------*/
/*!
@@ -355,65 +355,65 @@ static void knot_zone_contents_adjust_rdata_item(knot_rdata_t *rdata,
* \param rrset RRSet to adjust RDATA in.
* \param zone Zone to which the RRSet belongs.
*/
-static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
- knot_zone_contents_t *zone,
- knot_node_t *node)
-{
- uint16_t type = knot_rrset_type(rrset);
+//static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
+// knot_zone_contents_t *zone,
+// knot_node_t *node)
+//{
+// uint16_t type = knot_rrset_type(rrset);
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- assert(desc);
+// knot_rrtype_descriptor_t *desc =
+// knot_rrtype_descriptor_by_type(type);
+// assert(desc);
- knot_rdata_t *rdata_first = knot_rrset_get_rdata(rrset);
- knot_rdata_t *rdata = rdata_first;
+// knot_rdata_t *rdata_first = knot_rrset_get_rdata(rrset);
+// knot_rdata_t *rdata = rdata_first;
- if (rdata == NULL) {
- return;
- }
+// if (rdata == NULL) {
+// return;
+// }
- while (rdata->next != rdata_first) {
- for (int i = 0; i < rdata->count; ++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) {
- dbg_zone("Adjusting domain name at "
- "position %d of RDATA of record with owner "
- "%s and type %s.\n",
- i, rrset->owner->name,
- knot_rrtype_to_string(type));
-
- knot_zone_contents_adjust_rdata_item(rdata,
- zone,
- node,
- i);
- }
- }
- rdata = rdata->next;
- }
+// while (rdata->next != rdata_first) {
+// for (int i = 0; i < rdata->count; ++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) {
+// dbg_zone("Adjusting domain name at "
+// "position %d of RDATA of record with owner "
+// "%s and type %s.\n",
+// i, rrset->owner->name,
+// knot_rrtype_to_string(type));
+
+// knot_zone_contents_adjust_rdata_item(rdata,
+// zone,
+// node,
+// i);
+// }
+// }
+// rdata = rdata->next;
+// }
- for (int i = 0; i < rdata->count; ++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) {
- dbg_zone("Adjusting domain name at "
- "position %d of RDATA of record with owner "
- "%s and type %s.\n",
- i, rrset->owner->name,
- knot_rrtype_to_string(type));
-
- knot_zone_contents_adjust_rdata_item(rdata, zone,
- node, i);
- }
- }
+// for (int i = 0; i < rdata->count; ++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) {
+// dbg_zone("Adjusting domain name at "
+// "position %d of RDATA of record with owner "
+// "%s and type %s.\n",
+// i, rrset->owner->name,
+// knot_rrtype_to_string(type));
+
+// knot_zone_contents_adjust_rdata_item(rdata, zone,
+// node, i);
+// }
+// }
-}
+//}
/*----------------------------------------------------------------------------*/
/*!
@@ -426,31 +426,31 @@ static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
* \param node Zone node to adjust the RRSets in.
* \param zone Zone to which the node belongs.
*/
-static void knot_zone_contents_adjust_rrsets(knot_node_t *node,
- knot_zone_contents_t *zone)
-{
- //return;
- knot_rrset_t **rrsets = knot_node_get_rrsets(node);
- short count = knot_node_rrset_count(node);
-
- assert(count == 0 || rrsets != NULL);
-
- for (int r = 0; r < count; ++r) {
- assert(rrsets[r] != NULL);
- dbg_zone("Adjusting next RRSet.\n");
- knot_zone_contents_adjust_rdata_in_rrset(rrsets[r], zone,
- node);
- knot_rrset_t *rrsigs = rrsets[r]->rrsigs;
- if (rrsigs != NULL) {
- dbg_zone("Adjusting next RRSIGs.\n");
- knot_zone_contents_adjust_rdata_in_rrset(rrsigs,
- zone,
- node);
- }
- }
+//static void knot_zone_contents_adjust_rrsets(knot_node_t *node,
+// knot_zone_contents_t *zone)
+//{
+// //return;
+// knot_rrset_t **rrsets = knot_node_get_rrsets(node);
+// short count = knot_node_rrset_count(node);
+
+// assert(count == 0 || rrsets != NULL);
+
+// for (int r = 0; r < count; ++r) {
+// assert(rrsets[r] != NULL);
+// dbg_zone("Adjusting next RRSet.\n");
+// knot_zone_contents_adjust_rdata_in_rrset(rrsets[r], zone,
+// node);
+// knot_rrset_t *rrsigs = rrsets[r]->rrsigs;
+// if (rrsigs != NULL) {
+// dbg_zone("Adjusting next RRSIGs.\n");
+// knot_zone_contents_adjust_rdata_in_rrset(rrsigs,
+// zone,
+// node);
+// }
+// }
- free(rrsets);
-}
+// free(rrsets);
+//}
/*----------------------------------------------------------------------------*/
/*!
@@ -480,7 +480,12 @@ dbg_zone_exec(
);
// adjust domain names in RDATA
- knot_zone_contents_adjust_rrsets(node, zone);
+ /*!
+ * \note This is unnecessary, as the code in adjust_rdata_item() is not
+ * reachable anyway. However, it's not clear why we disabled the
+ * code, so this would need further investigation.
+ */
+ //knot_zone_contents_adjust_rrsets(node, zone);
dbg_zone_exec(
if (knot_node_parent(node)) {
@@ -1294,7 +1299,7 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
knot_zone_contents_dnames_from_node_to_table(
zone->dname_table, next_node);
if (ret != KNOT_EOK) {
- /*! \todo Will next_node leak? */
+ knot_node_free(&next_node, 0);
knot_dname_release(chopped);
return ret;
}
@@ -1594,7 +1599,10 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone,
// how to know if this is successfull??
// TREE_INSERT(zone->nsec3_nodes, knot_node, avl, node);
- knot_zone_tree_insert(zone->nsec3_nodes, node);
+ ret = knot_zone_tree_insert(zone->nsec3_nodes, node);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
if (use_domain_table) {
ret = knot_zone_contents_dnames_from_node_to_table(
@@ -2228,45 +2236,51 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone)
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 the NSEC3 nodes first.
+ * There are independent on the normal nodes, but the normal nodes are
+ * dependent on them.
+ */
+
+ dbg_zone("Adjusting NSEC3 nodes.\n");
+ int 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 normal nodes: %s\n",
+ dbg_zone("Failed to adjust NSEC3 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);
-
+ // 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);
+ }
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,
+ dbg_zone("Adjusting normal nodes.\n");
+ 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 NSEC3 nodes: %s\n",
+ 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");
- // 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;
}
@@ -2364,7 +2378,8 @@ int knot_zone_contents_load_nsec3param(knot_zone_contents_t *zone)
KNOT_RRTYPE_NSEC3PARAM);
if (rrset != NULL) {
- knot_nsec3_params_from_wire(&zone->nsec3_params, rrset);
+ int r = knot_nsec3_params_from_wire(&zone->nsec3_params, rrset);
+ assert(r == KNOT_EOK);
} else {
memset(&zone->nsec3_params, 0, sizeof(knot_nsec3_params_t));
}
@@ -3388,7 +3403,7 @@ int knot_zc_integrity_check_child_count(check_data_t *data)
// 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",
+ dbg_zone("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,
diff --git a/src/libknot/zone/zone-contents.h b/src/libknot/zone/zone-contents.h
index 24fbcac..d31bbbb 100644
--- a/src/libknot/zone/zone-contents.h
+++ b/src/libknot/zone/zone-contents.h
@@ -49,14 +49,16 @@ typedef struct knot_zone_contents_t {
knot_zone_tree_t *nodes;
knot_zone_tree_t *nsec3_nodes;
- /*!
- * \todo Unify the use of this field - authoritative nodes vs. all.
- */
- uint node_count;
-
knot_dname_table_t *dname_table;
+ struct knot_zone *zone;
+
knot_nsec3_params_t nsec3_params;
+
+ /*!
+ * \todo Unify the use of this field - authoritative nodes vs. all.
+ */
+ uint node_count;
/*! \brief Generation of the zone during update.
*
@@ -67,8 +69,6 @@ typedef struct knot_zone_contents_t {
* used, no matter their generation.
*/
short generation;
-
- struct knot_zone *zone;
} knot_zone_contents_t;
/*----------------------------------------------------------------------------*/
diff --git a/src/libknot/zone/zone-tree.c b/src/libknot/zone/zone-tree.c
index de5df18..2b79f86 100644
--- a/src/libknot/zone/zone-tree.c
+++ b/src/libknot/zone/zone-tree.c
@@ -318,6 +318,24 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
*found = (exact_match > 0) ? f->node : NULL;
+dbg_zone_exec_detail(
+ char *name = knot_dname_to_str(owner);
+ char *name_f = (f != NULL)
+ ? knot_dname_to_str(knot_node_owner(f->node))
+ : "none";
+
+ dbg_zone_detail("Searched for owner %s in zone tree.\n",
+ name);
+ dbg_zone_detail("Exact match: %d\n", exact_match);
+ dbg_zone_detail("Found node: %p: %s.\n", f, name_f);
+ dbg_zone_detail("Previous node: %p.\n", prev);
+
+ free(name);
+ if (f != NULL) {
+ free(name_f);
+ }
+);
+
if (exact_match < 0) {
// previous is not really previous but should be the leftmost
// node in the tree; take it's previous
@@ -325,18 +343,6 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
*previous = knot_node_get_previous(prev->node);
exact_match = 0;
} else if (prev == NULL) {
- if (!exact_match) {
- printf("Searched for owner %s in zone tree.\n",
- knot_dname_to_str(owner));
- printf("Exact match: %d\n", exact_match);
- printf("Found node: %p: %s.\n", f, (f)
- ? knot_dname_to_str(knot_node_owner(f->node))
- : "none");
- printf("Previous node: %p: %s.\n", prev, (prev)
- ? knot_dname_to_str(knot_node_owner(prev->node))
- : "none");
- }
-
// either the returned node is the root of the tree, or
// it is the leftmost node in the tree; in both cases
// node was found set the previous node of the found
diff --git a/src/libknot/zone/zone.c b/src/libknot/zone/zone.c
index 9de1a53..122b014 100644
--- a/src/libknot/zone/zone.c
+++ b/src/libknot/zone/zone.c
@@ -25,14 +25,11 @@
#include "zone/zone.h"
#include "zone/node.h"
#include "dname.h"
-#include "consts.h"
#include "util/descriptor.h"
#include "nsec3.h"
#include "util/error.h"
#include "util/debug.h"
#include "util/utils.h"
-#include "common/tree.h"
-#include "common/base32hex.h"
#include "hash/cuckoo-hash-table.h"
#include "zone/zone-contents.h"
diff --git a/src/libknot/zone/zonedb.c b/src/libknot/zone/zonedb.c
index 7b445dd..a9b6545 100644
--- a/src/libknot/zone/zonedb.c
+++ b/src/libknot/zone/zonedb.c
@@ -294,16 +294,22 @@ knot_zonedb_t *knot_zonedb_copy(const knot_zonedb_t *db)
return db_new;
}
+/*----------------------------------------------------------------------------*/
+
size_t knot_zonedb_zone_count(const knot_zonedb_t *db)
{
return db->zone_count;
}
+/*----------------------------------------------------------------------------*/
+
struct knot_zone_db_tree_arg {
const knot_zone_t **zones;
size_t count;
};
+/*----------------------------------------------------------------------------*/
+
static void save_zone_to_array(void *node, void *data)
{
knot_zone_t *zone = (knot_zone_t *)node;
@@ -313,15 +319,16 @@ static void save_zone_to_array(void *node, void *data)
args->zones[args->count++] = zone;
}
+/*----------------------------------------------------------------------------*/
+
const knot_zone_t **knot_zonedb_zones(const knot_zonedb_t *db)
{
struct knot_zone_db_tree_arg args;
- args.zones = malloc(sizeof(knot_zone_t) * db->zone_count);
+ args.zones = malloc(sizeof(knot_zone_t *) * db->zone_count);
args.count = 0;
CHECK_ALLOC_LOG(args.zones, NULL);
- gen_tree_apply_inorder(db->zone_tree, save_zone_to_array,
- &args);
+ gen_tree_apply_inorder(db->zone_tree, save_zone_to_array, &args);
assert(db->zone_count == args.count);
return args.zones;
diff --git a/src/tests/common/acl_tests.c b/src/tests/common/acl_tests.c
index a7613e7..ea7b653 100644
--- a/src/tests/common/acl_tests.c
+++ b/src/tests/common/acl_tests.c
@@ -34,7 +34,7 @@ unit_api acl_tests_api = {
static int acl_tests_count(int argc, char *argv[])
{
- return 13;
+ return 18;
}
static int acl_tests_run(int argc, char *argv[])
@@ -54,17 +54,17 @@ static int acl_tests_run(int argc, char *argv[])
ok(ret > 0, "acl: new IPv6 address");
// 4. Create simple IPv4 rule
- ret = acl_create(acl, &test_v4, ACL_ACCEPT, 0);
+ ret = acl_create(acl, &test_v4, ACL_ACCEPT, 0, 0);
ok(ret == ACL_ACCEPT, "acl: inserted IPv4 rule");
// 5. Create simple IPv6 rule
- ret = acl_create(acl, &test_v6, ACL_ACCEPT, 0);
+ ret = acl_create(acl, &test_v6, ACL_ACCEPT, 0, 0);
ok(ret == ACL_ACCEPT, "acl: inserted IPv6 rule");
// 6. Create simple IPv4 'any port' rule
sockaddr_t test_v4a;
sockaddr_set(&test_v4a, AF_INET, "20.20.20.20", 0);
- ret = acl_create(acl, &test_v4a, ACL_ACCEPT, 0);
+ ret = acl_create(acl, &test_v4a, ACL_ACCEPT, 0, 0);
ok(ret == ACL_ACCEPT, "acl: inserted IPv4 'any port' rule");
// 7. Attempt to match unmatching address
@@ -94,19 +94,60 @@ static int acl_tests_run(int argc, char *argv[])
ok(ret == ACL_ACCEPT, "acl: matching existing IPv4 'any port' address");
// 12. Attempt to match matching address without matching port
+ skip(1, 1) {
sockaddr_set(&unmatch_v4, AF_INET, "127.0.0.1", 54321);
ret = acl_match(acl, &unmatch_v4, 0);
ok(ret == ACL_DENY, "acl: matching address without matching port");
+ } endskip;
// 13. Invalid parameters
lives_ok({
acl_delete(0);
- acl_create(0, 0, ACL_ERROR, 0);
+ acl_create(0, 0, ACL_ERROR, 0, 0);
acl_match(0, 0, 0);
acl_truncate(0);
acl_name(0);
}, "acl: won't crash with NULL parameters");
+ // 14. Attempt to match subnet
+ sockaddr_t match_pf4, test_pf4;
+ sockaddr_set(&match_pf4, AF_INET, "192.168.1.0", 0);
+ sockaddr_setprefix(&match_pf4, 24);
+ acl_create(acl, &match_pf4, ACL_ACCEPT, 0, 0);
+ sockaddr_set(&test_pf4, AF_INET, "192.168.1.20", 0);
+ ret = acl_match(acl, &test_pf4, 0);
+ ok(ret == ACL_ACCEPT, "acl: searching address in matching prefix /24");
+
+ // 15. Attempt to search non-matching subnet
+ sockaddr_set(&test_pf4, AF_INET, "192.168.2.20", 0);
+ ret = acl_match(acl, &test_pf4, 0);
+ ok(ret == ACL_DENY, "acl: searching address in non-matching prefix /24");
+
+ // 16. Attempt to match v6 subnet
+ sockaddr_t match_pf6, test_pf6;
+ sockaddr_set(&match_pf6, AF_INET6, "2001:0DB8:0400:000e:0:0:0:AB00", 0);
+ sockaddr_setprefix(&match_pf6, 120);
+ acl_create(acl, &match_pf6, ACL_ACCEPT, 0, 0);
+ sockaddr_set(&test_pf6, AF_INET6, "2001:0DB8:0400:000e:0:0:0:AB03", 0);
+ ret = acl_match(acl, &test_pf6, 0);
+ ok(ret == ACL_ACCEPT, "acl: searching v6 address in matching prefix /120");
+
+ // 17. Attempt to search non-matching subnet
+ sockaddr_set(&test_pf6, AF_INET6, "2001:0DB8:0400:000e:0:0:0:CCCC", 0);
+ ret = acl_match(acl, &test_pf6, 0);
+ ok(ret == ACL_DENY, "acl: searching v6 address in non-matching prefix /120");
+
+ // 18. Add preferred node
+ sockaddr_set(&test_pf4, AF_INET, "192.168.1.20", 0);
+ void *sval = (void*)0x1234;
+ acl_create(acl, &match_pf4, ACL_ACCEPT, sval, ACL_PREFER);
+ acl_create(acl, &match_pf4, ACL_ACCEPT, 0, 0); /* Make decoy. */
+ acl_key_t *rval = NULL;
+ ret = acl_match(acl, &test_pf4, &rval);
+ ok(rval->val == sval, "acl: search for preferred node");
+
+ acl_delete(&acl);
+
// Return
return 0;
}
diff --git a/src/tests/knot/journal_tests.c b/src/tests/knot/journal_tests.c
index 21c92fe..420300e 100644
--- a/src/tests/knot/journal_tests.c
+++ b/src/tests/knot/journal_tests.c
@@ -34,7 +34,7 @@ unit_api journal_tests_api = {
/*
* Unit implementation.
*/
-static const int JOURNAL_TEST_COUNT = 11;
+static const int JOURNAL_TEST_COUNT = 12;
/*! \brief Generate random string with given length. */
static int randstr(char* dst, size_t len)
@@ -83,8 +83,11 @@ static int journal_tests_run(int argc, char *argv[])
ok(ret == KNOTD_EOK, "journal: create journal '%s'", jfilename);
/* Test 3: Open journal. */
- journal_t *j = journal_open(jfilename, fsize, 0);
- ok(j != 0, "journal: open");
+ journal_t *journal = journal_open(jfilename, fsize, JOURNAL_LAZY, 0);
+ ok(journal != 0, "journal: open");
+
+ /* Retain journal. */
+ journal_t *j = journal_retain(journal);
/* Test 4: Write entry to log. */
const char *sample = "deadbeef";
@@ -124,17 +127,25 @@ static int journal_tests_run(int argc, char *argv[])
ok(ret == 0, "journal: read data integrity check 3 '%s'", _walkbuf);
_wbi = 0;
+ /* Test 9: Attempt to retain and release. */
+ journal_t *tmp = journal_retain(j);
+ ok(tmp == j, "journal: tested journal retaining");
+ journal_release(tmp);
+
+ /* Release journal. */
+ journal_release(j);
+
/* Close journal. */
- journal_close(j);
+ journal_close(journal);
- /* Recreate journal. */
+ /* Recreate journal = NORMAL mode. */
remove(jfilename);
fsize = 8092;
jsize = 512;
ret = journal_create(jfilename, jsize);
- j = journal_open(jfilename, fsize, 0);
+ j = journal_open(jfilename, fsize, 0, 0);
- /* Test 9: Write random data. */
+ /* Test 10: Write random data. */
int chk_key = 0;
char chk_buf[64] = {'\0'};
ret = 0;
@@ -155,16 +166,16 @@ static int journal_tests_run(int argc, char *argv[])
}
ok(ret == 0, "journal: sustained looped writes");
- /* Test 10: Check data integrity. */
+ /* Test 11: Check data integrity. */
memset(tmpbuf, 0, sizeof(tmpbuf));
journal_read(j, chk_key, 0, tmpbuf);
ret = strncmp(chk_buf, tmpbuf, sizeof(chk_buf));
ok(ret == 0, "journal: read data integrity check");
- /* Test 11: Reopen log and re-read value. */
+ /* Test 12: Reopen log and re-read value. */
memset(tmpbuf, 0, sizeof(tmpbuf));
journal_close(j);
- j = journal_open(jfilename, fsize, 0);
+ j = journal_open(jfilename, fsize, 0, 0);
journal_read(j, chk_key, 0, tmpbuf);
ret = strncmp(chk_buf, tmpbuf, sizeof(chk_buf));
ok(ret == 0, "journal: read data integrity check after close/open");
diff --git a/src/tests/libknot/libknot/node_tests.c b/src/tests/libknot/libknot/node_tests.c
index d6b1e48..10b01fa 100644
--- a/src/tests/libknot/libknot/node_tests.c
+++ b/src/tests/libknot/libknot/node_tests.c
@@ -44,13 +44,13 @@ struct test_node {
};
static knot_dname_t test_dnames[TEST_NODES] = {
- {{}, (uint8_t *)"\3www\7example\3com", 17},
- {{}, (uint8_t *)"\3www\7example\3com", 17}
+ {{}, (uint8_t *)"\3www\7example\3com", NULL, NULL, 0, 17},
+ {{}, (uint8_t *)"\3www\7example\3com", NULL, NULL, 0, 17}
};
static struct test_node test_nodes[TEST_NODES] = {
- {{{}, (uint8_t *)"\3com", 4}, (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\3www\7example\3com", 17}, (knot_node_t *)NULL}
+ {{{}, (uint8_t *)"\3com", NULL, NULL, 0, 4}, (knot_node_t *)NULL},
+ {{{}, (uint8_t *)"\3www\7example\3com", NULL, NULL, 0, 17}, (knot_node_t *)NULL}
};
static knot_rrset_t rrsets[RRSETS] = {
diff --git a/src/tests/libknot/libknot/rdata_tests.c b/src/tests/libknot/libknot/rdata_tests.c
index 561686a..0c53613 100644
--- a/src/tests/libknot/libknot/rdata_tests.c
+++ b/src/tests/libknot/libknot/rdata_tests.c
@@ -80,10 +80,10 @@ static uint16_t *RDATA_ITEM_PTR = (uint16_t *)0xDEADBEEF;
enum { RDATA_ITEMS_COUNT = 7, TEST_RDATA_COUNT = 4 , RDATA_DNAMES_COUNT = 2 };
static knot_dname_t RDATA_DNAMES[RDATA_DNAMES_COUNT] = {
- {{}, (uint8_t *)"\6abcdef\7example\3com", 20,
- (uint8_t *)"\x0\x7\xF", 3},
- {{}, (uint8_t *)"\6abcdef\3foo\3com", 16,
- (uint8_t *)"\x0\x7\xB", 3}
+ {{}, (uint8_t *)"\6abcdef\7example\3com", (uint8_t *)"\x0\x7\xF",
+ NULL, 0, 20, 3},
+ {{}, (uint8_t *)"\6abcdef\3foo\3com", (uint8_t *)"\x0\x7\xB", NULL, 0,
+ 16, 3}
};
static knot_rdata_item_t TEST_RDATA_ITEMS[RDATA_ITEMS_COUNT] = {
diff --git a/src/tests/libknot/libknot/rrset_tests.c b/src/tests/libknot/libknot/rrset_tests.c
index fa75195..41284df 100644
--- a/src/tests/libknot/libknot/rrset_tests.c
+++ b/src/tests/libknot/libknot/rrset_tests.c
@@ -80,9 +80,9 @@ enum {
enum { TEST_DOMAINS_OK = 8 };
static knot_dname_t RR_DNAMES[RR_DNAMES_COUNT] =
- { {{}, (uint8_t *)"\7example\3com", 13, NULL}, //0's at the end are added
- {{}, (uint8_t *)"\3ns1\7example\3com", 17, NULL},
- {{}, (uint8_t *)"\3ns2\7example\3com", 17, NULL} };
+ { {{}, (uint8_t *)"\7example\3com", NULL, NULL, 0, 13, 0}, //0's at the end are added
+ {{}, (uint8_t *)"\3ns1\7example\3com", NULL, NULL, 0, 17, 0},
+ {{}, (uint8_t *)"\3ns2\7example\3com", NULL, NULL, 0, 17, 0} };
/* 192.168.1.1 */
static uint8_t address[4] = {0xc0, 0xa8, 0x01, 0x01};
diff --git a/src/tests/libknot/libknot/tsig_tests.c b/src/tests/libknot/libknot/tsig_tests.c
index 31720ec..e0a3d34 100644
--- a/src/tests/libknot/libknot/tsig_tests.c
+++ b/src/tests/libknot/libknot/tsig_tests.c
@@ -86,7 +86,7 @@ static int test_knot_tsig_sign()
int errors = 0;
/* Test bad arguments. */
int lived = 0;
- lives_ok_silent({
+ lives_ok({
int ret = knot_tsig_sign(NULL, NULL, 0, NULL, 0, NULL,
NULL, NULL, 0, 0);
if (ret != KNOT_EBADARG) {
@@ -143,7 +143,7 @@ static int test_knot_tsig_sign()
errors++;
}
lived = 1;
- }, NULL);
+ }, "");
errors += !lived;
@@ -301,7 +301,7 @@ static int test_knot_tsig_sign_next()
int errors = 0;
/* Test bad arguments. */
int lived = 0;
- lives_ok_silent({
+ lives_ok({
int ret = knot_tsig_sign_next(NULL, NULL, 0, NULL, 0, NULL,
NULL, NULL, NULL, 0); /*! \todo FIX */
if (ret != KNOT_EBADARG) {
@@ -359,7 +359,7 @@ static int test_knot_tsig_sign_next()
errors++;
}
lived = 1;
- }, NULL);
+ }, "");
errors += !lived;
@@ -416,7 +416,7 @@ static int test_knot_tsig_server_check()
int errors = 0;
/* Test bad arguments. */
int lived = 0;
- lives_ok_silent({
+ lives_ok({
int ret = knot_tsig_server_check(NULL, NULL, 0, NULL);
if (ret != KNOT_EBADARG) {
diag("NULL argument did not return KNOT_EBADARG!");
@@ -433,7 +433,7 @@ static int test_knot_tsig_server_check()
errors++;
}
lived = 1;
- }, NULL);
+ }, "");
errors += !lived;
@@ -524,7 +524,7 @@ static int test_knot_tsig_client_check()
errors++;
}
lived = 1;
- }, NULL);
+ }, "");
errors += !lived;
@@ -632,7 +632,7 @@ static int test_knot_tsig_test_tsig_add()
errors++;
}
lived = 1;
- }, NULL);
+ }, "");
errors += !lived;
diff --git a/src/tests/libknot/libknot/zone_tests.c b/src/tests/libknot/libknot/zone_tests.c
index 192996c..72aae39 100644
--- a/src/tests/libknot/libknot/zone_tests.c
+++ b/src/tests/libknot/libknot/zone_tests.c
@@ -46,27 +46,27 @@ struct zone_test_node {
};
static struct zone_test_node test_apex =
-{{{}, (uint8_t *)"\3com\0", 5, (uint8_t *)"\x0", 1}, (knot_node_t *)NULL};
+{{{}, (uint8_t *)"\3com\0", (uint8_t *)"\x0", NULL, 0, 5, 1}, (knot_node_t *)NULL};
static struct zone_test_node test_nodes_bad[TEST_NODES_BAD] = {
- {{{},(uint8_t *)"\5other\6domain\0", 14, (uint8_t *)"\x0\x6", 2},
+ {{{},(uint8_t *)"\5other\6domain\0", (uint8_t *)"\x0\x6", NULL, 0, 14, 2},
(knot_node_t *)NULL}
};
static struct zone_test_node test_nodes_good[TEST_NODES_GOOD] = {
- {{{}, (uint8_t *)"\7example\3com\0", 13, (uint8_t *)"\x0\x8", 2},
+ {{{}, (uint8_t *)"\7example\3com\0", (uint8_t *)"\x0\x8", NULL, 0, 13, 2},
(knot_node_t *)NULL},
- {{{}, (uint8_t *)"\3www\7example\3com\0", 17, (uint8_t *)"\x0\x4\xC", 3},
+ {{{}, (uint8_t *)"\3www\7example\3com\0", (uint8_t *)"\x0\x4\xC", NULL, 0, 17, 3},
(knot_node_t *)NULL},
- {{{}, (uint8_t *)"\7another\6domain\3com\0", 20, (uint8_t *)"\x0\x8\xF", 3},
+ {{{}, (uint8_t *)"\7another\6domain\3com\0", (uint8_t *)"\x0\x8\xF", NULL, 0, 20, 3},
(knot_node_t *)NULL},
- {{{}, (uint8_t *)"\5mail1\7example\3com\0", 19, (uint8_t *)"\x0\x6\xE", 3},
+ {{{}, (uint8_t *)"\5mail1\7example\3com\0", (uint8_t *)"\x0\x6\xE", NULL, 0, 19, 3},
(knot_node_t *)NULL},
- {{{}, (uint8_t *)"\5mail2\7example\3com\0", 19, (uint8_t *)"\x0\x6\xE", 3},
+ {{{}, (uint8_t *)"\5mail2\7example\3com\0", (uint8_t *)"\x0\x6\xE", NULL, 0, 19, 3},
(knot_node_t *)NULL},
- {{{}, (uint8_t *)"\3smb\7example\3com\0", 17, (uint8_t *)"\x0\x4\xC", 3},
+ {{{}, (uint8_t *)"\3smb\7example\3com\0", (uint8_t *)"\x0\x4\xC", NULL, 0, 17, 3},
(knot_node_t *)NULL},
- {{{}, (uint8_t *)"\4smtp\7example\3com\0", 18, (uint8_t *)"\x0\x5\xD", 3},
+ {{{}, (uint8_t *)"\4smtp\7example\3com\0", (uint8_t *)"\x0\x5\xD", NULL, 0, 18, 3},
(knot_node_t *)NULL},
};
diff --git a/src/zcompile/parser-util.c b/src/zcompile/parser-util.c
index 9e2e999..dde5411 100644
--- a/src/zcompile/parser-util.c
+++ b/src/zcompile/parser-util.c
@@ -2063,7 +2063,7 @@ uint16_t * zparser_conv_loc(char *str)
return NULL;
}
- if (sscanf(start, "%lf", &d) != 1) {
+ if (sscanf(start, "%16lf", &d) != 1) {
zc_error_prev_line("error parsing seconds");
}
@@ -2161,7 +2161,7 @@ uint16_t * zparser_conv_loc(char *str)
++str;
}
- if (sscanf(start, "%lf", &d) != 1) {
+ if (sscanf(start, "%16lf", &d) != 1) {
zc_error_prev_line("error parsing altitude");
}
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
index f02fdcf..25de281 100644
--- a/src/zcompile/zcompile.c
+++ b/src/zcompile/zcompile.c
@@ -33,12 +33,11 @@
#include <string.h>
#include <stdlib.h>
#include <assert.h>
+#include <sys/stat.h>
#include "common/base32hex.h"
#include "zcompile/zcompile.h"
#include "zcompile/parser-util.h"
-#include "knot/zone/zone-dump-text.h"
-#include "zparser.h"
#include "zcompile/zcompile-error.h"
#include "knot/zone/zone-dump.h"
#include "libknot/libknot.h"
@@ -55,9 +54,7 @@ static long int totalrrs = 0;
extern FILE *zp_get_in(void *scanner);
-//#define ZP_DEBUG
-
-#ifdef ZP_DEBUG
+#ifdef KNOT_COMPILER_DEBUG
#define dbg_zp(msg...) fprintf(stderr, msg)
#else
#define dbg_zp(msg...)
@@ -122,23 +119,33 @@ static int find_rrset_for_rrsig_in_zone(knot_zone_contents_t *zone,
knot_node_t *tmp_node = NULL;
- if (rrsig->type != KNOT_RRTYPE_NSEC3) {
+ if (knot_rdata_rrsig_type_covered(knot_rrset_rdata(rrsig))
+ != KNOT_RRTYPE_NSEC3) {
tmp_node = knot_zone_contents_get_node(zone, rrsig->owner);
} else {
tmp_node = knot_zone_contents_get_nsec3_node(zone,
rrsig->owner);
}
+
+ dbg_zp("Found this node for RRSIG: %p\n",
+ tmp_node);
if (tmp_node == NULL) {
return KNOTDZCOMPILE_EINVAL;
}
knot_rrset_t *tmp_rrset =
- knot_node_get_rrset(tmp_node, rrsig->type);
+ knot_node_get_rrset(tmp_node,
+ knot_rdata_rrsig_type_covered(
+ rrsig->rdata));
+
+ dbg_zp("Found this rrset for RRSIG: %p\n",
+ tmp_rrset);
if (tmp_rrset == NULL) {
return KNOTDZCOMPILE_EINVAL;
}
+
if (tmp_rrset->rrsigs != NULL) {
knot_zone_contents_add_rrsigs(zone, rrsig, &tmp_rrset, &tmp_node,
@@ -299,7 +306,6 @@ int process_rr(void)
}
if (current_rrset->type == KNOT_RRTYPE_RRSIG) {
- /*!< \todo Still a leak somewhere. */
knot_rrset_t *tmp_rrsig =
knot_rrset_new(current_rrset->owner,
KNOT_RRTYPE_RRSIG,
@@ -310,7 +316,8 @@ int process_rr(void)
}
if (knot_rrset_add_rdata(tmp_rrsig,
- current_rrset->rdata) != 0) {
+ current_rrset->rdata) != KNOT_EOK) {
+ knot_rrset_free(&tmp_rrsig);
return KNOTDZCOMPILE_EBRDATA;
}
@@ -325,12 +332,29 @@ int process_rr(void)
parser->last_node);
rrset_list_delete(&parser->node_rrsigs);
}
-
- if ((parser->last_node = create_node(contents,
- current_rrset, node_add_func,
- node_get_func)) == NULL) {
- knot_rrset_free(&tmp_rrsig);
- return KNOTDZCOMPILE_EBADNODE;
+
+ /* The node might however been created previously. */
+ parser->last_node =
+ knot_zone_contents_get_node(contents,
+ knot_rrset_owner(current_rrset));
+
+ if (parser->last_node == NULL) {
+ /* Try NSEC3 tree. */
+ parser->last_node =
+ knot_zone_contents_get_nsec3_node(
+ contents,
+ knot_rrset_owner(
+ current_rrset));
+ }
+
+ if (parser->last_node == NULL) {
+ /* Still NULL, node has to be created. */
+ if ((parser->last_node = create_node(contents,
+ current_rrset, node_add_func,
+ node_get_func)) == NULL) {
+ knot_rrset_free(&tmp_rrsig);
+ return KNOTDZCOMPILE_EBADNODE;
+ }
}
}
@@ -435,6 +459,10 @@ static uint find_rrsets_orphans(knot_zone_contents_t *zone, rrset_list_t
knot_rrtype_to_string(head->data->type));
}
else { /* we can throw it away now */
+ dbg_zp("RRSet not found for RRSIG: %s (%s)\n",
+ knot_dname_to_str(head->data->owner),
+ knot_rrtype_to_string(
+ knot_rdata_rrsig_type_covered(head->data->rdata)));
knot_rrset_free(&head->data);
}
head = head->next;
@@ -442,16 +470,6 @@ static uint find_rrsets_orphans(knot_zone_contents_t *zone, rrset_list_t
return found_rrsets;
}
-/*
- *
- * Opens a zone file.
- *
- * Returns:
- *
- * - pointer to the parser structure
- * - NULL on error and errno set
- *
- */
static int zone_open(const char *filename, uint32_t ttl, uint16_t rclass,
knot_node_t *origin, void *scanner, knot_dname_t *origin_from_config)
{
@@ -470,25 +488,13 @@ static int zone_open(const char *filename, uint32_t ttl, uint16_t rclass,
}
}
-// int fd = fileno(zp_get_in(scanner));
-// if (fd == -1) {
-// return 0;
-// }
-
-// if (fcntl(fd, F_SETLK, knot_file_lock(F_RDLCK, SEEK_SET)) == -1) {
-// fprintf(stderr, "Could not lock zone file for read!\n");
-// return 0;
-// }
+ /*!< \todo #1676 Implement proper locking. */
zparser_init(filename, ttl, rclass, origin, origin_from_config);
return 1;
}
-/*
- * Reads the specified zone into the memory
- *
- */
int zone_read(const char *name, const char *zonefile, const char *outfile,
int semantic_checks)
{
@@ -507,35 +513,40 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
}
fclose(f);
-
-// char ebuf[256];
-
knot_dname_t *dname =
knot_dname_new_from_str(name, strlen(name), NULL);
if (dname == NULL) {
return KNOTDZCOMPILE_ENOMEM;
}
+ if (!knot_dname_is_fqdn(dname)) {
+ fprintf(stderr, "Error: given zone origin is not FQDN.\n");
+ knot_dname_release(dname);
+ return KNOTDZCOMPILE_EINVAL;
+ }
+
knot_node_t *origin_node = knot_node_new(dname, NULL, 0);
+ if (origin_node == NULL) {
+ knot_dname_release(dname);
+ return KNOTDZCOMPILE_ENOMEM;
+ }
+
+ assert(knot_node_parent(origin_node) == NULL);
+
/*!< \todo Another copy is probably not needed. */
knot_dname_t *origin_from_config =
knot_dname_new_from_str(name, strlen(name), NULL);
if (origin_from_config == NULL) {
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- //assert(origin_node->next == NULL);
-
- assert(knot_node_parent(origin_node) == NULL);
- if (origin_node == NULL) {
- knot_dname_release(dname);
+ knot_node_free(&origin_node, 0);
return KNOTDZCOMPILE_ENOMEM;
}
void *scanner = NULL;
zp_lex_init(&scanner);
if (scanner == NULL) {
+ knot_dname_release(origin_from_config);
+ knot_node_free(&origin_node, 0);
return KNOTDZCOMPILE_ENOMEM;
}
@@ -544,20 +555,18 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
zc_error_prev_line("Cannot open '%s'\n",
zonefile);
zparser_free();
+ zp_lex_destroy(scanner);
+ knot_dname_release(origin_from_config);
+ knot_node_free(&origin_node, 0);
return KNOTDZCOMPILE_EZONEINVAL;
}
if (zp_parse(scanner) != 0) {
-// int fd = fileno(zp_get_in(scanner));
-// if (fcntl(fd, F_SETLK,
-// knot_file_lock(F_UNLCK, SEEK_SET)) == -1) {
-// return KNOTDZCOMPILE_EACCES;
-// }
-
+ /*!< \todo #1676 Implement proper locking. */
FILE *in_file = (FILE *)zp_get_in(scanner);
fclose(in_file);
zp_lex_destroy(scanner);
-
+ knot_node_free(&origin_node, 0);
return KNOTDZCOMPILE_ESYNT;
}
@@ -567,13 +576,8 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
FILE *in_file = (FILE *)zp_get_in(scanner);
fclose(in_file);
zp_lex_destroy(scanner);
-
- /* Unlock zone file. */
-// int fd = fileno(zp_get_in(scanner));
-// if (fcntl(fd, F_SETLK, knot_file_lock(F_UNLCK, SEEK_SET)) == -1) {
-// fprintf(stderr, "Could not lock zone file for read!\n");
-// return 0;
-// }
+
+ /*!< \todo #1676 Implement proper locking. */
dbg_zp("zp complete %p\n", parser->current_zone);
@@ -592,6 +596,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
zc_error_prev_line("Zone file does not contain SOA record!\n");
knot_zone_deep_free(&parser->current_zone, 1);
zparser_free();
+ knot_node_free(&origin_node, 0);
return KNOTDZCOMPILE_EZONEINVAL;
}
@@ -604,6 +609,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
rrset_list_delete(&parser->rrsig_orphans);
if (found_orphans != parser->rrsig_orphan_count) {
+ /*! \todo This might be desired behaviour. */
fprintf(stderr,
"There are unassigned RRSIGs in the zone!\n");
parser->errors++;
@@ -618,12 +624,49 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
fprintf(stderr,
"Parser finished with error, not dumping the zone!\n");
} else {
- if (knot_zdump_binary(contents,
- outfile, semantic_checks,
- zonefile) != 0) {
- fprintf(stderr, "Could not dump zone!\n");
+ int fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG);
+ if (fd < 0) {
+ fprintf(stderr,
+ "Could not open destination file for db: %s.\n",
+ outfile);
totalerrors++;
+ } else {
+ crc_t crc;
+ int ret = knot_zdump_binary(contents, fd,
+ semantic_checks,
+ zonefile, &crc);
+ if (ret != KNOT_EOK) {
+ fprintf(stderr, "Could not dump zone, reason: "
+ "%s.\n", knot_strerror(ret));
+ remove(outfile);
+ totalerrors++;
+ } else {
+ /* Write CRC file. */
+ char *crc_path = knot_zdump_crc_file(outfile);
+ if (crc_path == NULL) {
+ fprintf(stderr,
+ "Could not get crc file path.\n");
+ remove(outfile);
+ totalerrors++;
+ } else {
+ FILE *f_crc = fopen(crc_path, "w");
+ if (f_crc == NULL) {
+ fprintf(stderr,
+ "Could not open crc file \n");
+ remove(outfile);
+ totalerrors++;
+ } else {
+ fprintf(f_crc,
+ "%lu",
+ (unsigned long)crc);
+ fclose(f_crc);
+ }
+ }
+ free(crc_path);
+ }
}
+
+
dbg_zp("zone dumped.\n");
}
diff --git a/src/zcompile/zcompile.h b/src/zcompile/zcompile.h
index 33dd3ee..37b3791 100644
--- a/src/zcompile/zcompile.h
+++ b/src/zcompile/zcompile.h
@@ -142,6 +142,7 @@ struct zparser {
rrset_list_t *node_rrsigs; /*!< List of RRSIGs in current node. */
int rdata_count; /*!< Count of parsed rdata. */
+ int origin_directive; /*!< Set to 1 if $ORIGIN directive is present. */
};
typedef struct zparser zparser_type;
diff --git a/src/zcompile/zcompile_main.c b/src/zcompile/zcompile_main.c
index cb862f8..c02b780 100644
--- a/src/zcompile/zcompile_main.c
+++ b/src/zcompile/zcompile_main.c
@@ -19,8 +19,6 @@
#include <stdlib.h>
#include "zcompile/zcompile.h"
-#include "zcompile/zcompile-error.h"
-#include "common/errors.h"
#include <config.h>
static void help(int argc, char **argv)
diff --git a/src/zcompile/zparser.y b/src/zcompile/zparser.y
index c43b968..59f037d 100644
--- a/src/zcompile/zparser.y
+++ b/src/zcompile/zparser.y
@@ -307,11 +307,13 @@ ttl_directive: DOLLAR_TTL sp STR trail
origin_directive: DOLLAR_ORIGIN sp abs_dname trail
{
+ /*!< \todo this will leak. */
knot_node_t *origin_node = knot_node_new($3 ,NULL, 0);
if (parser->origin != NULL) {
// knot_node_free(&parser->origin, 1);
}
parser->origin = origin_node;
+ parser->origin_directive = 1;
}
| DOLLAR_ORIGIN sp rel_dname trail
{
@@ -392,7 +394,6 @@ dname: abs_dname
} else {
$$ = knot_dname_cat($1,
parser->origin->owner);
-// printf("leak: %s\n", knot_dname_to_str($$));
}
}
;
@@ -404,7 +405,12 @@ abs_dname: '.'
}
| '@'
{
+ if (parser->origin_directive) {
$$ = parser->origin->owner;
+ } else {
+ zc_error("@ used, but no $ORIGIN specified.\n");
+ $$ = parser->origin->owner;
+ }
}
| rel_dname '.'
{
@@ -422,10 +428,7 @@ label: STR
zc_error("label exceeds %d character limit", MAXLABELLEN);
$$ = error_dname;
} else {
-// printf("%s\n", $1.str);
$$ = knot_dname_new_from_str($1.str, $1.len, NULL);
-// printf("Creating new (label): %s %p\n", $1.str, $$);
-// printf("new: %p %s\n", $$, $1.str);
$$->ref.count = 0;
}
@@ -1620,6 +1623,8 @@ zparser_init(const char *filename, uint32_t ttl, uint16_t rclass,
parser->current_rrset->rclass = parser->default_class;
parser->current_rrset->rdata = NULL;
+
+ parser->origin_directive = 0;
}