diff --git a/Knot.files b/Knot.files
index ba5192f316da0259f4180e20d782567ce5f2f8a5..9b7bbf1982b314a259dacf5eb0a93bf006daf298 100644
--- a/Knot.files
+++ b/Knot.files
@@ -1,85 +1,84 @@
-Doxyfile
-KNOWN_ISSUES
-Makefile.am
-README
-configure.ac
-doc/Makefile.am
 doc/configuration.rst
 doc/index.rst
 doc/installation.rst
 doc/introduction.rst
+doc/Makefile.am
 doc/migration.rst
 doc/reference.rst
 doc/requirements.rst
 doc/running.rst
 doc/troubleshooting.rst
-libtap/Makefile.am
-libtap/runtests.c
 libtap/tap/basic.c
 libtap/tap/basic.h
 libtap/tap/float.c
 libtap/tap/float.h
 libtap/tap/macros.h
+libtap/Makefile.am
+libtap/runtests.c
 man/Makefile.am
 patches/Makefile.am
 samples/Makefile.am
-src/Makefile.am
-src/common-knot/array-sort.h
-src/common-knot/binsearch.h
-src/common-knot/crc.h
-src/common-knot/evsched.c
-src/common-knot/evsched.h
-src/common-knot/fdset.c
-src/common-knot/fdset.h
-src/common-knot/hattrie/hat-trie.c
-src/common-knot/hattrie/hat-trie.h
-src/common-knot/hattrie/murmurhash3.c
-src/common-knot/hattrie/murmurhash3.h
-src/common-knot/heap.c
-src/common-knot/heap.h
-src/common-knot/hex.c
-src/common-knot/hex.h
-src/common-knot/hhash.c
-src/common-knot/hhash.h
-src/common-knot/lists.c
-src/common-knot/lists.h
-src/common-knot/print.c
-src/common-knot/print.h
-src/common-knot/ref.c
-src/common-knot/ref.h
-src/common-knot/sockaddr.c
-src/common-knot/sockaddr.h
-src/common-knot/strlcat.c
-src/common-knot/strlcat.h
-src/common-knot/strlcpy.c
-src/common-knot/strlcpy.h
-src/common-knot/strtonum.h
-src/common-knot/trim.h
+src/common/namedb/namedb.h
+src/common/namedb/namedb_lmdb.c
+src/common/namedb/namedb_lmdb.h
+src/common/namedb/namedb_trie.c
+src/common/namedb/namedb_trie.h
+src/common/trie/hat-trie.c
+src/common/trie/hat-trie.h
+src/common/trie/murmurhash3.c
+src/common/trie/murmurhash3.h
+src/common/array-sort.h
 src/common/base32hex.c
 src/common/base32hex.h
 src/common/base64.c
 src/common/base64.h
+src/common/binsearch.h
 src/common/debug.h
 src/common/errors.c
 src/common/errors.h
 src/common/getline.c
 src/common/getline.h
+src/common/hhash.c
+src/common/hhash.h
+src/common/lists.c
+src/common/lists.h
 src/common/log.c
 src/common/log.h
+src/common/macros.h
 src/common/mem.c
 src/common/mem.h
+src/common/mempattern.c
+src/common/mempattern.h
 src/common/mempool.c
 src/common/mempool.h
-src/common/namedb/namedb.h
-src/common/namedb/namedb_lmdb.c
-src/common/namedb/namedb_lmdb.h
-src/common/namedb/namedb_trie.c
-src/common/namedb/namedb_trie.h
-src/dnstap/Makefile.am
+src/common/net.c
+src/common/net.h
+src/common/print.c
+src/common/print.h
+src/common/sockaddr.c
+src/common/sockaddr.h
+src/common/strlcpy.c
+src/common/strlcpy.h
+src/common-knot/crc.h
+src/common-knot/evsched.c
+src/common-knot/evsched.h
+src/common-knot/fdset.c
+src/common-knot/fdset.h
+src/common-knot/heap.c
+src/common-knot/heap.h
+src/common-knot/hex.c
+src/common-knot/hex.h
+src/common-knot/ref.c
+src/common-knot/ref.h
+src/common-knot/strlcat.c
+src/common-knot/strlcat.h
+src/common-knot/strtonum.h
+src/common-knot/trim.h
 src/dnstap/convert.c
 src/dnstap/convert.h
 src/dnstap/dnstap.c
 src/dnstap/dnstap.h
+src/dnstap/Makefile.am
 src/dnstap/message.c
 src/dnstap/message.h
 src/dnstap/reader.c
@@ -113,8 +112,6 @@ src/knot/dnssec/zone-nsec.c
 src/knot/dnssec/zone-nsec.h
 src/knot/dnssec/zone-sign.c
 src/knot/dnssec/zone-sign.h
-src/knot/knot.h
-src/knot/main.c
 src/knot/modules/dnstap.c
 src/knot/modules/dnstap.h
 src/knot/modules/synth_record.c
@@ -139,8 +136,6 @@ src/knot/nameserver/process_query.c
 src/knot/nameserver/process_query.h
 src/knot/nameserver/query_module.c
 src/knot/nameserver/query_module.h
-src/knot/nameserver/requestor.c
-src/knot/nameserver/requestor.h
 src/knot/nameserver/tsig_ctx.c
 src/knot/nameserver/tsig_ctx.h
 src/knot/nameserver/update.c
@@ -150,8 +145,6 @@ src/knot/server/dthreads.c
 src/knot/server/dthreads.h
 src/knot/server/journal.c
 src/knot/server/journal.h
-src/knot/server/net.c
-src/knot/server/net.h
 src/knot/server/rrl.c
 src/knot/server/rrl.h
 src/knot/server/serialization.c
@@ -176,14 +169,14 @@ src/knot/worker/pool.c
 src/knot/worker/pool.h
 src/knot/worker/queue.c
 src/knot/worker/queue.h
-src/knot/zone/contents.c
-src/knot/zone/contents.h
 src/knot/zone/events/events.c
 src/knot/zone/events/events.h
 src/knot/zone/events/handlers.c
 src/knot/zone/events/handlers.h
 src/knot/zone/events/replan.c
 src/knot/zone/events/replan.h
+src/knot/zone/contents.c
+src/knot/zone/contents.h
 src/knot/zone/node.c
 src/knot/zone/node.h
 src/knot/zone/semantic-check.c
@@ -206,15 +199,8 @@ src/knot/zone/zonedb.c
 src/knot/zone/zonedb.h
 src/knot/zone/zonefile.c
 src/knot/zone/zonefile.h
-src/libknot/binary.c
-src/libknot/binary.h
-src/libknot/common.h
-src/libknot/consts.c
-src/libknot/consts.h
-src/libknot/descriptor.c
-src/libknot/descriptor.h
-src/libknot/dname.c
-src/libknot/dname.h
+src/knot/knot.h
+src/knot/main.c
 src/libknot/dnssec/bitmap.h
 src/libknot/dnssec/config.h
 src/libknot/dnssec/crypto.c
@@ -230,11 +216,6 @@ src/libknot/dnssec/sig0.c
 src/libknot/dnssec/sig0.h
 src/libknot/dnssec/sign.c
 src/libknot/dnssec/sign.h
-src/libknot/errcode.c
-src/libknot/errcode.h
-src/libknot/libknot.h
-src/libknot/mempattern.c
-src/libknot/mempattern.h
 src/libknot/packet/compr.c
 src/libknot/packet/compr.h
 src/libknot/packet/pkt.c
@@ -242,16 +223,13 @@ src/libknot/packet/pkt.h
 src/libknot/packet/rrset-wire.c
 src/libknot/packet/rrset-wire.h
 src/libknot/packet/wire.h
-src/libknot/processing/process.c
-src/libknot/processing/process.h
-src/libknot/rdata.c
-src/libknot/rdata.h
-src/libknot/rdataset.c
-src/libknot/rdataset.h
-src/libknot/rrset-dump.c
-src/libknot/rrset-dump.h
-src/libknot/rrset.c
-src/libknot/rrset.h
+src/libknot/processing/layer.c
+src/libknot/processing/layer.h
+src/libknot/processing/overlay.c
+src/libknot/processing/overlay.h
+src/libknot/processing/requestor.c
+src/libknot/processing/requestor.h
+src/libknot/rrtype/aaaa.h
 src/libknot/rrtype/dnskey.h
 src/libknot/rrtype/naptr.h
 src/libknot/rrtype/nsec.h
@@ -266,13 +244,32 @@ src/libknot/rrtype/rrsig.h
 src/libknot/rrtype/soa.h
 src/libknot/rrtype/tsig.c
 src/libknot/rrtype/tsig.h
-src/libknot/tsig-op.c
-src/libknot/tsig-op.h
 src/libknot/util/endian.h
 src/libknot/util/tolower.c
 src/libknot/util/tolower.h
 src/libknot/util/utils.c
 src/libknot/util/utils.h
+src/libknot/binary.c
+src/libknot/binary.h
+src/libknot/consts.c
+src/libknot/consts.h
+src/libknot/descriptor.c
+src/libknot/descriptor.h
+src/libknot/dname.c
+src/libknot/dname.h
+src/libknot/errcode.c
+src/libknot/errcode.h
+src/libknot/libknot.h
+src/libknot/rdata.c
+src/libknot/rdata.h
+src/libknot/rdataset.c
+src/libknot/rdataset.h
+src/libknot/rrset-dump.c
+src/libknot/rrset-dump.h
+src/libknot/rrset.c
+src/libknot/rrset.h
+src/libknot/tsig-op.c
+src/libknot/tsig-op.h
 src/utils/common/exec.c
 src/utils/common/exec.h
 src/utils/common/msg.c
@@ -299,20 +296,20 @@ src/utils/nsupdate/nsupdate_exec.h
 src/utils/nsupdate/nsupdate_main.c
 src/utils/nsupdate/nsupdate_params.c
 src/utils/nsupdate/nsupdate_params.h
-src/zscanner/Makefile.am
+src/zscanner/tests/processing.c
+src/zscanner/tests/processing.h
+src/zscanner/tests/tests.c
+src/zscanner/tests/tests.h
+src/zscanner/tests/zscanner-tool.c
 src/zscanner/error.c
 src/zscanner/error.h
 src/zscanner/functions.c
 src/zscanner/functions.h
+src/zscanner/Makefile.am
 src/zscanner/scanner.h
 src/zscanner/scanner.rl
 src/zscanner/scanner_body.rl
-src/zscanner/tests/processing.c
-src/zscanner/tests/processing.h
-src/zscanner/tests/tests.c
-src/zscanner/tests/tests.h
-src/zscanner/tests/zscanner-tool.c
-tests/Makefile.am
+src/Makefile.am
 tests/acl.c
 tests/base32hex.c
 tests/base64.c
@@ -331,8 +328,10 @@ tests/fdset.c
 tests/hattrie.c
 tests/hhash.c
 tests/journal.c
+tests/Makefile.am
 tests/namedb.c
 tests/node.c
+tests/overlay.c
 tests/pkt.c
 tests/process_answer.c
 tests/process_query.c
@@ -353,3 +352,8 @@ tests/zone_timers.c
 tests/zone_update.c
 tests/zonedb.c
 tests/ztree.c
+configure.ac
+Doxyfile
+KNOWN_ISSUES
+Makefile.am
+README
diff --git a/NEWS b/NEWS
index 257944205771584e0a08fed9caf8711108d19b99..7d51225d839db5671b2e08059f51a36b50a0bada 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,23 @@
+Knot DNS 1.6.0 (2014-10-23)
+===========================
+
+Bugfixes:
+---------
+ - Fix zone expiration when AXFR/IXFR is being refused by master
+ - Fix forced zone refresh on slave (knotc refresh -f)
+
+Knot DNS 1.6.0-rc2 (2014-10-17)
+===============================
+
+Improvements:
+-------------
+ - Maximal size of persistent timers database increased from 10 MB to 100 MB
+ - Added logging of persistent timers database errors
+
+Bugfixes:
+---------
+ - Persistent timers database opening after privileges has been dropped
+
 Knot DNS 1.6.0-rc1 (2014-10-13)
 ===============================
 
@@ -6,7 +26,7 @@ Features:
  - Persistent timers for slave zones (expire, refresh, and flush)
 
 Bugfixes:
---------
+---------
  - DNSSEC: RFC compliant processing of letter case in RDATA domain names
  - EDNS: Return minimal error response for queries with unsupported version
  - EDNS: Fix interpretation of Extended RCODE
diff --git a/configure.ac b/configure.ac
index e9546aec9c49b9397ede4611a2fd4f00a009d527..75ef886cd21df1128b1ca3687d36f8ce2eebb34f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 #                                               -*- Autoconf -*-
 
 AC_PREREQ([2.60])
-AC_INIT([knot], [1.6.0-rc1], [knot-dns@labs.nic.cz])
+AC_INIT([knot], [1.6.0], [knot-dns@labs.nic.cz])
 AM_INIT_AUTOMAKE([gnits subdir-objects dist-xz -Wall -Werror])
 AM_SILENT_RULES([yes])
 AC_CONFIG_SRCDIR([src/knot/main.c])
@@ -350,8 +350,8 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sched.h>]], [[cpuset_t* set = cpuset
 
 # Use -fvisibility=hidden when linking.
 # Let's leave it default now and use -export-symbols-regex in LDFLAGS
-#gl_VISIBILITY()
-#CFLAGS="$CFLAGS $CFLAG_VISIBILITY"
+gl_VISIBILITY()
+CFLAGS="$CFLAGS $CFLAG_VISIBILITY"
 
 # Add code coverage macro
 AX_CODE_COVERAGE
diff --git a/src/Makefile.am b/src/Makefile.am
index 90cc7edf78548caafe3c87298f910a1ceef2e3d5..97d00235b74e19c4bde6bb5998fd53ec80f7258d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,9 +8,9 @@ noinst_LTLIBRARIES = libknotd.la libknots.la libknotus.la libknotcs.la
 
 # $(YACC) will generate header file
 AM_CPPFLAGS = \
-	-include $(top_builddir)/src/config.h \
-	-DCONFIG_DIR='"${config_dir}"' \
-	-DSTORAGE_DIR='"${storage_dir}"' \
+	-include $(top_builddir)/src/config.h	\
+	-DCONFIG_DIR='"${config_dir}"'		\
+	-DSTORAGE_DIR='"${storage_dir}"'	\
 	-DRUN_DIR='"${run_dir}"'
 AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
 AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS)
@@ -62,60 +62,65 @@ knsec3hash_SOURCES =				\
 
 # static: shared (not in libknot)
 libknots_la_SOURCES =				\
-	common-knot/array-sort.h		\
-	common-knot/binsearch.h			\
 	common-knot/crc.h			\
 	common-knot/evsched.c			\
 	common-knot/evsched.h			\
 	common-knot/fdset.c			\
 	common-knot/fdset.h			\
-	common-knot/hattrie/hat-trie.c		\
-	common-knot/hattrie/hat-trie.h		\
-	common-knot/hattrie/murmurhash3.c	\
-	common-knot/hattrie/murmurhash3.h	\
 	common-knot/heap.c			\
 	common-knot/heap.h			\
 	common-knot/hex.c			\
 	common-knot/hex.h			\
-	common-knot/hhash.c			\
-	common-knot/hhash.h			\
-	common-knot/lists.c			\
-	common-knot/lists.h			\
-	common-knot/print.c			\
-	common-knot/print.h			\
 	common-knot/ref.c			\
 	common-knot/ref.h			\
-	common-knot/sockaddr.c			\
-	common-knot/sockaddr.h			\
 	common-knot/strlcat.c			\
 	common-knot/strlcat.h			\
-	common-knot/strlcpy.c			\
-	common-knot/strlcpy.h			\
 	common-knot/strtonum.h			\
 	common-knot/trim.h
 
 # static: common shared (also in libknot)
 libknotcs_la_SOURCES =				\
+	common/array-sort.h			\
 	common/base32hex.c			\
 	common/base32hex.h			\
 	common/base64.c				\
 	common/base64.h				\
+	common/binsearch.h			\
 	common/debug.h				\
 	common/errors.c				\
 	common/errors.h				\
 	common/getline.c			\
 	common/getline.h			\
+	common/hhash.c				\
+	common/hhash.h				\
+	common/lists.c				\
+	common/lists.h				\
+	common/log.c				\
+	common/log.h				\
+	common/macros.h				\
 	common/mem.c				\
 	common/mem.h				\
+        common/mempattern.c			\
+        common/mempattern.h			\
 	common/mempool.c			\
 	common/mempool.h			\
 	common/namedb/namedb.h			\
-	common/namedb/namedb_lmdb.h		\
 	common/namedb/namedb_lmdb.c		\
-	common/namedb/namedb_trie.h		\
+	common/namedb/namedb_lmdb.h		\
 	common/namedb/namedb_trie.c		\
-	common/log.c				\
-	common/log.h
+	common/namedb/namedb_trie.h		\
+	common/net.c				\
+	common/net.h				\
+	common/print.c				\
+	common/print.h				\
+	common/sockaddr.c			\
+	common/sockaddr.h			\
+	common/strlcpy.c			\
+	common/strlcpy.h			\
+	common/trie/hat-trie.c			\
+	common/trie/hat-trie.h			\
+	common/trie/murmurhash3.c		\
+	common/trie/murmurhash3.h
 
 # static: utilities shared
 libknotus_la_SOURCES =				\
@@ -135,13 +140,11 @@ libknotus_la_SOURCES =				\
 # dynamic: libknot
 libknot_la_LDFLAGS =				\
 	$(AM_LDFLAGS)				\
-	-version-info 0:1:0			\
-	-export-symbols-regex '^(knot|KNOT|rrset|tsig|zone|mm)_'
+	-version-info 0:1:0
 
 libknot_la_SOURCES =				\
 	libknot/binary.c			\
 	libknot/binary.h			\
-	libknot/common.h			\
 	libknot/consts.c			\
 	libknot/consts.h			\
 	libknot/consts.h			\
@@ -149,12 +152,12 @@ libknot_la_SOURCES =				\
 	libknot/descriptor.h			\
 	libknot/dname.c				\
 	libknot/dname.h				\
+	libknot/dnssec/bitmap.h			\
 	libknot/dnssec/config.h			\
 	libknot/dnssec/crypto.c			\
 	libknot/dnssec/crypto.h			\
 	libknot/dnssec/key.c			\
 	libknot/dnssec/key.h			\
-	libknot/dnssec/bitmap.h			\
 	libknot/dnssec/policy.c			\
 	libknot/dnssec/policy.h			\
 	libknot/dnssec/random.h			\
@@ -167,8 +170,6 @@ libknot_la_SOURCES =				\
 	libknot/errcode.c			\
 	libknot/errcode.h			\
 	libknot/libknot.h			\
-	libknot/mempattern.c			\
-	libknot/mempattern.h			\
 	libknot/packet/compr.c			\
 	libknot/packet/compr.h			\
 	libknot/packet/pkt.c			\
@@ -176,12 +177,26 @@ libknot_la_SOURCES =				\
 	libknot/packet/rrset-wire.c		\
 	libknot/packet/rrset-wire.h		\
 	libknot/packet/wire.h			\
-	libknot/processing/process.c		\
-	libknot/processing/process.h		\
+	libknot/processing/layer.c		\
+	libknot/processing/layer.h		\
+	libknot/processing/overlay.c		\
+	libknot/processing/overlay.h		\
+	libknot/processing/requestor.c		\
+	libknot/processing/requestor.h		\
+	libknot/rdata.c				\
+	libknot/rdata.h				\
+	libknot/rdataset.c			\
+	libknot/rdataset.h			\
+	libknot/rrset-dump.c			\
+	libknot/rrset-dump.h			\
+	libknot/rrset.c				\
+	libknot/rrset.h				\
+	libknot/rrtype/aaaa.h			\
 	libknot/rrtype/dnskey.h			\
 	libknot/rrtype/naptr.h			\
 	libknot/rrtype/nsec.h			\
 	libknot/rrtype/nsec.h			\
+	libknot/rrtype/nsec.h			\
 	libknot/rrtype/nsec3.c			\
 	libknot/rrtype/nsec3.h			\
 	libknot/rrtype/nsec3param.c		\
@@ -193,14 +208,6 @@ libknot_la_SOURCES =				\
 	libknot/rrtype/soa.h			\
 	libknot/rrtype/tsig.c			\
 	libknot/rrtype/tsig.h			\
-	libknot/rrset-dump.c			\
-	libknot/rrset-dump.h			\
-	libknot/rdata.c				\
-	libknot/rdata.h				\
-	libknot/rdataset.c			\
-	libknot/rdataset.h			\
-	libknot/rrset.c				\
-	libknot/rrset.h				\
 	libknot/tsig-op.c			\
 	libknot/tsig-op.h			\
 	libknot/util/endian.h			\
@@ -238,34 +245,32 @@ libknotd_la_SOURCES =				\
 	knot/dnssec/zone-sign.c			\
 	knot/dnssec/zone-sign.h			\
 	knot/knot.h				\
+	knot/modules/synth_record.c		\
+	knot/modules/synth_record.h		\
 	knot/nameserver/axfr.c			\
 	knot/nameserver/axfr.h			\
-	knot/nameserver/chaos.c			\
-	knot/nameserver/chaos.h			\
 	knot/nameserver/capture.c		\
 	knot/nameserver/capture.h		\
+	knot/nameserver/chaos.c			\
+	knot/nameserver/chaos.h			\
 	knot/nameserver/internet.c		\
 	knot/nameserver/internet.h		\
 	knot/nameserver/ixfr.c			\
 	knot/nameserver/ixfr.h			\
+	knot/nameserver/notify.c		\
+	knot/nameserver/notify.h		\
 	knot/nameserver/nsec_proofs.c		\
 	knot/nameserver/nsec_proofs.h		\
-	knot/nameserver/process_query.c		\
-	knot/nameserver/process_query.h		\
 	knot/nameserver/process_answer.c	\
 	knot/nameserver/process_answer.h	\
-	knot/nameserver/requestor.c		\
-	knot/nameserver/requestor.h		\
+	knot/nameserver/process_query.c		\
+	knot/nameserver/process_query.h		\
 	knot/nameserver/query_module.c		\
 	knot/nameserver/query_module.h		\
-	knot/nameserver/update.c		\
-	knot/nameserver/update.h		\
-	knot/nameserver/notify.c		\
-	knot/nameserver/notify.h		\
 	knot/nameserver/tsig_ctx.c		\
 	knot/nameserver/tsig_ctx.h		\
-	knot/modules/synth_record.c		\
-	knot/modules/synth_record.h		\
+	knot/nameserver/update.c		\
+	knot/nameserver/update.h		\
 	knot/other/debug.h			\
 	knot/server/dthreads.c			\
 	knot/server/dthreads.h			\
@@ -273,24 +278,22 @@ libknotd_la_SOURCES =				\
 	knot/server/journal.h			\
 	knot/server/rrl.c			\
 	knot/server/rrl.h			\
+	knot/server/serialization.c		\
+	knot/server/serialization.h		\
 	knot/server/server.c			\
 	knot/server/server.h			\
-	knot/server/net.c			\
-	knot/server/net.h			\
 	knot/server/tcp-handler.c		\
 	knot/server/tcp-handler.h		\
 	knot/server/udp-handler.c		\
 	knot/server/udp-handler.h		\
-	knot/server/serialization.c		\
-	knot/server/serialization.h		\
 	knot/updates/acl.c			\
 	knot/updates/acl.h			\
+	knot/updates/apply.c			\
+	knot/updates/apply.h			\
 	knot/updates/changesets.c		\
 	knot/updates/changesets.h		\
 	knot/updates/ddns.c			\
 	knot/updates/ddns.h			\
-	knot/updates/apply.c			\
-	knot/updates/apply.h			\
 	knot/updates/zone-update.c		\
 	knot/updates/zone-update.h		\
 	knot/worker/pool.c			\
@@ -315,16 +318,16 @@ libknotd_la_SOURCES =				\
 	knot/zone/zone-diff.h			\
 	knot/zone/zone-dump.c			\
 	knot/zone/zone-dump.h			\
+	knot/zone/zone-load.c			\
+	knot/zone/zone-load.h			\
 	knot/zone/zone-tree.c			\
 	knot/zone/zone-tree.h			\
 	knot/zone/zone.c			\
 	knot/zone/zone.h			\
-	knot/zone/zone-load.c			\
-	knot/zone/zone-load.h			\
-	knot/zone/zonedb.c			\
-	knot/zone/zonedb.h			\
 	knot/zone/zonedb-load.c			\
 	knot/zone/zonedb-load.h			\
+	knot/zone/zonedb.c			\
+	knot/zone/zonedb.h			\
 	knot/zone/zonefile.c			\
 	knot/zone/zonefile.h
 
diff --git a/src/common-knot/fdset.c b/src/common-knot/fdset.c
index 55ec5839f9fc73031522c8f9c3220bce544408f6..2c9c958bdf68f1ebff1895c415b1c1773fbeddb1 100644
--- a/src/common-knot/fdset.c
+++ b/src/common-knot/fdset.c
@@ -19,7 +19,7 @@
 #include <unistd.h>
 #include <time.h>
 #include "common-knot/fdset.h"
-#include "libknot/common.h"
+#include "libknot/errcode.h"
 
 /* Workarounds for clock_gettime() not available on some platforms. */
 #ifdef HAVE_CLOCK_GETTIME
diff --git a/src/common-knot/array-sort.h b/src/common/array-sort.h
similarity index 99%
rename from src/common-knot/array-sort.h
rename to src/common/array-sort.h
index fe31b53356f1a0e8f1d2a1e1b84b50940f7a956c..bc5773e223ee73d266509a3e9c93385bc9986dd5 100644
--- a/src/common-knot/array-sort.h
+++ b/src/common/array-sort.h
@@ -40,6 +40,10 @@
  *  undef'd.
  */
 
+#pragma once
+
+#include "common/macros.h"
+
 typedef unsigned uns;
 
 #ifndef ASORT_LT
diff --git a/src/common-knot/binsearch.h b/src/common/binsearch.h
similarity index 99%
rename from src/common-knot/binsearch.h
rename to src/common/binsearch.h
index 4ae67efa5cb1890a1b171f7bfa074984b328c66a..88b38d484855e32809fdb2a52cb629c4bce84406 100644
--- a/src/common-knot/binsearch.h
+++ b/src/common/binsearch.h
@@ -7,6 +7,8 @@
  *	of the GNU Lesser General Public License.
  */
 
+#pragma once
+
 /***
  * [[defs]]
  * Definitions
diff --git a/src/common/debug.h b/src/common/debug.h
index 3238b6268a8322514853074382a2cb918cff3032..de51cd7c0b6003be65dc952db0a245b206ac550f 100644
--- a/src/common/debug.h
+++ b/src/common/debug.h
@@ -32,7 +32,7 @@
 #include <stdio.h>
 
 #include "common/log.h"
-#include "common-knot/print.h"
+#include "common/print.h"
 
 /*
  * Debug macros
diff --git a/src/common-knot/hhash.c b/src/common/hhash.c
similarity index 98%
rename from src/common-knot/hhash.c
rename to src/common/hhash.c
index 02f157563aa334b48e57cafb0edc27d55248aab1..04ed59cbf6dfa5133b32d3f2fd3537131d11e5b5 100644
--- a/src/common-knot/hhash.c
+++ b/src/common/hhash.c
@@ -2,11 +2,10 @@
 #include <assert.h>
 #include <stdbool.h>
 
-#include "common-knot/hhash.h"
-#include "common-knot/binsearch.h"
+#include "common/hhash.h"
+#include "common/binsearch.h"
+#include "common/trie/murmurhash3.h"
 #include "libknot/errcode.h"
-#include "common-knot/hattrie/murmurhash3.h"
-#include "libknot/common.h"
 
 /* UCW array sorting defines. */
 static int universal_cmp(uint32_t k1, uint32_t k2, hhash_t *tbl);
@@ -14,7 +13,7 @@ static int universal_cmp(uint32_t k1, uint32_t k2, hhash_t *tbl);
 #define ASORT_KEY_TYPE uint32_t 
 #define ASORT_LT(x, y) (universal_cmp((x), (y), tbl) < 0)
 #define ASORT_EXTRA_ARGS , hhash_t *tbl 
-#include "common-knot/array-sort.h"
+#include "common/array-sort.h"
 
 /* Hopscotch internal defines. */
 #define HOP_NEXT(x) __builtin_ctz((x))
@@ -218,7 +217,7 @@ hhash_t *hhash_create_mm(uint32_t size, const mm_ctx_t *mm)
 	}
 
 	const size_t total_len = sizeof(hhash_t) + size * sizeof(hhelem_t);
-	hhash_t *tbl = mm->alloc(mm->ctx, total_len);
+	hhash_t *tbl = mm_alloc((mm_ctx_t *)mm, total_len);
 	if (tbl) {
 		memset(tbl, 0, total_len);
 		tbl->size = size;
diff --git a/src/common-knot/hhash.h b/src/common/hhash.h
similarity index 99%
rename from src/common-knot/hhash.h
rename to src/common/hhash.h
index d57fb4ec85c71bb3e7af47764b1346d2607525c5..8787dff1037745edf0c8bd83a268fb7c0750b857 100644
--- a/src/common-knot/hhash.h
+++ b/src/common/hhash.h
@@ -29,7 +29,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdbool.h>
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 
 /*! \brief Bitvector type. */
 typedef unsigned hhbitvec_t;
diff --git a/src/common-knot/lists.c b/src/common/lists.c
similarity index 99%
rename from src/common-knot/lists.c
rename to src/common/lists.c
index fdcf81af11481704dee5aab17af600d8c6980cb6..e59721cedca85946914c19982a39758f08d69cad 100644
--- a/src/common-knot/lists.c
+++ b/src/common/lists.c
@@ -28,7 +28,7 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include "common-knot/lists.h"
+#include "common/lists.h"
 
 /**
  * add_tail - append a node to a list
diff --git a/src/common-knot/lists.h b/src/common/lists.h
similarity index 99%
rename from src/common-knot/lists.h
rename to src/common/lists.h
index 9c1fee5c964b30d33ed87565adbc45b08fce5f34..cdacfe0efc4a9a4cf5f7922e0a663aecc403c546 100644
--- a/src/common-knot/lists.h
+++ b/src/common/lists.h
@@ -83,7 +83,7 @@ void list_dup(list_t *dst, list_t *src, size_t itemsz);
 size_t list_size(const list_t *);
 
 #include <stdbool.h>
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 /*!
  * \brief Generic pointer list implementation.
  */
diff --git a/src/common/log.c b/src/common/log.c
index 22338702d72e062182e9bae8dfbefa78fba9fef1..f7305bb7b426d0be0b38bce753ee74e7371a0ce4 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -27,9 +27,11 @@
 #endif
 
 #include "common/log.h"
-#include "common-knot/lists.h"
-#include "common-knot/strlcpy.h"
+#include "common/lists.h"
+#include "common/macros.h"
+#include "common/strlcpy.h"
 #include "knot/conf/conf.h"
+#include "libknot/errcode.h"
 
 /* Single log message buffer length (one line). */
 #define LOG_BUFLEN 512
@@ -122,7 +124,7 @@ static uint8_t sink_levels(struct log_sink *log, int facility, logsrc_t src)
 	assert(log);
 
 	// Check facility
-	if (knot_unlikely(log->facility_count == 0 || facility >= log->facility_count)) {
+	if (unlikely(log->facility_count == 0 || facility >= log->facility_count)) {
 		return 0;
 	}
 
@@ -132,7 +134,7 @@ static uint8_t sink_levels(struct log_sink *log, int facility, logsrc_t src)
 static int sink_levels_set(struct log_sink *log, int facility, logsrc_t src, uint8_t levels)
 {
 	// Check facility
-	if (knot_unlikely(log->facility_count == 0 || facility >= log->facility_count)) {
+	if (unlikely(log->facility_count == 0 || facility >= log->facility_count)) {
 		return KNOT_EINVAL;
 	}
 
@@ -203,7 +205,7 @@ bool log_isopen()
 static int log_open_file(struct log_sink *log, const char* filename)
 {
 	// Check facility
-	if (knot_unlikely(log->facility_count  == 0 ||
+	if (unlikely(log->facility_count  == 0 ||
 	                  LOGT_FILE + log->file_count >= log->facility_count)) {
 		return KNOT_ERROR;
 	}
diff --git a/src/libknot/common.h b/src/common/macros.h
similarity index 50%
rename from src/libknot/common.h
rename to src/common/macros.h
index 0d3e1acd2b052903c63bbae731d6b55359b00bfd..47402c5376ec451b2154a381fa226f50dd740d12 100644
--- a/src/libknot/common.h
+++ b/src/common/macros.h
@@ -1,14 +1,4 @@
-/*!
- * \file libknot/common.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Common macros, includes and utilities.
- *
- * \addtogroup libknot
- * @{
- */
-/*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2014 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
@@ -23,22 +13,22 @@
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
-#include "libknot/errcode.h"
+/*!
+ * \file common/macros.h
+ *
+ * \author Lubos Slovak <lubos.slovak@nic.cz>
+ *
+ * \brief Common macros.
+ *
+ * \addtogroup common_lib
+ * @{
+ */
 
 #pragma once
 
-#define KNOT_NAME "lib" PACKAGE_NAME // Project name
-#define KNOT_VER  PACKAGE_VERSION  // 0xMMIIRR (MAJOR,MINOR,REVISION)
-
-#ifndef UINT_DEFINED
-typedef unsigned int uint; /*!< \brief Unsigned. */
-#define UINT_DEFINED
-#endif
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+/*! \brief Library visibility macros. */
+#define _public_ __attribute__((visibility("default")))
+#define _hidden_ __attribute__((visibility("hidden")))
 
 /*! \brief Eliminate compiler warning with unused parameters. */
 #define UNUSED(param) (void)(param)
@@ -53,40 +43,14 @@ typedef unsigned int uint; /*!< \brief Unsigned. */
 	({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
 #endif
 
-/* Optimisation macros. */
-#ifndef knot_likely
+#ifndef likely
 /*! \brief Optimize for x to be true value. */
-#define knot_likely(x)       __builtin_expect((x),1)
-#endif
-#ifndef knot_unlikely
-/*! \brief Optimize for x to be false value. */
-#define knot_unlikely(x)     __builtin_expect((x),0)
-#endif
-
-/*! \todo Refactor theese. We should have an allocator function handling this.*/
-#ifndef ERR_ALLOC_FAILED
-#define ERR_ALLOC_FAILED fprintf(stderr, \
-                                 "Allocation failed at %s:%d (%s ver.%s)\n", \
-                                 __FILE__, __LINE__, KNOT_NAME, KNOT_VER)
+#define likely(x) __builtin_expect((x), 1)
 #endif
 
-#ifndef CHECK_ALLOC_LOG
-#define CHECK_ALLOC_LOG(var, ret) \
-	do { \
-		if ((var) == NULL) { \
-			ERR_ALLOC_FAILED; \
-			return (ret); \
-		} \
-	} while (0)
-#endif
-
-#ifndef CHECK_ALLOC
-#define CHECK_ALLOC(var, ret) \
-	do { \
-		if ((var) == NULL) { \
-			return (ret); \
-		} \
-	} while (0)
+#ifndef unlikely
+/*! \brief Optimize for x to be false value. */
+#define unlikely(x) __builtin_expect((x), 0)
 #endif
 
 /*! @} */
diff --git a/src/libknot/mempattern.c b/src/common/mempattern.c
similarity index 95%
rename from src/libknot/mempattern.c
rename to src/common/mempattern.c
index 7969a210aca6033625711576ac352452d2af0b32..3bf01d1c93e4bf32d054a49f41a938ba5e41ea20 100644
--- a/src/libknot/mempattern.c
+++ b/src/common/mempattern.c
@@ -16,7 +16,7 @@
 
 #include <stdlib.h>
 
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 #include "common/mempool.h"
 
 static void mm_nofree(void *p)
@@ -39,6 +39,7 @@ void *mm_alloc(mm_ctx_t *mm, size_t size)
 	}
 }
 
+
 void *mm_realloc(mm_ctx_t *mm, void *what, size_t size, size_t prev_size)
 {
 	if (mm) {
@@ -50,9 +51,7 @@ void *mm_realloc(mm_ctx_t *mm, void *what, size_t size, size_t prev_size)
 				memcpy(p, what,
 				       prev_size < size ? prev_size : size);
 			}
-			if (mm->free) {
-				mm->free(what);
-			}
+			mm_free(mm, what);
 			return p;
 		}
 	} else {
@@ -60,7 +59,6 @@ void *mm_realloc(mm_ctx_t *mm, void *what, size_t size, size_t prev_size)
 	}
 }
 
-
 void mm_free(mm_ctx_t *mm, void *what)
 {
 	if (mm) {
diff --git a/src/libknot/mempattern.h b/src/common/mempattern.h
similarity index 97%
rename from src/libknot/mempattern.h
rename to src/common/mempattern.h
index 277eb45d884cd2b2d9a741f03a020f8e9570aeb8..fea6584ce43d0c56160dfd1c873524b735a25b4d 100644
--- a/src/libknot/mempattern.h
+++ b/src/common/mempattern.h
@@ -36,7 +36,7 @@ typedef void* (*mm_alloc_t)(void* ctx, size_t len);
 typedef void (*mm_free_t)(void *p);
 typedef void (*mm_flush_t)(void *p);
 
-/* Memory allocation context. */
+/*! \brief Memory allocation context. */
 typedef struct mm_ctx {
 	void *ctx; /* \note Must be first */
 	mm_alloc_t alloc;
diff --git a/src/common/mempool.c b/src/common/mempool.c
index dca1df6c61e19f5c13bc3de7b22159ecb9bc3b11..e3aad9c20ba0fce7d93b27a5de26d383e3e5c372 100644
--- a/src/common/mempool.c
+++ b/src/common/mempool.c
@@ -13,7 +13,7 @@
 
 #include "common/mem.h"
 #include "common/mempool.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 
 #include <string.h>
 #include <stdlib.h>
diff --git a/src/common/namedb/namedb.h b/src/common/namedb/namedb.h
index e3017079b772f4433eda44b18a78c111df929f28..a4c3397793d0d5f7b0b7a2fb1ae7e9fa4ad08c3a 100644
--- a/src/common/namedb/namedb.h
+++ b/src/common/namedb/namedb.h
@@ -18,6 +18,8 @@
 
 #include "libknot/dname.h"
 
+#include "common/mempattern.h"
+
 enum {
 	KNOT_NAMEDB_RDONLY = 1 << 0,
 	KNOT_NAMEDB_SORTED = 1 << 1
@@ -42,7 +44,7 @@ struct namedb_api {
 
 	/* Context operations */
 
-	knot_namedb_t *(*init)(const char *config, mm_ctx_t *mm);
+	int (*init)(const char *config, knot_namedb_t **db, mm_ctx_t *mm);
 	void (*deinit)(knot_namedb_t *db);
 
 	/* Transactions */
diff --git a/src/common/namedb/namedb_lmdb.c b/src/common/namedb/namedb_lmdb.c
index 25f4acca54557a6a7fbffa32dc2a3d4b6faff02c..68494b7d3f4d05df451fd1b9cce061cff1e295b6 100644
--- a/src/common/namedb/namedb_lmdb.c
+++ b/src/common/namedb/namedb_lmdb.c
@@ -18,12 +18,14 @@
 
 #include <lmdb.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 #include "common/namedb/namedb_lmdb.h"
 #include "libknot/errcode.h"
 
-#define LMDB_DIR_MODE 0770
-#define LMDB_FILE_MODE 0660
+#define LMDB_DIR_MODE	0770
+#define LMDB_FILE_MODE	0660
+#define LMDB_MAPSIZE	(100 * 1024 * 1024)
 
 struct lmdb_env
 {
@@ -42,11 +44,43 @@ static int create_env_dir(const char *path)
 	return KNOT_EOK;
 }
 
+/*!
+ * \brief Convert error code returned by LMDB to Knot DNS error code.
+ *
+ * LMDB defines own error codes but uses additional ones from libc. All LMDB
+ * specific error codes are translated to KNOT_DATABASE_ERROR.
+ */
+static int lmdb_error_to_knot(int error)
+{
+	if (error == MDB_SUCCESS) {
+		return KNOT_EOK;
+	}
+
+	if (MDB_KEYEXIST <= error && error <= MDB_LAST_ERRCODE) {
+		return KNOT_DATABASE_ERROR;
+	}
+
+	return knot_errno_to_error(error);
+}
+
 static int dbase_open(struct lmdb_env *env, const char *path)
 {
 	int ret = mdb_env_create(&env->env);
 	if (ret != 0) {
-		return ret;
+		return lmdb_error_to_knot(ret);
+	}
+
+	long page_size = sysconf(_SC_PAGESIZE);
+	if (page_size <= 0) {
+		mdb_env_close(env->env);
+		return KNOT_EINVAL;
+	}
+
+	size_t map_size = (LMDB_MAPSIZE / page_size) * page_size;
+	ret = mdb_env_set_mapsize(env->env, map_size);
+	if (ret != 0) {
+		mdb_env_close(env->env);
+		return lmdb_error_to_knot(ret);
 	}
 
 	ret = create_env_dir(path);
@@ -58,27 +92,27 @@ static int dbase_open(struct lmdb_env *env, const char *path)
 	ret = mdb_env_open(env->env, path, 0, LMDB_FILE_MODE);
 	if (ret != 0) {
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	MDB_txn *txn = NULL;
 	ret = mdb_txn_begin(env->env, NULL, 0, &txn);
 	if (ret != 0) {
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	ret = mdb_open(txn, NULL, 0, &env->dbi);
 	if (ret != 0) {
 		mdb_txn_abort(txn);
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	ret = mdb_txn_commit(txn);
 	if (ret != 0) {
 		mdb_env_close(env->env);
-		return ret;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return 0;
@@ -90,22 +124,24 @@ static void dbase_close(struct lmdb_env *env)
 	mdb_env_close(env->env);
 }
 
-static knot_namedb_t *init(const char *config, mm_ctx_t *mm)
+static int init(const char *config, knot_namedb_t **db_ptr, mm_ctx_t *mm)
 {
 	struct lmdb_env *env = mm_alloc(mm, sizeof(struct lmdb_env));
 	if (env == NULL) {
-		return NULL;
+		return KNOT_ENOMEM;
 	}
 	memset(env, 0, sizeof(struct lmdb_env));
 
 	int ret = dbase_open(env, config);
 	if (ret != 0) {
 		mm_free(mm, env);
-		return NULL;
+		return ret;
 	}
 
 	env->pool = mm;
-	return env;
+	*db_ptr = env;
+
+	return KNOT_EOK;
 }
 
 static void deinit(knot_namedb_t *db)
@@ -131,7 +167,7 @@ static int txn_begin(knot_namedb_t *db, knot_txn_t *txn, unsigned flags)
 	struct lmdb_env *env = db;
 	int ret = mdb_txn_begin(env->env, NULL, txn_flags, (MDB_txn **)&txn->txn);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -141,7 +177,7 @@ static int txn_commit(knot_txn_t *txn)
 {
 	int ret = mdb_txn_commit((MDB_txn *)txn->txn);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -159,7 +195,7 @@ static int count(knot_txn_t *txn)
 	MDB_stat stat;
 	int ret = mdb_stat(txn->txn, env->dbi, &stat);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return stat.ms_entries;
@@ -171,13 +207,12 @@ static int find(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flag
 	MDB_val db_key = { key->len, key->data };
 	MDB_val data = { 0, NULL };
 
-
 	int ret = mdb_get(txn->txn, env->dbi, &db_key, &data);
 	if (ret != 0) {
 		if (ret == MDB_NOTFOUND) {
 			return KNOT_ENOENT;
 		} else {
-			return KNOT_ERROR;
+			return lmdb_error_to_knot(ret);
 		}
 	}
 
@@ -193,7 +228,7 @@ static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned fl
 	MDB_cursor *cursor = NULL;
 	int ret = mdb_cursor_open(txn->txn, env->dbi, &cursor);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	MDB_val db_key = { key->len, key->data };
@@ -206,7 +241,7 @@ static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned fl
 			// Insert new item
 			ret = mdb_put(txn->txn, env->dbi, &db_key, &data, 0);
 			if (ret != 0) {
-				return KNOT_ERROR;
+				return lmdb_error_to_knot(ret);
 			}
 
 			return KNOT_EOK;
@@ -218,7 +253,7 @@ static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned fl
 	ret = mdb_cursor_put(cursor, &db_key, &data, MDB_CURRENT);
 	mdb_cursor_close(cursor);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -232,7 +267,7 @@ static int del(knot_txn_t *txn, knot_val_t *key)
 
 	int ret = mdb_del(txn->txn, env->dbi, &db_key, &data);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	return KNOT_EOK;
@@ -277,7 +312,7 @@ static int iter_key(knot_iter_t *iter, knot_val_t *key)
 	MDB_val mdb_key, mdb_val;
 	int ret = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	key->data = mdb_key.mv_data;
@@ -292,7 +327,7 @@ static int iter_val(knot_iter_t *iter, knot_val_t *val)
 	MDB_val mdb_key, mdb_val;
 	int ret = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT);
 	if (ret != 0) {
-		return KNOT_ERROR;
+		return lmdb_error_to_knot(ret);
 	}
 
 	val->data = mdb_val.mv_data;
@@ -310,9 +345,9 @@ static void iter_finish(knot_iter_t *iter)
 	mdb_cursor_close(cursor);
 }
 
-struct namedb_api *namedb_lmdb_api(void)
+const struct namedb_api *namedb_lmdb_api(void)
 {
-	static struct namedb_api api = {
+	static const struct namedb_api api = {
 		"lmdb",
 		init, deinit,
 		txn_begin, txn_commit, txn_abort,
@@ -327,7 +362,7 @@ struct namedb_api *namedb_lmdb_api(void)
 
 #include <stdlib.h>
 
-struct namedb_api *namedb_lmdb_api(void)
+const struct namedb_api *namedb_lmdb_api(void)
 {
 	return NULL;
 }
diff --git a/src/common/namedb/namedb_lmdb.h b/src/common/namedb/namedb_lmdb.h
index 0dcf9d64f1d8a708926d09b74435b1c96b6d8350..1baafe502da92943a3e8e6e37731d3b2b726be31 100644
--- a/src/common/namedb/namedb_lmdb.h
+++ b/src/common/namedb/namedb_lmdb.h
@@ -18,4 +18,4 @@
 
 #include "common/namedb/namedb.h"
 
-struct namedb_api *namedb_lmdb_api(void);
+const struct namedb_api *namedb_lmdb_api(void);
diff --git a/src/common/namedb/namedb_trie.c b/src/common/namedb/namedb_trie.c
index 0ca29f652ccea480c562f075cebed552840af161..926efcf74d5b923bc90938606633e84bdbc2171d 100644
--- a/src/common/namedb/namedb_trie.c
+++ b/src/common/namedb/namedb_trie.c
@@ -14,13 +14,26 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "common/namedb/namedb_trie.h"
-#include "common-knot/hattrie/hat-trie.h"
 #include "libknot/errcode.h"
 
-static knot_namedb_t *init(const char *handle, mm_ctx_t *mm)
+#include "common/namedb/namedb_trie.h"
+#include "common/trie/hat-trie.h"
+#include "common/mempattern.h"
+
+static int init(const char *config, knot_namedb_t **db, mm_ctx_t *mm)
 {
-	return hattrie_create_n(TRIE_BUCKET_SIZE, mm);
+	if (config != NULL || db == NULL) {
+		return KNOT_EINVAL;
+	}
+
+	hattrie_t *trie = hattrie_create_n(TRIE_BUCKET_SIZE, mm);
+	if (!trie) {
+		return KNOT_ENOMEM;
+	}
+
+	*db = trie;
+
+	return KNOT_EOK;
 }
 
 static void deinit(knot_namedb_t *db)
@@ -126,9 +139,9 @@ static void iter_finish(knot_iter_t *iter)
 	hattrie_iter_free((hattrie_iter_t *)iter);
 }
 
-struct namedb_api *namedb_trie_api(void)
+const struct namedb_api *namedb_trie_api(void)
 {
-	static struct namedb_api api = {
+	static const struct namedb_api api = {
 		"hattrie",
 		init, deinit,
 		txn_begin, txn_commit, txn_abort,
diff --git a/src/common/namedb/namedb_trie.h b/src/common/namedb/namedb_trie.h
index 048f299d2d01afb4fa7176da6a2bf6ae62316544..4ae3cd8277a99c6957b9c53b6b43496dabccbb26 100644
--- a/src/common/namedb/namedb_trie.h
+++ b/src/common/namedb/namedb_trie.h
@@ -18,4 +18,4 @@
 
 #include "common/namedb/namedb.h"
 
-struct namedb_api *namedb_trie_api(void);
+const struct namedb_api *namedb_trie_api(void);
diff --git a/src/knot/server/net.c b/src/common/net.c
similarity index 53%
rename from src/knot/server/net.c
rename to src/common/net.c
index f4d363a718b5d2ce489a6e9726d77cb02dfef20d..a37275b17b285788a0f35d20489dfa829be2ca45 100644
--- a/src/knot/server/net.c
+++ b/src/common/net.c
@@ -24,14 +24,15 @@
 #include <time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/uio.h>
 #ifdef HAVE_NETINET_IN_SYSTM_H
 #include <netinet/in_systm.h>
 #endif
 #include <sys/stat.h>
 #include <assert.h>
 
-#include "knot/server/net.h"
-#include "knot/knot.h"
+#include "libknot/errcode.h"
+#include "common/net.h"
 
 static int socket_create(int family, int type, int proto)
 {
@@ -50,19 +51,8 @@ int net_unbound_socket(int type, const struct sockaddr_storage *ss)
 		return KNOT_EINVAL;
 	}
 
-	/* Convert to string address format. */
-	char addr_str[SOCKADDR_STRLEN] = {0};
-	sockaddr_tostr(ss, addr_str, sizeof(addr_str));
-
 	/* Create socket. */
-	int socket = socket_create(ss->ss_family, type, 0);
-	if (socket < 0) {
-		log_error("failed to create socket '%s' (%s)",
-		          addr_str, knot_strerror(socket));
-		return socket;
-	}
-
-	return socket;
+	return socket_create(ss->ss_family, type, 0);
 }
 
 int net_bound_socket(int type, const struct sockaddr_storage *ss)
@@ -93,11 +83,10 @@ int net_bound_socket(int type, const struct sockaddr_storage *ss)
 	}
 
 	/* Bind to specified address. */
-	int ret = bind(socket, (const struct sockaddr *)ss, sockaddr_len(ss));
+	const struct sockaddr *sa = (const struct sockaddr *)ss;
+	int ret = bind(socket, sa, sockaddr_len(sa));
 	if (ret < 0) {
 		ret = knot_map_errno(EADDRINUSE, EINVAL, EACCES, ENOMEM);
-		log_error("cannot bind address '%s' (%s)",
-		          addr_str, knot_strerror(ret));
 		close(socket);
 		return ret;
 	}
@@ -134,8 +123,8 @@ int net_connected_socket(int type, const struct sockaddr_storage *dst_addr,
 		;
 
 	/* Connect to destination. */
-	int ret = connect(socket, (const struct sockaddr *)dst_addr,
-	                  sockaddr_len(dst_addr));
+	const struct sockaddr *sa = (const struct sockaddr *)dst_addr;
+	int ret = connect(socket, sa, sockaddr_len(sa));
 	if (ret != 0 && errno != EINPROGRESS) {
 		close(socket);
 		return knot_map_errno(EACCES, EADDRINUSE, EAGAIN,
@@ -151,3 +140,124 @@ int net_is_connected(int fd)
 	socklen_t len = sizeof(ss);
 	return getpeername(fd, (struct sockaddr *)&ss, &len) == 0;
 }
+
+/*! \brief Wait for data and return true if data arrived. */
+static int tcp_wait_for_data(int fd, struct timeval *timeout)
+{
+	fd_set set;
+	FD_ZERO(&set);
+	FD_SET(fd, &set);
+	return select(fd + 1, &set, NULL, NULL, timeout);
+}
+
+/* \brief Receive a block of data from TCP socket with wait. */
+static int tcp_recv_data(int fd, uint8_t *buf, int len, struct timeval *timeout)
+{
+	int ret = 0;
+	int rcvd = 0;
+	int flags = 0;
+
+#ifdef MSG_NOSIGNAL
+	flags |= MSG_NOSIGNAL;
+#endif
+
+	while (rcvd < len) {
+		/* Receive data. */
+		ret = recv(fd, buf + rcvd, len - rcvd, flags);
+		if (ret > 0) {
+			rcvd += ret;
+			continue;
+		}
+		/* Check for disconnected socket. */
+		if (ret == 0) {
+			return KNOT_ECONNREFUSED;
+		}
+
+		/* Check for no data available. */
+		if (errno == EAGAIN || errno == EINTR) {
+			/* Continue only if timeout didn't expire. */
+			ret = tcp_wait_for_data(fd, timeout);
+			if (ret) {
+				continue;
+			} else {
+				return KNOT_ETIMEOUT;
+			}
+		} else {
+			return KNOT_ECONN;
+		}
+	}
+
+	return rcvd;
+}
+
+int udp_send_msg(int fd, const uint8_t *msg, size_t msglen,
+                 const struct sockaddr *addr)
+{
+	socklen_t addr_len = sockaddr_len(addr);
+	int ret = sendto(fd, msg, msglen, 0, addr, addr_len);
+	if (ret != msglen) {
+		return KNOT_ECONN;
+	}
+
+	return ret;
+}
+
+int udp_recv_msg(int fd, uint8_t *buf, size_t len, struct sockaddr *addr)
+{
+	socklen_t addr_len = sizeof(struct sockaddr_storage);
+	int ret = recvfrom(fd, buf, len, 0, addr, &addr_len);
+	if (ret < 0) {
+		return KNOT_ECONN;
+	}
+
+	return ret;
+}
+
+int tcp_send_msg(int fd, const uint8_t *msg, size_t msglen)
+{
+	/* Create iovec for gathered write. */
+	struct iovec iov[2];
+	uint16_t pktsize = htons(msglen);
+	iov[0].iov_base = &pktsize;
+	iov[0].iov_len = sizeof(uint16_t);
+	iov[1].iov_base = (void *)msg;
+	iov[1].iov_len = msglen;
+
+	/* Send. */
+	int total_len = iov[0].iov_len + iov[1].iov_len;
+	int sent = writev(fd, iov, 2);
+	if (sent != total_len) {
+		return KNOT_ECONN;
+	}
+
+	return msglen; /* Do not count the size prefix. */
+}
+
+int tcp_recv_msg(int fd, uint8_t *buf, size_t len, struct timeval *timeout)
+{
+	if (buf == NULL || fd < 0) {
+		return KNOT_EINVAL;
+	}
+
+	/* Receive size. */
+	unsigned short pktsize = 0;
+	int ret = tcp_recv_data(fd, (uint8_t *)&pktsize, sizeof(pktsize), timeout);
+	if (ret != sizeof(pktsize)) {
+		return ret;
+	}
+
+	pktsize = ntohs(pktsize);
+
+	// Check packet size
+	if (len < pktsize) {
+		return KNOT_ENOMEM;
+	}
+
+	/* Receive payload. */
+	ret = tcp_recv_data(fd, buf, pktsize, timeout);
+	if (ret != pktsize) {
+		return ret;
+	}
+
+	return ret;
+}
diff --git a/src/knot/server/net.h b/src/common/net.h
similarity index 58%
rename from src/knot/server/net.h
rename to src/common/net.h
index d780fbb06c50c40844003896ff96aab7cd1fcd7f..7e0608adc13efe122cb19222a0c3226a2086b37e 100644
--- a/src/knot/server/net.h
+++ b/src/common/net.h
@@ -29,7 +29,9 @@
 #pragma once
 
 /* POSIX only. */
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
+
+/*******              #274, legacy API to be replaced below            ********/
 
 /*!
  * \brief Create unbound socket of given family and type.
@@ -75,4 +77,58 @@ int net_connected_socket(int type, const struct sockaddr_storage *dst_addr,
  */
 int net_is_connected(int fd);
 
+/*!
+ * \brief Send a UDP message.
+ *
+ * \param fd Associated socket.
+ * \param msg Buffer for a query wireformat.
+ * \param msglen Buffer maximum size.
+ * \param addr Destination address.
+ *
+ * \retval Number of sent data on success.
+ * \retval KNOT_ERROR on error.
+ */
+int udp_send_msg(int fd, const uint8_t *msg, size_t msglen,
+                 const struct sockaddr *addr);
+
+/*!
+ * \brief Receive a UDP message.
+ *
+ * \param fd Associated socket.
+ * \param buf Buffer for incoming bytestream.
+ * \param len Buffer maximum size.
+ * \param addr Source address.
+ *
+ * \retval Number of read bytes on success.
+ * \retval KNOT_ERROR on error.
+ * \retval KNOT_ENOMEM on potential buffer overflow.
+ */
+int udp_recv_msg(int fd, uint8_t *buf, size_t len, struct sockaddr *addr);
+
+/*!
+ * \brief Send a TCP message.
+ *
+ * \param fd Associated socket.
+ * \param msg Buffer for a query wireformat.
+ * \param msglen Buffer maximum size.
+ *
+ * \retval Number of sent data on success.
+ * \retval KNOT_ERROR on error.
+ */
+int tcp_send_msg(int fd, const uint8_t *msg, size_t msglen);
+
+/*!
+ * \brief Receive a TCP message.
+ *
+ * \param fd Associated socket.
+ * \param buf Buffer for incoming bytestream.
+ * \param len Buffer maximum size.
+ * \param timeout Message receive timeout.
+ *
+ * \retval Number of read bytes on success.
+ * \retval KNOT_ERROR on error.
+ * \retval KNOT_ENOMEM on potential buffer overflow.
+ */
+int tcp_recv_msg(int fd, uint8_t *buf, size_t len, struct timeval *timeout);
+
 /*! @} */
diff --git a/src/common-knot/print.c b/src/common/print.c
similarity index 98%
rename from src/common-knot/print.c
rename to src/common/print.c
index d37a036bad8710c4ca5af914c06392b0ae170bd0..6a71b4105947dacfabb85f27bf7ca84e2b243943 100644
--- a/src/common-knot/print.c
+++ b/src/common/print.c
@@ -16,7 +16,7 @@
 
 #include <stdio.h>
 #include <ctype.h>
-#include "common-knot/print.h"
+#include "common/print.h"
 
 void array_printf(const uint8_t *data, const unsigned length,
                   printf_t print_handler, const char type)
diff --git a/src/common-knot/print.h b/src/common/print.h
similarity index 100%
rename from src/common-knot/print.h
rename to src/common/print.h
diff --git a/src/common-knot/sockaddr.c b/src/common/sockaddr.c
similarity index 95%
rename from src/common-knot/sockaddr.c
rename to src/common/sockaddr.c
index 3e4f300d4973c3964e8d4cb1398d023cb463e099..ae90390efe1d19511ea2d0eac8670186b3702740 100644
--- a/src/common-knot/sockaddr.c
+++ b/src/common/sockaddr.c
@@ -18,14 +18,15 @@
 #include <string.h>
 #include <netdb.h>
 
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
 #include "libknot/errcode.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 #include "libknot/consts.h"
 
-int sockaddr_len(const struct sockaddr_storage *ss)
+int sockaddr_len(const struct sockaddr *ss)
 {
-	switch(ss->ss_family) {
+	const struct sockaddr_storage *sa = (const struct sockaddr_storage *)ss;
+	switch(sa->ss_family) {
 	case AF_INET:
 		return sizeof(struct sockaddr_in);
 	case AF_INET6:
@@ -43,7 +44,7 @@ int sockaddr_cmp(const struct sockaddr_storage *k1, const struct sockaddr_storag
 		return (int)k1->ss_family - (int)k2->ss_family;
 	}
 
-	return memcmp(k1, k2, sockaddr_len(k1));
+	return memcmp(k1, k2, sockaddr_len((const struct sockaddr *)k1));
 }
 
 int sockaddr_set(struct sockaddr_storage *ss, int family, const char *straddr, int port)
diff --git a/src/common-knot/sockaddr.h b/src/common/sockaddr.h
similarity index 98%
rename from src/common-knot/sockaddr.h
rename to src/common/sockaddr.h
index c9ea259f3db5d5ae1753ff9812f88785ab1b28aa..5b3833cd563381fef8aaffc3ca24490d0e6b8429 100644
--- a/src/common-knot/sockaddr.h
+++ b/src/common/sockaddr.h
@@ -54,7 +54,7 @@
  *
  * \return number of bytes or error code
  */
-int sockaddr_len(const struct sockaddr_storage *ss);
+int sockaddr_len(const struct sockaddr *ss);
 
 /*!
  * \brief Compare address storages.
diff --git a/src/common-knot/strlcpy.c b/src/common/strlcpy.c
similarity index 97%
rename from src/common-knot/strlcpy.c
rename to src/common/strlcpy.c
index f8938108a753b3e7699bd1e6a8aabdafda84b915..5371b90a62831ba8ae9cb53e967d931ea227393b 100644
--- a/src/common-knot/strlcpy.c
+++ b/src/common/strlcpy.c
@@ -17,7 +17,7 @@
 #include <sys/types.h>
 #include <string.h>
 
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 
 size_t
 knot_strlcpy(char *dst, const char *src, size_t siz)
diff --git a/src/common-knot/strlcpy.h b/src/common/strlcpy.h
similarity index 100%
rename from src/common-knot/strlcpy.h
rename to src/common/strlcpy.h
diff --git a/src/common-knot/hattrie/COPYING b/src/common/trie/COPYING
similarity index 100%
rename from src/common-knot/hattrie/COPYING
rename to src/common/trie/COPYING
diff --git a/src/common-knot/hattrie/README.md b/src/common/trie/README.md
similarity index 100%
rename from src/common-knot/hattrie/README.md
rename to src/common/trie/README.md
diff --git a/src/common-knot/hattrie/hat-trie.c b/src/common/trie/hat-trie.c
similarity index 99%
rename from src/common-knot/hattrie/hat-trie.c
rename to src/common/trie/hat-trie.c
index e6fd77f118317938efa80e43e926d27ba7b5daa8..138ff49ce57719e8261805b2e162bb32886d2176 100644
--- a/src/common-knot/hattrie/hat-trie.c
+++ b/src/common/trie/hat-trie.c
@@ -8,8 +8,8 @@
 #include <stdint.h>
 #include <assert.h>
 #include <string.h>
-#include "common-knot/hattrie/hat-trie.h"
-#include "common-knot/hhash.h"
+#include "common/trie/hat-trie.h"
+#include "common/hhash.h"
 
 /* number of child nodes for used alphabet */
 #define NODE_CHILDS (TRIE_MAXCHAR+1)
@@ -80,7 +80,7 @@ static trie_node_t* alloc_trie_node(hattrie_t* T, node_ptr child)
     for (i = 0; i < NODE_CHILDS; ++i) node->xs[i] = child;
     return node;
 }
-	
+
 /* iterate trie nodes until string is consumed or bucket is found */
 static node_ptr hattrie_consume_ns(node_ptr **s, size_t *sp, size_t slen,
                                 const char **k, size_t *l, unsigned min_len)
@@ -375,7 +375,7 @@ size_t hattrie_weight (const hattrie_t *T)
 
 hattrie_t* hattrie_create_n(unsigned bucket_size, const mm_ctx_t *mm)
 {
-    hattrie_t* T = mm->alloc(mm->ctx, sizeof(hattrie_t));
+    hattrie_t* T = mm_alloc((mm_ctx_t *)mm, sizeof(hattrie_t));
     memcpy(&T->mm, mm, sizeof(mm_ctx_t));
     hattrie_init(T, bucket_size);
     return T;
@@ -765,7 +765,7 @@ static value_t* hattrie_walk_right(node_ptr* s, size_t sp,
         --key;
         --sp;
     }
-    
+
     return NULL;
 }
 
diff --git a/src/common-knot/hattrie/hat-trie.h b/src/common/trie/hat-trie.h
similarity index 97%
rename from src/common-knot/hattrie/hat-trie.h
rename to src/common/trie/hat-trie.h
index a188ec93612e0aa56c91bb9e694f6317d921768f..06ac1c6a30e7a8492e5ba9abbc4b64e2f129b199 100644
--- a/src/common-knot/hattrie/hat-trie.h
+++ b/src/common/trie/hat-trie.h
@@ -23,9 +23,9 @@ extern "C" {
 
 #include <stdlib.h>
 #include <stdbool.h>
-#include "libknot/common.h"
-#include "libknot/mempattern.h"
-#include "common-knot/hhash.h"
+#include "common/mempattern.h"
+#include "common/hhash.h"
+#include "libknot/errcode.h"
 
 /* Hat-trie defines. */
 #define TRIE_ZEROBUCKETS  0    /* Do not use hash buckets (pure trie). */
diff --git a/src/common-knot/hattrie/murmurhash3.c b/src/common/trie/murmurhash3.c
similarity index 96%
rename from src/common-knot/hattrie/murmurhash3.c
rename to src/common/trie/murmurhash3.c
index 2e9a21360c45ad714946718e59ec634d1fe7a392..ac9da6aca5ec1a81c92ebb078051aeeba7575251 100644
--- a/src/common-knot/hattrie/murmurhash3.c
+++ b/src/common/trie/murmurhash3.c
@@ -1,7 +1,7 @@
 /* This is MurmurHash3. The original C++ code was placed in the public domain
  * by its author, Austin Appleby. */
 
-#include "common-knot/hattrie/murmurhash3.h"
+#include "common/trie/murmurhash3.h"
 
 static inline uint32_t fmix(uint32_t h)
 {
diff --git a/src/common-knot/hattrie/murmurhash3.h b/src/common/trie/murmurhash3.h
similarity index 100%
rename from src/common-knot/hattrie/murmurhash3.h
rename to src/common/trie/murmurhash3.h
diff --git a/src/dnstap/reader.c b/src/dnstap/reader.c
index c0ff4d60ed9e17b2e2e91619db7b26ab3b5bc52f..495e0ae60e6d13c204a096bf2fcfbd77ee5ea595 100644
--- a/src/dnstap/reader.c
+++ b/src/dnstap/reader.c
@@ -20,7 +20,6 @@
 #include <string.h>                     // strdup
 
 #include "libknot/errcode.h"
-#include "libknot/common.h"
 
 #include "dnstap/dnstap.h"
 #include "dnstap/reader.h"
diff --git a/src/dnstap/writer.c b/src/dnstap/writer.c
index de5a7ff262a14ae60dd4917bd9647491bbb7f4b5..9a3bb8a2e29ce79228793d1e0201d822dbee4d12 100644
--- a/src/dnstap/writer.c
+++ b/src/dnstap/writer.c
@@ -20,7 +20,6 @@
 #include <string.h>                     // strdup
 
 #include "libknot/errcode.h"
-#include "libknot/common.h"
 
 #include "dnstap/dnstap.h"
 #include "dnstap/writer.h"
diff --git a/src/knot/conf/cf-lex.l b/src/knot/conf/cf-lex.l
index bb50c32818a6bda1d11fbf761849f07358708399..45bcf2bd7521c2ff6a4810bbede8e4ffa6feb91d 100644
--- a/src/knot/conf/cf-lex.l
+++ b/src/knot/conf/cf-lex.l
@@ -33,7 +33,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
 #include "knot/conf/conf.h"
 #include "knot/conf/includes.h"
 #include "knot/conf/extra.h"
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index 0db4e115d1d034b9f36d13cfbe951057f70b0151..a87ed1e9ae43c399c1cf991408a9af6005764c3f 100644
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -30,9 +30,9 @@
 #include <stdlib.h>
 #include <pwd.h>
 #include <grp.h>
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
 #include "common-knot/strlcat.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 #include "libknot/dname.h"
 #include "libknot/binary.h"
 #include "libknot/rrtype/opt.h"
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index a3fb94bb2eb79ad883d0a81c732d1401d459cd8c..9d0caed06c64568360469b157357c0fb3e2b1832 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -26,14 +26,14 @@
 
 #include <urcu.h>
 #include "common-knot/strlcat.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
+#include "common/macros.h"
 #include "common/mem.h"
 #include "knot/conf/conf.h"
 #include "knot/conf/extra.h"
 #include "knot/knot.h"
 #include "knot/ctl/remote.h"
 #include "knot/nameserver/internet.h"
-#include "knot/zone/timers.h"
 
 /*
  * Defaults.
@@ -413,7 +413,6 @@ static int conf_process(conf_t *conf)
 		size_t size = stor_len + zname_len + 9; // /diff.db,\0
 		char *dest = malloc(size);
 		if (dest == NULL) {
-			ERR_ALLOC_FAILED;
 			zone->ixfr_db = NULL; /* Not enough memory. */
 			ret = KNOT_ENOMEM; /* Error report. */
 			continue;
@@ -725,10 +724,6 @@ void conf_truncate(conf_t *conf, int unload_hooks)
 
 	/* Free remote control iface. */
 	conf_free_iface(conf->ctl.iface);
-	
-	/* Close timers db. */
-	close_timers_db(conf->timers_db);
-	conf->timers_db = NULL;
 }
 
 void conf_free(conf_t *conf)
@@ -781,12 +776,6 @@ int conf_open(const char* path)
 		return ret;
 	}
 
-	/* Open zone timers db. */
-	nconf->timers_db = open_timers_db(nconf->storage);
-	if (nconf->timers_db == NULL) {
-		log_warning("cannot open timers db");
-	}
-
 	/* Replace current config. */
 	conf_t **current_config = &s_config;
 	conf_t *oldconf = rcu_xchg_pointer(current_config, nconf);
@@ -806,11 +795,10 @@ int conf_open(const char* path)
 
 		/* Update hooks. */
 		conf_update_hooks(nconf);
-		
+
 		/* Free old config. */
 		conf_free(oldconf);
 	}
-	
 
 	return KNOT_EOK;
 }
@@ -990,6 +978,7 @@ void conf_free_group(conf_group_t *group)
 		free(remote);
 	}
 
+	free(group->name);
 	free(group);
 }
 
diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h
index e25a54d626841bac514fc7d6ecb29dcab745861b..988f8a38b6365faccbd2db087523d4b27ee0479a 100644
--- a/src/knot/conf/conf.h
+++ b/src/knot/conf/conf.h
@@ -37,12 +37,12 @@
 #include "libknot/rrtype/tsig.h"
 #include "libknot/dnssec/key.h"
 #include "libknot/dnssec/policy.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
 #include "common/namedb/namedb.h"
 #include "common/log.h"
 #include "knot/updates/acl.h"
-#include "common-knot/sockaddr.h"
-#include "common-knot/hattrie/hat-trie.h"
+#include "common/sockaddr.h"
+#include "common/trie/hat-trie.h"
 #include "knot/nameserver/query_module.h"
 
 /* Constants. */
@@ -269,11 +269,6 @@ typedef struct conf_t {
 	struct query_plan *query_plan;
 	list_t query_modules;
 
-	/*
-	 * Zone timers db
-	 */
-	knot_namedb_t *timers_db;
-
 	/*
 	 * Remote control interface.
 	 */
diff --git a/src/knot/ctl/estimator.c b/src/knot/ctl/estimator.c
index b9f94629418848c2eb83c786c93d35abf0e5ad44..c0b9ab2d3623ec42acc39ec8ca8ecca9150f77d8 100644
--- a/src/knot/ctl/estimator.c
+++ b/src/knot/ctl/estimator.c
@@ -18,7 +18,8 @@
 
 #include "knot/ctl/estimator.h"
 #include "libknot/dname.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
+#include "common/macros.h"
 #include "common/mem.h"
 #include "knot/zone/node.h"
 #include "libknot/descriptor.h"
diff --git a/src/knot/ctl/estimator.h b/src/knot/ctl/estimator.h
index 8060c9b1073cd8b1311c71b9b487005a2c339047..673ff446041d21cbd537d7859d2f6b9309169d70 100644
--- a/src/knot/ctl/estimator.h
+++ b/src/knot/ctl/estimator.h
@@ -26,7 +26,7 @@
 
 #pragma once
 
-#include "common-knot/hattrie/hat-trie.h"
+#include "common/trie/hat-trie.h"
 #include "zscanner/scanner.h"
 
 // Mutiplicative constant, needed because of malloc's fragmentation
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index 122a31e0f0ccd421b40d9f4cb59c46e5ef7e9191..cddaecaaa8a04560c44c91f5029e9f1c9ebd5f3d 100644
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -26,6 +26,7 @@
 #endif
 
 #include "knot/knot.h"
+#include "common/macros.h"
 #include "common/mem.h"
 #include "libknot/descriptor.h"
 #include "knot/ctl/process.h"
@@ -80,7 +81,7 @@ knot_cmd_t knot_cmd_tbl[] = {
 	{&cmd_stop,       0, "stop",       "",       "\t\tStop server."},
 	{&cmd_reload,     0, "reload",     "<zone>", "\tReload configuration and changed zones."},
 	{&cmd_refresh,    0, "refresh",    "<zone>", "\tRefresh slave zone (all if not specified). Flag '-f' forces retransfer."},
-	{&cmd_flush,      0, "flush",      "<zone>", "\t\tFlush journal and update zone file (all if not specified)."},
+	{&cmd_flush,      0, "flush",      "<zone>", "\tFlush journal and update zone file (all if not specified)."},
 	{&cmd_status,     0, "status",     "",       "\tCheck if server is running."},
 	{&cmd_zonestatus, 0, "zonestatus", "",       "\tShow status of configured zones."},
 	{&cmd_checkconf,  1, "checkconf",  "",       "\tCheck current server configuration."},
diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c
index 067f39bfb8ee68faaf9f40f5eb571848bc1f9a7c..68d24f8a6dfb2d3f6ab926a8b3436ed132f433a3 100644
--- a/src/knot/ctl/remote.c
+++ b/src/knot/ctl/remote.c
@@ -18,15 +18,16 @@
 #include <sys/stat.h>
 #include "knot/ctl/remote.h"
 #include "common/log.h"
+#include "common/macros.h"
 #include "common/mem.h"
 #include "common-knot/fdset.h"
 #include "knot/knot.h"
 #include "knot/conf/conf.h"
-#include "knot/server/net.h"
+#include "common/net.h"
 #include "knot/server/tcp-handler.h"
 #include "libknot/packet/wire.h"
 #include "libknot/descriptor.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 #include "libknot/tsig-op.h"
 #include "libknot/rrtype/rdname.h"
 #include "libknot/rrtype/soa.h"
@@ -719,7 +720,7 @@ static int zones_verify_tsig_query(const knot_pkt_t *query,
 	/*
 	 * 1) Check if we support the requested algorithm.
 	 */
-	knot_tsig_algorithm_t alg = tsig_rdata_alg(query->tsig_rr);
+	knot_tsig_algorithm_t alg = knot_tsig_rdata_alg(query->tsig_rr);
 	if (knot_tsig_digest_length(alg) == 0) {
 		log_info("TSIG, unsupported algorithm, query NOTAUTH");
 		/*! \todo [TSIG] It is unclear from RFC if I
@@ -758,7 +759,7 @@ static int zones_verify_tsig_query(const knot_pkt_t *query,
 	//memset(digest, 0 , digest_max_size);
 
 	//const uint8_t* mac = tsig_rdata_mac(tsig_rr);
-	size_t mac_len = tsig_rdata_mac_length(query->tsig_rr);
+	size_t mac_len = knot_tsig_rdata_mac_length(query->tsig_rr);
 
 	int ret = KNOT_EOK;
 
@@ -790,7 +791,7 @@ static int zones_verify_tsig_query(const knot_pkt_t *query,
 		case KNOT_TSIG_EBADTIME:
 			*tsig_rcode = KNOT_TSIG_ERR_BADTIME;
 			// store the time signed from the query
-			*tsig_prev_time_signed = tsig_rdata_time_signed(query->tsig_rr);
+			*tsig_prev_time_signed = knot_tsig_rdata_time_signed(query->tsig_rr);
 			*rcode = KNOT_RCODE_NOTAUTH;
 			break;
 		case KNOT_EMALF:
@@ -896,7 +897,7 @@ knot_pkt_t* remote_query(const char *query, const knot_tsig_key_t *key)
 	}
 
 	knot_wire_set_id(pkt->wire, knot_random_uint16_t());
-	knot_pkt_reserve(pkt, tsig_wire_maxsize(key));
+	knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(key));
 
 	/* Question section. */
 	char *qname = strcdup(query, KNOT_CTL_REALM_EXT);
diff --git a/src/knot/dnssec/nsec-chain.c b/src/knot/dnssec/nsec-chain.c
index 637b2b1991953fa4b8a269b62c887aac5365abd7..6c9220b3b97fa5def68258a7262991a11bf67bf5 100644
--- a/src/knot/dnssec/nsec-chain.c
+++ b/src/knot/dnssec/nsec-chain.c
@@ -45,21 +45,21 @@ static int create_nsec_rrset(knot_rrset_t *rrset, const zone_node_t *from,
 	// Create bitmap
 	bitmap_t rr_types = { 0 };
 	bitmap_add_node_rrsets(&rr_types, from);
-	bitmap_add_type(&rr_types, KNOT_RRTYPE_NSEC);
-	bitmap_add_type(&rr_types, KNOT_RRTYPE_RRSIG);
+	knot_bitmap_add_type(&rr_types, KNOT_RRTYPE_NSEC);
+	knot_bitmap_add_type(&rr_types, KNOT_RRTYPE_RRSIG);
 	if (node_rrtype_exists(from, KNOT_RRTYPE_SOA)) {
-		bitmap_add_type(&rr_types, KNOT_RRTYPE_DNSKEY);
+		knot_bitmap_add_type(&rr_types, KNOT_RRTYPE_DNSKEY);
 	}
 
 	// Create RDATA
 	assert(to->owner);
 	size_t next_owner_size = knot_dname_size(to->owner);
-	size_t rdata_size = next_owner_size + bitmap_size(&rr_types);
+	size_t rdata_size = next_owner_size + knot_bitmap_size(&rr_types);
 	uint8_t rdata[rdata_size];
 
 	// Fill RDATA
 	memcpy(rdata, to->owner, next_owner_size);
-	bitmap_write(&rr_types, rdata + next_owner_size);
+	knot_bitmap_write(&rr_types, rdata + next_owner_size);
 
 	return knot_rrset_add_rdata(rrset, rdata, rdata_size, ttl, NULL);
 }
diff --git a/src/knot/dnssec/nsec-chain.h b/src/knot/dnssec/nsec-chain.h
index 5b039d8ae4409ca0e22d24517312bfcbf363c11d..26440b27cfa92c02d2b997c26f54b8f959262d31 100644
--- a/src/knot/dnssec/nsec-chain.h
+++ b/src/knot/dnssec/nsec-chain.h
@@ -65,7 +65,7 @@ inline static void bitmap_add_node_rrsets(bitmap_t *bitmap,
 		knot_rrset_t rr = node_rrset_at(node, i);
 		if (rr.type != KNOT_RRTYPE_NSEC &&
 		    rr.type != KNOT_RRTYPE_RRSIG) {
-			bitmap_add_type(bitmap, rr.type);
+			knot_bitmap_add_type(bitmap, rr.type);
 		}
 	}
 }
diff --git a/src/knot/dnssec/nsec3-chain.c b/src/knot/dnssec/nsec3-chain.c
index a2cab60076ed8b8e04e4fc671850ac507dad4868..136a66cd493463d40168c6a4cfb44633a055d568 100644
--- a/src/knot/dnssec/nsec3-chain.c
+++ b/src/knot/dnssec/nsec3-chain.c
@@ -17,6 +17,7 @@
 #include <assert.h>
 
 #include "common/base32hex.h"
+#include "common/macros.h"
 #include "knot/dnssec/nsec3-chain.h"
 #include "libknot/dname.h"
 #include "libknot/packet/wire.h"
@@ -199,7 +200,7 @@ static size_t nsec3_rdata_size(const knot_nsec3_params_t *params,
 
 	return 6 + params->salt_length
 	       + knot_nsec3_hash_length(params->algorithm)
-	       + bitmap_size(rr_types);
+	       + knot_bitmap_size(rr_types);
 }
 
 /*!
@@ -234,7 +235,7 @@ static void nsec3_fill_rdata(uint8_t *rdata, const knot_nsec3_params_t *params,
 		memcpy(rdata, next_hashed, hash_length);
 	}
 	rdata += hash_length;
-	bitmap_write(rr_types, rdata);                    // RR types bit map
+	knot_bitmap_write(rr_types, rdata);                    // RR types bit map
 }
 
 /*!
@@ -336,10 +337,10 @@ static zone_node_t *create_nsec3_node_for_node(zone_node_t *node,
 	bitmap_t rr_types = { 0 };
 	bitmap_add_node_rrsets(&rr_types, node);
 	if (node->rrset_count > 0 && node_should_be_signed_nsec3(node)) {
-		bitmap_add_type(&rr_types, KNOT_RRTYPE_RRSIG);
+		knot_bitmap_add_type(&rr_types, KNOT_RRTYPE_RRSIG);
 	}
 	if (node == apex) {
-		bitmap_add_type(&rr_types, KNOT_RRTYPE_DNSKEY);
+		knot_bitmap_add_type(&rr_types, KNOT_RRTYPE_DNSKEY);
 	}
 
 	zone_node_t *nsec3_node;
diff --git a/src/knot/dnssec/zone-keys.c b/src/knot/dnssec/zone-keys.c
index f998b5bc80321e56b3368c012ff39194d4872a8b..1902019f020798285dfb73e9770a0f3756c8f01e 100644
--- a/src/knot/dnssec/zone-keys.c
+++ b/src/knot/dnssec/zone-keys.c
@@ -20,9 +20,9 @@
 #include <inttypes.h>
 
 #include "common/debug.h"
+#include "common/macros.h"
 #include "common/mem.h"
 #include "libknot/errcode.h"
-#include "libknot/common.h"
 #include "libknot/dname.h"
 #include "libknot/consts.h"
 #include "libknot/rrtype/dnskey.h"
@@ -200,7 +200,6 @@ int knot_load_zone_keys(const char *keydir_name, const knot_dname_t *zone_name,
 		size_t path_len = strlen(keydir_name) + 1 + strlen(entry->d_name);
 		char *path = malloc((path_len + 1) * sizeof(char));
 		if (!path) {
-			ERR_ALLOC_FAILED;
 			closedir(keydir);
 			return KNOT_ENOMEM;
 		}
diff --git a/src/knot/dnssec/zone-keys.h b/src/knot/dnssec/zone-keys.h
index f0ab0519ab0e951b4615087f80b4ad9a0bd304dc..e2a9d0e10ed17de13230ffc6776174f867262cf9 100644
--- a/src/knot/dnssec/zone-keys.h
+++ b/src/knot/dnssec/zone-keys.h
@@ -30,7 +30,7 @@
 
 #include <stdbool.h>
 #include <stdint.h>
-#include "common-knot/lists.h"
+#include "common/lists.h"
 #include "libknot/dname.h"
 #include "libknot/dnssec/sign.h"
 
diff --git a/src/knot/dnssec/zone-nsec.c b/src/knot/dnssec/zone-nsec.c
index 9051959c6840ee76194302a52a949df949091419..0d73bdab389d9d3c9058df13ffafdcc5cc85d6bd 100644
--- a/src/knot/dnssec/zone-nsec.c
+++ b/src/knot/dnssec/zone-nsec.c
@@ -23,7 +23,6 @@
 #include "common/base32hex.h"
 #include "common/debug.h"
 #include "libknot/descriptor.h"
-#include "common-knot/hhash.h"
 #include "libknot/dnssec/bitmap.h"
 #include "libknot/util/utils.h"
 #include "libknot/packet/wire.h"
diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c
index 67613488cd9a06eae0f6fc9d75676f5c7751237e..41466d602af5202b406413293f4d483777a49d36 100644
--- a/src/knot/dnssec/zone-sign.c
+++ b/src/knot/dnssec/zone-sign.c
@@ -21,10 +21,10 @@
 #include <time.h>
 
 #include "common/debug.h"
+#include "common/macros.h"
 #include "libknot/descriptor.h"
 #include "libknot/errcode.h"
-#include "common-knot/hattrie/hat-trie.h"
-#include "libknot/common.h"
+#include "common/trie/hat-trie.h"
 #include "libknot/dname.h"
 #include "libknot/rrset.h"
 #include "libknot/dnssec/key.h"
@@ -996,7 +996,6 @@ static int add_rr_type_to_list(const knot_rrset_t *rr, list_t *l)
 
 	type_node_t *n = malloc(sizeof(type_node_t));
 	if (n == NULL) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 	n->type = rr->type;
@@ -1031,7 +1030,6 @@ static int rr_already_signed(const knot_rrset_t *rrset, hattrie_t *t,
 		// Create new info struct
 		signed_info_t *info = malloc(sizeof(signed_info_t));
 		if (info == NULL) {
-			ERR_ALLOC_FAILED;
 			return KNOT_ENOMEM;
 		}
 		memset(info, 0, sizeof(signed_info_t));
@@ -1044,7 +1042,6 @@ static int rr_already_signed(const knot_rrset_t *rrset, hattrie_t *t,
 		// Create new list to insert as a value
 		info->type_list = malloc(sizeof(list_t));
 		if (info->type_list == NULL) {
-			ERR_ALLOC_FAILED;
 			free(info->dname);
 			free(info);
 			return KNOT_ENOMEM;
@@ -1357,7 +1354,7 @@ int knot_zone_sign_changeset(const zone_contents_t *zone,
 	}
 	changeset_iter_t itt;
 	changeset_iter_all(&itt, in_ch, false);
-	
+
 	knot_rrset_t rr = changeset_iter_next(&itt);
 	while (!knot_rrset_empty(&rr)) {
 		int ret = sign_changeset_wrap(&rr, &args);
@@ -1388,7 +1385,7 @@ int knot_zone_sign_nsecs_in_changeset(const knot_zone_keys_t *zone_keys,
 
 	changeset_iter_t itt;
 	changeset_iter_add(&itt, changeset, false);
-	
+
 	knot_rrset_t rr = changeset_iter_next(&itt);
 	while (!knot_rrset_empty(&rr)) {
 		if (rr.type == KNOT_RRTYPE_NSEC ||
@@ -1403,7 +1400,7 @@ int knot_zone_sign_nsecs_in_changeset(const knot_zone_keys_t *zone_keys,
 		rr = changeset_iter_next(&itt);
 	}
 	changeset_iter_clear(&itt);
-	
+
 	return KNOT_EOK;
 }
 
diff --git a/src/knot/knot.h b/src/knot/knot.h
index 093ce7aa999c9b98feaaec46e162cba65dcc9c3c..050398a3f993d0535a9ee9797632b69c48909cd2 100644
--- a/src/knot/knot.h
+++ b/src/knot/knot.h
@@ -29,7 +29,7 @@
 #include <signal.h>
 #include <stdint.h>
 
-#include "common-knot/print.h"
+#include "common/print.h"
 #include "common/log.h"
 #include "libknot/errcode.h"
 #include "knot/other/debug.h"
diff --git a/src/knot/main.c b/src/knot/main.c
index 2dc5e3f55613ac3a6993f0c30abe159b9f87a927..d28a22769dc80e9529204045847122e42ec7205f 100644
--- a/src/knot/main.c
+++ b/src/knot/main.c
@@ -29,7 +29,6 @@
 #include <systemd/sd-daemon.h>
 #endif
 
-#include "libknot/common.h"
 #include "libknot/dnssec/crypto.h"
 #include "knot/knot.h"
 #include "knot/server/server.h"
diff --git a/src/knot/modules/dnstap.c b/src/knot/modules/dnstap.c
index 38cf63359cccd96f1b216e876af29c161689538f..8c991724199ca463a88d4c8d59854625f3baa984 100644
--- a/src/knot/modules/dnstap.c
+++ b/src/knot/modules/dnstap.c
@@ -31,7 +31,7 @@
 static int log_message(int state, const knot_pkt_t *pkt, struct query_data *qdata, void *ctx)
 {
 	if (pkt == NULL || qdata == NULL || ctx == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	int ret = KNOT_ERROR;
@@ -63,7 +63,7 @@ static int log_message(int state, const knot_pkt_t *pkt, struct query_data *qdat
 	                      protocol,
 	                      pkt->wire, pkt->size, &tv, &tv);
 	if (ret != KNOT_EOK) {
-		return NS_PROC_FAIL; 
+		return KNOT_NS_PROC_FAIL; 
 	}
 	Dnstap__Dnstap dnstap = DNSTAP__DNSTAP__INIT;
 	dnstap.type = DNSTAP__DNSTAP__TYPE__MESSAGE;
@@ -74,7 +74,7 @@ static int log_message(int state, const knot_pkt_t *pkt, struct query_data *qdat
 	size_t size = 0;
 	dt_pack(&dnstap, &frame, &size);
 	if (frame == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Submit a request. */
@@ -82,7 +82,7 @@ static int log_message(int state, const knot_pkt_t *pkt, struct query_data *qdat
 	                                   fstrm_free_wrapper, NULL);
 	if (res != fstrm_res_success) {
 		free(frame);
-		state = NS_PROC_FAIL;
+		state = KNOT_NS_PROC_FAIL;
 	}
 
 	return state;
@@ -92,7 +92,7 @@ static int log_message(int state, const knot_pkt_t *pkt, struct query_data *qdat
 static int dnstap_message_log(int state, knot_pkt_t *pkt, struct query_data *qdata, void *ctx)
 {
 	if (pkt == NULL || qdata == NULL || ctx == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	return log_message(state, pkt, qdata, ctx);
diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c
index bde81799a06a100b416e6951890f5d418f243df8..23115a055096faaa49791b014ebb096b950b7716 100644
--- a/src/knot/nameserver/axfr.c
+++ b/src/knot/nameserver/axfr.c
@@ -22,7 +22,7 @@
 #include "knot/zone/zonefile.h"
 #include "common/debug.h"
 #include "libknot/descriptor.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
 
 /* AXFR context. @note aliasing the generic xfr_proc */
 struct axfr_proc {
@@ -111,7 +111,7 @@ static int axfr_query_check(struct query_data *qdata)
 	/* Check expiration. */
 	NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL);
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 static int axfr_query_init(struct query_data *qdata)
@@ -120,7 +120,7 @@ static int axfr_query_init(struct query_data *qdata)
 
 	/* Check AXFR query validity. */
 	int state = axfr_query_check(qdata);
-	if (state == NS_PROC_FAIL) {
+	if (state == KNOT_NS_PROC_FAIL) {
 		if (qdata->rcode == KNOT_RCODE_FORMERR) {
 			return KNOT_EMALF;
 		} else {
@@ -132,7 +132,7 @@ static int axfr_query_init(struct query_data *qdata)
 	mm_ctx_t *mm = qdata->mm;
 
 	zone_contents_t *zone = qdata->zone->contents;
-	struct axfr_proc *axfr = mm->alloc(mm->ctx, sizeof(struct axfr_proc));
+	struct axfr_proc *axfr = mm_alloc(mm, sizeof(struct axfr_proc));
 	if (axfr == NULL) {
 		return KNOT_ENOMEM;
 	}
@@ -187,7 +187,7 @@ int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb process_item,
 		if (ret == KNOT_EOK) { /* Finished. */
 			/* Complete change set. */
 			rem_node((node_t *)head);
-			mm->free(head);
+			mm_free(mm, head);
 		} else { /* Packet full or other error. */
 			break;
 		}
@@ -212,7 +212,7 @@ int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb process_item,
 int axfr_query_process(knot_pkt_t *pkt, struct query_data *qdata)
 {
 	if (pkt == NULL || qdata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	int ret = KNOT_EOK;
@@ -221,7 +221,7 @@ int axfr_query_process(knot_pkt_t *pkt, struct query_data *qdata)
 	/* If AXFR is disabled, respond with NOTIMPL. */
 	if (qdata->param->proc_flags & NS_QUERY_NO_AXFR) {
 		qdata->rcode = KNOT_RCODE_NOTIMPL;
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Initialize on first call. */
@@ -231,7 +231,7 @@ int axfr_query_process(knot_pkt_t *pkt, struct query_data *qdata)
 		if (ret != KNOT_EOK) {
 			AXFROUT_LOG(LOG_ERR, "failed to start (%s)",
 			            knot_strerror(ret));
-			return NS_PROC_FAIL;
+			return KNOT_NS_PROC_FAIL;
 		} else {
 			AXFROUT_LOG(LOG_INFO, "started, serial %u",
 			           zone_contents_serial(qdata->zone->contents));
@@ -239,25 +239,25 @@ int axfr_query_process(knot_pkt_t *pkt, struct query_data *qdata)
 	}
 
 	/* Reserve space for TSIG. */
-	knot_pkt_reserve(pkt, tsig_wire_maxsize(qdata->sign.tsig_key));
+	knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(qdata->sign.tsig_key));
 
 	/* Answer current packet (or continue). */
 	struct axfr_proc *axfr = (struct axfr_proc *)qdata->ext;
 	ret = xfr_process_list(pkt, &axfr_process_node_tree, qdata);
 	switch(ret) {
 	case KNOT_ESPACE: /* Couldn't write more, send packet and continue. */
-		return NS_PROC_FULL; /* Check for more. */
+		return KNOT_NS_PROC_FULL; /* Check for more. */
 	case KNOT_EOK:    /* Last response. */
 		gettimeofday(&now, NULL);
 		AXFROUT_LOG(LOG_INFO,
 		            "finished, %.02f seconds, %u messages, %u bytes",
 		            time_diff(&axfr->proc.tstamp, &now) / 1000.0,
 		            axfr->proc.npkts, axfr->proc.nbytes);
-		return NS_PROC_DONE;
+		return KNOT_NS_PROC_DONE;
 		break;
 	default:          /* Generic error. */
 		AXFROUT_LOG(LOG_ERR, "failed (%s)", knot_strerror(ret));
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 }
 #undef AXFROUT_LOG
@@ -359,22 +359,22 @@ static int axfr_answer_packet(knot_pkt_t *pkt, struct xfr_proc *proc)
 		const knot_rrset_t *rr = &answer->rr[i];
 		if (rr->type == KNOT_RRTYPE_SOA &&
 		    node_rrtype_exists(zc.z->apex, KNOT_RRTYPE_SOA)) {
-			return NS_PROC_DONE;
+			return KNOT_NS_PROC_DONE;
 		} else {
 			int ret = zcreator_step(&zc, rr);
 			if (ret != KNOT_EOK) {
-				return NS_PROC_FAIL;
+				return KNOT_NS_PROC_FAIL;
 			}
 		}
 	}
 
-	return NS_PROC_MORE;
+	return KNOT_NS_PROC_MORE;
 }
 
 int axfr_answer_process(knot_pkt_t *pkt, struct answer_data *adata)
 {
 	if (pkt == NULL || adata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Check RCODE. */
@@ -384,22 +384,18 @@ int axfr_answer_process(knot_pkt_t *pkt, struct answer_data *adata)
 		if (lut != NULL) {
 			AXFRIN_LOG(LOG_ERR, "server responded with %s", lut->name);
 		}
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Initialize processing with first packet. */
 	if (adata->ext == NULL) {
 		NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
-		if (!zone_transfer_needed(adata->param->zone, pkt)) {
-			AXFRIN_LOG(LOG_INFO, "zone is up-to-date");
-			return NS_PROC_DONE;
-		}
 		AXFRIN_LOG(LOG_INFO, "starting");
 
 		int ret = axfr_answer_init(adata);
 		if (ret != KNOT_EOK) {
 			AXFRIN_LOG(LOG_ERR, "failed (%s)", knot_strerror(ret));
-			return NS_PROC_FAIL;
+			return KNOT_NS_PROC_FAIL;
 		}
 	} else {
 		NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 100);
@@ -407,12 +403,12 @@ int axfr_answer_process(knot_pkt_t *pkt, struct answer_data *adata)
 
 	/* Process answer packet. */
 	int ret = axfr_answer_packet(pkt, (struct xfr_proc *)adata->ext);
-	if (ret == NS_PROC_DONE) {
+	if (ret == KNOT_NS_PROC_DONE) {
 		NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
 		/* This was the last packet, finalize zone and publish it. */
 		int fret = axfr_answer_finalize(adata);
 		if (fret != KNOT_EOK) {
-			ret = NS_PROC_FAIL;
+			ret = KNOT_NS_PROC_FAIL;
 		}
 	}
 
diff --git a/src/knot/nameserver/axfr.h b/src/knot/nameserver/axfr.h
index b700ce792380cf4a5f07ae7f8063b9cc83b7cf1d..c6edd0d541cd78ff93c22aafa8836f9f42d50128 100644
--- a/src/knot/nameserver/axfr.h
+++ b/src/knot/nameserver/axfr.h
@@ -54,14 +54,14 @@ int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb put, struct query_data *qdata);
 /*!
  * \brief Process an AXFR query message.
  *
- * \return NS_PROC_* processing states
+ * \return KNOT_NS_PROC_* processing states
  */
 int axfr_query_process(knot_pkt_t *pkt, struct query_data *qdata);
 
 /*!
  * \brief Processes an AXFR response message.
  *
- * \return NS_PROC_* processing states
+ * \return KNOT_NS_PROC_* processing states
  */
 int axfr_answer_process(knot_pkt_t *pkt, struct answer_data *adata);
 
diff --git a/src/knot/nameserver/capture.c b/src/knot/nameserver/capture.c
index 30c9a4bd86b928b6b360aed3503001eb1947bd90..e0595d152ac4801fd9e59f0d39032df5bcca331c 100644
--- a/src/knot/nameserver/capture.c
+++ b/src/knot/nameserver/capture.c
@@ -19,40 +19,45 @@
 #include "knot/server/udp-handler.h"
 
 /* State-less packet capture, only incoming data is accepted. */
-static int reset(knot_process_t *ctx)  { return NS_PROC_MORE; }
-static int finish(knot_process_t *ctx) { return NS_PROC_NOOP; }
+static int reset(knot_layer_t *ctx)  { return KNOT_NS_PROC_FULL; }
+static int finish(knot_layer_t *ctx) { return KNOT_NS_PROC_NOOP; }
 
 /* Set capture parameters (sink). */
-static int begin(knot_process_t *ctx, void *module_param)
+static int begin(knot_layer_t *ctx, void *module_param)
 {
 	ctx->data = module_param;
-	return NS_PROC_MORE;
+	return reset(ctx);
+}
+
+static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
+{
+	/* \note Don't touch the query, expect answer. */
+	return KNOT_NS_PROC_MORE;
 }
 
 /* Forward packet. */
-static int capture(knot_pkt_t *pkt, knot_process_t *ctx)
+static int capture(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	assert(pkt && ctx);
-	struct process_capture_param *param = ctx->data;
+	struct capture_param *param = ctx->data;
 
 	/* Copy packet contents and free. */
 	knot_pkt_copy(param->sink, pkt);
-	knot_pkt_free(&pkt);
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 /*! \brief Module implementation. */
-static const knot_process_module_t PROCESS_CAPTURE_MODULE = {
+static const knot_layer_api_t CAPTURE_LAYER = {
 	&begin,
 	&reset,
 	&finish,
 	&capture,
-	&knot_process_noop, /* No output. */
-	&knot_process_noop  /* No error processing. */
+	&prepare_query,
+	NULL
 };
 
-const knot_process_module_t *proc_capture_get_module(void)
+const knot_layer_api_t *capture_get_module(void)
 {
-	return &PROCESS_CAPTURE_MODULE;
+	return &CAPTURE_LAYER;
 }
diff --git a/src/knot/nameserver/capture.h b/src/knot/nameserver/capture.h
index fac85a9d7a4aa385d7cd42763d1249e47b3fff3d..44ee80ded1edac60d9496cdfcf892520c5aa9a5a 100644
--- a/src/knot/nameserver/capture.h
+++ b/src/knot/nameserver/capture.h
@@ -26,18 +26,18 @@
 
 #pragma once
 
-#include "libknot/processing/process.h"
+#include "libknot/processing/layer.h"
 #include "libknot/packet/pkt.h"
 
 /* Processing module implementation. */
-const knot_process_module_t *proc_capture_get_module(void);
-#define NS_PROC_CAPTURE proc_capture_get_module()
-#define NS_PROC_CAPTURE_ID 3
+const knot_layer_api_t *capture_get_module(void);
+#define LAYER_CAPTURE capture_get_module()
+#define LAYER_CAPTURE_ID 3
 
 /*!
  * \brief Processing module parameters.
  */
-struct process_capture_param {
+struct capture_param {
 	knot_pkt_t *sink;        /*!< Container for captured response. */
 };
 
diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c
index 8510eba2736a8aae7b782cd68c9089cdece537e0..09c2f0c3fa7aafa5e303d5976c3c483590b7363f 100644
--- a/src/knot/nameserver/internet.c
+++ b/src/knot/nameserver/internet.c
@@ -16,7 +16,6 @@
 
 #include "common/debug.h"
 #include "libknot/descriptor.h"
-#include "libknot/common.h"
 #include "libknot/rrtype/rdname.h"
 #include "libknot/rrtype/soa.h"
 #include "libknot/dnssec/rrset-sign.h"
@@ -50,7 +49,7 @@ static int wildcard_visit(struct query_data *qdata, const zone_node_t *node, con
 	}
 
 	mm_ctx_t *mm = qdata->mm;
-	struct wildcard_hit *item = mm->alloc(mm->ctx, sizeof(struct wildcard_hit));
+	struct wildcard_hit *item = mm_alloc(mm, sizeof(struct wildcard_hit));
 	item->node = node;
 	item->sname = sname;
 	add_tail(&qdata->wildcards, (node_t *)item);
@@ -179,9 +178,9 @@ static int put_answer(knot_pkt_t *pkt, uint16_t type, struct query_data *qdata)
 	 * QNAME position. Just need to check if we're answering QNAME and not
 	 * a CNAME target.
 	 */
-	uint16_t compr_hint = COMPR_HINT_NONE;
+	uint16_t compr_hint = KNOT_COMPR_HINT_NONE;
 	if (pkt->rrset_count == 0) { /* Guaranteed first answer. */
-		compr_hint = COMPR_HINT_QNAME;
+		compr_hint = KNOT_COMPR_HINT_QNAME;
 	}
 
 	int ret = KNOT_EOK;
@@ -236,7 +235,7 @@ static int put_authority_ns(knot_pkt_t *pkt, struct query_data *qdata)
 	knot_rrset_t ns_rrset = node_rrset(zone->apex, KNOT_RRTYPE_NS);
 	if (!knot_rrset_empty(&ns_rrset)) {
 		knot_rrset_t rrsigs = node_rrset(zone->apex, KNOT_RRTYPE_RRSIG);
-		return ns_put_rr(pkt, &ns_rrset, &rrsigs, COMPR_HINT_NONE,
+		return ns_put_rr(pkt, &ns_rrset, &rrsigs, KNOT_COMPR_HINT_NONE,
 		                 KNOT_PF_NOTRUNC|KNOT_PF_CHECKDUP, qdata);
 	} else {
 		dbg_ns("%s: no NS RRSets in this zone, fishy...\n", __func__);
@@ -277,7 +276,7 @@ static int put_authority_soa(knot_pkt_t *pkt, struct query_data *qdata,
 		soa_rrset = copy;
 	}
 
-	ret = ns_put_rr(pkt, &soa_rrset, &rrsigs, COMPR_HINT_NONE, flags, qdata);
+	ret = ns_put_rr(pkt, &soa_rrset, &rrsigs, KNOT_COMPR_HINT_NONE, flags, qdata);
 	if (ret != KNOT_EOK && (flags & KNOT_PF_FREE)) {
 		knot_rrset_clear(&soa_rrset, &pkt->mm);
 	}
@@ -296,7 +295,7 @@ static int put_delegation(knot_pkt_t *pkt, struct query_data *qdata)
 	/* Insert NS record. */
 	knot_rrset_t rrset = node_rrset(qdata->node, KNOT_RRTYPE_NS);
 	knot_rrset_t rrsigs = node_rrset(qdata->node, KNOT_RRTYPE_RRSIG);
-	return ns_put_rr(pkt, &rrset, &rrsigs, COMPR_HINT_NONE, 0, qdata);
+	return ns_put_rr(pkt, &rrset, &rrsigs, KNOT_COMPR_HINT_NONE, 0, qdata);
 }
 
 /*! \brief Put additional records for given RR. */
@@ -310,13 +309,13 @@ static int put_additional(knot_pkt_t *pkt, const knot_rrset_t *rr,
 
 	int ret = KNOT_EOK;
 	uint32_t flags = KNOT_PF_NOTRUNC|KNOT_PF_CHECKDUP;
-	uint16_t hint = COMPR_HINT_NONE;
+	uint16_t hint = KNOT_COMPR_HINT_NONE;
 	const zone_node_t *node = NULL;
 
 	/* All RRs should have additional node cached or NULL. */
 	uint16_t rr_rdata_count = rr->rrs.rr_count;
 	for (uint16_t i = 0; i < rr_rdata_count; i++) {
-		hint = knot_pkt_compr_hint(info, COMPR_HINT_RDATA + i);
+		hint = knot_pkt_compr_hint(info, KNOT_COMPR_HINT_RDATA + i);
 		node = rr->additional[i];
 
 		/* No additional node for this record. */
@@ -714,7 +713,7 @@ int ns_put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr,
 	 * hint. */
 	int ret = KNOT_EOK;
 	knot_rrset_t to_add;
-	if (compr_hint == COMPR_HINT_NONE && expand) {
+	if (compr_hint == KNOT_COMPR_HINT_NONE && expand) {
 		knot_dname_t *qname_cpy = knot_dname_copy(qdata->name, &pkt->mm);
 		if (qname_cpy == NULL) {
 			return KNOT_ENOMEM;
@@ -752,9 +751,9 @@ int ns_put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr,
 #define SOLVE_STEP(solver, state, context) \
 	state = (solver)(state, response, qdata, context); \
 	if (state == TRUNC) { \
-		return NS_PROC_DONE; \
+		return KNOT_NS_PROC_DONE; \
 	} else if (state == ERROR) { \
-		return NS_PROC_FAIL; \
+		return KNOT_NS_PROC_FAIL; \
 	}
 
 static int default_answer(knot_pkt_t *response, struct query_data *qdata)
@@ -782,7 +781,7 @@ static int default_answer(knot_pkt_t *response, struct query_data *qdata)
 	/* Write resulting RCODE. */
 	knot_wire_set_rcode(response->wire, qdata->rcode);
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 static int planned_answer(struct query_plan *plan, knot_pkt_t *response, struct query_data *qdata)
@@ -811,7 +810,7 @@ static int planned_answer(struct query_plan *plan, knot_pkt_t *response, struct
 	/* Write resulting RCODE. */
 	knot_wire_set_rcode(response->wire, qdata->rcode);
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 #undef SOLVE_STEP
@@ -820,7 +819,7 @@ int internet_query(knot_pkt_t *response, struct query_data *qdata)
 {
 	dbg_ns("%s(%p, %p)\n", __func__, response, qdata);
 	if (response == NULL || qdata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Check valid zone, transaction security (optional) and contents. */
@@ -832,7 +831,7 @@ int internet_query(knot_pkt_t *response, struct query_data *qdata)
 		NS_NEED_AUTH(&qdata->zone->conf->acl.xfr_out, qdata);
 
 		/* Reserve space for TSIG. */
-		knot_pkt_reserve(response, tsig_wire_maxsize(qdata->sign.tsig_key));
+		knot_pkt_reserve(response, knot_tsig_wire_maxsize(qdata->sign.tsig_key));
 	}
 
 	NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL); /* Expired */
@@ -864,18 +863,18 @@ int internet_query_plan(struct query_plan *plan)
 /*! \brief Process answer to SOA query. */
 static int process_soa_answer(knot_pkt_t *pkt, struct answer_data *data)
 {
-	zone_t *zone  = data->param->zone;
+	zone_t *zone = data->param->zone;
 
 	/* Expect SOA in answer section. */
 	const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
 	if (answer->count < 1 || answer->rr[0].type != KNOT_RRTYPE_SOA) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Our zone is expired, schedule transfer. */
 	if (zone_contents_is_empty(zone->contents)) {
 		zone_events_schedule(zone, ZONE_EVENT_XFER, ZONE_EVENT_NOW);
-		return NS_PROC_DONE;
+		return KNOT_NS_PROC_DONE;
 	}
 
 	/* Check if master has newer zone and schedule transfer. */
@@ -884,20 +883,21 @@ static int process_soa_answer(knot_pkt_t *pkt, struct answer_data *data)
 	uint32_t their_serial =	knot_soa_serial(&answer->rr[0].rrs);
 	if (knot_serial_compare(our_serial, their_serial) >= 0) {
 		ANSWER_LOG(LOG_INFO, data, "refresh, outgoing", "zone is up-to-date");
-		return NS_PROC_DONE; /* Our zone is up to date. */
+		zone_events_cancel(zone, ZONE_EVENT_EXPIRE);
+		return KNOT_NS_PROC_DONE; /* Our zone is up to date. */
 	}
 
 	/* Our zone is outdated, schedule zone transfer. */
 	ANSWER_LOG(LOG_INFO, data, "refresh, outgoing", "master has newer serial %u -> %u",
 	           our_serial, their_serial);
 	zone_events_schedule(zone, ZONE_EVENT_XFER, ZONE_EVENT_NOW);
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 int internet_process_answer(knot_pkt_t *pkt, struct answer_data *data)
 {
 	if (pkt == NULL || data == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	NS_NEED_TSIG_SIGNED(&data->param->tsig_ctx, 0);
@@ -907,6 +907,6 @@ int internet_process_answer(knot_pkt_t *pkt, struct answer_data *data)
 	case KNOT_RRTYPE_SOA:
 		return process_soa_answer(pkt, data);
 	default:
-		return NS_PROC_NOOP;
+		return KNOT_NS_PROC_NOOP;
 	}
 }
diff --git a/src/knot/nameserver/internet.h b/src/knot/nameserver/internet.h
index f3d1134feeb391861f40b083f764760cce4ec9f0..fed9affd3c89f95e2b9b539867558be96d61eb04 100644
--- a/src/knot/nameserver/internet.h
+++ b/src/knot/nameserver/internet.h
@@ -27,6 +27,7 @@
 #pragma once
 
 #include "libknot/packet/pkt.h"
+#include "libknot/processing/layer.h"
 #include "knot/zone/contents.h"
 
 /* Query data (from query processing). */
@@ -92,43 +93,43 @@ int ns_put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr,
 #define NS_NEED_QTYPE(qdata, qtype_want, error_rcode) \
 	if (knot_pkt_qtype((qdata)->query) != (qtype_want)) { \
 		qdata->rcode = (error_rcode); \
-		return NS_PROC_FAIL; \
+		return KNOT_NS_PROC_FAIL; \
 	}
 
 /*! \brief Require given QUERY NAME or return error code. */
 #define NS_NEED_QNAME(qdata, qname_want, error_rcode) \
 	if (!knot_dname_is_equal(knot_pkt_qname((qdata)->query), (qname_want))) { \
 		qdata->rcode = (error_rcode); \
-		return NS_PROC_FAIL; \
+		return KNOT_NS_PROC_FAIL; \
 	}
 
 /*! \brief Require existing zone or return failure. */
 #define NS_NEED_ZONE(qdata, error_rcode) \
 	if ((qdata)->zone == NULL) { \
 		qdata->rcode = (error_rcode); \
-		return NS_PROC_FAIL; \
+		return KNOT_NS_PROC_FAIL; \
 	}
 
 /*! \brief Require existing zone contents or return failure. */
 #define NS_NEED_ZONE_CONTENTS(qdata, error_rcode) \
 	if ((qdata)->zone->contents == NULL) { \
 		qdata->rcode = (error_rcode); \
-		return NS_PROC_FAIL; \
+		return KNOT_NS_PROC_FAIL; \
 	}
 
 /*! \brief Require authentication. */
 #define NS_NEED_AUTH(acl, qdata) \
 	if (!process_query_acl_check((acl), (qdata))) { \
-		return NS_PROC_FAIL; \
+		return KNOT_NS_PROC_FAIL; \
 	} else { \
 		if (process_query_verify(qdata) != KNOT_EOK) { \
-			return NS_PROC_FAIL; \
+			return KNOT_NS_PROC_FAIL; \
 		} \
 	}
 
 #define NS_NEED_TSIG_SIGNED(tsig_ctx, max_unsigned) \
 	if (tsig_unsigned_count(tsig_ctx) > max_unsigned) { \
-		return NS_PROC_FAIL; \
+		return KNOT_NS_PROC_FAIL; \
 	}
 
 /*! @} */
diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c
index f3c7a338e3fab34d51b5ae11000c062bca5084a8..451e5a3c13b07948e05bc18799c60d7a6c973962 100644
--- a/src/knot/nameserver/ixfr.c
+++ b/src/knot/nameserver/ixfr.c
@@ -197,7 +197,7 @@ static int ixfr_query_check(struct query_data *qdata)
 	const knot_rrset_t *their_soa = &authority->rr[0];
 	if (authority->count < 1 || their_soa->type != KNOT_RRTYPE_SOA) {
 		qdata->rcode = KNOT_RCODE_FORMERR;
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 	/* SOA needs to match QNAME. */
 	NS_NEED_QNAME(qdata, their_soa->owner, KNOT_RCODE_FORMERR);
@@ -206,7 +206,7 @@ static int ixfr_query_check(struct query_data *qdata)
 	NS_NEED_AUTH(&qdata->zone->conf->acl.xfr_out, qdata);
 	NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL); /* Check expiration. */
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 /*! \brief Cleans up ixfr processing context. */
@@ -218,7 +218,7 @@ static void ixfr_answer_cleanup(struct query_data *qdata)
 	ptrlist_free(&ixfr->proc.nodes, mm);
 	changeset_iter_clear(&ixfr->cur);
 	changesets_free(&ixfr->changesets);
-	mm->free(qdata->ext);
+	mm_free(mm, qdata->ext);
 
 	/* Allow zone changes (finished). */
 	rcu_read_unlock();
@@ -229,7 +229,7 @@ static int ixfr_answer_init(struct query_data *qdata)
 {
 	/* Check IXFR query validity. */
 	int state = ixfr_query_check(qdata);
-	if (state == NS_PROC_FAIL) {
+	if (state == KNOT_NS_PROC_FAIL) {
 		if (qdata->rcode == KNOT_RCODE_FORMERR) {
 			return KNOT_EMALF;
 		} else {
@@ -249,7 +249,7 @@ static int ixfr_answer_init(struct query_data *qdata)
 
 	/* Initialize transfer processing. */
 	mm_ctx_t *mm = qdata->mm;
-	struct ixfr_proc *xfer = mm->alloc(mm->ctx, sizeof(struct ixfr_proc));
+	struct ixfr_proc *xfer = mm_alloc(mm, sizeof(struct ixfr_proc));
 	if (xfer == NULL) {
 		changesets_free(&chgsets);
 		return KNOT_ENOMEM;
@@ -291,31 +291,31 @@ static int ixfr_answer_soa(knot_pkt_t *pkt, struct query_data *qdata)
 {
 	dbg_ns("%s: answering IXFR/SOA\n", __func__);
 	if (pkt == NULL || qdata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Check query. */
 	int state = ixfr_query_check(qdata);
-	if (state == NS_PROC_FAIL) {
+	if (state == KNOT_NS_PROC_FAIL) {
 		return state; /* Malformed query. */
 	}
 
 	/* Reserve space for TSIG. */
-	knot_pkt_reserve(pkt, tsig_wire_maxsize(qdata->sign.tsig_key));
+	knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(qdata->sign.tsig_key));
 
 	/* Guaranteed to have zone contents. */
 	const zone_node_t *apex = qdata->zone->contents->apex;
 	knot_rrset_t soa_rr = node_rrset(apex, KNOT_RRTYPE_SOA);
 	if (knot_rrset_empty(&soa_rr)) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 	int ret = knot_pkt_put(pkt, 0, &soa_rr, 0);
 	if (ret != KNOT_EOK) {
 		qdata->rcode = KNOT_RCODE_SERVFAIL;
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 /* ------------------------- IXFR-in processing ----------------------------- */
@@ -569,7 +569,7 @@ static bool out_of_zone(const knot_rrset_t *rr, struct ixfr_proc *proc)
  * \param pkt    Packet containing the IXFR reply in wire format.
  * \param adata  Answer data, including processing context.
  *
- * \return NS_PROC_MORE, NS_PROC_DONE, NS_PROC_FAIL
+ * \return KNOT_NS_PROC_MORE, KNOT_NS_PROC_DONE, KNOT_NS_PROC_FAIL
  */
 static int process_ixfrin_packet(knot_pkt_t *pkt, struct answer_data *adata)
 {
@@ -584,7 +584,7 @@ static int process_ixfrin_packet(knot_pkt_t *pkt, struct answer_data *adata)
 	for (uint16_t i = 0; i < answer->count; ++i) {
 		if (journal_limit_exceeded(ixfr)) {
 			IXFRIN_LOG(LOG_WARNING, "journal is full");
-			return NS_PROC_FAIL;
+			return KNOT_NS_PROC_FAIL;
 		}
 
 		const knot_rrset_t *rr = &answer->rr[i];
@@ -595,16 +595,16 @@ static int process_ixfrin_packet(knot_pkt_t *pkt, struct answer_data *adata)
 		int ret = ixfrin_step(rr, ixfr);
 		if (ret != KNOT_EOK) {
 			IXFRIN_LOG(LOG_WARNING, "failed (%s)", knot_strerror(ret));
-			return NS_PROC_FAIL;
+			return KNOT_NS_PROC_FAIL;
 		}
 
 		if (ixfr->state == IXFR_DONE) {
 			// Transfer done, do not consume more RRs.
-			return NS_PROC_DONE;
+			return KNOT_NS_PROC_DONE;
 		}
 	}
 
-	return NS_PROC_MORE;
+	return KNOT_NS_PROC_MORE;
 }
 
 /* --------------------------------- API ------------------------------------ */
@@ -612,7 +612,7 @@ static int process_ixfrin_packet(knot_pkt_t *pkt, struct answer_data *adata)
 int ixfr_query(knot_pkt_t *pkt, struct query_data *qdata)
 {
 	if (pkt == NULL || qdata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	int ret = KNOT_EOK;
@@ -644,29 +644,29 @@ int ixfr_query(knot_pkt_t *pkt, struct query_data *qdata)
 			return axfr_query_process(pkt, qdata);
 		default:            /* Server errors. */
 			IXFROUT_LOG(LOG_ERR, "failed to start (%s)", knot_strerror(ret));
-			return NS_PROC_FAIL;
+			return KNOT_NS_PROC_FAIL;
 		}
 	}
 
 	/* Reserve space for TSIG. */
-	knot_pkt_reserve(pkt, tsig_wire_maxsize(qdata->sign.tsig_key));
+	knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(qdata->sign.tsig_key));
 
 	/* Answer current packet (or continue). */
 	ret = xfr_process_list(pkt, &ixfr_process_changeset, qdata);
 	switch(ret) {
 	case KNOT_ESPACE: /* Couldn't write more, send packet and continue. */
-		return NS_PROC_FULL; /* Check for more. */
+		return KNOT_NS_PROC_FULL; /* Check for more. */
 	case KNOT_EOK:    /* Last response. */
 		gettimeofday(&now, NULL);
 		IXFROUT_LOG(LOG_INFO,
 		            "finished, %.02f seconds, %u messages, %u bytes",
 		            time_diff(&ixfr->proc.tstamp, &now) / 1000.0,
 		            ixfr->proc.npkts, ixfr->proc.nbytes);
-		ret = NS_PROC_DONE;
+		ret = KNOT_NS_PROC_DONE;
 		break;
 	default:          /* Generic error. */
 		IXFROUT_LOG(LOG_ERR, "failed (%s)", knot_strerror(ret));
-		ret = NS_PROC_FAIL;
+		ret = KNOT_NS_PROC_FAIL;
 		break;
 	}
 
@@ -676,12 +676,12 @@ int ixfr_query(knot_pkt_t *pkt, struct query_data *qdata)
 int ixfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
 {
 	if (pkt == NULL || adata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 	
 	if (adata->ext == NULL) {
 		if (!ixfr_enough_data(pkt)) {
-			return NS_PROC_FAIL;
+			return KNOT_NS_PROC_FAIL;
 		}
 	
 		/* Check for AXFR-style IXFR. */
@@ -699,15 +699,16 @@ int ixfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
 		if (lut != NULL) {
 			IXFRIN_LOG(LOG_WARNING, "server responded with %s", lut->name);
 		}
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 	
 	/* Initialize processing with first packet. */
 	if (adata->ext == NULL) {
 		NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
 		if (!zone_transfer_needed(adata->param->zone, pkt)) {
-			IXFRIN_LOG(LOG_INFO, "server has newer zone");
-			return NS_PROC_DONE;
+			IXFRIN_LOG(LOG_WARNING, "master sent older serial, "
+			                        "ignoring");
+			return KNOT_NS_PROC_DONE;
 		}
 
 		IXFRIN_LOG(LOG_INFO, "starting");
@@ -715,18 +716,18 @@ int ixfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
 		int ret = ixfrin_answer_init(adata);
 		if (ret != KNOT_EOK) {
 			IXFRIN_LOG(LOG_WARNING, "failed (%s)", knot_strerror(ret));
-			return NS_PROC_FAIL;
+			return KNOT_NS_PROC_FAIL;
 		}
 	} else {
 		NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 100);
 	}
 
 	int ret = process_ixfrin_packet(pkt, adata);
-	if (ret == NS_PROC_DONE) {
+	if (ret == KNOT_NS_PROC_DONE) {
 		NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
 		int fret = ixfrin_finalize(adata);
 		if (fret != KNOT_EOK) {
-			ret = NS_PROC_FAIL;
+			ret = KNOT_NS_PROC_FAIL;
 		}
 	}
 
diff --git a/src/knot/nameserver/notify.c b/src/knot/nameserver/notify.c
index 502b80de35d4ca03563d38962a8bc0dd21398498..85a6cf7503930e9a339786fba8b6d476fa340f0a 100644
--- a/src/knot/nameserver/notify.c
+++ b/src/knot/nameserver/notify.c
@@ -25,7 +25,6 @@
 #include "libknot/consts.h"
 #include "knot/zone/zonedb.h"
 #include "knot/zone/timers.h"
-#include "libknot/common.h"
 #include "libknot/packet/wire.h"
 #include "knot/updates/acl.h"
 #include "common-knot/evsched.h"
@@ -57,18 +56,18 @@ static int notify_check_query(struct query_data *qdata)
 	NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
 	NS_NEED_AUTH(&zone->conf->acl.notify_in, qdata);
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 int notify_process_query(knot_pkt_t *pkt, struct query_data *qdata)
 {
 	if (pkt == NULL || qdata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Validate notification query. */
 	int state = notify_check_query(qdata);
-	if (state == NS_PROC_FAIL) {
+	if (state == KNOT_NS_PROC_FAIL) {
 		switch (qdata->rcode) {
 		case KNOT_RCODE_NOTAUTH: /* Not authoritative or ACL check failed. */
 			NOTIFY_QLOG(LOG_NOTICE, "unauthorized request");
@@ -81,7 +80,7 @@ int notify_process_query(knot_pkt_t *pkt, struct query_data *qdata)
 	}
 
 	/* Reserve space for TSIG. */
-	knot_pkt_reserve(pkt, tsig_wire_maxsize(qdata->sign.tsig_key));
+	knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(qdata->sign.tsig_key));
 
 	/* SOA RR in answer may be included, recover serial. */
 	const knot_pktsection_t *answer = knot_pkt_section(qdata->query, KNOT_ANSWER);
@@ -100,12 +99,12 @@ int notify_process_query(knot_pkt_t *pkt, struct query_data *qdata)
 	/* Incoming NOTIFY expires REFRESH timer and renews EXPIRE timer. */
 	zone_t *zone = (zone_t *)qdata->zone;
 	zone_events_schedule(zone, ZONE_EVENT_REFRESH, ZONE_EVENT_NOW);
-	int ret = write_zone_timers(conf()->timers_db, zone);
+	int ret = zone_events_write_persistent(zone);
 	if (ret != KNOT_EOK) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 #undef NOTIFY_QLOG
@@ -117,7 +116,7 @@ int notify_process_query(knot_pkt_t *pkt, struct query_data *qdata)
 int notify_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
 {
 	if (pkt == NULL || adata == NULL) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Check RCODE. */
@@ -127,12 +126,12 @@ int notify_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
 		if (lut != NULL) {
 			NOTIFY_RLOG(LOG_WARNING, "server responded with %s", lut->name);
 		}
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
 
-	return NS_PROC_DONE; /* No processing. */
+	return KNOT_NS_PROC_DONE; /* No processing. */
 }
 
 #undef NOTIFY_RLOG
diff --git a/src/knot/nameserver/nsec_proofs.c b/src/knot/nameserver/nsec_proofs.c
index 1cb76edbb3bb51b4ce799d2919251d355b997cbf..e552a34a4060a39b4f12f313ae98b3c8845cc8b6 100644
--- a/src/knot/nameserver/nsec_proofs.c
+++ b/src/knot/nameserver/nsec_proofs.c
@@ -3,7 +3,6 @@
 #include "knot/nameserver/internet.h"
 #include "knot/dnssec/zone-nsec.h"
 
-#include "libknot/common.h"
 #include "common/debug.h"
 
 #define DNSSEC_ENABLED 1
@@ -64,7 +63,7 @@ static int ns_put_nsec3_from_node(const zone_node_t *node,
 		return KNOT_EOK;
 	}
 
-	int res = ns_put_rr(resp, &rrset, &rrsigs, COMPR_HINT_NONE,
+	int res = ns_put_rr(resp, &rrset, &rrsigs, KNOT_COMPR_HINT_NONE,
 	                    KNOT_PF_CHECKDUP, qdata);
 
 	/*! \note TC bit is already set, if something went wrong. */
@@ -297,7 +296,7 @@ static int ns_put_nsec_wildcard(const zone_contents_t *zone,
 	if (!knot_rrset_empty(&rrset)) {
 		knot_rrset_t rrsigs = node_rrset(previous, KNOT_RRTYPE_RRSIG);
 		// NSEC proving that there is no node with the searched name
-		ret = ns_put_rr(resp, &rrset, &rrsigs, COMPR_HINT_NONE, 0, qdata);
+		ret = ns_put_rr(resp, &rrset, &rrsigs, KNOT_COMPR_HINT_NONE, 0, qdata);
 	}
 
 	return ret;
@@ -494,7 +493,7 @@ dbg_ns_exec_verb(
 		return KNOT_EOK;
 	}
 
-	int ret = ns_put_rr(resp, &rrset, &rrsigs, COMPR_HINT_NONE, 0, qdata);
+	int ret = ns_put_rr(resp, &rrset, &rrsigs, KNOT_COMPR_HINT_NONE, 0, qdata);
 	if (ret != KNOT_EOK) {
 		dbg_ns("Failed to add NSEC for NXDOMAIN to response: %s\n",
 		       knot_strerror(ret));
@@ -542,7 +541,7 @@ dbg_ns_exec_verb(
 			// bad zone, ignore
 			return KNOT_EOK;
 		}
-		ret = ns_put_rr(resp, &rrset, &rrsigs, COMPR_HINT_NONE, 0, qdata);
+		ret = ns_put_rr(resp, &rrset, &rrsigs, KNOT_COMPR_HINT_NONE, 0, qdata);
 		if (ret != KNOT_EOK) {
 			dbg_ns("Failed to add second NSEC for NXDOMAIN to "
 			       "response: %s\n", knot_strerror(ret));
@@ -692,7 +691,7 @@ static int ns_put_nsec_nsec3_nodata(const zone_node_t *node,
 		if (!knot_rrset_empty(&rrset)) {
 			dbg_ns_detail("Putting the RRSet to Authority\n");
 			knot_rrset_t rrsigs = node_rrset(node, KNOT_RRTYPE_RRSIG);
-			ret = ns_put_rr(resp, &rrset, &rrsigs, COMPR_HINT_NONE, 0, qdata);
+			ret = ns_put_rr(resp, &rrset, &rrsigs, KNOT_COMPR_HINT_NONE, 0, qdata);
 		}
 	}
 
@@ -764,7 +763,7 @@ int nsec_prove_dp_security(knot_pkt_t *pkt, struct query_data *qdata)
 	knot_rrset_t rrset = node_rrset(qdata->node, KNOT_RRTYPE_DS);
 	if (!knot_rrset_empty(&rrset)) {
 		knot_rrset_t rrsigs = node_rrset(qdata->node, KNOT_RRTYPE_RRSIG);
-		return ns_put_rr(pkt, &rrset, &rrsigs, COMPR_HINT_NONE, 0, qdata);
+		return ns_put_rr(pkt, &rrset, &rrsigs, KNOT_COMPR_HINT_NONE, 0, qdata);
 	}
 
 	/* DS doesn't exist => NODATA proof. */
@@ -787,7 +786,7 @@ int nsec_append_rrsigs(knot_pkt_t *pkt, struct query_data *qdata, bool optional)
 	struct rrsig_info *info = NULL;
 	WALK_LIST(info, qdata->rrsigs) {
 		knot_rrset_t *rrsig = &info->synth_rrsig;
-		uint16_t compr_hint = info->rrinfo->compress_ptr[COMPR_HINT_OWNER];
+		uint16_t compr_hint = info->rrinfo->compress_ptr[KNOT_COMPR_HINT_OWNER];
 		ret = knot_pkt_put(pkt, compr_hint, rrsig, flags);
 		if (ret != KNOT_EOK) {
 			break;
diff --git a/src/knot/nameserver/process_answer.c b/src/knot/nameserver/process_answer.c
index e18916b1a180ca7a0ada5a88f3bdf663b65e6e77..e43ec34c90c7b1bb2d7f359ccfd6bc5e0e6c1f0c 100644
--- a/src/knot/nameserver/process_answer.c
+++ b/src/knot/nameserver/process_answer.c
@@ -24,13 +24,13 @@
 #define ANSWER_DATA(ctx) ((struct answer_data *)(ctx)->data)
 #define RESPONSE_TYPE_UNSET -1
 
-static void answer_data_init(knot_process_t *ctx, void *module_param)
+static void answer_data_init(knot_layer_t *ctx, void *module_param)
 {
 	/* Initialize persistent data. */
 	struct answer_data *data = ANSWER_DATA(ctx);
 	memset(data, 0, sizeof(struct answer_data));
 	data->response_type = RESPONSE_TYPE_UNSET;
-	data->mm = &ctx->mm;
+	data->mm = ctx->mm;
 	data->param = module_param;
 }
 
@@ -44,21 +44,21 @@ static bool is_answer_to_query(const knot_pkt_t *query, knot_pkt_t *answer)
 	return knot_wire_get_id(query->wire) == knot_wire_get_id(answer->wire);
 }
 
-static int process_answer_begin(knot_process_t *ctx, void *module_param)
+static int process_answer_begin(knot_layer_t *ctx, void *module_param)
 {
 	/* Initialize context. */
 	assert(ctx);
-	ctx->type = NS_PROC_ANSWER_ID;
-	ctx->data = mm_alloc(&ctx->mm, sizeof(struct answer_data));
+	ctx->type = KNOT_NS_PROC_ANSWER_ID;
+	ctx->data = mm_alloc(ctx->mm, sizeof(struct answer_data));
 
 	/* Initialize persistent data. */
 	answer_data_init(ctx, module_param);
 
-	/* Await packet. */
-	return NS_PROC_MORE;
+	/* Issue the query. */
+	return KNOT_NS_PROC_FULL;
 }
 
-static int process_answer_reset(knot_process_t *ctx)
+static int process_answer_reset(knot_layer_t *ctx)
 {
 	assert(ctx);
 	struct answer_data *data = ANSWER_DATA(ctx);
@@ -74,17 +74,17 @@ static int process_answer_reset(knot_process_t *ctx)
 	/* Initialize persistent data. */
 	answer_data_init(ctx, module_param);
 
-	/* Await packet. */
-	return NS_PROC_MORE;
+	/* Issue the query. */
+	return KNOT_NS_PROC_FULL;
 }
 
-static int process_answer_finish(knot_process_t *ctx)
+static int process_answer_finish(knot_layer_t *ctx)
 {
 	process_answer_reset(ctx);
-	mm_free(&ctx->mm, ctx->data);
+	mm_free(ctx->mm, ctx->data);
 	ctx->data = NULL;
 
-	return NS_PROC_NOOP;
+	return KNOT_NS_PROC_NOOP;
 }
 
 /* \note Private helper for process_answer repetitive checks. */
@@ -94,33 +94,33 @@ static int process_answer_finish(knot_process_t *ctx)
 		return ret; \
 	}
 
-static int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
+static int process_answer(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	assert(pkt && ctx);
 	struct answer_data *data = ANSWER_DATA(ctx);
 
 	/* Check parse state. */
-	ANSWER_REQUIRES(pkt->parsed >= KNOT_WIRE_HEADER_SIZE, NS_PROC_FAIL);
-	ANSWER_REQUIRES(pkt->parsed == pkt->size, NS_PROC_FAIL);
+	ANSWER_REQUIRES(pkt->parsed >= KNOT_WIRE_HEADER_SIZE, KNOT_NS_PROC_FAIL);
+	ANSWER_REQUIRES(pkt->parsed == pkt->size, KNOT_NS_PROC_FAIL);
 	/* Accept only responses. */
-	ANSWER_REQUIRES(knot_wire_get_qr(pkt->wire), NS_PROC_NOOP);
+	ANSWER_REQUIRES(knot_wire_get_qr(pkt->wire), KNOT_NS_PROC_NOOP);
 	/* Check if we want answer paired to query. */
 	const knot_pkt_t *query = data->param->query;
 	if (!query) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
-	ANSWER_REQUIRES(is_answer_to_query(query, pkt), NS_PROC_NOOP);
+	ANSWER_REQUIRES(is_answer_to_query(query, pkt), KNOT_NS_PROC_NOOP);
 
 	/* Verify incoming packet. */
 	int ret = tsig_verify_packet(&data->param->tsig_ctx, pkt);
 	if (ret != KNOT_EOK) {
 		ANSWER_LOG(LOG_WARNING, data, "response", "denied (%s)",
 		           knot_strerror(ret));
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* Call appropriate processing handler. */
-	int next_state = NS_PROC_NOOP;
+	int next_state = KNOT_NS_PROC_NOOP;
 	if (data->response_type == RESPONSE_TYPE_UNSET) {
 		/* @note We can't derive type from response, as it may not contain QUESTION at all. */
 		data->response_type = knot_pkt_type(query) | KNOT_RESPONSE;
@@ -139,27 +139,31 @@ static int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
 		next_state = notify_process_answer(pkt, data);
 		break;
 	default:
-		next_state = NS_PROC_NOOP;
+		next_state = KNOT_NS_PROC_NOOP;
 		break;
 	}
 
-	knot_pkt_free(&pkt);
 	return next_state;
 }
-
 #undef ANSWER_REQUIRES
 
+static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
+{
+	/* \note Don't touch the query, expect answer. */
+	return KNOT_NS_PROC_MORE;
+}
+
 /*! \brief Module implementation. */
-static const knot_process_module_t PROCESS_ANSWER_MODULE = {
+static const knot_layer_api_t PROCESS_ANSWER_MODULE = {
 	&process_answer_begin,
 	&process_answer_reset,
 	&process_answer_finish,
 	&process_answer,
-	&knot_process_noop, /* No output. */
-	&knot_process_noop  /* No error processing. */
+	&prepare_query,
+	&knot_layer_noop
 };
 
-const knot_process_module_t *process_answer_get_module(void)
+const knot_layer_api_t *process_answer_get_module(void)
 {
 	return &PROCESS_ANSWER_MODULE;
 }
diff --git a/src/knot/nameserver/process_answer.h b/src/knot/nameserver/process_answer.h
index e87ea57b5bd52bc8dc54cb417b2b083e4787e424..abcbc3aa472dff267cef6e3671d4d3b5524e4211 100644
--- a/src/knot/nameserver/process_answer.h
+++ b/src/knot/nameserver/process_answer.h
@@ -30,11 +30,11 @@
 #include "knot/nameserver/tsig_ctx.h"
 
 /* Answer processing module implementation. */
-const knot_process_module_t *process_answer_get_module(void);
-#define NS_PROC_ANSWER process_answer_get_module()
-#define NS_PROC_ANSWER_ID 2
+const knot_layer_api_t *process_answer_get_module(void);
+#define KNOT_NS_PROC_ANSWER process_answer_get_module()
+#define KNOT_NS_PROC_ANSWER_ID 2
 
-/*! \brief Answer processsing logging base. */
+/*! \brief Answer processing logging base. */
 #define ANSWER_LOG(severity, data, operation, msg...) \
 	NS_PROC_LOG(severity, (data)->param->remote, (data)->param->zone->name, \
 		    operation, msg);
diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c
index 9bf62ff410f55766faff3df009c10660ed3ca280..ce7c8147198a0fc038198b451dfac2b79fb50f83 100644
--- a/src/knot/nameserver/process_query.c
+++ b/src/knot/nameserver/process_query.c
@@ -16,17 +16,18 @@
 #include "libknot/tsig-op.h"
 #include "libknot/descriptor.h"
 #include "common/debug.h"
+#include "common/macros.h"
 
 /*! \brief Accessor to query-specific data. */
 #define QUERY_DATA(ctx) ((struct query_data *)(ctx)->data)
 
 /*! \brief Reinitialize query data structure. */
-static void query_data_init(knot_process_t *ctx, void *module_param)
+static void query_data_init(knot_layer_t *ctx, void *module_param)
 {
 	/* Initialize persistent data. */
 	struct query_data *data = QUERY_DATA(ctx);
 	memset(data, 0, sizeof(struct query_data));
-	data->mm = &ctx->mm;
+	data->mm = ctx->mm;
 	data->param = (struct process_query_param*)module_param;
 
 	/* Initialize lists. */
@@ -34,21 +35,21 @@ static void query_data_init(knot_process_t *ctx, void *module_param)
 	init_list(&data->rrsigs);
 }
 
-static int process_query_begin(knot_process_t *ctx, void *module_param)
+static int process_query_begin(knot_layer_t *ctx, void *module_param)
 {
 	/* Initialize context. */
 	assert(ctx);
 	ctx->type = NS_PROC_QUERY_ID;
-	ctx->data = mm_alloc(&ctx->mm, sizeof(struct query_data));
+	ctx->data = mm_alloc(ctx->mm, sizeof(struct query_data));
 
 	/* Initialize persistent data. */
 	query_data_init(ctx, module_param);
 
 	/* Await packet. */
-	return NS_PROC_MORE;
+	return KNOT_NS_PROC_MORE;
 }
 
-static int process_query_reset(knot_process_t *ctx)
+static int process_query_reset(knot_layer_t *ctx)
 {
 	assert(ctx);
 	struct query_data *qdata = QUERY_DATA(ctx);
@@ -57,7 +58,6 @@ static int process_query_reset(knot_process_t *ctx)
 	struct process_query_param *module_param = qdata->param;
 
 	/* Free allocated data. */
-	knot_pkt_free(&qdata->query);
 	ptrlist_free(&qdata->wildcards, qdata->mm);
 	nsec_clear_rrsigs(qdata);
 	knot_rrset_clear(&qdata->opt_rr, qdata->mm);
@@ -69,33 +69,31 @@ static int process_query_reset(knot_process_t *ctx)
 	query_data_init(ctx, module_param);
 
 	/* Await packet. */
-	return NS_PROC_MORE;
+	return KNOT_NS_PROC_MORE;
 }
 
-static int process_query_finish(knot_process_t *ctx)
+static int process_query_finish(knot_layer_t *ctx)
 {
 	process_query_reset(ctx);
-	ctx->mm.free(ctx->data);
+	mm_free(ctx->mm, ctx->data);
 	ctx->data = NULL;
 
-	return NS_PROC_NOOP;
+	return KNOT_NS_PROC_NOOP;
 }
 
-static int process_query_in(knot_pkt_t *pkt, knot_process_t *ctx)
+static int process_query_in(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	assert(pkt && ctx);
 	struct query_data *qdata = QUERY_DATA(ctx);
 
 	/* Check if at least header is parsed. */
 	if (pkt->parsed < KNOT_WIRE_HEADER_SIZE) {
-		knot_pkt_free(&pkt);
-		return NS_PROC_NOOP; /* Ignore. */
+		return KNOT_NS_PROC_NOOP; /* Ignore. */
 	}
 
 	/* Accept only queries. */
 	if (knot_wire_get_qr(pkt->wire)) {
-		knot_pkt_free(&pkt);
-		return NS_PROC_NOOP; /* Ignore. */
+		return KNOT_NS_PROC_NOOP; /* Ignore. */
 	}
 
 	/* Store for processing. */
@@ -103,16 +101,16 @@ static int process_query_in(knot_pkt_t *pkt, knot_process_t *ctx)
 	qdata->packet_type = knot_pkt_type(pkt);
 
 	/* Declare having response. */
-	return NS_PROC_FULL;
+	return KNOT_NS_PROC_FULL;
 }
 
 /*!
  * \brief Create a response for a given query in the INTERNET class.
  */
-static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx)
+static int query_internet(knot_pkt_t *pkt, knot_layer_t *ctx)
 {
 	struct query_data *data = QUERY_DATA(ctx);
-	int next_state = NS_PROC_FAIL;
+	int next_state = KNOT_NS_PROC_FAIL;
 	dbg_ns("%s(%p, %p, pkt_type=%u)\n", __func__, pkt, ctx, data->packet_type);
 
 	switch(data->packet_type) {
@@ -134,7 +132,7 @@ static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx)
 	default:
 		/* Nothing else is supported. */
 		data->rcode = KNOT_RCODE_NOTIMPL;
-		next_state = NS_PROC_FAIL;
+		next_state = KNOT_NS_PROC_FAIL;
 		break;
 	}
 
@@ -144,7 +142,7 @@ static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx)
 /*!
  * \brief Create a response for a given query in the CHAOS class.
  */
-static int query_chaos(knot_pkt_t *pkt, knot_process_t *ctx)
+static int query_chaos(knot_pkt_t *pkt, knot_layer_t *ctx)
 {
 	dbg_ns("%s(%p, %p)\n", __func__, pkt, ctx);
 	struct query_data *data = QUERY_DATA(ctx);
@@ -152,16 +150,16 @@ static int query_chaos(knot_pkt_t *pkt, knot_process_t *ctx)
 	/* Nothing except normal queries is supported. */
 	if (data->packet_type != KNOT_QUERY_NORMAL) {
 		data->rcode = KNOT_RCODE_NOTIMPL;
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	data->rcode = knot_chaos_answer(pkt);
 	if (data->rcode != KNOT_RCODE_NOERROR) {
 		dbg_ns("%s: failed with RCODE=%d\n", __func__, data->rcode);
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 /*! \brief Find zone for given question. */
@@ -267,7 +265,7 @@ static int answer_edns_put(knot_pkt_t *resp, struct query_data *qdata)
 
 	/* Write to packet. */
 	assert(resp->current == KNOT_ADDITIONAL);
-	ret = knot_pkt_put(resp, COMPR_HINT_NONE, &qdata->opt_rr, 0);
+	ret = knot_pkt_put(resp, KNOT_COMPR_HINT_NONE, &qdata->opt_rr, 0);
 	if (ret == KNOT_EOK) {
 		/* Save position of the Ext RCODE field. */
 		qdata->ext_rcode = wire_end + KNOT_EDNS_EXT_RCODE_POS;
@@ -277,7 +275,7 @@ static int answer_edns_put(knot_pkt_t *resp, struct query_data *qdata)
 }
 
 /*! \brief Initialize response, sizes and find zone from which we're going to answer. */
-static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_process_t *ctx)
+static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx)
 {
 	struct query_data *qdata = QUERY_DATA(ctx);
 	server_t *server = qdata->param->server;
@@ -355,7 +353,7 @@ static int set_rcode_to_packet(knot_pkt_t *pkt, struct query_data *qdata)
 	return ret;
 }
 
-static int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx)
+static int process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	assert(pkt && ctx);
 	struct query_data *qdata = QUERY_DATA(ctx);
@@ -388,13 +386,13 @@ static int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx)
 	/* Transaction security (if applicable). */
 	(void) process_query_sign_response(pkt, qdata);
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 /*!
  * \brief Apply rate limit.
  */
-static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_process_t *ctx)
+static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_layer_t *ctx)
 {
 	/* Check if rate limiting applies. */
 	struct query_data *qdata = QUERY_DATA(ctx);
@@ -418,8 +416,8 @@ static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_process_t *ctx)
 	/* Now it is slip or drop. */
 	if (rrl_slip_roll(conf()->rrl_slip)) {
 		/* Answer slips. */
-		if (process_query_err(pkt, ctx) != KNOT_EOK) {
-			return NS_PROC_FAIL;
+		if (process_query_err(ctx, pkt) != KNOT_EOK) {
+			return KNOT_NS_PROC_FAIL;
 		}
 		knot_wire_set_tc(pkt->wire);
 	} else {
@@ -427,10 +425,10 @@ static int ratelimit_apply(int state, knot_pkt_t *pkt, knot_process_t *ctx)
 		pkt->size = 0;
 	}
 
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
-static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
+static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	assert(pkt && ctx);
 	struct query_data *qdata = QUERY_DATA(ctx);
@@ -441,12 +439,12 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
 
 	/* Check parse state. */
 	knot_pkt_t *query = qdata->query;
-	int next_state = NS_PROC_DONE;
+	int next_state = KNOT_NS_PROC_DONE;
 	if (query->parsed < query->size) {
 		dbg_ns("%s: incompletely parsed query, FORMERR\n", __func__);
 		knot_pkt_clear(pkt);
 		qdata->rcode = KNOT_RCODE_FORMERR;
-		next_state = NS_PROC_FAIL;
+		next_state = KNOT_NS_PROC_FAIL;
 		goto finish;
 	}
 
@@ -456,7 +454,7 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
 
 	int ret = prepare_answer(query, pkt, ctx);
 	if (ret != KNOT_EOK) {
-		next_state = NS_PROC_FAIL;
+		next_state = KNOT_NS_PROC_FAIL;
 		goto finish;
 	}
 
@@ -478,7 +476,7 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
 		break;
 	default:
 		qdata->rcode = KNOT_RCODE_REFUSED;
-		next_state = NS_PROC_FAIL;
+		next_state = KNOT_NS_PROC_FAIL;
 		break;
 	}
 
@@ -487,7 +485,7 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
 	 */
 
 
-	if (next_state == NS_PROC_DONE || next_state == NS_PROC_FULL) {
+	if (next_state == KNOT_NS_PROC_DONE || next_state == KNOT_NS_PROC_FULL) {
 
 		/* Restore original QNAME. */
 		process_query_qname_case_restore(qdata, pkt);
@@ -499,26 +497,26 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
 		/* Put OPT RR to the additional section. */
 		ret = answer_edns_put(pkt, qdata);
 		if (ret != KNOT_EOK) {
-			next_state = NS_PROC_FAIL;
+			next_state = KNOT_NS_PROC_FAIL;
 			goto finish;
 		}
 
 		/* Transaction security (if applicable). */
 		if (process_query_sign_response(pkt, qdata) != KNOT_EOK) {
-			next_state = NS_PROC_FAIL;
+			next_state = KNOT_NS_PROC_FAIL;
 		}
 	}
 
 finish:
 	/* Default RCODE is SERVFAIL if not specified otherwise. */
-	if (next_state == NS_PROC_FAIL && qdata->rcode == KNOT_RCODE_NOERROR) {
+	if (next_state == KNOT_NS_PROC_FAIL && qdata->rcode == KNOT_RCODE_NOERROR) {
 		qdata->rcode = KNOT_RCODE_SERVFAIL;
 	}
 
 	/* Store Extended RCODE - divide between header and OPT if possible. */
-	if (next_state != NS_PROC_FAIL) {
+	if (next_state != KNOT_NS_PROC_FAIL) {
 		if (set_rcode_to_packet(pkt, qdata) != KNOT_EOK) {
-			next_state = NS_PROC_FAIL;
+			next_state = KNOT_NS_PROC_FAIL;
 		}
 	}
 	/* In case of NS_PROC_FAIL, RCODE is set in the error-processing function. */
@@ -554,7 +552,7 @@ bool process_query_acl_check(list_t *acl, struct query_data *qdata)
 	/* Authenticate with NOKEY if the packet isn't signed. */
 	if (query->tsig_rr) {
 		key_name = query->tsig_rr->owner;
-		key_alg = tsig_rdata_alg(query->tsig_rr);
+		key_alg = knot_tsig_rdata_alg(query->tsig_rr);
 	}
 	conf_iface_t *match = acl_find(acl, query_source, key_name);
 
@@ -583,8 +581,8 @@ int process_query_verify(struct query_data *qdata)
 
 	/* Keep digest for signing response. */
 	/*! \note This memory will be rewritten for multi-pkt answers. */
-	ctx->tsig_digest = (uint8_t *)tsig_rdata_mac(query->tsig_rr);
-	ctx->tsig_digestlen = tsig_rdata_mac_length(query->tsig_rr);
+	ctx->tsig_digest = (uint8_t *)knot_tsig_rdata_mac(query->tsig_rr);
+	ctx->tsig_digestlen = knot_tsig_rdata_mac_length(query->tsig_rr);
 
 	/* Checking query. */
 	process_query_qname_case_restore(qdata, query);
@@ -610,7 +608,7 @@ int process_query_verify(struct query_data *qdata)
 	case KNOT_TSIG_EBADTIME:
 		qdata->rcode = KNOT_RCODE_NOTAUTH;
 		qdata->rcode_tsig = KNOT_TSIG_ERR_BADTIME;
-		ctx->tsig_time_signed = tsig_rdata_time_signed(query->tsig_rr);
+		ctx->tsig_time_signed = knot_tsig_rdata_time_signed(query->tsig_rr);
 		break;
 	case KNOT_EMALF:
 		qdata->rcode = KNOT_RCODE_FORMERR;
@@ -697,7 +695,7 @@ int process_query_qname_case_lower(knot_pkt_t *pkt)
 }
 
 /*! \brief Module implementation. */
-static const knot_process_module_t PROCESS_QUERY_MODULE = {
+static const knot_layer_api_t PROCESS_QUERY_MODULE = {
 	&process_query_begin,
 	&process_query_reset,
 	&process_query_finish,
@@ -706,7 +704,7 @@ static const knot_process_module_t PROCESS_QUERY_MODULE = {
 	&process_query_err
 };
 
-const knot_process_module_t *process_query_get_module(void)
+const knot_layer_api_t *process_query_get_module(void)
 {
 	return &PROCESS_QUERY_MODULE;
 }
diff --git a/src/knot/nameserver/process_query.h b/src/knot/nameserver/process_query.h
index 5801e1814d377b80c1644c7bcf418d978141dd06..20e279cb263b69a5fff725cec5992e4b26534c34 100644
--- a/src/knot/nameserver/process_query.h
+++ b/src/knot/nameserver/process_query.h
@@ -26,12 +26,12 @@
 
 #pragma once
 
-#include "libknot/processing/process.h"
+#include "libknot/processing/layer.h"
 #include "knot/server/server.h"
 #include "knot/updates/acl.h"
 
 /* Query processing module implementation. */
-const knot_process_module_t *process_query_get_module(void);
+const knot_layer_api_t *process_query_get_module(void);
 #define NS_PROC_QUERY process_query_get_module()
 #define NS_PROC_QUERY_ID 1
 
diff --git a/src/knot/nameserver/query_module.c b/src/knot/nameserver/query_module.c
index 56f4d1d6d17d9bb941cfb949f825838849a78440..9ab3e35bfefed118d04337f7b7419fc6ad4d98b8 100644
--- a/src/knot/nameserver/query_module.c
+++ b/src/knot/nameserver/query_module.c
@@ -1,7 +1,7 @@
 #include "knot/nameserver/query_module.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 #include "libknot/errcode.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 
 /* Compiled-in module headers. */
 #include "knot/modules/synth_record.h"
diff --git a/src/knot/nameserver/query_module.h b/src/knot/nameserver/query_module.h
index e3f90a5596aaed142e4d9593f992a912f85852f7..2695ea30260e2ed491a3b285c9ccf88a1c6c6f32 100644
--- a/src/knot/nameserver/query_module.h
+++ b/src/knot/nameserver/query_module.h
@@ -40,8 +40,8 @@
 
 #pragma once
 
-#include "common-knot/lists.h"
-#include "libknot/mempattern.h"
+#include "common/lists.h"
+#include "common/mempattern.h"
 #include "libknot/consts.h"
 #include "libknot/packet/pkt.h"
 
diff --git a/src/knot/nameserver/requestor.c b/src/knot/nameserver/requestor.c
deleted file mode 100644
index 9deadeb525abcfe15d1826e7380367552ee53730..0000000000000000000000000000000000000000
--- a/src/knot/nameserver/requestor.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <assert.h>
-
-#include "knot/nameserver/requestor.h"
-#include "knot/nameserver/process_answer.h"
-#include "knot/server/net.h"
-#include "knot/server/tcp-handler.h"
-
-/*! \brief Single pending request. */
-struct request {
-	struct request_data data; /*!< Request data. */
-	int state;                /*!< Processing state. */
-	knot_process_t process;   /*!< Response processor. */
-	uint8_t *pkt_buf;         /*!< Buffers. */
-};
-
-static struct request *request_make(mm_ctx_t *mm)
-{
-	struct request *request = mm_alloc(mm, sizeof(struct request));
-	if (request == NULL) {
-		return NULL;
-	}
-
-	memset(request, 0, sizeof(struct request));
-
-	request->pkt_buf = mm_alloc(mm, KNOT_WIRE_MAX_PKTSIZE);
-	if (request->pkt_buf == NULL) {
-		mm_free(mm, request);
-		request = NULL;
-	}
-
-	return request;
-}
-
-static int request_close(mm_ctx_t *mm, struct request *request)
-{
-	/* Reset processing if didn't complete. */
-	if (request->state != NS_PROC_DONE) {
-		knot_process_reset(&request->process);
-	}
-
-	knot_process_finish(&request->process);
-
-	rem_node(&request->data.node);
-	close(request->data.fd);
-	knot_pkt_free(&request->data.query);
-	mm_free(mm, request->pkt_buf);
-	mm_free(mm, request);
-
-	return KNOT_EOK;
-}
-
-/*! \brief Wait for socket readiness. */
-static int request_wait(int fd, int state, struct timeval *timeout)
-{
-	fd_set set;
-	FD_ZERO(&set);
-	FD_SET(fd, &set);
-
-	switch(state) {
-	case NS_PROC_FULL: /* Wait for writeability. */
-		return select(fd + 1, NULL, &set, NULL, timeout);
-	case NS_PROC_MORE: /* Wait for data. */
-		return select(fd + 1, &set, NULL, NULL, timeout);
-	default:
-		return -1;
-	}
-}
-
-static int request_send(struct request *request, const struct timeval *timeout)
-{
-	/* Each request has unique timeout. */
-	struct timeval tv = { timeout->tv_sec, timeout->tv_usec };
-
-	/* Wait for writeability or error. */
-	int ret = request_wait(request->data.fd, NS_PROC_FULL, &tv);
-	if (ret == 0) {
-		return KNOT_ETIMEOUT;
-	}
-
-	/* Check socket error. */
-	int err = 0;
-	socklen_t len = sizeof(int);
-	getsockopt(request->data.fd, SOL_SOCKET, SO_ERROR, &err, &len);
-	if (err != 0) {
-		return KNOT_ECONNREFUSED;
-	}
-
-	/* Send query. */
-	knot_pkt_t *query = request->data.query;
-	ret = tcp_send_msg(request->data.fd, query->wire, query->size);
-	if (ret != query->size) {
-		return KNOT_ECONN;
-	}
-
-	return KNOT_EOK;
-}
-
-static int request_recv(struct request *request, const struct timeval *timeout)
-{
-	/* Each request has unique timeout. */
-	struct timeval tv = { timeout->tv_sec, timeout->tv_usec };
-
-	/* Receive it */
-	int ret = tcp_recv_msg(request->data.fd, request->pkt_buf,
-	                       KNOT_WIRE_MAX_PKTSIZE, &tv);
-	if (ret < 0) {
-		return ret;
-	}
-
-	return ret;
-}
-
-void requestor_init(struct requestor *requestor, const knot_process_module_t *module,
-                    mm_ctx_t *mm)
-{
-	memset(requestor, 0, sizeof(struct requestor));
-	requestor->module = module;
-	requestor->mm = mm;
-	init_list(&requestor->pending);
-}
-
-void requestor_clear(struct requestor *requestor)
-{
-	while (requestor_dequeue(requestor) == KNOT_EOK)
-		;
-}
-
-bool requestor_finished(struct requestor *requestor)
-{
-	return requestor == NULL || EMPTY_LIST(requestor->pending);
-}
-
-struct request *requestor_make(struct requestor *requestor,
-                               const conf_iface_t *remote,
-                               knot_pkt_t *query)
-{
-	if (requestor == NULL || query == NULL || remote == NULL) {
-		return NULL;
-	}
-
-	/* Form a pending request. */
-	struct request *request = request_make(requestor->mm);
-	if (request == NULL) {
-		return NULL;
-	}
-
-	memcpy(&request->data.origin, &remote->via, sizeof(remote->via));
-	memcpy(&request->data.remote, &remote->addr, sizeof(remote->addr));
-
-	request->state = NS_PROC_DONE;
-	request->data.fd = -1;
-	request->data.query = query;
-	return request;
-}
-
-int requestor_enqueue(struct requestor *requestor, struct request *request, void *param)
-{
-	if (requestor == NULL || request == NULL) {
-		return KNOT_EINVAL;
-	}
-
-	/* Fetch a bound socket. */
-	int fd = net_connected_socket(SOCK_STREAM, &request->data.remote,
-	                              &request->data.origin, O_NONBLOCK);
-	if (fd < 0) {
-		return KNOT_ECONN;
-	}
-
-	/* Form a pending request. */
-	request->data.fd = fd;
-	request->state = NS_PROC_FULL; /* We have a query to be sent. */
-	if (requestor->mm != NULL) {
-		memcpy(&request->process.mm, requestor->mm, sizeof(mm_ctx_t));
-	} else {
-		mm_ctx_init(&request->process.mm);
-	}
-
-	knot_process_begin(&request->process, param, requestor->module);
-
-	add_tail(&requestor->pending, &request->data.node);
-
-	return KNOT_EOK;
-}
-
-int requestor_dequeue(struct requestor *requestor)
-{
-	if (requestor_finished(requestor)) {
-		return KNOT_ENOENT;
-	}
-
-	struct request *last = HEAD(requestor->pending);
-	return request_close(requestor->mm, last);
-}
-
-static int exec_request(struct request *last, struct timeval *timeout)
-{
-	int ret = KNOT_EOK;
-
-	/* Process any pending data. */
-	if (last->state == NS_PROC_FULL) {
-		ret = request_send(last, timeout);
-		if (ret != KNOT_EOK) {
-			return ret;
-		}
-		last->state = NS_PROC_MORE; /* Await response. */
-	}
-
-	/* Receive and process expected answers. */
-	while (last->state == NS_PROC_MORE) {
-		int rcvd = request_recv(last, timeout);
-		if (rcvd < 0) {
-			return rcvd;
-		}
-
-		last->state = knot_process_in(last->pkt_buf, rcvd, &last->process);
-	}
-
-	/* Expect complete request. */
-	if (last->state != NS_PROC_DONE) {
-		return KNOT_ERROR;
-	}
-
-	return KNOT_EOK;
-}
-
-int requestor_exec(struct requestor *requestor, struct timeval *timeout)
-{
-	if (requestor_finished(requestor)) {
-		return KNOT_ENOENT;
-	}
-
-	/* Execute next request. */
-	int ret = exec_request(HEAD(requestor->pending), timeout);
-
-	/* Remove it from processing. */
-	requestor_dequeue(requestor);
-
-	return ret;
-}
diff --git a/src/knot/nameserver/tsig_ctx.c b/src/knot/nameserver/tsig_ctx.c
index b8c25879edcb96b8329c215ad3ace3e581489b4f..de85df4a6bff65ce3f9d4103cd8da054b03ec3b1 100644
--- a/src/knot/nameserver/tsig_ctx.c
+++ b/src/knot/nameserver/tsig_ctx.c
@@ -83,12 +83,12 @@ static int update_ctx_after_verify(tsig_ctx_t *ctx, knot_rrset_t *tsig_rr)
 	assert(ctx);
 	assert(tsig_rr);
 
-	if (ctx->digest_size != tsig_rdata_mac_length(tsig_rr)) {
+	if (ctx->digest_size != knot_tsig_rdata_mac_length(tsig_rr)) {
 		return KNOT_EMALF;
 	}
 
-	memcpy(ctx->digest, tsig_rdata_mac(tsig_rr), ctx->digest_size);
-	ctx->prev_signed_time = tsig_rdata_time_signed(tsig_rr);
+	memcpy(ctx->digest, knot_tsig_rdata_mac(tsig_rr), ctx->digest_size);
+	ctx->prev_signed_time = knot_tsig_rdata_time_signed(tsig_rr);
 	ctx->unsigned_count = 0;
 	ctx->buffer_used = 0;
 
diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c
index 44f8acec7ea5aad74c8b71177b3c974f5ef99fde..abfc397c35cd3d43fc0a0cc54266ce38f62a2650 100644
--- a/src/knot/nameserver/update.c
+++ b/src/knot/nameserver/update.c
@@ -20,6 +20,7 @@
 #include "knot/updates/apply.h"
 #include "knot/dnssec/zone-sign.h"
 #include "common/debug.h"
+#include "common/macros.h"
 #include "knot/dnssec/zone-events.h"
 #include "knot/updates/ddns.h"
 #include "knot/updates/zone-update.h"
@@ -29,9 +30,9 @@
 #include "knot/zone/events/events.h"
 #include "knot/server/tcp-handler.h"
 #include "knot/server/udp-handler.h"
-#include "knot/nameserver/requestor.h"
 #include "knot/nameserver/capture.h"
 #include "libknot/dnssec/random.h"
+#include "libknot/processing/requestor.h"
 
 /* UPDATE-specific logging (internal, expects 'qdata' variable set). */
 #define UPDATE_LOG(severity, msg...) \
@@ -39,7 +40,7 @@
 
 static void init_qdata_from_request(struct query_data *qdata,
                                     const zone_t *zone,
-                                    struct request_data *req,
+                                    struct knot_request *req,
                                     struct process_query_param *param)
 {
 	memset(qdata, 0, sizeof(*qdata));
@@ -111,7 +112,7 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents,
 	return KNOT_EOK;
 }
 
-static int check_prereqs(struct request_data *request,
+static int check_prereqs(struct knot_request *request,
                          const zone_t *zone, zone_update_t *update,
                          struct query_data *qdata)
 {
@@ -128,7 +129,7 @@ static int check_prereqs(struct request_data *request,
 	return KNOT_EOK;
 }
 
-static int process_single_update(struct request_data *request,
+static int process_single_update(struct knot_request *request,
                                  const zone_t *zone, zone_update_t *update,
                                  struct query_data *qdata)
 {
@@ -147,7 +148,7 @@ static int process_single_update(struct request_data *request,
 
 static void set_rcodes(list_t *requests, const uint16_t rcode)
 {
-	struct request_data *req;
+	struct knot_request *req;
 	WALK_LIST(req, *requests) {
 		if (knot_wire_get_rcode(req->resp->wire) == KNOT_RCODE_NOERROR) {
 			knot_wire_set_rcode(req->resp->wire, rcode);
@@ -167,7 +168,7 @@ static int process_bulk(zone_t *zone, list_t *requests, changeset_t *ddns_ch)
 	zone_update_init(&zone_update, zone->contents, ddns_ch);
 
 	// Walk all the requests and process.
-	struct request_data *req;
+	struct knot_request *req;
 	WALK_LIST(req, *requests) {
 		// Init qdata structure for logging (unique per-request).
 		struct process_query_param param = { 0 };
@@ -328,11 +329,11 @@ static int process_requests(zone_t *zone, list_t *requests)
 	return KNOT_EOK;
 }
 
-static int forward_request(zone_t *zone, struct request_data *request)
+static int forward_request(zone_t *zone, struct knot_request *request)
 {
 	/* Create requestor instance. */
-	struct requestor re;
-	requestor_init(&re, NS_PROC_CAPTURE, NULL);
+	struct knot_requestor re;
+	knot_requestor_init(&re, NULL);
 
 	/* Fetch primary master. */
 	const conf_iface_t *master = zone_master(zone);
@@ -349,22 +350,27 @@ static int forward_request(zone_t *zone, struct request_data *request)
 	knot_tsig_append(query->wire, &query->size, query->max_size, query->tsig_rr);
 
 	/* Create a request. */
-	struct request *req = requestor_make(&re, master, query);
+	const struct sockaddr *dst = (const struct sockaddr *)&master->addr;
+	const struct sockaddr *src = (const struct sockaddr *)&master->via;
+	struct knot_request *req = knot_request_make(re.mm, dst, src, query, 0);
 	if (req == NULL) {
 		knot_pkt_free(&query);
 		return KNOT_ENOMEM;
 	}
 
-	/* Enqueue and execute request. */
-	struct process_capture_param param;
+	/* Prepare packet capture layer. */
+	struct capture_param param;
 	param.sink = request->resp;
-	ret = requestor_enqueue(&re, req, &param);
+	knot_requestor_overlay(&re, LAYER_CAPTURE, &param);
+
+	/* Enqueue and execute request. */
+	ret = knot_requestor_enqueue(&re, req);
 	if (ret == KNOT_EOK) {
 		struct timeval tv = { conf()->max_conn_reply, 0 };
-		ret = requestor_exec(&re, &tv);
+		ret = knot_requestor_exec(&re, &tv);
 	}
 
-	requestor_clear(&re);
+	knot_requestor_clear(&re);
 
 	/* Restore message ID and TSIG. */
 	knot_wire_set_id(request->resp->wire, knot_wire_get_id(request->query->wire));
@@ -385,13 +391,13 @@ static int forward_request(zone_t *zone, struct request_data *request)
 
 static void forward_requests(zone_t *zone, list_t *requests)
 {
-	struct request_data *req;
+	struct knot_request *req;
 	WALK_LIST(req, *requests) {
 		forward_request(zone, req);
 	}
 }
 
-static bool update_tsig_check(struct query_data *qdata, struct request_data *req)
+static bool update_tsig_check(struct query_data *qdata, struct knot_request *req)
 {
 	// Check that ACL is still valid.
 	if (!process_query_acl_check(&qdata->zone->conf->acl.update_in, qdata)) {
@@ -417,15 +423,7 @@ static bool update_tsig_check(struct query_data *qdata, struct request_data *req
 
 #undef UPDATE_LOG
 
-static void free_request(struct request_data *req)
-{
-	close(req->fd);
-	knot_pkt_free(&req->query);
-	knot_pkt_free(&req->resp);
-	free(req);
-}
-
-static void send_update_response(const zone_t *zone, struct request_data *req)
+static void send_update_response(const zone_t *zone, struct knot_request *req)
 {
 	if (req->resp) {
 		if (!zone_master(zone)) {
@@ -447,11 +445,11 @@ static void send_update_response(const zone_t *zone, struct request_data *req)
 
 static void send_update_responses(const zone_t *zone, list_t *updates)
 {
-	struct request_data *req;
+	struct knot_request *req;
 	node_t *nxt = NULL;
 	WALK_LIST_DELSAFE(req, nxt, *updates) {
 		send_update_response(zone, req);
-		free_request(req);
+		knot_request_free(NULL, req);
 	}
 	init_list(updates);
 }
@@ -459,7 +457,7 @@ static void send_update_responses(const zone_t *zone, list_t *updates)
 static int init_update_responses(const zone_t *zone, list_t *updates,
                                  size_t *update_count)
 {
-	struct request_data *req = NULL;
+	struct knot_request *req = NULL;
 	node_t *nxt = NULL;
 	WALK_LIST_DELSAFE(req, nxt, *updates) {
 		req->resp = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL);
@@ -483,8 +481,7 @@ static int init_update_responses(const zone_t *zone, list_t *updates,
 			// ACL/TSIG check failed, send response.
 			send_update_response(zone, req);
 			// Remove this request from processing list.
-			rem_node(&req->node);
-			free_request(req);
+			knot_request_free(NULL, req);
 			*update_count -= 1;
 		}
 	}
@@ -511,12 +508,12 @@ int update_query_process(knot_pkt_t *pkt, struct query_data *qdata)
 	/* Store update into DDNS queue. */
 	int ret = zone_update_enqueue(zone, qdata->query, qdata->param);
 	if (ret != KNOT_EOK) {
-		return NS_PROC_FAIL;
+		return KNOT_NS_PROC_FAIL;
 	}
 
 	/* No immediate response. */
 	pkt->size = 0;
-	return NS_PROC_DONE;
+	return KNOT_NS_PROC_DONE;
 }
 
 int updates_execute(zone_t *zone)
diff --git a/src/knot/nameserver/update.h b/src/knot/nameserver/update.h
index 674184864f5a26966c2153f5a4250b95a42a30ca..1ff7b1d124491447e7e7948daaa9abc4d3649cca 100644
--- a/src/knot/nameserver/update.h
+++ b/src/knot/nameserver/update.h
@@ -36,7 +36,7 @@ struct zone;
 /*!
  * \brief UPDATE query processing module.
  *
- * \return NS_PROC_* processing states
+ * \return KNOT_NS_PROC_* processing states
  */
 int update_query_process(knot_pkt_t *pkt, struct query_data *qdata);
 
diff --git a/src/knot/other/debug.h b/src/knot/other/debug.h
index 83dfd75ec33dcb081a2c802d017c5b7fbed6cc94..3bf7157dfb637a0e1cee1bc2c0ccca7f9f4e0d9b 100644
--- a/src/knot/other/debug.h
+++ b/src/knot/other/debug.h
@@ -39,7 +39,7 @@
 #endif
 
 #include "common/log.h"
-#include "common-knot/print.h"
+#include "common/print.h"
 
 /******************************************************************************/
 
diff --git a/src/knot/server/journal.c b/src/knot/server/journal.c
index e12aefaea85d8e83a60afd92ee1899a31170a1bb..648267b951dd52173dc460a06c0c7cbe233e53e5 100644
--- a/src/knot/server/journal.c
+++ b/src/knot/server/journal.c
@@ -25,7 +25,6 @@
 #include <assert.h>
 
 #include "common-knot/crc.h"
-#include "libknot/common.h"
 #include "knot/other/debug.h"
 #include "knot/server/journal.h"
 #include "knot/server/serialization.h"
diff --git a/src/knot/server/rrl.c b/src/knot/server/rrl.c
index 0a77ab867715ea347982c91d916f0eaa46813d4b..cecf7fd363404729f0a5900d3684aae5dbf7d892 100644
--- a/src/knot/server/rrl.c
+++ b/src/knot/server/rrl.c
@@ -24,7 +24,7 @@
 #include "knot/knot.h"
 #include "libknot/consts.h"
 #include "libknot/packet/wire.h"
-#include "common-knot/hattrie/murmurhash3.h"
+#include "common/trie/murmurhash3.h"
 #include "libknot/dnssec/random.h"
 #include "libknot/descriptor.h"
 #include "common/errors.h"
diff --git a/src/knot/server/rrl.h b/src/knot/server/rrl.h
index f27fe0ff8e8060f8f1fdc87c7ad8a4f5741bf0f2..44df7fa7c9235a825b5b82675114d9b8db16f154 100644
--- a/src/knot/server/rrl.h
+++ b/src/knot/server/rrl.h
@@ -28,7 +28,7 @@
 
 #include <stdint.h>
 #include <pthread.h>
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
 #include "libknot/packet/pkt.h"
 
 /* Defaults */
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index 3365ff11b03061337c5fc18ba1e86bf8452fe0a8..f73727d0edf575bc2075ea70087f210074438b5b 100644
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -28,6 +28,7 @@
 #include "knot/server/tcp-handler.h"
 #include "knot/conf/conf.h"
 #include "knot/worker/pool.h"
+#include "knot/zone/timers.h"
 #include "knot/zone/zonedb-load.h"
 #include "libknot/dname.h"
 #include "libknot/dnssec/crypto.h"
@@ -114,6 +115,7 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
 	/* Create bound UDP socket. */
 	int sock = net_bound_socket(SOCK_DGRAM, &cfg_if->addr);
 	if (sock < 0) {
+		log_error("cannot bind address '%s' (%s)", addr_str, knot_strerror(sock));
 		return sock;
 	}
 
@@ -329,6 +331,9 @@ void server_deinit(server_t *server)
 	/* Free remaining events. */
 	evsched_deinit(&server->sched);
 
+	/* Close persistent timers database. */
+	close_timers_db(server->timers_db);
+
 	/* Clear the structure. */
 	memset(server, 0, sizeof(server_t));
 }
@@ -578,7 +583,19 @@ int server_reconfigure(const struct conf_t *conf, void *data)
 	return ret;
 }
 
-int server_update_zones(const struct conf_t *conf, void *data)
+static void reopen_timers_database(const conf_t *conf, server_t *server)
+{
+	close_timers_db(server->timers_db);
+	server->timers_db = NULL;
+
+	int ret = open_timers_db(conf->storage, &server->timers_db);
+	if (ret != KNOT_EOK && ret != KNOT_ENOTSUP) {
+		log_warning("cannot open persistent timers DB (%s)",
+		            knot_strerror(ret));
+	}
+}
+
+int server_update_zones(const conf_t *conf, void *data)
 {
 	server_t *server = (server_t *)data;
 
@@ -593,6 +610,7 @@ int server_update_zones(const struct conf_t *conf, void *data)
 	worker_pool_wait(server->workers);
 
 	/* Reload zone database and free old zones. */
+	reopen_timers_database(conf, server);
 	int ret = zonedb_reload(conf, server);
 
 	/* Trim extra heap. */
diff --git a/src/knot/server/server.h b/src/knot/server/server.h
index 342666fc491840d836d7a32b78a944c7be819dba..3a3516fc01cad55c381196df533441534247b8b8 100644
--- a/src/knot/server/server.h
+++ b/src/knot/server/server.h
@@ -30,10 +30,11 @@
 #pragma once
 
 #include "common-knot/evsched.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
 #include "common-knot/fdset.h"
+#include "common/net.h"
+#include "common/namedb/namedb.h"
 #include "knot/server/dthreads.h"
-#include "knot/server/net.h"
 #include "knot/server/rrl.h"
 #include "knot/worker/pool.h"
 #include "knot/zone/zonedb.h"
@@ -93,7 +94,9 @@ typedef struct server_t {
 	/*! \brief Server state tracking. */
 	volatile unsigned state;
 
-	knot_zonedb_t *zone_db; /*!< Zone database. */
+	/*! \brief Zone database. */
+	knot_zonedb_t *zone_db;
+	knot_namedb_t *timers_db;
 
 	/*! \brief I/O handlers. */
 	unsigned tu_size;
diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index e0b23e9f3712e85883d098e923ca90e7a5346abf..d3c1ff8e4e0adbe94de57b4a000746cf124ac6a3 100644
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -31,19 +31,24 @@
 #include <cap-ng.h>
 #endif /* HAVE_CAP_NG_H */
 
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
 #include "common-knot/fdset.h"
+#include "common/macros.h"
 #include "common/mempool.h"
-#include "knot/knot.h"
-#include "knot/server/tcp-handler.h"
+#include "common/net.h"
+
 #include "libknot/packet/wire.h"
-#include "knot/nameserver/process_query.h"
 #include "libknot/dnssec/crypto.h"
 #include "libknot/dnssec/random.h"
+#include "libknot/processing/overlay.h"
+
+#include "knot/knot.h"
+#include "knot/server/tcp-handler.h"
+#include "knot/nameserver/process_query.h"
 
 /*! \brief TCP context data. */
 typedef struct tcp_context {
-	knot_process_t query_ctx;   /*!< Query processing context. */
+	struct knot_overlay overlay;/*!< Query processing overlay. */
 	server_t *server;           /*!< Name server structure. */
 	struct iovec iov[2];        /*!< TX/RX buffers. */
 	unsigned client_threshold;  /*!< Index of first TCP client. */
@@ -132,21 +137,26 @@ static int tcp_handle(tcp_context_t *tcp, int fd,
 		rx->iov_len = ret;
 	}
 
-	/* Create query processing context. */
-	knot_process_begin(&tcp->query_ctx, &param, NS_PROC_QUERY);
+	/* Create packets. */
+	mm_ctx_t *mm = tcp->overlay.mm;
+	knot_pkt_t *ans = knot_pkt_new(tx->iov_base, tx->iov_len, mm);
+	knot_pkt_t *query = knot_pkt_new(rx->iov_base, rx->iov_len, mm);
+
+	/* Initialize processing overlay. */
+	knot_overlay_init(&tcp->overlay, mm);
+	knot_overlay_add(&tcp->overlay, NS_PROC_QUERY, &param);
 
 	/* Input packet. */
-	int state = knot_process_in(rx->iov_base, rx->iov_len, &tcp->query_ctx);
+	int state = knot_overlay_in(&tcp->overlay, query);
 
 	/* Resolve until NOOP or finished. */
 	ret = KNOT_EOK;
-	while (state & (NS_PROC_FULL|NS_PROC_FAIL)) {
-		uint16_t tx_len = tx->iov_len;
-		state = knot_process_out(tx->iov_base, &tx_len, &tcp->query_ctx);
+	while (state & (KNOT_NS_PROC_FULL|KNOT_NS_PROC_FAIL)) {
+		state = knot_overlay_out(&tcp->overlay, ans);
 
-		/* If it has response, send it. */
-		if (tx_len > 0) {
-			if (tcp_send_msg(fd, tx->iov_base, tx_len) != tx_len) {
+		/* Send, if response generation passed and wasn't ignored. */
+		if (ans->size > 0 && !(state & (KNOT_NS_PROC_FAIL|KNOT_NS_PROC_NOOP))) {
+			if (tcp_send_msg(fd, ans->wire, ans->size) != ans->size) {
 				ret = KNOT_ECONNREFUSED;
 				break;
 			}
@@ -154,7 +164,12 @@ static int tcp_handle(tcp_context_t *tcp, int fd,
 	}
 
 	/* Reset after processing. */
-	knot_process_finish(&tcp->query_ctx);
+	knot_overlay_finish(&tcp->overlay);
+	knot_overlay_deinit(&tcp->overlay);
+
+	/* Cleanup. */
+	knot_pkt_free(&query);
+	knot_pkt_free(&ans);
 
 	return ret;
 }
@@ -198,106 +213,6 @@ int tcp_accept(int fd)
 	return incoming;
 }
 
-
-/*! \brief Wait for data and return true if data arrived. */
-static int tcp_wait_for_data(int fd, struct timeval *timeout)
-{
-	fd_set set;
-	FD_ZERO(&set);
-	FD_SET(fd, &set);
-	return select(fd + 1, &set, NULL, NULL, timeout);
-}
-
-int tcp_recv_data(int fd, uint8_t *buf, int len, struct timeval *timeout)
-{
-	int ret = 0;
-	int rcvd = 0;
-	int flags = 0;
-
-#ifdef MSG_NOSIGNAL
-	flags |= MSG_NOSIGNAL;
-#endif
-
-	while (rcvd < len) {
-		/* Receive data. */
-		ret = recv(fd, buf + rcvd, len - rcvd, flags);
-		if (ret > 0) {
-			rcvd += ret;
-			continue;
-		}
-		/* Check for disconnected socket. */
-		if (ret == 0) {
-			return KNOT_ECONNREFUSED;
-		}
-
-		/* Check for no data available. */
-		if (errno == EAGAIN || errno == EINTR) {
-			/* Continue only if timeout didn't expire. */
-			ret = tcp_wait_for_data(fd, timeout);
-			if (ret) {
-				continue;
-			} else {
-				return KNOT_ETIMEOUT;
-			}
-		} else {
-			return KNOT_ECONN;
-		}
-	}
-
-	return rcvd;
-}
-
-int tcp_send_msg(int fd, const uint8_t *msg, size_t msglen)
-{
-	/* Create iovec for gathered write. */
-	struct iovec iov[2];
-	uint16_t pktsize = htons(msglen);
-	iov[0].iov_base = &pktsize;
-	iov[0].iov_len = sizeof(uint16_t);
-	iov[1].iov_base = (void *)msg;
-	iov[1].iov_len = msglen;
-
-	/* Send. */
-	int total_len = iov[0].iov_len + iov[1].iov_len;
-	int sent = writev(fd, iov, 2);
-	if (sent != total_len) {
-		return KNOT_ECONN;
-	}
-
-	return msglen; /* Do not count the size prefix. */
-}
-
-int tcp_recv_msg(int fd, uint8_t *buf, size_t len, struct timeval *timeout)
-{
-	if (buf == NULL || fd < 0) {
-		return KNOT_EINVAL;
-	}
-
-	/* Receive size. */
-	unsigned short pktsize = 0;
-	int ret = tcp_recv_data(fd, (uint8_t *)&pktsize, sizeof(pktsize), timeout);
-	if (ret != sizeof(pktsize)) {
-		return ret;
-	}
-
-	pktsize = ntohs(pktsize);
-	dbg_net("tcp: incoming packet size=%hu on fd=%d\n", pktsize, fd);
-
-	// Check packet size
-	if (len < pktsize) {
-		return KNOT_ENOMEM;
-	}
-
-	/* Receive payload. */
-	ret = tcp_recv_data(fd, buf, pktsize, timeout);
-	if (ret != pktsize) {
-		return ret;
-	}
-
-	dbg_net("tcp: received packet size=%d on fd=%d\n", ret, fd);
-	return ret;
-}
-
 static int tcp_event_accept(tcp_context_t *tcp, unsigned i)
 {
 	/* Accept client. */
@@ -326,7 +241,7 @@ static int tcp_event_serve(tcp_context_t *tcp, unsigned i)
 	int ret = tcp_handle(tcp, fd, &tcp->iov[0], &tcp->iov[1]);
 
 	/* Flush per-query memory. */
-	mp_flush(tcp->query_ctx.mm.ctx);
+	mp_flush(tcp->overlay.mm->ctx);
 
 	if (ret == KNOT_EOK) {
 		/* Update socket activity timer. */
@@ -400,12 +315,14 @@ int tcp_master(dthread_t *thread)
 	tcp_context_t tcp;
 	memset(&tcp, 0, sizeof(tcp_context_t));
 
+	/* Create big enough memory cushion. */
+	mm_ctx_t mm;
+	mm_ctx_mempool(&mm, 4 * sizeof(knot_pkt_t));
+
 	/* Create TCP answering context. */
 	tcp.server = handler->server;
 	tcp.thread_id = handler->thread_id[dt_get_id(thread)];
-
-	/* Create big enough memory cushion. */
-	mm_ctx_mempool(&tcp.query_ctx.mm, 4 * sizeof(knot_pkt_t));
+	tcp.overlay.mm = &mm;
 
 	/* Prepare structures for bound sockets. */
 	fdset_init(&tcp.set, list_size(&conf()->ifaces) + CONFIG_XFERS);
@@ -428,7 +345,7 @@ int tcp_master(dthread_t *thread)
 	for(;;) {
 
 		/* Check handler state. */
-		if (knot_unlikely(*iostate & ServerReload)) {
+		if (unlikely(*iostate & ServerReload)) {
 			*iostate &= ~ServerReload;
 
 			/* Cancel client connections. */
@@ -464,7 +381,7 @@ int tcp_master(dthread_t *thread)
 finish:
 	free(tcp.iov[0].iov_base);
 	free(tcp.iov[1].iov_base);
-	mp_delete(tcp.query_ctx.mm.ctx);
+	mp_delete(mm.ctx);
 	fdset_clear(&tcp.set);
 	ref_release(ref);
 
diff --git a/src/knot/server/tcp-handler.h b/src/knot/server/tcp-handler.h
index 16a87d4b20d0ab3372c67abddae6d2f78785564b..e1d60c605a065b38d475428ea53376451d39c1f0 100644
--- a/src/knot/server/tcp-handler.h
+++ b/src/knot/server/tcp-handler.h
@@ -30,10 +30,6 @@
 
 #pragma once
 
-#include <stdint.h>
-
-#include "knot/server/net.h"
-#include "knot/server/server.h"
 #include "knot/server/dthreads.h"
 
 /* Constants */
@@ -48,44 +44,6 @@
  */
 int tcp_accept(int fd);
 
-/*!
- * \brief Receive a block of data from TCP socket with wait.
- *
- * \param fd  File descriptor.
- * \param buf Data buffer.
- * \param len Block length.
- * \param timeout Timeout for the operation, NULL for infinite.
- *
- * \return number of bytes received or an error
- */
-int tcp_recv_data(int fd, uint8_t *buf, int len, struct timeval *timeout);
-
-/*!
- * \brief Send a TCP message.
- *
- * \param fd Associated socket.
- * \param msg Buffer for a query wireformat.
- * \param msglen Buffer maximum size.
- *
- * \retval Number of sent data on success.
- * \retval KNOT_ERROR on error.
- */
-int tcp_send_msg(int fd, const uint8_t *msg, size_t msglen);
-
-/*!
- * \brief Receive a TCP message.
- *
- * \param fd Associated socket.
- * \param buf Buffer for incoming bytestream.
- * \param len Buffer maximum size.
- * \param timeout Message receive timeout.
- *
- * \retval Number of read bytes on success.
- * \retval KNOT_ERROR on error.
- * \retval KNOT_ENOMEM on potential buffer overflow.
- */
-int tcp_recv_msg(int fd, uint8_t *buf, size_t len, struct timeval *timeout);
-
 /*!
  * \brief TCP handler thread runnable.
  *
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index 9f1da742f29f047f316b2ba62a8f28b545e2043b..c43713928fdc80e3fd7a1a01a0ec471761c1baaa 100644
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -36,8 +36,9 @@
 #include <cap-ng.h>
 #endif /* HAVE_CAP_NG_H */
 
-#include "common-knot/sockaddr.h"
-#include "libknot/mempattern.h"
+#include "common/sockaddr.h"
+#include "common/macros.h"
+#include "common/mempattern.h"
 #include "common/mempool.h"
 #include "knot/knot.h"
 #include "knot/server/udp-handler.h"
@@ -46,7 +47,7 @@
 #include "libknot/consts.h"
 #include "libknot/packet/pkt.h"
 #include "libknot/dnssec/crypto.h"
-#include "libknot/processing/process.h"
+#include "libknot/processing/overlay.h"
 
 /* Buffer identifiers. */
 enum {
@@ -57,9 +58,9 @@ enum {
 
 /*! \brief UDP context data. */
 typedef struct udp_context {
-	knot_process_t query_ctx; /*!< Query processing context. */
-	server_t *server;         /*!< Name server structure. */
-	unsigned thread_id;       /*!< Thread identifier. */
+	struct knot_overlay overlay; /*!< Query processing overlay. */
+	server_t *server;            /*!< Name server structure. */
+	unsigned thread_id;          /*!< Thread identifier. */
 } udp_context_t;
 
 /* FD_COPY macro compat. */
@@ -128,37 +129,41 @@ void udp_handle(udp_context_t *udp, int fd, struct sockaddr_storage *ss,
 	param.thread_id = udp->thread_id;
 
 	/* Rate limit is applied? */
-	if (knot_unlikely(udp->server->rrl != NULL) && udp->server->rrl->rate > 0) {
+	if (unlikely(udp->server->rrl != NULL) && udp->server->rrl->rate > 0) {
 		param.proc_flags |= NS_QUERY_LIMIT_RATE;
 	}
 
+	/* Create packets. */
+	mm_ctx_t *mm = udp->overlay.mm;
+	knot_pkt_t *query = knot_pkt_new(rx->iov_base, rx->iov_len, mm);
+	knot_pkt_t *ans = knot_pkt_new(tx->iov_base, tx->iov_len, mm);
+
 	/* Create query processing context. */
-	knot_process_begin(&udp->query_ctx, &param, NS_PROC_QUERY);
+	knot_overlay_init(&udp->overlay, mm);
+	knot_overlay_add(&udp->overlay, NS_PROC_QUERY, &param);
 
 	/* Input packet. */
-	int state = knot_process_in(rx->iov_base, rx->iov_len, &udp->query_ctx);
+	int state = knot_overlay_in(&udp->overlay, query);
 
 	/* Process answer. */
-	uint16_t tx_len = tx->iov_len;
-	if (state == NS_PROC_FULL) {
-		state = knot_process_out(tx->iov_base, &tx_len, &udp->query_ctx);
-	}
-
-	/* Process error response (if failed). */
-	if (state == NS_PROC_FAIL) {
-		tx_len = tx->iov_len; /* Reset size. */
-		state = knot_process_out(tx->iov_base, &tx_len, &udp->query_ctx);
+	while (state & (KNOT_NS_PROC_FULL|KNOT_NS_PROC_FAIL)) {
+		state = knot_overlay_out(&udp->overlay, ans);
 	}
 
 	/* Send response only if finished successfuly. */
-	if (state == NS_PROC_DONE) {
-		tx->iov_len = tx_len;
+	if (state == KNOT_NS_PROC_DONE) {
+		tx->iov_len = ans->size;
 	} else {
 		tx->iov_len = 0;
 	}
 
-	/* Reset context. */
-	knot_process_finish(&udp->query_ctx);
+	/* Reset after processing. */
+	knot_overlay_finish(&udp->overlay);
+	knot_overlay_deinit(&udp->overlay);
+
+	/* Cleanup. */
+	knot_pkt_free(&query);
+	knot_pkt_free(&ans);
 }
 
 /* Check for sendmmsg syscall. */
@@ -444,18 +449,6 @@ void __attribute__ ((constructor)) udp_master_init()
 #endif /* HAVE_RECVMMSG */
 }
 
-
-int udp_send_msg(int fd, const uint8_t *msg, size_t msglen, struct sockaddr *addr)
-{
-	int addr_len = sockaddr_len((struct sockaddr_storage *)addr);
-	int ret = sendto(fd, msg, msglen, 0, addr, addr_len);
-	if (ret != msglen) {
-		return KNOT_ECONN;
-	}
-
-	return ret;
-}
-
 /*! \brief Release the reference on the interface list and clear watched fdset. */
 static void forget_ifaces(ifacelist_t *ifaces, fd_set *set, int maxfd)
 {
@@ -515,7 +508,9 @@ int udp_master(dthread_t *thread)
 	udp.thread_id = handler->thread_id[thr_id];
 
 	/* Create big enough memory cushion. */
-	mm_ctx_mempool(&udp.query_ctx.mm, 4 * sizeof(knot_pkt_t));
+	mm_ctx_t mm;
+	mm_ctx_mempool(&mm, 4 * sizeof(knot_pkt_t));
+	udp.overlay.mm = &mm;
 
 	/* Chose select as epoll/kqueue has larger overhead for a
 	 * single or handful of sockets. */
@@ -530,7 +525,7 @@ int udp_master(dthread_t *thread)
 	for (;;) {
 
 		/* Check handler state. */
-		if (knot_unlikely(*iostate & ServerReload)) {
+		if (unlikely(*iostate & ServerReload)) {
 			*iostate &= ~ServerReload;
 			udp.thread_id = handler->thread_id[thr_id];
 
@@ -560,7 +555,7 @@ int udp_master(dthread_t *thread)
 				if ((rcvd = _udp_recv(fd, rq)) > 0) {
 					_udp_handle(&udp, rq);
 					/* Flush allocated memory. */
-					mp_flush(udp.query_ctx.mm.ctx);
+					mp_flush(mm.ctx);
 					_udp_send(rq);
 					udp_pps_sample(rcvd, thr_id);
 				}
@@ -570,7 +565,7 @@ int udp_master(dthread_t *thread)
 
 	_udp_deinit(rq);
 	forget_ifaces(ref, &fds, maxfd);
-	mp_delete(udp.query_ctx.mm.ctx);
+	mp_delete(mm.ctx);
 	return KNOT_EOK;
 }
 
diff --git a/src/knot/server/udp-handler.h b/src/knot/server/udp-handler.h
index 7bbcb6707da7f8e8e1e2885256b3c5fbd6f1e2e6..1cdb729c03df0e0fb6c0c7a9f6003ccbe5e0cf2a 100644
--- a/src/knot/server/udp-handler.h
+++ b/src/knot/server/udp-handler.h
@@ -30,23 +30,8 @@
 
 #pragma once
 
-#include "knot/server/net.h"
-#include "knot/server/server.h"
 #include "knot/server/dthreads.h"
 
-/*!
- * \brief Send a UDP message.
- *
- * \param fd Associated socket.
- * \param msg Buffer for a query wireformat.
- * \param msglen Buffer maximum size.
- * \param addr Destination address.
- *
- * \retval Number of sent data on success.
- * \retval KNOT_ERROR on error.
- */
-int udp_send_msg(int fd, const uint8_t *msg, size_t msglen, struct sockaddr *addr);
-
 /*!
  * \brief UDP handler thread runnable.
  *
diff --git a/src/knot/updates/acl.h b/src/knot/updates/acl.h
index b9b38efa7b20085a7d6bff0fa3dab2d8edf7354d..ce924978deef83bb7c0fe5e84c74897789a7f4b7 100644
--- a/src/knot/updates/acl.h
+++ b/src/knot/updates/acl.h
@@ -29,9 +29,9 @@
 
 #pragma once
 
-#include "common-knot/lists.h"
-#include "common-knot/sockaddr.h"
-#include "libknot/mempattern.h"
+#include "common/lists.h"
+#include "common/sockaddr.h"
+#include "common/mempattern.h"
 #include "libknot/rrtype/tsig.h"
 
 struct conf_iface_t;
diff --git a/src/knot/updates/apply.c b/src/knot/updates/apply.c
index b1ae659752d64ba8dd58a7d3651b3eab4232eb49..20a415f58c8362ba1c1aefbe6b3e53e3c7735762 100644
--- a/src/knot/updates/apply.c
+++ b/src/knot/updates/apply.c
@@ -19,10 +19,10 @@
 #include "knot/updates/apply.h"
 
 #include "knot/zone/zone.h"
-#include "libknot/common.h"
 #include "knot/updates/changesets.h"
 #include "knot/zone/zonefile.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
+#include "common/macros.h"
 #include "libknot/rrtype/soa.h"
 #include "libknot/rrtype/rrsig.h"
 
@@ -245,7 +245,7 @@ static int apply_remove(zone_contents_t *contents, changeset_t *chset)
 {
 	changeset_iter_t itt;
 	changeset_iter_rem(&itt, chset, false);
-	
+
 	knot_rrset_t rr = changeset_iter_next(&itt);
 	while (!knot_rrset_empty(&rr)) {
 		// Find node for this owner
@@ -263,7 +263,7 @@ static int apply_remove(zone_contents_t *contents, changeset_t *chset)
 			changeset_iter_clear(&itt);
 			return ret;
 		}
-		
+
 		rr = changeset_iter_next(&itt);
 	}
 	changeset_iter_clear(&itt);
@@ -322,7 +322,7 @@ static int apply_add(zone_contents_t *contents, changeset_t *chset,
 {
 	changeset_iter_t itt;
 	changeset_iter_add(&itt, chset, false);
-	
+
 	knot_rrset_t rr = changeset_iter_next(&itt);
 	while(!knot_rrset_empty(&rr)) {
 		// Get or create node with this owner
@@ -340,7 +340,7 @@ static int apply_add(zone_contents_t *contents, changeset_t *chset,
 		rr = changeset_iter_next(&itt);
 	}
 	changeset_iter_clear(&itt);
-	
+
 	return KNOT_EOK;
 }
 
@@ -494,7 +494,7 @@ int apply_changeset(zone_t *zone, changeset_t *change, zone_contents_t **new_con
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
-	
+
 	const bool master = (zone_master(zone) == NULL);
 	ret = apply_single(contents_copy, change, master);
 	if (ret != KNOT_EOK) {
@@ -502,16 +502,16 @@ int apply_changeset(zone_t *zone, changeset_t *change, zone_contents_t **new_con
 		update_free_zone(&contents_copy);
 		return ret;
 	}
-	
+
 	ret = finalize_updated_zone(contents_copy, true);
 	if (ret != KNOT_EOK) {
 		update_rollback(change);
 		update_free_zone(&contents_copy);
 		return ret;
 	}
-	
+
 	*new_contents = contents_copy;
-	
+
 	return KNOT_EOK;
 }
 
@@ -535,7 +535,7 @@ int apply_changesets_directly(zone_contents_t *contents, list_t *chsets)
 	if (ret != KNOT_EOK) {
 		updates_cleanup(chsets);
 	}
-	
+
 	return ret;
 }
 
@@ -544,20 +544,20 @@ int apply_changeset_directly(zone_contents_t *contents, changeset_t *ch)
 	if (contents == NULL || ch == NULL) {
 		return KNOT_EINVAL;
 	}
-	
+
 	const bool master = true; // Only DNSSEC changesets are applied directly.
 	int ret = apply_single(contents, ch, master);
 	if (ret != KNOT_EOK) {
 		update_cleanup(ch);
 		return ret;
 	}
-	
+
 	ret = finalize_updated_zone(contents, true);
 	if (ret != KNOT_EOK) {
 		update_cleanup(ch);
 		return ret;
 	}
-	
+
 	return KNOT_EOK;
 }
 
diff --git a/src/knot/updates/changesets.c b/src/knot/updates/changesets.c
index b62aa5f5a20dccbb5ad2b78ef2b9e620b2d445ad..5882536efe072b3836cf442eb2aab7735fae927e 100644
--- a/src/knot/updates/changesets.c
+++ b/src/knot/updates/changesets.c
@@ -19,8 +19,8 @@
 #include <stdarg.h>
 
 #include "knot/updates/changesets.h"
-#include "libknot/common.h"
 #include "libknot/rrset.h"
+#include "common/macros.h"
 
 /* -------------------- Changeset iterator helpers -------------------------- */
 
@@ -152,7 +152,6 @@ changeset_t *changeset_new(const knot_dname_t *apex)
 {
 	changeset_t *ret = malloc(sizeof(changeset_t));
 	if (ret == NULL) {
-		ERR_ALLOC_FAILED;
 		return NULL;
 	}
 
diff --git a/src/knot/updates/changesets.h b/src/knot/updates/changesets.h
index 8800c85fb59cf72ec60c996c623859b420b22a17..2863353c257f2ef4bbfbc501550793caa4f7c385 100644
--- a/src/knot/updates/changesets.h
+++ b/src/knot/updates/changesets.h
@@ -28,7 +28,7 @@
 
 #include "libknot/rrset.h"
 #include "knot/zone/contents.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
 
 /*! \brief One zone change, from 'soa_from' to 'soa_to'. */
 typedef struct {
diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c
index 494d00bbf6c61be155d381c6928b1e7f7f2f9fe7..d366244032e597534dfbe24cecebd30536347dd6 100644
--- a/src/knot/updates/ddns.c
+++ b/src/knot/updates/ddns.c
@@ -22,12 +22,11 @@
 #include "knot/updates/changesets.h"
 #include "knot/updates/zone-update.h"
 #include "libknot/packet/pkt.h"
-#include "libknot/common.h"
 #include "libknot/consts.h"
 #include "libknot/rrtype/soa.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 #include "libknot/descriptor.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
 
 /* ----------------------------- prereq check ------------------------------- */
 
diff --git a/src/knot/updates/zone-update.c b/src/knot/updates/zone-update.c
index 21633ecf1058aa6b102f10e639a3dc4ae85e084d..a2c00e4fb37b6d6e34e949577920276e15b7a137 100644
--- a/src/knot/updates/zone-update.c
+++ b/src/knot/updates/zone-update.c
@@ -15,7 +15,7 @@
  */
 
 #include "knot/updates/zone-update.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
 #include "common/mempool.h"
 
 static int add_to_node(zone_node_t *node, const zone_node_t *add_node,
diff --git a/src/knot/updates/zone-update.h b/src/knot/updates/zone-update.h
index ea5e1eac4b9cecdcc07f4fe719d60331b4d6bcb2..183867b58933807a6776cc1e23b17ac326cbf536 100644
--- a/src/knot/updates/zone-update.h
+++ b/src/knot/updates/zone-update.h
@@ -28,7 +28,7 @@
 
 #include "knot/updates/changesets.h"
 #include "knot/zone/contents.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 
 /*! \brief Structure for zone contents updating / querying \todo to be moved to new ZONE API */
 typedef struct {
diff --git a/src/knot/worker/queue.h b/src/knot/worker/queue.h
index b1149951fd9d8edc011cac2d0eced9125c1e95da..98e1e372744bcda436f0ccce1c6f2eea77609d2c 100644
--- a/src/knot/worker/queue.h
+++ b/src/knot/worker/queue.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include "common-knot/lists.h"
+#include "common/lists.h"
 
 struct task;
 typedef void (*task_cb)(struct task *);
diff --git a/src/knot/zone/contents.c b/src/knot/zone/contents.c
index e9058ba9bd7a9961fb609bc01db4fd2bf012aa6f..703417f1f3913fabf40b5f68933a9e4d0b75edea 100644
--- a/src/knot/zone/contents.c
+++ b/src/knot/zone/contents.c
@@ -18,10 +18,11 @@
 
 #include "knot/zone/contents.h"
 #include "common/debug.h"
+#include "common/macros.h"
 #include "libknot/rrset.h"
 #include "common/base32hex.h"
 #include "libknot/descriptor.h"
-#include "common-knot/hattrie/hat-trie.h"
+#include "common/trie/hat-trie.h"
 #include "knot/dnssec/zone-nsec.h"
 #include "knot/dnssec/zone-sign.h"
 #include "knot/zone/zone-tree.h"
@@ -153,7 +154,6 @@ static int discover_additionals(struct rr_data *rr_data,
 	}
 	rr_data->additional = malloc(rdcount * sizeof(zone_node_t *));
 	if (rr_data->additional == NULL) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
@@ -1255,7 +1255,6 @@ int zone_contents_shallow_copy(const zone_contents_t *from, zone_contents_t **to
 
 	zone_contents_t *contents = calloc(1, sizeof(zone_contents_t));
 	if (contents == NULL) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
diff --git a/src/knot/zone/contents.h b/src/knot/zone/contents.h
index 62125433ec2ffb1e127db8d6c36a1aeb4d857008..0042c17abb8a872e20bb5b99b43787a56bb128ba 100644
--- a/src/knot/zone/contents.h
+++ b/src/knot/zone/contents.h
@@ -26,7 +26,7 @@
 
 #pragma once
 
-#include "common-knot/lists.h"
+#include "common/lists.h"
 #include "libknot/rrtype/nsec3param.h"
 #include "knot/zone/node.h"
 #include "knot/zone/zone-tree.h"
diff --git a/src/knot/zone/events/events.c b/src/knot/zone/events/events.c
index 0a1968033e2aad24766ce859a4418412bf5d223b..15838451cd84061a62606b9c2bd2df039f04b5a1 100644
--- a/src/knot/zone/events/events.c
+++ b/src/knot/zone/events/events.c
@@ -18,12 +18,14 @@
 #include <time.h>
 
 #include "common-knot/evsched.h"
+#include "common/namedb/namedb.h"
 #include "knot/server/server.h"
 #include "knot/worker/pool.h"
 #include "knot/zone/zone.h"
 #include "knot/zone/events/events.h"
 #include "knot/zone/events/handlers.h"
 #include "knot/zone/events/replan.h"
+#include "knot/zone/timers.h"
 
 /* ------------------------- internal timers -------------------------------- */
 
@@ -232,7 +234,8 @@ int zone_events_init(zone_t *zone)
 	return KNOT_EOK;
 }
 
-int zone_events_setup(zone_t *zone, worker_pool_t *workers, evsched_t *scheduler)
+int zone_events_setup(struct zone_t *zone, worker_pool_t *workers,
+                      evsched_t *scheduler, knot_namedb_t *timers_db)
 {
 	if (!zone || !workers || !scheduler) {
 		return KNOT_EINVAL;
@@ -246,6 +249,7 @@ int zone_events_setup(zone_t *zone, worker_pool_t *workers, evsched_t *scheduler
 
 	zone->events.event = event;
 	zone->events.pool = workers;
+	zone->events.timers_db = timers_db;
 
 	return KNOT_EOK;
 }
@@ -278,6 +282,11 @@ void zone_events_schedule_at(zone_t *zone, zone_event_type_t type, time_t time)
 	pthread_mutex_unlock(&events->mx);
 }
 
+bool zone_events_is_scheduled(zone_t *zone, zone_event_type_t type)
+{
+	return zone_events_get_time(zone, type) > 0;
+}
+
 void zone_events_enqueue(zone_t *zone, zone_event_type_t type)
 {
 	if (!zone || !valid_event(type)) {
@@ -409,3 +418,16 @@ void zone_events_replan_ddns(struct zone_t *zone, const struct zone_t *old_zone)
 		replan_update(zone, (zone_t *)old_zone);
 	}
 }
+
+int zone_events_write_persistent(zone_t *zone)
+{
+	if (!zone) {
+		return KNOT_EINVAL;
+	}
+
+	if (zone->events.timers_db == NULL) {
+		return KNOT_EOK;
+	}
+
+	return write_zone_timers(zone->events.timers_db, zone);
+}
diff --git a/src/knot/zone/events/events.h b/src/knot/zone/events/events.h
index 5bb27fe9acfd05169481b99306665e3f22855b64..9454a0fef287f3a30c0be74ecc620fde59453908 100644
--- a/src/knot/zone/events/events.h
+++ b/src/knot/zone/events/events.h
@@ -20,6 +20,7 @@
 #include <stdbool.h>
 
 #include "common-knot/evsched.h"
+#include "common/namedb/namedb.h"
 #include "knot/worker/pool.h"
 
 /* Timer special values. */
@@ -51,6 +52,7 @@ typedef struct zone_events {
 
 	event_t *event;			//!< Scheduler event.
 	worker_pool_t *pool;		//!< Server worker pool.
+	knot_namedb_t *timers_db;	//!< Persistent zone timers database.
 
 	task_t task;			//!< Event execution context.
 	time_t time[ZONE_EVENT_COUNT];	//!< Event execution times.
@@ -74,11 +76,12 @@ int zone_events_init(struct zone_t *zone);
  * \param zone       Zone to setup.
  * \param workers    Worker thread pool.
  * \param scheduler  Event scheduler.
+ * \param timers_db  Persistent timers database. Can be NULL.
  *
  * \return KNOT_E*
  */
 int zone_events_setup(struct zone_t *zone, worker_pool_t *workers,
-                      evsched_t *scheduler);
+                      evsched_t *scheduler, knot_namedb_t *timers_db);
 
 /*!
  * \brief Deinitialize zone events.
@@ -116,6 +119,14 @@ void zone_events_schedule_at(struct zone_t *zone, zone_event_type_t type, time_t
  */
 void zone_events_schedule(struct zone_t *zone, zone_event_type_t type, unsigned dt);
 
+/*!
+ * \brief Check if zone event is scheduled.
+ *
+ * \param zone  Zone to check event of.
+ * \param type  Type of event.
+ */
+bool zone_events_is_scheduled(struct zone_t *zone, zone_event_type_t type);
+
 /*!
  * \brief Cancel one zone event.
  *
@@ -185,3 +196,10 @@ void zone_events_update(struct zone_t *zone, struct zone_t *old_zone);
  * \param old_zone  Zone with old config.
  */
 void zone_events_replan_ddns(struct zone_t *zone, const struct zone_t *old_zone);
+
+/*!
+ * \brief Write persistent timers to timers database.
+ *
+ * \return KNOT_E*
+ */
+int zone_events_write_persistent(struct zone_t *zone);
diff --git a/src/knot/zone/events/handlers.c b/src/knot/zone/events/handlers.c
index 61d45d178d5bcb4a263a30060bf6fe3d2223d206..9eb74492b3547d15061a6f26c89ff5ad4d4b00dc 100644
--- a/src/knot/zone/events/handlers.c
+++ b/src/knot/zone/events/handlers.c
@@ -16,8 +16,12 @@
 
 #include "libknot/rrtype/soa.h"
 #include "libknot/dnssec/random.h"
+#include "libknot/processing/requestor.h"
+
 #include "common-knot/trim.h"
+#include "common/macros.h"
 #include "common/mempool.h"
+
 #include "knot/server/udp-handler.h"
 #include "knot/server/tcp-handler.h"
 #include "knot/updates/changesets.h"
@@ -31,7 +35,6 @@
 #include "knot/nameserver/internet.h"
 #include "knot/nameserver/update.h"
 #include "knot/nameserver/notify.h"
-#include "knot/nameserver/requestor.h"
 #include "knot/nameserver/tsig_ctx.h"
 #include "knot/nameserver/process_answer.h"
 
@@ -71,11 +74,11 @@ static knot_pkt_t *zone_query(const zone_t *zone, uint16_t pkt_type, mm_ctx_t *m
 	if (pkt_type == KNOT_QUERY_IXFR) {  /* RFC1995, SOA in AUTHORITY. */
 		knot_pkt_begin(pkt, KNOT_AUTHORITY);
 		knot_rrset_t soa_rr = node_rrset(contents->apex, KNOT_RRTYPE_SOA);
-		knot_pkt_put(pkt, COMPR_HINT_QNAME, &soa_rr, 0);
+		knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &soa_rr, 0);
 	} else if (pkt_type == KNOT_QUERY_NOTIFY) { /* RFC1996, SOA in ANSWER. */
 		knot_pkt_begin(pkt, KNOT_ANSWER);
 		knot_rrset_t soa_rr = node_rrset(contents->apex, KNOT_RRTYPE_SOA);
-		knot_pkt_put(pkt, COMPR_HINT_QNAME, &soa_rr, 0);
+		knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &soa_rr, 0);
 	}
 
 	return pkt;
@@ -100,15 +103,17 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
 		return KNOT_ENOMEM;
 	}
 
-	/* Create requestor instance. */
-	struct requestor re;
-	requestor_init(&re, NS_PROC_ANSWER, &mm);
-
 	/* Answer processing parameters. */
 	struct process_answer_param param = { 0 };
 	param.zone = zone;
 	param.query = query;
 	param.remote = &remote->addr;
+
+	/* Create requestor instance. */
+	struct knot_requestor re;
+	knot_requestor_init(&re, &mm);
+	knot_requestor_overlay(&re, KNOT_NS_PROC_ANSWER, &param);
+
 	tsig_init(&param.tsig_ctx, remote->key);
 
 	ret = tsig_sign_packet(&param.tsig_ctx, query);
@@ -117,23 +122,25 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
 	}
 
 	/* Create a request. */
-	struct request *req = requestor_make(&re, remote, query);
+	const struct sockaddr *dst = (const struct sockaddr *)&remote->addr;
+	const struct sockaddr *src = (const struct sockaddr *)&remote->via;
+	struct knot_request *req = knot_request_make(re.mm, dst, src, query, 0);
 	if (req == NULL) {
 		ret = KNOT_ENOMEM;
 		goto fail;
 	}
 
 	/* Send the queries and process responses. */
-	ret = requestor_enqueue(&re, req, &param);
+	ret = knot_requestor_enqueue(&re, req);
 	if (ret == KNOT_EOK) {
 		struct timeval tv = { conf()->max_conn_reply, 0 };
-		ret = requestor_exec(&re, &tv);
+		ret = knot_requestor_exec(&re, &tv);
 	}
 
 fail:
 	/* Cleanup. */
 	tsig_cleanup(&param.tsig_ctx);
-	requestor_clear(&re);
+	knot_requestor_clear(&re);
 	mp_delete(mm.ctx);
 
 	return ret;
@@ -196,7 +203,11 @@ static void schedule_dnssec(zone_t *zone, time_t refresh_at)
 	zone_events_schedule_at(zone, ZONE_EVENT_DNSSEC, refresh_at);
 }
 
-/* -- zone events handling callbacks --------------------------------------- */
+/*! \brief Get SOA from zone. */
+static const knot_rdataset_t *zone_soa(zone_t *zone)
+{
+	return node_rdataset(zone->contents->apex, KNOT_RRTYPE_SOA);
+}
 
 /*! \brief Fetch SOA expire timer and add a timeout grace period. */
 static uint32_t soa_graceful_expire(const knot_rdataset_t *soa)
@@ -206,6 +217,18 @@ static uint32_t soa_graceful_expire(const knot_rdataset_t *soa)
 	return knot_soa_expire(soa) + 2 * conf()->max_conn_idle;
 }
 
+/*! \brief Schedule expire event, unless it is already scheduled. */
+static void start_expire_timer(zone_t *zone, const knot_rdataset_t *soa)
+{
+	if (zone_events_is_scheduled(zone, ZONE_EVENT_EXPIRE)) {
+		return;
+	}
+
+	zone_events_schedule(zone, ZONE_EVENT_EXPIRE, soa_graceful_expire(soa));
+}
+
+/* -- zone events handling callbacks --------------------------------------- */
+
 int event_reload(zone_t *zone)
 {
 	assert(zone);
@@ -276,21 +299,18 @@ int event_reload(zone_t *zone)
 	log_zone_info(zone->name, "loaded, serial %u -> %u",
 	              old_serial, current_serial);
 
-	return write_zone_timers(conf()->timers_db, zone);
+	return zone_events_write_persistent(zone);
 
 fail:
 	zone_contents_deep_free(&contents);
 	return result;
 }
 
-/* -- zone events implementation API ---------------------------------------- */
-
 int event_refresh(zone_t *zone)
 {
 	assert(zone);
 
-	zone_contents_t *contents = zone->contents;
-	if (zone_contents_is_empty(contents)) {
+	if (zone_contents_is_empty(zone->contents)) {
 		/* No contents, schedule retransfer now. */
 		zone_events_schedule(zone, ZONE_EVENT_XFER, ZONE_EVENT_NOW);
 		return KNOT_EOK;
@@ -300,8 +320,7 @@ int event_refresh(zone_t *zone)
 	assert(master);
 
 	int ret = zone_query_execute(zone, KNOT_QUERY_NORMAL, master);
-
-	const knot_rdataset_t *soa = node_rdataset(contents->apex, KNOT_RRTYPE_SOA);
+	const knot_rdataset_t *soa = zone_soa(zone);
 	if (ret != KNOT_EOK) {
 		/* Log connection errors. */
 		ZONE_QUERY_LOG(LOG_WARNING, zone, master, "SOA query, outgoing",
@@ -310,18 +329,13 @@ int event_refresh(zone_t *zone)
 		zone_master_rotate(zone);
 		/* Schedule next retry. */
 		zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_retry(soa));
-		if (zone_events_get_time(zone, ZONE_EVENT_EXPIRE) <= ZONE_EVENT_NOW) {
-			/* Schedule zone expiration if not previously planned. */
-			zone_events_schedule(zone, ZONE_EVENT_EXPIRE, soa_graceful_expire(soa));
-		}
+		start_expire_timer(zone, soa);
 	} else {
 		/* SOA query answered, reschedule refresh timer. */
 		zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_refresh(soa));
-		/* Cancel possible expire. */
-		zone_events_cancel(zone, ZONE_EVENT_EXPIRE);
 	}
 
-	return write_zone_timers(conf()->timers_db, zone);
+	return zone_events_write_persistent(zone);
 }
 
 int event_xfer(zone_t *zone)
@@ -329,41 +343,49 @@ int event_xfer(zone_t *zone)
 	assert(zone);
 
 	/* Determine transfer type. */
-	bool is_bootstrap = false;
+	bool is_boostrap = zone_contents_is_empty(zone->contents);
 	uint16_t pkt_type = KNOT_QUERY_IXFR;
-	if (zone_contents_is_empty(zone->contents) || zone->flags & ZONE_FORCE_AXFR) {
+	if (is_boostrap || zone->flags & ZONE_FORCE_AXFR) {
 		pkt_type = KNOT_QUERY_AXFR;
-		is_bootstrap = true;
 	}
 
 	/* Execute zone transfer and reschedule timers. */
 	int ret = zone_query_transfer(zone, zone_master(zone), pkt_type);
-	if (ret == KNOT_EOK) {
-		assert(!zone_contents_is_empty(zone->contents));
-		/* New zone transferred, reschedule zone expiration and refresh
-		 * timers and send notifications to slaves. */
-		const knot_rdataset_t *soa =
-			node_rdataset(zone->contents->apex, KNOT_RRTYPE_SOA);
-		zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_refresh(soa));
-		zone_events_schedule(zone, ZONE_EVENT_NOTIFY,  ZONE_EVENT_NOW);
-		/* Sync zonefile immediately if configured. */
-		if (zone->conf->dbsync_timeout == 0) {
-			zone_events_schedule(zone, ZONE_EVENT_FLUSH, ZONE_EVENT_NOW);
-		} else if (zone_events_get_time(zone, ZONE_EVENT_FLUSH) <= ZONE_EVENT_NOW) {
-			/* Plan sync if not previously planned. */
-			zone_events_schedule(zone, ZONE_EVENT_FLUSH, zone->conf->dbsync_timeout);
-		}
-		zone->bootstrap_retry = ZONE_EVENT_NOW;
-		zone->flags &= ~ZONE_FORCE_AXFR;
-		/* Trim extra heap. */
-		if (!is_bootstrap) {
-			mem_trim();
+
+	/* Handle failure during transfer. */
+	if (ret != KNOT_EOK) {
+		if (is_boostrap) {
+			zone->bootstrap_retry = bootstrap_next(zone->bootstrap_retry);
+			zone_events_schedule(zone, ZONE_EVENT_XFER, zone->bootstrap_retry);
+		} else {
+			const knot_rdataset_t *soa = zone_soa(zone);
+			zone_events_schedule(zone, ZONE_EVENT_XFER, knot_soa_retry(soa));
+			start_expire_timer(zone, soa);
 		}
-	} else {
-		/* Zone contents is still empty, increment bootstrap retry timer
-		 * and try again. */
-		zone->bootstrap_retry = bootstrap_next(zone->bootstrap_retry);
-		zone_events_schedule(zone, ZONE_EVENT_XFER, zone->bootstrap_retry);
+
+		return KNOT_EOK;
+	}
+
+	assert(!zone_contents_is_empty(zone->contents));
+	const knot_rdataset_t *soa = zone_soa(zone);
+
+	/* Rechedule events. */
+	zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_refresh(soa));
+	zone_events_schedule(zone, ZONE_EVENT_NOTIFY,  ZONE_EVENT_NOW);
+	zone_events_cancel(zone, ZONE_EVENT_EXPIRE);
+	if (zone->conf->dbsync_timeout == 0) {
+		zone_events_schedule(zone, ZONE_EVENT_FLUSH, ZONE_EVENT_NOW);
+	} else if (!zone_events_is_scheduled(zone, ZONE_EVENT_FLUSH)) {
+		zone_events_schedule(zone, ZONE_EVENT_FLUSH, zone->conf->dbsync_timeout);
+	}
+
+	/* Transfer cleanup. */
+	zone->bootstrap_retry = ZONE_EVENT_NOW;
+	zone->flags &= ~ZONE_FORCE_AXFR;
+
+	/* Trim extra heap. */
+	if (!is_boostrap) {
+		mem_trim();
 	}
 
 	return KNOT_EOK;
@@ -382,11 +404,11 @@ int event_update(zone_t *zone)
 
 	/* Replan event if next update waiting. */
 	pthread_mutex_lock(&zone->ddns_lock);
-	
+
 	const bool empty = EMPTY_LIST(zone->ddns_queue);
-	
+
 	pthread_mutex_unlock(&zone->ddns_lock);
-	
+
 	if (!empty) {
 		zone_events_schedule(zone, ZONE_EVENT_UPDATE, ZONE_EVENT_NOW);
 	}
diff --git a/src/knot/zone/events/replan.c b/src/knot/zone/events/replan.c
index 6039f9b24a9546eb35b19df90f20ae159a7045f6..ee0ebd75e805f7e4b52cedd0d1f63f05c51fa9e2 100644
--- a/src/knot/zone/events/replan.c
+++ b/src/knot/zone/events/replan.c
@@ -15,9 +15,11 @@
 */
 
 #include "libknot/rrtype/soa.h"
+
 #include "knot/zone/events/replan.h"
 #include "knot/zone/events/handlers.h"
 #include "knot/zone/zone.h"
+#include "common/macros.h"
 
 /* -- Zone event replanning functions --------------------------------------- */
 
diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c
index ba8640625d960daa107bd852d3aa829506bb051d..e3df563fd6c5a0c35c2815ac972235d95c7a27e6 100644
--- a/src/knot/zone/node.c
+++ b/src/knot/zone/node.c
@@ -17,13 +17,13 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#include "libknot/common.h"
 #include "knot/zone/node.h"
+#include "libknot/errcode.h"
 #include "libknot/rrset.h"
 #include "libknot/rdataset.h"
 #include "libknot/rrtype/rrsig.h"
 #include "libknot/descriptor.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 
 /*! \brief Clears allocated data in RRSet entry. */
 static void rr_data_clear(struct rr_data *data, mm_ctx_t *mm)
@@ -88,7 +88,6 @@ zone_node_t *node_new(const knot_dname_t *owner, mm_ctx_t *mm)
 {
 	zone_node_t *ret = mm_alloc(mm, sizeof(zone_node_t));
 	if (ret == NULL) {
-		ERR_ALLOC_FAILED;
 		return NULL;
 	}
 	memset(ret, 0, sizeof(*ret));
@@ -116,7 +115,7 @@ void node_free_rrsets(zone_node_t *node, mm_ctx_t *mm)
 	for (uint16_t i = 0; i < node->rrset_count; ++i) {
 		rr_data_clear(&node->rrs[i], NULL);
 	}
-	
+
 	node->rrset_count = 0;
 }
 
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index 9a74af9826c791366cb7b674ef9f55921c18f5e7..ef0b283796792e1e68824205b623e79d2b50269d 100644
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -33,7 +33,7 @@
 #include "common/base32hex.h"
 #include "common-knot/crc.h"
 #include "libknot/descriptor.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 #include "knot/dnssec/zone-nsec.h"
 
 #include "knot/zone/semantic-check.h"
@@ -127,7 +127,7 @@ static char *error_messages[(-ZC_ERR_UNKNOWN) + 1] = {
 void err_handler_init(err_handler_t *h)
 {
 	memset(h, 0, sizeof(err_handler_t));
-	memset(h->errors, 0, sizeof(uint) * (-ZC_ERR_UNKNOWN + 1));
+	memset(h->errors, 0, sizeof(unsigned) * (-ZC_ERR_UNKNOWN + 1));
 	h->options.log_cname = 0;
 	h->options.log_glue = 0;
 	h->options.log_rrsigs = 0;
@@ -530,7 +530,6 @@ static int rdata_nsec_to_type_array(const knot_rdataset_t *rrs, uint16_t type,
 		uint8_t *bitmap =
 			malloc(sizeof(uint8_t) * (bitmap_size));
 		if (bitmap == NULL) {
-			ERR_ALLOC_FAILED;
 			free(*array);
 			return KNOT_ENOMEM;
 		}
@@ -547,7 +546,6 @@ static int rdata_nsec_to_type_array(const knot_rdataset_t *rrs, uint16_t type,
 						    sizeof(uint16_t) *
 						    *count);
 				if (tmp == NULL) {
-					ERR_ALLOC_FAILED;
 					free(bitmap);
 					free(*array);
 					return KNOT_ENOMEM;
diff --git a/src/knot/zone/semantic-check.h b/src/knot/zone/semantic-check.h
index aadef005916c1373f39f5409288925615b28c5bd..11fb863b0ec3698b67d38dd270cb821b8450c7c2 100644
--- a/src/knot/zone/semantic-check.h
+++ b/src/knot/zone/semantic-check.h
@@ -133,8 +133,8 @@ struct handler_options {
 struct err_handler {
 	/* Consider moving error messages here */
 	struct handler_options options; /*!< Handler options. */
-	uint errors[(-ZC_ERR_UNKNOWN) + 1]; /*!< Array with error messages */
-	uint error_count; /*!< Total error count */
+	unsigned errors[(-ZC_ERR_UNKNOWN) + 1]; /*!< Array with error messages */
+	unsigned error_count; /*!< Total error count */
 };
 
 typedef struct err_handler err_handler_t;
diff --git a/src/knot/zone/timers.c b/src/knot/zone/timers.c
index 63c9ce1d1e16a3fc25645239b1ab5dbcff6c9065..83eefd623a17ea338e353bb23fdb5a2c975de6b0 100644
--- a/src/knot/zone/timers.c
+++ b/src/knot/zone/timers.c
@@ -56,6 +56,12 @@ static bool event_persistent(size_t event)
 	return event_id_to_key[event] != 0;
 }
 
+/*! \brief Clear array of timers. */
+static void clear_timers(time_t *timers)
+{
+	memset(timers, 0, ZONE_EVENT_COUNT * sizeof(time_t));
+}
+
 /*! \brief Stores timers for persistent events. */
 static int store_timers(knot_txn_t *txn, zone_t *zone)
 {
@@ -87,21 +93,20 @@ static int store_timers(knot_txn_t *txn, zone_t *zone)
 static int read_timers(knot_txn_t *txn, const zone_t *zone, time_t *timers)
 {
 	const struct namedb_api *db_api = namedb_lmdb_api();
+	assert(db_api);
 
 	knot_val_t key = { .len = knot_dname_size(zone->name), .data = zone->name };
 	knot_val_t val;
+
 	int ret = db_api->find(txn, &key, &val, 0);
-	if (ret != KNOT_EOK) {
-		if (ret == KNOT_ENOENT) {
-			// New zone, no entry in db.
-			memset(timers, 0, ZONE_EVENT_COUNT * sizeof(time_t));
-			return KNOT_EOK;
-		}
+	if (ret != KNOT_EOK && ret != KNOT_ENOENT) {
 		return ret;
 	}
 
-	// Set unknown/unset event timers to 0.
-	memset(timers, 0, ZONE_EVENT_COUNT * sizeof(time_t));
+	clear_timers(timers);
+	if (ret == KNOT_ENOENT) {
+		return KNOT_EOK;
+	}
 
 	const size_t stored_event_count = val.len / EVENT_KEY_PAIR_SIZE;
 	size_t offset = 0;
@@ -120,40 +125,50 @@ static int read_timers(knot_txn_t *txn, const zone_t *zone, time_t *timers)
 
 /* -------- API ------------------------------------------------------------- */
 
-knot_namedb_t *open_timers_db(const char *storage)
+int open_timers_db(const char *storage, knot_namedb_t **db_ptr)
 {
-#ifndef HAVE_LMDB
-	// No-op if we don't have lmdb, all other operations will no-op as well then
-	return NULL;
-#else
+	if (!storage || !db_ptr) {
+		return KNOT_EINVAL;
+	}
+
+	const struct namedb_api *api = namedb_lmdb_api();
+	if (!api) {
+		return KNOT_ENOTSUP;
+	}
+
 	char *path = sprintf_alloc("%s/timers", storage);
 	if (!path) {
-		return NULL;
+		return KNOT_ENOMEM;
 	}
 
-	knot_namedb_t *db = namedb_lmdb_api()->init(path, NULL);
+	int ret = api->init(path, db_ptr, NULL);
 
 	free(path);
 
-	return db;
-#endif
+	return ret;
 }
 
 void close_timers_db(knot_namedb_t *timer_db)
 {
-	if (timer_db) {
-		namedb_lmdb_api()->deinit(timer_db);
+	if (!timer_db) {
+		return;
 	}
+
+	const struct namedb_api *db_api = namedb_lmdb_api();
+	assert(db_api);
+
+	db_api->deinit(timer_db);
 }
 
 int read_zone_timers(knot_namedb_t *timer_db, const zone_t *zone, time_t *timers)
 {
 	if (timer_db == NULL) {
-		memset(timers, 0, ZONE_EVENT_COUNT * sizeof(time_t));
+		clear_timers(timers);
 		return KNOT_EOK;
 	}
 
 	const struct namedb_api *db_api = namedb_lmdb_api();
+	assert(db_api);
 
 	knot_txn_t txn;
 	int ret = db_api->txn_begin(timer_db, &txn, KNOT_NAMEDB_RDONLY);
@@ -177,6 +192,7 @@ int write_zone_timers(knot_namedb_t *timer_db, zone_t *zone)
 	}
 
 	const struct namedb_api *db_api = namedb_lmdb_api();
+	assert(db_api);
 
 	knot_txn_t txn;
 	int ret = db_api->txn_begin(timer_db, &txn, 0);
@@ -198,7 +214,9 @@ int sweep_timer_db(knot_namedb_t *timer_db, knot_zonedb_t *zone_db)
 	if (timer_db == NULL) {
 		return KNOT_EOK;
 	}
+
 	const struct namedb_api *db_api = namedb_lmdb_api();
+	assert(db_api);
 
 	knot_txn_t txn;
 	int ret = db_api->txn_begin(timer_db, &txn, KNOT_NAMEDB_SORTED);
@@ -236,5 +254,3 @@ int sweep_timer_db(knot_namedb_t *timer_db, knot_zonedb_t *zone_db)
 
 	return db_api->txn_commit(&txn);
 }
-
-
diff --git a/src/knot/zone/timers.h b/src/knot/zone/timers.h
index caa2772ac7082302a14091036ecdf73d17598ffa..f93c05815c2a2994512d6867a3e764af6ae9889c 100644
--- a/src/knot/zone/timers.h
+++ b/src/knot/zone/timers.h
@@ -23,11 +23,12 @@
 /*!
  * \brief Opens zone timers db. No-op without LMDB support.
  *
- * \param storage  Path to storage directory.
+ * \param[in]  storage   Path to storage directory.
+ * \param[out] timer_db  Created database.
  *
- * \return Created database.
+ * \return KNOT_E*
  */
-knot_namedb_t *open_timers_db(const char *storage);
+int open_timers_db(const char *storage, knot_namedb_t **timer_db);
 
 /*!
  * \brief Closes zone timers db.
@@ -69,4 +70,3 @@ int write_zone_timers(knot_namedb_t *timer_db, zone_t *zone);
  * \return KNOT_EOK or an error
  */
 int sweep_timer_db(knot_namedb_t *timer_db, knot_zonedb_t *zone_db);
-
diff --git a/src/knot/zone/zone-diff.c b/src/knot/zone/zone-diff.c
index a7dd6ec5cbdb8927f7cc49468424bc6d294c6e40..54beb477b0fec8cadc0886b052946ce59c0f9853 100644
--- a/src/knot/zone/zone-diff.c
+++ b/src/knot/zone/zone-diff.c
@@ -94,7 +94,7 @@ static int knot_zone_diff_add_node(const zone_node_t *node,
                                    changeset_t *changeset)
 {
 	/* Add all rrsets from node. */
-	for (uint i = 0; i < node->rrset_count; i++) {
+	for (unsigned i = 0; i < node->rrset_count; i++) {
 		knot_rrset_t rrset = node_rrset_at(node, i);
 		int ret = changeset_add_rrset(changeset, &rrset);
 		if (ret != KNOT_EOK) {
@@ -111,7 +111,7 @@ static int knot_zone_diff_remove_node(changeset_t *changeset,
                                       const zone_node_t *node)
 {
 	/* Remove all the RRSets of the node. */
-	for (uint i = 0; i < node->rrset_count; i++) {
+	for (unsigned i = 0; i < node->rrset_count; i++) {
 		knot_rrset_t rrset = node_rrset_at(node, i);
 		int ret = changeset_rem_rrset(changeset, &rrset);
 		if (ret != KNOT_EOK) {
@@ -154,7 +154,7 @@ static int knot_zone_diff_rdata_return_changes(const knot_rrset_t *rrset1,
 	/* Create fake RRSet, it will be easier to handle. */
 	knot_rrset_init(changes, rrset1->owner, rrset1->type, rrset1->rclass);
 
-	const rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset1->type);
+	const knot_rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset1->type);
 	assert(desc);
 
 	uint16_t rr1_count = rrset1->rrs.rr_count;
@@ -270,7 +270,7 @@ static int knot_zone_diff_node(zone_node_t **node_ptr, void *data)
 		                               param->changeset);
 	}
 
-	for (uint i = 0; i < node->rrset_count; i++) {
+	for (unsigned i = 0; i < node->rrset_count; i++) {
 		/* Search for the RRSet in the node from the second tree. */
 		knot_rrset_t rrset = node_rrset_at(node, i);
 
@@ -299,7 +299,7 @@ static int knot_zone_diff_node(zone_node_t **node_ptr, void *data)
 		}
 	}
 
-	for (uint i = 0; i < node_in_second_tree->rrset_count; i++) {
+	for (unsigned i = 0; i < node_in_second_tree->rrset_count; i++) {
 		/* Search for the RRSet in the node from the second tree. */
 		knot_rrset_t rrset = node_rrset_at(node_in_second_tree, i);
 
diff --git a/src/knot/zone/zone-dump.c b/src/knot/zone/zone-dump.c
index a776ce5b73279d4da618b3ac5cc6b0e5ca1c98f2..057004646aab690de75ab8399c9021396a073ac0 100644
--- a/src/knot/zone/zone-dump.c
+++ b/src/knot/zone/zone-dump.c
@@ -138,7 +138,6 @@ int zone_dump_text(zone_contents_t *zone, const struct sockaddr_storage *from, F
 	// Allocate auxiliary buffer for dumping operations.
 	char *buf = malloc(DUMP_BUF_LEN);
 	if (buf == NULL) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
diff --git a/src/knot/zone/zone-tree.c b/src/knot/zone/zone-tree.c
index 370a45d1e89395e7ae827182a4967ee6b070ac91..2fe78ef52c38b0279dcf53563cb7f2d535c4642f 100644
--- a/src/knot/zone/zone-tree.c
+++ b/src/knot/zone/zone-tree.c
@@ -21,7 +21,8 @@
 #include "knot/zone/zone-tree.h"
 #include "knot/zone/node.h"
 #include "common/debug.h"
-#include "common-knot/hattrie/hat-trie.h"
+#include "common/macros.h"
+#include "common/trie/hat-trie.h"
 
 /*----------------------------------------------------------------------------*/
 /* API functions                                                              */
diff --git a/src/knot/zone/zone-tree.h b/src/knot/zone/zone-tree.h
index 4c5232501f84a1495b285d72e4a4cea588720cb4..9270017823dbe736c33f28f1cb27550609ab11fd 100644
--- a/src/knot/zone/zone-tree.h
+++ b/src/knot/zone/zone-tree.h
@@ -28,7 +28,7 @@
 
 #pragma once
 
-#include "common-knot/hattrie/hat-trie.h"
+#include "common/trie/hat-trie.h"
 #include "knot/zone/node.h"
 
 /*----------------------------------------------------------------------------*/
diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c
index e3557ebbba4eef651c8da7f2c4544d8c59e05b6e..dd7d9a57f7a05a18605351286934a6cd4fb336c9 100644
--- a/src/knot/zone/zone.c
+++ b/src/knot/zone/zone.c
@@ -21,15 +21,16 @@
 
 #include "libknot/descriptor.h"
 #include "common-knot/evsched.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
 #include "common-knot/trim.h"
 #include "knot/zone/node.h"
 #include "knot/zone/zone.h"
 #include "knot/zone/zonefile.h"
 #include "knot/zone/contents.h"
 #include "knot/updates/apply.h"
-#include "knot/nameserver/requestor.h"
-#include "libknot/common.h"
+#include "libknot/processing/requestor.h"
+#include "knot/nameserver/process_query.h"
+#include "libknot/errcode.h"
 #include "libknot/dname.h"
 #include "libknot/dnssec/random.h"
 #include "libknot/util/utils.h"
@@ -37,7 +38,7 @@
 
 static void free_ddns_queue(zone_t *z)
 {
-	struct request_data *n = NULL;
+	struct knot_request *n = NULL;
 	node_t *nxt = NULL;
 	WALK_LIST_DELSAFE(n, nxt, z->ddns_queue) {
 		close(n->fd);
@@ -55,7 +56,6 @@ zone_t* zone_new(conf_zone_t *conf)
 
 	zone_t *zone = malloc(sizeof(zone_t));
 	if (zone == NULL) {
-		ERR_ALLOC_FAILED;
 		return NULL;
 	}
 	memset(zone, 0, sizeof(zone_t));
@@ -64,7 +64,6 @@ zone_t* zone_new(conf_zone_t *conf)
 	knot_dname_to_lower(zone->name);
 	if (zone->name == NULL) {
 		free(zone);
-		ERR_ALLOC_FAILED;
 		return NULL;
 	}
 
@@ -248,11 +247,11 @@ int zone_update_enqueue(zone_t *zone, knot_pkt_t *pkt, struct process_query_para
 {
 
 	/* Create serialized request. */
-	struct request_data *req = malloc(sizeof(struct request_data));
+	struct knot_request *req = malloc(sizeof(struct knot_request));
 	if (req == NULL) {
 		return KNOT_ENOMEM;
 	}
-	memset(req, 0, sizeof(struct request_data));
+	memset(req, 0, sizeof(struct knot_request));
 
 	/* Copy socket and request. */
 	req->fd = dup(param->socket);
@@ -299,7 +298,7 @@ size_t zone_update_dequeue(zone_t *zone, list_t *updates)
 	zone->ddns_queue_size = 0;
 
 	pthread_mutex_unlock(&zone->ddns_lock);
-	
+
 	return update_count;
 }
 
diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c
index 97f938edf0d81c074b8c15d80ef10ef07acf3164..e03b48654b6ae12be090579a9ee2d4ddc61cd776 100644
--- a/src/knot/zone/zonedb-load.c
+++ b/src/knot/zone/zonedb-load.c
@@ -120,7 +120,8 @@ static zone_t *create_zone_from(conf_zone_t *zone_conf, server_t *server)
 		return NULL;
 	}
 
-	int result = zone_events_setup(zone, server->workers, &server->sched);
+	int result = zone_events_setup(zone, server->workers, &server->sched,
+	                               server->timers_db);
 	if (result != KNOT_EOK) {
 		zone->conf = NULL;
 		zone_free(&zone);
@@ -130,7 +131,7 @@ static zone_t *create_zone_from(conf_zone_t *zone_conf, server_t *server)
 	return zone;
 }
 
-static zone_t *create_zone_reload(const conf_t *conf, conf_zone_t *zone_conf, server_t *server,
+static zone_t *create_zone_reload(conf_zone_t *zone_conf, server_t *server,
                                   zone_t *old_zone)
 {
 	zone_t *zone = create_zone_from(zone_conf, server);
@@ -154,7 +155,7 @@ static zone_t *create_zone_reload(const conf_t *conf, conf_zone_t *zone_conf, se
 		/* Reuse events from old zone. */
 		zone_events_update(zone, old_zone);
 		/* Write updated timers. */
-		write_zone_timers(conf->timers_db, zone);
+		zone_events_write_persistent(zone);
 		break;
 	default:
 		assert(0);
@@ -168,7 +169,7 @@ static bool slave_event(zone_event_type_t event)
 	return event == ZONE_EVENT_EXPIRE || event == ZONE_EVENT_REFRESH;
 }
 
-static void reuse_uvents(zone_t *zone, const time_t *timers)
+static void reuse_events(zone_t *zone, const time_t *timers)
 {
 	for (zone_event_type_t event = 0; event < ZONE_EVENT_COUNT; ++event) {
 		if (timers[event] == 0) {
@@ -201,7 +202,7 @@ static zone_t *create_zone_new(conf_zone_t *zone_conf, server_t *server)
 	memset(timers, 0, sizeof(timers));
 	
 	// Get persistent timers
-	int ret = read_zone_timers(conf()->timers_db, zone, timers);
+	int ret = read_zone_timers(server->timers_db, zone, timers);
 	if (ret != KNOT_EOK) {
 		log_zone_error(zone->name, "cannot read zone timers (%s)",
 		               knot_strerror(ret));
@@ -210,7 +211,7 @@ static zone_t *create_zone_new(conf_zone_t *zone_conf, server_t *server)
 		return NULL;
 	}
 	
-	reuse_uvents(zone, timers);
+	reuse_events(zone, timers);
 	
 	const zone_status_t zstatus = zone_file_status(NULL, zone_conf);
 	
@@ -247,14 +248,14 @@ static zone_t *create_zone_new(conf_zone_t *zone_conf, server_t *server)
  *
  * \return Error code, KNOT_EOK if successful.
  */
-static zone_t *create_zone(const conf_t *conf, conf_zone_t *zone_conf, server_t *server,
+static zone_t *create_zone(conf_zone_t *zone_conf, server_t *server,
                            zone_t *old_zone)
 {
 	assert(zone_conf);
 	assert(server);
 
 	if (old_zone) {
-		return create_zone_reload(conf, zone_conf, server, old_zone);
+		return create_zone_reload(zone_conf, server, old_zone);
 	} else {
 		return create_zone_new(zone_conf, server);
 	}
@@ -291,7 +292,7 @@ static knot_zonedb_t *create_zonedb(const conf_t *conf, server_t *server)
 		zone_t *old_zone = knot_zonedb_find(db_old, apex);
 		knot_dname_free(&apex, NULL);
 
-		zone_t *zone = create_zone(conf, zone_config, server, old_zone);
+		zone_t *zone = create_zone(zone_config, server, old_zone);
 		if (!zone) {
 			log_zone_str_error(zone_config->name,
 					   "zone cannot be created");
@@ -353,8 +354,6 @@ int zonedb_reload(const conf_t *conf, struct server_t *server)
 	}
 
 	/* Insert all required zones to the new zone DB. */
-	/*! \warning RCU must not be locked as some contents switching will
-	             be required. */
 	knot_zonedb_t *db_new = create_zonedb(conf, server);
 	if (db_new == NULL) {
 		log_error("failed to create new zone database");
@@ -372,7 +371,7 @@ int zonedb_reload(const conf_t *conf, struct server_t *server)
 	synchronize_rcu();
 	
 	/* Sweep the timer database. */
-	sweep_timer_db(conf->timers_db, db_new);
+	sweep_timer_db(server->timers_db, db_new);
 
 	/*
 	 * Remove all zones present in the new DB from the old DB.
diff --git a/src/knot/zone/zonedb.c b/src/knot/zone/zonedb.c
index 705db05b00d017ccfac5daf9a46e0e90a91a42bc..caeebdbd7bf899bb24c542a0d83514c0c705deb8 100644
--- a/src/knot/zone/zonedb.c
+++ b/src/knot/zone/zonedb.c
@@ -21,14 +21,14 @@
 
 #include "knot/zone/zonedb.h"
 #include "knot/server/server.h"
-#include "libknot/common.h"
 #include "knot/zone/zone.h"
 #include "knot/zone/zonedb.h"
 #include "libknot/dname.h"
 #include "libknot/packet/wire.h"
 #include "knot/zone/node.h"
 #include "common/debug.h"
-#include "libknot/mempattern.h"
+#include "common/macros.h"
+#include "common/mempattern.h"
 #include "common/mempool.h"
 
 
diff --git a/src/knot/zone/zonedb.h b/src/knot/zone/zonedb.h
index 6b6599fd2ba51cfbc8225c8be944a32e82f3685b..ffab431618d6f06111e2a01a0b105f8c32247197 100644
--- a/src/knot/zone/zonedb.h
+++ b/src/knot/zone/zonedb.h
@@ -33,7 +33,7 @@
 #include "knot/zone/zone.h"
 #include "knot/zone/contents.h"
 #include "libknot/dname.h"
-#include "common-knot/hhash.h"
+#include "common/hhash.h"
 
 /*
  * Zone DB represents a list of managed zones.
diff --git a/src/knot/zone/zonefile.c b/src/knot/zone/zonefile.c
index b627ae550748b9f8bd24b6cce616861d47427cf2..7b90840aa50bec722568fd2de4f239fbfa0ab099 100644
--- a/src/knot/zone/zonefile.c
+++ b/src/knot/zone/zonefile.c
@@ -28,8 +28,8 @@
 
 #include "common-knot/crc.h"
 #include "common-knot/strlcat.h"
-#include "common-knot/strlcpy.h"
-#include "libknot/common.h"
+#include "common/macros.h"
+#include "common/strlcpy.h"
 #include "knot/zone/semantic-check.h"
 #include "knot/zone/contents.h"
 #include "knot/dnssec/zone-nsec.h"
@@ -217,7 +217,6 @@ int zonefile_open(zloader_t *loader, const char *source, const char *origin,
 	/* Create context. */
 	zcreator_t *zc = malloc(sizeof(zcreator_t));
 	if (zc == NULL) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 	memset(zc, 0, sizeof(zcreator_t));
diff --git a/src/libknot/binary.c b/src/libknot/binary.c
index 179195ece67feef9dcac1d7af771641c283edf2e..e069ca0ebe9250043351d6b078344e0ac8e739b0 100644
--- a/src/libknot/binary.c
+++ b/src/libknot/binary.c
@@ -17,11 +17,15 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "libknot/binary.h"
+
 #include "common/base64.h"
-#include "libknot/errcode.h"
+#include "common/macros.h"
 #include "common/mem.h"
-#include "libknot/binary.h"
 
+#include "libknot/errcode.h"
+
+_public_
 int knot_binary_from_base64(const char *base64, knot_binary_t *to)
 {
 	if (!base64 || !to) {
@@ -42,6 +46,7 @@ int knot_binary_from_base64(const char *base64, knot_binary_t *to)
 	return KNOT_EOK;
 }
 
+_public_
 int knot_binary_from_string(const uint8_t *data, size_t size, knot_binary_t *to)
 {
 	if (!data || !to) {
@@ -59,6 +64,7 @@ int knot_binary_from_string(const uint8_t *data, size_t size, knot_binary_t *to)
 	return KNOT_EOK;
 }
 
+_public_
 int knot_binary_free(knot_binary_t *binary)
 {
 	if (!binary) {
@@ -74,6 +80,7 @@ int knot_binary_free(knot_binary_t *binary)
 	return KNOT_EOK;
 }
 
+_public_
 int knot_binary_dup(const knot_binary_t *from, knot_binary_t *to)
 {
 	if (!from || !to) {
diff --git a/src/libknot/consts.c b/src/libknot/consts.c
index 694d47dd899963b116b7acf23b2e6c09cb4f4b07..0999b9102ef31e0254f94a286260ca7905339517 100644
--- a/src/libknot/consts.c
+++ b/src/libknot/consts.c
@@ -14,8 +14,10 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <libknot/consts.h>
+#include "libknot/consts.h"
+#include "common/macros.h"
 
+_public_
 knot_lookup_table_t knot_opcode_names[] = {
 	{ KNOT_OPCODE_QUERY,  "QUERY" },
 	{ KNOT_OPCODE_IQUERY, "IQUERY" },
@@ -25,6 +27,7 @@ knot_lookup_table_t knot_opcode_names[] = {
 	{ 0, NULL }
 };
 
+_public_
 knot_lookup_table_t knot_rcode_names[] = {
 	{ KNOT_RCODE_NOERROR,  "NOERROR" },
 	{ KNOT_RCODE_FORMERR,  "FORMERR" },
@@ -41,6 +44,7 @@ knot_lookup_table_t knot_rcode_names[] = {
 	{ 0, NULL }
 };
 
+_public_
 knot_lookup_table_t knot_tsig_err_names[] = {
 	{ KNOT_TSIG_ERR_BADSIG,   "BADSIG" },
 	{ KNOT_TSIG_ERR_BADKEY,   "BADKEY" },
@@ -49,6 +53,7 @@ knot_lookup_table_t knot_tsig_err_names[] = {
 	{ 0, NULL }
 };
 
+_public_
 knot_lookup_table_t knot_tkey_err_names[] = {
 	{ KNOT_TKEY_ERR_BADMODE,  "BADMODE" },
 	{ KNOT_TKEY_ERR_BADNAME,  "BADNAME" },
@@ -56,6 +61,7 @@ knot_lookup_table_t knot_tkey_err_names[] = {
 	{ 0, NULL }
 };
 
+_public_
 knot_lookup_table_t knot_tsig_alg_names[] = {
 	{ KNOT_TSIG_ALG_HMAC_MD5,    "hmac-md5" },
 	{ KNOT_TSIG_ALG_HMAC_SHA1,   "hmac-sha1" },
@@ -66,6 +72,7 @@ knot_lookup_table_t knot_tsig_alg_names[] = {
 	{ KNOT_TSIG_ALG_NULL, NULL }
 };
 
+_public_
 knot_lookup_table_t knot_tsig_alg_dnames_str[] = {
 	{ KNOT_TSIG_ALG_GSS_TSIG,    "gss-tsig." },
 	{ KNOT_TSIG_ALG_HMAC_MD5,    "hmac-md5.sig-alg.reg.int." },
@@ -77,9 +84,10 @@ knot_lookup_table_t knot_tsig_alg_dnames_str[] = {
 	{ KNOT_TSIG_ALG_NULL, NULL }
 };
 
+_public_
 knot_lookup_table_t knot_tsig_alg_dnames[] = {
-        { KNOT_TSIG_ALG_GSS_TSIG,    "\x08" "gss-tsig" },
-        { KNOT_TSIG_ALG_HMAC_MD5,    "\x08" "hmac-md5" "\x07" "sig-alg" "\x03" "reg" "\x03" "int" },
+	{ KNOT_TSIG_ALG_GSS_TSIG,    "\x08" "gss-tsig" },
+	{ KNOT_TSIG_ALG_HMAC_MD5,    "\x08" "hmac-md5" "\x07" "sig-alg" "\x03" "reg" "\x03" "int" },
 	{ KNOT_TSIG_ALG_HMAC_SHA1,   "\x09" "hmac-sha1" },
 	{ KNOT_TSIG_ALG_HMAC_SHA224, "\x0B" "hmac-sha224" },
 	{ KNOT_TSIG_ALG_HMAC_SHA256, "\x0B" "hmac-sha256" },
@@ -88,6 +96,7 @@ knot_lookup_table_t knot_tsig_alg_dnames[] = {
 	{ KNOT_TSIG_ALG_NULL, NULL }
 };
 
+_public_
 knot_lookup_table_t knot_dnssec_alg_names[] = {
 	{ KNOT_DNSSEC_ALG_RSAMD5,             "RSAMD5" },
 	{ KNOT_DNSSEC_ALG_DH,                 "DH" },
@@ -103,6 +112,7 @@ knot_lookup_table_t knot_dnssec_alg_names[] = {
 	{ 0, NULL }
 };
 
+_public_
 size_t knot_tsig_digest_length(const uint8_t algorithm)
 {
 	switch (algorithm) {
@@ -125,6 +135,7 @@ size_t knot_tsig_digest_length(const uint8_t algorithm)
 	}
 }
 
+_public_
 bool knot_dnssec_algorithm_is_zonesign(uint8_t algorithm, bool nsec3_enabled)
 {
 	switch (algorithm) {
diff --git a/src/libknot/consts.h b/src/libknot/consts.h
index 8293ff528b75ea983805397b082828b2b071bf20..802d43d972cc9f7b1d9aecafd9358e368d3165db 100644
--- a/src/libknot/consts.h
+++ b/src/libknot/consts.h
@@ -207,6 +207,16 @@ extern knot_lookup_table_t knot_opcode_names[];
  */
 extern knot_lookup_table_t knot_rcode_names[];
 
+/*!
+ * \brief TSIG error names.
+ */
+extern knot_lookup_table_t knot_tsig_err_names[];
+
+/*!
+ * \brief TKEY error names.
+ */
+extern knot_lookup_table_t knot_tkey_err_names[];
+
 /*!
  * \brief TSIG key algorithm names.
  */
diff --git a/src/libknot/descriptor.c b/src/libknot/descriptor.c
index 6b858072158f17a931977583c31fd5cc9cdd05d4..ff4f130bb067cef9893bdec810d6599787687cba 100644
--- a/src/libknot/descriptor.c
+++ b/src/libknot/descriptor.c
@@ -19,6 +19,7 @@
 #include <strings.h>			// strcasecmp
 
 #include "libknot/descriptor.h"
+#include "common/macros.h"
 
 /*!
  * \brief Table with DNS classes.
@@ -33,7 +34,7 @@ static const char* dns_classes[] = {
 /*!
  * \brief RR type descriptors.
  */
-static const rdata_descriptor_t rdata_descriptors[] = {
+static const knot_rdata_descriptor_t rdata_descriptors[] = {
 	[0]                      = { { KNOT_RDATA_WF_REMAINDER,
 	                               KNOT_RDATA_WF_END }, NULL },
 	[KNOT_RRTYPE_A]          = { { 4, KNOT_RDATA_WF_END }, "A" },
@@ -132,7 +133,7 @@ static const rdata_descriptor_t rdata_descriptors[] = {
 /*!
  * \brief Some (OBSOLETE) RR type descriptors.
  */
-static const rdata_descriptor_t obsolete_rdata_descriptors[] = {
+static const knot_rdata_descriptor_t obsolete_rdata_descriptors[] = {
 	[0]                      = { { KNOT_RDATA_WF_REMAINDER,
 	                               KNOT_RDATA_WF_END }, NULL },
 	[KNOT_RRTYPE_MD]         = { { KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME,
@@ -153,7 +154,8 @@ static const rdata_descriptor_t obsolete_rdata_descriptors[] = {
 	                               KNOT_RDATA_WF_END }, "NXT" },
 };
 
-const rdata_descriptor_t *knot_get_rdata_descriptor(const uint16_t type)
+_public_
+const knot_rdata_descriptor_t *knot_get_rdata_descriptor(const uint16_t type)
 {
 	if (type <= KNOT_RRTYPE_ANY &&
 	    rdata_descriptors[type].type_name != NULL) {
@@ -163,7 +165,8 @@ const rdata_descriptor_t *knot_get_rdata_descriptor(const uint16_t type)
 	}
 }
 
-const rdata_descriptor_t *knot_get_obsolete_rdata_descriptor(const uint16_t type)
+_public_
+const knot_rdata_descriptor_t *knot_get_obsolete_rdata_descriptor(const uint16_t type)
 {
 	if (type <= KNOT_RRTYPE_NXT &&
 	    obsolete_rdata_descriptors[type].type_name != NULL) {
@@ -173,6 +176,7 @@ const rdata_descriptor_t *knot_get_obsolete_rdata_descriptor(const uint16_t type
 	}
 }
 
+_public_
 int knot_rrtype_to_string(const uint16_t rrtype,
                           char           *out,
                           const size_t   out_len)
@@ -183,7 +187,7 @@ int knot_rrtype_to_string(const uint16_t rrtype,
 
 	int ret;
 
-	const rdata_descriptor_t *descr = knot_get_rdata_descriptor(rrtype);
+	const knot_rdata_descriptor_t *descr = knot_get_rdata_descriptor(rrtype);
 
 	if (descr->type_name != NULL) {
 		ret = snprintf(out, out_len, "%s", descr->type_name);
@@ -198,6 +202,7 @@ int knot_rrtype_to_string(const uint16_t rrtype,
 	}
 }
 
+_public_
 int knot_rrtype_from_string(const char *name, uint16_t *num)
 {
 	if (name == NULL || num == NULL) {
@@ -234,6 +239,7 @@ int knot_rrtype_from_string(const char *name, uint16_t *num)
 	return 0;
 }
 
+_public_
 int knot_rrclass_to_string(const uint16_t rrclass,
                            char           *out,
                            const size_t   out_len)
@@ -257,6 +263,7 @@ int knot_rrclass_to_string(const uint16_t rrclass,
 	}
 }
 
+_public_
 int knot_rrclass_from_string(const char *name, uint16_t *num)
 {
 	if (name == NULL || num == NULL) {
@@ -293,6 +300,7 @@ int knot_rrclass_from_string(const char *name, uint16_t *num)
 	return 0;
 }
 
+_public_
 int knot_rrtype_is_metatype(const uint16_t type)
 {
 	return type == KNOT_RRTYPE_SIG  ||
@@ -304,6 +312,7 @@ int knot_rrtype_is_metatype(const uint16_t type)
 	       type == KNOT_RRTYPE_ANY;
 }
 
+_public_
 int knot_rrtype_is_ddns_forbidden(const uint16_t type)
 {
 	return type == KNOT_RRTYPE_RRSIG ||
@@ -311,6 +320,7 @@ int knot_rrtype_is_ddns_forbidden(const uint16_t type)
 	       type == KNOT_RRTYPE_NSEC3;
 }
 
+_public_
 int knot_rrtype_additional_needed(const uint16_t type)
 {
 	return type == KNOT_RRTYPE_NS ||
@@ -318,6 +328,7 @@ int knot_rrtype_additional_needed(const uint16_t type)
 	       type == KNOT_RRTYPE_SRV;
 }
 
+_public_
 bool knot_rrtype_should_be_lowercased(const uint16_t type)
 {
 	return type == KNOT_RRTYPE_NS    ||
diff --git a/src/libknot/descriptor.h b/src/libknot/descriptor.h
index 7f38f23be70d06a07bc2256062c4e33f947dad07..861721784e6e2f33ba115d2a6d0b70e9c7ca08e8 100644
--- a/src/libknot/descriptor.h
+++ b/src/libknot/descriptor.h
@@ -161,7 +161,7 @@ typedef struct {
 	const int  block_types[KNOT_MAX_RDATA_BLOCKS];
 	/*!< RR type name. */
 	const char *type_name;
-} rdata_descriptor_t;
+} knot_rdata_descriptor_t;
 
 /*!
  * \brief Gets rdata descriptor for given RR name.
@@ -171,7 +171,7 @@ typedef struct {
  * \retval RR descriptor for given name, NULL descriptor if
  *         unknown type.
  */
-const rdata_descriptor_t *knot_get_rdata_descriptor(const uint16_t type);
+const knot_rdata_descriptor_t *knot_get_rdata_descriptor(const uint16_t type);
 
 /*!
  * \brief Gets rdata descriptor for given RR name (obsolete version).
@@ -181,7 +181,7 @@ const rdata_descriptor_t *knot_get_rdata_descriptor(const uint16_t type);
  * \retval RR descriptor for given name, NULL descriptor if
  *         unknown type.
  */
-const rdata_descriptor_t *knot_get_obsolete_rdata_descriptor(const uint16_t type);
+const knot_rdata_descriptor_t *knot_get_obsolete_rdata_descriptor(const uint16_t type);
 
 /*!
  * \brief Converts numeric type representation to mnemonic string.
diff --git a/src/libknot/dname.c b/src/libknot/dname.c
index 9dc4105c9d645449aecb139635a05d33bec93485..539a5f3ee0c031f95037d7e6ecf33cf69d1c3c7e 100644
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -21,18 +21,21 @@
 #include <ctype.h>
 #include <inttypes.h>
 
-#include "libknot/common.h"
-#include "libknot/mempattern.h"
 #include "libknot/dname.h"
+
+#include "common/macros.h"
+#include "common/mempattern.h"
+#include "common/debug.h"
+
 #include "libknot/consts.h"
+#include "libknot/errcode.h"
 #include "libknot/util/tolower.h"
-#include "common/debug.h"
 #include "libknot/util/utils.h"
 #include "libknot/packet/wire.h"
 
 /*----------------------------------------------------------------------------*/
 
-static int knot_label_is_equal(const uint8_t *lb1, const uint8_t *lb2)
+static int label_is_equal(const uint8_t *lb1, const uint8_t *lb2)
 {
 	return (*lb1 == *lb2) && memcmp(lb1 + 1, lb2 + 1, *lb1) == 0;
 }
@@ -40,7 +43,7 @@ static int knot_label_is_equal(const uint8_t *lb1, const uint8_t *lb2)
 /*----------------------------------------------------------------------------*/
 /* API functions                                                              */
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp,
                           const uint8_t *pkt)
 {
@@ -100,7 +103,7 @@ int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 knot_dname_t *knot_dname_parse(const uint8_t *pkt, size_t *pos, size_t maxpos,
                                mm_ctx_t *mm)
 {
@@ -136,7 +139,7 @@ knot_dname_t *knot_dname_parse(const uint8_t *pkt, size_t *pos, size_t maxpos,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 knot_dname_t *knot_dname_copy(const knot_dname_t *name, mm_ctx_t *mm)
 {
 	if (name == NULL)
@@ -146,7 +149,7 @@ knot_dname_t *knot_dname_copy(const knot_dname_t *name, mm_ctx_t *mm)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 knot_dname_t *knot_dname_copy_part(const knot_dname_t *name, unsigned len,
                                    mm_ctx_t *mm)
 {
@@ -163,7 +166,7 @@ knot_dname_t *knot_dname_copy_part(const knot_dname_t *name, unsigned len,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_to_wire(uint8_t *dst, const knot_dname_t *src, size_t maxlen)
 {
 	if (dst == NULL || src == NULL) {
@@ -180,7 +183,7 @@ int knot_dname_to_wire(uint8_t *dst, const knot_dname_t *src, size_t maxlen)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_unpack(uint8_t* dst, const knot_dname_t *src,
                       size_t maxlen, const uint8_t *pkt)
 {
@@ -210,7 +213,7 @@ int knot_dname_unpack(uint8_t* dst, const knot_dname_t *src,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 char *knot_dname_to_str(char *dst, const knot_dname_t *name, size_t maxlen)
 {
 	if (name == NULL) {
@@ -236,7 +239,7 @@ char *knot_dname_to_str(char *dst, const knot_dname_t *name, size_t maxlen)
 	uint8_t label_len = 0;
 	size_t  str_len = 0;
 
-	for (uint i = 0; i < dname_size; i++) {
+	for (unsigned i = 0; i < dname_size; i++) {
 		uint8_t c = name[i];
 
 		/* Read next label size. */
@@ -317,7 +320,7 @@ char *knot_dname_to_str(char *dst, const knot_dname_t *name, size_t maxlen)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 knot_dname_t *knot_dname_from_str(uint8_t *dst, const char *name, size_t maxlen)
 {
 	if (name == NULL) {
@@ -458,7 +461,7 @@ dname_from_str_failed:
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_to_lower(knot_dname_t *name)
 {
 	if (name == NULL)
@@ -478,7 +481,7 @@ int knot_dname_to_lower(knot_dname_t *name)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_size(const knot_dname_t *name)
 {
 	if (name == NULL)
@@ -500,14 +503,14 @@ int knot_dname_size(const knot_dname_t *name)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_realsize(const knot_dname_t *name, const uint8_t *pkt)
 {
 	return knot_dname_prefixlen(name, KNOT_DNAME_MAXLABELS, pkt);
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_dname_is_sub(const knot_dname_t *sub, const knot_dname_t *domain)
 {
 	if (sub == domain)
@@ -534,7 +537,7 @@ bool knot_dname_is_sub(const knot_dname_t *sub, const knot_dname_t *domain)
 	/* Compare common suffix. */
 	while(common > 0) {
 		/* Compare label. */
-		if (!knot_label_is_equal(sub, domain))
+		if (!label_is_equal(sub, domain))
 			return false;
 		/* Next label. */
 		sub = knot_wire_next_label(sub, NULL);
@@ -545,14 +548,14 @@ bool knot_dname_is_sub(const knot_dname_t *sub, const knot_dname_t *domain)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_dname_in(const knot_dname_t *domain, const knot_dname_t *sub)
 {
 	return knot_dname_is_equal(domain, sub) || knot_dname_is_sub(sub, domain);
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_dname_is_wildcard(const knot_dname_t *name)
 {
 	assert(name != NULL);
@@ -560,7 +563,7 @@ bool knot_dname_is_wildcard(const knot_dname_t *name)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2)
 {
 	if (d1 == NULL || d2 == NULL)
@@ -582,7 +585,7 @@ int knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2)
 	/* Count longest chain leading to root label. */
 	int matched = 0;
 	while (common > 0) {
-		if (knot_label_is_equal(d1, d2))
+		if (label_is_equal(d1, d2))
 			++matched;
 		else
 			matched = 0; /* Broken chain. */
@@ -597,9 +600,9 @@ int knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned labels,
-                                        const knot_dname_t *suffix)
+					const knot_dname_t *suffix)
 {
 	if (name == NULL)
 		return NULL;
@@ -641,7 +644,7 @@ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned label
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 void knot_dname_free(knot_dname_t **name, mm_ctx_t *mm)
 {
 	if (name == NULL || *name == NULL)
@@ -652,14 +655,14 @@ void knot_dname_free(knot_dname_t **name, mm_ctx_t *mm)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_cmp(const knot_dname_t *d1, const knot_dname_t *d2)
 {
 	return knot_dname_cmp_wire(d1, d2, NULL);
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_cmp_wire(const knot_dname_t *d1, const knot_dname_t *d2,
                         const uint8_t *pkt)
 {
@@ -690,11 +693,11 @@ int knot_dname_cmp_wire(const knot_dname_t *d1, const knot_dname_t *d2,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_dname_is_equal(const knot_dname_t *d1, const knot_dname_t *d2)
 {
 	while(*d1 != '\0' || *d2 != '\0') {
-		if (knot_label_is_equal(d1, d2)) {
+		if (label_is_equal(d1, d2)) {
 			d1 = knot_wire_next_label(d1, NULL);
 			d2 = knot_wire_next_label(d2, NULL);
 		} else {
@@ -706,7 +709,7 @@ bool knot_dname_is_equal(const knot_dname_t *d1, const knot_dname_t *d2)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2)
 {
 	if (d1 == NULL || d2 == NULL)
@@ -723,7 +726,7 @@ knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_prefixlen(const uint8_t *name, unsigned nlabels, const uint8_t *pkt)
 {
 	if (name == NULL)
@@ -748,7 +751,7 @@ int knot_dname_prefixlen(const uint8_t *name, unsigned nlabels, const uint8_t *p
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_labels(const uint8_t *name, const uint8_t *pkt)
 {
 	if (name == NULL)
@@ -765,7 +768,7 @@ int knot_dname_labels(const uint8_t *name, const uint8_t *pkt)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_align(const uint8_t **d1, uint8_t d1_labels,
                      const uint8_t **d2, uint8_t d2_labels,
                      uint8_t *wire)
@@ -783,7 +786,7 @@ int knot_dname_align(const uint8_t **d1, uint8_t d1_labels,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_dname_lf(uint8_t *dst, const knot_dname_t *src, const uint8_t *pkt)
 {
 	if (dst == NULL || src == NULL)
diff --git a/src/libknot/dname.h b/src/libknot/dname.h
index db7af67c6bd21a6d6191659f81a8aee5b793f543..315aa6ecea4f756bad8917c7cfdf58661193f89f 100644
--- a/src/libknot/dname.h
+++ b/src/libknot/dname.h
@@ -31,9 +31,11 @@
 #include <stdio.h>
 #include <stdbool.h>
 
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
+
 #include "libknot/consts.h"
 
+/*! \brief Type representing a domain name in wire format. */
 typedef uint8_t knot_dname_t;
 
 /*!
@@ -82,7 +84,8 @@ knot_dname_t *knot_dname_copy(const knot_dname_t *name, mm_ctx_t *mm);
  *
  * \return New domain name which is an partial copy of \a dname.
  */
-knot_dname_t *knot_dname_copy_part(const knot_dname_t *name, unsigned len, mm_ctx_t *mm);
+knot_dname_t *knot_dname_copy_part(const knot_dname_t *name, unsigned len,
+				   mm_ctx_t *mm);
 
 /*!
  * \brief Copy name to wire as is, no compression pointer expansion will be done.
@@ -254,8 +257,7 @@ int knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2);
  * \return New domain name created by replacing suffix of \a dname of size
  *         \a size with \a suffix.
  */
-knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name,
-                                        unsigned labels,
+knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned labels,
                                         const knot_dname_t *suffix);
 
 /*!
diff --git a/src/libknot/dnssec/bitmap.h b/src/libknot/dnssec/bitmap.h
index 12703ec57c85e98f1ca32eb524a2f3f9c6ab3582..1be625167d2d6197f86cc63203de68acbc08728f 100644
--- a/src/libknot/dnssec/bitmap.h
+++ b/src/libknot/dnssec/bitmap.h
@@ -30,16 +30,16 @@
 #include <string.h>
 #include <limits.h>
 
-#define BITMAP_WINDOW_SIZE 256
-#define BITMAP_WINDOW_BYTES (BITMAP_WINDOW_SIZE/CHAR_BIT)
-#define BITMAP_WINDOW_COUNT 256
+#define KNOT_BITMAP_WINDOW_SIZE 256
+#define KNOT_BITMAP_WINDOW_BYTES (KNOT_BITMAP_WINDOW_SIZE/CHAR_BIT)
+#define KNOT_BITMAP_WINDOW_COUNT 256
 
 /*!
  * \brief One window of a bitmap.
  */
 typedef struct {
 	uint8_t used;
-	uint8_t data[BITMAP_WINDOW_BYTES];
+	uint8_t data[KNOT_BITMAP_WINDOW_BYTES];
 } bitmap_window_t;
 
 /*!
@@ -47,16 +47,16 @@ typedef struct {
  */
 typedef struct {
 	int used;
-	bitmap_window_t windows[BITMAP_WINDOW_COUNT];
+	bitmap_window_t windows[KNOT_BITMAP_WINDOW_COUNT];
 } bitmap_t;
 
 /*!
  * \brief Add one RR type into the bitmap.
  */
-inline static void bitmap_add_type(bitmap_t *bitmap, uint16_t type)
+inline static void knot_bitmap_add_type(bitmap_t *bitmap, uint16_t type)
 {
-	int win = type / BITMAP_WINDOW_SIZE;
-	int bit = type % BITMAP_WINDOW_SIZE;
+	int win = type / KNOT_BITMAP_WINDOW_SIZE;
+	int bit = type % KNOT_BITMAP_WINDOW_SIZE;
 
 	if (bitmap->used <= win) {
 		bitmap->used = win + 1;
@@ -75,7 +75,7 @@ inline static void bitmap_add_type(bitmap_t *bitmap, uint16_t type)
 /*!
  * \brief Compute the size of the bitmap in NSEC RDATA format.
  */
-inline static size_t bitmap_size(const bitmap_t *bitmap)
+inline static size_t knot_bitmap_size(const bitmap_t *bitmap)
 {
 	size_t result = 0;
 
@@ -94,7 +94,7 @@ inline static size_t bitmap_size(const bitmap_t *bitmap)
 /*!
  * \brief Write bitmap in NSEC RDATA format.
  */
-inline static void bitmap_write(const bitmap_t *bitmap, uint8_t *output)
+inline static void knot_bitmap_write(const bitmap_t *bitmap, uint8_t *output)
 {
 	uint8_t *write_ptr = output;
 	for (int win = 0; win < bitmap->used; win++) {
diff --git a/src/libknot/dnssec/crypto.c b/src/libknot/dnssec/crypto.c
index 8c080dc025c393ec7dade6cac2ff231a8cf8884c..611dc8e1a3c9b23d921d0e5196e6deae96c7bf7a 100644
--- a/src/libknot/dnssec/crypto.c
+++ b/src/libknot/dnssec/crypto.c
@@ -21,7 +21,7 @@
 #include <openssl/evp.h>
 #include <pthread.h>
 
-#include "libknot/common.h"
+#include "common/macros.h"
 #include "libknot/dnssec/config.h"
 #include "libknot/dnssec/crypto.h"
 
@@ -160,12 +160,13 @@ static void deinit_gost_engine(void)
 #endif
 
 /*- public API --------------------------------------------------------------*/
-
+_public_
 void knot_crypto_init(void)
 {
 	OpenSSL_add_all_digests();
 }
 
+_public_
 void knot_crypto_cleanup(void)
 {
 	knot_crypto_unload_engines();
@@ -177,11 +178,13 @@ void knot_crypto_cleanup(void)
 	knot_crypto_cleanup_thread();
 }
 
+_public_
 void knot_crypto_cleanup_thread(void)
 {
 	ERR_remove_state(0);
 }
 
+_public_
 void knot_crypto_init_threads(void)
 {
 	// locking
@@ -197,6 +200,7 @@ void knot_crypto_init_threads(void)
 #endif
 }
 
+_public_
 void knot_crypto_cleanup_threads(void)
 {
 	if (openssl_mutex) {
@@ -204,6 +208,7 @@ void knot_crypto_cleanup_threads(void)
 	}
 }
 
+_public_
 void knot_crypto_load_engines(void)
 {
 #if KNOT_ENABLE_GOST
@@ -213,6 +218,7 @@ void knot_crypto_load_engines(void)
 #endif
 }
 
+_public_
 void knot_crypto_unload_engines(void)
 {
 #if KNOT_ENABLE_GOST
diff --git a/src/libknot/dnssec/key.c b/src/libknot/dnssec/key.c
index 2b9cce3102257bec449d69ca3f725d334675bc50..78712af27aa87582a99b85f077198b53d19b4de4 100644
--- a/src/libknot/dnssec/key.c
+++ b/src/libknot/dnssec/key.c
@@ -26,15 +26,19 @@
 #include <string.h>
 #include <time.h>
 
-#include "libknot/descriptor.h"
+#include "libknot/dnssec/key.h"
+
 #include "common/getline.h"
+#include "common/macros.h"
+
+#include "zscanner/scanner.h"		// TODO: remove dependency!!
+
+#include "libknot/descriptor.h"
+#include "libknot/errcode.h"
 #include "libknot/binary.h"
-#include "libknot/common.h"
 #include "libknot/dname.h"
-#include "libknot/dnssec/key.h"
 #include "libknot/dnssec/sig0.h"
 #include "libknot/rrtype/tsig.h"
-#include "zscanner/scanner.h"
 
 /*!
  * \brief Calculates keytag for RSA/MD5 algorithm.
@@ -50,9 +54,7 @@ static uint16_t keytag_rsa_md5(const uint8_t *rdata, uint16_t rdata_len)
 	return ac;
 }
 
-/*!
- * \brief Calculates keytag from key wire.
- */
+_public_
 uint16_t knot_keytag(const uint8_t *rdata, uint16_t rdata_len)
 {
 	if (!rdata || rdata_len < 4) {
@@ -349,9 +351,7 @@ static int parse_keyfile_line(knot_key_params_t *key_params,
 	return KNOT_EOK;
 }
 
-/*!
- * \brief Reads the key file and extracts key parameters.
- */
+_public_
 int knot_load_key_params(const char *filename, knot_key_params_t *key_params)
 {
 	if (!filename || !key_params) {
@@ -411,6 +411,7 @@ int knot_load_key_params(const char *filename, knot_key_params_t *key_params)
 	return result;
 }
 
+_public_
 int knot_copy_key_params(const knot_key_params_t *src, knot_key_params_t *dst)
 {
 	if (src == NULL || dst == NULL) {
@@ -456,9 +457,7 @@ int knot_copy_key_params(const knot_key_params_t *src, knot_key_params_t *dst)
 	return KNOT_EOK;
 }
 
-/*!
- * \brief Frees the key parameters.
- */
+_public_
 int knot_free_key_params(knot_key_params_t *key_params)
 {
 	if (!key_params) {
@@ -492,9 +491,7 @@ int knot_free_key_params(knot_key_params_t *key_params)
 	return KNOT_EOK;
 }
 
-/*!
- * \brief Get the type of the key.
- */
+_public_
 knot_key_type_t knot_get_key_type(const knot_key_params_t *key_params)
 {
 	if (!key_params) {
@@ -517,9 +514,7 @@ knot_key_type_t knot_get_key_type(const knot_key_params_t *key_params)
 	return KNOT_KEY_UNKNOWN;
 }
 
-/*!
- * \brief Creates TSIG key.
- */
+_public_
 int knot_tsig_create_key(const char *name, int algorithm,
                          const char *b64secret, knot_tsig_key_t *key)
 {
@@ -547,9 +542,7 @@ int knot_tsig_create_key(const char *name, int algorithm,
 	return KNOT_EOK;
 }
 
-/*!
- * \brief Creates TSIG key from key parameters.
- */
+_public_
 int knot_tsig_key_from_params(const knot_key_params_t *params,
                               knot_tsig_key_t *key)
 {
@@ -569,9 +562,7 @@ int knot_tsig_key_from_params(const knot_key_params_t *params,
 	return KNOT_EOK;
 }
 
-/*!
- * \brief Frees TSIG key.
- */
+_public_
 int knot_tsig_key_free(knot_tsig_key_t *key)
 {
 	if (!key) {
diff --git a/src/libknot/dnssec/key.h b/src/libknot/dnssec/key.h
index 87c160cce972b85f6af1417720f61d38ac31432f..0bd7b71eccf8b4b7f3538dd02171e2a0e615f794 100644
--- a/src/libknot/dnssec/key.h
+++ b/src/libknot/dnssec/key.h
@@ -28,6 +28,7 @@
 
 #include <stdint.h>
 #include <time.h>
+
 #include "libknot/dname.h"
 #include "libknot/binary.h"
 #include "libknot/rrtype/tsig.h"
diff --git a/src/libknot/dnssec/policy.c b/src/libknot/dnssec/policy.c
index db3f3606b8a280dace28773048e289f19646ab4a..943894d7cbb3a3119b9a8ef17c9d7ec2bea64dea 100644
--- a/src/libknot/dnssec/policy.c
+++ b/src/libknot/dnssec/policy.c
@@ -19,7 +19,9 @@
 #include <time.h>
 
 #include "libknot/dnssec/policy.h"
+#include "common/macros.h"
 
+_public_
 uint32_t knot_dnssec_policy_refresh_time(const knot_dnssec_policy_t *policy,
                                          uint32_t earliest_expiration)
 {
@@ -35,6 +37,7 @@ uint32_t knot_dnssec_policy_refresh_time(const knot_dnssec_policy_t *policy,
 	return earliest_expiration - signature_safety;
 }
 
+_public_
 void knot_dnssec_policy_set_sign_lifetime(knot_dnssec_policy_t *policy,
                                           uint32_t sign_lifetime)
 {
@@ -49,6 +52,7 @@ void knot_dnssec_policy_set_sign_lifetime(knot_dnssec_policy_t *policy,
 	                                                         max_expiration);
 }
 
+_public_
 void knot_dnssec_init_default_policy(knot_dnssec_policy_t *policy)
 {
 	if (policy == NULL) {
diff --git a/src/libknot/dnssec/random.h b/src/libknot/dnssec/random.h
index 1b704b2a203bbbfaf11b2b9a2f92caf86f4ceacf..8b0fd4ceea008659ab92d314b5a4c2590f0d5135 100644
--- a/src/libknot/dnssec/random.h
+++ b/src/libknot/dnssec/random.h
@@ -29,6 +29,7 @@
 #include <assert.h>
 #include <openssl/rand.h>
 #include <stdint.h>
+
 #include "libknot/errcode.h"
 
 /*!
diff --git a/src/libknot/dnssec/rrset-sign.c b/src/libknot/dnssec/rrset-sign.c
index 221c63d3bb15ff294b74feb70e5cf5bb56bf0eb0..567f222156aba88594ebef887547c9fe9b3d5183 100644
--- a/src/libknot/dnssec/rrset-sign.c
+++ b/src/libknot/dnssec/rrset-sign.c
@@ -18,25 +18,25 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include "libknot/common.h"
+
+#include "libknot/dnssec/rrset-sign.h"
+
 #include "libknot/descriptor.h"
 #include "libknot/dnssec/key.h"
 #include "libknot/dnssec/policy.h"
-#include "libknot/dnssec/rrset-sign.h"
 #include "libknot/dnssec/sign.h"
 #include "libknot/errcode.h"
 #include "libknot/packet/wire.h"
 #include "libknot/rrset.h"
 #include "libknot/rrtype/rrsig.h"
 #include "libknot/packet/rrset-wire.h"
+#include "common/macros.h"
 
 #define RRSIG_RDATA_SIGNER_OFFSET 18
 
 /*- Creating of RRSIGs -------------------------------------------------------*/
 
-/*!
- * \brief Get size of RRSIG RDATA for a given key.
- */
+_public_
 size_t knot_rrsig_rdata_size(const knot_dnssec_key_t *key)
 {
 	if (!key) {
@@ -66,9 +66,7 @@ size_t knot_rrsig_rdata_size(const knot_dnssec_key_t *key)
 	return size;
 }
 
-/*!
- * \brief Write RRSIG RDATA except signature.
- */
+_public_
 int knot_rrsig_write_rdata(uint8_t *rdata, const knot_dnssec_key_t *key,
                            uint16_t covered_type, uint8_t owner_labels,
                            uint32_t owner_ttl,  uint32_t sig_incepted,
@@ -256,9 +254,7 @@ static int rrsigs_create_rdata(knot_rrset_t *rrsigs,
 	                            knot_rdata_ttl(covered_data), NULL);
 }
 
-/*!
- * \brief Create RRSIG RR for given RR set.
- */
+_public_
 int knot_sign_rrset(knot_rrset_t *rrsigs, const knot_rrset_t *covered,
                     const knot_dnssec_key_t *key,
                     knot_dnssec_sign_context_t *sign_ctx,
@@ -278,6 +274,7 @@ int knot_sign_rrset(knot_rrset_t *rrsigs, const knot_rrset_t *covered,
 	                           sig_expire);
 }
 
+_public_
 int knot_synth_rrsig(uint16_t type, const knot_rdataset_t *rrsig_rrs,
                      knot_rdataset_t *out_sig, mm_ctx_t *mm)
 {
@@ -326,9 +323,7 @@ static bool is_expired_signature(const knot_rrset_t *rrsigs, size_t pos,
 	return (expiration <= policy->refresh_before);
 }
 
-/*!
- * \brief Check if RRSIG signature is valid.
- */
+_public_
 int knot_is_valid_signature(const knot_rrset_t *covered,
                             const knot_rrset_t *rrsigs, size_t pos,
                             const knot_dnssec_key_t *key,
diff --git a/src/libknot/dnssec/rrset-sign.h b/src/libknot/dnssec/rrset-sign.h
index 5aa1f4bb73e122e70c34e06b5ad62c8b3a4b1781..c3abc492ea795bf74a3a4bfea6834e26394f8a19 100644
--- a/src/libknot/dnssec/rrset-sign.h
+++ b/src/libknot/dnssec/rrset-sign.h
@@ -29,6 +29,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
+
 #include "libknot/dnssec/policy.h"
 #include "libknot/dnssec/sign.h"
 #include "libknot/rrset.h"
diff --git a/src/libknot/dnssec/sig0.c b/src/libknot/dnssec/sig0.c
index c6ead6f14b9bc3b0f89a57e2d998ae5e224e30b3..2a59ec2f9cf284cd3bc09e056ad748da613ddccb 100644
--- a/src/libknot/dnssec/sig0.c
+++ b/src/libknot/dnssec/sig0.c
@@ -16,13 +16,16 @@
 
 #include <assert.h>
 #include <time.h>
+
+#include "libknot/dnssec/sig0.h"
+
 #include "libknot/errcode.h"
 #include "libknot/descriptor.h"
 #include "libknot/dnssec/rrset-sign.h"
-#include "libknot/dnssec/sig0.h"
 #include "libknot/dnssec/sign.h"
 #include "libknot/packet/wire.h"
 #include "libknot/packet/rrset-wire.h"
+#include "common/macros.h"
 
 /*!
  * \brief Lifetime fudge of the SIG(0) packets in seconds.
@@ -123,9 +126,7 @@ static int sig0_write_signature(uint8_t* wire, size_t request_size,
 
 /*- SIG(0) public ------------------------------------------------------------*/
 
-/*!
- * \brief Sign a packet using SIG(0) mechanism.
- */
+_public_
 int knot_sig0_sign(uint8_t *wire, size_t *wire_size, size_t wire_max_size,
                    knot_dnssec_key_t *key)
 {
diff --git a/src/libknot/dnssec/sign.c b/src/libknot/dnssec/sign.c
index ccf978d30ea2f78987351ac4e4f96ecdc37a8d2b..99704bbaf80fe2aa5230b3b584d98920886f2aac 100644
--- a/src/libknot/dnssec/sign.c
+++ b/src/libknot/dnssec/sign.c
@@ -22,12 +22,12 @@
 #include <pthread.h>
 #include "libknot/descriptor.h"
 #include "libknot/errcode.h"
-#include "libknot/common.h"
 #include "libknot/consts.h"
 #include "libknot/dnssec/config.h"
 #include "libknot/dnssec/crypto.h"
 #include "libknot/dnssec/key.h"
 #include "libknot/dnssec/sign.h"
+#include "common/macros.h"
 
 #ifdef KNOT_ENABLE_ECDSA
 #include <openssl/ecdsa.h>
@@ -41,13 +41,13 @@
 struct algorithm_functions;
 typedef struct algorithm_functions algorithm_functions_t;
 
-//! \brief Algorithm private key data and algorithm implementation.
+/*! \brief Algorithm private key data and algorithm implementation. */
 struct knot_dnssec_key_data {
 	const algorithm_functions_t *functions; //!< Implementation specific.
 	EVP_PKEY *private_key;                  //!< Private key.
 };
 
-//! \brief DNSSEC signature contextual data.
+/*! \brief DNSSEC signature contextual data. */
 struct knot_dnssec_sign_context {
 	const knot_dnssec_key_t *key; //!< Associated key.
 	EVP_MD_CTX *digest_context;   //!< Digest computation context.
@@ -57,21 +57,21 @@ struct knot_dnssec_sign_context {
  * \brief Algorithm implementation specific functions.
  */
 struct algorithm_functions {
-	//! \brief Callback: function called before creating any keys/contexts
+	/*! \brief Callback: function called before creating any keys/contexts */
 	int (*algorithm_init)(void);
-	//! \brief Callback: create private key from key parameters.
+	/*! \brief Callback: create private key from key parameters. */
 	int (*create_pkey)(const knot_key_params_t *, EVP_PKEY *);
-	//! \brief Callback: get signature size in bytes.
+	/*! \brief Callback: get signature size in bytes. */
 	size_t (*sign_size)(const knot_dnssec_key_t *);
-	//! \brief Callback: cover supplied data with the signature.
+	/*! \brief Callback: cover supplied data with the signature. */
 	int (*sign_add)(const knot_dnssec_sign_context_t *, const uint8_t *, size_t);
-	//! \brief Callback: finish the signing and write out the signature.
+	/*! \brief Callback: finish the signing and write out the signature. */
 	int (*sign_write)(const knot_dnssec_sign_context_t *, uint8_t *, size_t);
-	//! \brief Callback: finish the signing and validate the signature.
+	/*! \brief Callback: finish the signing and validate the signature. */
 	int (*sign_verify)(const knot_dnssec_sign_context_t *, const uint8_t *, size_t);
 };
 
-/**
+/*!
  * \brief Convert binary data to OpenSSL BIGNUM format.
  */
 static BIGNUM *binary_to_bn(const knot_binary_t *bin)
@@ -1106,9 +1106,7 @@ static int init_algorithm_data(const knot_key_params_t *params,
 
 /*- Public init/clean functions ----------------------------------------------*/
 
-/*!
- * \brief Fill DNSSEC key structure according to key parameters.
- */
+_public_
 int knot_dnssec_key_from_params(const knot_key_params_t *params,
                                 knot_dnssec_key_t *key)
 {
@@ -1153,9 +1151,7 @@ int knot_dnssec_key_from_params(const knot_key_params_t *params,
 	return KNOT_EOK;
 }
 
-/*!
- * \brief Free DNSSEC key structure content.
- */
+_public_
 int knot_dnssec_key_free(knot_dnssec_key_t *key)
 {
 	if (!key) {
@@ -1178,9 +1174,7 @@ int knot_dnssec_key_free(knot_dnssec_key_t *key)
 
 /*- Public low level signing interface ---------------------------------------*/
 
-/*!
- * \brief Initialize DNSSEC signing context.
- */
+_public_
 knot_dnssec_sign_context_t *knot_dnssec_sign_init(const knot_dnssec_key_t *key)
 {
 	if (!key) {
@@ -1202,9 +1196,7 @@ knot_dnssec_sign_context_t *knot_dnssec_sign_init(const knot_dnssec_key_t *key)
 	return context;
 }
 
-/*!
- * \brief Free DNSSEC signing context.
- */
+_public_
 void knot_dnssec_sign_free(knot_dnssec_sign_context_t *context)
 {
 	if (!context) {
@@ -1216,9 +1208,7 @@ void knot_dnssec_sign_free(knot_dnssec_sign_context_t *context)
 	free(context);
 }
 
-/*!
- * \brief Get DNSSEC signature size.
- */
+_public_
 size_t knot_dnssec_sign_size(const knot_dnssec_key_t *key)
 {
 	if (!key) {
@@ -1228,9 +1218,7 @@ size_t knot_dnssec_sign_size(const knot_dnssec_key_t *key)
 	return key->data->functions->sign_size(key);
 }
 
-/**
- * \brief Clean DNSSEC signing context to start a new signature.
- */
+_public_
 int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context)
 {
 	if (!context) {
@@ -1241,9 +1229,7 @@ int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context)
 	return create_digest_context(context->key, &context->digest_context);
 }
 
-/*!
- * \brief Add data to be covered by DNSSEC signature.
- */
+_public_
 int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context,
                          const uint8_t *data, size_t data_size)
 {
@@ -1254,9 +1240,7 @@ int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context,
 	return context->key->data->functions->sign_add(context, data, data_size);
 }
 
-/**
- * \brief Write down the DNSSEC signature for supplied data.
- */
+_public_
 int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context,
                            uint8_t *signature, size_t signature_size)
 {
@@ -1268,9 +1252,7 @@ int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context,
 	                                                 signature_size);
 }
 
-/**
- * \brief Verify the DNSSEC signature for supplied data.
- */
+_public_
 int knot_dnssec_sign_verify(knot_dnssec_sign_context_t *context,
 			    const uint8_t *signature, size_t signature_size)
 {
diff --git a/src/libknot/errcode.c b/src/libknot/errcode.c
index a85f6a9d05fdc9fca4f01943abeb14851b24ba16..a3a1d9533205a408bee18fb18816596aa24e51e3 100644
--- a/src/libknot/errcode.c
+++ b/src/libknot/errcode.c
@@ -17,9 +17,11 @@
 #include <stdarg.h>
 #include <stdlib.h>
 
-#include "common/errors.h"
 #include "libknot/errcode.h"
 
+#include "common/errors.h"
+#include "common/macros.h"
+
 const error_table_t error_messages[] = {
 	{ KNOT_EOK, "OK" },
 
@@ -120,14 +122,19 @@ const error_table_t error_messages[] = {
 	/* NSEC3 errors. */
 	{ KNOT_NSEC3_ECOMPUTE_HASH, "cannot compute NSEC3 hash" },
 
+	/* Dynamic backend errors. */
+	{ KNOT_DATABASE_ERROR, "unspecified database error" },
+
 	{ KNOT_ERROR, NULL } /* Terminator */
 };
 
+_public_
 const char *knot_strerror(int code)
 {
 	return error_to_str(error_messages, code);
 }
 
+_public_
 int knot_map_errno_internal(int fallback, int arg0, ...)
 {
 	/* Iterate all variable-length arguments. */
diff --git a/src/libknot/errcode.h b/src/libknot/errcode.h
index 88bec58fc42a2ead7846a24488117f5f516d1e11..2b2b1fc5e5b59d831aa89203f6e7b1d7c6ccc30a 100644
--- a/src/libknot/errcode.h
+++ b/src/libknot/errcode.h
@@ -134,7 +134,10 @@ enum knot_error {
 	KNOT_DNSSEC_EMISSINGKEYTYPE,
 
 	/* NSEC3 errors. */
-	KNOT_NSEC3_ECOMPUTE_HASH
+	KNOT_NSEC3_ECOMPUTE_HASH,
+
+	/* Database backend. */
+	KNOT_DATABASE_ERROR
 };
 
 /*!
@@ -161,7 +164,7 @@ int knot_map_errno_internal(int fallback, int arg0, ...);
 /*!
  * \brief Map POSIX errno to Knot error code.
  *
- * KNOT_ERRNO is used as a fallback error, the list is terminated implicitly.
+ * KNOT_ERROR is used as a fallback error, the list is terminated implicitly.
  */
 #define knot_map_errno(errors...) knot_map_errno_internal(KNOT_ERROR, errors, 0)
 
diff --git a/src/libknot/libknot.h b/src/libknot/libknot.h
index f059ae635a9904cf02d61134545bb676aa893b72..b8192bdd8e7a28e3fef495906603d734b5b4e7a9 100644
--- a/src/libknot/libknot.h
+++ b/src/libknot/libknot.h
@@ -30,7 +30,6 @@
 #include "libknot/dname.h"
 #include "libknot/descriptor.h"
 #include "libknot/errcode.h"
-#include "libknot/mempattern.h"
 #include "libknot/rrtype/opt.h"
 #include "libknot/packet/wire.h"
 #include "libknot/packet/compr.h"
diff --git a/src/libknot/packet/compr.c b/src/libknot/packet/compr.c
index c24f89f260cd5738c048bdda6242cfd5a4b361ed..8a41cb57454f91d79c77ec08d3b6b16abc1e8363 100644
--- a/src/libknot/packet/compr.c
+++ b/src/libknot/packet/compr.c
@@ -20,6 +20,8 @@
 
 #include "common/debug.h"
 #include "common/log.h"
+#include "common/macros.h"
+
 #include "libknot/errcode.h"
 #include "libknot/packet/pkt.h"
 #include "libknot/util/tolower.h"
@@ -33,14 +35,14 @@ static bool compr_label_match(const uint8_t *n, const uint8_t *p)
 	if (*n != *p) {
 		return false;
 	}
-	
+
 	uint8_t len = *n;
 	for (uint8_t i = 0; i < len; ++i) {
 		if (knot_tolower(n[1 + i]) != knot_tolower(p[1 + i])) {
 			return false;
 		}
 	}
-	
+
 	return true;
 }
 
@@ -53,6 +55,7 @@ static bool compr_label_match(const uint8_t *n, const uint8_t *p)
 		written += (len); \
 	}
 
+_public_
 int knot_compr_put_dname(const knot_dname_t *dname, uint8_t *dst, uint16_t max,
                          knot_compr_t *compr)
 {
diff --git a/src/libknot/packet/compr.h b/src/libknot/packet/compr.h
index 13a7162660fbe89e3e3d0d963ddfbe15399dc65a..32cc9da1abcef3f4a517393ba218a55c027dae5e 100644
--- a/src/libknot/packet/compr.h
+++ b/src/libknot/packet/compr.h
@@ -32,16 +32,16 @@
 
 /*! \brief Compression hint type. */
 enum knot_compr_hint {
-	COMPR_HINT_NONE    = 0, /* No hint. */
-	COMPR_HINT_NOCOMP  = 1, /* Don't compress. */
-	COMPR_HINT_QNAME   = KNOT_WIRE_HEADER_SIZE /* Name is QNAME. */
+	KNOT_COMPR_HINT_NONE    = 0, /* No hint. */
+	KNOT_COMPR_HINT_NOCOMP  = 1, /* Don't compress. */
+	KNOT_COMPR_HINT_QNAME   = KNOT_WIRE_HEADER_SIZE /* Name is QNAME. */
 };
 
 /*! \brief Compression hint array offsets. */
 enum knot_compr_offset {
-	COMPR_HINT_OWNER = 0,  /* First element in the array is RR owner. */
-	COMPR_HINT_RDATA = 1,  /* First name in RDATA is at offset 1. */
-	COMPR_HINT_COUNT = 16  /* Maximum number of stored hints per-RR. */
+	KNOT_COMPR_HINT_OWNER = 0,  /* First element in the array is RR owner. */
+	KNOT_COMPR_HINT_RDATA = 1,  /* First name in RDATA is at offset 1. */
+	KNOT_COMPR_HINT_COUNT = 16  /* Maximum number of stored hints per-RR. */
 };
 
 /*
@@ -61,7 +61,7 @@ enum knot_compr_offset {
 typedef struct {
 	uint16_t pos;   /* RRSet position in the packet. */
 	uint16_t flags; /* RRSet flags. */
-	uint16_t compress_ptr[COMPR_HINT_COUNT]; /* Array of compr. ptr hints. */
+	uint16_t compress_ptr[KNOT_COMPR_HINT_COUNT]; /* Array of compr. ptr hints. */
 } knot_rrinfo_t;
 
 /*!
@@ -88,21 +88,25 @@ typedef struct knot_compr {
 int knot_compr_put_dname(const knot_dname_t *dname, uint8_t *dst, uint16_t max,
                          knot_compr_t *compr);
 
-/*! \brief Retrieve compression hint from given offset. */
+/*! \brief Retrieve compression hint from given offset.
+ *  \todo More detailed documentation.
+ */
 static inline uint16_t knot_pkt_compr_hint(const knot_rrinfo_t *info, uint16_t hint_id)
 {
-	if (hint_id < COMPR_HINT_COUNT) {
+	if (hint_id < KNOT_COMPR_HINT_COUNT) {
 		return info->compress_ptr[hint_id];
 	} else {
-		return COMPR_HINT_NONE;
+		return KNOT_COMPR_HINT_NONE;
 	}
 }
 
-/*! \brief Store compression hint for given offset. */
+/*! \brief Store compression hint for given offset.
+ *  \todo More detailed documentation.
+ */
 static inline void knot_pkt_compr_hint_set(knot_rrinfo_t *info, uint16_t hint_id,
                                            uint16_t val, uint16_t len)
 {
-	if ((hint_id < COMPR_HINT_COUNT) && (val + len < KNOT_WIRE_PTR_MAX)) {
+	if ((hint_id < KNOT_COMPR_HINT_COUNT) && (val + len < KNOT_WIRE_PTR_MAX)) {
 		info->compress_ptr[hint_id] = val;
 	}
 }
diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c
index 9d6e52e9d69dfab2c19d15fc3465f5132eef01b3..d41f626668790c91d8195de0073639c8d80a5ab3 100644
--- a/src/libknot/packet/pkt.c
+++ b/src/libknot/packet/pkt.c
@@ -22,8 +22,10 @@
 
 #include "common/debug.h"
 #include "common/log.h"
-#include "libknot/common.h"
+#include "common/macros.h"
+
 #include "libknot/descriptor.h"
+#include "libknot/errcode.h"
 #include "libknot/packet/wire.h"
 #include "libknot/rrtype/tsig.h"
 #include "libknot/tsig-op.h"
@@ -150,6 +152,15 @@ static int pkt_reset(knot_pkt_t *pkt, void *wire, uint16_t len)
 	return ret;
 }
 
+/*! \brief Reset packet parse state. */
+static int pkt_reset_sections(knot_pkt_t *pkt)
+{
+	pkt->parsed  = 0;
+	pkt->current = KNOT_ANSWER;
+	memset(pkt->sections, 0, sizeof(pkt->sections));
+	return knot_pkt_begin(pkt, KNOT_ANSWER);
+}
+
 /*! \brief Clear packet payload and free allocated data. */
 static void pkt_clear_payload(knot_pkt_t *pkt)
 {
@@ -166,10 +177,8 @@ static void pkt_clear_payload(knot_pkt_t *pkt)
 	/* Free RRSets if applicable. */
 	pkt_free_data(pkt);
 
-	/* Reset section. */
-	pkt->current = KNOT_ANSWER;
-	pkt->sections[pkt->current].rr = pkt->rr;
-	pkt->sections[pkt->current].rrinfo = pkt->rr_info;
+	/* Reset sections. */
+	pkt_reset_sections(pkt);
 }
 
 /*! \brief Allocate new packet using memory context. */
@@ -177,7 +186,7 @@ static knot_pkt_t *pkt_new_mm(void *wire, uint16_t len, mm_ctx_t *mm)
 {
 	assert(mm);
 
-	knot_pkt_t *pkt = mm->alloc(mm->ctx, sizeof(knot_pkt_t));
+	knot_pkt_t *pkt = mm_alloc(mm, sizeof(knot_pkt_t));
 	if (pkt == NULL) {
 		return NULL;
 	}
@@ -186,13 +195,14 @@ static knot_pkt_t *pkt_new_mm(void *wire, uint16_t len, mm_ctx_t *mm)
 	pkt->rrset_count = 0;
 	memcpy(&pkt->mm, mm, sizeof(mm_ctx_t));
 	if (pkt_reset(pkt, wire, len) != KNOT_EOK) {
-		mm->free(pkt);
+		mm_free(mm, pkt);
 		return NULL;
 	}
 
 	return pkt;
 }
 
+_public_
 knot_pkt_t *knot_pkt_new(void *wire, uint16_t len, mm_ctx_t *mm)
 {
 	/* Default memory allocator if NULL. */
@@ -206,6 +216,7 @@ knot_pkt_t *knot_pkt_new(void *wire, uint16_t len, mm_ctx_t *mm)
 	return pkt_new_mm(wire, len, mm);
 }
 
+_public_
 int knot_pkt_copy(knot_pkt_t *dst, const knot_pkt_t *src)
 {
 	dbg_packet("%s(%p, %p)\n", __func__, dst, src);
@@ -233,6 +244,7 @@ int knot_pkt_copy(knot_pkt_t *dst, const knot_pkt_t *src)
 	return knot_pkt_parse(dst, 0);
 }
 
+_public_
 int knot_pkt_init_response(knot_pkt_t *pkt, const knot_pkt_t *query)
 {
 	dbg_packet("%s(%p, %p)\n", __func__, pkt, query);
@@ -263,6 +275,7 @@ int knot_pkt_init_response(knot_pkt_t *pkt, const knot_pkt_t *query)
 	return KNOT_EOK;
 }
 
+_public_
 void knot_pkt_clear(knot_pkt_t *pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -278,6 +291,7 @@ void knot_pkt_clear(knot_pkt_t *pkt)
 	memset(pkt->wire, 0, pkt->size);
 }
 
+_public_
 void knot_pkt_free(knot_pkt_t **pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -298,6 +312,7 @@ void knot_pkt_free(knot_pkt_t **pkt)
 	*pkt = NULL;
 }
 
+_public_
 int knot_pkt_reserve(knot_pkt_t *pkt, uint16_t size)
 {
 	dbg_packet("%s(%p, %hu)\n", __func__, pkt, size);
@@ -314,6 +329,7 @@ int knot_pkt_reserve(knot_pkt_t *pkt, uint16_t size)
 	}
 }
 
+_public_
 int knot_pkt_reclaim(knot_pkt_t *pkt, uint16_t size)
 {
 	dbg_packet("%s(%p, %hu)\n", __func__, pkt, size);
@@ -330,6 +346,7 @@ int knot_pkt_reclaim(knot_pkt_t *pkt, uint16_t size)
 
 }
 
+_public_
 uint16_t knot_pkt_type(const knot_pkt_t *pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -364,7 +381,7 @@ uint16_t knot_pkt_type(const knot_pkt_t *pkt)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 uint16_t knot_pkt_question_size(const knot_pkt_t *pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -376,7 +393,7 @@ uint16_t knot_pkt_question_size(const knot_pkt_t *pkt)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 const knot_dname_t *knot_pkt_qname(const knot_pkt_t *pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -388,7 +405,7 @@ const knot_dname_t *knot_pkt_qname(const knot_pkt_t *pkt)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 uint16_t knot_pkt_qtype(const knot_pkt_t *pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -401,7 +418,7 @@ uint16_t knot_pkt_qtype(const knot_pkt_t *pkt)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 uint16_t knot_pkt_qclass(const knot_pkt_t *pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -413,6 +430,7 @@ uint16_t knot_pkt_qclass(const knot_pkt_t *pkt)
 	return knot_wire_read_u16(pkt->wire + off);
 }
 
+_public_
 int knot_pkt_begin(knot_pkt_t *pkt, knot_section_t section_id)
 {
 	if (pkt == NULL) {
@@ -430,6 +448,7 @@ int knot_pkt_begin(knot_pkt_t *pkt, knot_section_t section_id)
 	return KNOT_EOK;
 }
 
+_public_
 int knot_pkt_put_question(knot_pkt_t *pkt, const knot_dname_t *qname, uint16_t qclass, uint16_t qtype)
 {
 	dbg_packet("%s(%p, %p, %hu, %hu)\n", __func__, pkt, qname, qclass, qtype);
@@ -449,8 +468,9 @@ int knot_pkt_put_question(knot_pkt_t *pkt, const knot_dname_t *qname, uint16_t q
 
 	/* Check size limits. */
 	size_t question_len = 2 * sizeof(uint16_t) + qname_len;
-	if (qname_len < 0 || pkt->size + question_len > pkt->max_size)
+	if (qname_len < 0 || pkt->size + question_len > pkt->max_size) {
 		return KNOT_ESPACE;
+	}
 
 	/* Copy QTYPE & QCLASS */
 	dst += qname_len;
@@ -467,6 +487,7 @@ int knot_pkt_put_question(knot_pkt_t *pkt, const knot_dname_t *qname, uint16_t q
 	return knot_pkt_begin(pkt, KNOT_ANSWER);
 }
 
+_public_
 int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr,
                  uint16_t flags)
 {
@@ -533,7 +554,9 @@ int knot_pkt_put(knot_pkt_t *pkt, uint16_t compr_hint, const knot_rrset_t *rr,
 	return KNOT_EOK;
 }
 
-const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *pkt, knot_section_t section_id)
+_public_
+const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *pkt,
+                                          knot_section_t section_id)
 {
 	dbg_packet("%s(%p, %u)\n", __func__, pkt, section_id);
 	if (pkt == NULL) {
@@ -543,6 +566,7 @@ const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *pkt, knot_section_t
 	return &pkt->sections[section_id];
 }
 
+_public_
 int knot_pkt_parse(knot_pkt_t *pkt, unsigned flags)
 {
 	dbg_packet("%s(%p, %u)\n", __func__, pkt, flags);
@@ -550,6 +574,9 @@ int knot_pkt_parse(knot_pkt_t *pkt, unsigned flags)
 		return KNOT_EINVAL;
 	}
 
+	/* Reset parse state. */
+	pkt_reset_sections(pkt);
+
 	int ret = knot_pkt_parse_question(pkt);
 	if (ret == KNOT_EOK) {
 		ret = knot_pkt_parse_payload(pkt, flags);
@@ -558,6 +585,7 @@ int knot_pkt_parse(knot_pkt_t *pkt, unsigned flags)
 	return ret;
 }
 
+_public_
 int knot_pkt_parse_question(knot_pkt_t *pkt)
 {
 	dbg_packet("%s(%p)\n", __func__, pkt);
@@ -623,19 +651,22 @@ int knot_pkt_parse_question(knot_pkt_t *pkt)
 		(pkt)->var = rr; \
 	}
 
-/*! \brief Check constraints (position, uniqueness, validity) for special types (TSIG, OPT). */
-static int check_rr_constraints(knot_pkt_t *pkt, knot_rrset_t *rr, size_t rr_size, unsigned flags)
+/*! \brief Check constraints (position, uniqueness, validity) for special types
+ *         (TSIG, OPT).
+ */
+static int check_rr_constraints(knot_pkt_t *pkt, knot_rrset_t *rr, size_t rr_size,
+                                unsigned flags)
 {
 	/* Check RR constraints. */
 	switch(rr->type) {
 	case KNOT_RRTYPE_TSIG:
-		CHECK_AR_CONSTRAINTS(pkt, rr, tsig_rr, tsig_rdata_is_ok);
+		CHECK_AR_CONSTRAINTS(pkt, rr, tsig_rr, knot_tsig_rdata_is_ok);
 
 		/* Strip TSIG RR from wireformat and decrease ARCOUNT. */
 		if (!(flags & KNOT_PF_KEEPWIRE)) {
 			pkt->parsed -= rr_size;
 			pkt->size -= rr_size;
-			knot_wire_set_id(pkt->wire, tsig_rdata_orig_id(rr));
+			knot_wire_set_id(pkt->wire, knot_tsig_rdata_orig_id(rr));
 			knot_wire_set_arcount(pkt->wire, knot_wire_get_arcount(pkt->wire) - 1);
 		}
 		break;
@@ -651,6 +682,7 @@ static int check_rr_constraints(knot_pkt_t *pkt, knot_rrset_t *rr, size_t rr_siz
 
 #undef CHECK_AR_RECORD
 
+_public_
 int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags)
 {
 	dbg_packet("%s(%p, %u)\n", __func__, pkt, flags);
@@ -690,6 +722,7 @@ int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags)
 	return check_rr_constraints(pkt, rr, rr_size, flags);
 }
 
+_public_
 int knot_pkt_parse_section(knot_pkt_t *pkt, unsigned flags)
 {
 	dbg_packet("%s(%p, %u)\n", __func__, pkt, flags);
@@ -714,6 +747,7 @@ int knot_pkt_parse_section(knot_pkt_t *pkt, unsigned flags)
 	return KNOT_EOK;
 }
 
+_public_
 int knot_pkt_parse_payload(knot_pkt_t *pkt, unsigned flags)
 {
 	dbg_packet("%s(%p, %u)\n", __func__, pkt, flags);
@@ -760,6 +794,7 @@ int knot_pkt_parse_payload(knot_pkt_t *pkt, unsigned flags)
 	return KNOT_EOK;
 }
 
+_public_
 uint16_t knot_pkt_get_ext_rcode(const knot_pkt_t *pkt)
 {
 	if (pkt == NULL) {
diff --git a/src/libknot/packet/pkt.h b/src/libknot/packet/pkt.h
index f37b0c6149a48a3b4d48c6a62390819897eda2ed..151e7c39798fba1e0af23fb2749275e4b5f937de 100644
--- a/src/libknot/packet/pkt.h
+++ b/src/libknot/packet/pkt.h
@@ -29,12 +29,13 @@
 #include <stdint.h>
 #include <string.h>
 
+#include "common/mempattern.h"
+
 #include "libknot/dname.h"
 #include "libknot/rrset.h"
 #include "libknot/rrtype/opt.h"
 #include "libknot/packet/wire.h"
 #include "libknot/packet/compr.h"
-#include "libknot/mempattern.h"
 
 /* Number of packet sections (ANSWER, AUTHORITY, ADDITIONAL). */
 #define KNOT_PKT_SECTIONS 3
@@ -181,9 +182,16 @@ uint16_t knot_pkt_type(const knot_pkt_t *pkt);
 /*
  * Packet QUESTION accessors.
  */
+/*! \todo Documentation */
 uint16_t knot_pkt_question_size(const knot_pkt_t *pkt);
+
+/*! \todo Documentation */
 const knot_dname_t *knot_pkt_qname(const knot_pkt_t *pkt);
+
+/*! \todo Documentation */
 uint16_t knot_pkt_qtype(const knot_pkt_t *pkt);
+
+/*! \todo Documentation */
 uint16_t knot_pkt_qclass(const knot_pkt_t *pkt);
 
 /*
diff --git a/src/libknot/packet/rrset-wire.c b/src/libknot/packet/rrset-wire.c
index 2e397dd1636f6fd8ec9c82eb15c0347c97bb01f1..dd9aa693b55b2568c3e4dc32ad49cc8ff1e3de16 100644
--- a/src/libknot/packet/rrset-wire.c
+++ b/src/libknot/packet/rrset-wire.c
@@ -21,15 +21,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "libknot/common.h"
+#include "libknot/packet/rrset-wire.h"
+
 #include "libknot/consts.h"
 #include "libknot/descriptor.h"
 #include "libknot/dname.h"
 #include "libknot/packet/pkt.h"
-#include "libknot/packet/rrset-wire.h"
 #include "libknot/packet/wire.h"
 #include "libknot/rrset.h"
 #include "libknot/rrtype/naptr.h"
+#include "common/macros.h"
 
 /*!
  * \brief Get maximal size of a domain name in a wire with given capacity.
@@ -168,7 +169,7 @@ static int write_rdata_block(const uint8_t **src, size_t *src_avail,
  */
 static int rdata_traverse(const uint8_t **src, size_t *src_avail,
                           uint8_t **dst, size_t *dst_avail,
-                          const rdata_descriptor_t *desc,
+                          const knot_rdata_descriptor_t *desc,
                           dname_config_t *dname_cfg)
 {
 	for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
@@ -195,7 +196,7 @@ static int write_owner(const knot_rrset_t *rrset, uint8_t **dst, size_t *dst_ava
 	assert(dst && *dst);
 	assert(dst_avail);
 
-	uint16_t owner_pointer = compr_get_ptr(compr, COMPR_HINT_OWNER);
+	uint16_t owner_pointer = compr_get_ptr(compr, KNOT_COMPR_HINT_OWNER);
 
 	/* Check size */
 
@@ -221,7 +222,7 @@ static int write_owner(const knot_rrset_t *rrset, uint8_t **dst, size_t *dst_ava
 			return written;
 		}
 
-		compr_set_ptr(compr, COMPR_HINT_OWNER, *dst, written);
+		compr_set_ptr(compr, KNOT_COMPR_HINT_OWNER, *dst, written);
 		owner_size = written;
 	}
 
@@ -354,14 +355,14 @@ static int write_rdata(const knot_rrset_t *rrset, uint16_t rrset_index,
 	dname_config_t dname_cfg = {
 		.write_cb = compress_rdata_dname,
 		.compr = compr,
-		.hint = COMPR_HINT_RDATA + rrset_index
+		.hint = KNOT_COMPR_HINT_RDATA + rrset_index
 	};
 
 	const uint8_t *src = knot_rdata_data(rdata);
 	size_t src_avail = knot_rdata_rdlen(rdata);
 	if (src_avail > 0) {
 		/* Only write non-empty data. */
-		const rdata_descriptor_t *desc =
+		const knot_rdata_descriptor_t *desc =
 			knot_get_rdata_descriptor(rrset->type);
 		int ret = rdata_traverse(&src, &src_avail, dst, dst_avail,
 		                         desc, &dname_cfg);
@@ -407,6 +408,7 @@ static int write_rr(const knot_rrset_t *rrset, uint16_t rrset_index,
 /*!
  * \brief Write RR Set content to a wire.
  */
+_public_
 int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, uint16_t max_size,
                        knot_compr_t *compr)
 {
@@ -495,13 +497,13 @@ static int decompress_rdata_dname(const uint8_t **src, size_t *src_avail,
 	if (compr_size <= 0) {
 		return compr_size;
 	}
-	
+
 	int decompr_size = knot_dname_unpack(*dst, *src, *dst_avail,
 	                                     dname_cfg->pkt_wire);
 	if (decompr_size <= 0) {
 		return decompr_size;
 	}
-	
+
 	/* Update buffers */
 	*dst += decompr_size;
 	*dst_avail -= decompr_size;
@@ -512,7 +514,8 @@ static int decompress_rdata_dname(const uint8_t **src, size_t *src_avail,
 	return KNOT_EOK;
 }
 
-static bool allow_zero_rdata(const knot_rrset_t *rr, const rdata_descriptor_t *desc)
+static bool allow_zero_rdata(const knot_rrset_t *rr,
+                             const knot_rdata_descriptor_t *desc)
 {
 	return rr->rclass != KNOT_CLASS_IN ||  // NONE and ANY for DDNS
 	       rr->type == KNOT_RRTYPE_APL ||  // APL RR type
@@ -534,7 +537,7 @@ static int parse_rdata(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
 		return KNOT_EMALF;
 	}
 
-	const rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset->type);
+	const knot_rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset->type);
 	if (desc->type_name == NULL) {
 		desc = knot_get_obsolete_rdata_descriptor(rrset->type);
 	}
@@ -552,7 +555,8 @@ static int parse_rdata(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
 	const uint8_t *src = pkt_wire + *pos;
 	size_t src_avail = rdlength;
 
-	const size_t buffer_size = rdlength + KNOT_MAX_RDATA_DNAMES * KNOT_DNAME_MAXLEN;
+	const size_t buffer_size = rdlength +
+	                           KNOT_MAX_RDATA_DNAMES * KNOT_DNAME_MAXLEN;
 	uint8_t rdata_buffer[buffer_size];
 	uint8_t *dst = rdata_buffer;
 	size_t dst_avail = buffer_size;
@@ -579,21 +583,20 @@ static int parse_rdata(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
 		/* DNAME compression caused RDATA overflow. */
 		return KNOT_EMALF;
 	}
-	
+
 	ret = knot_rrset_add_rdata(rrset, rdata_buffer, written, ttl, mm);
 	if (ret == KNOT_EOK) {
 		/* Update position pointer. */
 		*pos += rdlength;
 	}
-	
+
 	return ret;
 }
 
-/*!
-* \brief Creates one RR from a wire.
- */
+_public_
 int knot_rrset_rr_from_wire(const uint8_t *pkt_wire, size_t *pos,
-                            size_t pkt_size, mm_ctx_t *mm, knot_rrset_t *rrset)
+                            size_t pkt_size, mm_ctx_t *mm,
+                            knot_rrset_t *rrset)
 {
 	if (!pkt_wire || !pos || !rrset || *pos > pkt_size) {
 		return KNOT_EINVAL;
diff --git a/src/libknot/packet/rrset-wire.h b/src/libknot/packet/rrset-wire.h
index 357324bbc8976432d1063898a4b0aec231ec54fb..22680dd5b3ac3e0b0bce5e9812d95351221a014e 100644
--- a/src/libknot/packet/rrset-wire.h
+++ b/src/libknot/packet/rrset-wire.h
@@ -30,7 +30,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
+
 #include "libknot/dname.h"
 #include "libknot/rrset.h"
 
diff --git a/src/libknot/processing/layer.c b/src/libknot/processing/layer.c
new file mode 100644
index 0000000000000000000000000000000000000000..623a76fc4ae76e1213ef28b0945f4ffd5fad73cc
--- /dev/null
+++ b/src/libknot/processing/layer.c
@@ -0,0 +1,91 @@
+/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+
+#include "libknot/processing/layer.h"
+
+#include "common/debug.h"
+#include "common/macros.h"
+
+/*! \brief Helper for conditional layer call. */
+#define LAYER_CALL(layer, func, ...) \
+	assert(layer->api); \
+	if (layer->api->func) { \
+		layer->state = layer->api->func(layer, ##__VA_ARGS__); \
+	}
+
+/* State -> string translation table. */
+#ifdef KNOT_NS_DEBUG
+#define LAYER_STATE_STR(x) _state_table[x]
+static const char* _state_table[] = {
+        [KNOT_NS_PROC_NOOP] = "NOOP",
+        [KNOT_NS_PROC_MORE] = "MORE",
+        [KNOT_NS_PROC_FULL] = "FULL",
+        [KNOT_NS_PROC_DONE] = "DONE",
+        [KNOT_NS_PROC_FAIL] = "FAIL"
+};
+#endif /* KNOT_NS_DEBUG */
+
+_public_
+int knot_layer_begin(knot_layer_t *ctx, const knot_layer_api_t *api, void *param)
+{
+	ctx->api = api;
+
+	LAYER_CALL(ctx, begin, param);
+
+	dbg_ns("%s -> %s\n", __func__, LAYER_STATE_STR(ctx->state));
+	return ctx->state;
+}
+
+_public_
+int knot_layer_reset(knot_layer_t *ctx)
+{
+	LAYER_CALL(ctx, reset);
+	dbg_ns("%s -> %s\n", __func__, LAYER_STATE_STR(ctx->state));
+	return ctx->state;
+}
+
+_public_
+int knot_layer_finish(knot_layer_t *ctx)
+{
+	LAYER_CALL(ctx, finish);
+	dbg_ns("%s -> %s\n", __func__, LAYER_STATE_STR(ctx->state));
+	return ctx->state;
+}
+
+_public_
+int knot_layer_in(knot_layer_t *ctx, knot_pkt_t *pkt)
+{
+	LAYER_CALL(ctx, in, pkt);
+	dbg_ns("%s -> %s\n", __func__, LAYER_STATE_STR(ctx->state));
+	return ctx->state;
+}
+
+_public_
+int knot_layer_out(knot_layer_t *ctx, knot_pkt_t *pkt)
+{
+	switch (ctx->state) {
+	case KNOT_NS_PROC_FAIL: LAYER_CALL(ctx, err, pkt); break;
+	case KNOT_NS_PROC_FULL:
+	default: LAYER_CALL(ctx, out, pkt); break;
+	}
+
+	dbg_ns("%s -> %s\n", __func__, LAYER_STATE_STR(ctx->state));
+	return ctx->state;
+}
+
+#undef LAYER_STATE_STR
diff --git a/src/libknot/processing/process.h b/src/libknot/processing/layer.h
similarity index 50%
rename from src/libknot/processing/process.h
rename to src/libknot/processing/layer.h
index db7fd68f403cdc65d17dca28b182d456e0fc6582..f9b8f16ba20de51acda1ef36625bd6c974af7e48 100644
--- a/src/libknot/processing/process.h
+++ b/src/libknot/processing/layer.h
@@ -14,7 +14,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 /*!
- * \file process.h
+ * \file layer.h
  *
  * \author Marek Vavrusa <marek.vavrusa@nic.cz>
  *
@@ -26,7 +26,9 @@
 
 #include <stdint.h>
 
-#include "libknot/mempattern.h"
+#include "common/lists.h"
+#include "common/mempattern.h"
+
 #include "libknot/consts.h"
 #include "libknot/rrtype/tsig.h"
 #include "libknot/packet/pkt.h"
@@ -36,99 +38,96 @@
  *         and determines readiness for next action.
  */
 
-enum knot_process_state {
-	NS_PROC_NOOP = 0,      /* N/A */
-	NS_PROC_MORE = 1 << 0, /* More input data. */
-	NS_PROC_FULL = 1 << 1, /* Has output data. */
-	NS_PROC_DONE = 1 << 2, /* Finished. */
-	NS_PROC_FAIL = 1 << 3  /* Error. */
+enum knot_layer_state {
+	KNOT_NS_PROC_NOOP = 0,      /* N/A */
+	KNOT_NS_PROC_MORE = 1 << 0, /* More input data. */
+	KNOT_NS_PROC_FULL = 1 << 1, /* Has output data. */
+	KNOT_NS_PROC_DONE = 1 << 2, /* Finished. */
+	KNOT_NS_PROC_FAIL = 1 << 3  /* Error. */
 };
 
 /* Forward declarations. */
-struct knot_process_module;
+struct knot_layer_api;
 
 /*! \brief Packet processing context. */
-typedef struct knot_process_context
+typedef struct knot_layer
 {
-	uint16_t state;  /* Bitmap of enum knot_process_state. */
+	node_t node;
+
+	uint16_t state;  /* Bitmap of enum knot_layer_state. */
 	uint16_t type;   /* Module identifier. */
-	mm_ctx_t mm;     /* Processing memory context. */
+	mm_ctx_t *mm;    /* Processing memory context. */
 
 	/* Module specific. */
 	void *data;
-	const struct knot_process_module *module;
-} knot_process_t;
+	const struct knot_layer_api *api;
+} knot_layer_t;
 
 /*! \brief Packet processing module API. */
-typedef struct knot_process_module {
-	int (*begin)(knot_process_t *ctx, void *module_param);
-	int (*reset)(knot_process_t *ctx);
-	int (*finish)(knot_process_t *ctx);
-	int (*in)(knot_pkt_t *pkt, knot_process_t *ctx);
-	int (*out)(knot_pkt_t *pkt, knot_process_t *ctx);
-	int (*err)(knot_pkt_t *pkt, knot_process_t *ctx);
-} knot_process_module_t;
+typedef struct knot_layer_api {
+	int (*begin)(knot_layer_t *ctx, void *module_param);
+	int (*reset)(knot_layer_t *ctx);
+	int (*finish)(knot_layer_t *ctx);
+	int (*in)(knot_layer_t *ctx, knot_pkt_t *pkt);
+	int (*out)(knot_layer_t *ctx, knot_pkt_t *pkt);
+	int (*err)(knot_layer_t *ctx, knot_pkt_t *pkt);
+} knot_layer_api_t;
 
 /*!
  * \brief Universal noop process function.
  */
-inline static int knot_process_noop(knot_pkt_t *pkt, knot_process_t *ctx)
+inline static int knot_layer_noop(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
-	return NS_PROC_NOOP;
+	return KNOT_NS_PROC_NOOP;
 }
 
 /*!
  * \brief Initialize packet processing context.
  *
- * Allowed from states: NOOP
- *
- * \param ctx Context.
- * \param module_param Parameters for given module.
- * \param module Module API.
+ * \param ctx   Layer context.
+ * \param param Parameters for given module.
+ * \param api   Layer API.
  * \return (module specific state)
  */
-int knot_process_begin(knot_process_t *ctx, void *module_param,
-                       const knot_process_module_t *module);
+int knot_layer_begin(knot_layer_t *ctx, const knot_layer_api_t *api, void *param);
 
 /*!
  * \brief Reset current packet processing context.
- * \param ctx Context.
+ * \param ctx   Layer context.
  * \return (module specific state)
  */
-int knot_process_reset(knot_process_t *ctx);
+int knot_layer_reset(knot_layer_t *ctx);
 
 /*!
  * \brief Finish and close packet processing context.
  *
  * Allowed from states: MORE, FULL, DONE, FAIL
  *
- * \param ctx Context.
+ * \param ctx   Layer context.
  * \return (module specific state)
  */
-int knot_process_finish(knot_process_t *ctx);
+int knot_layer_finish(knot_layer_t *ctx);
 
 /*!
- * \brief Input more data into packet processing.
+ * \brief Add more data to layer processing.
  *
  * Allowed from states: MORE
  *
- * \param wire Source data.
- * \param wire_len Source data length.
- * \param ctx Context.
+ * \param ctx Layer context.
+ * \param pkt Data packet.
+ *
  * \return (module specific state)
  */
-int knot_process_in(const uint8_t *wire, uint16_t wire_len, knot_process_t *ctx);
+int knot_layer_in(knot_layer_t *ctx, knot_pkt_t *pkt);
 
 /*!
- * \brief Write out output from packet processing.
+ * \brief Generate output from layer.
  *
- * Allowed from states: FULL, FAIL
+ * \param ctx Layer context.
+ * \param pkt Data packet.
  *
- * \param wire Destination.
- * \param wire_len Destination length.
- * \param ctx Context.
  * \return (module specific state)
  */
-int knot_process_out(uint8_t *wire, uint16_t *wire_len, knot_process_t *ctx);
+int knot_layer_out(knot_layer_t *ctx, knot_pkt_t *pkt);
 
 /*! @} */
diff --git a/src/libknot/processing/overlay.c b/src/libknot/processing/overlay.c
new file mode 100644
index 0000000000000000000000000000000000000000..ea5772b49e0233848c523f6d39eac2d945c052c4
--- /dev/null
+++ b/src/libknot/processing/overlay.c
@@ -0,0 +1,107 @@
+/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "libknot/processing/overlay.h"
+
+#include "libknot/errcode.h"
+#include "common/macros.h"
+
+/*! \note Macro for state-chaining layers. */
+#define ITERATE_LAYERS(overlay, func, ...) \
+	int state = overlay->state; \
+	struct knot_layer *layer = NULL; \
+	WALK_LIST(layer, (overlay)->layers) { \
+		layer->state = state; /* Pass-through state. */ \
+		state = (func)(layer, ##__VA_ARGS__); \
+	} \
+	return overlay->state = state;
+
+_public_
+void knot_overlay_init(struct knot_overlay *overlay, mm_ctx_t *mm)
+{
+	init_list(&overlay->layers);
+	overlay->mm = mm;
+	overlay->state = KNOT_NS_PROC_NOOP;
+}
+
+_public_
+void knot_overlay_deinit(struct knot_overlay *overlay)
+{
+	struct knot_layer *layer = NULL, *next = NULL;
+	WALK_LIST_DELSAFE(layer, next, overlay->layers) {
+		mm_free(overlay->mm, layer);
+	}
+}
+
+_public_
+int knot_overlay_add(struct knot_overlay *overlay, const knot_layer_api_t *module,
+                     void *module_param)
+{
+	struct knot_layer *layer = mm_alloc(overlay->mm, sizeof(struct knot_layer));
+	if (layer == NULL) {
+		return KNOT_ENOMEM;
+	}
+
+	memset(layer, 0, sizeof(struct knot_layer));
+	layer->mm = overlay->mm;
+	layer->state = overlay->state;
+	add_tail(&overlay->layers, (node_t *)layer);
+
+	overlay->state = knot_layer_begin(layer, module, module_param);
+
+	return KNOT_EOK;
+}
+
+_public_
+int knot_overlay_reset(struct knot_overlay *overlay)
+{
+	ITERATE_LAYERS(overlay, knot_layer_reset);
+}
+
+_public_
+int knot_overlay_finish(struct knot_overlay *overlay)
+{
+	/* Only in operable state. */
+	if (overlay->state == KNOT_NS_PROC_NOOP) {
+		return overlay->state;
+	}
+
+	ITERATE_LAYERS(overlay, knot_layer_finish);
+}
+
+_public_
+int knot_overlay_in(struct knot_overlay *overlay, knot_pkt_t *pkt)
+{
+	/* Only if expecting data. */
+	if (overlay->state != KNOT_NS_PROC_MORE) {
+		return overlay->state;
+	}
+
+	knot_pkt_parse(pkt, 0);
+
+	ITERATE_LAYERS(overlay, knot_layer_in, pkt);
+}
+
+_public_
+int knot_overlay_out(struct knot_overlay *overlay, knot_pkt_t *pkt)
+{
+	/* Only in operable state. */
+	if (overlay->state == KNOT_NS_PROC_NOOP) {
+		return overlay->state;
+	}
+
+	ITERATE_LAYERS(overlay, knot_layer_out, pkt);
+}
diff --git a/src/libknot/processing/overlay.h b/src/libknot/processing/overlay.h
new file mode 100644
index 0000000000000000000000000000000000000000..c86cea7338f95ad4965f06c54828160375081b58
--- /dev/null
+++ b/src/libknot/processing/overlay.h
@@ -0,0 +1,101 @@
+/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/*!
+ * \file overlay.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \addtogroup query_processing
+ * @{
+ */
+
+#pragma once
+
+#include "common/lists.h"
+
+#include "libknot/processing/layer.h"
+
+/*! \brief Processsing overlay (list of chained FSMs). */
+struct knot_overlay {
+	int state;
+	list_t layers;
+	mm_ctx_t *mm;
+};
+
+/*!
+ * \brief Initialize overlay and memory context.
+ *
+ * \param overlay
+ * \param mm
+ */
+void knot_overlay_init(struct knot_overlay *overlay, mm_ctx_t *mm);
+
+/*!
+ * \brief Clear structure nad free list of layers.
+ *
+ * \param overlay
+ */
+void knot_overlay_deinit(struct knot_overlay *overlay);
+
+/*!
+ * \brief Add an overlay on top of the list and begin execution.
+ *
+ * \fn knot_layer_begin
+ *
+ * \param overlay
+ * \param module
+ * \param module_param
+ *
+ * \return KNOT_EOK or an error
+ */
+int knot_overlay_add(struct knot_overlay *overlay, const knot_layer_api_t *module,
+                     void *module_param);
+
+/*!
+ * \brief Reset layer processing.
+ *
+ * \fn knot_layer_reset
+ */
+int knot_overlay_reset(struct knot_overlay *overlay);
+
+/*!
+ * \brief Finish layer processing.
+ *
+ * Allowed from states: MORE, FULL, DONE, FAIL
+ *
+ * \fn knot_layer_finish
+ */
+int knot_overlay_finish(struct knot_overlay *overlay);
+
+/*!
+ * \brief Add more data to layer processing.
+ *
+ * Allowed from states: MORE
+ *
+ * \fn knot_layer_in
+ */
+int knot_overlay_in(struct knot_overlay *overlay, knot_pkt_t *pkt);
+
+/*!
+ * \brief Generate output from layers.
+ *
+ * Allowed from states: FULL, FAIL
+ *
+ * \fn knot_layer_out
+ */
+int knot_overlay_out(struct knot_overlay *overlay, knot_pkt_t *pkt);
+
+/*! @} */
diff --git a/src/libknot/processing/process.c b/src/libknot/processing/process.c
deleted file mode 100644
index f264e2a32573100426729e5c3123376970357bd6..0000000000000000000000000000000000000000
--- a/src/libknot/processing/process.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <assert.h>
-
-#include "libknot/processing/process.h"
-#include "common/debug.h"
-
-/* State -> string translation table. */
-#ifdef KNOT_NS_DEBUG
-#define PROCESSING_STATE_STR(x) _state_table[x]
-static const char* _state_table[] = {
-        [NS_PROC_NOOP] = "NOOP",
-        [NS_PROC_MORE] = "MORE",
-        [NS_PROC_FULL] = "FULL",
-        [NS_PROC_DONE] = "DONE",
-        [NS_PROC_FAIL] = "FAIL"
-};
-#endif /* KNOT_NS_DEBUG */
-
-int knot_process_begin(knot_process_t *ctx, void *module_param,
-                       const knot_process_module_t *module)
-{
-	/* Only in inoperable state. */
-	if (ctx->state != NS_PROC_NOOP) {
-		return NS_PROC_NOOP;
-	}
-
-#ifdef KNOT_NS_DEBUG
-	/* Check module API. */
-	assert(module->begin);
-	assert(module->in);
-	assert(module->out);
-	assert(module->err);
-	assert(module->reset);
-	assert(module->finish);
-#endif /* KNOT_NS_DEBUG */
-
-	ctx->module = module;
-	ctx->state = module->begin(ctx, module_param);
-
-	dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state));
-	return ctx->state;
-}
-
-int knot_process_reset(knot_process_t *ctx)
-{
-	ctx->state = ctx->module->reset(ctx);
-	dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state));
-	return ctx->state;
-}
-
-int knot_process_finish(knot_process_t *ctx)
-{
-	/* Only in operable state. */
-	if (ctx->state == NS_PROC_NOOP) {
-		return NS_PROC_NOOP;
-	}
-
-	ctx->state = ctx->module->finish(ctx);
-	dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state));
-	return ctx->state;
-}
-
-int knot_process_in(const uint8_t *wire, uint16_t wire_len, knot_process_t *ctx)
-{
-	/* Only if expecting data. */
-	if (ctx->state != NS_PROC_MORE) {
-		return NS_PROC_NOOP;
-	}
-
-	knot_pkt_t *pkt = knot_pkt_new((uint8_t *)wire, wire_len, &ctx->mm);
-	knot_pkt_parse(pkt, 0);
-
-	ctx->state = ctx->module->in(pkt, ctx);
-	dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state));
-	return ctx->state;
-}
-
-int knot_process_out(uint8_t *wire, uint16_t *wire_len, knot_process_t *ctx)
-{
-	knot_pkt_t *pkt = knot_pkt_new(wire, *wire_len, &ctx->mm);
-
-	switch (ctx->state) {
-	case NS_PROC_FULL: ctx->state = ctx->module->out(pkt, ctx); break;
-	case NS_PROC_FAIL: ctx->state = ctx->module->err(pkt, ctx); break;
-	default:
-		assert(0); /* Improper use. */
-		knot_pkt_free(&pkt);
-		return NS_PROC_NOOP;
-	}
-
-	/* Accept only finished result. */
-	if (ctx->state != NS_PROC_FAIL) {
-		*wire_len = pkt->size;
-	} else {
-		*wire_len = 0;
-	}
-
-	knot_pkt_free(&pkt);
-
-	dbg_ns("%s -> %s\n", __func__, PROCESSING_STATE_STR(ctx->state));
-	return ctx->state;
-}
-
-#undef PROCESSING_STATE_STR
diff --git a/src/libknot/processing/requestor.c b/src/libknot/processing/requestor.c
new file mode 100644
index 0000000000000000000000000000000000000000..f63868981655becad3ae11e2458da3a40914feba
--- /dev/null
+++ b/src/libknot/processing/requestor.c
@@ -0,0 +1,317 @@
+/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <sys/fcntl.h>
+
+#include "common/macros.h"
+#include "common/net.h"
+
+#include "libknot/errcode.h"
+#include "libknot/processing/requestor.h"
+
+static bool use_tcp(struct knot_request *request)
+{
+	return !(request->flags & KNOT_RQ_UDP);
+}
+
+static struct knot_request *request_make(mm_ctx_t *mm)
+{
+	struct knot_request *request =
+	                mm_alloc(mm, sizeof(struct knot_request));
+	if (request == NULL) {
+		return NULL;
+	}
+
+	memset(request, 0, sizeof(struct knot_request));
+
+	return request;
+}
+
+/*! \brief Wait for socket readiness. */
+static int request_wait(int fd, int state, struct timeval *timeout)
+{
+	fd_set set;
+	FD_ZERO(&set);
+	FD_SET(fd, &set);
+
+	switch(state) {
+	case KNOT_NS_PROC_FULL: /* Wait for writeability. */
+		return select(fd + 1, NULL, &set, NULL, timeout);
+	case KNOT_NS_PROC_MORE: /* Wait for data. */
+		return select(fd + 1, &set, NULL, NULL, timeout);
+	default:
+		return -1;
+	}
+}
+
+static int request_send(struct knot_request *request,
+                        const struct timeval *timeout)
+{
+	/* Each request has unique timeout. */
+	struct timeval tv = { timeout->tv_sec, timeout->tv_usec };
+
+	/* Wait for writeability or error. */
+	int ret = request_wait(request->fd, KNOT_NS_PROC_FULL, &tv);
+	if (ret == 0) {
+		return KNOT_ETIMEOUT;
+	}
+
+	/* Check socket error. */
+	int err = 0;
+	socklen_t len = sizeof(int);
+	getsockopt(request->fd, SOL_SOCKET, SO_ERROR, &err, &len);
+	if (err != 0) {
+		return KNOT_ECONNREFUSED;
+	}
+
+	/* Send query, construct if not exists. */
+	knot_pkt_t *query = request->query;
+	uint8_t *wire = query->wire;
+	uint16_t wire_len = query->size;
+
+	/* Send query. */
+	if (use_tcp(request)) {
+		ret = tcp_send_msg(request->fd, wire, wire_len);
+	} else {
+		ret = udp_send_msg(request->fd, wire, wire_len,
+		                   (const struct sockaddr *)&request->remote);
+	}
+	if (ret != wire_len) {
+		return KNOT_ECONN;
+	}
+
+	return KNOT_EOK;
+}
+
+static int request_recv(struct knot_request *request,
+                        const struct timeval *timeout)
+{
+	int ret = 0;
+	knot_pkt_t *resp = request->resp;
+	knot_pkt_clear(resp);
+
+	/* Each request has unique timeout. */
+	struct timeval tv = { timeout->tv_sec, timeout->tv_usec };
+
+	/* Receive it */
+	if (use_tcp(request)) {
+		ret = tcp_recv_msg(request->fd, resp->wire, resp->max_size, &tv);
+	} else {
+		ret = udp_recv_msg(request->fd, resp->wire, resp->max_size,
+		                   (struct sockaddr *)&request->remote);
+	}
+	if (ret < 0) {
+		resp->size = 0;
+		return ret;
+	}
+
+	resp->size = ret;
+	return ret;
+}
+
+_public_
+struct knot_request *knot_request_make(mm_ctx_t *mm,
+                                       const struct sockaddr *dst,
+                                       const struct sockaddr *src,
+                                       knot_pkt_t *query,
+                                       unsigned flags)
+{
+	if (dst == NULL || query == NULL) {
+		return NULL;
+	}
+
+	/* Form a pending request. */
+	struct knot_request *request = request_make(mm);
+	if (request == NULL) {
+		return NULL;
+	}
+
+	memcpy(&request->remote, dst, sockaddr_len(dst));
+	if (src) {
+		memcpy(&request->origin, src, sockaddr_len(src));
+	}
+
+	request->fd = -1;
+	request->query = query;
+	request->resp  = NULL;
+	request->flags = flags;
+	return request;
+}
+
+_public_
+int knot_request_free(mm_ctx_t *mm, struct knot_request *request)
+{
+	close(request->fd);
+	knot_pkt_free(&request->query);
+	knot_pkt_free(&request->resp);
+
+	rem_node(&request->node);
+	mm_free(mm, request);
+
+	return KNOT_EOK;
+}
+
+_public_
+void knot_requestor_init(struct knot_requestor *requestor, mm_ctx_t *mm)
+{
+	memset(requestor, 0, sizeof(struct knot_requestor));
+	requestor->mm = mm;
+	init_list(&requestor->pending);
+	knot_overlay_init(&requestor->overlay, mm);
+}
+
+_public_
+void knot_requestor_clear(struct knot_requestor *requestor)
+{
+	while (knot_requestor_dequeue(requestor) == KNOT_EOK)
+		;
+
+	knot_overlay_finish(&requestor->overlay);
+	knot_overlay_deinit(&requestor->overlay);
+}
+
+_public_
+bool knot_requestor_finished(struct knot_requestor *requestor)
+{
+	return requestor == NULL || EMPTY_LIST(requestor->pending);
+}
+
+_public_
+int knot_requestor_overlay(struct knot_requestor *requestor,
+                           const knot_layer_api_t *proc, void *param)
+{
+	return knot_overlay_add(&requestor->overlay, proc, param);
+}
+
+_public_
+int knot_requestor_enqueue(struct knot_requestor *requestor,
+                           struct knot_request *request)
+{
+	if (requestor == NULL || request == NULL) {
+		return KNOT_EINVAL;
+	}
+
+	/* Determine comm protocol. */
+	int sock_type = SOCK_DGRAM;
+	if (use_tcp(request)) {
+		sock_type = SOCK_STREAM;
+	}
+
+	/* Fetch a bound socket. */
+	request->fd = net_connected_socket(sock_type, &request->remote,
+	                                   &request->origin, O_NONBLOCK);
+	if (request->fd < 0) {
+		return KNOT_ECONN;
+	}
+
+	/* Prepare response buffers. */
+	request->resp  = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, requestor->mm);
+	if (request->resp == NULL) {
+		mm_free(requestor->mm, request);
+		return KNOT_ENOMEM;
+	}
+
+	add_tail(&requestor->pending, &request->node);
+
+	return KNOT_EOK;
+}
+
+_public_
+int knot_requestor_dequeue(struct knot_requestor *requestor)
+{
+	if (knot_requestor_finished(requestor)) {
+		return KNOT_ENOENT;
+	}
+
+	struct knot_request *last = HEAD(requestor->pending);
+	return knot_request_free(requestor->mm, last);
+}
+
+static int request_io(struct knot_requestor *req, struct knot_request *last,
+                      struct timeval *timeout)
+{
+	int ret = KNOT_EOK;
+	knot_pkt_t *query = last->query;
+	knot_pkt_t *resp = last->resp;
+
+	/* Data to be sent. */
+	if (req->overlay.state == KNOT_NS_PROC_FULL) {
+
+		/* Process query and send it out. */
+		knot_overlay_out(&req->overlay, query);
+
+		ret = request_send(last, timeout);
+		if (ret != KNOT_EOK) {
+			return ret;
+		}
+	}
+
+	/* Data to be read. */
+	if (req->overlay.state == KNOT_NS_PROC_MORE) {
+		/* Read answer and process it. */
+		ret = request_recv(last, timeout);
+		if (ret < 0) {
+			return ret;
+		}
+
+		knot_overlay_in(&req->overlay, resp);
+	}
+
+	return KNOT_EOK;
+}
+
+static int exec_request(struct knot_requestor *req, struct knot_request *last,
+                        struct timeval *timeout)
+{
+	int ret = KNOT_EOK;
+
+	/* Do I/O until the processing is satisifed or fails. */
+	while (req->overlay.state & (KNOT_NS_PROC_FULL|KNOT_NS_PROC_MORE)) {
+		ret = request_io(req, last, timeout);
+		if (ret != KNOT_EOK) {
+			knot_overlay_reset(&req->overlay);
+			return ret;
+		}
+	}
+
+	/* Expect complete request. */
+	if (req->overlay.state == KNOT_NS_PROC_FAIL) {
+		ret = KNOT_ERROR;
+	}
+
+	/* Finish current query processing. */
+	knot_overlay_reset(&req->overlay);
+
+	return ret;
+}
+
+_public_
+int knot_requestor_exec(struct knot_requestor *requestor,
+                        struct timeval *timeout)
+{
+	if (knot_requestor_finished(requestor)) {
+		return KNOT_ENOENT;
+	}
+
+	/* Execute next request. */
+	int ret = exec_request(requestor, HEAD(requestor->pending), timeout);
+
+	/* Remove it from processing. */
+	knot_requestor_dequeue(requestor);
+
+	return ret;
+}
diff --git a/src/knot/nameserver/requestor.h b/src/libknot/processing/requestor.h
similarity index 52%
rename from src/knot/nameserver/requestor.h
rename to src/libknot/processing/requestor.h
index 771535e5fb9c3943e2f11cbf205b24c6973f2993..f0d73b9088cc780bdaa170a15e4f0837481406ce 100644
--- a/src/knot/nameserver/requestor.h
+++ b/src/libknot/processing/requestor.h
@@ -16,68 +16,98 @@
 
 #pragma once
 
-#include "knot/nameserver/process_query.h"
-#include "knot/nameserver/process_answer.h"
-#include "common-knot/lists.h"
+#include "common/lists.h"
+#include "common/sockaddr.h"
+#include "common/mempattern.h"
 
-struct request;
+#include "libknot/processing/overlay.h"
+
+struct knot_request;
+
+/* Requestor flags. */
+enum {
+	KNOT_RQ_UDP = 1 << 0  /* Use UDP for requests. */
+};
 
 /*! \brief Requestor structure.
  *
  *  Requestor holds a FIFO of pending queries.
  */
-struct requestor {
-	const knot_process_module_t *module; /*!< Response processing module. */
-	list_t pending;                      /*!< Pending requests (FIFO). */
-	mm_ctx_t *mm;                        /*!< Memory context. */
+struct knot_requestor {
+	mm_ctx_t *mm;            /*!< Memory context. */
+	list_t pending;               /*!< Pending requests (FIFO). */
+	struct knot_overlay overlay;  /*!< Response processing overlay. */
 };
 
 /*! \brief Request data (socket, payload, response, TSIG and endpoints). */
-struct request_data {
+struct knot_request {
 	node_t node;
 	int fd;
+	unsigned flags;
 	struct sockaddr_storage remote, origin;
 	knot_sign_context_t sign;
 	knot_pkt_t *query;
 	knot_pkt_t *resp;
 };
 
+/*!
+ * \brief Make request out of endpoints and query.
+ *
+ * \param mm     Memory context.
+ * \param dst    Remote endpoint address.
+ * \param src    Source address (or NULL).
+ * \param query  Query message.
+ * \param flags  Request flags.
+ *
+ * \return Prepared request or NULL in case of error.
+ */
+struct knot_request *knot_request_make(mm_ctx_t *mm,
+                                       const struct sockaddr *dst,
+                                       const struct sockaddr *src,
+                                       knot_pkt_t *query,
+                                       unsigned flags);
+
+/*!
+ * \brief Free request and associated data.
+ *
+ * \param mm      Memory context.
+ * \param request Freed request.
+ *
+ * \return Prepared request or NULL in case of error.
+ */
+int knot_request_free(mm_ctx_t *mm, struct knot_request *request);
+
 /*!
  * \brief Initialize requestor structure.
  *
  * \param requestor Requestor instance.
- * \param module    Response processing module.
  * \param mm        Memory context.
  */
-void requestor_init(struct requestor *requestor, const knot_process_module_t *module, mm_ctx_t *mm);
+void knot_requestor_init(struct knot_requestor *requestor, mm_ctx_t *mm);
 
 /*!
  * \brief Clear the requestor structure and close pending queries.
  *
  * \param requestor Requestor instance.
  */
-void requestor_clear(struct requestor *requestor);
+void knot_requestor_clear(struct knot_requestor *requestor);
 
 /*!
  * \brief Return true if there are no pending queries.
  *
  * \param requestor Requestor instance.
  */
-bool requestor_finished(struct requestor *requestor);
-
+bool knot_requestor_finished(struct knot_requestor *requestor);
 
 /*!
- * \brief Make request out of endpoints and query.
+ * \brief Add a processing layer.
  *
  * \param requestor Requestor instance.
- * \param remote    Remote endpoint descriptor (source, destination, [key])
- * \param query     Query message.
- *
- * \return Prepared request or NULL in case of error.
+ * \param proc      Response processing module.
+ * \param param     Processing module parameters.
  */
-struct request *requestor_make(struct requestor *requestor,
-                               const conf_iface_t *remote,
-                               knot_pkt_t *query);
+int knot_requestor_overlay(struct knot_requestor *requestor,
+                           const knot_layer_api_t *proc, void *param);
 
 /*!
  * \brief Enqueue a query for processing.
@@ -87,11 +117,11 @@ struct request *requestor_make(struct requestor *requestor,
  *
  * \param requestor Requestor instance.
  * \param request   Prepared request.
- * \param param     Request processing module parameter.
  *
  * \return KNOT_EOK or error
  */
-int requestor_enqueue(struct requestor *requestor, struct request *request, void *param);
+int knot_requestor_enqueue(struct knot_requestor *requestor,
+                           struct knot_request *request);
 
 /*!
  * \brief Close first pending request.
@@ -100,7 +130,7 @@ int requestor_enqueue(struct requestor *requestor, struct request *request, void
  *
  * \return KNOT_EOK or error
  */
-int requestor_dequeue(struct requestor *requestor);
+int knot_requestor_dequeue(struct knot_requestor *requestor);
 
 /*!
  * \brief Execute next pending query (FIFO).
@@ -110,4 +140,5 @@ int requestor_dequeue(struct requestor *requestor);
  *
  * \return KNOT_EOK or error
  */
-int requestor_exec(struct requestor *requestor, struct timeval *timeout);
+int knot_requestor_exec(struct knot_requestor *requestor,
+                        struct timeval *timeout);
diff --git a/src/libknot/rdata.c b/src/libknot/rdata.c
index 9d308da0d9331c8d636206203a192358169cf16d..35dcd7f5fad12f2b0a6ce2e079f06880645fcaa3 100644
--- a/src/libknot/rdata.c
+++ b/src/libknot/rdata.c
@@ -20,8 +20,9 @@
 #include <stdlib.h>
 
 #include "libknot/rdata.h"
-#include "libknot/common.h"
+
 #include "libknot/errcode.h"
+#include "common/macros.h"
 
 #ifndef STRICT_ALIGNMENT
 #pragma pack(push, 1)
@@ -38,6 +39,7 @@ struct rr_offsets {
 #pragma pack(pop)
 #endif
 
+_public_
 void knot_rdata_init(knot_rdata_t *rdata,
                      uint16_t rdlen, const uint8_t *data, uint32_t ttl)
 {
@@ -46,36 +48,43 @@ void knot_rdata_init(knot_rdata_t *rdata,
 	memcpy(knot_rdata_data(rdata), data, rdlen);
 }
 
+_public_
 uint16_t knot_rdata_rdlen(const knot_rdata_t *rr)
 {
 	return ((struct rr_offsets *)rr)->size;
 }
 
+_public_
 void knot_rdata_set_rdlen(knot_rdata_t *rr, uint16_t size)
 {
 	((struct rr_offsets *)rr)->size = size;
 }
 
+_public_
 uint32_t knot_rdata_ttl(const knot_rdata_t *rr)
 {
 	return ((struct rr_offsets *)rr)->ttl;
 }
 
+_public_
 void knot_rdata_set_ttl(knot_rdata_t *rr, uint32_t ttl)
 {
 	((struct rr_offsets *)rr)->ttl = ttl;
 }
 
+_public_
 uint8_t *knot_rdata_data(const knot_rdata_t *rr)
 {
 	return ((struct rr_offsets *)rr)->rdata;
 }
 
+_public_
 size_t knot_rdata_array_size(uint16_t size)
 {
 	return size + sizeof(struct rr_offsets);
 }
 
+_public_
 int knot_rdata_cmp(const knot_rdata_t *rr1, const knot_rdata_t *rr2)
 {
 	assert(rr1 && rr2);
diff --git a/src/libknot/rdata.h b/src/libknot/rdata.h
index 812b94f3ed0dcf156360485eb616e3e50f79b4a5..4c23d71bbbb1fb0761868c47b554c48b4c6e788b 100644
--- a/src/libknot/rdata.h
+++ b/src/libknot/rdata.h
@@ -30,7 +30,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 
 /* ---------------------------- Single RR ----------------------------------- */
 
diff --git a/src/libknot/rdataset.c b/src/libknot/rdataset.c
index 847475558e030e9d6f2df68a38890e1e66d3e2cb..7faf483c0f2f331791316e0c85be23e1804a7e70 100644
--- a/src/libknot/rdataset.c
+++ b/src/libknot/rdataset.c
@@ -20,7 +20,9 @@
 #include <stdlib.h>
 
 #include "libknot/rdataset.h"
-#include "libknot/common.h"
+
+#include "libknot/errcode.h"
+#include "common/macros.h"
 
 static knot_rdata_t *rr_seek(knot_rdata_t *d, size_t pos)
 {
@@ -69,7 +71,6 @@ static int add_rr_at(knot_rdataset_t *rrs, const knot_rdata_t *rr, size_t pos,
 	if (tmp) {
 		rrs->data = tmp;
 	} else {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
@@ -124,7 +125,6 @@ static int remove_rr_at(knot_rdataset_t *rrs, size_t pos, mm_ctx_t *mm)
 		                       total_size - (knot_rdata_array_size(old_size)),
 		                       total_size);
 		if (tmp == NULL) {
-			ERR_ALLOC_FAILED;
 			return KNOT_ENOMEM;
 		} else {
 			rrs->data = tmp;
@@ -139,6 +139,7 @@ static int remove_rr_at(knot_rdataset_t *rrs, size_t pos, mm_ctx_t *mm)
 	return KNOT_EOK;
 }
 
+_public_
 void knot_rdataset_init(knot_rdataset_t *rrs)
 {
 	if (rrs) {
@@ -147,6 +148,7 @@ void knot_rdataset_init(knot_rdataset_t *rrs)
 	}
 }
 
+_public_
 void knot_rdataset_clear(knot_rdataset_t *rrs, mm_ctx_t *mm)
 {
 	if (rrs) {
@@ -155,6 +157,7 @@ void knot_rdataset_clear(knot_rdataset_t *rrs, mm_ctx_t *mm)
 	}
 }
 
+_public_
 int knot_rdataset_copy(knot_rdataset_t *dst, const knot_rdataset_t *src, mm_ctx_t *mm)
 {
 	if (dst == NULL || src == NULL) {
@@ -165,7 +168,6 @@ int knot_rdataset_copy(knot_rdataset_t *dst, const knot_rdataset_t *src, mm_ctx_
 	size_t src_size = knot_rdataset_size(src);
 	dst->data = mm_alloc(mm, src_size);
 	if (dst->data == NULL) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
@@ -173,6 +175,7 @@ int knot_rdataset_copy(knot_rdataset_t *dst, const knot_rdataset_t *src, mm_ctx_
 	return KNOT_EOK;
 }
 
+_public_
 knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *rrs, size_t pos)
 {
 	if (rrs == NULL || pos >= rrs->rr_count) {
@@ -182,6 +185,7 @@ knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *rrs, size_t pos)
 	return rr_seek(rrs->data, pos);
 }
 
+_public_
 size_t knot_rdataset_size(const knot_rdataset_t *rrs)
 {
 	if (rrs == NULL) {
@@ -198,6 +202,7 @@ size_t knot_rdataset_size(const knot_rdataset_t *rrs)
 	return total_size;
 }
 
+_public_
 int knot_rdataset_add(knot_rdataset_t *rrs, const knot_rdata_t *rr, mm_ctx_t *mm)
 {
 	if (rrs == NULL || rr == NULL) {
@@ -220,6 +225,7 @@ int knot_rdataset_add(knot_rdataset_t *rrs, const knot_rdata_t *rr, mm_ctx_t *mm
 	return add_rr_at(rrs, rr, rrs->rr_count, mm);
 }
 
+_public_
 bool knot_rdataset_eq(const knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2)
 {
 	if (rrs1->rr_count != rrs2->rr_count) {
@@ -237,7 +243,9 @@ bool knot_rdataset_eq(const knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2)
 	return true;
 }
 
-bool knot_rdataset_member(const knot_rdataset_t *rrs, const knot_rdata_t *rr, bool cmp_ttl)
+_public_
+bool knot_rdataset_member(const knot_rdataset_t *rrs, const knot_rdata_t *rr,
+			  bool cmp_ttl)
 {
 	for (uint16_t i = 0; i < rrs->rr_count; ++i) {
 		const knot_rdata_t *cmp_rr = knot_rdataset_at(rrs, i);
@@ -259,6 +267,7 @@ bool knot_rdataset_member(const knot_rdataset_t *rrs, const knot_rdata_t *rr, bo
 	return false;
 }
 
+_public_
 int knot_rdataset_merge(knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2, mm_ctx_t *mm)
 {
 	if (rrs1 == NULL || rrs2 == NULL) {
@@ -276,6 +285,7 @@ int knot_rdataset_merge(knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2, mm_c
 	return KNOT_EOK;
 }
 
+_public_
 int knot_rdataset_intersect(const knot_rdataset_t *a, const knot_rdataset_t *b,
                        knot_rdataset_t *out, mm_ctx_t *mm)
 {
@@ -300,7 +310,9 @@ int knot_rdataset_intersect(const knot_rdataset_t *a, const knot_rdataset_t *b,
 	return KNOT_EOK;
 }
 
-int knot_rdataset_subtract(knot_rdataset_t *from, const knot_rdataset_t *what, mm_ctx_t *mm)
+_public_
+int knot_rdataset_subtract(knot_rdataset_t *from, const knot_rdataset_t *what,
+			   mm_ctx_t *mm)
 {
 	if (from == NULL || what == NULL || from->data == what->data) {
 		return KNOT_EINVAL;
diff --git a/src/libknot/rdataset.h b/src/libknot/rdataset.h
index 34a0ad2f105d2ac279d416ca82e8dcadf17e9c7d..97adcef26bb3d84f344aff3f771cd719b58c0a86 100644
--- a/src/libknot/rdataset.h
+++ b/src/libknot/rdataset.h
@@ -30,7 +30,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
+
 #include "libknot/rdata.h"
 
 /*!< \brief Set of RRs. */
@@ -110,7 +111,8 @@ bool knot_rdataset_eq(const knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2);
  * \retval true if \a rr is present in \a rrs.
  * \retval false if \a rr is not present in \a rrs.
  */
-bool knot_rdataset_member(const knot_rdataset_t *rrs, const knot_rdata_t *rr, bool cmp_ttl);
+bool knot_rdataset_member(const knot_rdataset_t *rrs, const knot_rdata_t *rr,
+			  bool cmp_ttl);
 
 /*!
  * \brief Merges two RRS into the first one. Second RRS is left intact.
@@ -120,7 +122,8 @@ bool knot_rdataset_member(const knot_rdataset_t *rrs, const knot_rdata_t *rr, bo
  * \param mm    Memory context.
  * \return KNOT_E*
  */
-int knot_rdataset_merge(knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2, mm_ctx_t *mm);
+int knot_rdataset_merge(knot_rdataset_t *rrs1, const knot_rdataset_t *rrs2,
+			mm_ctx_t *mm);
 
 /*!
  * \brief RRS set-like intersection. Full compare is done.
@@ -151,6 +154,7 @@ int knot_rdataset_subtract(knot_rdataset_t *from, const knot_rdataset_t *what,
 		code; \
 	}
 
+/*! \todo Documentation. */
 static inline
 uint8_t *knot_rdata_offset(const knot_rdataset_t *rrs, size_t pos, size_t offset) {
 	knot_rdata_t *rr = knot_rdataset_at(rrs, pos);
diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c
index 647ea6b95752cad3054b70abcdb23ce300e7ed0d..4b05c5c20991c8a14751088cf893aac4d00ac4eb 100644
--- a/src/libknot/rrset-dump.c
+++ b/src/libknot/rrset-dump.c
@@ -14,8 +14,6 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "libknot/rrset-dump.h"
-
 #include <stdlib.h>			// free
 #include <stdbool.h>			// bool
 #include <string.h>			// memcpy
@@ -28,9 +26,13 @@
 #include <netinet/in.h>			// in_addr (BSD)
 #include <arpa/inet.h>			// ntohs
 
-#include "libknot/errcode.h"		// KNOT_EOK
+#include "libknot/rrset-dump.h"
+
 #include "common/base64.h"		// base64
 #include "common/base32hex.h"		// base32hex
+#include "common/macros.h"
+
+#include "libknot/errcode.h"		// KNOT_EOK
 #include "libknot/descriptor.h"		// KNOT_RRTYPE
 #include "libknot/dnssec/key.h"		// knot_keytag
 #include "libknot/consts.h"		// knot_rcode_names
@@ -52,6 +54,7 @@ typedef struct {
 	int           ret;
 } rrset_dump_params_t;
 
+_public_
 const knot_dump_style_t KNOT_DUMP_STYLE_DEFAULT = {
 	.wrap = false,
 	.show_class = false,
@@ -1686,6 +1689,7 @@ static int dump_unknown(DUMP_PARAMS)
 	DUMP_END;
 }
 
+_public_
 int knot_rrset_txt_dump_data(const knot_rrset_t      *rrset,
                              const size_t            pos,
                              char                    *dst,
@@ -1823,6 +1827,7 @@ int knot_rrset_txt_dump_data(const knot_rrset_t      *rrset,
 		return KNOT_ESPACE;			\
 	}
 
+_public_
 int knot_rrset_txt_dump_header(const knot_rrset_t      *rrset,
                                const uint32_t          ttl,
                                char                    *dst,
@@ -1894,6 +1899,7 @@ int knot_rrset_txt_dump_header(const knot_rrset_t      *rrset,
 	return len;
 }
 
+_public_
 int knot_rrset_txt_dump(const knot_rrset_t      *rrset,
                         char                    *dst,
                         const size_t            maxlen,
diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index 26792844632e4c28fe8028e96ac954b8f3653efa..126aa3c78b18b90a49ec5a9a692b3e0abed45662 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -20,13 +20,15 @@
 
 #include "libknot/rrset.h"
 
+#include "common/macros.h"
+#include "common/mempattern.h"
+
 #include "libknot/consts.h"
-#include "libknot/common.h"
-#include "libknot/mempattern.h"
 #include "libknot/descriptor.h"
 #include "libknot/dname.h"
 #include "libknot/rrtype/naptr.h"
 
+_public_
 knot_rrset_t *knot_rrset_new(const knot_dname_t *owner, uint16_t type,
                              uint16_t rclass, mm_ctx_t *mm)
 {
@@ -37,7 +39,6 @@ knot_rrset_t *knot_rrset_new(const knot_dname_t *owner, uint16_t type,
 
 	knot_rrset_t *ret = mm_alloc(mm, sizeof(knot_rrset_t));
 	if (ret == NULL) {
-		ERR_ALLOC_FAILED;
 		knot_dname_free(&owner_cpy, mm);
 		return NULL;
 	}
@@ -47,6 +48,7 @@ knot_rrset_t *knot_rrset_new(const knot_dname_t *owner, uint16_t type,
 	return ret;
 }
 
+_public_
 void knot_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner, uint16_t type,
                      uint16_t rclass)
 {
@@ -57,11 +59,13 @@ void knot_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner, uint16_t type,
 	rrset->additional = NULL;
 }
 
+_public_
 void knot_rrset_init_empty(knot_rrset_t *rrset)
 {
 	knot_rrset_init(rrset, NULL, 0, KNOT_CLASS_IN);
 }
 
+_public_
 knot_rrset_t *knot_rrset_copy(const knot_rrset_t *src, mm_ctx_t *mm)
 {
 	if (src == NULL) {
@@ -83,6 +87,7 @@ knot_rrset_t *knot_rrset_copy(const knot_rrset_t *src, mm_ctx_t *mm)
 	return rrset;
 }
 
+_public_
 void knot_rrset_free(knot_rrset_t **rrset, mm_ctx_t *mm)
 {
 	if (rrset == NULL || *rrset == NULL) {
@@ -95,6 +100,7 @@ void knot_rrset_free(knot_rrset_t **rrset, mm_ctx_t *mm)
 	*rrset = NULL;
 }
 
+_public_
 void knot_rrset_clear(knot_rrset_t *rrset, mm_ctx_t *mm)
 {
 	if (rrset) {
@@ -103,6 +109,7 @@ void knot_rrset_clear(knot_rrset_t *rrset, mm_ctx_t *mm)
 	}
 }
 
+_public_
 int knot_rrset_add_rdata(knot_rrset_t *rrset,
                          const uint8_t *rdata, const uint16_t size,
                          const uint32_t ttl, mm_ctx_t *mm)
@@ -117,6 +124,7 @@ int knot_rrset_add_rdata(knot_rrset_t *rrset,
 	return knot_rdataset_add(&rrset->rrs, rr, mm);
 }
 
+_public_
 bool knot_rrset_equal(const knot_rrset_t *r1,
                       const knot_rrset_t *r2,
                       knot_rrset_compare_type_t cmp)
@@ -144,6 +152,7 @@ bool knot_rrset_equal(const knot_rrset_t *r1,
 	return true;
 }
 
+_public_
 bool knot_rrset_empty(const knot_rrset_t *rrset)
 {
 	if (rrset) {
@@ -154,11 +163,13 @@ bool knot_rrset_empty(const knot_rrset_t *rrset)
 	}
 }
 
+_public_
 uint32_t knot_rrset_ttl(const knot_rrset_t *rrset)
 {
 	return knot_rdata_ttl(knot_rdataset_at(&(rrset->rrs), 0));
 }
 
+_public_
 int knot_rrset_rr_to_canonical(knot_rrset_t *rrset)
 {
 	if (rrset == NULL || rrset->rrs.rr_count != 1) {
@@ -176,7 +187,7 @@ int knot_rrset_rr_to_canonical(knot_rrset_t *rrset)
 		return KNOT_EOK;
 	}
 
-	const rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset->type);
+	const knot_rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset->type);
 	if (desc->type_name == NULL) {
 		desc = knot_get_obsolete_rdata_descriptor(rrset->type);
 	}
diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h
index 23219a8bc62b83dd9b3afca7e05f8e0b4a1da3c4..90eb38db5127a9cf362d68c33202077e5d6d70a5 100644
--- a/src/libknot/rrset.h
+++ b/src/libknot/rrset.h
@@ -30,7 +30,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
+
 #include "libknot/dname.h"
 #include "libknot/rdataset.h"
 
@@ -50,6 +51,7 @@ struct knot_rrset {
 
 typedef struct knot_rrset knot_rrset_t;
 
+/*! \todo Documentation */
 typedef enum {
 	KNOT_RRSET_COMPARE_PTR,
 	KNOT_RRSET_COMPARE_HEADER,
diff --git a/src/libknot/rrtype/aaaa.h b/src/libknot/rrtype/aaaa.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ebb1763151ccee35ea4cba39621f7b28a4423c0
--- /dev/null
+++ b/src/libknot/rrtype/aaaa.h
@@ -0,0 +1,42 @@
+/*  Copyright (C) 2014 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/>.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+
+#include "common/sockaddr.h"
+
+#include "libknot/rdataset.h"
+#include "libknot/errcode.h"
+
+static inline
+int knot_a_addr(const knot_rdataset_t *rrs, size_t pos, struct sockaddr_in *dst)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return KNOT_EINVAL);
+	knot_rdata_t *rr = knot_rdataset_at(rrs, pos);
+	return sockaddr_set_raw((struct sockaddr_storage *)dst, AF_INET,
+	                        knot_rdata_data(rr), knot_rdata_rdlen(rr));
+}
+
+static inline
+int knot_aaaa_addr(const knot_rdataset_t *rrs, size_t pos, struct sockaddr_in6 *dst)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return KNOT_EINVAL);
+	knot_rdata_t *rr = knot_rdataset_at(rrs, pos);
+	return sockaddr_set_raw((struct sockaddr_storage *)dst, AF_INET6,
+	                        knot_rdata_data(rr), knot_rdata_rdlen(rr));
+}
diff --git a/src/libknot/rrtype/nsec3.c b/src/libknot/rrtype/nsec3.c
index b6eae3fb22140ffefd79050fc4020ccf37212c02..bf9b1fb217e94879b41acaa63ed39c806c92a327 100644
--- a/src/libknot/rrtype/nsec3.c
+++ b/src/libknot/rrtype/nsec3.c
@@ -21,6 +21,7 @@
 #include "libknot/rrtype/nsec3.h"
 #include "libknot/util/tolower.h"
 #include "libknot/errcode.h"
+#include "common/macros.h"
 
 /*!
  * \brief Compute NSEC3 SHA1 hash.
@@ -95,9 +96,27 @@ static int nsec3_sha1(const uint8_t *salt, uint8_t salt_length,
 	return KNOT_EOK;
 }
 
-/*!
- * \brief Compute NSEC3 hash for given data.
- */
+_public_
+void knot_nsec3_bitmap(const knot_rdataset_t *rrs, size_t pos,
+                       uint8_t **bitmap, uint16_t *size)
+{
+	KNOT_RDATASET_CHECK(rrs, pos, return);
+
+	/* Bitmap is last, skip all the items. */
+	size_t offset = 6; //hash alg., flags, iterations, salt len., hash len.
+	offset += knot_nsec3_salt_length(rrs, pos); //salt
+
+	uint8_t *next_hashed = NULL;
+	uint8_t next_hashed_size = 0;
+	knot_nsec3_next_hashed(rrs, pos, &next_hashed, &next_hashed_size);
+	offset += next_hashed_size; //hash
+
+	*bitmap = knot_rdata_offset(rrs, pos, offset);
+	const knot_rdata_t *rr = knot_rdataset_at(rrs, pos);
+	*size = knot_rdata_rdlen(rr) - offset;
+}
+
+_public_
 int knot_nsec3_hash(const knot_nsec3_params_t *params, const uint8_t *data,
                     size_t data_size, uint8_t **digest, size_t *digest_size)
 {
diff --git a/src/libknot/rrtype/nsec3.h b/src/libknot/rrtype/nsec3.h
index a1c2fa26892accbffcb65eda025eb1c502e713d9..61dc07bf2452f5d9928b4c25e38dc44796a90c2a 100644
--- a/src/libknot/rrtype/nsec3.h
+++ b/src/libknot/rrtype/nsec3.h
@@ -72,7 +72,7 @@ const uint8_t *knot_nsec3_salt(const knot_rdataset_t *rrs, size_t pos)
 
 static inline
 void knot_nsec3_next_hashed(const knot_rdataset_t *rrs, size_t pos,
-                                  uint8_t **name, uint8_t *name_size)
+                            uint8_t **name, uint8_t *name_size)
 {
 	KNOT_RDATASET_CHECK(rrs, pos, return);
 	uint8_t salt_size = knot_nsec3_salt_length(rrs, pos);
@@ -80,25 +80,8 @@ void knot_nsec3_next_hashed(const knot_rdataset_t *rrs, size_t pos,
 	*name = knot_rdata_offset(rrs, pos, 4 + salt_size + 2);
 }
 
-static inline
 void knot_nsec3_bitmap(const knot_rdataset_t *rrs, size_t pos,
-                             uint8_t **bitmap, uint16_t *size)
-{
-	KNOT_RDATASET_CHECK(rrs, pos, return);
-
-	/* Bitmap is last, skip all the items. */
-	size_t offset = 6; //hash alg., flags, iterations, salt len., hash len.
-	offset += knot_nsec3_salt_length(rrs, pos); //salt
-
-	uint8_t *next_hashed = NULL;
-	uint8_t next_hashed_size = 0;
-	knot_nsec3_next_hashed(rrs, pos, &next_hashed, &next_hashed_size);
-	offset += next_hashed_size; //hash
-
-	*bitmap = knot_rdata_offset(rrs, pos, offset);
-	const knot_rdata_t *rr = knot_rdataset_at(rrs, pos);
-	*size = knot_rdata_rdlen(rr) - offset;
-}
+                       uint8_t **bitmap, uint16_t *size);
 
 /*!
  * \brief Get length of the raw NSEC3 hash.
diff --git a/src/libknot/rrtype/nsec3param.c b/src/libknot/rrtype/nsec3param.c
index 5700b760d23e76b050262c4ce579312ab19e780e..1aeb6a9e3228d46aaec3b0d39ae2106501631a0d 100644
--- a/src/libknot/rrtype/nsec3param.c
+++ b/src/libknot/rrtype/nsec3param.c
@@ -14,13 +14,14 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "libknot/rrtype/nsec3param.h"
+
+#include "common/macros.h"
 #include "common/mem.h"
+
 #include "libknot/errcode.h"
-#include "libknot/rrtype/nsec3param.h"
 
-/*!
- * \brief Initialize the structure with NSEC3 params from NSEC3PARAM RR set.
- */
+_public_
 int knot_nsec3param_from_wire(knot_nsec3_params_t *params,
                                 const knot_rdataset_t *rrs)
 {
@@ -50,11 +51,3 @@ int knot_nsec3param_from_wire(knot_nsec3_params_t *params,
 
 	return KNOT_EOK;
 }
-
-/*!
- * \brief Clean up structure with NSEC3 params (do not deallocate).
- */
-void knot_nsec3param_free(knot_nsec3_params_t *params)
-{
-	free(params->salt);
-}
diff --git a/src/libknot/rrtype/nsec3param.h b/src/libknot/rrtype/nsec3param.h
index 9bdc9d50a3bebe1d77b472915ff278575e3f511d..623f2966901b0c8db809d43ec762bc16d58eaf82 100644
--- a/src/libknot/rrtype/nsec3param.h
+++ b/src/libknot/rrtype/nsec3param.h
@@ -86,4 +86,8 @@ int knot_nsec3param_from_wire(knot_nsec3_params_t *params,
  *
  * \param params Structure with NSEC3 params.
  */
-void knot_nsec3param_free(knot_nsec3_params_t *params);
+static inline
+void knot_nsec3param_free(knot_nsec3_params_t *params)
+{
+	free(params->salt);
+}
diff --git a/src/libknot/rrtype/opt.c b/src/libknot/rrtype/opt.c
index ee887e240bf3d8b1f6cff3e7bdffefeeb71f9c55..9861a8809e60cc9fa918a9856626c5defbca9cce 100644
--- a/src/libknot/rrtype/opt.c
+++ b/src/libknot/rrtype/opt.c
@@ -17,13 +17,16 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <assert.h>
-
 #include <string.h>
+
 #include "libknot/rrtype/opt.h"
-#include "libknot/common.h"
-#include "libknot/descriptor.h"
+
 #include "common/debug.h"
-#include "common-knot/sockaddr.h"
+#include "common/macros.h"
+#include "common/sockaddr.h"
+
+#include "libknot/errcode.h"
+#include "libknot/descriptor.h"
 
 /*! \brief Some implementation-related constants. */
 enum knot_edns_private_consts {
@@ -46,7 +49,7 @@ enum knot_edns_private_consts {
 };
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_edns_init(knot_rrset_t *opt_rr, uint16_t max_pld,
                   uint8_t ext_rcode, uint8_t ver, mm_ctx_t *mm)
 {
@@ -74,7 +77,7 @@ int knot_edns_init(knot_rrset_t *opt_rr, uint16_t max_pld,
 
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 size_t knot_edns_wire_size(knot_rrset_t *opt_rr)
 {
 	if (opt_rr == NULL) {
@@ -88,7 +91,7 @@ size_t knot_edns_wire_size(knot_rrset_t *opt_rr)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 uint16_t knot_edns_get_payload(const knot_rrset_t *opt_rr)
 {
 	assert(opt_rr != NULL);
@@ -96,7 +99,7 @@ uint16_t knot_edns_get_payload(const knot_rrset_t *opt_rr)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 void knot_edns_set_payload(knot_rrset_t *opt_rr, uint16_t payload)
 {
 	assert(opt_rr != NULL);
@@ -104,7 +107,7 @@ void knot_edns_set_payload(knot_rrset_t *opt_rr, uint16_t payload)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 uint8_t knot_edns_get_ext_rcode(const knot_rrset_t *opt_rr)
 {
 	assert(opt_rr != NULL);
@@ -138,7 +141,7 @@ static void set_value_to_ttl(knot_rrset_t *opt_rr, size_t offset, uint8_t value)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 void knot_edns_set_ext_rcode(knot_rrset_t *opt_rr, uint8_t ext_rcode)
 {
 	assert(opt_rr != NULL);
@@ -146,7 +149,7 @@ void knot_edns_set_ext_rcode(knot_rrset_t *opt_rr, uint8_t ext_rcode)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 uint8_t knot_edns_get_version(const knot_rrset_t *opt_rr)
 {
 	assert(opt_rr != NULL);
@@ -163,7 +166,7 @@ uint8_t knot_edns_get_version(const knot_rrset_t *opt_rr)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 void knot_edns_set_version(knot_rrset_t *opt_rr, uint8_t version)
 {
 	assert(opt_rr != NULL);
@@ -171,7 +174,7 @@ void knot_edns_set_version(knot_rrset_t *opt_rr, uint8_t version)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_edns_do(const knot_rrset_t *opt_rr)
 {
 	assert(opt_rr != NULL);
@@ -180,7 +183,7 @@ bool knot_edns_do(const knot_rrset_t *opt_rr)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 void knot_edns_set_do(knot_rrset_t *opt_rr)
 {
 	assert(opt_rr != NULL);
@@ -226,7 +229,7 @@ static uint8_t *find_option(knot_rdata_t *rdata, uint16_t opt_code)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_edns_add_option(knot_rrset_t *opt_rr, uint16_t code,
                          uint16_t length, const uint8_t *data, mm_ctx_t *mm)
 {
@@ -267,7 +270,7 @@ int knot_edns_add_option(knot_rrset_t *opt_rr, uint16_t code,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_edns_has_option(const knot_rrset_t *opt_rr, uint16_t code)
 {
 	assert(opt_rr != NULL);
@@ -281,14 +284,14 @@ bool knot_edns_has_option(const knot_rrset_t *opt_rr, uint16_t code)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_edns_has_nsid(const knot_rrset_t *opt_rr)
 {
 	return knot_edns_has_option(opt_rr, KNOT_EDNS_OPTION_NSID);
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 bool knot_edns_check_record(knot_rrset_t *opt_rr)
 {
 	if (opt_rr->rrs.rr_count != 1) {
@@ -318,7 +321,7 @@ bool knot_edns_check_record(knot_rrset_t *opt_rr)
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 int knot_edns_client_subnet_create(const knot_addr_family_t family,
                                    const uint8_t *addr,
                                    const uint16_t addr_len,
@@ -359,6 +362,7 @@ int knot_edns_client_subnet_create(const knot_addr_family_t family,
 	return KNOT_EOK;
 }
 
+_public_
 int knot_edns_client_subnet_parse(const uint8_t *data,
                                   const uint16_t data_len,
                                   knot_addr_family_t *family,
diff --git a/src/libknot/rrtype/tsig.c b/src/libknot/rrtype/tsig.c
index ee2b99871f9a5e260025d75b9018adc5be0c4616..0cfd8b9ef3345ea0c8f1984e18578a31d751824a 100644
--- a/src/libknot/rrtype/tsig.c
+++ b/src/libknot/rrtype/tsig.c
@@ -25,7 +25,9 @@
 
 #include "common/debug.h"
 #include "common/log.h"
-#include "libknot/common.h"
+#include "common/macros.h"
+
+#include "libknot/errcode.h"
 #include "libknot/util/utils.h"
 #include "libknot/rrset.h"
 #include "libknot/dname.h"
@@ -57,7 +59,7 @@ typedef enum tsig_off_t {
  * \param nb Required number of bytes after the offset (for boundaries check).
  * \return pointer to field on wire or NULL.
  */
-static uint8_t* tsig_rdata_seek(const knot_rrset_t *rr, tsig_off_t id, size_t nb)
+static uint8_t* rdata_seek(const knot_rrset_t *rr, tsig_off_t id, size_t nb)
 {
 	const knot_rdata_t *rr_data = knot_rdataset_at(&rr->rrs, 0);
 	uint8_t *rd = knot_rdata_data(rr_data);
@@ -112,9 +114,9 @@ static uint8_t* tsig_rdata_seek(const knot_rrset_t *rr, tsig_off_t id, size_t nb
 	return rd;
 }
 
-static int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error)
+static int rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ERROR_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_ERROR_O, sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
@@ -123,7 +125,9 @@ static int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error)
 	return KNOT_EOK;
 }
 
-int tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg, uint16_t maclen, uint16_t tsig_err)
+_public_
+int knot_tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg,
+                           uint16_t maclen, uint16_t tsig_err)
 {
 	if (rr == NULL || alg == NULL) {
 		return KNOT_EINVAL;
@@ -151,14 +155,15 @@ int tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg, uint16_t maclen
 	}
 
 	/* Set error. */
-	tsig_rdata_set_tsig_error(rr, tsig_err);
+	rdata_set_tsig_error(rr, tsig_err);
 
 	return KNOT_EOK;
 }
 
-int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time)
+_public_
+int knot_tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_TSIGNED_O, 3*sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_TSIGNED_O, 3*sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
@@ -167,9 +172,22 @@ int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time)
 	return KNOT_EOK;
 }
 
-int tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge)
+_public_
+int knot_tsig_rdata_store_current_time(knot_rrset_t *tsig)
+{
+	if (!tsig) {
+		return KNOT_EINVAL;
+	}
+	time_t curr_time = time(NULL);
+	/*! \todo bleeding eyes. */
+	knot_tsig_rdata_set_time_signed(tsig, (uint64_t)curr_time);
+	return KNOT_EOK;
+}
+
+_public_
+int knot_tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_FUDGE_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_FUDGE_O, sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
@@ -178,9 +196,10 @@ int tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge)
 	return KNOT_EOK;
 }
 
-int tsig_rdata_set_mac(knot_rrset_t *tsig, uint16_t length, const uint8_t *mac)
+_public_
+int knot_tsig_rdata_set_mac(knot_rrset_t *tsig, uint16_t length, const uint8_t *mac)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_MAC_O, length);
+	uint8_t *rd = rdata_seek(tsig, TSIG_MAC_O, length);
 	if (!rd) {
 		return KNOT_ERROR;
 	}
@@ -192,9 +211,10 @@ int tsig_rdata_set_mac(knot_rrset_t *tsig, uint16_t length, const uint8_t *mac)
 	return KNOT_EOK;
 }
 
-int tsig_rdata_set_orig_id(knot_rrset_t *tsig, uint16_t id)
+_public_
+int knot_tsig_rdata_set_orig_id(knot_rrset_t *tsig, uint16_t id)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ORIGID_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_ORIGID_O, sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
@@ -204,15 +224,16 @@ int tsig_rdata_set_orig_id(knot_rrset_t *tsig, uint16_t id)
 	return KNOT_EOK;
 }
 
-int tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t len,
-                              const uint8_t *other_data)
+_public_
+int knot_tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t len,
+                                   const uint8_t *other_data)
 {
 	if (len > TSIG_OTHER_MAXLEN) {
 		dbg_tsig("TSIG: rdata: other len > %zu B\n", TSIG_OTHER_MAXLEN);
 		return KNOT_EINVAL;
 	}
 
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_OLEN_O, len+sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_OLEN_O, len+sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
@@ -225,16 +246,18 @@ int tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t len,
 	return KNOT_EOK;
 }
 
-const knot_dname_t *tsig_rdata_alg_name(const knot_rrset_t *tsig)
+_public_
+const knot_dname_t *knot_tsig_rdata_alg_name(const knot_rrset_t *tsig)
 {
 	const knot_rdata_t *rr_data = knot_rdataset_at(&tsig->rrs, 0);
 	return knot_rdata_data(rr_data);
 }
 
-knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
+_public_
+knot_tsig_algorithm_t knot_tsig_rdata_alg(const knot_rrset_t *tsig)
 {
 	/* Get the algorithm name. */
-	const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig);
+	const knot_dname_t *alg_name = knot_tsig_rdata_alg_name(tsig);
 	if (!alg_name) {
 		dbg_tsig("TSIG: rdata: cannot get algorithm name.\n");
 		return KNOT_TSIG_ALG_NULL;
@@ -257,80 +280,89 @@ knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
 	return item->id;
 }
 
-uint64_t tsig_rdata_time_signed(const knot_rrset_t *tsig)
+_public_
+uint64_t knot_tsig_rdata_time_signed(const knot_rrset_t *tsig)
 {
 	/*! \todo How to return invalid value? */
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_TSIGNED_O, 3*sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_TSIGNED_O, 3*sizeof(uint16_t));
 	if (!rd) {
 		return 0;
 	}
 	return knot_wire_read_u48(rd);
 }
 
-uint16_t tsig_rdata_fudge(const knot_rrset_t *tsig)
+_public_
+uint16_t knot_tsig_rdata_fudge(const knot_rrset_t *tsig)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_FUDGE_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_FUDGE_O, sizeof(uint16_t));
 	if (!rd) {
 		return 0;
 	}
 	return knot_wire_read_u16(rd);
 }
 
-const uint8_t *tsig_rdata_mac(const knot_rrset_t *tsig)
+_public_
+const uint8_t *knot_tsig_rdata_mac(const knot_rrset_t *tsig)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_MAC_O, 0);
+	uint8_t *rd = rdata_seek(tsig, TSIG_MAC_O, 0);
 	if (!rd) {
 		return NULL;
 	}
 	return rd;
 }
 
-size_t tsig_rdata_mac_length(const knot_rrset_t *tsig)
+_public_
+size_t knot_tsig_rdata_mac_length(const knot_rrset_t *tsig)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_MACLEN_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_MACLEN_O, sizeof(uint16_t));
 	if (!rd) {
 		return 0;
 	}
 	return knot_wire_read_u16(rd);
 }
 
-uint16_t tsig_rdata_orig_id(const knot_rrset_t *tsig)
+_public_
+uint16_t knot_tsig_rdata_orig_id(const knot_rrset_t *tsig)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ORIGID_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_ORIGID_O, sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
 	return knot_wire_read_u16(rd);
 }
 
-uint16_t tsig_rdata_error(const knot_rrset_t *tsig)
+_public_
+uint16_t knot_tsig_rdata_error(const knot_rrset_t *tsig)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ERROR_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_ERROR_O, sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
 	return knot_wire_read_u16(rd);
 }
 
-const uint8_t *tsig_rdata_other_data(const knot_rrset_t *tsig)
+_public_
+const uint8_t *knot_tsig_rdata_other_data(const knot_rrset_t *tsig)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_OTHER_O, 0);
+	uint8_t *rd = rdata_seek(tsig, TSIG_OTHER_O, 0);
 	if (!rd) {
 		return NULL;
 	}
 	return rd;
 }
 
-uint16_t tsig_rdata_other_data_length(const knot_rrset_t *tsig)
+_public_
+uint16_t knot_tsig_rdata_other_data_length(const knot_rrset_t *tsig)
 {
-	uint8_t *rd = tsig_rdata_seek(tsig, TSIG_OLEN_O, sizeof(uint16_t));
+	uint8_t *rd = rdata_seek(tsig, TSIG_OLEN_O, sizeof(uint16_t));
 	if (!rd) {
 		return KNOT_ERROR;
 	}
 	return knot_wire_read_u16(rd);
 }
 
-int tsig_alg_from_name(const knot_dname_t *alg_name)
+_public_
+int knot_tsig_alg_from_name(const knot_dname_t *alg_name)
 {
 	if (!alg_name) {
 		return 0;
@@ -355,7 +387,8 @@ int tsig_alg_from_name(const knot_dname_t *alg_name)
 	return found->id;
 }
 
-size_t tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig)
+_public_
+size_t knot_tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig)
 {
 	if (tsig == NULL) {
 		return 0;
@@ -366,35 +399,33 @@ size_t tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig)
 		return 0;
 	}
 
-	const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig);
+	const knot_dname_t *alg_name = knot_tsig_rdata_alg_name(tsig);
 	if (!alg_name) {
 		return 0;
 	}
 
-	uint16_t other_data_length = tsig_rdata_other_data_length(tsig);
+	uint16_t other_data_length = knot_tsig_rdata_other_data_length(tsig);
 
 	return knot_dname_size(key_name) + knot_dname_size(alg_name) +
 	       other_data_length + KNOT_TSIG_VARIABLES_LENGTH;
 }
 
-size_t tsig_rdata_tsig_timers_length()
+_public_
+size_t knot_tsig_rdata_tsig_timers_length()
 {
 	/*! \todo Cleanup */
 	return KNOT_TSIG_TIMERS_LENGTH;
 }
 
-int tsig_rdata_store_current_time(knot_rrset_t *tsig)
-{
-	if (!tsig) {
-		return KNOT_EINVAL;
-	}
-	time_t curr_time = time(NULL);
-	/*! \todo bleeding eyes. */
-	tsig_rdata_set_time_signed(tsig, (uint64_t)curr_time);
-	return KNOT_EOK;
-}
-
-const char* tsig_alg_to_str(knot_tsig_algorithm_t alg)
+/*!
+ * \brief Convert TSIG algorithm identifier to name.
+ *
+ * \param alg TSIG algorithm identifier.
+ *
+ * \retval TSIG algorithm string name.
+ * \retval Empty string if undefined.
+ */
+static const char *alg_to_str(knot_tsig_algorithm_t alg)
 {
 	knot_lookup_table_t *item;
 
@@ -407,7 +438,8 @@ const char* tsig_alg_to_str(knot_tsig_algorithm_t alg)
 	}
 }
 
-const knot_dname_t* tsig_alg_to_dname(knot_tsig_algorithm_t alg)
+_public_
+const knot_dname_t *knot_tsig_alg_to_dname(knot_tsig_algorithm_t alg)
 {
 	knot_lookup_table_t *item;
 
@@ -420,13 +452,14 @@ const knot_dname_t* tsig_alg_to_dname(knot_tsig_algorithm_t alg)
 	}
 }
 
-size_t tsig_wire_maxsize(const knot_tsig_key_t *key)
+_public_
+size_t knot_tsig_wire_maxsize(const knot_tsig_key_t *key)
 {
 	if (key == NULL) {
 		return 0;
 	}
 
-	size_t alg_name_size = strlen(tsig_alg_to_str(key->algorithm)) + 1;
+	size_t alg_name_size = strlen(alg_to_str(key->algorithm)) + 1;
 
 	/*! \todo Used fixed size as a base. */
 	return knot_dname_size(key->name) +
@@ -445,13 +478,14 @@ size_t tsig_wire_maxsize(const knot_tsig_key_t *key)
 	6* sizeof(uint8_t); /* uint48_t in case of BADTIME RCODE */
 }
 
-int tsig_rdata_is_ok(const knot_rrset_t *tsig)
+_public_
+int knot_tsig_rdata_is_ok(const knot_rrset_t *tsig)
 {
 	/*! \todo Check size, needs to check variable-length fields. */
 	const knot_rdata_t *rr_data = knot_rdataset_at(&tsig->rrs, 0);
 	return (tsig
 	        && knot_rdata_data(rr_data) != NULL
-	        && tsig_rdata_seek(tsig, TSIG_OTHER_O, 0) != NULL
-	        && tsig_rdata_alg_name(tsig) != NULL
-	        && tsig_rdata_time_signed(tsig) != 0);
+	        && rdata_seek(tsig, TSIG_OTHER_O, 0) != NULL
+	        && knot_tsig_rdata_alg_name(tsig) != NULL
+	        && knot_tsig_rdata_time_signed(tsig) != 0);
 }
diff --git a/src/libknot/rrtype/tsig.h b/src/libknot/rrtype/tsig.h
index 04425a78a8962cddced57827256309023634ec5e..a17954bc2e670a144947196b886fe6a6690cffc9 100644
--- a/src/libknot/rrtype/tsig.h
+++ b/src/libknot/rrtype/tsig.h
@@ -77,44 +77,47 @@ typedef struct knot_sign_context {
  * \retval KNOT_EINVAL
  * \retval KNOT_EOK
  */
-int tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg,
+int knot_tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg,
                       uint16_t maclen, uint16_t tsig_err);
 
-int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time);
-int tsig_rdata_store_current_time(knot_rrset_t *tsig);
-int tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge);
-int tsig_rdata_set_mac(knot_rrset_t *tsig, uint16_t length,
-                       const uint8_t *mac);
-int tsig_rdata_set_orig_id(knot_rrset_t *tsig, uint16_t id);
-//int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error);
-int tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t length,
+int knot_tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time);
+
+int knot_tsig_rdata_store_current_time(knot_rrset_t *tsig);
+
+int knot_tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge);
+
+int knot_tsig_rdata_set_mac(knot_rrset_t *tsig, uint16_t length, const uint8_t *mac);
+
+int knot_tsig_rdata_set_orig_id(knot_rrset_t *tsig, uint16_t id);
+
+int knot_tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t length,
                               const uint8_t *other_data);
 
-const knot_dname_t *tsig_rdata_alg_name(const knot_rrset_t *tsig);
-knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig);
-uint64_t tsig_rdata_time_signed(const knot_rrset_t *tsig);
-uint16_t tsig_rdata_fudge(const knot_rrset_t *tsig);
-const uint8_t *tsig_rdata_mac(const knot_rrset_t *tsig);
-size_t tsig_rdata_mac_length(const knot_rrset_t *tsig);
-uint16_t tsig_rdata_orig_id(const knot_rrset_t *tsig);
-uint16_t tsig_rdata_error(const knot_rrset_t *tsig);
-const uint8_t *tsig_rdata_other_data(const knot_rrset_t *tsig);
-uint16_t tsig_rdata_other_data_length(const knot_rrset_t *tsig);
-size_t tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig);
+const knot_dname_t *knot_tsig_rdata_alg_name(const knot_rrset_t *tsig);
 
-size_t tsig_rdata_tsig_timers_length();
+knot_tsig_algorithm_t knot_tsig_rdata_alg(const knot_rrset_t *tsig);
 
-int tsig_alg_from_name(const knot_dname_t *name);
+uint64_t knot_tsig_rdata_time_signed(const knot_rrset_t *tsig);
 
-/*!
- * \brief Convert TSIG algorithm identifier to name.
- *
- * \param alg TSIG algorithm identifier.
- *
- * \retval TSIG algorithm string name.
- * \retval Empty string if undefined.
- */
-const char* tsig_alg_to_str(knot_tsig_algorithm_t alg);
+uint16_t knot_tsig_rdata_fudge(const knot_rrset_t *tsig);
+
+const uint8_t *knot_tsig_rdata_mac(const knot_rrset_t *tsig);
+
+size_t knot_tsig_rdata_mac_length(const knot_rrset_t *tsig);
+
+uint16_t knot_tsig_rdata_orig_id(const knot_rrset_t *tsig);
+
+uint16_t knot_tsig_rdata_error(const knot_rrset_t *tsig);
+
+const uint8_t *knot_tsig_rdata_other_data(const knot_rrset_t *tsig);
+
+uint16_t knot_tsig_rdata_other_data_length(const knot_rrset_t *tsig);
+
+size_t knot_tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig);
+
+size_t knot_tsig_rdata_tsig_timers_length();
+
+int knot_tsig_alg_from_name(const knot_dname_t *name);
 
 /*!
  * \brief Convert TSIG algorithm identifier to domain name.
@@ -124,7 +127,7 @@ const char* tsig_alg_to_str(knot_tsig_algorithm_t alg);
  * \retval TSIG algorithm string name.
  * \retval Empty string if undefined.
  */
-const knot_dname_t* tsig_alg_to_dname(knot_tsig_algorithm_t alg);
+const knot_dname_t *knot_tsig_alg_to_dname(knot_tsig_algorithm_t alg);
 
 /*!
  * \brief Return TSIG RRSET maximum wire size for given algorithm.
@@ -133,8 +136,9 @@ const knot_dname_t* tsig_alg_to_dname(knot_tsig_algorithm_t alg);
  *
  * \return RRSET wire size.
  */
-size_t tsig_wire_maxsize(const knot_tsig_key_t *key);
+size_t knot_tsig_wire_maxsize(const knot_tsig_key_t *key);
 
-int tsig_rdata_is_ok(const knot_rrset_t *tsig);
+/*! \todo Documentation. */
+int knot_tsig_rdata_is_ok(const knot_rrset_t *tsig);
 
 /*! @} */
diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c
index b57cb4cce6a2e9f0a8e7421a8ccfdc4913df2a6f..76c2e5e55ad3dfd874b42d1c7c6d3213f9be7cd0 100644
--- a/src/libknot/tsig-op.c
+++ b/src/libknot/tsig-op.c
@@ -25,7 +25,9 @@
 
 #include "common/debug.h"
 #include "common/log.h"
-#include "libknot/common.h"
+#include "common/macros.h"
+
+#include "libknot/errcode.h"
 #include "libknot/descriptor.h"
 #include "libknot/rrtype/tsig.h"
 #include "libknot/packet/wire.h"
@@ -36,18 +38,18 @@
 const int KNOT_TSIG_MAX_DIGEST_SIZE = 64;    // size of HMAC-SHA512 digest
 const uint16_t KNOT_TSIG_FUDGE_DEFAULT = 300;  // default Fudge value
 
-static int knot_tsig_check_algorithm(const knot_rrset_t *tsig_rr)
+static int check_algorithm(const knot_rrset_t *tsig_rr)
 {
 	if (tsig_rr == NULL) {
 		return KNOT_EINVAL;
 	}
 
-	const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig_rr);
+	const knot_dname_t *alg_name = knot_tsig_rdata_alg_name(tsig_rr);
 	if (!alg_name) {
 		return KNOT_EMALF;
 	}
 
-	knot_tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
+	knot_tsig_algorithm_t alg = knot_tsig_alg_from_name(alg_name);
 	if (alg == 0) {
 		/*!< \todo is this error OK? */
 		dbg_tsig("TSIG: unknown algorithm.\n");
@@ -57,8 +59,8 @@ static int knot_tsig_check_algorithm(const knot_rrset_t *tsig_rr)
 	return KNOT_EOK;
 }
 
-static int knot_tsig_check_key(const knot_rrset_t *tsig_rr,
-                               const knot_tsig_key_t *tsig_key)
+static int check_key(const knot_rrset_t *tsig_rr,
+                     const knot_tsig_key_t *tsig_key)
 {
 	if (tsig_rr == NULL || tsig_key == NULL) {
 		return KNOT_EINVAL;
@@ -85,9 +87,9 @@ static int knot_tsig_check_key(const knot_rrset_t *tsig_rr,
 	return KNOT_EOK;
 }
 
-static int knot_tsig_compute_digest(const uint8_t *wire, size_t wire_len,
-                                    uint8_t *digest, size_t *digest_len,
-                                    const knot_tsig_key_t *key)
+static int compute_digest(const uint8_t *wire, size_t wire_len,
+                          uint8_t *digest, size_t *digest_len,
+                          const knot_tsig_key_t *key)
 {
 	if (!wire || !digest || !digest_len || !key) {
 		dbg_tsig("TSIG: digest: bad args.\n");
@@ -152,8 +154,8 @@ static int knot_tsig_compute_digest(const uint8_t *wire, size_t wire_len,
 	return KNOT_EOK;
 }
 
-static int knot_tsig_check_time_signed(const knot_rrset_t *tsig_rr,
-                                       uint64_t prev_time_signed)
+static int check_time_signed(const knot_rrset_t *tsig_rr,
+                             uint64_t prev_time_signed)
 {
 	if (!tsig_rr) {
 		dbg_tsig("TSIG: check_time_signed: NULL argument.\n");
@@ -161,11 +163,11 @@ static int knot_tsig_check_time_signed(const knot_rrset_t *tsig_rr,
 	}
 
 	/* Get the time signed and fudge values. */
-	uint64_t time_signed = tsig_rdata_time_signed(tsig_rr);
+	uint64_t time_signed = knot_tsig_rdata_time_signed(tsig_rr);
 	if (time_signed == 0) {
 		return KNOT_TSIG_EBADTIME;
 	}
-	uint16_t fudge = tsig_rdata_fudge(tsig_rr);
+	uint16_t fudge = knot_tsig_rdata_fudge(tsig_rr);
 	if (fudge == 0) {
 		return KNOT_TSIG_EBADTIME;
 	}
@@ -189,8 +191,7 @@ static int knot_tsig_check_time_signed(const knot_rrset_t *tsig_rr,
 	return KNOT_EOK;
 }
 
-static int knot_tsig_write_tsig_variables(uint8_t *wire,
-                                          const knot_rrset_t *tsig_rr)
+static int write_tsig_variables(uint8_t *wire, const knot_rrset_t *tsig_rr)
 {
 	if (wire == NULL || tsig_rr == NULL) {
 		dbg_tsig("TSIG: write tsig variables: NULL arguments.\n");
@@ -223,7 +224,7 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
 	offset += sizeof(uint32_t);
 
 	/* Copy alg name. */
-	const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig_rr);
+	const knot_dname_t *alg_name = knot_tsig_rdata_alg_name(tsig_rr);
 	if (!alg_name) {
 		dbg_tsig("TSIG: write variables: no algorithm name.\n");
 		return KNOT_EINVAL;
@@ -240,23 +241,23 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
 
 	/* Following data are written in network order. */
 	/* Time signed. */
-	knot_wire_write_u48(wire + offset, tsig_rdata_time_signed(tsig_rr));
+	knot_wire_write_u48(wire + offset, knot_tsig_rdata_time_signed(tsig_rr));
 	offset += 6;
 	dbg_tsig_verb("TSIG: write variables: time signed: %"PRIu64" \n",
-	              tsig_rdata_time_signed(tsig_rr));
+	              knot_tsig_rdata_time_signed(tsig_rr));
 	dbg_tsig_hex_detail((char *)(wire + offset - 6), 6);
 	/* Fudge. */
-	knot_wire_write_u16(wire + offset, tsig_rdata_fudge(tsig_rr));
+	knot_wire_write_u16(wire + offset, knot_tsig_rdata_fudge(tsig_rr));
 	offset += sizeof(uint16_t);
 	dbg_tsig_verb("TSIG: write variables: fudge: %hu\n",
-	              tsig_rdata_fudge(tsig_rr));
+	              knot_tsig_rdata_fudge(tsig_rr));
 	/* TSIG error. */
-	knot_wire_write_u16(wire + offset, tsig_rdata_error(tsig_rr));
+	knot_wire_write_u16(wire + offset, knot_tsig_rdata_error(tsig_rr));
 	offset += sizeof(uint16_t);
 	/* Get other data length. */
-	uint16_t other_data_length = tsig_rdata_other_data_length(tsig_rr);
+	uint16_t other_data_length = knot_tsig_rdata_other_data_length(tsig_rr);
 	/* Get other data. */
-	const uint8_t *other_data = tsig_rdata_other_data(tsig_rr);
+	const uint8_t *other_data = knot_tsig_rdata_other_data(tsig_rr);
 	if (!other_data) {
 		dbg_tsig("TSIG: write variables: no other data.\n");
 		return KNOT_EINVAL;
@@ -276,8 +277,7 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
 	return KNOT_EOK;
 }
 
-static int knot_tsig_wire_write_timers(uint8_t *wire,
-                                       const knot_rrset_t *tsig_rr)
+static int wire_write_timers(uint8_t *wire, const knot_rrset_t *tsig_rr)
 {
 	if (wire == NULL || tsig_rr == NULL) {
 		dbg_tsig("TSIG: write timers: NULL arguments.\n");
@@ -285,19 +285,18 @@ static int knot_tsig_wire_write_timers(uint8_t *wire,
 	}
 
 	//write time signed
-	knot_wire_write_u48(wire, tsig_rdata_time_signed(tsig_rr));
+	knot_wire_write_u48(wire, knot_tsig_rdata_time_signed(tsig_rr));
 	//write fudge
-	knot_wire_write_u16(wire + 6, tsig_rdata_fudge(tsig_rr));
+	knot_wire_write_u16(wire + 6, knot_tsig_rdata_fudge(tsig_rr));
 
 	return KNOT_EOK;
 }
 
-static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
-				      const uint8_t *request_mac,
-		                      size_t request_mac_len,
-		                      uint8_t *digest, size_t *digest_len,
-				      const knot_rrset_t *tmp_tsig,
-		                      const knot_tsig_key_t *key)
+static int create_sign_wire(const uint8_t *msg, size_t msg_len,
+                            const uint8_t *request_mac, size_t request_mac_len,
+                            uint8_t *digest, size_t *digest_len,
+                            const knot_rrset_t *tmp_tsig,
+                            const knot_tsig_key_t *key)
 {
 	if (!msg || !key || digest_len == NULL) {
 		dbg_tsig("TSIG: create wire: bad args.\n");
@@ -313,14 +312,13 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
 	 */
 	dbg_tsig_verb("Counting wire size: %zu, %zu, %zu.\n",
 	              msg_len, request_mac_len,
-	              tsig_rdata_tsig_variables_length(tmp_tsig));
+	              knot_tsig_rdata_tsig_variables_length(tmp_tsig));
 	size_t wire_len = sizeof(uint8_t) *
 			(msg_len + request_mac_len + ((request_mac_len > 0)
 			 ? 2 : 0) +
-			tsig_rdata_tsig_variables_length(tmp_tsig));
+			knot_tsig_rdata_tsig_variables_length(tmp_tsig));
 	uint8_t *wire = malloc(wire_len);
 	if (!wire) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
@@ -345,7 +343,7 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
 	pos += msg_len;
 	/* Copy TSIG variables. */
 	dbg_tsig_verb("Writing TSIG variables.\n");
-	ret = knot_tsig_write_tsig_variables(pos, tmp_tsig);
+	ret = write_tsig_variables(pos, tmp_tsig);
 	if (ret != KNOT_EOK) {
 		dbg_tsig("TSIG: create wire: failed to write TSIG "
 		         "variables: %s\n", knot_strerror(ret));
@@ -354,7 +352,7 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
 	}
 
 	/* Compute digest. */
-	ret = knot_tsig_compute_digest(wire, wire_len, digest, digest_len, key);
+	ret = compute_digest(wire, wire_len, digest, digest_len, key);
 	if (ret != KNOT_EOK) {
 		dbg_tsig("TSIG: create wire: failed to compute digest: %s\n",
 		         knot_strerror(ret));
@@ -368,12 +366,11 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
 	return KNOT_EOK;
 }
 
-static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
-                                           const uint8_t *prev_mac,
-                                           size_t prev_mac_len,
-                                           uint8_t *digest, size_t *digest_len,
-                                           const knot_rrset_t *tmp_tsig,
-                                           const knot_tsig_key_t *key)
+static int create_sign_wire_next(const uint8_t *msg, size_t msg_len,
+                                 const uint8_t *prev_mac, size_t prev_mac_len,
+                                 uint8_t *digest, size_t *digest_len,
+                                 const knot_rrset_t *tmp_tsig,
+                                 const knot_tsig_key_t *key)
 {
 	if (!msg || !key || digest_len == NULL) {
 		dbg_tsig("TSIG: create wire: bad args.\n");
@@ -389,13 +386,12 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
 	 */
 	dbg_tsig_verb("Counting wire size: %zu, %zu, %zu.\n",
 	              msg_len, prev_mac_len,
-	              tsig_rdata_tsig_timers_length());
+	              knot_tsig_rdata_tsig_timers_length());
 	size_t wire_len = sizeof(uint8_t) *
 	                (msg_len + prev_mac_len +
-			tsig_rdata_tsig_timers_length() + 2);
+			knot_tsig_rdata_tsig_timers_length() + 2);
 	uint8_t *wire = malloc(wire_len);
 	if (!wire) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
@@ -414,7 +410,7 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
 	/* Copy TSIG variables. */
 
 	dbg_tsig_verb("Writing TSIG timers.\n");
-	ret = knot_tsig_wire_write_timers(wire + prev_mac_len + msg_len + 2,
+	ret = wire_write_timers(wire + prev_mac_len + msg_len + 2,
 	                                  tmp_tsig);
 	if (ret != KNOT_EOK) {
 		dbg_tsig("TSIG: create wire: failed to write TSIG "
@@ -424,7 +420,7 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
 	}
 
 	/* Compute digest. */
-	ret = knot_tsig_compute_digest(wire, wire_len,
+	ret = compute_digest(wire, wire_len,
 	                               digest, digest_len, key);
 	if (ret != KNOT_EOK) {
 		dbg_tsig("TSIG: create wire: failed to compute digest: %s\n",
@@ -439,9 +435,9 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
 	return KNOT_EOK;
 }
 
-int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
-                   size_t msg_max_len, const uint8_t *request_mac,
-                   size_t request_mac_len,
+_public_
+int knot_tsig_sign(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
+                   const uint8_t *request_mac, size_t request_mac_len,
                    uint8_t *digest, size_t *digest_len,
                    const knot_tsig_key_t *key, uint16_t tsig_rcode,
                    uint64_t request_time_signed)
@@ -462,13 +458,13 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
 	uint16_t rdata_rcode = 0;
 	if (tsig_rcode == KNOT_TSIG_ERR_BADTIME)
 		rdata_rcode = tsig_rcode;
-	tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm),
+	knot_tsig_create_rdata(tmp_tsig, knot_tsig_alg_to_dname(key->algorithm),
 	                  knot_tsig_digest_length(key->algorithm), rdata_rcode);
 
 	/* Distinguish BADTIME response. */
 	if (tsig_rcode == KNOT_TSIG_ERR_BADTIME) {
 		/* Set client's time signed into the time signed field. */
-		tsig_rdata_set_time_signed(tmp_tsig, request_time_signed);
+		knot_tsig_rdata_set_time_signed(tmp_tsig, request_time_signed);
 
 		/* Store current time into Other data. */
 		uint8_t time_signed[6];
@@ -477,24 +473,24 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
 		uint64_t time64 = curr_time;
 		knot_wire_write_u48(time_signed, time64);
 
-		tsig_rdata_set_other_data(tmp_tsig, 6, time_signed);
+		knot_tsig_rdata_set_other_data(tmp_tsig, 6, time_signed);
 	} else {
-		tsig_rdata_store_current_time(tmp_tsig);
+		knot_tsig_rdata_store_current_time(tmp_tsig);
 
 		/* Set other len. */
-		tsig_rdata_set_other_data(tmp_tsig, 0, 0);
+		knot_tsig_rdata_set_other_data(tmp_tsig, 0, 0);
 	}
 
-	tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
+	knot_tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
 
 	/* Set original ID */
-	tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
+	knot_tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
 
 	uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
 	size_t digest_tmp_len = 0;
 
 	int ret = KNOT_ERROR;
-	ret = knot_tsig_create_sign_wire(msg, *msg_len, /*msg_max_len,*/
+	ret = create_sign_wire(msg, *msg_len, /*msg_max_len,*/
 	                                     request_mac, request_mac_len,
 	                                     digest_tmp, &digest_tmp_len,
 					     tmp_tsig, key);
@@ -506,7 +502,7 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
 	}
 
 	/* Set the digest. */
-	tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);
+	knot_tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);
 
 	/* Write RRSet to wire */
 
@@ -536,6 +532,7 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
 	return KNOT_EOK;
 }
 
+_public_
 int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
                         const uint8_t *prev_digest, size_t prev_digest_len,
                         uint8_t *digest, size_t *digest_len,
@@ -555,17 +552,16 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
 	}
 
 	/* Create rdata for TSIG RR. */
-	tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm),
+	knot_tsig_create_rdata(tmp_tsig, knot_tsig_alg_to_dname(key->algorithm),
 	                  knot_tsig_digest_length(key->algorithm), 0);
-	tsig_rdata_store_current_time(tmp_tsig);
-	tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
+	knot_tsig_rdata_store_current_time(tmp_tsig);
+	knot_tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
 
 	/* Create wire to be signed. */
 	size_t wire_len = prev_digest_len + to_sign_len
 	                  + KNOT_TSIG_TIMERS_LENGTH + 2;
 	uint8_t *wire = malloc(wire_len);
 	if (!wire) {
-		ERR_ALLOC_FAILED;
 		knot_rrset_free(&tmp_tsig, NULL);
 		return KNOT_ENOMEM;
 	}
@@ -578,7 +574,7 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
 	/* Write original message. */
 	memcpy(wire + prev_digest_len + 2, to_sign, to_sign_len);
 	/* Write timers. */
-	knot_tsig_wire_write_timers(wire + prev_digest_len + to_sign_len + 2,
+	wire_write_timers(wire + prev_digest_len + to_sign_len + 2,
 	                            tmp_tsig);
 
 	dbg_tsig_detail("Previous digest: \n");
@@ -589,7 +585,7 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
 			    KNOT_TSIG_TIMERS_LENGTH);
 
 	int ret = KNOT_ERROR;
-	ret = knot_tsig_compute_digest(wire, wire_len,
+	ret = compute_digest(wire, wire_len,
 	                               digest_tmp, &digest_tmp_len, key);
 
 	/* No matter how the function did, this data is no longer needed. */
@@ -607,13 +603,13 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
 	}
 
 	/* Set the MAC. */
-	tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);
+	knot_tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);
 
 	/* Set original id. */
-	tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
+	knot_tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
 
 	/* Set other data. */
-	tsig_rdata_set_other_data(tmp_tsig, 0, NULL);
+	knot_tsig_rdata_set_other_data(tmp_tsig, 0, NULL);
 
 	dbg_tsig_verb("Message max length: %zu, message length: %zu\n",
 	              msg_max_len, *msg_len);
@@ -640,13 +636,11 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
 	return KNOT_EOK;
 }
 
-static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
-                                  const uint8_t *wire, size_t size,
-                                  const uint8_t *request_mac,
-                                  size_t request_mac_len,
-                                  const knot_tsig_key_t *tsig_key,
-                                  uint64_t prev_time_signed,
-                                  int use_times)
+static int check_digest(const knot_rrset_t *tsig_rr,
+                        const uint8_t *wire, size_t size,
+                        const uint8_t *request_mac, size_t request_mac_len,
+                        const knot_tsig_key_t *tsig_key,
+                        uint64_t prev_time_signed, int use_times)
 {
 	if (!wire || !tsig_key) {
 		return KNOT_EINVAL;
@@ -658,7 +652,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
 	}
 
 	/* Check time signed. */
-	int ret = knot_tsig_check_time_signed(tsig_rr, prev_time_signed);
+	int ret = check_time_signed(tsig_rr, prev_time_signed);
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
@@ -666,7 +660,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
 	dbg_tsig_verb("TSIG: time checked.\n");
 
 	/* Check that libknot knows the algorithm. */
-	ret = knot_tsig_check_algorithm(tsig_rr);
+	ret = check_algorithm(tsig_rr);
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
@@ -674,7 +668,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
 	dbg_tsig_verb("TSIG: algorithm checked.\n");
 
 	/* Check that key is valid, ie. the same as given in args. */
-	ret = knot_tsig_check_key(tsig_rr, tsig_key);
+	ret = check_key(tsig_rr, tsig_key);
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
@@ -683,7 +677,6 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
 
 	uint8_t *wire_to_sign = malloc(sizeof(uint8_t) * size);
 	if (!wire_to_sign) {
-		ERR_ALLOC_FAILED;
 		return KNOT_ENOMEM;
 	}
 
@@ -696,15 +689,15 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
 
 	if (use_times) {
 		/* Wire is not a single packet, TSIG RRs must be stripped already. */
-		ret = knot_tsig_create_sign_wire_next(wire_to_sign, size,
+		ret = create_sign_wire_next(wire_to_sign, size,
 		                                 request_mac, request_mac_len,
 		                                 digest_tmp, &digest_tmp_len,
 		                                 tsig_rr, tsig_key);
 	} else {
-		ret = knot_tsig_create_sign_wire(wire_to_sign, size,
-		                                 request_mac, request_mac_len,
-		                                 digest_tmp, &digest_tmp_len,
-		                                 tsig_rr, tsig_key);
+		ret = create_sign_wire(wire_to_sign, size,
+		                            request_mac, request_mac_len,
+		                            digest_tmp, &digest_tmp_len,
+		                            tsig_rr, tsig_key);
 	}
 
 	assert(tsig_rr->rrs.rr_count > 0);
@@ -721,12 +714,12 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
 	/* Compare MAC from TSIG RR RDATA with just computed digest. */
 
 	/*!< \todo move to function. */
-	const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig_rr);
-	knot_tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
+	const knot_dname_t *alg_name = knot_tsig_rdata_alg_name(tsig_rr);
+	knot_tsig_algorithm_t alg = knot_tsig_alg_from_name(alg_name);
 
 	/*! \todo [TSIG] TRUNCATION */
-	uint16_t mac_length = tsig_rdata_mac_length(tsig_rr);
-	const uint8_t *tsig_mac = tsig_rdata_mac(tsig_rr);
+	uint16_t mac_length = knot_tsig_rdata_mac_length(tsig_rr);
+	const uint8_t *tsig_mac = knot_tsig_rdata_mac(tsig_rr);
 
 	if (mac_length != knot_tsig_digest_length(alg)) {
 		dbg_tsig("TSIG: calculated digest length and given length do "
@@ -747,15 +740,17 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
 	return KNOT_EOK;
 }
 
+_public_
 int knot_tsig_server_check(const knot_rrset_t *tsig_rr,
                            const uint8_t *wire, size_t size,
                            const knot_tsig_key_t *tsig_key)
 {
 	dbg_tsig("tsig_server_check()\n");
-	return knot_tsig_check_digest(tsig_rr, wire, size, NULL, 0, tsig_key,
+	return check_digest(tsig_rr, wire, size, NULL, 0, tsig_key,
 	                              0, 0);
 }
 
+_public_
 int knot_tsig_client_check(const knot_rrset_t *tsig_rr,
                            const uint8_t *wire, size_t size,
                            const uint8_t *request_mac, size_t request_mac_len,
@@ -763,11 +758,12 @@ int knot_tsig_client_check(const knot_rrset_t *tsig_rr,
                            uint64_t prev_time_signed)
 {
 	dbg_tsig("tsig_client_check()\n");
-	return knot_tsig_check_digest(tsig_rr, wire, size, request_mac,
+	return check_digest(tsig_rr, wire, size, request_mac,
 	                              request_mac_len, tsig_key,
 	                              prev_time_signed, 0);
 }
 
+_public_
 int knot_tsig_client_check_next(const knot_rrset_t *tsig_rr,
                                 const uint8_t *wire, size_t size,
                                 const uint8_t *prev_digest,
@@ -776,11 +772,12 @@ int knot_tsig_client_check_next(const knot_rrset_t *tsig_rr,
                                 uint64_t prev_time_signed)
 {
 	dbg_tsig("tsig_client_check_next()\n");
-	return knot_tsig_check_digest(tsig_rr, wire, size, prev_digest,
+	return check_digest(tsig_rr, wire, size, prev_digest,
 	                              prev_digest_len, tsig_key,
 	                              prev_time_signed, 1);
 }
 
+_public_
 int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
                   uint16_t tsig_rcode, const knot_rrset_t *tsig_rr)
 {
@@ -800,19 +797,19 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
 	}
 
 	assert(tsig_rcode != KNOT_TSIG_ERR_BADTIME);
-	tsig_create_rdata(tmp_tsig, tsig_rdata_alg_name(tsig_rr), 0, tsig_rcode);
-	tsig_rdata_set_time_signed(tmp_tsig, tsig_rdata_time_signed(tsig_rr));
+	knot_tsig_create_rdata(tmp_tsig, knot_tsig_rdata_alg_name(tsig_rr), 0, tsig_rcode);
+	knot_tsig_rdata_set_time_signed(tmp_tsig, knot_tsig_rdata_time_signed(tsig_rr));
 
 	/* Comparing to BIND it was found out that the Fudge should always be
 	 * set to the server's value.
 	 */
-	tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
+	knot_tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
 
 	/* Set original ID */
-	tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
+	knot_tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
 
 	/* Set other len. */
-	tsig_rdata_set_other_data(tmp_tsig, 0, 0);
+	knot_tsig_rdata_set_other_data(tmp_tsig, 0, 0);
 
 	/* Append TSIG RR. */
 	int ret = knot_tsig_append(msg, msg_len, msg_max_len, tmp_tsig);
@@ -823,6 +820,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
 	return ret;
 }
 
+_public_
 int knot_tsig_append(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
                      const knot_rrset_t *tsig_rr)
 {
diff --git a/src/libknot/tsig-op.h b/src/libknot/tsig-op.h
index b6bb4cd5cf5447f0171ef67a7ff4de332bc607ff..71e193049aef6c9db2af6735eed8cc90eb3fb5ce 100644
--- a/src/libknot/tsig-op.h
+++ b/src/libknot/tsig-op.h
@@ -160,14 +160,21 @@ int knot_tsig_client_check_next(const knot_rrset_t *tsig_rr,
                                 const knot_tsig_key_t *key,
                                 uint64_t prev_time_signed);
 
+/*!
+ * \todo Documentation!
+ */
 int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
                   uint16_t tsig_rcode, const knot_rrset_t *tsig_rr);
 
-/*! \brief Append TSIG RR to message. */
+/*! \brief Append TSIG RR to message.
+ *  \todo Proper documentation.
+ */
 int knot_tsig_append(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
                      const knot_rrset_t *tsig_rr);
 
-/*! \brief Return true if the TSIG RCODE allows signing the packet. */
+/*! \brief Return true if the TSIG RCODE allows signing the packet.
+ *  \todo Proper documentation.
+ */
 static inline bool knot_tsig_can_sign(uint16_t tsig_rcode) {
 	return (tsig_rcode == KNOT_RCODE_NOERROR || tsig_rcode == KNOT_TSIG_ERR_BADTIME);
 }
diff --git a/src/libknot/util/tolower.c b/src/libknot/util/tolower.c
index ffa10ab4a0226b9d0df2d25bb8dcbb51bda1189f..a441c6edfc25c4b4802ad052dba60d493bc5dbaf 100644
--- a/src/libknot/util/tolower.c
+++ b/src/libknot/util/tolower.c
@@ -15,8 +15,10 @@
  */
 
 #include "libknot/util/tolower.h"
+#include "common/macros.h"
 
-const uint8_t char_table[KNOT_CHAR_TABLE_SIZE] = {
+_public_
+const uint8_t knot_char_table[KNOT_CHAR_TABLE_SIZE] = {
 	'\x00',
 	'\x01',
 	'\x02',
diff --git a/src/libknot/util/tolower.h b/src/libknot/util/tolower.h
index b41aeb3deb1b4f897e8553cfc1d19629ac6060b2..1ca6103cfa9d4dbd3b450c1d68674f6728620c0a 100644
--- a/src/libknot/util/tolower.h
+++ b/src/libknot/util/tolower.h
@@ -33,7 +33,7 @@
 #define KNOT_CHAR_TABLE_SIZE (UINT8_MAX + 1)
 
 /*! \brief Character table mapping uppercase letters to lowercase. */
-extern const uint8_t char_table[KNOT_CHAR_TABLE_SIZE];
+extern const uint8_t knot_char_table[KNOT_CHAR_TABLE_SIZE];
 
 /*!
  * \brief Converts binary character to lowercase.
@@ -43,7 +43,7 @@ extern const uint8_t char_table[KNOT_CHAR_TABLE_SIZE];
  * \return \a c converted to lowercase (or \a c if not applicable).
  */
 static inline uint8_t knot_tolower(uint8_t c) {
-	return char_table[c];
+	return knot_char_table[c];
 }
 
 /*!
diff --git a/src/libknot/util/utils.c b/src/libknot/util/utils.c
index cce26264ed9626af908f68dea63ae6eb0fda92ed..6e8ca0677df4f9324ae5606548a864670b06d0a0 100644
--- a/src/libknot/util/utils.c
+++ b/src/libknot/util/utils.c
@@ -19,11 +19,13 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "libknot/common.h"
 #include "libknot/util/utils.h"
 
-/*----------------------------------------------------------------------------*/
+#include "libknot/util/endian.h"
+#include "common/macros.h"
 
+/*----------------------------------------------------------------------------*/
+_public_
 knot_lookup_table_t *knot_lookup_by_name(knot_lookup_table_t *table,
                                              const char *name)
 {
@@ -38,7 +40,7 @@ knot_lookup_table_t *knot_lookup_by_name(knot_lookup_table_t *table,
 }
 
 /*----------------------------------------------------------------------------*/
-
+_public_
 knot_lookup_table_t *knot_lookup_by_id(knot_lookup_table_t *table,
                                            int id)
 {
@@ -59,6 +61,7 @@ static int32_t serial_difference(uint32_t s1, uint32_t s2)
 	return (((int64_t)s1 - s2) % ((int64_t)1 << 32));
 }
 
+_public_
 int knot_serial_compare(uint32_t s1, uint32_t s2)
 {
 	int32_t diff = serial_difference(s1, s2);
@@ -68,3 +71,54 @@ int knot_serial_compare(uint32_t s1, uint32_t s2)
 	           ? 1	/* s1 larger than s2 */
 	           : -1); /* s1 less than s2 */
 }
+
+_public_
+uint16_t knot_wire_read_u16(const uint8_t *pos)
+{
+	return be16toh(*(uint16_t *)pos);
+}
+
+_public_
+uint32_t knot_wire_read_u32(const uint8_t *pos)
+{
+	return be32toh(*(uint32_t *)pos);
+}
+
+_public_
+uint64_t knot_wire_read_u48(const uint8_t *pos)
+{
+	uint64_t input = 0;
+	memcpy((void *)&input + 1, (void *)pos, 6);
+	return be64toh(input) >> 8;
+}
+
+_public_
+uint64_t knot_wire_read_u64(const uint8_t *pos)
+{
+	return be64toh(*(uint64_t *)pos);
+}
+
+_public_
+void knot_wire_write_u16(uint8_t *pos, uint16_t data)
+{
+	*(uint16_t *)pos = htobe16(data);
+}
+
+_public_
+void knot_wire_write_u32(uint8_t *pos, uint32_t data)
+{
+	*(uint32_t *)pos = htobe32(data);
+}
+
+_public_
+void knot_wire_write_u48(uint8_t *pos, uint64_t data)
+{
+	uint64_t swapped = htobe64(data << 8);
+	memcpy((void *)pos, (uint8_t *)&swapped + 1, 6);
+}
+
+_public_
+void knot_wire_write_u64(uint8_t *pos, uint64_t data)
+{
+	*(uint64_t *)pos = htobe64(data);
+}
diff --git a/src/libknot/util/utils.h b/src/libknot/util/utils.h
index 40be87ded01b838ec6fb1d3a71c32990199fdfa3..7882cb065a3d8920e0ccccd285e1a64e201ca60a 100644
--- a/src/libknot/util/utils.h
+++ b/src/libknot/util/utils.h
@@ -26,7 +26,6 @@
 
 #pragma once
 
-#include "libknot/util/endian.h"
 #include <string.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -53,7 +52,7 @@ typedef struct knot_lookup_table knot_lookup_table_t;
  *         present.
  */
 knot_lookup_table_t *knot_lookup_by_name(knot_lookup_table_t *table,
-                                             const char *name);
+                                         const char *name);
 
 /*!
  * \brief Looks up the given id in the lookup table.
@@ -64,8 +63,7 @@ knot_lookup_table_t *knot_lookup_by_name(knot_lookup_table_t *table,
  * \return Item in the lookup table with the given id or NULL if no such is
  *         present.
  */
-knot_lookup_table_t *knot_lookup_by_id(knot_lookup_table_t *table,
-                                           int id);
+knot_lookup_table_t *knot_lookup_by_id(knot_lookup_table_t *table, int id);
 
 /*
  * Writing / reading arbitrary data to / from wireformat.
@@ -78,10 +76,7 @@ knot_lookup_table_t *knot_lookup_by_id(knot_lookup_table_t *table,
  *
  * \return The 2 bytes read, in host byte order.
  */
-static inline uint16_t knot_wire_read_u16(const uint8_t *pos)
-{
-	return be16toh(*(uint16_t *)pos);
-}
+uint16_t knot_wire_read_u16(const uint8_t *pos);
 
 /*!
  * \brief Reads 4 bytes from the wireformat data.
@@ -90,10 +85,7 @@ static inline uint16_t knot_wire_read_u16(const uint8_t *pos)
  *
  * \return The 4 bytes read, in host byte order.
  */
-static inline uint32_t knot_wire_read_u32(const uint8_t *pos)
-{
-	return be32toh(*(uint32_t *)pos);
-}
+uint32_t knot_wire_read_u32(const uint8_t *pos);
 
 /*!
  * \brief Reads 6 bytes from the wireformat data.
@@ -102,12 +94,7 @@ static inline uint32_t knot_wire_read_u32(const uint8_t *pos)
  *
  * \return The 6 bytes read, in host byte order.
  */
-static inline uint64_t knot_wire_read_u48(const uint8_t *pos)
-{
-	uint64_t input = 0;
-	memcpy((void *)&input + 1, (void *)pos, 6);
-	return be64toh(input) >> 8;
-}
+uint64_t knot_wire_read_u48(const uint8_t *pos);
 
 /*!
  * \brief Read 8 bytes from the wireformat data.
@@ -116,10 +103,7 @@ static inline uint64_t knot_wire_read_u48(const uint8_t *pos)
  *
  * \return The 8 bytes read, in host byte order.
  */
-static inline uint64_t knot_wire_read_u64(const uint8_t *pos)
-{
-	return be64toh(*(uint64_t *)pos);
-}
+uint64_t knot_wire_read_u64(const uint8_t *pos);
 
 /*!
  * \brief Writes 2 bytes in wireformat.
@@ -129,10 +113,7 @@ static inline uint64_t knot_wire_read_u64(const uint8_t *pos)
  * \param pos Position where to put the 2 bytes.
  * \param data Data to put.
  */
-static inline void knot_wire_write_u16(uint8_t *pos, uint16_t data)
-{
-	*(uint16_t *)pos = htobe16(data);
-}
+void knot_wire_write_u16(uint8_t *pos, uint16_t data);
 
 /*!
  * \brief Writes 4 bytes in wireformat.
@@ -142,10 +123,7 @@ static inline void knot_wire_write_u16(uint8_t *pos, uint16_t data)
  * \param pos Position where to put the 4 bytes.
  * \param data Data to put.
  */
-static inline void knot_wire_write_u32(uint8_t *pos, uint32_t data)
-{
-	*(uint32_t *)pos = htobe32(data);
-}
+void knot_wire_write_u32(uint8_t *pos, uint32_t data);
 
 /*!
  * \brief Writes 6 bytes in wireformat.
@@ -155,11 +133,7 @@ static inline void knot_wire_write_u32(uint8_t *pos, uint32_t data)
  * \param pos Position where to put the 4 bytes.
  * \param data Data to put.
  */
-static inline void knot_wire_write_u48(uint8_t *pos, uint64_t data)
-{
-	uint64_t swapped = htobe64(data << 8);
-	memcpy((void *)pos, (uint8_t *)&swapped + 1, 6);
-}
+void knot_wire_write_u48(uint8_t *pos, uint64_t data);
 
 /*!
  * \brief Writes 8 bytes in wireformat.
@@ -169,10 +143,7 @@ static inline void knot_wire_write_u48(uint8_t *pos, uint64_t data)
  * \param pos Position where to put the 8 bytes.
  * \param data Data to put.
  */
-static inline void knot_wire_write_u64(uint8_t *pos, uint64_t data)
-{
-	*(uint64_t *)pos = htobe64(data);
-}
+void knot_wire_write_u64(uint8_t *pos, uint64_t data);
 
 /*!
  * \brief Compares two zone serials.
diff --git a/src/utils/common/exec.c b/src/utils/common/exec.c
index 1fa4b5010a3562de5f260f95a673053dbb32d578..e470c35cc5ce855581cfc8d36090a018e223884d 100644
--- a/src/utils/common/exec.c
+++ b/src/utils/common/exec.c
@@ -21,10 +21,10 @@
 #include <arpa/inet.h>			// inet_ntop
 
 #include "libknot/libknot.h"
-#include "common-knot/lists.h"		// list
-#include "common-knot/print.h"		// txt_print
+#include "common/lists.h"		// list
+#include "common/sockaddr.h"		// IPV4_PREFIXLEN
+#include "common/print.h"		// txt_print
 #include "common-knot/strlcat.h"	// strlcat
-#include "common-knot/sockaddr.h"	// IPV4_PREFIXLEN
 #include "utils/common/msg.h"		// WARN
 #include "utils/common/params.h"	// params_t
 #include "utils/common/netio.h"		// send_msg
@@ -728,7 +728,7 @@ int sign_packet(knot_pkt_t              *pkt,
 		sign_ctx->digest_size = knot_tsig_digest_length(key->algorithm);
 		sign_ctx->digest = malloc(sign_ctx->digest_size);
 
-		knot_pkt_reserve(pkt, tsig_wire_maxsize(key));
+		knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(key));
 
 		result = knot_tsig_sign(wire, wire_size, max_size, NULL, 0,
 		                        sign_ctx->digest, &sign_ctx->digest_size,
diff --git a/src/utils/common/netio.c b/src/utils/common/netio.c
index b995ff52c76262ab389e1e2ad3e2c14311672d3c..ce14e38e880c227f8022a8b17aeec493552b46c7 100644
--- a/src/utils/common/netio.c
+++ b/src/utils/common/netio.c
@@ -31,7 +31,7 @@
 #include "utils/common/msg.h"		// WARN
 #include "libknot/descriptor.h"		// KNOT_CLASS_IN
 #include "libknot/errcode.h"		// KNOT_E
-#include "common-knot/sockaddr.h"	// sockaddr_tostr, sockaddr_portnum
+#include "common/sockaddr.h"		// sockaddr_tostr, sockaddr_portnum
 
 srv_info_t* srv_info_create(const char *name, const char *service)
 {
diff --git a/src/utils/common/netio.h b/src/utils/common/netio.h
index 3ada463f35483c02e90d8106625e26249f4f6c48..f0fd875909dc5e261286f9e0770693a277397e15 100644
--- a/src/utils/common/netio.h
+++ b/src/utils/common/netio.h
@@ -30,7 +30,7 @@
 #include <netdb.h>			// addrinfo
 #include <sys/socket.h>			// sockaddr_storage (BSD)
 
-#include "common-knot/lists.h"		// node
+#include "common/lists.h"		// node
 #include "utils/common/params.h"	// params_t
 
 /*! \brief Structure containing server information. */
diff --git a/src/utils/common/params.c b/src/utils/common/params.c
index 0058e3a3aacf3389981050a75fba4e5695d67193..f863f29dd9d633a6a31702a8747dfe5eaa6fcbb4 100644
--- a/src/utils/common/params.c
+++ b/src/utils/common/params.c
@@ -28,9 +28,9 @@
 
 #include "libknot/libknot.h"
 #include "libknot/errcode.h"		// KNOT_EOK
-#include "libknot/mempattern.h"		// strcdup
+#include "common/mempattern.h"		// strcdup
 #include "libknot/descriptor.h"		// KNOT_RRTYPE_
-#include "common-knot/strlcpy.h"		// strlcpy
+#include "common/strlcpy.h"		// strlcpy
 #include "utils/common/msg.h"		// WARN
 #include "utils/common/resolv.h"	// parse_nameserver
 #include "utils/common/token.h"		// token
diff --git a/src/utils/common/params.h b/src/utils/common/params.h
index 9124a5d006c5316b53706cc8c715acbac0cfd3f4..734f9f5e34b30a8b3da3d09dc7ca49af5e665594 100644
--- a/src/utils/common/params.h
+++ b/src/utils/common/params.h
@@ -31,7 +31,7 @@
 #include <stdbool.h>			// bool
 
 #include "libknot/libknot.h"
-#include "common-knot/lists.h"		// list
+#include "common/lists.h"		// list
 
 #define DEFAULT_IPV4_NAME	"127.0.0.1"
 #define DEFAULT_IPV6_NAME	"::1"
diff --git a/src/utils/common/resolv.c b/src/utils/common/resolv.c
index ce4ae2cd4152d8e3d4e8c4a9cd0b04750860b50b..71692b538210d1add02072aa5543a3e7deceedeb 100644
--- a/src/utils/common/resolv.c
+++ b/src/utils/common/resolv.c
@@ -19,7 +19,7 @@
 #include <stdio.h>			// fopen
 #include <stdlib.h>			// free
 
-#include "common-knot/lists.h"		// list
+#include "common/lists.h"		// list
 #include "libknot/errcode.h"		// KNOT_ENOENT
 #include "utils/common/msg.h"		// DBG_NULL
 #include "utils/common/params.h"	// DEFAULT_IPV6_NAME
diff --git a/src/utils/common/resolv.h b/src/utils/common/resolv.h
index 4a0314cbe28945076a14179527537ad4611f47d5..a9d28797fc1c3e229c646dac1680fe5da66c394d 100644
--- a/src/utils/common/resolv.h
+++ b/src/utils/common/resolv.h
@@ -26,7 +26,7 @@
 
 #pragma once
 
-#include "common-knot/lists.h"		// list
+#include "common/lists.h"		// list
 #include "utils/common/netio.h"		// server_t
 
 srv_info_t* parse_nameserver(const char *str, const char *def_port);
diff --git a/src/utils/dig/dig_exec.c b/src/utils/dig/dig_exec.c
index e5f5f3b32bc69b5f594d2244f9f6108036b64567..52726d5e1543cb2767c24de2855b5d475c6fe6fc 100644
--- a/src/utils/dig/dig_exec.c
+++ b/src/utils/dig/dig_exec.c
@@ -22,11 +22,11 @@
 #include <netinet/in.h>			// sockaddr_in (BSD)
 
 #include "libknot/libknot.h"
-#include "common-knot/lists.h"		// list
-#include "common-knot/print.h"		// time_diff
+#include "common/lists.h"		// list
+#include "common/print.h"		// time_diff
 #include "libknot/errcode.h"		// KNOT_EOK
 #include "libknot/descriptor.h"		// KNOT_RRTYPE_
-#include "common-knot/sockaddr.h"		// sockaddr_set_raw
+#include "common/sockaddr.h"		// sockaddr_set_raw
 #include "utils/common/msg.h"		// WARN
 #include "utils/common/netio.h"		// get_socktype
 #include "utils/common/exec.h"		// print_packet
@@ -246,7 +246,7 @@ static int add_query_edns(knot_pkt_t *packet, const query_t *query, int max_size
 	}
 
 	/* Add prepared OPT to packet. */
-	ret = knot_pkt_put(packet, COMPR_HINT_NONE, &opt_rr, KNOT_PF_FREE);
+	ret = knot_pkt_put(packet, KNOT_COMPR_HINT_NONE, &opt_rr, KNOT_PF_FREE);
 	if (ret != KNOT_EOK) {
 		knot_rrset_clear(&opt_rr, &packet->mm);
 	}
diff --git a/src/utils/dig/dig_params.c b/src/utils/dig/dig_params.c
index 068a1828b8712a1d59e247d6b63c35355cd01343..55c3cacbd5d26dd20b19abc3bfbdc4dbedb75f94 100644
--- a/src/utils/dig/dig_params.c
+++ b/src/utils/dig/dig_params.c
@@ -23,10 +23,10 @@
 #include <locale.h>			// setlocale
 #include <arpa/inet.h>			// inet_pton
 
-#include "common-knot/lists.h"		// list
+#include "common/lists.h"		// list
 #include "libknot/errcode.h"		// KNOT_EOK
 #include "libknot/descriptor.h"		// KNOT_CLASS_IN
-#include "common-knot/sockaddr.h"	// IPV4_PREFIXLEN
+#include "common/sockaddr.h"		// IPV4_PREFIXLEN
 #include "utils/common/msg.h"		// WARN
 #include "utils/common/params.h"	// parse_class
 #include "utils/common/resolv.h"	// get_nameservers
diff --git a/src/utils/dig/dig_params.h b/src/utils/dig/dig_params.h
index 8ae17c07711f74547d1b0cced44e7cf307487eaf..1869bf15710739e770419f8dd7809a2167a428dd 100644
--- a/src/utils/dig/dig_params.h
+++ b/src/utils/dig/dig_params.h
@@ -29,7 +29,7 @@
 #include <stdbool.h>			// bool
 
 #include "libknot/libknot.h"		// knot_addr_family_t
-#include "common-knot/sockaddr.h"	// IPV6_PREFIXLEN
+#include "common/sockaddr.h"		// IPV6_PREFIXLEN
 #include "utils/common/params.h"	// protocol_t
 #include "utils/common/exec.h"		// sign_context_t
 
diff --git a/src/utils/host/host_params.c b/src/utils/host/host_params.c
index abef70252ea01d3a7d0341ca400cf1f98143957e..97fa6da3bf165a863edd0f1606b08b4bf93dcfa4 100644
--- a/src/utils/host/host_params.c
+++ b/src/utils/host/host_params.c
@@ -22,7 +22,7 @@
 #include <stdlib.h>			// free
 #include <locale.h>			// setlocale
 
-#include "common-knot/lists.h"		// list
+#include "common/lists.h"		// list
 #include "libknot/errcode.h"		// KNOT_EOK
 #include "libknot/descriptor.h"		// KNOT_CLASS_IN
 #include "utils/common/msg.h"		// WARN
diff --git a/src/utils/nsupdate/nsupdate_exec.c b/src/utils/nsupdate/nsupdate_exec.c
index c212d6987a33a08b2341e6c55d023b0b06397b8d..947c7b78f266e95a2d697aa5ec12187b888148fe 100644
--- a/src/utils/nsupdate/nsupdate_exec.c
+++ b/src/utils/nsupdate/nsupdate_exec.c
@@ -28,11 +28,11 @@
 #include "utils/common/exec.h"
 #include "utils/common/netio.h"
 #include "utils/common/token.h"
+#include "common/macros.h"
 #include "common/mem.h"
 #include "libknot/errcode.h"
 #include "libknot/descriptor.h"
-#include "common-knot/strlcpy.h"
-#include "libknot/common.h"
+#include "common/strlcpy.h"
 #include "libknot/libknot.h"
 #include "libknot/dnssec/random.h"
 
@@ -368,7 +368,7 @@ static int rr_list_to_packet(knot_pkt_t *dst, list_t *list)
 	int ret = KNOT_EOK;
 	ptrnode_t *node = NULL;
 	WALK_LIST(node, *list) {
-		ret = knot_pkt_put(dst, COMPR_HINT_NONE,
+		ret = knot_pkt_put(dst, KNOT_COMPR_HINT_NONE,
 		                   (knot_rrset_t *)node->d, 0);
 		if (ret != KNOT_EOK) {
 			break;
diff --git a/src/utils/nsupdate/nsupdate_params.c b/src/utils/nsupdate/nsupdate_params.c
index 1a0d4d2fbf5f5e9c31098d6a97dfbbc61dd4ff57..fd2335792207ce6f78146dfe93726c310c2bae1a 100644
--- a/src/utils/nsupdate/nsupdate_params.c
+++ b/src/utils/nsupdate/nsupdate_params.c
@@ -25,7 +25,7 @@
 #include "utils/common/netio.h"
 #include "libknot/errcode.h"
 #include "libknot/descriptor.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 #include "common/mempool.h"
 #include "libknot/libknot.h"
 
diff --git a/src/utils/nsupdate/nsupdate_params.h b/src/utils/nsupdate/nsupdate_params.h
index 96c609ad71bbaf50df4582f52ead8c3c8e2486a2..ee4610f50db7ce40a6b4ba2b07dcf039abd9ff8f 100644
--- a/src/utils/nsupdate/nsupdate_params.h
+++ b/src/utils/nsupdate/nsupdate_params.h
@@ -29,7 +29,7 @@
 #include <stdint.h>
 
 #include "libknot/libknot.h"
-#include "common-knot/lists.h"		// list
+#include "common/lists.h"		// list
 #include "zscanner/scanner.h"		// zs_scanner_t
 #include "utils/common/netio.h"		// server_t
 #include "utils/common/params.h"	// protocol_t
diff --git a/src/zscanner/Makefile.am b/src/zscanner/Makefile.am
index d93b5d5ac7e62f43962dbf84cef8910e292b366d..9a115f379e384e4a8ff952f623a6c7f24c963e44 100644
--- a/src/zscanner/Makefile.am
+++ b/src/zscanner/Makefile.am
@@ -36,7 +36,6 @@ nodist_libzscanner_la_SOURCES =		\
 libzscanner_la_CFLAGS = $(CODE_COVERAGE_CFLAGS)
 libzscanner_la_LDFLAGS =		\
 	$(CODE_COVERAGE_LDFLAGS)	\
-	-version-info 0:1:0		\
-	-export-symbols-regex '^zs_'
+	-version-info 0:1:0
 
 include $(srcdir)/tests/Makefile.inc
diff --git a/src/zscanner/error.c b/src/zscanner/error.c
index ccc43075769704332d0e0b2e0ce60b2a91bcc2f3..a7c74a4dd8d81a78ef91b1267afbe687e9536769 100644
--- a/src/zscanner/error.c
+++ b/src/zscanner/error.c
@@ -26,7 +26,7 @@ typedef struct {
 
 #define ERR_ITEM(code, text) { code, text, #code }
 
-const err_table_t err_msgs[] = {
+static const err_table_t err_msgs[] = {
 	ERR_ITEM( ZS_OK, "ok" ),
 
 	ERR_ITEM( ZS_SYSTEM,
@@ -161,6 +161,7 @@ const err_table_t err_msgs[] = {
 	ERR_ITEM( 0, NULL ) // Terminator
 };
 
+__attribute__((visibility("default")))
 const char* zs_strerror(const int code)
 {
 	const err_table_t *err = err_msgs;
@@ -175,6 +176,7 @@ const char* zs_strerror(const int code)
 	return NULL;
 }
 
+__attribute__((visibility("default")))
 const char* zs_errorname(const int code)
 {
 	const err_table_t *err = err_msgs;
diff --git a/src/zscanner/scanner.c.g2 b/src/zscanner/scanner.c.g2
index 8072cdf55207ce23514097c5eaa9e76247966f61..fcdd95ee5051fd3ede435189c2863965b53b3d82 100644
--- a/src/zscanner/scanner.c.g2
+++ b/src/zscanner/scanner.c.g2
@@ -100,6 +100,7 @@ static const int zone_scanner_error = 0;
 
 
 
+__attribute__((visibility("default")))
 zs_scanner_t* zs_scanner_create(const char     *origin,
                                 const uint16_t rclass,
                                 const uint32_t ttl,
@@ -152,6 +153,7 @@ zs_scanner_t* zs_scanner_create(const char     *origin,
 	return s;
 }
 
+__attribute__((visibility("default")))
 void zs_scanner_free(zs_scanner_t *s)
 {
 	if (s != NULL) {
@@ -73071,6 +73073,7 @@ case 1140:
 	s->r_data_tail = rdata_tail - s->r_data;
 }
 
+__attribute__((visibility("default")))
 int zs_scanner_parse(zs_scanner_t *s,
                      const char   *start,
                      const char   *end,
@@ -73096,6 +73099,7 @@ int zs_scanner_parse(zs_scanner_t *s,
 	return 0;
 }
 
+__attribute__((visibility("default")))
 int zs_scanner_parse_file(zs_scanner_t *s,
                           const char   *file_name)
 {
diff --git a/src/zscanner/scanner.c.t0 b/src/zscanner/scanner.c.t0
index 684d05d524068acb402da7050b49d95e3d92c2cc..f06c0f9bbd026e86ccdd2fbf569eb99b1dc3fcb8 100644
--- a/src/zscanner/scanner.c.t0
+++ b/src/zscanner/scanner.c.t0
@@ -4891,6 +4891,7 @@ static const int zone_scanner_error = 0;
 
 
 
+__attribute__((visibility("default")))
 zs_scanner_t* zs_scanner_create(const char     *origin,
                                 const uint16_t rclass,
                                 const uint32_t ttl,
@@ -4943,6 +4944,7 @@ zs_scanner_t* zs_scanner_create(const char     *origin,
 	return s;
 }
 
+__attribute__((visibility("default")))
 void zs_scanner_free(zs_scanner_t *s)
 {
 	if (s != NULL) {
@@ -7392,6 +7394,7 @@ _again:
 	s->r_data_tail = rdata_tail - s->r_data;
 }
 
+__attribute__((visibility("default")))
 int zs_scanner_parse(zs_scanner_t *s,
                      const char   *start,
                      const char   *end,
@@ -7417,6 +7420,7 @@ int zs_scanner_parse(zs_scanner_t *s,
 	return 0;
 }
 
+__attribute__((visibility("default")))
 int zs_scanner_parse_file(zs_scanner_t *s,
                           const char   *file_name)
 {
diff --git a/src/zscanner/scanner.rl b/src/zscanner/scanner.rl
index 506854f52e18715afc735cb990e3477f974ca5ff..3a27b7e5128870adbb6441fb31d589ad06e58b84 100644
--- a/src/zscanner/scanner.rl
+++ b/src/zscanner/scanner.rl
@@ -99,6 +99,7 @@ static inline void window_add_bit(const uint16_t type, zs_scanner_t *s) {
 	write data;
 }%%
 
+__attribute__((visibility("default")))
 zs_scanner_t* zs_scanner_create(const char     *origin,
                                 const uint16_t rclass,
                                 const uint32_t ttl,
@@ -151,6 +152,7 @@ zs_scanner_t* zs_scanner_create(const char     *origin,
 	return s;
 }
 
+__attribute__((visibility("default")))
 void zs_scanner_free(zs_scanner_t *s)
 {
 	if (s != NULL) {
@@ -239,6 +241,7 @@ static void parse_block(zs_scanner_t *s,
 	s->r_data_tail = rdata_tail - s->r_data;
 }
 
+__attribute__((visibility("default")))
 int zs_scanner_parse(zs_scanner_t *s,
                      const char   *start,
                      const char   *end,
@@ -264,6 +267,7 @@ int zs_scanner_parse(zs_scanner_t *s,
 	return 0;
 }
 
+__attribute__((visibility("default")))
 int zs_scanner_parse_file(zs_scanner_t *s,
                           const char   *file_name)
 {
diff --git a/tests-extra/tests/dnssec/case_sensitivity/test.py b/tests-extra/tests/dnssec/case_sensitivity/test.py
index ff5fc09d1706fe8e3d7e2c36df4c13a31c2e1d51..db71bc99588d9bb37bc6f8d305d6718733dbd330 100644
--- a/tests-extra/tests/dnssec/case_sensitivity/test.py
+++ b/tests-extra/tests/dnssec/case_sensitivity/test.py
@@ -38,6 +38,7 @@ scripts = [
 ]
 
 for name, script, resign in scripts:
+    t.sleep(1)
     server.flush()
     server.stop()
     patch_zone(t, server, zone, script)
diff --git a/tests-extra/tests/dnssec/dnskey_timestamps/test.py b/tests-extra/tests/dnssec/dnskey_timestamps/test.py
index 9248cbf936d4d5084b769c61b479ae7a69a91361..a4e88a8dd940ee3342c377e4be1719243eb8c6ae 100644
--- a/tests-extra/tests/dnssec/dnskey_timestamps/test.py
+++ b/tests-extra/tests/dnssec/dnskey_timestamps/test.py
@@ -121,7 +121,7 @@ check_zone(knot, False, True, "not published, active")
 check_log("Planned events")
 
 # key about to be published
-event_in = 5
+event_in = 7
 key_settime(key_file, Publish=date_offset(event_in), Activate=date_future, Inactive=None, Delete=None)
 knot.reload()
 t.sleep(WAIT_SIGN)
diff --git a/tests-extra/tests/zone/expire/data/example.zone b/tests-extra/tests/zone/expire/data/example.zone
new file mode 100644
index 0000000000000000000000000000000000000000..2fbcf4bc4b9daad20d6678d647de1aaa0bcf1b0e
--- /dev/null
+++ b/tests-extra/tests/zone/expire/data/example.zone
@@ -0,0 +1,5 @@
+$ORIGIN example.
+$TTL 1200
+
+@ SOA ns admin 42 1 1 8 600
+ns AAAA ::0
diff --git a/tests-extra/tests/zone/expire/data/example.zone.1 b/tests-extra/tests/zone/expire/data/example.zone.1
new file mode 100644
index 0000000000000000000000000000000000000000..0c22c7a1742611eb76222bb438e3211b47248f71
--- /dev/null
+++ b/tests-extra/tests/zone/expire/data/example.zone.1
@@ -0,0 +1,5 @@
+$ORIGIN example.
+$TTL 1200
+
+@ SOA ns admin 4242 1 1 8 600
+ns AAAA ::0
diff --git a/tests-extra/tests/zone/expire/test.py b/tests-extra/tests/zone/expire/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a1469bbe7708f576068286ad007637007486131
--- /dev/null
+++ b/tests-extra/tests/zone/expire/test.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+'''Test zone expiration by master shutdown or broken AXFR.'''
+
+from dnstest.test import Test
+
+def test_expire(zone, server):
+    resp = server.dig(zone[0].name, "SOA")
+    resp.check(rcode="SERVFAIL")
+
+def break_xfrout(server):
+    with open(server.confile, "r+") as f:
+        config = f.read()
+        f.seek(0)
+        f.truncate()
+        config = config.replace("xfr-out ", "#xfr-out ")
+        f.write(config)
+
+t = Test(tsig=False)
+
+# this zone has refresh = 1s, retry = 1s and expire = 10s + 2s for connection timeouts
+zone = t.zone("example.", storage=".")
+EXPIRE_SLEEP = 15
+
+master = t.server("knot")
+slave = t.server("knot")
+slave.max_conn_idle = "1s"
+
+t.link(zone, master, slave)
+
+t.start()
+
+master.zone_wait(zone)
+slave.zone_wait(zone)
+
+# expire by shutting down the master
+master.stop()
+t.sleep(EXPIRE_SLEEP);
+test_expire(zone, slave)
+
+# bring back master (notifies slave)
+master.start()
+master.zone_wait(zone)
+slave.zone_wait(zone)
+
+# expire by breaking AXFR
+break_xfrout(master)
+master.update_zonefile(zone, version=1)
+master.reload()
+t.sleep(EXPIRE_SLEEP);
+test_expire(zone, slave)
+
+t.stop()
diff --git a/tests-extra/tests/zone/force-refresh/data/example.com.zone b/tests-extra/tests/zone/force-refresh/data/example.com.zone
new file mode 100644
index 0000000000000000000000000000000000000000..8a1af1e3ce59d11842d931232be145137267007d
--- /dev/null
+++ b/tests-extra/tests/zone/force-refresh/data/example.com.zone
@@ -0,0 +1,16 @@
+$ORIGIN example.com.
+$TTL 3600
+
+@	SOA	dns1 hostmaster 2010111201 10800 3600 1209600 7200
+	NS	dns1
+	NS	dns2
+	MX	10 mail
+
+dns1	A	192.0.2.1
+	AAAA	2001:DB8::1
+
+dns2	A	192.0.2.2
+	AAAA	2001:DB8::2
+
+mail	A	192.0.2.3
+	AAAA	2001:DB8::3
diff --git a/tests-extra/tests/zone/force-refresh/data/example.com.zone.1 b/tests-extra/tests/zone/force-refresh/data/example.com.zone.1
new file mode 100644
index 0000000000000000000000000000000000000000..1dd73fab9770e98f6bd9163c256729b4f30e8147
--- /dev/null
+++ b/tests-extra/tests/zone/force-refresh/data/example.com.zone.1
@@ -0,0 +1,18 @@
+$ORIGIN example.com.
+$TTL 3600
+
+@	SOA	dns1 hostmaster 2010111202 10800 3600 1209600 7200
+	NS	dns1
+	NS	dns2
+	MX	10 mail
+
+dns1	A	192.0.2.1
+	AAAA	2001:DB8::1
+
+dns2	A	192.0.2.2
+	AAAA	2001:DB8::2
+
+mail	A	192.0.2.3
+	AAAA	2001:DB8::3
+
+new	A	1.2.3.4
diff --git a/tests-extra/tests/zone/force-refresh/test.py b/tests-extra/tests/zone/force-refresh/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..f568db5fd7703151677decc5358606128a30395c
--- /dev/null
+++ b/tests-extra/tests/zone/force-refresh/test.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+
+'''Test for reload of a changed zone (serial up, nochange, serial down). '''
+
+from dnstest.test import Test
+from dnstest.utils import *
+
+t = Test()
+
+master = t.server("bind")
+slave = t.server("knot")
+
+zone = t.zone("example.com.", storage=".")
+t.link(zone, master, slave)
+
+# Load newer zone to the slave
+slave.update_zonefile(zone, version=1)
+
+t.start()
+
+serial_master = master.zone_wait(zone)
+serial_slave = slave.zone_wait(zone)
+
+# Check that the slave's serial is larger than master's
+assert serial_master <= serial_slave
+
+# Force refresh
+slave.ctl("-f refresh example.com.")
+t.sleep(2)
+
+serial_slave = slave.zone_wait(zone)
+compare(serial_slave, serial_master, "Forced refresh")
+
+t.end()
diff --git a/tests-extra/tools/dnstest/server.py b/tests-extra/tools/dnstest/server.py
index c55b73d528cfa85939ee5ff7379102e0af9d3946..699c871c30fbe6d3366b95dd8e04a8d2c16bd9e7 100644
--- a/tests-extra/tools/dnstest/server.py
+++ b/tests-extra/tools/dnstest/server.py
@@ -391,7 +391,7 @@ class Server(object):
     def gen_confile(self):
         f = open(self.confile, mode="w")
         f.write(self.get_config())
-        f.close
+        f.close()
 
     def dig(self, rname, rtype, rclass="IN", udp=None, serial=None,
             timeout=None, tries=3, flags="", bufsize=None, edns=None,
@@ -995,6 +995,17 @@ class Knot(Server):
 
         return s.conf
 
+    def ctl(self, params):
+        try:
+            check_call([self.control_bin] + self.start_params + params.split(),
+                       stdout=open(self.dir + "/call.out", mode="a"),
+                       stderr=open(self.dir + "/call.err", mode="a"))
+            time.sleep(Server.START_WAIT)
+        except CalledProcessError as e:
+            self.backtrace()
+            raise Failed("Can't control='%s' server='%s', ret='%i'" %
+                         (params, self.name, e.returncode))
+
 class Nsd(Server):
 
     def __init__(self, *args, **kwargs):
diff --git a/tests-extra/tools/dnstest/test.py b/tests-extra/tools/dnstest/test.py
index 456bc40405cbd32ad8b8c6e79011cb1f77fcdde7..ede2e402a5fe85dd2a03517c2ac4af489a7a696c 100644
--- a/tests-extra/tools/dnstest/test.py
+++ b/tests-extra/tools/dnstest/test.py
@@ -67,10 +67,10 @@ class Test(object):
         try:
             s = socket.socket(proto, socket.SOCK_DGRAM)
             s.bind((Test.LOCAL_ADDR[self.ip], port))
-            s.close
+            s.close()
             s = socket.socket(proto, socket.SOCK_STREAM)
             s.bind((Test.LOCAL_ADDR[self.ip], port))
-            s.close
+            s.close()
         except:
             return False
 
diff --git a/tests/.gitignore b/tests/.gitignore
index 3ef75e8bd5cac0492e09ea94c9ad3d6169fe224a..fb095c8f8be1b1e529fc81df9a9a98b0da4618cf 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -23,6 +23,7 @@ hhash
 journal
 namedb
 node
+overlay
 pkt
 process_answer
 process_query
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2db0910e0bf96f4f34d663e82731afaa10515469..2da579a64ad3cc9912e30248636426f283087972 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,6 +28,7 @@ check_PROGRAMS = \
 	journal				\
 	namedb				\
 	node				\
+	overlay				\
 	pkt				\
 	process_answer			\
 	process_query			\
diff --git a/tests/acl.c b/tests/acl.c
index 8855fd91b67d581f10899f27aceccfe72ddefa5a..5b925a9b43dfacf4c266c093cf98659b6bfefd09 100644
--- a/tests/acl.c
+++ b/tests/acl.c
@@ -19,7 +19,7 @@
 #include <tap/basic.h>
 
 #include "libknot/errcode.h"
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
 #include "knot/updates/acl.h"
 #include "knot/conf/conf.h"
 
diff --git a/tests/base32hex.c b/tests/base32hex.c
index 824443b19c0042b4749a1df38b84bb2b42228c25..6c7b750e102ef1cb75b4c64914049b54844722d4 100644
--- a/tests/base32hex.c
+++ b/tests/base32hex.c
@@ -21,7 +21,7 @@
 
 #include "libknot/errcode.h"
 #include "common/base32hex.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 
 #define BUF_LEN			256
 #define MAX_BIN_DATA_LEN	((INT32_MAX / 8) * 5)
diff --git a/tests/base64.c b/tests/base64.c
index 4d0c1ba71c8c43962be9b93594bdcba0c9ba9055..9d7cdaaf7981b8173058aac25ce8a915d0536f94 100644
--- a/tests/base64.c
+++ b/tests/base64.c
@@ -21,7 +21,7 @@
 
 #include "libknot/errcode.h"
 #include "common/base64.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 
 #define BUF_LEN			256
 #define MAX_BIN_DATA_LEN	((INT32_MAX / 4) * 3)
diff --git a/tests/descriptor.c b/tests/descriptor.c
index 656358ad0dba92bada04845e3bf1bb65ab2a26ea..2d77f41c29808acf27ca0bef3dd16f0d5d51868b 100644
--- a/tests/descriptor.c
+++ b/tests/descriptor.c
@@ -27,7 +27,7 @@ int main(int argc, char *argv[])
 {
 	plan(122);
 
-	const    rdata_descriptor_t *descr;
+	const    knot_rdata_descriptor_t *descr;
 	char     name[BUF_LEN];
 	int      ret;
 	uint16_t num;
diff --git a/tests/edns.c b/tests/edns.c
index 0e5e569c1bea2a3be85c9e9143bd136c5d793d09..45069583c41bac7f1bf0ee478fb66533387fec21 100644
--- a/tests/edns.c
+++ b/tests/edns.c
@@ -20,7 +20,7 @@
 #include "libknot/errcode.h"
 #include "libknot/rrtype/opt.h"
 #include "libknot/descriptor.h"
-#include "common-knot/sockaddr.h"
+#include "common/sockaddr.h"
 
 static const uint16_t E_MAX_PLD = 10000;
 static const uint16_t E_MAX_PLD2 = 20000;
diff --git a/tests/fake_server.h b/tests/fake_server.h
index 9026b2a321ca289ba6d3371bbaea2d95a7b133ba..eb9caa91481c8a315250b2b20909cf05daa6b8cc 100644
--- a/tests/fake_server.h
+++ b/tests/fake_server.h
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "knot/server/server.h"
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 
 /* Some domain names. */
 #define ROOT_DNAME ((const uint8_t *)"")
diff --git a/tests/hattrie.c b/tests/hattrie.c
index cb8d9c241ea7a1090edc44bf7b536d4c9100728a..7f986f0862c25443c1ce71a59779835528a22acd 100644
--- a/tests/hattrie.c
+++ b/tests/hattrie.c
@@ -18,7 +18,7 @@
 #include <time.h>
 #include <tap/basic.h>
 
-#include "common-knot/hattrie/hat-trie.h"
+#include "common/trie/hat-trie.h"
 #include "common/mem.h"
 
 /* Constants. */
@@ -97,7 +97,7 @@ static bool str_key_find_leq(hattrie_t *trie, char **keys, size_t i, size_t size
 #define ASORT_PREFIX(X) str_key_##X
 #define ASORT_KEY_TYPE char*
 #define ASORT_LT(x, y) (strcmp((x), (y)) < 0)
-#include "common-knot/array-sort.h"
+#include "common/array-sort.h"
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/hhash.c b/tests/hhash.c
index 59ca522d4b88b3c21afe34708f48861ec662d5d8..097b0fb90dc77d625d99fe08591c3ea63d7e6b9e 100644
--- a/tests/hhash.c
+++ b/tests/hhash.c
@@ -18,10 +18,11 @@
 #include <assert.h>
 #include <tap/basic.h>
 
-#include "common-knot/hhash.h"
-#include "libknot/mempattern.h"
+#include "common/hhash.h"
+#include "common/macros.h"
+#include "common/mempattern.h"
 #include "common/mempool.h"
-#include "libknot/common.h"
+#include "libknot/errcode.h"
 
 /* Test defines. */
 #define ELEM_COUNT 65535
@@ -32,7 +33,7 @@ static const char *alphabet = "0123abcdABCDwxyzWXYZ.-_";
 char *test_randstr_mm(struct mm_ctx *mm)
 {
 	unsigned len = (5 + rand() % 251) + 1;
-	char *s = mm->alloc(mm->ctx, len * sizeof(char));
+	char *s = mm_alloc(mm, len * sizeof(char));
 	for (unsigned i = 0; i < len - 1; ++i) {
 		s[i] = alphabet[rand() % strlen(alphabet)];
 	}
diff --git a/tests/namedb.c b/tests/namedb.c
index 67a61f517fc2731d36be9d33567f311f7a30f143..0490b6ae83e48800e7677dc286edbe701a193e69 100644
--- a/tests/namedb.c
+++ b/tests/namedb.c
@@ -19,7 +19,7 @@
 #include <unistd.h>
 #include <tap/basic.h>
 
-#include "libknot/common.h"
+#include "libknot/errcode.h"
 #include "common/mempool.h"
 #include "common/mem.h"
 #include "common/namedb/namedb_lmdb.h"
@@ -45,10 +45,10 @@ static char *str_key_rand(size_t len, mm_ctx_t *pool)
 #define ASORT_PREFIX(X) str_key_##X
 #define ASORT_KEY_TYPE char*
 #define ASORT_LT(x, y) (strcmp((x), (y)) < 0)
-#include "common-knot/array-sort.h"
+#include "common/array-sort.h"
 
 static void namedb_test_set(unsigned nkeys, char **keys, char *dbid,
-                            struct namedb_api *api, mm_ctx_t *pool)
+                            const struct namedb_api *api, mm_ctx_t *pool)
 {
 	if (api == NULL) {
 		skip("API not compiled in");
@@ -56,12 +56,13 @@ static void namedb_test_set(unsigned nkeys, char **keys, char *dbid,
 	}
 
 	/* Create database */
-	knot_namedb_t *db = api->init(dbid, pool);
-	ok(db != NULL, "%s: create", api->name);
+	knot_namedb_t *db = NULL;
+	int ret = api->init(dbid, &db, pool);
+	ok(ret == KNOT_EOK && db != NULL, "%s: create", api->name);
 
 	/* Start WR transaction. */
 	knot_txn_t txn;
-	int ret = api->txn_begin(db, &txn, 0);
+	ret = api->txn_begin(db, &txn, 0);
 	ok(ret == KNOT_EOK, "%s: txn_begin(WR)", api->name);
 
 	/* Insert keys */
@@ -169,7 +170,7 @@ int main(int argc, char *argv[])
 
 	/* Execute test set for all backends. */
 	namedb_test_set(nkeys, keys, dbid, namedb_lmdb_api(), &pool);
-	namedb_test_set(nkeys, keys, dbid, namedb_trie_api(), &pool);
+	namedb_test_set(nkeys, keys, NULL, namedb_trie_api(), &pool);
 
 	/* Cleanup */
 	mp_delete(pool.ctx);
diff --git a/tests/overlay.c b/tests/overlay.c
new file mode 100644
index 0000000000000000000000000000000000000000..5172f6336004bb483624378ffacaebe0dc545e90
--- /dev/null
+++ b/tests/overlay.c
@@ -0,0 +1,101 @@
+/*  Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <tap/basic.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "common/mempool.h"
+#include "libknot/processing/overlay.h"
+
+/* @note Purpose of this test is to verify, that FSM chaining works. */
+
+#define transition(expect, generate) \
+{ \
+	if (ctx->state != expect) { \
+		return KNOT_NS_PROC_FAIL; \
+	} else { \
+		return generate; \
+	} \
+}
+
+static int fsm1_begin(knot_layer_t *ctx, void *param)
+transition(KNOT_NS_PROC_NOOP, KNOT_NS_PROC_NOOP)
+static int fsm1_in(knot_layer_t *ctx, knot_pkt_t *pkt)
+transition(KNOT_NS_PROC_MORE, KNOT_NS_PROC_MORE)
+static int fsm1_reset(knot_layer_t *ctx)
+transition(KNOT_NS_PROC_DONE, KNOT_NS_PROC_DONE)
+static int fsm1_out(knot_layer_t *ctx, knot_pkt_t *pkt)
+transition(KNOT_NS_PROC_FULL, KNOT_NS_PROC_FAIL)
+static int fsm1_finish(knot_layer_t *ctx)
+transition(KNOT_NS_PROC_DONE, KNOT_NS_PROC_DONE)
+
+static int fsm2_begin(knot_layer_t *ctx, void *param)
+transition(KNOT_NS_PROC_NOOP, KNOT_NS_PROC_MORE)
+static int fsm2_in(knot_layer_t *ctx, knot_pkt_t *pkt)
+transition(KNOT_NS_PROC_MORE, KNOT_NS_PROC_DONE)
+static int fsm2_reset(knot_layer_t *ctx)
+transition(KNOT_NS_PROC_DONE, KNOT_NS_PROC_FULL)
+static int fsm2_out(knot_layer_t *ctx, knot_pkt_t *pkt)
+transition(KNOT_NS_PROC_FAIL, KNOT_NS_PROC_DONE)
+static int fsm2_finish(knot_layer_t *ctx)
+transition(KNOT_NS_PROC_DONE, KNOT_NS_PROC_NOOP)
+
+const knot_layer_api_t fsm1_module = {
+        &fsm1_begin, &fsm1_reset, &fsm1_finish, &fsm1_in, &fsm1_out, &fsm1_out
+};
+const knot_layer_api_t fsm2_module = {
+        &fsm2_begin, &fsm2_reset, &fsm2_finish, &fsm2_in, &fsm2_out, &fsm2_out
+};
+
+/* Test implementations. */
+
+#define TESTS_COUNT 4
+
+int main(int argc, char *argv[])
+{
+	plan(TESTS_COUNT);
+
+	mm_ctx_t mm;
+	mm_ctx_mempool(&mm, MM_DEFAULT_BLKSIZE);
+
+	knot_pkt_t *buf = knot_pkt_new(NULL, 512, &mm);
+	knot_pkt_put_question(buf, (const uint8_t *)"", 0, 0);
+
+	/* Initialize overlay. */
+	struct knot_overlay overlay;
+	knot_overlay_init(&overlay, &mm);
+
+	/* Add FSMs. */
+	knot_overlay_add(&overlay, &fsm1_module, NULL);
+	knot_overlay_add(&overlay, &fsm2_module, NULL);
+
+	/* Run the sequence. */
+	int state = knot_overlay_in(&overlay, buf);
+	is_int(KNOT_NS_PROC_DONE, state, "overlay: in");
+	state = knot_overlay_reset(&overlay);
+	is_int(KNOT_NS_PROC_FULL, state, "overlay: reset");
+	state = knot_overlay_out(&overlay, buf);
+	is_int(KNOT_NS_PROC_DONE, state, "overlay: out");
+	state = knot_overlay_finish(&overlay);
+	is_int(KNOT_NS_PROC_NOOP, state, "overlay: finish");
+
+	/* Cleanup. */
+	knot_overlay_deinit(&overlay);
+	mp_delete((struct mempool *)mm.ctx);
+
+	return 0;
+}
diff --git a/tests/pkt.c b/tests/pkt.c
index cb596a13faac13eef8233959035846f7b042e86e..cdeaeb233c116bcd62ffbee4dabb09e64e16504e 100644
--- a/tests/pkt.c
+++ b/tests/pkt.c
@@ -114,7 +114,7 @@ int main(int argc, char *argv[])
 	tsig_key.name = dnames[0];
 	tsig_key.secret.data = (uint8_t *)strdup(tsig_secret);
 	tsig_key.secret.size = strlen(tsig_secret);
-	ret = knot_pkt_reserve(out, tsig_wire_maxsize(&tsig_key));
+	ret = knot_pkt_reserve(out, knot_tsig_wire_maxsize(&tsig_key));
 	ok(ret == KNOT_EOK, "pkt: set TSIG key");
 
 	/* Write question. */
@@ -133,7 +133,7 @@ int main(int argc, char *argv[])
 	rrsets[0] = knot_rrset_new(dnames[0], KNOT_RRTYPE_A, KNOT_CLASS_IN, NULL);
 	knot_dname_free(&dnames[0], NULL);
 	knot_rrset_add_rdata(rrsets[0], RDVAL(0), RDLEN(0), TTL, NULL);
-	ret = knot_pkt_put(out, COMPR_HINT_QNAME, rrsets[0], 0);
+	ret = knot_pkt_put(out, KNOT_COMPR_HINT_QNAME, rrsets[0], 0);
 	ok(ret == KNOT_EOK, "pkt: write ANSWER");
 
 	/* Begin AUTHORITY. */
@@ -146,7 +146,7 @@ int main(int argc, char *argv[])
 		rrsets[i] = knot_rrset_new(dnames[i], KNOT_RRTYPE_NS, KNOT_CLASS_IN, NULL);
 		knot_dname_free(&dnames[i], NULL);
 		knot_rrset_add_rdata(rrsets[i], RDVAL(i), RDLEN(i), TTL, NULL);
-		ret |= knot_pkt_put(out, COMPR_HINT_NONE, rrsets[i], 0);
+		ret |= knot_pkt_put(out, KNOT_COMPR_HINT_NONE, rrsets[i], 0);
 	}
 	ok(ret == KNOT_EOK, "pkt: write AUTHORITY(%u)", NAMECOUNT - 1);
 
@@ -155,7 +155,7 @@ int main(int argc, char *argv[])
 	ok(ret == KNOT_EOK, "pkt: begin ADDITIONALS");
 
 	/* Encode OPT RR. */
-	ret = knot_pkt_put(out, COMPR_HINT_NONE, &opt_rr, 0);
+	ret = knot_pkt_put(out, KNOT_COMPR_HINT_NONE, &opt_rr, 0);
 	ok(ret == KNOT_EOK, "pkt: write OPT RR");
 
 	/*
diff --git a/tests/process_answer.c b/tests/process_answer.c
index 158d4d7df941fc328a89108d2ba38e9de034816c..4c48316d50ccdb1e691cfa9e434449984899f344 100644
--- a/tests/process_answer.c
+++ b/tests/process_answer.c
@@ -26,12 +26,13 @@
 
 /* @note Test helpers. */
 #define TEST_RESET() \
-	knot_process_reset(proc); \
+	knot_layer_reset(proc); \
+	knot_layer_out(proc, pkt); \
 	knot_pkt_clear(pkt)
 
 #define TEST_EXEC(expect, info) {\
-	pkt->parsed = pkt->size; /* Simulate parsed packet. */ \
-	int state = knot_process_in(pkt->wire, pkt->size, proc); \
+	knot_pkt_parse(pkt, 0); \
+	int state = knot_layer_in(proc, pkt); \
 	is_int((expect), state, "proc_answer: " info); \
 	}
 
@@ -40,26 +41,26 @@
 #define INCLASS_COUNT  2
 #define TEST_COUNT INVALID_COUNT + SPECIFIC_COUNT + INCLASS_COUNT
 
-static void test_invalid(knot_pkt_t *pkt, knot_process_t *proc)
+static void test_invalid(knot_pkt_t *pkt, knot_layer_t *proc)
 {
 	/* Invalid packet - query. */
 	TEST_RESET();
 	knot_pkt_put_question(pkt, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_A);
-	TEST_EXEC(NS_PROC_NOOP, "ignored query");
+	TEST_EXEC(KNOT_NS_PROC_NOOP, "ignored query");
 
 	/* Invalid packet - mangled. */
 	TEST_RESET();
 	knot_pkt_put_question(pkt, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_A);
 	pkt->size += 1; /* Mangle size. */
-	TEST_EXEC(NS_PROC_FAIL, "malformed query");
+	TEST_EXEC(KNOT_NS_PROC_FAIL, "malformed query");
 }
 
 /* Test if context accepts only answer to specific query. */
-static void test_specific(knot_pkt_t *pkt, knot_process_t *proc, struct process_answer_param *param)
+static void test_specific(knot_pkt_t *pkt, knot_layer_t *proc, struct process_answer_param *param)
 {
 	/* Set specific SOA query. */
 	uint16_t query_id = 0xBEEF;
-	knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MIN_PKTSIZE, &proc->mm);
+	knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MIN_PKTSIZE, proc->mm);
 	assert(query);
 	knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
 	knot_wire_set_id(query->wire, query_id);
@@ -69,17 +70,17 @@ static void test_specific(knot_pkt_t *pkt, knot_process_t *proc, struct process_
 	TEST_RESET();
 	knot_pkt_init_response(pkt, param->query);
 	knot_wire_set_id(pkt->wire, 0xDEAD);
-	TEST_EXEC(NS_PROC_NOOP, "ignored mismatching MSGID");
+	TEST_EXEC(KNOT_NS_PROC_NOOP, "ignored mismatching MSGID");
 
 	/* Clear the specific query. */
 	knot_pkt_free(&query);
 	param->query = NULL;
 }
 
-static void test_inclass(knot_pkt_t *pkt, knot_process_t *proc, struct process_answer_param *param)
+static void test_inclass(knot_pkt_t *pkt, knot_layer_t *proc, struct process_answer_param *param)
 {
 	/* Set specific SOA query. */
-	knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MIN_PKTSIZE, &proc->mm);
+	knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MIN_PKTSIZE, proc->mm);
 	assert(query);
 	knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
 	param->query = query;
@@ -91,14 +92,14 @@ static void test_inclass(knot_pkt_t *pkt, knot_process_t *proc, struct process_a
 	knot_pkt_put_question(pkt, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
 	knot_wire_set_qr(pkt->wire);
 	knot_pkt_begin(pkt, KNOT_ANSWER);
-	knot_pkt_put(pkt, COMPR_HINT_OWNER, &soa, 0);
-	TEST_EXEC(NS_PROC_DONE, "IN/SOA answer");
+	knot_pkt_put(pkt, KNOT_COMPR_HINT_OWNER, &soa, 0);
+	TEST_EXEC(KNOT_NS_PROC_DONE, "IN/SOA answer");
 
 	/* Unsupported anwer. */
 	TEST_RESET();
 	knot_pkt_put_question(pkt, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_TXT);
 	knot_wire_set_qr(pkt->wire);
-	TEST_EXEC(NS_PROC_NOOP, "IN/unsupported answer");
+	TEST_EXEC(KNOT_NS_PROC_NOOP, "IN/unsupported answer");
 
 	/* Clear the specific query. */
 	knot_pkt_free(&query);
@@ -110,13 +111,16 @@ int main(int argc, char *argv[])
 	plan(3 + TEST_COUNT);
 
 	/* Create processing context. */
-	knot_process_t proc;
-	memset(&proc, 0, sizeof(knot_process_t));
-	mm_ctx_mempool(&proc.mm, sizeof(knot_pkt_t));
+	mm_ctx_t mm;
+	mm_ctx_mempool(&mm, sizeof(knot_pkt_t));
+
+	knot_layer_t proc;
+	memset(&proc, 0, sizeof(knot_layer_t));
+	proc.mm = &mm;
 
 	/* Create fake server environment. */
 	server_t server;
-	int ret = create_fake_server(&server, &proc.mm);
+	int ret = create_fake_server(&server, proc.mm);
 	ok(ret == KNOT_EOK, "proc_answer: fake server initialization");
 
 	/* Prepare. */
@@ -126,11 +130,11 @@ int main(int argc, char *argv[])
 	struct process_answer_param param = {0};
 	param.remote = &remote;
 	param.zone = knot_zonedb_find(server.zone_db, ROOT_DNAME);
-	knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, &proc.mm);
+	knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, proc.mm);
 
 	/* Begin processing. */
-	int state = knot_process_begin(&proc, &param, NS_PROC_ANSWER);
-	ok(state == NS_PROC_MORE, "proc_answer: expects packet after init");
+	int state = knot_layer_begin(&proc, KNOT_NS_PROC_ANSWER, &param);
+	ok(state == KNOT_NS_PROC_FULL, "proc_answer: expects query to be sent");
 
 	/* Invalid generic input tests. */
 	test_invalid(pkt, &proc);
@@ -147,11 +151,11 @@ int main(int argc, char *argv[])
 	/* TSIG check tests. */
 
 	/* Finish. */
-	state = knot_process_finish(&proc);
-	ok(state == NS_PROC_NOOP, "proc_answer: processing end" );
+	state = knot_layer_finish(&proc);
+	ok(state == KNOT_NS_PROC_NOOP, "proc_answer: processing end" );
 
 	/* Cleanup. */
-	mp_delete((struct mempool *)proc.mm.ctx);
+	mp_delete(mm.ctx);
 	server_deinit(&server);
 	conf_free(conf());
 
diff --git a/tests/process_query.c b/tests/process_query.c
index 0fb7f23e56af1f14cec3884059fcc08777c5449e..9c5e9378620a806a0bd28b5abdaa290d7c45abf4 100644
--- a/tests/process_query.c
+++ b/tests/process_query.c
@@ -41,30 +41,32 @@ static void answer_sanity_check(const uint8_t *query,
 }
 
 /* Resolve query and check answer for sanity (2 TAP tests). */
-static void exec_query(knot_process_t *query_ctx, const char *name,
-                       const uint8_t *query, uint16_t query_len,
+static void exec_query(knot_layer_t *query_ctx, const char *name,
+                       knot_pkt_t *query,
                        uint8_t expected_rcode)
 {
-	uint16_t answer_len = KNOT_WIRE_MAX_PKTSIZE;
-	uint8_t answer[KNOT_WIRE_MAX_PKTSIZE];
+	knot_pkt_t *answer = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL);
+	assert(answer);
 
 	/* Input packet. */
-	int state = knot_process_in(query, query_len, query_ctx);
+	knot_pkt_parse(query, 0);
+	int state = knot_layer_in(query_ctx, query);
 
-	ok(state & (NS_PROC_FULL|NS_PROC_FAIL), "ns: process %s query", name);
+	ok(state & (KNOT_NS_PROC_FULL|KNOT_NS_PROC_FAIL), "ns: process %s query", name);
 
 	/* Create answer. */
-	state = knot_process_out(answer, &answer_len, query_ctx);
-	if (state & NS_PROC_FAIL) {
+	state = knot_layer_out(query_ctx, answer);
+	if (state & KNOT_NS_PROC_FAIL) {
 		/* Allow 1 generic error response. */
-		answer_len = KNOT_WIRE_MAX_PKTSIZE;
-		state = knot_process_out(answer, &answer_len, query_ctx);
+		state = knot_layer_out(query_ctx, answer);
 	}
 
-	ok(state == NS_PROC_DONE, "ns: answer %s query", name);
+	ok(state == KNOT_NS_PROC_DONE, "ns: answer %s query", name);
 
 	/* Check answer. */
-	answer_sanity_check(query, answer, answer_len, expected_rcode, name);
+	answer_sanity_check(query->wire, answer->wire, answer->size, expected_rcode, name);
+
+	knot_pkt_free(&answer);
 }
 
 /* \internal Helpers */
@@ -76,20 +78,23 @@ int main(int argc, char *argv[])
 {
 	plan(8*6 + 4); /* exec_query = 6 TAP tests */
 
+	mm_ctx_t mm;
+	mm_ctx_mempool(&mm, sizeof(knot_pkt_t));
+
 	/* Create processing context. */
-	knot_process_t proc;
-	memset(&proc, 0, sizeof(knot_process_t));
-	mm_ctx_mempool(&proc.mm, sizeof(knot_pkt_t));
+	knot_layer_t proc;
+	memset(&proc, 0, sizeof(knot_layer_t));
+	proc.mm = &mm;
 
 	/* Create fake server environment. */
 	server_t server;
-	int ret = create_fake_server(&server, &proc.mm);
+	int ret = create_fake_server(&server, proc.mm);
 	ok(ret == KNOT_EOK, "ns: fake server initialization");
 
 	zone_t *zone = knot_zonedb_find(server.zone_db, ROOT_DNAME);
 
 	/* Prepare. */
-	knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, &proc.mm);
+	knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, proc.mm);
 
 	/* Create query processing parameter. */
 	struct sockaddr_storage ss;
@@ -100,50 +105,56 @@ int main(int argc, char *argv[])
 	param.server = &server;
 
 	/* Query processor (CH zone) */
-	knot_process_begin(&proc, &param, NS_PROC_QUERY);
+	knot_layer_begin(&proc, NS_PROC_QUERY, &param);
 	knot_pkt_clear(query);
 	knot_pkt_put_question(query, IDSERVER_DNAME, KNOT_CLASS_CH, KNOT_RRTYPE_TXT);
-	exec_query(&proc, "CH TXT", query->wire, query->size, KNOT_RCODE_NOERROR);
+	exec_query(&proc, "CH TXT", query, KNOT_RCODE_NOERROR);
 
 	/* Query processor (valid input). */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
 	knot_pkt_clear(query);
 	knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
-	exec_query(&proc, "IN/root", query->wire, query->size, KNOT_RCODE_NOERROR);
+	exec_query(&proc, "IN/root", query, KNOT_RCODE_NOERROR);
 
 	/* Query processor (-1 bytes, not enough data). */
-	knot_process_reset(&proc);
-	exec_query(&proc, "IN/few-data", query->wire, query->size - 1, KNOT_RCODE_FORMERR);
+	knot_layer_reset(&proc);
+	query->size -= 1;
+	exec_query(&proc, "IN/few-data", query, KNOT_RCODE_FORMERR);
+	query->size += 1;
 
 	/* Query processor (+1 bytes trailing). */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
 	query->wire[query->size] = '\1'; /* Initialize the "garbage" value. */
-	exec_query(&proc, "IN/trail-garbage", query->wire, query->size + 1, KNOT_RCODE_FORMERR);
+	query->size += 1;
+	exec_query(&proc, "IN/trail-garbage", query, KNOT_RCODE_FORMERR);
+	query->size -= 1;
 
 	/* Forge NOTIFY query from SOA query. */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
 	knot_wire_set_opcode(query->wire, KNOT_OPCODE_NOTIFY);
-	exec_query(&proc, "IN/notify", query->wire, query->size, KNOT_RCODE_NOTAUTH);
+	exec_query(&proc, "IN/notify", query, KNOT_RCODE_NOTAUTH);
 
 	/* Forge AXFR query. */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
 	knot_pkt_clear(query);
 	knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_AXFR);
-	exec_query(&proc, "IN/axfr", query->wire, query->size, KNOT_RCODE_NOTAUTH);
+	exec_query(&proc, "IN/axfr", query, KNOT_RCODE_NOTAUTH);
 
 	/* Forge IXFR query (badly formed, no SOA in AUTHORITY section). */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
 	knot_pkt_clear(query);
 	knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_IXFR);
-	exec_query(&proc, "IN/ixfr-formerr", query->wire, query->size, KNOT_RCODE_FORMERR);
+	exec_query(&proc, "IN/ixfr-formerr", query, KNOT_RCODE_FORMERR);
 
 	/* Forge IXFR query (well formed). */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
+	knot_pkt_clear(query);
+	knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_IXFR);
 	/* Append SOA RR. */
 	knot_rrset_t soa_rr = node_rrset(zone->contents->apex, KNOT_RRTYPE_SOA);
 	knot_pkt_begin(query, KNOT_AUTHORITY);
-	knot_pkt_put(query, COMPR_HINT_NONE, &soa_rr, 0);
-	exec_query(&proc, "IN/ixfr", query->wire, query->size, KNOT_RCODE_NOTAUTH);
+	knot_pkt_put(query, KNOT_COMPR_HINT_NONE, &soa_rr, 0);
+	exec_query(&proc, "IN/ixfr", query, KNOT_RCODE_NOTAUTH);
 
 	/* \note Tests below are not possible without proper zone and zone data. */
 	/* #189 Process UPDATE query. */
@@ -151,24 +162,27 @@ int main(int argc, char *argv[])
 	/* #189 Process IXFR client. */
 
 	/* Query processor (smaller than DNS header, ignore). */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
 	knot_pkt_clear(query);
 	knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
-	int state = knot_process_in(query->wire, KNOT_WIRE_HEADER_SIZE - 1, &proc);
-	ok(state == NS_PROC_NOOP, "ns: IN/less-than-header query ignored");
+	size_t orig_query_size = query->size;
+	query->size = KNOT_WIRE_HEADER_SIZE - 1;
+	int state = knot_layer_in(&proc, query);
+	ok(state == KNOT_NS_PROC_NOOP, "ns: IN/less-than-header query ignored");
+	query->size = orig_query_size;
 
 	/* Query processor (response, ignore). */
-	knot_process_reset(&proc);
+	knot_layer_reset(&proc);
 	knot_wire_set_qr(query->wire);
-	state = knot_process_in(query->wire, query->size, &proc);
-	ok(state == NS_PROC_NOOP, "ns: IN/less-than-header query ignored");
+	state = knot_layer_in(&proc, query);
+	ok(state == KNOT_NS_PROC_NOOP, "ns: IN/less-than-header query ignored");
 
 	/* Finish. */
-	state = knot_process_finish(&proc);
-	ok(state == NS_PROC_NOOP, "ns: processing end" );
+	state = knot_layer_finish(&proc);
+	ok(state == KNOT_NS_PROC_NOOP, "ns: processing end" );
 
 	/* Cleanup. */
-	mp_delete((struct mempool *)proc.mm.ctx);
+	mp_delete((struct mempool *)mm.ctx);
 	server_deinit(&server);
 
 	return 0;
diff --git a/tests/query_module.c b/tests/query_module.c
index fa11983daf877a4a120717753e71ba7b691cd663..9df9b3c81e681e4b6fd8ee2c8ea948d60099f2fa 100644
--- a/tests/query_module.c
+++ b/tests/query_module.c
@@ -18,7 +18,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include "libknot/mempattern.h"
+#include "common/mempattern.h"
 #include "common/mempool.h"
 #include "libknot/errcode.h"
 #include "knot/nameserver/query_module.h"
diff --git a/tests/requestor.c b/tests/requestor.c
index 122b7058ed509679a0d9df76cd45b322438ffa7c..e5caffe2f9df9625941c14a62bec6cb3893a179b 100644
--- a/tests/requestor.c
+++ b/tests/requestor.c
@@ -19,21 +19,22 @@
 #include <stdlib.h>
 
 #include "common/mempool.h"
-#include "libknot/processing/process.h"
-#include "knot/nameserver/requestor.h"
-#include "knot/server/tcp-handler.h"
+#include "libknot/processing/layer.h"
+#include "libknot/processing/requestor.h"
 #include "fake_server.h"
 
 /* @note Purpose of this test is not to verify process_answer functionality,
  *       but simply if the requesting/receiving works, so mirror is okay. */
-static int begin(knot_process_t *ctx, void *module_param) { return NS_PROC_MORE; }
-static int answer(knot_pkt_t *pkt, knot_process_t *ctx) { return NS_PROC_DONE; }
-static int reset(knot_process_t *ctx) { return NS_PROC_NOOP; }
-static int noop(knot_pkt_t *pkt, knot_process_t *ctx) { return NS_PROC_NOOP; }
+static int reset(knot_layer_t *ctx) { return KNOT_NS_PROC_FULL; }
+static int begin(knot_layer_t *ctx, void *module_param) { return reset(ctx); }
+static int finish(knot_layer_t *ctx) { return KNOT_NS_PROC_NOOP; }
+static int in(knot_layer_t *ctx, knot_pkt_t *pkt) { return KNOT_NS_PROC_DONE; }
+static int out(knot_layer_t *ctx, knot_pkt_t *pkt) { return KNOT_NS_PROC_MORE; }
 
 /*! \brief Dummy answer processing module. */
-const knot_process_module_t dummy_module = {
-        &begin, &reset, &reset, &answer, &noop, &noop
+const knot_layer_api_t dummy_module = {
+        &begin, &reset, &finish,
+        &in, &out, &knot_layer_noop
 };
 
 static void* responder_thread(void *arg)
@@ -41,7 +42,7 @@ static void* responder_thread(void *arg)
 	int fd = *((int *)arg);
 	uint8_t buf[KNOT_WIRE_MAX_PKTSIZE];
 	while(true) {
-		int client = tcp_accept(fd);
+		int client = accept(fd, NULL, NULL);
 		if (client < 0) {
 			break;
 		}
@@ -63,42 +64,44 @@ static void* responder_thread(void *arg)
 #define CONNECTED_TESTS    4
 #define TESTS_COUNT DISCONNECTED_TESTS + CONNECTED_TESTS
 
-static struct request *make_query(struct requestor *requestor,  conf_iface_t *remote)
+static struct knot_request *make_query(struct knot_requestor *requestor,  conf_iface_t *remote)
 {
 	knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, requestor->mm);
 	assert(pkt);
 	knot_pkt_put_question(pkt, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
 
-	return requestor_make(requestor, remote, pkt);
+	const struct sockaddr *dst = (const struct sockaddr *)&remote->addr;
+	const struct sockaddr *src = (const struct sockaddr *)&remote->via;
+	return knot_request_make(requestor->mm, dst, src, pkt, 0);
 }
 
-static void test_disconnected(struct requestor *requestor, conf_iface_t *remote)
+static void test_disconnected(struct knot_requestor *requestor, conf_iface_t *remote)
 {
 	/* Enqueue packet. */
-	int ret = requestor_enqueue(requestor, make_query(requestor, remote), NULL);
+	int ret = knot_requestor_enqueue(requestor, make_query(requestor, remote));
 	is_int(KNOT_ECONN, ret, "requestor: disconnected/enqueue");
 
 	/* Wait for completion. */
 	struct timeval tv = { 5, 0 };
-	ret = requestor_exec(requestor, &tv);
+	ret = knot_requestor_exec(requestor, &tv);
 	is_int(KNOT_ENOENT, ret, "requestor: disconnected/wait");
 }
 
-static void test_connected(struct requestor *requestor, conf_iface_t *remote)
+static void test_connected(struct knot_requestor *requestor, conf_iface_t *remote)
 {
 	/* Enqueue packet. */
-	int ret = requestor_enqueue(requestor, make_query(requestor, remote), NULL);;
+	int ret = knot_requestor_enqueue(requestor, make_query(requestor, remote));
 	is_int(KNOT_EOK, ret, "requestor: connected/enqueue");
 
 	/* Wait for completion. */
 	struct timeval tv = { 5, 0 };
-	ret = requestor_exec(requestor, &tv);
+	ret = knot_requestor_exec(requestor, &tv);
 	is_int(KNOT_EOK, ret, "requestor: connected/wait");
 
 	/* Enqueue multiple queries. */
 	ret = KNOT_EOK;
 	for (unsigned i = 0; i < 10; ++i) {
-		ret |= requestor_enqueue(requestor, make_query(requestor, remote), NULL);;
+		ret |= knot_requestor_enqueue(requestor, make_query(requestor, remote));
 	}
 	is_int(KNOT_EOK, ret, "requestor: multiple enqueue");
 
@@ -106,7 +109,7 @@ static void test_connected(struct requestor *requestor, conf_iface_t *remote)
 	ret = KNOT_EOK;
 	for (unsigned i = 0; i < 10; ++i) {
 		struct timeval tv = { 5, 0 };
-		ret |= requestor_exec(requestor, &tv);
+		ret |= knot_requestor_exec(requestor, &tv);
 	}
 	is_int(KNOT_EOK, ret, "requestor: multiple wait");
 }
@@ -117,6 +120,7 @@ int main(int argc, char *argv[])
 
 	mm_ctx_t mm;
 	mm_ctx_mempool(&mm, MM_DEFAULT_BLKSIZE);
+
 	conf_iface_t remote;
 	memset(&remote, 0, sizeof(conf_iface_t));
 	sockaddr_set(&remote.addr, AF_INET, "127.0.0.1", 0);
@@ -125,11 +129,12 @@ int main(int argc, char *argv[])
 	/* Create fake server environment. */
 	server_t server;
 	int ret = create_fake_server(&server, &mm);
-	ok(ret == KNOT_EOK, "requestor: failed to initialize fake server");
+	ok(ret == KNOT_EOK, "requestor: initialize fake server");
 
 	/* Initialize requestor. */
-	struct requestor requestor;
-	requestor_init(&requestor, &dummy_module, &mm);
+	struct knot_requestor requestor;
+	knot_requestor_init(&requestor, &mm);
+	knot_requestor_overlay(&requestor, &dummy_module, NULL);
 
 	/* Test requestor in disconnected environment. */
 	test_disconnected(&requestor, &remote);
@@ -137,7 +142,7 @@ int main(int argc, char *argv[])
 	/* Bind to random port. */
 	int origin_fd = net_bound_socket(SOCK_STREAM, &remote.addr);
 	assert(origin_fd > 0);
-	socklen_t addr_len = sockaddr_len(&remote.addr);
+	socklen_t addr_len = sockaddr_len((struct sockaddr *)&remote.addr);
 	getsockname(origin_fd, (struct sockaddr *)&remote.addr, &addr_len);
 	ret = listen(origin_fd, 10);
 	assert(ret == 0);
@@ -159,7 +164,7 @@ int main(int argc, char *argv[])
 	close(responder);
 
 	/* Close requestor. */
-	requestor_clear(&requestor);
+	knot_requestor_clear(&requestor);
 	close(origin_fd);
 
 	/* Cleanup. */
diff --git a/tests/zone_events.c b/tests/zone_events.c
index 804cf08f5c3045d568d97aad3184ba0d8c467ebb..2542d05db6cd61cef5ab91471b4dc98d719674d4 100644
--- a/tests/zone_events.c
+++ b/tests/zone_events.c
@@ -86,7 +86,7 @@ int main(void)
 	r = zone_events_init(&zone);
 	ok(r == KNOT_EOK, "zone events init");
 
-	r = zone_events_setup(&zone, pool, &sched);
+	r = zone_events_setup(&zone, pool, &sched, NULL);
 	ok(r == KNOT_EOK, "zone events setup");
 
 	test_scheduling(&zone);
diff --git a/tests/zone_timers.c b/tests/zone_timers.c
index 3162806f1d11b5bf5155cf6f1f2e9108d34f2e92..417d3f87888d6454f0686ee71c42ff166e4768b6 100644
--- a/tests/zone_timers.c
+++ b/tests/zone_timers.c
@@ -18,7 +18,7 @@
 #include <time.h>
 #include <tap/basic.h>
 
-#include "libknot/common.h"
+#include "libknot/errcode.h"
 #include "common/namedb/namedb.h"
 #include "common/namedb/namedb_lmdb.h"
 #include "knot/zone/timers.h"
@@ -58,8 +58,9 @@ int main(int argc, char *argv[])
 	ret = knot_zonedb_insert(zone_db, zone_2);
 	assert(ret == KNOT_EOK);
 
-	knot_namedb_t *db = open_timers_db(dbid);
-	ok(db != NULL, "zone timers: create");
+	knot_namedb_t *db = NULL;
+	ret = open_timers_db(dbid, &db);
+	ok(ret == KNOT_EOK && db != NULL, "zone timers: create");
 
 	// Set up events in the future.
 	const time_t now = time(NULL);
diff --git a/tests/zone_update.c b/tests/zone_update.c
index cf596543fea94a0f394e0cb158f40e9723965b39..17c6ad5fbafad31b8569e40d2dbe04ab1b403f78 100644
--- a/tests/zone_update.c
+++ b/tests/zone_update.c
@@ -20,6 +20,7 @@
 #include "knot/updates/zone-update.h"
 #include "zscanner/scanner.h"
 #include "common/getline.h"
+#include "common/macros.h"
 
 static const char *zone_str =
 "test. 3600 IN SOA a.ns.test. hostmaster.nic.cz. 1406641065 900 300 604800 900 \n"
diff --git a/tests/zonedb.c b/tests/zonedb.c
index cc0ed69ab3d69bdfb045986564bbb27694a9fa4d..9330ac01fce393e5004bee77d8c310de8d852813 100644
--- a/tests/zonedb.c
+++ b/tests/zonedb.c
@@ -17,7 +17,7 @@
 #include <tap/basic.h>
 
 #include "common-knot/strlcat.h"
-#include "common-knot/strlcpy.h"
+#include "common/strlcpy.h"
 #include "knot/zone/zone.h"
 #include "knot/zone/zonedb.h"